@geekmidas/cli 0.35.0 ā 0.36.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/index.cjs +18 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +18 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/dev/index.ts +23 -10
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["options?: CredentialOptions","credentials: StoredCredentials","token: string","endpoint: string","registryId: string","logger","endpoint: string","token: string","DokployApi","prompt","message: string","resolve","err: Error","char: Buffer","options: LoginOptions","options: LogoutOptions","config: GkmConfig","options: BuildOptions","providers: LegacyProvider[]","config","mainProvider: MainProvider","providersConfig?: ProvidersConfig","providersConfig: ProvidersConfig","config:\n\t\t| boolean\n\t\t| AWSApiGatewayConfig\n\t\t| AWSLambdaConfig\n\t\t| ServerConfig\n\t\t| undefined","context: BuildContext","constructs: GeneratedConstruct<\n\t\t\tCron<any, any, any, any, any, any, any, any>\n\t\t>[]","outputDir: string","options?: GeneratorOptions","logger","cronInfos: CronInfo[]","value: any","sourceFile: string","exportName: string","value: any","context: BuildContext","constructs: GeneratedConstruct<\n\t\t\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>\n\t\t>[]","outputDir: string","options?: GeneratorOptions","logger","functionInfos: FunctionInfo[]","sourceFile: string","exportName: string","value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","logger","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","exports","logger","content: string","routes: string | string[] | undefined","workspace: NormalizedWorkspace","appName: string","frontendAppName: string","options: { force?: boolean }","results: ClientGenerationResult[]","dependencies","result: ClientGenerationResult","options: { force?: boolean; silent?: boolean }","allResults: ClientGenerationResult[]","backendAppName: string","dependentApps: string[]","logger","envConfig: string | string[] | undefined","cwd: string","loaded: string[]","missing: string[]","port: number","resolve","err: NodeJS.ErrnoException","preferredPort: number","config: GkmConfig['telescope']","config","isEnabled","telescopeConfig: TelescopeConfig","config: GkmConfig['studio']","studioConfig: StudioConfig","config: GkmConfig['hooks']","cliProduction: boolean","configProduction?: ProductionConfig","config: GkmConfig","options: DevOptions","appRoot: string","secretsRoot: string","workspaceAppName: string | undefined","workspaceAppPort: number | undefined","buildContext: BuildContext","runtime: Runtime","secretsJsonPath: string | undefined","rebuildTimeout: NodeJS.Timeout | null","workspace: NormalizedWorkspace","env: Record<string, string>","conflicts: { app1: string; app2: string; port: number }[]","appName: string","appPath: string","workspaceRoot: string","errors: string[]","warnings: string[]","pkg","results: FrontendValidationResult[]","appName?: string","secrets: Record<string, string>","servicesToStart: string[]","turboFilter: string[]","turboEnv: Record<string, string>","endpointWatcher: ReturnType<typeof chokidar.watch> | null","watchPatterns: string[]","regenerateTimeout: NodeJS.Timeout | null","changedBackends: string[]","config: any","context: BuildContext","provider: LegacyProvider","enableOpenApi: boolean","startDir: string","wrapperPath: string","entryPath: string","secretsJsonPath?: string","watch: boolean","restartTimeout: NodeJS.Timeout | null","requestedPort: number","portExplicit: boolean","telescope: NormalizedTelescopeConfig | undefined","studio: NormalizedStudioConfig | undefined","logger","outputDir: string","routes: RouteInfo[]","functions: FunctionInfo[]","crons: CronInfo[]","subscribers: SubscriberInfo[]","appInfo: ServerAppInfo","logger","options: BuildOptions","config","buildContext: BuildContext","result: BuildResult","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","skipBundle: boolean","stage?: string","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo","masterKey: string | undefined","detectPackageManager","pm: 'pnpm' | 'npm' | 'yarn'","filter?: string","workspace: NormalizedWorkspace","results: AppBuildResult[]","name","resolve","_appName: string","app: NormalizedAppConfig","DEFAULT_SERVICE_IMAGES: Record<ComposeServiceName, string>","DEFAULT_SERVICE_VERSIONS: Record<ComposeServiceName, string>","serviceName: ComposeServiceName","services: ComposeServicesConfig | ComposeServiceName[]","name","config","version","options: ComposeOptions","options: Omit<ComposeOptions, 'services'>","workspace: NormalizedWorkspace","options: WorkspaceComposeOptions","serviceName: 'postgres' | 'redis'","config: boolean | { version?: string; image?: string } | undefined","defaults: Record<'postgres' | 'redis', string>","appName: string","app: NormalizedAppConfig","allApps: [string, NormalizedAppConfig][]","options: {\n\t\tregistry?: string;\n\t\thasPostgres: boolean;\n\t\thasRedis: boolean;\n\t}","dependencies: string[]","dependencies","LOCKFILES: [string, PackageManager][]","detectPackageManager","cwd: string","pm: PackageManager","commands: Record<PackageManager, string>","options: MultiStageDockerfileOptions","options: DockerTemplateOptions","resolveDockerConfig","config: GkmConfig","config","pkg","options: FrontendDockerfileOptions","options: FrontendDockerfileOptions & { healthCheckPath?: string }","logger","options: DockerOptions","config","pkg","result: DockerGeneratedFiles","cwd: string","imageName: string","appPath: string","workspace: NormalizedWorkspace","results: AppDockerResult[]","dockerfile: string","getAppNameFromCwd","pkg","logger","registry: string | undefined","imageName: string","tag: string","imageRef: string","options: DockerDeployOptions","config","config: GkmConfig","logger","getApiToken","createApi","endpoint: string","options: DokployDeployOptions","config","registryOptions: {\n\t\tregistryId?: string;\n\t\tusername?: string;\n\t\tpassword?: string;\n\t\tregistryUrl?: string;\n\t}","envVars: Record<string, string>","logger","providedEndpoint?: string","endpoint: string","config: DokployDeployConfig","cwd: string","config","newContent: string","options: DeployInitOptions","projectId: string","environmentId: string","options: {\n\tendpoint?: string;\n\tresource: 'projects' | 'registries';\n}","logger","message: string","resolve","char: Buffer","api: DokployApi","projectId: string","environmentId: string | undefined","appName: string","services?: DockerComposeServices","existingUrls?: Pick<ServiceUrls, 'DATABASE_URL' | 'REDIS_URL'>","serviceUrls: ServiceUrls","config: GkmConfig","dockerConfig: DockerDeployConfig","stage: string","existingUrls: { DATABASE_URL?: string; REDIS_URL?: string }","config","environmentId","serviceUrls","environmentId: string","applicationId: string","dokployConfig: DokployDeployConfig","workspace: NormalizedWorkspace","options: DeployOptions","name","deployedAppUrls: Record<string, string>","results: AppDeployResult[]","application: DokployApplication | undefined","envVars: string[]","dokployConfig: DokployDeployConfig | undefined","dockerServices: DockerComposeServices | undefined","masterKey: string | undefined","result: DeployResult","SERVICE_DEFAULTS: Record<\n\tComposeServiceName,\n\tOmit<ServiceCredentials, 'password'>\n>","service: ComposeServiceName","services: ComposeServiceName[]","result: StageSecrets['services']","creds: ServiceCredentials","services: StageSecrets['services']","urls: StageSecrets['urls']","stage: string","secrets: StageSecrets","newCreds: ServiceCredentials","require","options: TemplateOptions","options: TemplateOptions","template: TemplateConfig","_template: TemplateConfig","_helpers: ConfigHelperOptions","options: TemplateOptions","template: TemplateConfig","dbApps?: DatabaseAppConfig[]","services: string[]","volumes: string[]","files: GeneratedFile[]","apps: DatabaseAppConfig[]","options: TemplateOptions","_template: TemplateConfig","files: GeneratedFile[]","options: TemplateOptions","options: TemplateOptions","_template: TemplateConfig","files: GeneratedFile[]","config","apiTemplate: TemplateConfig","options: TemplateOptions","name","file: string","files: GeneratedFile[]","minimalTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","serverlessTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","workerTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","OPENAPI_OUTPUT_PATH","templates: Record<\n\tExclude<TemplateName, 'fullstack'>,\n\tTemplateConfig\n>","name: TemplateName","name","options: TemplateOptions","template: TemplateConfig","dependencies","devDependencies","scripts","name","obj: Record<string, string>","OPENAPI_OUTPUT_PATH","options: TemplateOptions","template: TemplateConfig","options: TemplateOptions","cwd: string","name: string","name","pkgManager: PackageManager","script: string","appName: string","password: string","projectName: string","projectName?: string","options: InitOptions","value: string","name","template: TemplateName","servicesArray: string[]","services: ServicesSelection","pkgManager: PackageManager","deployTarget: DeployTarget","templateOptions: TemplateOptions","isMonorepo","dbApps: DatabaseAppConfig[]","secretServices: ComposeServiceName[]","customSecrets: Record<string, string>","options: TemplateOptions","devCommand","services: ComposeServicesConfig | ComposeServiceName[] | undefined","config","name","options: SecretsInitOptions","chunks: Buffer[]","key: string","value: string | undefined","options: SecretsSetOptions","options: SecretsShowOptions","options: SecretsRotateOptions","file: string","options: SecretsImportOptions","importedSecrets: Record<string, string>","url: string","options: TestOptions","envVars: Record<string, string>","args: string[]","resolve","pkg","name: string | undefined","options: InitOptions","name","options: {\n\t\t\tprovider?: string;\n\t\t\tproviders?: string;\n\t\t\tenableOpenapi?: boolean;\n\t\t\tproduction?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tstage?: string;\n\t\t}","options: {\n\t\t\tport?: string;\n\t\t\tentry?: string;\n\t\t\twatch?: boolean;\n\t\t\tenableOpenapi?: boolean;\n\t\t}","pattern: string | undefined","options: TestOptions","options: { input?: string; output?: string; name?: string }","options: DockerOptions","options: {\n\t\t\tbuild?: boolean;\n\t\t\tpush?: boolean;\n\t\t\ttag?: string;\n\t\t\tregistry?: string;\n\t\t\tslim?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tturbo?: boolean;\n\t\t\tturboPackage?: string;\n\t\t}","options: { stage: string; force?: boolean }","key: string","value: string | undefined","options: { stage: string }","options: { stage: string; reveal?: boolean }","options: { stage: string; service?: ComposeServiceName }","file: string","options: { stage: string; merge?: boolean }","options: {\n\t\t\tprovider: string;\n\t\t\tstage: string;\n\t\t\ttag?: string;\n\t\t\tskipPush?: boolean;\n\t\t\tskipBuild?: boolean;\n\t\t}","options: {\n\t\t\tendpoint?: string;\n\t\t\tproject: string;\n\t\t\tapp: string;\n\t\t\tprojectId?: string;\n\t\t\tregistryId?: string;\n\t\t}","options: {\n\t\t\tendpoint?: string;\n\t\t\tprojects?: boolean;\n\t\t\tregistries?: boolean;\n\t\t}","options: { service: string; token?: string; endpoint?: string }","options: { service: string }"],"sources":["../package.json","../src/auth/credentials.ts","../src/auth/index.ts","../src/build/providerResolver.ts","../src/generators/CronGenerator.ts","../src/generators/FunctionGenerator.ts","../src/generators/SubscriberGenerator.ts","../src/workspace/client-generator.ts","../src/dev/index.ts","../src/build/manifests.ts","../src/build/index.ts","../src/docker/compose.ts","../src/docker/templates.ts","../src/docker/index.ts","../src/deploy/docker.ts","../src/deploy/dokploy.ts","../src/deploy/init.ts","../src/deploy/index.ts","../src/secrets/generator.ts","../src/init/versions.ts","../src/init/generators/auth.ts","../src/init/generators/config.ts","../src/init/generators/docker.ts","../src/init/generators/env.ts","../src/init/generators/models.ts","../src/init/generators/monorepo.ts","../src/init/templates/api.ts","../src/init/templates/minimal.ts","../src/init/templates/serverless.ts","../src/init/templates/worker.ts","../src/init/templates/index.ts","../src/init/generators/package.ts","../src/init/generators/source.ts","../src/init/generators/web.ts","../src/init/utils.ts","../src/init/index.ts","../src/secrets/index.ts","../src/test/index.ts","../src/index.ts"],"sourcesContent":["{\n\t\"name\": \"@geekmidas/cli\",\n\t\"version\": \"0.35.0\",\n\t\"description\": \"CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs\",\n\t\"private\": false,\n\t\"type\": \"module\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"require\": \"./dist/index.cjs\"\n\t\t},\n\t\t\"./config\": {\n\t\t\t\"types\": \"./dist/config.d.ts\",\n\t\t\t\"import\": \"./dist/config.mjs\",\n\t\t\t\"require\": \"./dist/config.cjs\"\n\t\t},\n\t\t\"./workspace\": {\n\t\t\t\"types\": \"./dist/workspace/index.d.ts\",\n\t\t\t\"import\": \"./dist/workspace/index.mjs\",\n\t\t\t\"require\": \"./dist/workspace/index.cjs\"\n\t\t},\n\t\t\"./openapi\": {\n\t\t\t\"types\": \"./dist/openapi.d.ts\",\n\t\t\t\"import\": \"./dist/openapi.mjs\",\n\t\t\t\"require\": \"./dist/openapi.cjs\"\n\t\t},\n\t\t\"./openapi-react-query\": {\n\t\t\t\"types\": \"./dist/openapi-react-query.d.ts\",\n\t\t\t\"import\": \"./dist/openapi-react-query.mjs\",\n\t\t\t\"require\": \"./dist/openapi-react-query.cjs\"\n\t\t}\n\t},\n\t\"bin\": {\n\t\t\"gkm\": \"./dist/index.cjs\"\n\t},\n\t\"scripts\": {\n\t\t\"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n\t\t\"test\": \"vitest\",\n\t\t\"test:once\": \"vitest run\",\n\t\t\"test:coverage\": \"vitest run --coverage\"\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/geekmidas/toolbox\"\n\t},\n\t\"dependencies\": {\n\t\t\"@apidevtools/swagger-parser\": \"^10.1.0\",\n\t\t\"@geekmidas/constructs\": \"workspace:~\",\n\t\t\"@geekmidas/envkit\": \"workspace:~\",\n\t\t\"@geekmidas/errors\": \"workspace:~\",\n\t\t\"@geekmidas/logger\": \"workspace:~\",\n\t\t\"@geekmidas/schema\": \"workspace:~\",\n\t\t\"chokidar\": \"~4.0.3\",\n\t\t\"commander\": \"^12.1.0\",\n\t\t\"dotenv\": \"~17.2.3\",\n\t\t\"fast-glob\": \"^3.3.2\",\n\t\t\"hono\": \"~4.8.0\",\n\t\t\"lodash.kebabcase\": \"^4.1.1\",\n\t\t\"openapi-typescript\": \"^7.4.2\",\n\t\t\"prompts\": \"~2.4.2\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@geekmidas/testkit\": \"workspace:*\",\n\t\t\"@types/lodash.kebabcase\": \"^4.1.9\",\n\t\t\"@types/node\": \"~24.9.1\",\n\t\t\"@types/prompts\": \"~2.4.9\",\n\t\t\"typescript\": \"^5.8.2\",\n\t\t\"vitest\": \"^3.2.4\",\n\t\t\"zod\": \"~4.1.13\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"@geekmidas/telescope\": \"workspace:~\"\n\t},\n\t\"peerDependenciesMeta\": {\n\t\t\"@geekmidas/telescope\": {\n\t\t\t\"optional\": true\n\t\t}\n\t}\n}\n","import { existsSync, mkdirSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * Stored credentials for various services\n */\nexport interface StoredCredentials {\n\tdokploy?: {\n\t\t/** API token */\n\t\ttoken: string;\n\t\t/** Dokploy endpoint URL */\n\t\tendpoint: string;\n\t\t/** Registry ID in Dokploy (for Docker image pulls) */\n\t\tregistryId?: string;\n\t\t/** When the credentials were stored */\n\t\tstoredAt: string;\n\t};\n}\n\n/**\n * Options for credential operations\n */\nexport interface CredentialOptions {\n\t/** Root directory for credentials storage (default: user home directory) */\n\troot?: string;\n}\n\n/**\n * Get the path to the credentials directory\n */\nexport function getCredentialsDir(options?: CredentialOptions): string {\n\tconst root = options?.root ?? homedir();\n\treturn join(root, '.gkm');\n}\n\n/**\n * Get the path to the credentials file\n */\nexport function getCredentialsPath(options?: CredentialOptions): string {\n\treturn join(getCredentialsDir(options), 'credentials.json');\n}\n\n/**\n * Ensure the credentials directory exists\n */\nfunction ensureCredentialsDir(options?: CredentialOptions): void {\n\tconst dir = getCredentialsDir(options);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Read stored credentials from disk\n */\nexport async function readCredentials(\n\toptions?: CredentialOptions,\n): Promise<StoredCredentials> {\n\tconst path = getCredentialsPath(options);\n\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\ttry {\n\t\tconst content = await readFile(path, 'utf-8');\n\t\treturn JSON.parse(content) as StoredCredentials;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Write credentials to disk\n */\nexport async function writeCredentials(\n\tcredentials: StoredCredentials,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tensureCredentialsDir(options);\n\tconst path = getCredentialsPath(options);\n\n\tawait writeFile(path, JSON.stringify(credentials, null, 2), {\n\t\tmode: 0o600, // Owner read/write only\n\t});\n}\n\n/**\n * Store Dokploy credentials\n */\nexport async function storeDokployCredentials(\n\ttoken: string,\n\tendpoint: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tcredentials.dokploy = {\n\t\ttoken,\n\t\tendpoint,\n\t\tstoredAt: new Date().toISOString(),\n\t};\n\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get stored Dokploy credentials\n */\nexport async function getDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<{\n\ttoken: string;\n\tendpoint: string;\n\tregistryId?: string;\n} | null> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\ttoken: credentials.dokploy.token,\n\t\tendpoint: credentials.dokploy.endpoint,\n\t\tregistryId: credentials.dokploy.registryId,\n\t};\n}\n\n/**\n * Remove Dokploy credentials\n */\nexport async function removeDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<boolean> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\treturn false;\n\t}\n\n\tdelete credentials.dokploy;\n\tawait writeCredentials(credentials, options);\n\treturn true;\n}\n\n/**\n * Remove all stored credentials\n */\nexport async function removeAllCredentials(\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst path = getCredentialsPath(options);\n\n\tif (existsSync(path)) {\n\t\tawait unlink(path);\n\t}\n}\n\n/**\n * Get Dokploy API token, checking stored credentials first, then environment\n */\nexport async function getDokployToken(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\t// First check environment variable (takes precedence)\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tif (envToken) {\n\t\treturn envToken;\n\t}\n\n\t// Then check stored credentials\n\tconst stored = await getDokployCredentials(options);\n\tif (stored) {\n\t\treturn stored.token;\n\t}\n\n\treturn null;\n}\n\n/**\n * Get Dokploy endpoint from stored credentials\n */\nexport async function getDokployEndpoint(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.endpoint ?? null;\n}\n\n/**\n * Store Dokploy registry ID\n */\nexport async function storeDokployRegistryId(\n\tregistryId: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found. Run \"gkm login --service dokploy\" first.',\n\t\t);\n\t}\n\n\tcredentials.dokploy.registryId = registryId;\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get Dokploy registry ID from stored credentials\n */\nexport async function getDokployRegistryId(\n\toptions?: CredentialOptions,\n): Promise<string | undefined> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.registryId ?? undefined;\n}\n","import { stdin as input, stdout as output } from 'node:process';\nimport * as readline from 'node:readline/promises';\nimport {\n\tgetCredentialsPath,\n\tgetDokployCredentials,\n\tremoveDokployCredentials,\n\tstoreDokployCredentials,\n} from './credentials';\n\nconst logger = console;\n\nexport interface LoginOptions {\n\t/** Service to login to */\n\tservice: 'dokploy';\n\t/** API token (if not provided, will prompt) */\n\ttoken?: string;\n\t/** Endpoint URL */\n\tendpoint?: string;\n}\n\nexport interface LogoutOptions {\n\t/** Service to logout from */\n\tservice?: 'dokploy' | 'all';\n}\n\n/**\n * Validate Dokploy token by making a test API call\n */\nexport async function validateDokployToken(\n\tendpoint: string,\n\ttoken: string,\n): Promise<boolean> {\n\tconst { DokployApi } = await import('../deploy/dokploy-api');\n\tconst api = new DokployApi({ baseUrl: endpoint, token });\n\treturn api.validateToken();\n}\n\n/**\n * Prompt for input (handles both TTY and non-TTY)\n */\nasync function prompt(message: string, hidden = false): Promise<string> {\n\tif (!process.stdin.isTTY) {\n\t\tthrow new Error(\n\t\t\t'Interactive input required. Please provide --token option.',\n\t\t);\n\t}\n\n\tif (hidden) {\n\t\t// For hidden input, use raw mode directly without readline\n\t\tprocess.stdout.write(message);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet value = '';\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\tprocess.stdin.pause();\n\t\t\t\tprocess.stdin.removeListener('data', onData);\n\t\t\t\tprocess.stdin.removeListener('error', onError);\n\t\t\t};\n\n\t\t\tconst onError = (err: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\treject(err);\n\t\t\t};\n\n\t\t\tconst onData = (char: Buffer) => {\n\t\t\t\tconst c = char.toString();\n\n\t\t\t\tif (c === '\\n' || c === '\\r') {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tresolve(value);\n\t\t\t\t} else if (c === '\\u0003') {\n\t\t\t\t\t// Ctrl+C\n\t\t\t\t\tcleanup();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t} else if (c === '\\u007F' || c === '\\b') {\n\t\t\t\t\t// Backspace\n\t\t\t\t\tif (value.length > 0) {\n\t\t\t\t\t\tvalue = value.slice(0, -1);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvalue += c;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t\tprocess.stdin.resume();\n\t\t\tprocess.stdin.on('data', onData);\n\t\t\tprocess.stdin.on('error', onError);\n\t\t});\n\t} else {\n\t\t// For visible input, use readline\n\t\tconst rl = readline.createInterface({ input, output });\n\t\ttry {\n\t\t\treturn await rl.question(message);\n\t\t} finally {\n\t\t\trl.close();\n\t\t}\n\t}\n}\n\n/**\n * Login to a service\n */\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n\tconst { service, token: providedToken, endpoint: providedEndpoint } = options;\n\n\tif (service === 'dokploy') {\n\t\tlogger.log('\\nš Logging in to Dokploy...\\n');\n\n\t\t// Get endpoint\n\t\tlet endpoint = providedEndpoint;\n\t\tif (!endpoint) {\n\t\t\tendpoint = await prompt(\n\t\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t\t);\n\t\t}\n\n\t\t// Normalize endpoint (remove trailing slash)\n\t\tendpoint = endpoint.replace(/\\/$/, '');\n\n\t\t// Validate endpoint format\n\t\ttry {\n\t\t\tnew URL(endpoint);\n\t\t} catch {\n\t\t\tlogger.error('Invalid URL format');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Get token\n\t\tlet token = providedToken;\n\t\tif (!token) {\n\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\ttoken = await prompt('API Token: ', true);\n\t\t}\n\n\t\tif (!token) {\n\t\t\tlogger.error('Token is required');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Validate token\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(endpoint, token);\n\n\t\tif (!isValid) {\n\t\t\tlogger.error(\n\t\t\t\t'\\nā Invalid credentials. Please check your token and try again.',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Store credentials\n\t\tawait storeDokployCredentials(token, endpoint);\n\n\t\tlogger.log('\\nā Successfully logged in to Dokploy!');\n\t\tlogger.log(` Endpoint: ${endpoint}`);\n\t\tlogger.log(` Credentials stored in: ${getCredentialsPath()}`);\n\t\tlogger.log(\n\t\t\t'\\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n}\n\n/**\n * Logout from a service\n */\nexport async function logoutCommand(options: LogoutOptions): Promise<void> {\n\tconst { service = 'dokploy' } = options;\n\n\tif (service === 'all') {\n\t\tconst dokployRemoved = await removeDokployCredentials();\n\n\t\tif (dokployRemoved) {\n\t\t\tlogger.log('\\nā Logged out from all services');\n\t\t} else {\n\t\t\tlogger.log('\\nNo stored credentials found');\n\t\t}\n\t\treturn;\n\t}\n\n\tif (service === 'dokploy') {\n\t\tconst removed = await removeDokployCredentials();\n\n\t\tif (removed) {\n\t\t\tlogger.log('\\nā Logged out from Dokploy');\n\t\t} else {\n\t\t\tlogger.log('\\nNo Dokploy credentials found');\n\t\t}\n\t}\n}\n\n/**\n * Show current login status\n */\nexport async function whoamiCommand(): Promise<void> {\n\tlogger.log('\\nš Current credentials:\\n');\n\n\tconst dokploy = await getDokployCredentials();\n\n\tif (dokploy) {\n\t\tlogger.log(' Dokploy:');\n\t\tlogger.log(` Endpoint: ${dokploy.endpoint}`);\n\t\tlogger.log(` Token: ${maskToken(dokploy.token)}`);\n\t} else {\n\t\tlogger.log(' Dokploy: Not logged in');\n\t}\n\n\tlogger.log(`\\n Credentials file: ${getCredentialsPath()}`);\n}\n\n/**\n * Mask a token for display\n */\nexport function maskToken(token: string): string {\n\tif (token.length <= 8) {\n\t\treturn '****';\n\t}\n\treturn `${token.slice(0, 4)}...${token.slice(-4)}`;\n}\n\n// Re-export credentials utilities for use in other modules\nexport {\n\tgetDokployCredentials,\n\tgetDokployEndpoint,\n\tgetDokployRegistryId,\n\tgetDokployToken,\n\tstoreDokployCredentials,\n\tstoreDokployRegistryId,\n} from './credentials';\n","import type {\n\tAWSApiGatewayConfig,\n\tAWSLambdaConfig,\n\tBuildOptions,\n\tGkmConfig,\n\tLegacyProvider,\n\tMainProvider,\n\tProvidersConfig,\n\tServerConfig,\n} from '../types';\n\nexport interface ResolvedProviders {\n\tproviders: LegacyProvider[];\n\tenableOpenApi: boolean;\n}\n\n/**\n * Resolves provider configuration from the new simplified system\n * to the internal legacy format for backward compatibility\n */\nexport function resolveProviders(\n\tconfig: GkmConfig,\n\toptions: BuildOptions,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = options.enableOpenApi || false;\n\n\t// Handle legacy providers option (deprecated)\n\tif (options.providers) {\n\t\treturn {\n\t\t\tproviders: options.providers,\n\t\t\tenableOpenApi,\n\t\t};\n\t}\n\n\t// Handle new provider option\n\tif (options.provider) {\n\t\tconst resolvedProviders = resolveMainProvider(\n\t\t\toptions.provider,\n\t\t\tconfig.providers,\n\t\t);\n\t\tproviders.push(...resolvedProviders.providers);\n\t\tenableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;\n\t}\n\t// Default: build all configured providers\n\telse if (config.providers) {\n\t\tconst resolvedProviders = resolveAllConfiguredProviders(config.providers);\n\t\tproviders.push(...resolvedProviders.providers);\n\t\tenableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;\n\t}\n\t// Fallback: use default AWS configuration\n\telse {\n\t\tproviders.push('aws-apigatewayv2', 'aws-lambda');\n\t}\n\n\treturn {\n\t\tproviders: [...new Set(providers)], // Remove duplicates\n\t\tenableOpenApi,\n\t};\n}\n\nfunction resolveMainProvider(\n\tmainProvider: MainProvider,\n\tprovidersConfig?: ProvidersConfig,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = false;\n\n\tif (mainProvider === 'aws') {\n\t\tconst awsConfig = providersConfig?.aws;\n\n\t\t// Resolve API Gateway providers\n\t\tif (awsConfig?.apiGateway) {\n\t\t\tif (isEnabled(awsConfig.apiGateway.v1)) {\n\t\t\t\tproviders.push('aws-apigatewayv1');\n\t\t\t}\n\t\t\tif (isEnabled(awsConfig.apiGateway.v2)) {\n\t\t\t\tproviders.push('aws-apigatewayv2');\n\t\t\t}\n\t\t} else {\n\t\t\t// Default: enable v2 if no specific config\n\t\t\tproviders.push('aws-apigatewayv2');\n\t\t}\n\n\t\t// Resolve Lambda providers\n\t\tif (awsConfig?.lambda) {\n\t\t\tif (\n\t\t\t\tisEnabled(awsConfig.lambda.functions) ||\n\t\t\t\tisEnabled(awsConfig.lambda.crons)\n\t\t\t) {\n\t\t\t\tproviders.push('aws-lambda');\n\t\t\t}\n\t\t} else {\n\t\t\t// Default: enable lambda if no specific config\n\t\t\tproviders.push('aws-lambda');\n\t\t}\n\t} else if (mainProvider === 'server') {\n\t\tproviders.push('server');\n\t\tconst serverConfig = providersConfig?.server;\n\n\t\tif (typeof serverConfig === 'object' && serverConfig?.enableOpenApi) {\n\t\t\tenableOpenApi = true;\n\t\t}\n\t}\n\n\treturn { providers, enableOpenApi };\n}\n\nfunction resolveAllConfiguredProviders(\n\tprovidersConfig: ProvidersConfig,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = false;\n\n\t// AWS providers\n\tif (providersConfig.aws) {\n\t\tconst awsProviders = resolveMainProvider('aws', providersConfig);\n\t\tproviders.push(...awsProviders.providers);\n\t}\n\n\t// Server provider\n\tif (providersConfig.server && isEnabled(providersConfig.server)) {\n\t\tproviders.push('server');\n\t\tif (\n\t\t\ttypeof providersConfig.server === 'object' &&\n\t\t\tprovidersConfig.server.enableOpenApi\n\t\t) {\n\t\t\tenableOpenApi = true;\n\t\t}\n\t}\n\n\treturn { providers, enableOpenApi };\n}\n\nfunction isEnabled(\n\tconfig:\n\t\t| boolean\n\t\t| AWSApiGatewayConfig\n\t\t| AWSLambdaConfig\n\t\t| ServerConfig\n\t\t| undefined,\n): boolean {\n\tif (config === undefined) return false;\n\tif (typeof config === 'boolean') return config;\n\treturn config.enabled !== false; // Default to true if enabled is not explicitly false\n}\n\n/**\n * Gets configuration for a specific AWS service\n */\nexport function getAWSServiceConfig<\n\tT extends AWSApiGatewayConfig | AWSLambdaConfig,\n>(\n\tconfig: GkmConfig,\n\tservice: 'apiGateway' | 'lambda',\n\tsubService?: 'v1' | 'v2' | 'functions' | 'crons',\n): T | undefined {\n\tconst awsConfig = config.providers?.aws;\n\tif (!awsConfig) return undefined;\n\n\tif (service === 'apiGateway' && awsConfig.apiGateway) {\n\t\tconst apiConfig = subService\n\t\t\t? awsConfig.apiGateway[subService as 'v1' | 'v2']\n\t\t\t: undefined;\n\t\treturn typeof apiConfig === 'object' ? (apiConfig as T) : undefined;\n\t}\n\n\tif (service === 'lambda' && awsConfig.lambda) {\n\t\tconst lambdaConfig = subService\n\t\t\t? awsConfig.lambda[subService as 'functions' | 'crons']\n\t\t\t: undefined;\n\t\treturn typeof lambdaConfig === 'object' ? (lambdaConfig as T) : undefined;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Gets server configuration\n */\nexport function getServerConfig(config: GkmConfig): ServerConfig | undefined {\n\tconst serverConfig = config.providers?.server;\n\treturn typeof serverConfig === 'object' ? serverConfig : undefined;\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Cron } from '@geekmidas/constructs/crons';\nimport type { BuildContext } from '../build/types';\nimport type { CronInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class CronGenerator extends ConstructGenerator<\n\tCron<any, any, any, any, any, any, any, any>,\n\tCronInfo[]\n> {\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<\n\t\t\tCron<any, any, any, any, any, any, any, any>\n\t\t>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<CronInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst cronInfos: CronInfo[] = [];\n\n\t\tif (constructs.length === 0 || provider !== 'aws-lambda') {\n\t\t\treturn cronInfos;\n\t\t}\n\n\t\t// Create crons subdirectory\n\t\tconst cronsDir = join(outputDir, 'crons');\n\t\tawait mkdir(cronsDir, { recursive: true });\n\n\t\t// Generate cron handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateCronHandler(\n\t\t\t\tcronsDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tcronInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\tschedule: construct.schedule || 'rate(1 hour)',\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated cron handler: ${key}`);\n\t\t}\n\n\t\treturn cronInfos;\n\t}\n\n\tisConstruct(\n\t\tvalue: any,\n\t): value is Cron<any, any, any, any, any, any, any, any> {\n\t\treturn Cron.isCron(value);\n\t}\n\n\tprivate async generateCronHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\t\tconst relativeLoggerPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.loggerPath,\n\t\t);\n\n\t\tconst content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSScheduledFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Function } from '@geekmidas/constructs/functions';\nimport type { BuildContext } from '../build/types';\nimport type { FunctionInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class FunctionGenerator extends ConstructGenerator<\n\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>,\n\tFunctionInfo[]\n> {\n\tisConstruct(\n\t\tvalue: any,\n\t): value is Function<\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany\n\t> {\n\t\treturn Function.isFunction(value);\n\t}\n\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<\n\t\t\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>\n\t\t>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<FunctionInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst functionInfos: FunctionInfo[] = [];\n\n\t\tif (constructs.length === 0 || provider !== 'aws-lambda') {\n\t\t\treturn functionInfos;\n\t\t}\n\n\t\t// Create functions subdirectory\n\t\tconst functionsDir = join(outputDir, 'functions');\n\t\tawait mkdir(functionsDir, { recursive: true });\n\n\t\t// Generate function handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateFunctionHandler(\n\t\t\t\tfunctionsDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tfunctionInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated function handler: ${key}`);\n\t\t}\n\n\t\treturn functionInfos;\n\t}\n\n\tprivate async generateFunctionHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\t\tconst relativeLoggerPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.loggerPath,\n\t\t);\n\n\t\tconst content = `import { AWSLambdaFunction } from '@geekmidas/constructs/functions';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSLambdaFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n\tSubscriber<any, any, any, any, any, any>,\n\tSubscriberInfo[]\n> {\n\tisConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n\t\treturn Subscriber.isSubscriber(value);\n\t}\n\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<SubscriberInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst subscriberInfos: SubscriberInfo[] = [];\n\n\t\tif (provider === 'server') {\n\t\t\t// Generate subscribers.ts for server-based polling (even if empty)\n\t\t\tawait this.generateServerSubscribersFile(outputDir, constructs);\n\n\t\t\tlogger.log(\n\t\t\t\t`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n\t\t\t);\n\n\t\t\t// Return empty array as server subscribers don't have individual handlers\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\tif (constructs.length === 0) {\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\tif (provider !== 'aws-lambda') {\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\t// Create subscribers subdirectory\n\t\tconst subscribersDir = join(outputDir, 'subscribers');\n\t\tawait mkdir(subscribersDir, { recursive: true });\n\n\t\t// Generate subscriber handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateSubscriberHandler(\n\t\t\t\tsubscribersDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tconstruct,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tsubscriberInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\tsubscribedEvents: construct.subscribedEvents || [],\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated subscriber handler: ${key}`);\n\t\t}\n\n\t\treturn subscriberInfos;\n\t}\n\n\tprivate async generateSubscriberHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\t_subscriber: Subscriber<any, any, any, any, any, any>,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\n\t\tconst content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n\n\tprivate async generateServerSubscribersFile(\n\t\toutputDir: string,\n\t\tsubscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\t): Promise<string> {\n\t\t// Ensure output directory exists\n\t\tawait mkdir(outputDir, { recursive: true });\n\n\t\tconst subscribersFileName = 'subscribers.ts';\n\t\tconst subscribersPath = join(outputDir, subscribersFileName);\n\n\t\t// Group imports by file\n\t\tconst importsByFile = new Map<string, string[]>();\n\n\t\tfor (const { path, key } of subscribers) {\n\t\t\tconst relativePath = relative(dirname(subscribersPath), path.relative);\n\t\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\t\tif (!importsByFile.has(importPath)) {\n\t\t\t\timportsByFile.set(importPath, []);\n\t\t\t}\n\t\t\timportsByFile.get(importPath)?.push(key);\n\t\t}\n\n\t\t// Generate import statements\n\t\tconst imports = Array.from(importsByFile.entries())\n\t\t\t.map(\n\t\t\t\t([importPath, exports]) =>\n\t\t\t\t\t`import { ${exports.join(', ')} } from '${importPath}';`,\n\t\t\t)\n\t\t\t.join('\\n');\n\n\t\tconst allExportNames = subscribers.map(({ key }) => key);\n\n\t\tconst content = `/**\n * Generated subscribers setup\n *\n * ā ļø WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n\t\tawait writeFile(subscribersPath, content);\n\t\treturn subscribersPath;\n\t}\n}\n","import { createHash } from 'node:crypto';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { EndpointGenerator } from '../generators/EndpointGenerator.js';\nimport { OpenApiTsGenerator } from '../generators/OpenApiTsGenerator.js';\nimport type { NormalizedWorkspace } from './types.js';\n\nconst logger = console;\n\n/**\n * Result of generating a client for a frontend app.\n */\nexport interface ClientGenerationResult {\n\tfrontendApp: string;\n\tbackendApp: string;\n\toutputPath: string;\n\tendpointCount: number;\n\tgenerated: boolean;\n\treason?: string;\n}\n\n/**\n * Cache of OpenAPI spec hashes to detect changes.\n */\nconst specHashCache = new Map<string, string>();\n\n/**\n * Calculate hash of content for change detection.\n */\nfunction hashContent(content: string): string {\n\treturn createHash('sha256').update(content).digest('hex').slice(0, 16);\n}\n\n/**\n * Normalize routes to an array of patterns.\n * @internal Exported for use in dev command\n */\nexport function normalizeRoutes(\n\troutes: string | string[] | undefined,\n): string[] {\n\tif (!routes) return [];\n\treturn Array.isArray(routes) ? routes : [routes];\n}\n\n/**\n * Get the first routes pattern as a string (for simple cases).\n * @internal Exported for use in dev command\n */\nexport function getFirstRoute(\n\troutes: string | string[] | undefined,\n): string | null {\n\tconst normalized = normalizeRoutes(routes);\n\treturn normalized[0] || null;\n}\n\n/**\n * Generate OpenAPI spec for a backend app.\n * Returns the spec content and endpoint count.\n */\nexport async function generateBackendOpenApi(\n\tworkspace: NormalizedWorkspace,\n\tappName: string,\n): Promise<{ content: string; endpointCount: number } | null> {\n\tconst app = workspace.apps[appName];\n\tif (!app || app.type !== 'backend' || !app.routes) {\n\t\treturn null;\n\t}\n\n\tconst appPath = join(workspace.root, app.path);\n\tconst routesPatterns = normalizeRoutes(app.routes);\n\n\tif (routesPatterns.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Load endpoints from all routes patterns\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst allLoadedEndpoints = [];\n\n\tfor (const pattern of routesPatterns) {\n\t\tconst fullPattern = join(appPath, pattern);\n\t\tconst loaded = await endpointGenerator.load(fullPattern);\n\t\tallLoadedEndpoints.push(...loaded);\n\t}\n\n\tconst loadedEndpoints = allLoadedEndpoints;\n\n\tif (loadedEndpoints.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst endpoints = loadedEndpoints.map(({ construct }) => construct);\n\n\tconst tsGenerator = new OpenApiTsGenerator();\n\tconst content = await tsGenerator.generate(endpoints, {\n\t\ttitle: `${appName} API`,\n\t\tversion: '1.0.0',\n\t\tdescription: `Auto-generated API client for ${appName}`,\n\t});\n\n\treturn { content, endpointCount: loadedEndpoints.length };\n}\n\n/**\n * Generate client for a frontend app from its backend dependencies.\n * Only regenerates if the OpenAPI spec has changed.\n */\nexport async function generateClientForFrontend(\n\tworkspace: NormalizedWorkspace,\n\tfrontendAppName: string,\n\toptions: { force?: boolean } = {},\n): Promise<ClientGenerationResult[]> {\n\tconst results: ClientGenerationResult[] = [];\n\tconst frontendApp = workspace.apps[frontendAppName];\n\n\tif (!frontendApp || frontendApp.type !== 'frontend') {\n\t\treturn results;\n\t}\n\n\tconst dependencies = frontendApp.dependencies || [];\n\tconst backendDeps = dependencies.filter((dep) => {\n\t\tconst depApp = workspace.apps[dep];\n\t\treturn depApp?.type === 'backend' && depApp.routes;\n\t});\n\n\tif (backendDeps.length === 0) {\n\t\treturn results;\n\t}\n\n\t// Determine output directory\n\tconst clientOutput = frontendApp.client?.output || 'src/api';\n\tconst frontendPath = join(workspace.root, frontendApp.path);\n\tconst outputDir = join(frontendPath, clientOutput);\n\n\tfor (const backendAppName of backendDeps) {\n\t\tconst result: ClientGenerationResult = {\n\t\t\tfrontendApp: frontendAppName,\n\t\t\tbackendApp: backendAppName,\n\t\t\toutputPath: '',\n\t\t\tendpointCount: 0,\n\t\t\tgenerated: false,\n\t\t};\n\n\t\ttry {\n\t\t\t// Generate OpenAPI spec for backend\n\t\t\tconst spec = await generateBackendOpenApi(workspace, backendAppName);\n\n\t\t\tif (!spec) {\n\t\t\t\tresult.reason = 'No endpoints found in backend';\n\t\t\t\tresults.push(result);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.endpointCount = spec.endpointCount;\n\n\t\t\t// Check if spec has changed (unless force)\n\t\t\tconst cacheKey = `${backendAppName}:${frontendAppName}`;\n\t\t\tconst newHash = hashContent(spec.content);\n\t\t\tconst oldHash = specHashCache.get(cacheKey);\n\n\t\t\tif (!options.force && oldHash === newHash) {\n\t\t\t\tresult.reason = 'No schema changes detected';\n\t\t\t\tresults.push(result);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Generate client file\n\t\t\tawait mkdir(outputDir, { recursive: true });\n\n\t\t\t// For single dependency, use openapi.ts; for multiple, use {backend}-api.ts\n\t\t\tconst fileName =\n\t\t\t\tbackendDeps.length === 1 ? 'openapi.ts' : `${backendAppName}-api.ts`;\n\t\t\tconst outputPath = join(outputDir, fileName);\n\n\t\t\t// Add header comment with backend reference\n\t\t\tconst backendRelPath = relative(\n\t\t\t\tdirname(outputPath),\n\t\t\t\tjoin(workspace.root, workspace.apps[backendAppName]!.path),\n\t\t\t);\n\n\t\t\tconst clientContent = `/**\n * Auto-generated API client for ${backendAppName}\n * Generated from: ${backendRelPath}\n *\n * DO NOT EDIT - This file is automatically regenerated when backend schemas change.\n */\n\n${spec.content}\n`;\n\n\t\t\tawait writeFile(outputPath, clientContent);\n\n\t\t\t// Update cache\n\t\t\tspecHashCache.set(cacheKey, newHash);\n\n\t\t\tresult.outputPath = outputPath;\n\t\t\tresult.generated = true;\n\t\t\tresults.push(result);\n\t\t} catch (error) {\n\t\t\tresult.reason = `Error: ${(error as Error).message}`;\n\t\t\tresults.push(result);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Generate clients for all frontend apps in the workspace.\n */\nexport async function generateAllClients(\n\tworkspace: NormalizedWorkspace,\n\toptions: { force?: boolean; silent?: boolean } = {},\n): Promise<ClientGenerationResult[]> {\n\tconst log = options.silent ? () => {} : logger.log.bind(logger);\n\tconst allResults: ClientGenerationResult[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend' && app.dependencies.length > 0) {\n\t\t\tconst results = await generateClientForFrontend(workspace, appName, {\n\t\t\t\tforce: options.force,\n\t\t\t});\n\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.generated) {\n\t\t\t\t\tlog(\n\t\t\t\t\t\t`š¦ Generated client for ${result.frontendApp} from ${result.backendApp} (${result.endpointCount} endpoints)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tallResults.push(result);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn allResults;\n}\n\n/**\n * Check if a file path matches endpoint patterns that could affect OpenAPI schema.\n * Returns true for changes that should trigger client regeneration.\n */\nexport function shouldRegenerateClient(\n\tfilePath: string,\n\troutesPattern: string,\n): boolean {\n\t// Normalize path separators\n\tconst normalizedPath = filePath.replace(/\\\\/g, '/');\n\tconst normalizedPattern = routesPattern.replace(/\\\\/g, '/');\n\n\t// Check if the file matches the routes pattern\n\t// This is a simple check - the file should be within the routes directory\n\tconst patternDir = normalizedPattern.split('*')[0] || '';\n\n\tif (!normalizedPath.includes(patternDir.replace('./', ''))) {\n\t\treturn false;\n\t}\n\n\t// Check file extension - only TypeScript endpoint files\n\tif (!normalizedPath.endsWith('.ts') && !normalizedPath.endsWith('.tsx')) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Get backend apps that a frontend depends on.\n */\nexport function getBackendDependencies(\n\tworkspace: NormalizedWorkspace,\n\tfrontendAppName: string,\n): string[] {\n\tconst frontendApp = workspace.apps[frontendAppName];\n\tif (!frontendApp || frontendApp.type !== 'frontend') {\n\t\treturn [];\n\t}\n\n\treturn frontendApp.dependencies.filter((dep) => {\n\t\tconst depApp = workspace.apps[dep];\n\t\treturn depApp?.type === 'backend' && depApp.routes;\n\t});\n}\n\n/**\n * Get frontend apps that depend on a backend app.\n */\nexport function getDependentFrontends(\n\tworkspace: NormalizedWorkspace,\n\tbackendAppName: string,\n): string[] {\n\tconst dependentApps: string[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend' && app.dependencies.includes(backendAppName)) {\n\t\t\tdependentApps.push(appName);\n\t\t}\n\t}\n\n\treturn dependentApps;\n}\n\n/**\n * Clear the spec hash cache (useful for testing).\n */\nexport function clearSpecHashCache(): void {\n\tspecHashCache.clear();\n}\n","import { type ChildProcess, execSync, spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { dirname, join, resolve } from 'node:path';\nimport chokidar from 'chokidar';\nimport { config as dotenvConfig } from 'dotenv';\nimport fg from 'fast-glob';\nimport { resolveProviders } from '../build/providerResolver';\nimport type {\n\tBuildContext,\n\tNormalizedHooksConfig,\n\tNormalizedProductionConfig,\n\tNormalizedStudioConfig,\n\tNormalizedTelescopeConfig,\n} from '../build/types';\nimport {\n\tgetAppNameFromCwd,\n\tloadAppConfig,\n\tloadWorkspaceConfig,\n\tparseModuleConfig,\n} from '../config';\nimport {\n\tCronGenerator,\n\tEndpointGenerator,\n\tFunctionGenerator,\n\tSubscriberGenerator,\n} from '../generators';\nimport {\n\tgenerateOpenApi,\n\tOPENAPI_OUTPUT_PATH,\n\tresolveOpenApiConfig,\n} from '../openapi';\nimport {\n\treadStageSecrets,\n\tsecretsExist,\n\ttoEmbeddableSecrets,\n} from '../secrets/storage.js';\nimport type {\n\tGkmConfig,\n\tLegacyProvider,\n\tProductionConfig,\n\tRuntime,\n\tServerConfig,\n\tStudioConfig,\n\tTelescopeConfig,\n} from '../types';\nimport {\n\tgenerateAllClients,\n\tgenerateClientForFrontend,\n\tgetDependentFrontends,\n\tnormalizeRoutes,\n} from '../workspace/client-generator.js';\nimport {\n\tgetAppBuildOrder,\n\tgetDependencyEnvVars,\n\ttype NormalizedWorkspace,\n} from '../workspace/index.js';\n\nconst logger = console;\n\n/**\n * Load environment files\n * @internal Exported for testing\n */\nexport function loadEnvFiles(\n\tenvConfig: string | string[] | undefined,\n\tcwd: string = process.cwd(),\n): { loaded: string[]; missing: string[] } {\n\tconst loaded: string[] = [];\n\tconst missing: string[] = [];\n\n\t// Normalize to array\n\tconst envFiles = envConfig\n\t\t? Array.isArray(envConfig)\n\t\t\t? envConfig\n\t\t\t: [envConfig]\n\t\t: ['.env'];\n\n\t// Load each env file in order (later files override earlier)\n\tfor (const envFile of envFiles) {\n\t\tconst envPath = resolve(cwd, envFile);\n\t\tif (existsSync(envPath)) {\n\t\t\tdotenvConfig({ path: envPath, override: true, quiet: true });\n\t\t\tloaded.push(envFile);\n\t\t} else if (envConfig) {\n\t\t\t// Only report as missing if explicitly configured\n\t\t\tmissing.push(envFile);\n\t\t}\n\t}\n\n\treturn { loaded, missing };\n}\n\n/**\n * Check if a port is available\n * @internal Exported for testing\n */\nexport async function isPortAvailable(port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = createServer();\n\n\t\tserver.once('error', (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === 'EADDRINUSE') {\n\t\t\t\tresolve(false);\n\t\t\t} else {\n\t\t\t\tresolve(false);\n\t\t\t}\n\t\t});\n\n\t\tserver.once('listening', () => {\n\t\t\tserver.close();\n\t\t\tresolve(true);\n\t\t});\n\n\t\tserver.listen(port);\n\t});\n}\n\n/**\n * Find an available port starting from the preferred port\n * @internal Exported for testing\n */\nexport async function findAvailablePort(\n\tpreferredPort: number,\n\tmaxAttempts = 10,\n): Promise<number> {\n\tfor (let i = 0; i < maxAttempts; i++) {\n\t\tconst port = preferredPort + i;\n\t\tif (await isPortAvailable(port)) {\n\t\t\treturn port;\n\t\t}\n\t\tlogger.log(`ā ļø Port ${port} is in use, trying ${port + 1}...`);\n\t}\n\n\tthrow new Error(\n\t\t`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`,\n\t);\n}\n\n/**\n * Normalize telescope configuration\n * @internal Exported for testing\n */\nexport function normalizeTelescopeConfig(\n\tconfig: GkmConfig['telescope'],\n): NormalizedTelescopeConfig | undefined {\n\tif (config === false) {\n\t\treturn undefined;\n\t}\n\n\t// Handle string path (e.g., './src/config/telescope')\n\tif (typeof config === 'string') {\n\t\tconst { path: telescopePath, importPattern: telescopeImportPattern } =\n\t\t\tparseModuleConfig(config, 'telescope');\n\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\ttelescopePath,\n\t\t\ttelescopeImportPattern,\n\t\t\tpath: '/__telescope',\n\t\t\tignore: [],\n\t\t\trecordBody: true,\n\t\t\tmaxEntries: 1000,\n\t\t\twebsocket: true,\n\t\t};\n\t}\n\n\t// Default to enabled in development mode\n\tconst isEnabled =\n\t\tconfig === true || config === undefined || config.enabled !== false;\n\n\tif (!isEnabled) {\n\t\treturn undefined;\n\t}\n\n\tconst telescopeConfig: TelescopeConfig =\n\t\ttypeof config === 'object' ? config : {};\n\n\treturn {\n\t\tenabled: true,\n\t\tpath: telescopeConfig.path ?? '/__telescope',\n\t\tignore: telescopeConfig.ignore ?? [],\n\t\trecordBody: telescopeConfig.recordBody ?? true,\n\t\tmaxEntries: telescopeConfig.maxEntries ?? 1000,\n\t\twebsocket: telescopeConfig.websocket ?? true,\n\t};\n}\n\n/**\n * Normalize studio configuration\n * @internal Exported for testing\n */\nexport function normalizeStudioConfig(\n\tconfig: GkmConfig['studio'],\n): NormalizedStudioConfig | undefined {\n\tif (config === false) {\n\t\treturn undefined;\n\t}\n\n\t// Handle string path (e.g., './src/config/studio')\n\tif (typeof config === 'string') {\n\t\tconst { path: studioPath, importPattern: studioImportPattern } =\n\t\t\tparseModuleConfig(config, 'studio');\n\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tstudioPath,\n\t\t\tstudioImportPattern,\n\t\t\tpath: '/__studio',\n\t\t\tschema: 'public',\n\t\t};\n\t}\n\n\t// Default to enabled in development mode\n\tconst isEnabled =\n\t\tconfig === true || config === undefined || config.enabled !== false;\n\n\tif (!isEnabled) {\n\t\treturn undefined;\n\t}\n\n\tconst studioConfig: StudioConfig = typeof config === 'object' ? config : {};\n\n\treturn {\n\t\tenabled: true,\n\t\tpath: studioConfig.path ?? '/__studio',\n\t\tschema: studioConfig.schema ?? 'public',\n\t};\n}\n\n/**\n * Normalize hooks configuration\n * @internal Exported for testing\n */\nexport function normalizeHooksConfig(\n\tconfig: GkmConfig['hooks'],\n\tcwd: string = process.cwd(),\n): NormalizedHooksConfig | undefined {\n\tif (!config?.server) {\n\t\treturn undefined;\n\t}\n\n\t// Resolve the path (handle .ts extension)\n\tconst serverPath = config.server.endsWith('.ts')\n\t\t? config.server\n\t\t: `${config.server}.ts`;\n\n\tconst resolvedPath = resolve(cwd, serverPath);\n\n\treturn {\n\t\tserverHooksPath: resolvedPath,\n\t};\n}\n\n/**\n * Normalize production configuration\n * @internal Exported for testing\n */\nexport function normalizeProductionConfig(\n\tcliProduction: boolean,\n\tconfigProduction?: ProductionConfig,\n): NormalizedProductionConfig | undefined {\n\t// Production mode is only enabled if --production CLI flag is passed\n\tif (!cliProduction) {\n\t\treturn undefined;\n\t}\n\n\t// Merge CLI flag with config options\n\tconst config = configProduction ?? {};\n\n\treturn {\n\t\tenabled: true,\n\t\tbundle: config.bundle ?? true,\n\t\tminify: config.minify ?? true,\n\t\thealthCheck: config.healthCheck ?? '/health',\n\t\tgracefulShutdown: config.gracefulShutdown ?? true,\n\t\texternal: config.external ?? [],\n\t\tsubscribers: config.subscribers ?? 'exclude',\n\t\topenapi: config.openapi ?? false,\n\t\toptimizedHandlers: config.optimizedHandlers ?? true, // Default to optimized handlers in production\n\t};\n}\n\n/**\n * Get production config from GkmConfig\n * @internal\n */\nexport function getProductionConfigFromGkm(\n\tconfig: GkmConfig,\n): ProductionConfig | undefined {\n\tconst serverConfig = config.providers?.server;\n\tif (typeof serverConfig === 'object') {\n\t\treturn (serverConfig as ServerConfig).production;\n\t}\n\treturn undefined;\n}\n\nexport interface DevOptions {\n\tport?: number;\n\tportExplicit?: boolean;\n\tenableOpenApi?: boolean;\n\t/** Specific app to run in workspace mode (default: all apps) */\n\tapp?: string;\n\t/** Filter apps by pattern (passed to turbo --filter) */\n\tfilter?: string;\n\t/** Entry file to run (bypasses gkm config) */\n\tentry?: string;\n\t/** Watch for file changes (default: true with --entry) */\n\twatch?: boolean;\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n\t// Handle --entry mode: run any file with secret injection\n\tif (options.entry) {\n\t\treturn entryDevCommand(options);\n\t}\n\n\t// Load default .env file BEFORE loading config\n\t// This ensures env vars are available when config and its dependencies are loaded\n\tconst defaultEnv = loadEnvFiles('.env');\n\tif (defaultEnv.loaded.length > 0) {\n\t\tlogger.log(`š¦ Loaded env: ${defaultEnv.loaded.join(', ')}`);\n\t}\n\n\t// Check if we're in an app subdirectory\n\tconst appName = getAppNameFromCwd();\n\tlet config: GkmConfig;\n\tlet appRoot: string = process.cwd();\n\tlet secretsRoot: string = process.cwd(); // Where .gkm/secrets/ lives\n\tlet workspaceAppName: string | undefined; // Set if in workspace mode\n\tlet workspaceAppPort: number | undefined; // Port from workspace config\n\n\tif (appName) {\n\t\t// Try to load app-specific config from workspace\n\t\ttry {\n\t\t\tconst appConfig = await loadAppConfig();\n\t\t\tconfig = appConfig.gkmConfig;\n\t\t\tappRoot = appConfig.appRoot;\n\t\t\tsecretsRoot = appConfig.workspaceRoot;\n\t\t\tworkspaceAppName = appConfig.appName;\n\t\t\tworkspaceAppPort = appConfig.app.port;\n\t\t\tlogger.log(`š¦ Running app: ${appConfig.appName} on port ${workspaceAppPort}`);\n\t\t} catch {\n\t\t\t// Not in a workspace or app not found in workspace - fall back to regular loading\n\t\t\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t\t\t// Route to workspace dev mode for multi-app workspaces\n\t\t\tif (loadedConfig.type === 'workspace') {\n\t\t\t\tlogger.log('š¦ Detected workspace configuration');\n\t\t\t\treturn workspaceDevCommand(loadedConfig.workspace, options);\n\t\t\t}\n\n\t\t\tconfig = loadedConfig.raw as GkmConfig;\n\t\t}\n\t} else {\n\t\t// Try to load workspace config\n\t\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t\t// Route to workspace dev mode for multi-app workspaces\n\t\tif (loadedConfig.type === 'workspace') {\n\t\t\tlogger.log('š¦ Detected workspace configuration');\n\t\t\treturn workspaceDevCommand(loadedConfig.workspace, options);\n\t\t}\n\n\t\t// Single-app mode - use existing logic\n\t\tconfig = loadedConfig.raw as GkmConfig;\n\t}\n\n\t// Load any additional env files specified in config\n\tif (config.env) {\n\t\tconst { loaded, missing } = loadEnvFiles(config.env, appRoot);\n\t\tif (loaded.length > 0) {\n\t\t\tlogger.log(`š¦ Loaded env: ${loaded.join(', ')}`);\n\t\t}\n\t\tif (missing.length > 0) {\n\t\t\tlogger.warn(`ā ļø Missing env files: ${missing.join(', ')}`);\n\t\t}\n\t}\n\n\t// Force server provider for dev mode\n\tconst resolved = resolveProviders(config, { provider: 'server' });\n\n\tlogger.log('š Starting development server...');\n\tlogger.log(`Loading routes from: ${config.routes}`);\n\tif (config.functions) {\n\t\tlogger.log(`Loading functions from: ${config.functions}`);\n\t}\n\tif (config.crons) {\n\t\tlogger.log(`Loading crons from: ${config.crons}`);\n\t}\n\tif (config.subscribers) {\n\t\tlogger.log(`Loading subscribers from: ${config.subscribers}`);\n\t}\n\tlogger.log(`Using envParser: ${config.envParser}`);\n\n\t// Parse envParser and logger configuration\n\tconst { path: envParserPath, importPattern: envParserImportPattern } =\n\t\tparseModuleConfig(config.envParser, 'envParser');\n\tconst { path: loggerPath, importPattern: loggerImportPattern } =\n\t\tparseModuleConfig(config.logger, 'logger');\n\n\t// Normalize telescope configuration\n\tconst telescope = normalizeTelescopeConfig(config.telescope);\n\tif (telescope) {\n\t\tlogger.log(`š Telescope enabled at ${telescope.path}`);\n\t}\n\n\t// Normalize studio configuration\n\tconst studio = normalizeStudioConfig(config.studio);\n\tif (studio) {\n\t\tlogger.log(`šļø Studio enabled at ${studio.path}`);\n\t}\n\n\t// Normalize hooks configuration\n\tconst hooks = normalizeHooksConfig(config.hooks, appRoot);\n\tif (hooks) {\n\t\tlogger.log(`šŖ Server hooks enabled from ${config.hooks?.server}`);\n\t}\n\n\t// Resolve OpenAPI configuration\n\tconst openApiConfig = resolveOpenApiConfig(config);\n\t// Enable OpenAPI docs endpoint if either root config or provider config enables it\n\tconst enableOpenApi = openApiConfig.enabled || resolved.enableOpenApi;\n\tif (enableOpenApi) {\n\t\tlogger.log(`š OpenAPI output: ${OPENAPI_OUTPUT_PATH}`);\n\t}\n\n\tconst buildContext: BuildContext = {\n\t\tenvParserPath,\n\t\tenvParserImportPattern,\n\t\tloggerPath,\n\t\tloggerImportPattern,\n\t\ttelescope,\n\t\tstudio,\n\t\thooks,\n\t};\n\n\t// Build initial version\n\tawait buildServer(\n\t\tconfig,\n\t\tbuildContext,\n\t\tresolved.providers[0] as LegacyProvider,\n\t\tenableOpenApi,\n\t\tappRoot,\n\t);\n\n\t// Generate OpenAPI spec on startup\n\tif (enableOpenApi) {\n\t\tawait generateOpenApi(config);\n\t}\n\n\t// Determine runtime (default to node)\n\tconst runtime: Runtime = config.runtime ?? 'node';\n\n\t// Load secrets for dev mode and write to JSON file\n\tlet secretsJsonPath: string | undefined;\n\tconst appSecrets = await loadSecretsForApp(secretsRoot, workspaceAppName);\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tconst secretsDir = join(secretsRoot, '.gkm');\n\t\tawait mkdir(secretsDir, { recursive: true });\n\t\tsecretsJsonPath = join(secretsDir, 'dev-secrets.json');\n\t\tawait writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));\n\t\tlogger.log(`š Loaded ${Object.keys(appSecrets).length} secret(s)`);\n\t}\n\n\t// Start the dev server\n\t// Priority: explicit --port option > workspace app port > default 3000\n\tconst devServer = new DevServer(\n\t\tresolved.providers[0] as LegacyProvider,\n\t\toptions.port ?? workspaceAppPort ?? 3000,\n\t\toptions.portExplicit ?? false,\n\t\tenableOpenApi,\n\t\ttelescope,\n\t\tstudio,\n\t\truntime,\n\t\tappRoot,\n\t\tsecretsJsonPath,\n\t);\n\n\tawait devServer.start();\n\n\t// Watch for file changes\n\tconst envParserFile = config.envParser.split('#')[0] ?? config.envParser;\n\tconst loggerFile = config.logger.split('#')[0] ?? config.logger;\n\n\t// Get hooks file path for watching\n\tconst hooksFileParts = config.hooks?.server?.split('#');\n\tconst hooksFile = hooksFileParts?.[0];\n\n\tconst watchPatterns = [\n\t\tconfig.routes,\n\t\t...(config.functions ? [config.functions] : []),\n\t\t...(config.crons ? [config.crons] : []),\n\t\t...(config.subscribers ? [config.subscribers] : []),\n\t\t// Add .ts extension if not present for config files\n\t\tenvParserFile.endsWith('.ts') ? envParserFile : `${envParserFile}.ts`,\n\t\tloggerFile.endsWith('.ts') ? loggerFile : `${loggerFile}.ts`,\n\t\t// Add hooks file to watch list\n\t\t...(hooksFile\n\t\t\t? [hooksFile.endsWith('.ts') ? hooksFile : `${hooksFile}.ts`]\n\t\t\t: []),\n\t]\n\t\t.flat()\n\t\t.filter((p): p is string => typeof p === 'string');\n\n\t// Normalize patterns - remove leading ./ when using cwd option\n\tconst normalizedPatterns = watchPatterns.map((p) =>\n\t\tp.startsWith('./') ? p.slice(2) : p,\n\t);\n\n\tlogger.log(`š Watching for changes in: ${normalizedPatterns.join(', ')}`);\n\n\t// Resolve glob patterns to actual files (chokidar 4.x doesn't support globs)\n\tconst resolvedFiles = await fg(normalizedPatterns, {\n\t\tcwd: appRoot,\n\t\tabsolute: false,\n\t\tonlyFiles: true,\n\t});\n\n\t// Also watch the directories for new files\n\tconst dirsToWatch = [\n\t\t...new Set(\n\t\t\tresolvedFiles.map((f) => {\n\t\t\t\tconst parts = f.split('/');\n\t\t\t\treturn parts.slice(0, -1).join('/');\n\t\t\t}),\n\t\t),\n\t];\n\n\tlogger.log(\n\t\t`š Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`,\n\t);\n\n\tconst watcher = chokidar.watch([...resolvedFiles, ...dirsToWatch], {\n\t\tignored: /(^|[/\\\\])\\../, // ignore dotfiles\n\t\tpersistent: true,\n\t\tignoreInitial: true,\n\t\tcwd: appRoot,\n\t});\n\n\twatcher.on('ready', () => {\n\t\tlogger.log('š File watcher ready');\n\t});\n\n\twatcher.on('error', (error) => {\n\t\tlogger.error('ā Watcher error:', error);\n\t});\n\n\tlet rebuildTimeout: NodeJS.Timeout | null = null;\n\n\twatcher.on('change', async (path) => {\n\t\tlogger.log(`š File changed: ${path}`);\n\n\t\t// Debounce rebuilds\n\t\tif (rebuildTimeout) {\n\t\t\tclearTimeout(rebuildTimeout);\n\t\t}\n\n\t\trebuildTimeout = setTimeout(async () => {\n\t\t\ttry {\n\t\t\t\tlogger.log('š Rebuilding...');\n\t\t\t\tawait buildServer(\n\t\t\t\t\tconfig,\n\t\t\t\t\tbuildContext,\n\t\t\t\t\tresolved.providers[0] as LegacyProvider,\n\t\t\t\t\tenableOpenApi,\n\t\t\t\t\tappRoot,\n\t\t\t\t);\n\n\t\t\t\t// Regenerate OpenAPI if enabled\n\t\t\t\tif (enableOpenApi) {\n\t\t\t\t\tawait generateOpenApi(config, { silent: true });\n\t\t\t\t}\n\n\t\t\t\tlogger.log('ā
Rebuild complete, restarting server...');\n\t\t\t\tawait devServer.restart();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('ā Rebuild failed:', (error as Error).message);\n\t\t\t}\n\t\t}, 300);\n\t});\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down...');\n\n\t\t// Use sync-style shutdown to ensure it completes before exit\n\t\tPromise.all([watcher.close(), devServer.stop()])\n\t\t\t.catch((err) => {\n\t\t\t\tlogger.error('Error during shutdown:', err);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tprocess.exit(0);\n\t\t\t});\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n}\n\n/**\n * Generate all dependency environment variables for all apps.\n * Returns a flat object with all {APP_NAME}_URL variables.\n * @internal Exported for testing\n */\nexport function generateAllDependencyEnvVars(\n\tworkspace: NormalizedWorkspace,\n\turlPrefix = 'http://localhost',\n): Record<string, string> {\n\tconst env: Record<string, string> = {};\n\n\tfor (const appName of Object.keys(workspace.apps)) {\n\t\tconst appEnv = getDependencyEnvVars(workspace, appName, urlPrefix);\n\t\tObject.assign(env, appEnv);\n\t}\n\n\treturn env;\n}\n\n/**\n * Check for port conflicts across all apps.\n * Returns list of conflicts if any ports are duplicated.\n * @internal Exported for testing\n */\nexport function checkPortConflicts(\n\tworkspace: NormalizedWorkspace,\n): { app1: string; app2: string; port: number }[] {\n\tconst conflicts: { app1: string; app2: string; port: number }[] = [];\n\tconst portToApp = new Map<number, string>();\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tconst existingApp = portToApp.get(app.port);\n\t\tif (existingApp) {\n\t\t\tconflicts.push({ app1: existingApp, app2: appName, port: app.port });\n\t\t} else {\n\t\t\tportToApp.set(app.port, appName);\n\t\t}\n\t}\n\n\treturn conflicts;\n}\n\n/**\n * Next.js config file patterns to check.\n */\nconst NEXTJS_CONFIG_FILES = [\n\t'next.config.js',\n\t'next.config.ts',\n\t'next.config.mjs',\n];\n\n/**\n * Validation result for a frontend app.\n */\nexport interface FrontendValidationResult {\n\tappName: string;\n\tvalid: boolean;\n\terrors: string[];\n\twarnings: string[];\n}\n\n/**\n * Validate a frontend (Next.js) app configuration.\n * Checks for Next.js config file and dependency.\n * @internal Exported for testing\n */\nexport async function validateFrontendApp(\n\tappName: string,\n\tappPath: string,\n\tworkspaceRoot: string,\n): Promise<FrontendValidationResult> {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\tconst fullPath = join(workspaceRoot, appPath);\n\n\t// Check for Next.js config file\n\tconst hasConfigFile = NEXTJS_CONFIG_FILES.some((file) =>\n\t\texistsSync(join(fullPath, file)),\n\t);\n\n\tif (!hasConfigFile) {\n\t\terrors.push(\n\t\t\t`Next.js config file not found. Expected one of: ${NEXTJS_CONFIG_FILES.join(', ')}`,\n\t\t);\n\t}\n\n\t// Check for package.json\n\tconst packageJsonPath = join(fullPath, 'package.json');\n\tif (existsSync(packageJsonPath)) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\tconst pkg = require(packageJsonPath);\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (!deps.next) {\n\t\t\t\terrors.push(\n\t\t\t\t\t'Next.js not found in dependencies. Run: pnpm add next react react-dom',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for dev script\n\t\t\tif (!pkg.scripts?.dev) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t'No \"dev\" script found in package.json. Turbo expects a \"dev\" script to run.',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\terrors.push(`Failed to read package.json at ${packageJsonPath}`);\n\t\t}\n\t} else {\n\t\terrors.push(\n\t\t\t`package.json not found at ${appPath}. Run: pnpm init in the app directory.`,\n\t\t);\n\t}\n\n\treturn {\n\t\tappName,\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n/**\n * Validate all frontend apps in the workspace.\n * Returns validation results for each frontend app.\n * @internal Exported for testing\n */\nexport async function validateFrontendApps(\n\tworkspace: NormalizedWorkspace,\n): Promise<FrontendValidationResult[]> {\n\tconst results: FrontendValidationResult[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend') {\n\t\t\tconst result = await validateFrontendApp(\n\t\t\t\tappName,\n\t\t\t\tapp.path,\n\t\t\t\tworkspace.root,\n\t\t\t);\n\t\t\tresults.push(result);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Load secrets for development stage.\n * Returns env vars to inject, or empty object if secrets not configured/found.\n * @internal Exported for testing\n */\nexport async function loadDevSecrets(\n\tworkspace: NormalizedWorkspace,\n): Promise<Record<string, string>> {\n\t// Check if secrets are enabled in workspace config\n\tif (!workspace.secrets.enabled) {\n\t\treturn {};\n\t}\n\n\t// Try 'dev' stage first, then 'development'\n\tconst stages = ['dev', 'development'];\n\n\tfor (const stage of stages) {\n\t\tif (secretsExist(stage, workspace.root)) {\n\t\t\tconst secrets = await readStageSecrets(stage, workspace.root);\n\t\t\tif (secrets) {\n\t\t\t\tlogger.log(`š Loading secrets from stage: ${stage}`);\n\t\t\t\treturn toEmbeddableSecrets(secrets);\n\t\t\t}\n\t\t}\n\t}\n\n\tlogger.warn(\n\t\t'ā ļø Secrets enabled but no dev/development secrets found. Run \"gkm secrets:init --stage dev\"',\n\t);\n\treturn {};\n}\n\n/**\n * Load secrets from a path for dev mode.\n * For single app: returns secrets as-is.\n * For workspace app: maps {APP}_DATABASE_URL ā DATABASE_URL.\n * @internal Exported for testing\n */\nexport async function loadSecretsForApp(\n\tsecretsRoot: string,\n\tappName?: string,\n): Promise<Record<string, string>> {\n\t// Try 'dev' stage first, then 'development'\n\tconst stages = ['dev', 'development'];\n\n\tlet secrets: Record<string, string> = {};\n\n\tfor (const stage of stages) {\n\t\tif (secretsExist(stage, secretsRoot)) {\n\t\t\tconst stageSecrets = await readStageSecrets(stage, secretsRoot);\n\t\t\tif (stageSecrets) {\n\t\t\t\tlogger.log(`š Loading secrets from stage: ${stage}`);\n\t\t\t\tsecrets = toEmbeddableSecrets(stageSecrets);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Object.keys(secrets).length === 0) {\n\t\treturn {};\n\t}\n\n\t// Single app mode - no mapping needed\n\tif (!appName) {\n\t\treturn secrets;\n\t}\n\n\t// Workspace app mode - map {APP}_* to generic names\n\tconst prefix = appName.toUpperCase();\n\tconst mapped = { ...secrets };\n\n\t// Map {APP}_DATABASE_URL ā DATABASE_URL\n\tconst appDbUrl = secrets[`${prefix}_DATABASE_URL`];\n\tif (appDbUrl) {\n\t\tmapped.DATABASE_URL = appDbUrl;\n\t}\n\n\treturn mapped;\n}\n\n/**\n * Start docker-compose services for the workspace.\n * @internal Exported for testing\n */\nexport async function startWorkspaceServices(\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst services = workspace.services;\n\tif (!services.db && !services.cache && !services.mail) {\n\t\treturn;\n\t}\n\n\tconst servicesToStart: string[] = [];\n\n\tif (services.db) {\n\t\tservicesToStart.push('postgres');\n\t}\n\tif (services.cache) {\n\t\tservicesToStart.push('redis');\n\t}\n\tif (services.mail) {\n\t\tservicesToStart.push('mailpit');\n\t}\n\n\tif (servicesToStart.length === 0) {\n\t\treturn;\n\t}\n\n\tlogger.log(`š³ Starting services: ${servicesToStart.join(', ')}`);\n\n\ttry {\n\t\t// Check if docker-compose.yml exists\n\t\tconst composeFile = join(workspace.root, 'docker-compose.yml');\n\t\tif (!existsSync(composeFile)) {\n\t\t\tlogger.warn(\n\t\t\t\t'ā ļø No docker-compose.yml found. Services will not be started.',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Start services with docker-compose\n\t\texecSync(`docker compose up -d ${servicesToStart.join(' ')}`, {\n\t\t\tcwd: workspace.root,\n\t\t\tstdio: 'inherit',\n\t\t});\n\n\t\tlogger.log('ā
Services started');\n\t} catch (error) {\n\t\tlogger.error('ā Failed to start services:', (error as Error).message);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Workspace dev command - orchestrates multi-app development using Turbo.\n *\n * Flow:\n * 1. Check for port conflicts\n * 2. Start docker-compose services (db, cache, mail)\n * 3. Generate dependency URLs ({APP_NAME}_URL)\n * 4. Spawn turbo run dev with injected env vars\n */\nasync function workspaceDevCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DevOptions,\n): Promise<void> {\n\tconst appCount = Object.keys(workspace.apps).length;\n\tconst backendApps = Object.entries(workspace.apps).filter(\n\t\t([_, app]) => app.type === 'backend',\n\t);\n\tconst frontendApps = Object.entries(workspace.apps).filter(\n\t\t([_, app]) => app.type === 'frontend',\n\t);\n\n\tlogger.log(`\\nš Starting workspace: ${workspace.name}`);\n\tlogger.log(\n\t\t` ${backendApps.length} backend app(s), ${frontendApps.length} frontend app(s)`,\n\t);\n\n\t// Check for port conflicts\n\tconst conflicts = checkPortConflicts(workspace);\n\tif (conflicts.length > 0) {\n\t\tfor (const conflict of conflicts) {\n\t\t\tlogger.error(\n\t\t\t\t`ā Port conflict: Apps \"${conflict.app1}\" and \"${conflict.app2}\" both use port ${conflict.port}`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\n\t\t\t'Port conflicts detected. Please assign unique ports to each app.',\n\t\t);\n\t}\n\n\t// Validate frontend apps (Next.js setup)\n\tif (frontendApps.length > 0) {\n\t\tlogger.log('\\nš Validating frontend apps...');\n\t\tconst validationResults = await validateFrontendApps(workspace);\n\n\t\tlet hasErrors = false;\n\t\tfor (const result of validationResults) {\n\t\t\tif (!result.valid) {\n\t\t\t\thasErrors = true;\n\t\t\t\tlogger.error(\n\t\t\t\t\t`\\nā Frontend app \"${result.appName}\" validation failed:`,\n\t\t\t\t);\n\t\t\t\tfor (const error of result.errors) {\n\t\t\t\t\tlogger.error(` ⢠${error}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const warning of result.warnings) {\n\t\t\t\tlogger.warn(` ā ļø ${result.appName}: ${warning}`);\n\t\t\t}\n\t\t}\n\n\t\tif (hasErrors) {\n\t\t\tthrow new Error(\n\t\t\t\t'Frontend app validation failed. Fix the issues above and try again.',\n\t\t\t);\n\t\t}\n\t\tlogger.log('ā
Frontend apps validated');\n\t}\n\n\t// Generate initial clients for frontends with backend dependencies\n\tif (frontendApps.length > 0) {\n\t\tconst clientResults = await generateAllClients(workspace, { force: true });\n\t\tconst generatedCount = clientResults.filter((r) => r.generated).length;\n\t\tif (generatedCount > 0) {\n\t\t\tlogger.log(`\\nš¦ Generated ${generatedCount} API client(s)`);\n\t\t}\n\t}\n\n\t// Start docker-compose services\n\tawait startWorkspaceServices(workspace);\n\n\t// Load secrets if enabled\n\tconst secretsEnv = await loadDevSecrets(workspace);\n\tif (Object.keys(secretsEnv).length > 0) {\n\t\tlogger.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);\n\t}\n\n\t// Generate dependency URLs\n\tconst dependencyEnv = generateAllDependencyEnvVars(workspace);\n\tif (Object.keys(dependencyEnv).length > 0) {\n\t\tlogger.log('š” Dependency URLs:');\n\t\tfor (const [key, value] of Object.entries(dependencyEnv)) {\n\t\t\tlogger.log(` ${key}=${value}`);\n\t\t}\n\t}\n\n\t// Build turbo filter\n\tlet turboFilter: string[] = [];\n\tif (options.app) {\n\t\t// Run specific app\n\t\tif (!workspace.apps[options.app]) {\n\t\t\tconst appNames = Object.keys(workspace.apps).join(', ');\n\t\t\tthrow new Error(\n\t\t\t\t`App \"${options.app}\" not found. Available apps: ${appNames}`,\n\t\t\t);\n\t\t}\n\t\tturboFilter = ['--filter', options.app];\n\t\tlogger.log(`\\nšÆ Running single app: ${options.app}`);\n\t} else if (options.filter) {\n\t\t// Use custom filter\n\t\tturboFilter = ['--filter', options.filter];\n\t\tlogger.log(`\\nš Using filter: ${options.filter}`);\n\t} else {\n\t\t// Run all apps\n\t\tlogger.log(`\\nšÆ Running all ${appCount} apps`);\n\t}\n\n\t// List apps and their ports\n\tconst buildOrder = getAppBuildOrder(workspace);\n\tlogger.log('\\nš Apps (in dependency order):');\n\tfor (const appName of buildOrder) {\n\t\tconst app = workspace.apps[appName];\n\t\tif (!app) continue;\n\t\tconst deps =\n\t\t\tapp.dependencies.length > 0\n\t\t\t\t? ` (depends on: ${app.dependencies.join(', ')})`\n\t\t\t\t: '';\n\t\tlogger.log(\n\t\t\t` ${app.type === 'backend' ? 'š§' : 'š'} ${appName} ā http://localhost:${app.port}${deps}`,\n\t\t);\n\t}\n\n\t// Find the config file path for GKM_CONFIG_PATH\n\tconst configFiles = ['gkm.config.ts', 'gkm.config.js', 'gkm.config.json'];\n\tlet configPath = '';\n\tfor (const file of configFiles) {\n\t\tconst fullPath = join(workspace.root, file);\n\t\tif (existsSync(fullPath)) {\n\t\t\tconfigPath = fullPath;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Prepare environment variables\n\t// Order matters: secrets first, then dependencies (dependencies can override)\n\tconst turboEnv: Record<string, string> = {\n\t\t...process.env,\n\t\t...secretsEnv,\n\t\t...dependencyEnv,\n\t\tNODE_ENV: 'development',\n\t\t// Inject config path so child processes can find the workspace config\n\t\t...(configPath ? { GKM_CONFIG_PATH: configPath } : {}),\n\t};\n\n\t// Spawn turbo run dev\n\tlogger.log('\\nš Starting turbo run dev...\\n');\n\n\tconst turboProcess = spawn('pnpm', ['turbo', 'run', 'dev', ...turboFilter], {\n\t\tcwd: workspace.root,\n\t\tstdio: 'inherit',\n\t\tenv: turboEnv,\n\t});\n\n\t// Set up file watcher for backend endpoint changes (smart client regeneration)\n\tlet endpointWatcher: ReturnType<typeof chokidar.watch> | null = null;\n\n\tif (frontendApps.length > 0 && backendApps.length > 0) {\n\t\t// Collect all backend route patterns to watch\n\t\tconst watchPatterns: string[] = [];\n\t\tconst backendRouteMap = new Map<string, string[]>(); // routes pattern -> backend app names\n\n\t\tfor (const [appName, app] of backendApps) {\n\t\t\tconst routePatterns = normalizeRoutes(app.routes);\n\t\t\tfor (const routePattern of routePatterns) {\n\t\t\t\tconst fullPattern = join(workspace.root, app.path, routePattern);\n\t\t\t\twatchPatterns.push(fullPattern);\n\n\t\t\t\t// Map pattern to app name for change detection\n\t\t\t\tconst patternKey = join(app.path, routePattern);\n\t\t\t\tconst existing = backendRouteMap.get(patternKey) || [];\n\t\t\t\tbackendRouteMap.set(patternKey, [...existing, appName]);\n\t\t\t}\n\t\t}\n\n\t\tif (watchPatterns.length > 0) {\n\t\t\t// Resolve glob patterns to files\n\t\t\tconst resolvedFiles = await fg(watchPatterns, {\n\t\t\t\tcwd: workspace.root,\n\t\t\t\tabsolute: true,\n\t\t\t\tonlyFiles: true,\n\t\t\t});\n\n\t\t\tif (resolvedFiles.length > 0) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`\\nš Watching ${resolvedFiles.length} endpoint file(s) for schema changes`,\n\t\t\t\t);\n\n\t\t\t\tendpointWatcher = chokidar.watch(resolvedFiles, {\n\t\t\t\t\tignored: /(^|[/\\\\])\\../,\n\t\t\t\t\tpersistent: true,\n\t\t\t\t\tignoreInitial: true,\n\t\t\t\t});\n\n\t\t\t\tlet regenerateTimeout: NodeJS.Timeout | null = null;\n\n\t\t\t\tendpointWatcher.on('change', async (changedPath) => {\n\t\t\t\t\t// Debounce regeneration\n\t\t\t\t\tif (regenerateTimeout) {\n\t\t\t\t\t\tclearTimeout(regenerateTimeout);\n\t\t\t\t\t}\n\n\t\t\t\t\tregenerateTimeout = setTimeout(async () => {\n\t\t\t\t\t\t// Find which backend app this file belongs to\n\t\t\t\t\t\tconst changedBackends: string[] = [];\n\n\t\t\t\t\t\tfor (const [appName, app] of backendApps) {\n\t\t\t\t\t\t\tconst routePatterns = normalizeRoutes(app.routes);\n\t\t\t\t\t\t\tfor (const routePattern of routePatterns) {\n\t\t\t\t\t\t\t\tconst routesDir = join(\n\t\t\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\t\t\tapp.path,\n\t\t\t\t\t\t\t\t\troutePattern.split('*')[0] || '',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (changedPath.startsWith(routesDir.replace(/\\/$/, ''))) {\n\t\t\t\t\t\t\t\t\tchangedBackends.push(appName);\n\t\t\t\t\t\t\t\t\tbreak; // Found a match, no need to check other patterns\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (changedBackends.length === 0) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Find frontends that depend on changed backends\n\t\t\t\t\t\tconst affectedFrontends = new Set<string>();\n\t\t\t\t\t\tfor (const backend of changedBackends) {\n\t\t\t\t\t\t\tconst dependents = getDependentFrontends(workspace, backend);\n\t\t\t\t\t\t\tfor (const frontend of dependents) {\n\t\t\t\t\t\t\t\taffectedFrontends.add(frontend);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (affectedFrontends.size === 0) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Regenerate clients for affected frontends\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t`\\nš Detected schema change in ${changedBackends.join(', ')}`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tfor (const frontend of affectedFrontends) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst results = await generateClientForFrontend(\n\t\t\t\t\t\t\t\t\tworkspace,\n\t\t\t\t\t\t\t\t\tfrontend,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tfor (const result of results) {\n\t\t\t\t\t\t\t\t\tif (result.generated) {\n\t\t\t\t\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t\t\t\t\t` š¦ Regenerated client for ${result.frontendApp} (${result.endpointCount} endpoints)`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t\t` ā Failed to regenerate client for ${frontend}: ${(error as Error).message}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 500); // 500ms debounce\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down workspace...');\n\n\t\t// Close endpoint watcher\n\t\tif (endpointWatcher) {\n\t\t\tendpointWatcher.close().catch(() => {});\n\t\t}\n\n\t\t// Kill turbo process\n\t\tif (turboProcess.pid) {\n\t\t\ttry {\n\t\t\t\t// Try to kill the process group\n\t\t\t\tprocess.kill(-turboProcess.pid, 'SIGTERM');\n\t\t\t} catch {\n\t\t\t\t// Fall back to killing just the process\n\t\t\t\tturboProcess.kill('SIGTERM');\n\t\t\t}\n\t\t}\n\n\t\t// Give processes time to clean up\n\t\tsetTimeout(() => {\n\t\t\tprocess.exit(0);\n\t\t}, 2000);\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n\n\t// Wait for turbo to exit\n\treturn new Promise((resolve, reject) => {\n\t\tturboProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Turbo error:', error);\n\t\t\treject(error);\n\t\t});\n\n\t\tturboProcess.on('exit', (code) => {\n\t\t\t// Close watcher on exit\n\t\t\tif (endpointWatcher) {\n\t\t\t\tendpointWatcher.close().catch(() => {});\n\t\t\t}\n\n\t\t\tif (code !== null && code !== 0) {\n\t\t\t\treject(new Error(`Turbo exited with code ${code}`));\n\t\t\t} else {\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\t});\n}\n\nasync function buildServer(\n\tconfig: any,\n\tcontext: BuildContext,\n\tprovider: LegacyProvider,\n\tenableOpenApi: boolean,\n\tappRoot: string = process.cwd(),\n): Promise<void> {\n\t// Initialize generators\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst functionGenerator = new FunctionGenerator();\n\tconst cronGenerator = new CronGenerator();\n\tconst subscriberGenerator = new SubscriberGenerator();\n\n\t// Load all constructs (resolve paths relative to appRoot)\n\tconst [allEndpoints, allFunctions, allCrons, allSubscribers] =\n\t\tawait Promise.all([\n\t\t\tendpointGenerator.load(config.routes, appRoot),\n\t\t\tconfig.functions ? functionGenerator.load(config.functions, appRoot) : [],\n\t\t\tconfig.crons ? cronGenerator.load(config.crons, appRoot) : [],\n\t\t\tconfig.subscribers\n\t\t\t\t? subscriberGenerator.load(config.subscribers, appRoot)\n\t\t\t\t: [],\n\t\t]);\n\n\t// Ensure .gkm directory exists in app root\n\tconst outputDir = join(appRoot, '.gkm', provider);\n\tawait mkdir(outputDir, { recursive: true });\n\n\t// Build for server provider\n\tawait Promise.all([\n\t\tendpointGenerator.build(context, allEndpoints, outputDir, {\n\t\t\tprovider,\n\t\t\tenableOpenApi,\n\t\t}),\n\t\tfunctionGenerator.build(context, allFunctions, outputDir, { provider }),\n\t\tcronGenerator.build(context, allCrons, outputDir, { provider }),\n\t\tsubscriberGenerator.build(context, allSubscribers, outputDir, { provider }),\n\t]);\n}\n\n/**\n * Find the directory containing .gkm/secrets/.\n * Walks up from cwd until it finds one, or returns cwd.\n * @internal Exported for testing\n */\nexport function findSecretsRoot(startDir: string): string {\n\tlet dir = startDir;\n\twhile (dir !== '/') {\n\t\tif (existsSync(join(dir, '.gkm', 'secrets'))) {\n\t\t\treturn dir;\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn startDir;\n}\n\n/**\n * Create a wrapper script that injects secrets before importing the entry file.\n * @internal Exported for testing\n */\nexport async function createEntryWrapper(\n\twrapperPath: string,\n\tentryPath: string,\n\tsecretsJsonPath?: string,\n): Promise<void> {\n\tconst credentialsInjection = secretsJsonPath\n\t\t? `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { existsSync, readFileSync } from 'node:fs';\n\n// Inject dev secrets into Credentials (before app import)\nconst secretsPath = '${secretsJsonPath}';\nif (existsSync(secretsPath)) {\n Object.assign(Credentials, JSON.parse(readFileSync(secretsPath, 'utf-8')));\n}\n\n`\n\t\t: '';\n\n\t// Use dynamic import() to ensure secrets are assigned before the entry file loads\n\t// Static imports are hoisted, so Object.assign would run after the entry file is loaded\n\tconst content = `#!/usr/bin/env node\n/**\n * Entry wrapper generated by 'gkm dev --entry'\n */\n${credentialsInjection}// Import and run the user's entry file (dynamic import ensures secrets load first)\nawait import('${entryPath}');\n`;\n\n\tawait writeFile(wrapperPath, content);\n}\n\n/**\n * Run any TypeScript file with secret injection.\n * Does not require gkm.config.ts.\n */\nasync function entryDevCommand(options: DevOptions): Promise<void> {\n\tconst { entry, port = 3000, watch = true } = options;\n\n\tif (!entry) {\n\t\tthrow new Error('--entry requires a file path');\n\t}\n\n\tconst entryPath = resolve(process.cwd(), entry);\n\n\tif (!existsSync(entryPath)) {\n\t\tthrow new Error(`Entry file not found: ${entryPath}`);\n\t}\n\n\tlogger.log(`š Starting entry file: ${entry}`);\n\n\t// Load .env files\n\tconst defaultEnv = loadEnvFiles('.env');\n\tif (defaultEnv.loaded.length > 0) {\n\t\tlogger.log(`š¦ Loaded env: ${defaultEnv.loaded.join(', ')}`);\n\t}\n\n\t// Determine secrets root (current dir or workspace root)\n\tconst secretsRoot = findSecretsRoot(process.cwd());\n\tlogger.log(`š Secrets root: ${secretsRoot}`);\n\n\t// Determine app name for per-app secret mapping\n\tconst appName = getAppNameFromCwd() ?? undefined;\n\tif (appName) {\n\t\tlogger.log(`š¦ App name: ${appName}`);\n\t}\n\n\t// Load secrets\n\tconst appSecrets = await loadSecretsForApp(secretsRoot, appName);\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tlogger.log(`š Loaded ${Object.keys(appSecrets).length} secret(s)`);\n\t} else {\n\t\tlogger.log(`ā ļø No secrets found in ${secretsRoot}/.gkm/secrets/`);\n\t}\n\n\t// Write secrets to temp JSON file\n\tlet secretsJsonPath: string | undefined;\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tconst secretsDir = join(secretsRoot, '.gkm');\n\t\tawait mkdir(secretsDir, { recursive: true });\n\t\tsecretsJsonPath = join(secretsDir, 'dev-secrets.json');\n\t\tawait writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));\n\t}\n\n\t// Create wrapper entry that injects secrets before importing user's file\n\tconst wrapperDir = join(process.cwd(), '.gkm');\n\tawait mkdir(wrapperDir, { recursive: true });\n\tconst wrapperPath = join(wrapperDir, 'entry-wrapper.ts');\n\tawait createEntryWrapper(wrapperPath, entryPath, secretsJsonPath);\n\n\t// Start with tsx\n\tconst runner = new EntryRunner(wrapperPath, entryPath, watch, port);\n\tawait runner.start();\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down...');\n\t\trunner.stop();\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n\n\t// Keep the process alive\n\tawait new Promise(() => {});\n}\n\n/**\n * Runs and watches a TypeScript entry file using tsx.\n */\nclass EntryRunner {\n\tprivate childProcess: ChildProcess | null = null;\n\tprivate watcher: ReturnType<typeof chokidar.watch> | null = null;\n\tprivate isRunning = false;\n\n\tconstructor(\n\t\tprivate wrapperPath: string,\n\t\tprivate entryPath: string,\n\t\tprivate watch: boolean,\n\t\tprivate port: number,\n\t) {}\n\n\tasync start(): Promise<void> {\n\t\tawait this.runProcess();\n\n\t\tif (this.watch) {\n\t\t\t// Watch the entry file's directory for changes\n\t\t\tconst watchDir = dirname(this.entryPath);\n\n\t\t\tthis.watcher = chokidar.watch(watchDir, {\n\t\t\t\tignored: /(^|[/\\\\])\\../,\n\t\t\t\tpersistent: true,\n\t\t\t\tignoreInitial: true,\n\t\t\t});\n\n\t\t\tlet restartTimeout: NodeJS.Timeout | null = null;\n\n\t\t\tthis.watcher.on('change', (path) => {\n\t\t\t\tlogger.log(`š File changed: ${path}`);\n\n\t\t\t\t// Debounce restarts\n\t\t\t\tif (restartTimeout) {\n\t\t\t\t\tclearTimeout(restartTimeout);\n\t\t\t\t}\n\n\t\t\t\trestartTimeout = setTimeout(async () => {\n\t\t\t\t\tlogger.log('š Restarting...');\n\t\t\t\t\tawait this.restart();\n\t\t\t\t}, 300);\n\t\t\t});\n\n\t\t\tlogger.log(`š Watching for changes in: ${watchDir}`);\n\t\t}\n\t}\n\n\tprivate async runProcess(): Promise<void> {\n\t\t// Pass PORT as environment variable\n\t\tconst env = { ...process.env, PORT: String(this.port) };\n\n\t\tthis.childProcess = spawn('npx', ['tsx', this.wrapperPath], {\n\t\t\tstdio: 'inherit',\n\t\t\tenv,\n\t\t\tdetached: true,\n\t\t});\n\n\t\tthis.isRunning = true;\n\n\t\tthis.childProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Process error:', error);\n\t\t});\n\n\t\tthis.childProcess.on('exit', (code) => {\n\t\t\tif (code !== null && code !== 0 && code !== 143) {\n\t\t\t\t// 143 = SIGTERM\n\t\t\t\tlogger.error(`ā Process exited with code ${code}`);\n\t\t\t}\n\t\t\tthis.isRunning = false;\n\t\t});\n\n\t\t// Give the process a moment to start\n\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\n\t\tif (this.isRunning) {\n\t\t\tlogger.log(`\\nš Running at http://localhost:${this.port}`);\n\t\t}\n\t}\n\n\tasync restart(): Promise<void> {\n\t\tthis.stopProcess();\n\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\tawait this.runProcess();\n\t}\n\n\tstop(): void {\n\t\tthis.watcher?.close();\n\t\tthis.stopProcess();\n\t}\n\n\tprivate stopProcess(): void {\n\t\tif (this.childProcess && this.isRunning) {\n\t\t\tconst pid = this.childProcess.pid;\n\t\t\tif (pid) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(-pid, 'SIGTERM');\n\t\t\t\t} catch {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 'SIGTERM');\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Process already dead\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.childProcess = null;\n\t\t\tthis.isRunning = false;\n\t\t}\n\t}\n}\n\nclass DevServer {\n\tprivate serverProcess: ChildProcess | null = null;\n\tprivate isRunning = false;\n\tprivate actualPort: number;\n\n\tconstructor(\n\t\tprivate provider: LegacyProvider,\n\t\tprivate requestedPort: number,\n\t\tprivate portExplicit: boolean,\n\t\tprivate enableOpenApi: boolean,\n\t\tprivate telescope: NormalizedTelescopeConfig | undefined,\n\t\tprivate studio: NormalizedStudioConfig | undefined,\n\t\tprivate runtime: Runtime = 'node',\n\t\tprivate appRoot: string = process.cwd(),\n\t\tprivate secretsJsonPath?: string,\n\t) {\n\t\tthis.actualPort = requestedPort;\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.isRunning) {\n\t\t\tawait this.stop();\n\t\t}\n\n\t\t// Check port availability\n\t\tif (this.portExplicit) {\n\t\t\t// Port was explicitly specified - throw if unavailable\n\t\t\tconst available = await isPortAvailable(this.requestedPort);\n\t\t\tif (!available) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Port ${this.requestedPort} is already in use. ` +\n\t\t\t\t\t\t`Either stop the process using that port or omit -p/--port to auto-select an available port.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.actualPort = this.requestedPort;\n\t\t} else {\n\t\t\t// Find an available port starting from the default\n\t\t\tthis.actualPort = await findAvailablePort(this.requestedPort);\n\n\t\t\tif (this.actualPort !== this.requestedPort) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`ā¹ļø Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst serverEntryPath = join(\n\t\t\tthis.appRoot,\n\t\t\t'.gkm',\n\t\t\tthis.provider,\n\t\t\t'server.ts',\n\t\t);\n\n\t\t// Create server entry file\n\t\tawait this.createServerEntry();\n\n\t\tlogger.log(`\\n⨠Starting server on port ${this.actualPort}...`);\n\n\t\t// Start the server using tsx (TypeScript execution)\n\t\t// Use detached: true so we can kill the entire process tree\n\t\tthis.serverProcess = spawn(\n\t\t\t'npx',\n\t\t\t['tsx', serverEntryPath, '--port', this.actualPort.toString()],\n\t\t\t{\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, NODE_ENV: 'development' },\n\t\t\t\tdetached: true,\n\t\t\t},\n\t\t);\n\n\t\tthis.isRunning = true;\n\n\t\tthis.serverProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Server error:', error);\n\t\t});\n\n\t\tthis.serverProcess.on('exit', (code, signal) => {\n\t\t\tif (code !== null && code !== 0 && signal !== 'SIGTERM') {\n\t\t\t\tlogger.error(`ā Server exited with code ${code}`);\n\t\t\t}\n\t\t\tthis.isRunning = false;\n\t\t});\n\n\t\t// Give the server a moment to start\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\n\n\t\tif (this.isRunning) {\n\t\t\tlogger.log(`\\nš Server running at http://localhost:${this.actualPort}`);\n\t\t\tif (this.enableOpenApi) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`š API Docs available at http://localhost:${this.actualPort}/__docs`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.telescope) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`š Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.studio) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`šļø Studio available at http://localhost:${this.actualPort}${this.studio.path}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tconst port = this.actualPort;\n\n\t\tif (this.serverProcess && this.isRunning) {\n\t\t\tconst pid = this.serverProcess.pid;\n\n\t\t\t// Use SIGKILL directly since the server ignores SIGTERM\n\t\t\tif (pid) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(-pid, 'SIGKILL');\n\t\t\t\t} catch {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 'SIGKILL');\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Process might already be dead\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.serverProcess = null;\n\t\t\tthis.isRunning = false;\n\t\t}\n\n\t\t// Also kill any processes still holding the port\n\t\tthis.killProcessesOnPort(port);\n\t}\n\n\tprivate killProcessesOnPort(port: number): void {\n\t\ttry {\n\t\t\t// Use lsof to find PIDs on the port and kill them with -9\n\t\t\texecSync(`lsof -ti tcp:${port} | xargs kill -9 2>/dev/null || true`, {\n\t\t\t\tstdio: 'ignore',\n\t\t\t});\n\t\t} catch {\n\t\t\t// Ignore errors - port may already be free\n\t\t}\n\t}\n\n\tasync restart(): Promise<void> {\n\t\tconst portToReuse = this.actualPort;\n\t\tawait this.stop();\n\n\t\t// Wait for port to be released (up to 3 seconds)\n\t\tlet attempts = 0;\n\t\twhile (attempts < 30) {\n\t\t\tif (await isPortAvailable(portToReuse)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t\tattempts++;\n\t\t}\n\n\t\t// Force reuse the same port\n\t\tthis.requestedPort = portToReuse;\n\t\tawait this.start();\n\t}\n\n\tprivate async createServerEntry(): Promise<void> {\n\t\tconst { writeFile: fsWriteFile } = await import('node:fs/promises');\n\t\tconst { relative, dirname } = await import('node:path');\n\n\t\tconst serverPath = join(this.appRoot, '.gkm', this.provider, 'server.ts');\n\n\t\tconst relativeAppPath = relative(\n\t\t\tdirname(serverPath),\n\t\t\tjoin(dirname(serverPath), 'app.js'),\n\t\t);\n\n\t\t// Generate credentials injection code if secrets are available\n\t\tconst credentialsInjection = this.secretsJsonPath\n\t\t\t? `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { existsSync, readFileSync } from 'node:fs';\n\n// Inject dev secrets into Credentials (must happen before app import)\nconst secretsPath = '${this.secretsJsonPath}';\nif (existsSync(secretsPath)) {\n Object.assign(Credentials, JSON.parse(readFileSync(secretsPath, 'utf-8')));\n}\n\n`\n\t\t\t: '';\n\n\t\tconst serveCode =\n\t\t\tthis.runtime === 'bun'\n\t\t\t\t? `Bun.serve({\n port,\n fetch: app.fetch,\n });`\n\t\t\t\t: `const { serve } = await import('@hono/node-server');\n const server = serve({\n fetch: app.fetch,\n port,\n });\n // Inject WebSocket support if available\n const injectWs = (app as any).__injectWebSocket;\n if (injectWs) {\n injectWs(server);\n console.log('š Telescope real-time updates enabled');\n }`;\n\n\t\tconst content = `#!/usr/bin/env node\n/**\n * Development server entry point\n * This file is auto-generated by 'gkm dev'\n */\n${credentialsInjection}import { createApp } from './${relativeAppPath.startsWith('.') ? relativeAppPath : `./${relativeAppPath}`}';\n\nconst port = process.argv.includes('--port')\n ? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])\n : 3000;\n\n// createApp is async to support optional WebSocket setup\nconst { app, start } = await createApp(undefined, ${this.enableOpenApi});\n\n// Start the server\nstart({\n port,\n serve: async (app, port) => {\n ${serveCode}\n },\n}).catch((error) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n});\n`;\n\n\t\tawait fsWriteFile(serverPath, content);\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type {\n\tCronInfo,\n\tFunctionInfo,\n\tRouteInfo,\n\tSubscriberInfo,\n} from '../types';\n\nconst logger = console;\n\nexport type ManifestProvider = 'aws' | 'server';\n\nexport interface ServerAppInfo {\n\thandler: string;\n\tendpoints: string;\n}\n\nexport async function generateAwsManifest(\n\toutputDir: string,\n\troutes: RouteInfo[],\n\tfunctions: FunctionInfo[],\n\tcrons: CronInfo[],\n\tsubscribers: SubscriberInfo[],\n): Promise<void> {\n\tconst manifestDir = join(outputDir, 'manifest');\n\tawait mkdir(manifestDir, { recursive: true });\n\n\t// Filter out 'ALL' method routes (server-specific)\n\tconst awsRoutes = routes.filter((r) => r.method !== 'ALL');\n\n\tconst content = `export const manifest = {\n routes: ${JSON.stringify(awsRoutes, null, 2)},\n functions: ${JSON.stringify(functions, null, 2)},\n crons: ${JSON.stringify(crons, null, 2)},\n subscribers: ${JSON.stringify(subscribers, null, 2)},\n} as const;\n\n// Derived types\nexport type Route = (typeof manifest.routes)[number];\nexport type Function = (typeof manifest.functions)[number];\nexport type Cron = (typeof manifest.crons)[number];\nexport type Subscriber = (typeof manifest.subscribers)[number];\n\n// Useful union types\nexport type Authorizer = Route['authorizer'];\nexport type HttpMethod = Route['method'];\nexport type RoutePath = Route['path'];\n`;\n\n\tconst manifestPath = join(manifestDir, 'aws.ts');\n\tawait writeFile(manifestPath, content);\n\n\tlogger.log(\n\t\t`Generated AWS manifest with ${awsRoutes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`,\n\t);\n\tlogger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);\n}\n\nexport async function generateServerManifest(\n\toutputDir: string,\n\tappInfo: ServerAppInfo,\n\troutes: RouteInfo[],\n\tsubscribers: SubscriberInfo[],\n): Promise<void> {\n\tconst manifestDir = join(outputDir, 'manifest');\n\tawait mkdir(manifestDir, { recursive: true });\n\n\t// For server, extract route metadata (path, method, authorizer)\n\tconst serverRoutes = routes\n\t\t.filter((r) => r.method !== 'ALL')\n\t\t.map((r) => ({\n\t\t\tpath: r.path,\n\t\t\tmethod: r.method,\n\t\t\tauthorizer: r.authorizer,\n\t\t}));\n\n\t// Server subscribers only need name and events\n\tconst serverSubscribers = subscribers.map((s) => ({\n\t\tname: s.name,\n\t\tsubscribedEvents: s.subscribedEvents,\n\t}));\n\n\tconst content = `export const manifest = {\n app: ${JSON.stringify(appInfo, null, 2)},\n routes: ${JSON.stringify(serverRoutes, null, 2)},\n subscribers: ${JSON.stringify(serverSubscribers, null, 2)},\n} as const;\n\n// Derived types\nexport type Route = (typeof manifest.routes)[number];\nexport type Subscriber = (typeof manifest.subscribers)[number];\n\n// Useful union types\nexport type Authorizer = Route['authorizer'];\nexport type HttpMethod = Route['method'];\nexport type RoutePath = Route['path'];\n`;\n\n\tconst manifestPath = join(manifestDir, 'server.ts');\n\tawait writeFile(manifestPath, content);\n\n\tlogger.log(\n\t\t`Generated server manifest with ${serverRoutes.length} routes, ${serverSubscribers.length} subscribers`,\n\t);\n\tlogger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);\n}\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig, loadWorkspaceConfig, parseModuleConfig } from '../config';\nimport {\n\tgetProductionConfigFromGkm,\n\tnormalizeHooksConfig,\n\tnormalizeProductionConfig,\n\tnormalizeStudioConfig,\n\tnormalizeTelescopeConfig,\n} from '../dev';\nimport {\n\tCronGenerator,\n\tEndpointGenerator,\n\tFunctionGenerator,\n\ttype GeneratedConstruct,\n\tSubscriberGenerator,\n} from '../generators';\nimport type {\n\tBuildOptions,\n\tBuildResult,\n\tLegacyProvider,\n\tRouteInfo,\n} from '../types';\nimport {\n\tgetAppBuildOrder,\n\ttype NormalizedAppConfig,\n\ttype NormalizedWorkspace,\n} from '../workspace/index.js';\nimport {\n\tgenerateAwsManifest,\n\tgenerateServerManifest,\n\ttype ServerAppInfo,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(\n\toptions: BuildOptions,\n): Promise<BuildResult> {\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace build mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceBuildCommand(loadedConfig.workspace, options);\n\t}\n\n\t// Single-app build - use existing logic\n\tconst config = await loadConfig();\n\n\t// Resolve providers from new config format\n\tconst resolved = resolveProviders(config, options);\n\n\t// Normalize production configuration\n\tconst productionConfigFromGkm = getProductionConfigFromGkm(config);\n\tconst production = normalizeProductionConfig(\n\t\toptions.production ?? false,\n\t\tproductionConfigFromGkm,\n\t);\n\n\tif (production) {\n\t\tlogger.log(`š Building for PRODUCTION`);\n\t}\n\n\tlogger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n\tlogger.log(`Loading routes from: ${config.routes}`);\n\tif (config.functions) {\n\t\tlogger.log(`Loading functions from: ${config.functions}`);\n\t}\n\tif (config.crons) {\n\t\tlogger.log(`Loading crons from: ${config.crons}`);\n\t}\n\tif (config.subscribers) {\n\t\tlogger.log(`Loading subscribers from: ${config.subscribers}`);\n\t}\n\tlogger.log(`Using envParser: ${config.envParser}`);\n\n\t// Parse envParser and logger configuration\n\tconst { path: envParserPath, importPattern: envParserImportPattern } =\n\t\tparseModuleConfig(config.envParser, 'envParser');\n\tconst { path: loggerPath, importPattern: loggerImportPattern } =\n\t\tparseModuleConfig(config.logger, 'logger');\n\n\t// Normalize telescope configuration (disabled in production)\n\tconst telescope = production\n\t\t? undefined\n\t\t: normalizeTelescopeConfig(config.telescope);\n\tif (telescope) {\n\t\tlogger.log(`š Telescope enabled at ${telescope.path}`);\n\t}\n\n\t// Normalize studio configuration (disabled in production)\n\tconst studio = production ? undefined : normalizeStudioConfig(config.studio);\n\tif (studio) {\n\t\tlogger.log(`šļø Studio enabled at ${studio.path}`);\n\t}\n\n\t// Normalize hooks configuration\n\tconst hooks = normalizeHooksConfig(config.hooks);\n\tif (hooks) {\n\t\tlogger.log(`šŖ Server hooks enabled`);\n\t}\n\n\t// Extract docker compose services for env var auto-population\n\tconst services = config.docker?.compose?.services;\n\tconst dockerServices = services\n\t\t? Array.isArray(services)\n\t\t\t? {\n\t\t\t\t\tpostgres: services.includes('postgres'),\n\t\t\t\t\tredis: services.includes('redis'),\n\t\t\t\t\trabbitmq: services.includes('rabbitmq'),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tpostgres: Boolean(services.postgres),\n\t\t\t\t\tredis: Boolean(services.redis),\n\t\t\t\t\trabbitmq: Boolean(services.rabbitmq),\n\t\t\t\t}\n\t\t: undefined;\n\n\tconst buildContext: BuildContext = {\n\t\tenvParserPath,\n\t\tenvParserImportPattern,\n\t\tloggerPath,\n\t\tloggerImportPattern,\n\t\ttelescope,\n\t\tstudio,\n\t\thooks,\n\t\tproduction,\n\t\tdockerServices,\n\t};\n\n\t// Initialize generators\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst functionGenerator = new FunctionGenerator();\n\tconst cronGenerator = new CronGenerator();\n\tconst subscriberGenerator = new SubscriberGenerator();\n\n\t// Load all constructs in parallel\n\tconst [allEndpoints, allFunctions, allCrons, allSubscribers] =\n\t\tawait Promise.all([\n\t\t\tendpointGenerator.load(config.routes),\n\t\t\tconfig.functions ? functionGenerator.load(config.functions) : [],\n\t\t\tconfig.crons ? cronGenerator.load(config.crons) : [],\n\t\t\tconfig.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n\t\t]);\n\n\tlogger.log(`Found ${allEndpoints.length} endpoints`);\n\tlogger.log(`Found ${allFunctions.length} functions`);\n\tlogger.log(`Found ${allCrons.length} crons`);\n\tlogger.log(`Found ${allSubscribers.length} subscribers`);\n\n\tif (\n\t\tallEndpoints.length === 0 &&\n\t\tallFunctions.length === 0 &&\n\t\tallCrons.length === 0 &&\n\t\tallSubscribers.length === 0\n\t) {\n\t\tlogger.log(\n\t\t\t'No endpoints, functions, crons, or subscribers found to process',\n\t\t);\n\t\treturn {};\n\t}\n\n\t// Ensure .gkm directory exists\n\tconst rootOutputDir = join(process.cwd(), '.gkm');\n\tawait mkdir(rootOutputDir, { recursive: true });\n\n\t// Build for each provider and generate per-provider manifests\n\tlet result: BuildResult = {};\n\tfor (const provider of resolved.providers) {\n\t\tconst providerResult = await buildForProvider(\n\t\t\tprovider,\n\t\t\tbuildContext,\n\t\t\trootOutputDir,\n\t\t\tendpointGenerator,\n\t\t\tfunctionGenerator,\n\t\t\tcronGenerator,\n\t\t\tsubscriberGenerator,\n\t\t\tallEndpoints,\n\t\t\tallFunctions,\n\t\t\tallCrons,\n\t\t\tallSubscribers,\n\t\t\tresolved.enableOpenApi,\n\t\t\toptions.skipBundle ?? false,\n\t\t\toptions.stage,\n\t\t);\n\t\t// Keep the master key from the server provider\n\t\tif (providerResult.masterKey) {\n\t\t\tresult = providerResult;\n\t\t}\n\t}\n\treturn result;\n}\n\nasync function buildForProvider(\n\tprovider: LegacyProvider,\n\tcontext: BuildContext,\n\trootOutputDir: string,\n\tendpointGenerator: EndpointGenerator,\n\tfunctionGenerator: FunctionGenerator,\n\tcronGenerator: CronGenerator,\n\tsubscriberGenerator: SubscriberGenerator,\n\tendpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n\tfunctions: GeneratedConstruct<Function<any, any, any, any>>[],\n\tcrons: GeneratedConstruct<Cron<any, any, any, any>>[],\n\tsubscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\tenableOpenApi: boolean,\n\tskipBundle: boolean,\n\tstage?: string,\n): Promise<BuildResult> {\n\tconst outputDir = join(process.cwd(), '.gkm', provider);\n\n\t// Ensure output directory exists\n\tawait mkdir(outputDir, { recursive: true });\n\n\tlogger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n\t// Build all constructs in parallel\n\tconst [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n\t\t[\n\t\t\tendpointGenerator.build(context, endpoints, outputDir, {\n\t\t\t\tprovider,\n\t\t\t\tenableOpenApi,\n\t\t\t}),\n\t\t\tfunctionGenerator.build(context, functions, outputDir, { provider }),\n\t\t\tcronGenerator.build(context, crons, outputDir, { provider }),\n\t\t\tsubscriberGenerator.build(context, subscribers, outputDir, { provider }),\n\t\t],\n\t);\n\n\tlogger.log(\n\t\t`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n\t);\n\n\t// Generate provider-specific manifest\n\tif (provider === 'server') {\n\t\t// For server, collect actual route metadata from endpoint constructs\n\t\tconst routeMetadata: RouteInfo[] = await Promise.all(\n\t\t\tendpoints.map(async ({ construct }) => ({\n\t\t\t\tpath: construct._path,\n\t\t\t\tmethod: construct.method,\n\t\t\t\thandler: '', // Not needed for server manifest\n\t\t\t\tauthorizer: construct.authorizer?.name ?? 'none',\n\t\t\t})),\n\t\t);\n\n\t\tconst appInfo: ServerAppInfo = {\n\t\t\thandler: relative(process.cwd(), join(outputDir, 'app.ts')),\n\t\t\tendpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n\t\t};\n\n\t\tawait generateServerManifest(\n\t\t\trootOutputDir,\n\t\t\tappInfo,\n\t\t\trouteMetadata,\n\t\t\tsubscriberInfos,\n\t\t);\n\n\t\t// Bundle for production if enabled\n\t\tlet masterKey: string | undefined;\n\t\tif (context.production?.bundle && !skipBundle) {\n\t\t\tlogger.log(`\\nš¦ Bundling production server...`);\n\t\t\tconst { bundleServer } = await import('./bundler');\n\n\t\t\t// Collect all constructs for environment variable validation\n\t\t\tconst allConstructs = [\n\t\t\t\t...endpoints.map((e) => e.construct),\n\t\t\t\t...functions.map((f) => f.construct),\n\t\t\t\t...crons.map((c) => c.construct),\n\t\t\t\t...subscribers.map((s) => s.construct),\n\t\t\t];\n\n\t\t\t// Get docker compose services for auto-populating env vars\n\t\t\tconst dockerServices = context.dockerServices;\n\n\t\t\tconst bundleResult = await bundleServer({\n\t\t\t\tentryPoint: join(outputDir, 'server.ts'),\n\t\t\t\toutputDir: join(outputDir, 'dist'),\n\t\t\t\tminify: context.production.minify,\n\t\t\t\tsourcemap: false,\n\t\t\t\texternal: context.production.external,\n\t\t\t\tstage,\n\t\t\t\tconstructs: allConstructs,\n\t\t\t\tdockerServices,\n\t\t\t});\n\t\t\tmasterKey = bundleResult.masterKey;\n\t\t\tlogger.log(`ā
Bundle complete: .gkm/server/dist/server.mjs`);\n\n\t\t\t// Display master key if secrets were injected\n\t\t\tif (masterKey) {\n\t\t\t\tlogger.log(`\\nš Secrets encrypted for deployment`);\n\t\t\t\tlogger.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);\n\t\t\t}\n\t\t}\n\n\t\treturn { masterKey };\n\t} else {\n\t\t// For AWS providers, generate AWS manifest\n\t\tawait generateAwsManifest(\n\t\t\trootOutputDir,\n\t\t\troutes,\n\t\t\tfunctionInfos,\n\t\t\tcronInfos,\n\t\t\tsubscriberInfos,\n\t\t);\n\t}\n\n\treturn {};\n}\n\n/**\n * Result of building a single app in a workspace.\n */\nexport interface AppBuildResult {\n\tappName: string;\n\ttype: 'backend' | 'frontend';\n\tsuccess: boolean;\n\toutputPath?: string;\n\terror?: string;\n}\n\n/**\n * Result of workspace build command.\n */\nexport interface WorkspaceBuildResult extends BuildResult {\n\tapps: AppBuildResult[];\n}\n\n/**\n * Detect available package manager.\n * @internal Exported for testing\n */\nexport function detectPackageManager(): 'pnpm' | 'npm' | 'yarn' {\n\tif (existsSync('pnpm-lock.yaml')) return 'pnpm';\n\tif (existsSync('yarn.lock')) return 'yarn';\n\treturn 'npm';\n}\n\n/**\n * Get the turbo command for running builds.\n * @internal Exported for testing\n */\nexport function getTurboCommand(\n\tpm: 'pnpm' | 'npm' | 'yarn',\n\tfilter?: string,\n): string {\n\tconst filterArg = filter ? ` --filter=${filter}` : '';\n\tswitch (pm) {\n\t\tcase 'pnpm':\n\t\t\treturn `pnpm exec turbo run build${filterArg}`;\n\t\tcase 'yarn':\n\t\t\treturn `yarn turbo run build${filterArg}`;\n\t\tcase 'npm':\n\t\t\treturn `npx turbo run build${filterArg}`;\n\t}\n}\n\n/**\n * Build all apps in a workspace using Turbo for dependency-ordered parallel builds.\n * @internal Exported for testing\n */\nexport async function workspaceBuildCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: BuildOptions,\n): Promise<WorkspaceBuildResult> {\n\tconst results: AppBuildResult[] = [];\n\tconst apps = Object.entries(workspace.apps);\n\tconst backendApps = apps.filter(([, app]) => app.type === 'backend');\n\tconst frontendApps = apps.filter(([, app]) => app.type === 'frontend');\n\n\tlogger.log(`\\nšļø Building workspace: ${workspace.name}`);\n\tlogger.log(\n\t\t` Backend apps: ${backendApps.map(([name]) => name).join(', ') || 'none'}`,\n\t);\n\tlogger.log(\n\t\t` Frontend apps: ${frontendApps.map(([name]) => name).join(', ') || 'none'}`,\n\t);\n\n\tif (options.production) {\n\t\tlogger.log(` š Production mode enabled`);\n\t}\n\n\t// Get build order (topologically sorted by dependencies)\n\tconst buildOrder = getAppBuildOrder(workspace);\n\tlogger.log(` Build order: ${buildOrder.join(' ā ')}`);\n\n\t// Use Turbo for parallel builds with dependency awareness\n\tconst pm = detectPackageManager();\n\tlogger.log(`\\nš¦ Using ${pm} with Turbo for parallel builds...\\n`);\n\n\ttry {\n\t\t// Run turbo build which handles dependency ordering and parallelization\n\t\tconst turboCommand = getTurboCommand(pm);\n\t\tlogger.log(`Running: ${turboCommand}`);\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst child = spawn(turboCommand, {\n\t\t\t\tshell: true,\n\t\t\t\tcwd: workspace.root,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: {\n\t\t\t\t\t...process.env,\n\t\t\t\t\t// Pass production flag to builds\n\t\t\t\t\tNODE_ENV: options.production ? 'production' : 'development',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tchild.on('close', (code) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Turbo build failed with exit code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tchild.on('error', (err) => {\n\t\t\t\treject(err);\n\t\t\t});\n\t\t});\n\n\t\t// Mark all apps as successful\n\t\tfor (const [appName, app] of apps) {\n\t\t\tconst outputPath = getAppOutputPath(workspace, appName, app);\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: true,\n\t\t\t\toutputPath,\n\t\t\t});\n\t\t}\n\n\t\tlogger.log(`\\nā
Workspace build complete!`);\n\n\t\t// Summary\n\t\tlogger.log(`\\nš Build Summary:`);\n\t\tfor (const result of results) {\n\t\t\tconst icon = result.type === 'backend' ? 'āļø' : 'š';\n\t\t\tlogger.log(\n\t\t\t\t` ${icon} ${result.appName}: ${result.outputPath || 'built'}`,\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\tconst errorMessage =\n\t\t\terror instanceof Error ? error.message : 'Build failed';\n\t\tlogger.log(`\\nā Build failed: ${errorMessage}`);\n\n\t\t// Mark all apps as failed\n\t\tfor (const [appName, app] of apps) {\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage,\n\t\t\t});\n\t\t}\n\n\t\tthrow error;\n\t}\n\n\treturn { apps: results };\n}\n\n/**\n * Get the output path for a built app.\n */\nfunction getAppOutputPath(\n\tworkspace: NormalizedWorkspace,\n\t_appName: string,\n\tapp: NormalizedAppConfig,\n): string {\n\tconst appPath = join(workspace.root, app.path);\n\n\tif (app.type === 'frontend') {\n\t\t// Next.js standalone output\n\t\treturn join(appPath, '.next');\n\t} else {\n\t\t// Backend .gkm output\n\t\treturn join(appPath, '.gkm');\n\t}\n}\n","import type {\n\tComposeServiceName,\n\tComposeServicesConfig,\n\tServiceConfig,\n} from '../types';\nimport type {\n\tNormalizedAppConfig,\n\tNormalizedWorkspace,\n} from '../workspace/types.js';\n\n/** Default Docker images for services */\nexport const DEFAULT_SERVICE_IMAGES: Record<ComposeServiceName, string> = {\n\tpostgres: 'postgres',\n\tredis: 'redis',\n\trabbitmq: 'rabbitmq',\n};\n\n/** Default Docker image versions for services */\nexport const DEFAULT_SERVICE_VERSIONS: Record<ComposeServiceName, string> = {\n\tpostgres: '16-alpine',\n\tredis: '7-alpine',\n\trabbitmq: '3-management-alpine',\n};\n\nexport interface ComposeOptions {\n\timageName: string;\n\tregistry: string;\n\tport: number;\n\thealthCheckPath: string;\n\t/** Services config - object format or legacy array format */\n\tservices: ComposeServicesConfig | ComposeServiceName[];\n}\n\n/** Get the default full image reference for a service */\nfunction getDefaultImage(serviceName: ComposeServiceName): string {\n\treturn `${DEFAULT_SERVICE_IMAGES[serviceName]}:${DEFAULT_SERVICE_VERSIONS[serviceName]}`;\n}\n\n/** Normalize services config to a consistent format - returns Map of service name to full image reference */\nfunction normalizeServices(\n\tservices: ComposeServicesConfig | ComposeServiceName[],\n): Map<ComposeServiceName, string> {\n\tconst result = new Map<ComposeServiceName, string>();\n\n\tif (Array.isArray(services)) {\n\t\t// Legacy array format - use default images\n\t\tfor (const name of services) {\n\t\t\tresult.set(name, getDefaultImage(name));\n\t\t}\n\t} else {\n\t\t// Object format\n\t\tfor (const [name, config] of Object.entries(services)) {\n\t\t\tconst serviceName = name as ComposeServiceName;\n\t\t\tif (config === true) {\n\t\t\t\t// boolean true - use default image\n\t\t\t\tresult.set(serviceName, getDefaultImage(serviceName));\n\t\t\t} else if (config && typeof config === 'object') {\n\t\t\t\tconst serviceConfig = config as ServiceConfig;\n\t\t\t\tif (serviceConfig.image) {\n\t\t\t\t\t// Full image reference provided\n\t\t\t\t\tresult.set(serviceName, serviceConfig.image);\n\t\t\t\t} else {\n\t\t\t\t\t// Version only - use default image name with custom version\n\t\t\t\t\tconst version =\n\t\t\t\t\t\tserviceConfig.version ?? DEFAULT_SERVICE_VERSIONS[serviceName];\n\t\t\t\t\tresult.set(\n\t\t\t\t\t\tserviceName,\n\t\t\t\t\t\t`${DEFAULT_SERVICE_IMAGES[serviceName]}:${version}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// false or undefined - skip\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Generate docker-compose.yml for production deployment\n */\nexport function generateDockerCompose(options: ComposeOptions): string {\n\tconst { imageName, registry, port, healthCheckPath, services } = options;\n\n\t// Normalize services to Map<name, version>\n\tconst serviceMap = normalizeServices(services);\n\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\tlet yaml = `version: '3.8'\n\nservices:\n api:\n build:\n context: ../..\n dockerfile: .gkm/docker/Dockerfile\n image: ${imageRef}\\${IMAGE_NAME:-${imageName}}:\\${TAG:-latest}\n container_name: ${imageName}\n restart: unless-stopped\n ports:\n - \"\\${PORT:-${port}}:${port}\"\n environment:\n - NODE_ENV=production\n`;\n\n\t// Add environment variables based on services\n\tif (serviceMap.has('postgres')) {\n\t\tyaml += ` - DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/app}\n`;\n\t}\n\n\tif (serviceMap.has('redis')) {\n\t\tyaml += ` - REDIS_URL=\\${REDIS_URL:-redis://redis:6379}\n`;\n\t}\n\n\tif (serviceMap.has('rabbitmq')) {\n\t\tyaml += ` - RABBITMQ_URL=\\${RABBITMQ_URL:-amqp://rabbitmq:5672}\n`;\n\t}\n\n\tyaml += ` healthcheck:\n test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${port}${healthCheckPath}\"]\n interval: 30s\n timeout: 3s\n retries: 3\n`;\n\n\t// Add depends_on if there are services\n\tif (serviceMap.size > 0) {\n\t\tyaml += ` depends_on:\n`;\n\t\tfor (const serviceName of serviceMap.keys()) {\n\t\t\tyaml += ` ${serviceName}:\n condition: service_healthy\n`;\n\t\t}\n\t}\n\n\tyaml += ` networks:\n - app-network\n`;\n\n\t// Add service definitions with images\n\tconst postgresImage = serviceMap.get('postgres');\n\tif (postgresImage) {\n\t\tyaml += `\n postgres:\n image: ${postgresImage}\n container_name: postgres\n restart: unless-stopped\n environment:\n POSTGRES_USER: \\${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: \\${POSTGRES_PASSWORD:-postgres}\n POSTGRES_DB: \\${POSTGRES_DB:-app}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\tconst redisImage = serviceMap.get('redis');\n\tif (redisImage) {\n\t\tyaml += `\n redis:\n image: ${redisImage}\n container_name: redis\n restart: unless-stopped\n volumes:\n - redis_data:/data\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\tconst rabbitmqImage = serviceMap.get('rabbitmq');\n\tif (rabbitmqImage) {\n\t\tyaml += `\n rabbitmq:\n image: ${rabbitmqImage}\n container_name: rabbitmq\n restart: unless-stopped\n environment:\n RABBITMQ_DEFAULT_USER: \\${RABBITMQ_USER:-guest}\n RABBITMQ_DEFAULT_PASS: \\${RABBITMQ_PASSWORD:-guest}\n ports:\n - \"15672:15672\" # Management UI\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n healthcheck:\n test: [\"CMD\", \"rabbitmq-diagnostics\", \"-q\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\t// Add volumes\n\tyaml += `\nvolumes:\n`;\n\n\tif (serviceMap.has('postgres')) {\n\t\tyaml += ` postgres_data:\n`;\n\t}\n\n\tif (serviceMap.has('redis')) {\n\t\tyaml += ` redis_data:\n`;\n\t}\n\n\tif (serviceMap.has('rabbitmq')) {\n\t\tyaml += ` rabbitmq_data:\n`;\n\t}\n\n\t// Add networks\n\tyaml += `\nnetworks:\n app-network:\n driver: bridge\n`;\n\n\treturn yaml;\n}\n\n/**\n * Generate a minimal docker-compose.yml for API only\n */\nexport function generateMinimalDockerCompose(\n\toptions: Omit<ComposeOptions, 'services'>,\n): string {\n\tconst { imageName, registry, port, healthCheckPath } = options;\n\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\treturn `version: '3.8'\n\nservices:\n api:\n build:\n context: ../..\n dockerfile: .gkm/docker/Dockerfile\n image: ${imageRef}\\${IMAGE_NAME:-${imageName}}:\\${TAG:-latest}\n container_name: ${imageName}\n restart: unless-stopped\n ports:\n - \"\\${PORT:-${port}}:${port}\"\n environment:\n - NODE_ENV=production\n healthcheck:\n test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${port}${healthCheckPath}\"]\n interval: 30s\n timeout: 3s\n retries: 3\n networks:\n - app-network\n\nnetworks:\n app-network:\n driver: bridge\n`;\n}\n\n/**\n * Options for workspace compose generation.\n */\nexport interface WorkspaceComposeOptions {\n\t/** Container registry URL */\n\tregistry?: string;\n}\n\n/**\n * Generate docker-compose.yml for a workspace with all apps as services.\n * Apps can communicate with each other via service names.\n * @internal Exported for testing\n */\nexport function generateWorkspaceCompose(\n\tworkspace: NormalizedWorkspace,\n\toptions: WorkspaceComposeOptions = {},\n): string {\n\tconst { registry } = options;\n\tconst apps = Object.entries(workspace.apps);\n\tconst services = workspace.services;\n\n\t// Determine which infrastructure services to include\n\tconst hasPostgres = services.db !== undefined && services.db !== false;\n\tconst hasRedis = services.cache !== undefined && services.cache !== false;\n\tconst hasMail = services.mail !== undefined && services.mail !== false;\n\n\t// Get image versions from config\n\tconst postgresImage = getInfraServiceImage('postgres', services.db);\n\tconst redisImage = getInfraServiceImage('redis', services.cache);\n\n\tlet yaml = `# Docker Compose for ${workspace.name} workspace\n# Generated by gkm - do not edit manually\n\nservices:\n`;\n\n\t// Generate service for each app\n\tfor (const [appName, app] of apps) {\n\t\tyaml += generateAppService(appName, app, apps, {\n\t\t\tregistry,\n\t\t\thasPostgres,\n\t\t\thasRedis,\n\t\t});\n\t}\n\n\t// Add infrastructure services\n\tif (hasPostgres) {\n\t\tyaml += `\n postgres:\n image: ${postgresImage}\n container_name: ${workspace.name}-postgres\n restart: unless-stopped\n environment:\n POSTGRES_USER: \\${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: \\${POSTGRES_PASSWORD:-postgres}\n POSTGRES_DB: \\${POSTGRES_DB:-app}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - workspace-network\n`;\n\t}\n\n\tif (hasRedis) {\n\t\tyaml += `\n redis:\n image: ${redisImage}\n container_name: ${workspace.name}-redis\n restart: unless-stopped\n volumes:\n - redis_data:/data\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - workspace-network\n`;\n\t}\n\n\tif (hasMail) {\n\t\tyaml += `\n mailpit:\n image: axllent/mailpit:latest\n container_name: ${workspace.name}-mailpit\n restart: unless-stopped\n ports:\n - \"8025:8025\" # Web UI\n - \"1025:1025\" # SMTP\n networks:\n - workspace-network\n`;\n\t}\n\n\t// Add volumes section\n\tyaml += `\nvolumes:\n`;\n\n\tif (hasPostgres) {\n\t\tyaml += ` postgres_data:\n`;\n\t}\n\n\tif (hasRedis) {\n\t\tyaml += ` redis_data:\n`;\n\t}\n\n\t// Add networks section\n\tyaml += `\nnetworks:\n workspace-network:\n driver: bridge\n`;\n\n\treturn yaml;\n}\n\n/**\n * Get infrastructure service image with version.\n */\nfunction getInfraServiceImage(\n\tserviceName: 'postgres' | 'redis',\n\tconfig: boolean | { version?: string; image?: string } | undefined,\n): string {\n\tconst defaults: Record<'postgres' | 'redis', string> = {\n\t\tpostgres: 'postgres:16-alpine',\n\t\tredis: 'redis:7-alpine',\n\t};\n\n\tif (!config || config === true) {\n\t\treturn defaults[serviceName];\n\t}\n\n\tif (typeof config === 'object') {\n\t\tif (config.image) {\n\t\t\treturn config.image;\n\t\t}\n\t\tif (config.version) {\n\t\t\tconst baseImage = serviceName === 'postgres' ? 'postgres' : 'redis';\n\t\t\treturn `${baseImage}:${config.version}`;\n\t\t}\n\t}\n\n\treturn defaults[serviceName];\n}\n\n/**\n * Generate a service definition for an app.\n */\nfunction generateAppService(\n\tappName: string,\n\tapp: NormalizedAppConfig,\n\tallApps: [string, NormalizedAppConfig][],\n\toptions: {\n\t\tregistry?: string;\n\t\thasPostgres: boolean;\n\t\thasRedis: boolean;\n\t},\n): string {\n\tconst { registry, hasPostgres, hasRedis } = options;\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\t// Health check path - frontends use /, backends use /health\n\tconst healthCheckPath = app.type === 'frontend' ? '/' : '/health';\n\tconst healthCheckCmd =\n\t\tapp.type === 'frontend'\n\t\t\t? `[\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${app.port}/\"]`\n\t\t\t: `[\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${app.port}${healthCheckPath}\"]`;\n\n\tlet yaml = `\n ${appName}:\n build:\n context: .\n dockerfile: .gkm/docker/Dockerfile.${appName}\n image: ${imageRef}\\${${appName.toUpperCase()}_IMAGE:-${appName}}:\\${TAG:-latest}\n container_name: ${appName}\n restart: unless-stopped\n ports:\n - \"\\${${appName.toUpperCase()}_PORT:-${app.port}}:${app.port}\"\n environment:\n - NODE_ENV=production\n - PORT=${app.port}\n`;\n\n\t// Add dependency URLs - apps can reach other apps by service name\n\tfor (const dep of app.dependencies) {\n\t\tconst depApp = allApps.find(([name]) => name === dep)?.[1];\n\t\tif (depApp) {\n\t\t\tyaml += ` - ${dep.toUpperCase()}_URL=http://${dep}:${depApp.port}\n`;\n\t\t}\n\t}\n\n\t// Add infrastructure service URLs for backend apps\n\tif (app.type === 'backend') {\n\t\tif (hasPostgres) {\n\t\t\tyaml += ` - DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/app}\n`;\n\t\t}\n\t\tif (hasRedis) {\n\t\t\tyaml += ` - REDIS_URL=\\${REDIS_URL:-redis://redis:6379}\n`;\n\t\t}\n\t}\n\n\tyaml += ` healthcheck:\n test: ${healthCheckCmd}\n interval: 30s\n timeout: 3s\n retries: 3\n`;\n\n\t// Add depends_on for dependencies and infrastructure\n\tconst dependencies: string[] = [...app.dependencies];\n\tif (app.type === 'backend') {\n\t\tif (hasPostgres) dependencies.push('postgres');\n\t\tif (hasRedis) dependencies.push('redis');\n\t}\n\n\tif (dependencies.length > 0) {\n\t\tyaml += ` depends_on:\n`;\n\t\tfor (const dep of dependencies) {\n\t\t\tyaml += ` ${dep}:\n condition: service_healthy\n`;\n\t\t}\n\t}\n\n\tyaml += ` networks:\n - workspace-network\n`;\n\n\treturn yaml;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\nimport type { DockerConfig, GkmConfig } from '../types';\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\nexport interface DockerTemplateOptions {\n\timageName: string;\n\tbaseImage: string;\n\tport: number;\n\thealthCheckPath: string;\n\t/** Whether the build is pre-built (slim Dockerfile) or needs building */\n\tprebuilt: boolean;\n\t/** Detected package manager */\n\tpackageManager: PackageManager;\n}\n\nexport interface FrontendDockerfileOptions {\n\timageName: string;\n\tbaseImage: string;\n\tport: number;\n\t/** App path relative to workspace root */\n\tappPath: string;\n\t/** Package name for turbo prune */\n\tturboPackage: string;\n\t/** Detected package manager */\n\tpackageManager: PackageManager;\n}\n\nexport interface MultiStageDockerfileOptions extends DockerTemplateOptions {\n\t/** Enable turbo prune for monorepo optimization */\n\tturbo?: boolean;\n\t/** Package name for turbo prune (defaults to current directory name) */\n\tturboPackage?: string;\n}\n\nconst LOCKFILES: [string, PackageManager][] = [\n\t['pnpm-lock.yaml', 'pnpm'],\n\t['bun.lockb', 'bun'],\n\t['yarn.lock', 'yarn'],\n\t['package-lock.json', 'npm'],\n];\n\n/**\n * Detect package manager from lockfiles\n * Walks up the directory tree to find lockfile (for monorepos)\n */\nexport function detectPackageManager(\n\tcwd: string = process.cwd(),\n): PackageManager {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\t// Walk up the directory tree\n\twhile (dir !== root) {\n\t\tfor (const [lockfile, pm] of LOCKFILES) {\n\t\t\tif (existsSync(join(dir, lockfile))) {\n\t\t\t\treturn pm;\n\t\t\t}\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\t// Check root directory\n\tfor (const [lockfile, pm] of LOCKFILES) {\n\t\tif (existsSync(join(root, lockfile))) {\n\t\t\treturn pm;\n\t\t}\n\t}\n\n\treturn 'pnpm'; // default\n}\n\n/**\n * Find the lockfile path by walking up the directory tree\n * Returns the full path to the lockfile, or null if not found\n */\nexport function findLockfilePath(cwd: string = process.cwd()): string | null {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\t// Walk up the directory tree\n\twhile (dir !== root) {\n\t\tfor (const [lockfile] of LOCKFILES) {\n\t\t\tconst lockfilePath = join(dir, lockfile);\n\t\t\tif (existsSync(lockfilePath)) {\n\t\t\t\treturn lockfilePath;\n\t\t\t}\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\t// Check root directory\n\tfor (const [lockfile] of LOCKFILES) {\n\t\tconst lockfilePath = join(root, lockfile);\n\t\tif (existsSync(lockfilePath)) {\n\t\t\treturn lockfilePath;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get the lockfile name for a package manager\n */\nexport function getLockfileName(pm: PackageManager): string {\n\tconst lockfileMap: Record<PackageManager, string> = {\n\t\tpnpm: 'pnpm-lock.yaml',\n\t\tnpm: 'package-lock.json',\n\t\tyarn: 'yarn.lock',\n\t\tbun: 'bun.lockb',\n\t};\n\treturn lockfileMap[pm];\n}\n\n/**\n * Check if we're in a monorepo (lockfile is in a parent directory)\n */\nexport function isMonorepo(cwd: string = process.cwd()): boolean {\n\tconst lockfilePath = findLockfilePath(cwd);\n\tif (!lockfilePath) {\n\t\treturn false;\n\t}\n\n\t// Check if lockfile is in a parent directory (not in cwd)\n\tconst lockfileDir = dirname(lockfilePath);\n\treturn lockfileDir !== cwd;\n}\n\n/**\n * Check if turbo.json exists (walks up directory tree)\n */\nexport function hasTurboConfig(cwd: string = process.cwd()): boolean {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\twhile (dir !== root) {\n\t\tif (existsSync(join(dir, 'turbo.json'))) {\n\t\t\treturn true;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\treturn existsSync(join(root, 'turbo.json'));\n}\n\n/**\n * Get install command for turbo builds (without frozen lockfile)\n * Turbo prune creates a subset that may not perfectly match the lockfile\n */\nfunction getTurboInstallCmd(pm: PackageManager): string {\n\tconst commands: Record<PackageManager, string> = {\n\t\tpnpm: 'pnpm install',\n\t\tnpm: 'npm install',\n\t\tyarn: 'yarn install',\n\t\tbun: 'bun install',\n\t};\n\treturn commands[pm];\n}\n\n/**\n * Get package manager specific commands and paths\n */\nfunction getPmConfig(pm: PackageManager) {\n\tconst configs = {\n\t\tpnpm: {\n\t\t\tinstall: 'corepack enable && corepack prepare pnpm@latest --activate',\n\t\t\tlockfile: 'pnpm-lock.yaml',\n\t\t\tfetch: 'pnpm fetch',\n\t\t\tinstallCmd: 'pnpm install --frozen-lockfile --offline',\n\t\t\tcacheTarget: '/root/.local/share/pnpm/store',\n\t\t\tcacheId: 'pnpm',\n\t\t\trun: 'pnpm',\n\t\t\texec: 'pnpm exec',\n\t\t\tdlx: 'pnpm dlx',\n\t\t\taddGlobal: 'pnpm add -g',\n\t\t},\n\t\tnpm: {\n\t\t\tinstall: '', // npm comes with node\n\t\t\tlockfile: 'package-lock.json',\n\t\t\tfetch: '', // npm doesn't have fetch\n\t\t\tinstallCmd: 'npm ci',\n\t\t\tcacheTarget: '/root/.npm',\n\t\t\tcacheId: 'npm',\n\t\t\trun: 'npm run',\n\t\t\texec: 'npx',\n\t\t\tdlx: 'npx',\n\t\t\taddGlobal: 'npm install -g',\n\t\t},\n\t\tyarn: {\n\t\t\tinstall: 'corepack enable && corepack prepare yarn@stable --activate',\n\t\t\tlockfile: 'yarn.lock',\n\t\t\tfetch: '', // yarn doesn't have fetch\n\t\t\tinstallCmd: 'yarn install --frozen-lockfile',\n\t\t\tcacheTarget: '/root/.yarn/cache',\n\t\t\tcacheId: 'yarn',\n\t\t\trun: 'yarn',\n\t\t\texec: 'yarn exec',\n\t\t\tdlx: 'yarn dlx',\n\t\t\taddGlobal: 'yarn global add',\n\t\t},\n\t\tbun: {\n\t\t\tinstall: 'npm install -g bun',\n\t\t\tlockfile: 'bun.lockb',\n\t\t\tfetch: '', // bun doesn't have fetch\n\t\t\tinstallCmd: 'bun install --frozen-lockfile',\n\t\t\tcacheTarget: '/root/.bun/install/cache',\n\t\t\tcacheId: 'bun',\n\t\t\trun: 'bun run',\n\t\t\texec: 'bunx',\n\t\t\tdlx: 'bunx',\n\t\t\taddGlobal: 'bun add -g',\n\t\t},\n\t};\n\treturn configs[pm];\n}\n\n/**\n * Generate a multi-stage Dockerfile for building from source\n * Optimized for build speed with:\n * - BuildKit cache mounts for package manager store\n * - pnpm fetch for better layer caching (when using pnpm)\n * - Optional turbo prune for monorepos\n */\nexport function generateMultiStageDockerfile(\n\toptions: MultiStageDockerfileOptions,\n): string {\n\tconst {\n\t\tbaseImage,\n\t\tport,\n\t\thealthCheckPath,\n\t\tturbo,\n\t\tturboPackage,\n\t\tpackageManager,\n\t} = options;\n\n\tif (turbo) {\n\t\treturn generateTurboDockerfile({\n\t\t\t...options,\n\t\t\tturboPackage: turboPackage ?? 'api',\n\t\t});\n\t}\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install\n\t\t? `\\n# Install ${packageManager}\\nRUN ${pm.install}\\n`\n\t\t: '';\n\tconst hasFetch = packageManager === 'pnpm';\n\n\t// pnpm has fetch which allows better caching\n\tconst depsStage = hasFetch\n\t\t? `# Copy lockfile first for better caching\nCOPY ${pm.lockfile} ./\n\n# Fetch dependencies (downloads to virtual store, cached separately)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.fetch}\n\n# Copy package.json after fetch\nCOPY package.json ./\n\n# Install from cache (fast - no network needed)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.installCmd}`\n\t\t: `# Copy package files\nCOPY package.json ${pm.lockfile} ./\n\n# Install dependencies with cache\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.installCmd}`;\n\n\treturn `# syntax=docker/dockerfile:1\n# Stage 1: Dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n${installPm}\n${depsStage}\n\n# Stage 2: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy source (deps already installed)\nCOPY . .\n\n# Debug: Show node_modules/.bin contents and build production server\nRUN echo \"=== node_modules/.bin contents ===\" && \\\n ls -la node_modules/.bin/ 2>/dev/null || echo \"node_modules/.bin not found\" && \\\n echo \"=== Checking for gkm ===\" && \\\n which gkm 2>/dev/null || echo \"gkm not in PATH\" && \\\n ls -la node_modules/.bin/gkm 2>/dev/null || echo \"gkm binary not found in node_modules/.bin\" && \\\n echo \"=== Running build ===\" && \\\n ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 3: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\n# Install tini for proper signal handling as PID 1\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy bundled server\nCOPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./\n\n# Environment\nENV NODE_ENV=production\nENV PORT=${port}\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\n# Switch to non-root user\nUSER hono\n\nEXPOSE ${port}\n\n# Use tini as entrypoint to handle PID 1 responsibilities\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate a Dockerfile optimized for Turbo monorepos\n * Uses turbo prune to create minimal Docker context\n */\nfunction generateTurboDockerfile(options: MultiStageDockerfileOptions): string {\n\tconst { baseImage, port, healthCheckPath, turboPackage, packageManager } =\n\t\toptions;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\n\t// For turbo builds, we can't use --frozen-lockfile because turbo prune\n\t// creates a subset that may not perfectly match. Use relaxed install.\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\n\t// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies (no frozen-lockfile since turbo prune creates a subset)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Debug: Show node_modules/.bin contents and build production server\nRUN echo \"=== node_modules/.bin contents ===\" && \\\n ls -la node_modules/.bin/ 2>/dev/null || echo \"node_modules/.bin not found\" && \\\n echo \"=== Checking for gkm ===\" && \\\n which gkm 2>/dev/null || echo \"gkm not in PATH\" && \\\n ls -la node_modules/.bin/gkm 2>/dev/null || echo \"gkm binary not found in node_modules/.bin\" && \\\n echo \"=== Running build ===\" && \\\n ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\nRUN apk add --no-cache tini\n\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\nCOPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./\n\nENV NODE_ENV=production\nENV PORT=${port}\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\nUSER hono\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate a slim Dockerfile for pre-built bundles\n */\nexport function generateSlimDockerfile(options: DockerTemplateOptions): string {\n\tconst { baseImage, port, healthCheckPath } = options;\n\n\treturn `# Slim Dockerfile for pre-built production bundle\nFROM ${baseImage}\n\nWORKDIR /app\n\n# Install tini for proper signal handling as PID 1\n# Handles SIGTERM propagation and zombie process reaping\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy pre-built bundle\nCOPY .gkm/server/dist/server.mjs ./\n\n# Environment\nENV NODE_ENV=production\nENV PORT=${port}\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\n# Switch to non-root user\nUSER hono\n\nEXPOSE ${port}\n\n# Use tini as entrypoint to handle PID 1 responsibilities\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate .dockerignore file\n */\nexport function generateDockerignore(): string {\n\treturn `# Dependencies\nnode_modules\n.pnpm-store\n\n# Build output (except what we need)\n.gkm/aws*\n.gkm/server/*.ts\n!.gkm/server/dist\n\n# IDE and editor\n.idea\n.vscode\n*.swp\n*.swo\n\n# Git\n.git\n.gitignore\n\n# Logs\n*.log\nnpm-debug.log*\npnpm-debug.log*\n\n# Test files\n**/*.test.ts\n**/*.spec.ts\n**/__tests__\ncoverage\n\n# Documentation\ndocs\n*.md\n!README.md\n\n# Environment files (handle secrets separately)\n.env\n.env.*\n!.env.example\n\n# Docker files (don't copy recursively)\nDockerfile*\ndocker-compose*\n.dockerignore\n`;\n}\n\n/**\n * Generate docker-entrypoint.sh for custom startup logic\n */\nexport function generateDockerEntrypoint(): string {\n\treturn `#!/bin/sh\nset -e\n\n# Run any custom startup scripts here\n# Example: wait for database\n# until nc -z $DB_HOST $DB_PORT; do\n# echo \"Waiting for database...\"\n# sleep 1\n# done\n\n# Execute the main command\nexec \"$@\"\n`;\n}\n\n/**\n * Resolve Docker configuration from GkmConfig with defaults\n */\nexport function resolveDockerConfig(\n\tconfig: GkmConfig,\n): Required<Omit<DockerConfig, 'compose'>> & Pick<DockerConfig, 'compose'> {\n\tconst docker = config.docker ?? {};\n\n\t// Try to get image name from package.json name\n\tlet defaultImageName = 'api';\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\tconst pkg = require(`${process.cwd()}/package.json`);\n\t\tif (pkg.name) {\n\t\t\t// Remove scope and use just the package name\n\t\t\tdefaultImageName = pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore if package.json doesn't exist\n\t}\n\n\treturn {\n\t\tregistry: docker.registry ?? '',\n\t\timageName: docker.imageName ?? defaultImageName,\n\t\tbaseImage: docker.baseImage ?? 'node:22-alpine',\n\t\tport: docker.port ?? 3000,\n\t\tcompose: docker.compose,\n\t};\n}\n\n/**\n * Generate a Dockerfile for Next.js frontend apps using standalone output.\n * Uses turbo prune for monorepo optimization.\n * @internal Exported for testing\n */\nexport function generateNextjsDockerfile(\n\toptions: FrontendDockerfileOptions,\n): string {\n\tconst { baseImage, port, appPath, turboPackage, packageManager } = options;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\n\t// For turbo builds, we can't use --frozen-lockfile because turbo prune\n\t// creates a subset that may not perfectly match. Use relaxed install.\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\n\t// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Next.js standalone Dockerfile with turbo prune optimization\n\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Set Next.js to produce standalone output\nENV NEXT_TELEMETRY_DISABLED=1\n\n# Build the application\nRUN ${turboCmd} run build --filter=${turboPackage}\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\n# Install tini for proper signal handling\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 nextjs\n\n# Set environment\nENV NODE_ENV=production\nENV NEXT_TELEMETRY_DISABLED=1\nENV PORT=${port}\nENV HOSTNAME=\"0.0.0.0\"\n\n# Copy static files and standalone output\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/static ./${appPath}/.next/static\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/public ./${appPath}/public\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}/ || exit 1\n\nUSER nextjs\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"${appPath}/server.js\"]\n`;\n}\n\n/**\n * Generate a Dockerfile for backend apps in a workspace.\n * Uses turbo prune for monorepo optimization.\n * @internal Exported for testing\n */\nexport function generateBackendDockerfile(\n\toptions: FrontendDockerfileOptions & { healthCheckPath?: string },\n): string {\n\tconst {\n\t\tbaseImage,\n\t\tport,\n\t\tappPath,\n\t\tturboPackage,\n\t\tpackageManager,\n\t\thealthCheckPath = '/health',\n\t} = options;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Backend Dockerfile with turbo prune optimization\n\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Build production server using gkm\nRUN cd ${appPath} && ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\nRUN apk add --no-cache tini\n\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy bundled server\nCOPY --from=builder --chown=hono:nodejs /app/${appPath}/.gkm/server/dist/server.mjs ./\n\nENV NODE_ENV=production\nENV PORT=${port}\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\nUSER hono\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n","import { execSync } from 'node:child_process';\nimport { copyFileSync, existsSync, unlinkSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { loadConfig, loadWorkspaceConfig } from '../config';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport {\n\tgenerateDockerCompose,\n\tgenerateMinimalDockerCompose,\n\tgenerateWorkspaceCompose,\n} from './compose';\nimport {\n\tdetectPackageManager,\n\tfindLockfilePath,\n\tgenerateBackendDockerfile,\n\tgenerateDockerEntrypoint,\n\tgenerateDockerignore,\n\tgenerateMultiStageDockerfile,\n\tgenerateNextjsDockerfile,\n\tgenerateSlimDockerfile,\n\thasTurboConfig,\n\tisMonorepo,\n\tresolveDockerConfig,\n} from './templates';\n\nexport {\n\tdetectPackageManager,\n\tfindLockfilePath,\n\thasTurboConfig,\n\tisMonorepo,\n} from './templates';\n\nconst logger = console;\n\nexport interface DockerOptions {\n\t/** Build Docker image after generating files */\n\tbuild?: boolean;\n\t/** Push image to registry after building */\n\tpush?: boolean;\n\t/** Image tag (default: 'latest') */\n\ttag?: string;\n\t/** Container registry URL */\n\tregistry?: string;\n\t/** Use slim Dockerfile (requires pre-built bundle from `gkm build --production`) */\n\tslim?: boolean;\n\t/** Enable turbo prune for monorepo optimization */\n\tturbo?: boolean;\n\t/** Package name for turbo prune (defaults to package.json name) */\n\tturboPackage?: string;\n}\n\nexport interface DockerGeneratedFiles {\n\tdockerfile: string;\n\tdockerCompose: string;\n\tdockerignore: string;\n\tentrypoint: string;\n}\n\n/**\n * Docker command implementation\n * Generates Dockerfile, docker-compose.yml, and related files\n *\n * Default: Multi-stage Dockerfile that builds from source inside Docker\n * --slim: Slim Dockerfile that copies pre-built bundle (requires prior build)\n */\nexport async function dockerCommand(\n\toptions: DockerOptions,\n): Promise<DockerGeneratedFiles | WorkspaceDockerResult> {\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace docker mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceDockerCommand(loadedConfig.workspace, options);\n\t}\n\n\t// Single-app mode - use existing logic\n\tconst config = await loadConfig();\n\tconst dockerConfig = resolveDockerConfig(config);\n\n\t// Get health check path from production config\n\tconst serverConfig =\n\t\ttypeof config.providers?.server === 'object'\n\t\t\t? config.providers.server\n\t\t\t: undefined;\n\tconst healthCheckPath = serverConfig?.production?.healthCheck ?? '/health';\n\n\t// Determine Dockerfile type\n\t// Default: Multi-stage (builds inside Docker for reproducibility)\n\t// --slim: Requires pre-built bundle\n\tconst useSlim = options.slim === true;\n\n\tif (useSlim) {\n\t\t// Verify pre-built bundle exists for slim mode\n\t\tconst distDir = join(process.cwd(), '.gkm', 'server', 'dist');\n\t\tconst hasBuild = existsSync(join(distDir, 'server.mjs'));\n\n\t\tif (!hasBuild) {\n\t\t\tthrow new Error(\n\t\t\t\t'Slim Dockerfile requires a pre-built bundle. Run `gkm build --provider server --production` first, or omit --slim to use multi-stage build.',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Generate Docker files\n\tconst dockerDir = join(process.cwd(), '.gkm', 'docker');\n\tawait mkdir(dockerDir, { recursive: true });\n\n\t// Detect package manager from lockfiles\n\tconst packageManager = detectPackageManager();\n\tconst inMonorepo = isMonorepo();\n\tconst hasTurbo = hasTurboConfig();\n\n\t// Auto-enable turbo for monorepos with turbo.json\n\tlet useTurbo = options.turbo ?? false;\n\tif (inMonorepo && !useSlim) {\n\t\tif (hasTurbo) {\n\t\t\tuseTurbo = true;\n\t\t\tlogger.log(' Detected monorepo with turbo.json - using turbo prune');\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t'Monorepo detected but turbo.json not found.\\n\\n' +\n\t\t\t\t\t'Docker builds in monorepos require Turborepo for proper dependency isolation.\\n\\n' +\n\t\t\t\t\t'To fix this:\\n' +\n\t\t\t\t\t' 1. Install turbo: pnpm add -Dw turbo\\n' +\n\t\t\t\t\t' 2. Create turbo.json in your monorepo root\\n' +\n\t\t\t\t\t' 3. Run this command again\\n\\n' +\n\t\t\t\t\t'See: https://turbo.build/repo/docs/guides/tools/docker',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Get the actual package name from package.json for turbo prune\n\tlet turboPackage = options.turboPackage ?? dockerConfig.imageName;\n\tif (useTurbo && !options.turboPackage) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\tconst pkg = require(`${process.cwd()}/package.json`);\n\t\t\tif (pkg.name) {\n\t\t\t\tturboPackage = pkg.name;\n\t\t\t\tlogger.log(` Turbo package: ${turboPackage}`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall back to imageName\n\t\t}\n\t}\n\n\tconst templateOptions = {\n\t\timageName: dockerConfig.imageName,\n\t\tbaseImage: dockerConfig.baseImage,\n\t\tport: dockerConfig.port,\n\t\thealthCheckPath,\n\t\tprebuilt: useSlim,\n\t\tturbo: useTurbo,\n\t\tturboPackage,\n\t\tpackageManager,\n\t};\n\n\t// Generate Dockerfile\n\tconst dockerfile = useSlim\n\t\t? generateSlimDockerfile(templateOptions)\n\t\t: generateMultiStageDockerfile(templateOptions);\n\n\tconst dockerMode = useSlim ? 'slim' : useTurbo ? 'turbo' : 'multi-stage';\n\n\tconst dockerfilePath = join(dockerDir, 'Dockerfile');\n\tawait writeFile(dockerfilePath, dockerfile);\n\tlogger.log(\n\t\t`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`,\n\t);\n\n\t// Generate docker-compose.yml\n\tconst composeOptions = {\n\t\timageName: dockerConfig.imageName,\n\t\tregistry: options.registry ?? dockerConfig.registry,\n\t\tport: dockerConfig.port,\n\t\thealthCheckPath,\n\t\tservices: dockerConfig.compose?.services ?? {},\n\t};\n\n\t// Check if there are any services configured\n\tconst hasServices = Array.isArray(composeOptions.services)\n\t\t? composeOptions.services.length > 0\n\t\t: Object.keys(composeOptions.services).length > 0;\n\n\tconst dockerCompose = hasServices\n\t\t? generateDockerCompose(composeOptions)\n\t\t: generateMinimalDockerCompose(composeOptions);\n\n\tconst composePath = join(dockerDir, 'docker-compose.yml');\n\tawait writeFile(composePath, dockerCompose);\n\tlogger.log('Generated: .gkm/docker/docker-compose.yml');\n\n\t// Generate .dockerignore in project root (Docker looks for it there)\n\tconst dockerignore = generateDockerignore();\n\tconst dockerignorePath = join(process.cwd(), '.dockerignore');\n\tawait writeFile(dockerignorePath, dockerignore);\n\tlogger.log('Generated: .dockerignore (project root)');\n\n\t// Generate docker-entrypoint.sh\n\tconst entrypoint = generateDockerEntrypoint();\n\tconst entrypointPath = join(dockerDir, 'docker-entrypoint.sh');\n\tawait writeFile(entrypointPath, entrypoint);\n\tlogger.log('Generated: .gkm/docker/docker-entrypoint.sh');\n\n\tconst result: DockerGeneratedFiles = {\n\t\tdockerfile: dockerfilePath,\n\t\tdockerCompose: composePath,\n\t\tdockerignore: dockerignorePath,\n\t\tentrypoint: entrypointPath,\n\t};\n\n\t// Build Docker image if requested\n\tif (options.build) {\n\t\tawait buildDockerImage(dockerConfig.imageName, options);\n\t}\n\n\t// Push Docker image if requested\n\tif (options.push) {\n\t\tawait pushDockerImage(dockerConfig.imageName, options);\n\t}\n\n\treturn result;\n}\n\n/**\n * Ensure lockfile exists in the build context\n * For monorepos, copies from workspace root if needed\n * Returns cleanup function if file was copied\n */\nfunction ensureLockfile(cwd: string): (() => void) | null {\n\tconst lockfilePath = findLockfilePath(cwd);\n\n\tif (!lockfilePath) {\n\t\tlogger.warn(\n\t\t\t'\\nā ļø No lockfile found. Docker build may fail or use stale dependencies.',\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst lockfileName = basename(lockfilePath);\n\tconst localLockfile = join(cwd, lockfileName);\n\n\t// If lockfile exists locally (same directory), nothing to do\n\tif (lockfilePath === localLockfile) {\n\t\treturn null;\n\t}\n\n\tlogger.log(` Copying ${lockfileName} from monorepo root...`);\n\tcopyFileSync(lockfilePath, localLockfile);\n\n\t// Return cleanup function\n\treturn () => {\n\t\ttry {\n\t\t\tunlinkSync(localLockfile);\n\t\t} catch {\n\t\t\t// Ignore cleanup errors\n\t\t}\n\t};\n}\n\n/**\n * Build Docker image\n * Uses BuildKit for cache mount support\n */\nasync function buildDockerImage(\n\timageName: string,\n\toptions: DockerOptions,\n): Promise<void> {\n\tconst tag = options.tag ?? 'latest';\n\tconst registry = options.registry;\n\n\tconst fullImageName = registry\n\t\t? `${registry}/${imageName}:${tag}`\n\t\t: `${imageName}:${tag}`;\n\n\tlogger.log(`\\nš³ Building Docker image: ${fullImageName}`);\n\n\tconst cwd = process.cwd();\n\n\t// Ensure lockfile exists (copy from monorepo root if needed)\n\tconst cleanup = ensureLockfile(cwd);\n\n\ttry {\n\t\t// Use BuildKit for cache mount support (required for --mount=type=cache)\n\t\texecSync(\n\t\t\t`DOCKER_BUILDKIT=1 docker build -f .gkm/docker/Dockerfile -t ${fullImageName} .`,\n\t\t\t{\n\t\t\t\tcwd,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, DOCKER_BUILDKIT: '1' },\n\t\t\t},\n\t\t);\n\t\tlogger.log(`ā
Docker image built: ${fullImageName}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to build Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t} finally {\n\t\t// Clean up copied lockfile\n\t\tcleanup?.();\n\t}\n}\n\n/**\n * Push Docker image to registry\n */\nasync function pushDockerImage(\n\timageName: string,\n\toptions: DockerOptions,\n): Promise<void> {\n\tconst tag = options.tag ?? 'latest';\n\tconst registry = options.registry;\n\n\tif (!registry) {\n\t\tthrow new Error(\n\t\t\t'Registry is required to push Docker image. Use --registry or configure docker.registry in gkm.config.ts',\n\t\t);\n\t}\n\n\tconst fullImageName = `${registry}/${imageName}:${tag}`;\n\n\tlogger.log(`\\nš Pushing Docker image: ${fullImageName}`);\n\n\ttry {\n\t\texecSync(`docker push ${fullImageName}`, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t});\n\t\tlogger.log(`ā
Docker image pushed: ${fullImageName}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to push Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Result of generating Docker files for a single app in a workspace.\n */\nexport interface AppDockerResult {\n\tappName: string;\n\ttype: 'backend' | 'frontend';\n\tdockerfile: string;\n\timageName: string;\n}\n\n/**\n * Result of workspace docker command.\n */\nexport interface WorkspaceDockerResult {\n\tapps: AppDockerResult[];\n\tdockerCompose: string;\n\tdockerignore: string;\n}\n\n/**\n * Get the package name from package.json in an app directory.\n */\nfunction getAppPackageName(appPath: string): string | undefined {\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\tconst pkg = require(`${appPath}/package.json`);\n\t\treturn pkg.name;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Generate Dockerfiles for all apps in a workspace.\n * @internal Exported for testing\n */\nexport async function workspaceDockerCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DockerOptions,\n): Promise<WorkspaceDockerResult> {\n\tconst results: AppDockerResult[] = [];\n\tconst apps = Object.entries(workspace.apps);\n\n\tlogger.log(`\\nš³ Generating Dockerfiles for workspace: ${workspace.name}`);\n\n\t// Create docker output directory\n\tconst dockerDir = join(workspace.root, '.gkm', 'docker');\n\tawait mkdir(dockerDir, { recursive: true });\n\n\t// Detect package manager\n\tconst packageManager = detectPackageManager(workspace.root);\n\tlogger.log(` Package manager: ${packageManager}`);\n\n\t// Generate Dockerfile for each app\n\tfor (const [appName, app] of apps) {\n\t\tconst appPath = app.path;\n\t\tconst fullAppPath = join(workspace.root, appPath);\n\n\t\t// Get package name for turbo prune (use package.json name or app name)\n\t\tconst turboPackage = getAppPackageName(fullAppPath) ?? appName;\n\n\t\t// Determine image name\n\t\tconst imageName = appName;\n\n\t\tlogger.log(`\\n š Generating Dockerfile for ${appName} (${app.type})`);\n\n\t\tlet dockerfile: string;\n\n\t\tif (app.type === 'frontend') {\n\t\t\t// Generate Next.js Dockerfile\n\t\t\tdockerfile = generateNextjsDockerfile({\n\t\t\t\timageName,\n\t\t\t\tbaseImage: 'node:22-alpine',\n\t\t\t\tport: app.port,\n\t\t\t\tappPath,\n\t\t\t\tturboPackage,\n\t\t\t\tpackageManager,\n\t\t\t});\n\t\t} else {\n\t\t\t// Generate backend Dockerfile\n\t\t\tdockerfile = generateBackendDockerfile({\n\t\t\t\timageName,\n\t\t\t\tbaseImage: 'node:22-alpine',\n\t\t\t\tport: app.port,\n\t\t\t\tappPath,\n\t\t\t\tturboPackage,\n\t\t\t\tpackageManager,\n\t\t\t\thealthCheckPath: '/health',\n\t\t\t});\n\t\t}\n\n\t\t// Write Dockerfile with app-specific name\n\t\tconst dockerfilePath = join(dockerDir, `Dockerfile.${appName}`);\n\t\tawait writeFile(dockerfilePath, dockerfile);\n\t\tlogger.log(` Generated: .gkm/docker/Dockerfile.${appName}`);\n\n\t\tresults.push({\n\t\t\tappName,\n\t\t\ttype: app.type,\n\t\t\tdockerfile: dockerfilePath,\n\t\t\timageName,\n\t\t});\n\t}\n\n\t// Generate shared .dockerignore\n\tconst dockerignore = generateDockerignore();\n\tconst dockerignorePath = join(workspace.root, '.dockerignore');\n\tawait writeFile(dockerignorePath, dockerignore);\n\tlogger.log(`\\n Generated: .dockerignore (workspace root)`);\n\n\t// Generate docker-compose.yml for workspace\n\tconst dockerCompose = generateWorkspaceCompose(workspace, {\n\t\tregistry: options.registry,\n\t});\n\tconst composePath = join(dockerDir, 'docker-compose.yml');\n\tawait writeFile(composePath, dockerCompose);\n\tlogger.log(` Generated: .gkm/docker/docker-compose.yml`);\n\n\t// Summary\n\tlogger.log(\n\t\t`\\nā
Generated ${results.length} Dockerfile(s) + docker-compose.yml`,\n\t);\n\tlogger.log('\\nš Build commands:');\n\tfor (const result of results) {\n\t\tconst icon = result.type === 'backend' ? 'āļø' : 'š';\n\t\tlogger.log(\n\t\t\t` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`,\n\t\t);\n\t}\n\tlogger.log('\\nš Run all services:');\n\tlogger.log(' docker compose -f .gkm/docker/docker-compose.yml up --build');\n\n\treturn {\n\t\tapps: results,\n\t\tdockerCompose: composePath,\n\t\tdockerignore: dockerignorePath,\n\t};\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport type { GkmConfig } from '../config';\nimport { dockerCommand, findLockfilePath, isMonorepo } from '../docker';\nimport type { DeployResult, DockerDeployConfig } from './types';\n\n/**\n * Get app name from package.json in the current working directory\n * Used for Dokploy app/project naming\n */\nexport function getAppNameFromCwd(): string | undefined {\n\tconst packageJsonPath = join(process.cwd(), 'package.json');\n\n\tif (!existsSync(packageJsonPath)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\t\tif (pkg.name) {\n\t\t\t// Strip org scope if present (e.g., @myorg/app -> app)\n\t\t\treturn pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore parse errors\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Get app name from package.json adjacent to the lockfile (project root)\n * Used for Docker image naming\n */\nexport function getAppNameFromPackageJson(): string | undefined {\n\tconst cwd = process.cwd();\n\n\t// Find the lockfile to determine the project root\n\tconst lockfilePath = findLockfilePath(cwd);\n\tif (!lockfilePath) {\n\t\treturn undefined;\n\t}\n\n\t// Use the package.json adjacent to the lockfile\n\tconst projectRoot = dirname(lockfilePath);\n\tconst packageJsonPath = join(projectRoot, 'package.json');\n\n\tif (!existsSync(packageJsonPath)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\t\tif (pkg.name) {\n\t\t\t// Strip org scope if present (e.g., @myorg/app -> app)\n\t\t\treturn pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore parse errors\n\t}\n\n\treturn undefined;\n}\n\nconst logger = console;\n\nexport interface DockerDeployOptions {\n\t/** Deployment stage */\n\tstage: string;\n\t/** Image tag */\n\ttag: string;\n\t/** Skip pushing to registry */\n\tskipPush?: boolean;\n\t/** Master key from build */\n\tmasterKey?: string;\n\t/** Docker config from gkm.config */\n\tconfig: DockerDeployConfig;\n}\n\n/**\n * Get the full image reference\n */\nexport function getImageRef(\n\tregistry: string | undefined,\n\timageName: string,\n\ttag: string,\n): string {\n\tif (registry) {\n\t\treturn `${registry}/${imageName}:${tag}`;\n\t}\n\treturn `${imageName}:${tag}`;\n}\n\n/**\n * Build Docker image\n */\nasync function buildImage(imageRef: string): Promise<void> {\n\tlogger.log(`\\nšØ Building Docker image: ${imageRef}`);\n\n\tconst cwd = process.cwd();\n\tconst inMonorepo = isMonorepo(cwd);\n\n\t// Generate appropriate Dockerfile\n\tif (inMonorepo) {\n\t\tlogger.log(' Generating Dockerfile for monorepo (turbo prune)...');\n\t} else {\n\t\tlogger.log(' Generating Dockerfile...');\n\t}\n\tawait dockerCommand({});\n\n\t// Determine build context and Dockerfile path\n\tlet buildCwd = cwd;\n\tlet dockerfilePath = '.gkm/docker/Dockerfile';\n\n\tif (inMonorepo) {\n\t\t// For monorepos, build from root so turbo prune can access all packages\n\t\tconst lockfilePath = findLockfilePath(cwd);\n\t\tif (lockfilePath) {\n\t\t\tconst monorepoRoot = dirname(lockfilePath);\n\t\t\tconst appRelPath = relative(monorepoRoot, cwd);\n\t\t\tdockerfilePath = join(appRelPath, '.gkm/docker/Dockerfile');\n\t\t\tbuildCwd = monorepoRoot;\n\t\t\tlogger.log(` Building from monorepo root: ${monorepoRoot}`);\n\t\t}\n\t}\n\n\ttry {\n\t\t// Build for linux/amd64 to ensure compatibility with most cloud servers\n\t\texecSync(\n\t\t\t`DOCKER_BUILDKIT=1 docker build --platform linux/amd64 -f ${dockerfilePath} -t ${imageRef} .`,\n\t\t\t{\n\t\t\t\tcwd: buildCwd,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, DOCKER_BUILDKIT: '1' },\n\t\t\t},\n\t\t);\n\t\tlogger.log(`ā
Image built: ${imageRef}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to build Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Push Docker image to registry\n */\nasync function pushImage(imageRef: string): Promise<void> {\n\tlogger.log(`\\nāļø Pushing image: ${imageRef}`);\n\n\ttry {\n\t\texecSync(`docker push ${imageRef}`, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t});\n\t\tlogger.log(`ā
Image pushed: ${imageRef}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to push Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Deploy using Docker (build and optionally push image)\n */\nexport async function deployDocker(\n\toptions: DockerDeployOptions,\n): Promise<DeployResult> {\n\tconst { stage, tag, skipPush, masterKey, config } = options;\n\n\t// imageName should always be set by resolveDockerConfig\n\tconst imageName = config.imageName!;\n\tconst imageRef = getImageRef(config.registry, imageName, tag);\n\n\t// Build image\n\tawait buildImage(imageRef);\n\n\t// Push to registry if not skipped\n\tif (!skipPush) {\n\t\tif (!config.registry) {\n\t\t\tlogger.warn(\n\t\t\t\t'\\nā ļø No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts',\n\t\t\t);\n\t\t} else {\n\t\t\tawait pushImage(imageRef);\n\t\t}\n\t}\n\n\t// Output deployment info\n\tlogger.log('\\nā
Docker deployment ready!');\n\tlogger.log(`\\nš Deployment details:`);\n\tlogger.log(` Image: ${imageRef}`);\n\tlogger.log(` Stage: ${stage}`);\n\n\tif (masterKey) {\n\t\tlogger.log(`\\nš Deploy with this environment variable:`);\n\t\tlogger.log(` GKM_MASTER_KEY=${masterKey}`);\n\t\tlogger.log('\\n Example docker run:');\n\t\tlogger.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);\n\t}\n\n\treturn {\n\t\timageRef,\n\t\tmasterKey,\n\t};\n}\n\n/**\n * Resolve Docker deploy config from gkm config\n * - imageName: from config, or cwd package.json, or 'app' (for Docker image)\n * - projectName: from root package.json, or 'app' (for Dokploy project)\n * - appName: from cwd package.json, or projectName (for Dokploy app within project)\n */\nexport function resolveDockerConfig(config: GkmConfig): DockerDeployConfig {\n\t// projectName comes from root package.json (monorepo name)\n\tconst projectName = getAppNameFromPackageJson() ?? 'app';\n\n\t// appName comes from cwd package.json (the app being deployed)\n\tconst appName = getAppNameFromCwd() ?? projectName;\n\n\t// imageName defaults to appName (cwd package.json)\n\tconst imageName = config.docker?.imageName ?? appName;\n\n\treturn {\n\t\tregistry: config.docker?.registry,\n\t\timageName,\n\t\tprojectName,\n\t\tappName,\n\t};\n}\n","import { getDokployRegistryId, getDokployToken } from '../auth';\nimport { DokployApi } from './dokploy-api';\nimport type { DeployResult, DokployDeployConfig } from './types';\n\nconst logger = console;\n\nexport interface DokployDeployOptions {\n\t/** Deployment stage */\n\tstage: string;\n\t/** Image tag */\n\ttag: string;\n\t/** Image reference */\n\timageRef: string;\n\t/** Master key from build */\n\tmasterKey?: string;\n\t/** Dokploy config from gkm.config */\n\tconfig: DokployDeployConfig;\n}\n\n/**\n * Get the Dokploy API token from stored credentials or environment\n */\nasync function getApiToken(): Promise<string> {\n\tconst token = await getDokployToken();\n\tif (!token) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found.\\n' +\n\t\t\t\t'Run \"gkm login --service dokploy\" to authenticate, or set DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n\treturn token;\n}\n\n/**\n * Create a Dokploy API client\n */\nasync function createApi(endpoint: string): Promise<DokployApi> {\n\tconst token = await getApiToken();\n\treturn new DokployApi({ baseUrl: endpoint, token });\n}\n\n/**\n * Deploy to Dokploy\n */\nexport async function deployDokploy(\n\toptions: DokployDeployOptions,\n): Promise<DeployResult> {\n\tconst { stage, imageRef, masterKey, config } = options;\n\n\tlogger.log(`\\nšÆ Deploying to Dokploy...`);\n\tlogger.log(` Endpoint: ${config.endpoint}`);\n\tlogger.log(` Application: ${config.applicationId}`);\n\n\tconst api = await createApi(config.endpoint);\n\n\t// Configure Docker provider with the image\n\tlogger.log(` Configuring Docker image: ${imageRef}`);\n\n\t// Determine registry credentials\n\tconst registryOptions: {\n\t\tregistryId?: string;\n\t\tusername?: string;\n\t\tpassword?: string;\n\t\tregistryUrl?: string;\n\t} = {};\n\n\tif (config.registryId) {\n\t\t// Use registry ID from config\n\t\tregistryOptions.registryId = config.registryId;\n\t\tlogger.log(` Using Dokploy registry: ${config.registryId}`);\n\t} else {\n\t\t// Try stored registry ID from credentials\n\t\tconst storedRegistryId = await getDokployRegistryId();\n\t\tif (storedRegistryId) {\n\t\t\tregistryOptions.registryId = storedRegistryId;\n\t\t\tlogger.log(` Using stored Dokploy registry: ${storedRegistryId}`);\n\t\t} else if (config.registryCredentials) {\n\t\t\t// Use explicit credentials from config\n\t\t\tregistryOptions.username = config.registryCredentials.username;\n\t\t\tregistryOptions.password = config.registryCredentials.password;\n\t\t\tregistryOptions.registryUrl = config.registryCredentials.registryUrl;\n\t\t\tlogger.log(\n\t\t\t\t` Using registry credentials for: ${config.registryCredentials.registryUrl}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Try environment variables\n\t\t\tconst username = process.env.DOCKER_REGISTRY_USERNAME;\n\t\t\tconst password = process.env.DOCKER_REGISTRY_PASSWORD;\n\t\t\tconst registryUrl = process.env.DOCKER_REGISTRY_URL || config.registry;\n\n\t\t\tif (username && password && registryUrl) {\n\t\t\t\tregistryOptions.username = username;\n\t\t\t\tregistryOptions.password = password;\n\t\t\t\tregistryOptions.registryUrl = registryUrl;\n\t\t\t\tlogger.log(` Using registry credentials from environment`);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait api.saveDockerProvider(config.applicationId, imageRef, registryOptions);\n\tlogger.log(' ā Docker provider configured');\n\n\t// Prepare environment variables\n\tconst envVars: Record<string, string> = {};\n\n\tif (masterKey) {\n\t\tenvVars.GKM_MASTER_KEY = masterKey;\n\t}\n\n\t// Update environment if we have variables to set\n\tif (Object.keys(envVars).length > 0) {\n\t\tlogger.log(' Updating environment variables...');\n\n\t\t// Convert env vars to the format Dokploy expects (KEY=VALUE per line)\n\t\tconst envString = Object.entries(envVars)\n\t\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t\t.join('\\n');\n\n\t\tawait api.saveApplicationEnv(config.applicationId, envString);\n\t\tlogger.log(' ā Environment variables updated');\n\t}\n\n\t// Trigger deployment\n\tlogger.log(' Triggering deployment...');\n\tawait api.deployApplication(config.applicationId);\n\tlogger.log(' ā Deployment triggered');\n\n\tlogger.log('\\nā
Dokploy deployment initiated!');\n\tlogger.log(`\\nš Deployment details:`);\n\tlogger.log(` Image: ${imageRef}`);\n\tlogger.log(` Stage: ${stage}`);\n\tlogger.log(` Application ID: ${config.applicationId}`);\n\n\tif (masterKey) {\n\t\tlogger.log(`\\nš GKM_MASTER_KEY has been set in Dokploy environment`);\n\t}\n\n\t// Construct the probable deployment URL\n\tconst deploymentUrl = `${config.endpoint}/project/${config.projectId}`;\n\tlogger.log(`\\nš View deployment: ${deploymentUrl}`);\n\n\treturn {\n\t\timageRef,\n\t\tmasterKey,\n\t\turl: deploymentUrl,\n\t};\n}\n\n/**\n * Validate Dokploy configuration\n */\nexport function validateDokployConfig(\n\tconfig: Partial<DokployDeployConfig> | undefined,\n): config is DokployDeployConfig {\n\tif (!config) {\n\t\treturn false;\n\t}\n\n\tconst required = ['endpoint', 'projectId', 'applicationId'] as const;\n\tconst missing = required.filter((key) => !config[key]);\n\n\tif (missing.length > 0) {\n\t\tthrow new Error(\n\t\t\t`Missing Dokploy configuration: ${missing.join(', ')}\\n` +\n\t\t\t\t'Configure in gkm.config.ts:\\n' +\n\t\t\t\t' providers: {\\n' +\n\t\t\t\t' dokploy: {\\n' +\n\t\t\t\t\" endpoint: 'https://dokploy.example.com',\\n\" +\n\t\t\t\t\" projectId: 'proj_xxx',\\n\" +\n\t\t\t\t\" applicationId: 'app_xxx',\\n\" +\n\t\t\t\t' },\\n' +\n\t\t\t\t' }',\n\t\t);\n\t}\n\n\treturn true;\n}\n","import { existsSync } from 'node:fs';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n\tgetDokployCredentials,\n\tgetDokployRegistryId,\n\tgetDokployToken,\n\tstoreDokployRegistryId,\n} from '../auth';\nimport { DokployApi } from './dokploy-api';\nimport type { DokployDeployConfig } from './types';\n\nconst logger = console;\n\nexport interface DeployInitOptions {\n\t/** Dokploy endpoint URL (optional if logged in) */\n\tendpoint?: string;\n\t/** Project name (creates new or uses existing) */\n\tprojectName: string;\n\t/** Application name */\n\tappName: string;\n\t/** Use existing project ID instead of creating/finding */\n\tprojectId?: string;\n\t/** Registry ID in Dokploy (optional, uses stored if available) */\n\tregistryId?: string;\n}\n\nexport interface RegistrySetupOptions {\n\t/** Dokploy endpoint URL (optional if logged in) */\n\tendpoint?: string;\n\t/** Registry name (for display in Dokploy) */\n\tregistryName: string;\n\t/** Registry URL (e.g., ghcr.io, docker.io) */\n\tregistryUrl: string;\n\t/** Registry username */\n\tusername: string;\n\t/** Registry password or token */\n\tpassword: string;\n\t/** Image prefix (optional, e.g., org-name) */\n\timagePrefix?: string;\n}\n\n/**\n * Get the Dokploy API token from stored credentials or environment\n */\nasync function getApiToken(): Promise<string> {\n\tconst token = await getDokployToken();\n\tif (!token) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found.\\n' +\n\t\t\t\t'Run \"gkm login --service dokploy\" to authenticate, or set DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n\treturn token;\n}\n\n/**\n * Get Dokploy endpoint from options or stored credentials\n */\nasync function getEndpoint(providedEndpoint?: string): Promise<string> {\n\tif (providedEndpoint) {\n\t\treturn providedEndpoint;\n\t}\n\n\tconst stored = await getDokployCredentials();\n\tif (stored) {\n\t\treturn stored.endpoint;\n\t}\n\n\tthrow new Error(\n\t\t'Dokploy endpoint not specified.\\n' +\n\t\t\t'Either run \"gkm login --service dokploy\" first, or provide --endpoint.',\n\t);\n}\n\n/**\n * Create a Dokploy API client\n */\nasync function createApi(endpoint: string): Promise<DokployApi> {\n\tconst token = await getApiToken();\n\treturn new DokployApi({ baseUrl: endpoint, token });\n}\n\n/**\n * Update gkm.config.ts with Dokploy configuration\n */\nexport async function updateConfig(\n\tconfig: DokployDeployConfig,\n\tcwd: string = process.cwd(),\n): Promise<void> {\n\tconst configPath = join(cwd, 'gkm.config.ts');\n\n\tif (!existsSync(configPath)) {\n\t\tlogger.warn(\n\t\t\t'\\n gkm.config.ts not found. Add this configuration manually:\\n',\n\t\t);\n\t\tlogger.log(` providers: {`);\n\t\tlogger.log(` dokploy: {`);\n\t\tlogger.log(` endpoint: '${config.endpoint}',`);\n\t\tlogger.log(` projectId: '${config.projectId}',`);\n\t\tlogger.log(` applicationId: '${config.applicationId}',`);\n\t\tlogger.log(` },`);\n\t\tlogger.log(` },`);\n\t\treturn;\n\t}\n\n\tconst content = await readFile(configPath, 'utf-8');\n\n\t// Check if providers.dokploy already exists\n\tif (content.includes('dokploy:') && content.includes('applicationId:')) {\n\t\tlogger.log('\\n Dokploy config already exists in gkm.config.ts');\n\t\tlogger.log(' Updating with new values...');\n\t}\n\n\t// Build the dokploy config string\n\tconst registryLine = config.registryId\n\t\t? `\\n\\t\\t\\tregistryId: '${config.registryId}',`\n\t\t: '';\n\tconst dokployConfigStr = `dokploy: {\n\t\t\tendpoint: '${config.endpoint}',\n\t\t\tprojectId: '${config.projectId}',\n\t\t\tapplicationId: '${config.applicationId}',${registryLine}\n\t\t}`;\n\n\t// Try to add or update the dokploy config\n\tlet newContent: string;\n\n\tif (content.includes('providers:')) {\n\t\t// Add dokploy to existing providers\n\t\tif (content.includes('dokploy:')) {\n\t\t\t// Update existing dokploy config (handle multi-line with registryId)\n\t\t\tnewContent = content.replace(/dokploy:\\s*\\{[^}]*\\}/s, dokployConfigStr);\n\t\t} else {\n\t\t\t// Add dokploy to providers\n\t\t\tnewContent = content.replace(\n\t\t\t\t/providers:\\s*\\{/,\n\t\t\t\t`providers: {\\n\\t\\t${dokployConfigStr},`,\n\t\t\t);\n\t\t}\n\t} else {\n\t\t// Add providers section before the closing of defineConfig\n\t\tnewContent = content.replace(\n\t\t\t/}\\s*\\)\\s*;?\\s*$/,\n\t\t\t`\n\tproviders: {\n\t\t${dokployConfigStr},\n\t},\n});`,\n\t\t);\n\t}\n\n\tawait writeFile(configPath, newContent);\n\tlogger.log('\\n ā Updated gkm.config.ts with Dokploy configuration');\n}\n\n/**\n * Initialize Dokploy deployment configuration\n */\nexport async function deployInitCommand(\n\toptions: DeployInitOptions,\n): Promise<DokployDeployConfig> {\n\tconst {\n\t\tprojectName,\n\t\tappName,\n\t\tprojectId: existingProjectId,\n\t\tregistryId,\n\t} = options;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš Initializing Dokploy deployment...`);\n\tlogger.log(` Endpoint: ${endpoint}`);\n\n\t// Step 1: Find or create project\n\tlet projectId: string;\n\n\tif (existingProjectId) {\n\t\tprojectId = existingProjectId;\n\t\tlogger.log(`\\nš Using existing project: ${projectId}`);\n\t} else {\n\t\tlogger.log(`\\nš Looking for project: ${projectName}`);\n\n\t\tconst projects = await api.listProjects();\n\t\tconst existingProject = projects.find(\n\t\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t\t);\n\n\t\tif (existingProject) {\n\t\t\tprojectId = existingProject.projectId;\n\t\t\tlogger.log(` Found existing project: ${projectId}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating new project...`);\n\t\t\tconst result = await api.createProject(projectName);\n\t\t\tprojectId = result.project.projectId;\n\t\t\tlogger.log(` ā Created project: ${projectId}`);\n\t\t}\n\t}\n\n\t// Step 2: Get project to find environment\n\tconst project = await api.getProject(projectId);\n\tlet environmentId: string;\n\n\tconst firstEnv = project.environments?.[0];\n\tif (firstEnv) {\n\t\tenvironmentId = firstEnv.environmentId;\n\t} else {\n\t\t// Create a default environment\n\t\tlogger.log(` Creating production environment...`);\n\t\tconst env = await api.createEnvironment(projectId, 'production');\n\t\tenvironmentId = env.environmentId;\n\t}\n\n\t// Step 3: Create application\n\tlogger.log(`\\nš¦ Creating application: ${appName}`);\n\tconst application = await api.createApplication(\n\t\tappName,\n\t\tprojectId,\n\t\tenvironmentId,\n\t);\n\tlogger.log(` ā Created application: ${application.applicationId}`);\n\n\t// Step 4: Configure registry if provided\n\tif (registryId) {\n\t\tlogger.log(`\\nš§ Configuring registry: ${registryId}`);\n\t\tawait api.updateApplication(application.applicationId, { registryId });\n\t\tlogger.log(` ā Registry configured`);\n\t} else {\n\t\t// List available registries\n\t\ttry {\n\t\t\tconst registries = await api.listRegistries();\n\t\t\tif (registries.length > 0) {\n\t\t\t\tlogger.log(`\\nš Available registries:`);\n\t\t\t\tfor (const reg of registries) {\n\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlogger.log(`\\n To use a registry, run with --registry-id <id>`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore registry listing errors\n\t\t}\n\t}\n\n\t// Step 5: Build config\n\tconst config: DokployDeployConfig = {\n\t\tendpoint,\n\t\tprojectId,\n\t\tapplicationId: application.applicationId,\n\t};\n\n\t// Step 6: Update gkm.config.ts\n\tawait updateConfig(config);\n\n\tlogger.log(`\\nā
Dokploy deployment initialized!`);\n\tlogger.log(`\\nš Configuration:`);\n\tlogger.log(` Project ID: ${projectId}`);\n\tlogger.log(` Application ID: ${application.applicationId}`);\n\tlogger.log(`\\nš View in Dokploy: ${endpoint}/project/${projectId}`);\n\tlogger.log(`\\nš Next steps:`);\n\tlogger.log(` 1. Initialize secrets: gkm secrets:init --stage production`);\n\tlogger.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);\n\n\treturn config;\n}\n\n/**\n * List available Dokploy resources\n */\nexport async function deployListCommand(options: {\n\tendpoint?: string;\n\tresource: 'projects' | 'registries';\n}): Promise<void> {\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tconst { resource } = options;\n\n\tif (resource === 'projects') {\n\t\tlogger.log(`\\nš Projects in ${endpoint}:`);\n\t\tconst projects = await api.listProjects();\n\n\t\tif (projects.length === 0) {\n\t\t\tlogger.log(' No projects found');\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const project of projects) {\n\t\t\tlogger.log(`\\n ${project.name} (${project.projectId})`);\n\t\t\tif (project.description) {\n\t\t\t\tlogger.log(` ${project.description}`);\n\t\t\t}\n\t\t}\n\t} else if (resource === 'registries') {\n\t\tlogger.log(`\\nš³ Registries in ${endpoint}:`);\n\t\tconst registries = await api.listRegistries();\n\n\t\tif (registries.length === 0) {\n\t\t\tlogger.log(' No registries configured');\n\t\t\tlogger.log(' Run \"gkm registry:setup\" to configure a registry');\n\t\t\treturn;\n\t\t}\n\n\t\tconst storedRegistryId = await getDokployRegistryId();\n\n\t\tfor (const registry of registries) {\n\t\t\tconst isDefault = registry.registryId === storedRegistryId;\n\t\t\tconst marker = isDefault ? ' (default)' : '';\n\t\t\tlogger.log(\n\t\t\t\t`\\n ${registry.registryName}${marker} (${registry.registryId})`,\n\t\t\t);\n\t\t\tlogger.log(` URL: ${registry.registryUrl}`);\n\t\t\tlogger.log(` Username: ${registry.username}`);\n\t\t\tif (registry.imagePrefix) {\n\t\t\t\tlogger.log(` Prefix: ${registry.imagePrefix}`);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Setup a Docker registry in Dokploy\n */\nexport async function registrySetupCommand(\n\toptions: RegistrySetupOptions,\n): Promise<string> {\n\tconst { registryName, registryUrl, username, password, imagePrefix } =\n\t\toptions;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš³ Setting up Docker registry in Dokploy...`);\n\tlogger.log(` Endpoint: ${endpoint}`);\n\n\t// Check if registry with same URL already exists\n\tconst existingRegistries = await api.listRegistries();\n\tconst existing = existingRegistries.find(\n\t\t(r) =>\n\t\t\tr.registryUrl === registryUrl ||\n\t\t\tr.registryName.toLowerCase() === registryName.toLowerCase(),\n\t);\n\n\tlet registryId: string;\n\n\tif (existing) {\n\t\tlogger.log(`\\nš Found existing registry: ${existing.registryName}`);\n\t\tlogger.log(` Updating credentials...`);\n\n\t\tawait api.updateRegistry(existing.registryId, {\n\t\t\tregistryName,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\timagePrefix,\n\t\t});\n\n\t\tregistryId = existing.registryId;\n\t\tlogger.log(` ā Registry updated: ${registryId}`);\n\t} else {\n\t\tlogger.log(`\\nš¦ Creating registry: ${registryName}`);\n\n\t\tconst registry = await api.createRegistry(\n\t\t\tregistryName,\n\t\t\tregistryUrl,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\t{ imagePrefix },\n\t\t);\n\n\t\tregistryId = registry.registryId;\n\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t}\n\n\t// Store registry ID in credentials\n\tawait storeDokployRegistryId(registryId);\n\tlogger.log(`\\nš¾ Saved registry ID to ~/.gkm/credentials.json`);\n\n\tlogger.log(`\\nā
Registry setup complete!`);\n\tlogger.log(`\\nš Registry Details:`);\n\tlogger.log(` ID: ${registryId}`);\n\tlogger.log(` Name: ${registryName}`);\n\tlogger.log(` URL: ${registryUrl}`);\n\tlogger.log(` Username: ${username}`);\n\tif (imagePrefix) {\n\t\tlogger.log(` Prefix: ${imagePrefix}`);\n\t}\n\n\tlogger.log(\n\t\t`\\nš The registry ID is now stored and will be used automatically`,\n\t);\n\tlogger.log(` when deploying with \"gkm deploy --provider dokploy\"`);\n\n\treturn registryId;\n}\n\n/**\n * Use an existing registry (set as default)\n */\nexport async function registryUseCommand(options: {\n\tendpoint?: string;\n\tregistryId: string;\n}): Promise<void> {\n\tconst { registryId } = options;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš§ Setting default registry...`);\n\n\t// Verify the registry exists\n\ttry {\n\t\tconst registry = await api.getRegistry(registryId);\n\t\tlogger.log(` Found registry: ${registry.registryName}`);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Registry not found: ${registryId}\\n` +\n\t\t\t\t'Run \"gkm deploy:list registries\" to see available registries.',\n\t\t);\n\t}\n\n\t// Store registry ID in credentials\n\tawait storeDokployRegistryId(registryId);\n\n\tlogger.log(`\\nā
Default registry set: ${registryId}`);\n\tlogger.log(` This registry will be used for future deployments.`);\n}\n","import { stdin as input, stdout as output } from 'node:process';\nimport * as readline from 'node:readline/promises';\nimport {\n\tgetDokployCredentials,\n\tgetDokployRegistryId,\n\tstoreDokployCredentials,\n\tvalidateDokployToken,\n} from '../auth';\nimport { storeDokployRegistryId } from '../auth/credentials';\nimport { buildCommand } from '../build/index';\nimport { type GkmConfig, loadConfig, loadWorkspaceConfig } from '../config';\nimport {\n\tgetAppBuildOrder,\n\tgetDeployTargetError,\n\tisDeployTargetSupported,\n} from '../workspace/index.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport { deployDocker, resolveDockerConfig } from './docker';\nimport { deployDokploy } from './dokploy';\nimport { DokployApi, type DokployApplication } from './dokploy-api';\nimport { updateConfig } from './init';\nimport type {\n\tAppDeployResult,\n\tDeployOptions,\n\tDeployProvider,\n\tDeployResult,\n\tDockerDeployConfig,\n\tDokployDeployConfig,\n\tWorkspaceDeployResult,\n} from './types';\n\nconst logger = console;\n\n/**\n * Prompt for input\n */\nasync function prompt(message: string, hidden = false): Promise<string> {\n\tif (!process.stdin.isTTY) {\n\t\tthrow new Error('Interactive input required. Please configure manually.');\n\t}\n\n\tif (hidden) {\n\t\tprocess.stdout.write(message);\n\t\treturn new Promise((resolve) => {\n\t\t\tlet value = '';\n\t\t\tconst onData = (char: Buffer) => {\n\t\t\t\tconst c = char.toString();\n\t\t\t\tif (c === '\\n' || c === '\\r') {\n\t\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\t\tprocess.stdin.pause();\n\t\t\t\t\tprocess.stdin.removeListener('data', onData);\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tresolve(value);\n\t\t\t\t} else if (c === '\\u0003') {\n\t\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\t\tprocess.stdin.pause();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t} else if (c === '\\u007F' || c === '\\b') {\n\t\t\t\t\tif (value.length > 0) value = value.slice(0, -1);\n\t\t\t\t} else {\n\t\t\t\t\tvalue += c;\n\t\t\t\t}\n\t\t\t};\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t\tprocess.stdin.resume();\n\t\t\tprocess.stdin.on('data', onData);\n\t\t});\n\t}\n\n\tconst rl = readline.createInterface({ input, output });\n\ttry {\n\t\treturn await rl.question(message);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\n/**\n * Docker compose services that can be provisioned\n */\ninterface DockerComposeServices {\n\tpostgres?: boolean;\n\tredis?: boolean;\n\trabbitmq?: boolean;\n}\n\n/**\n * Service URLs including both connection URLs and individual parameters\n */\ninterface ServiceUrls {\n\tDATABASE_URL?: string;\n\tDATABASE_HOST?: string;\n\tDATABASE_PORT?: string;\n\tDATABASE_NAME?: string;\n\tDATABASE_USER?: string;\n\tDATABASE_PASSWORD?: string;\n\tREDIS_URL?: string;\n\tREDIS_HOST?: string;\n\tREDIS_PORT?: string;\n\tREDIS_PASSWORD?: string;\n}\n\n/**\n * Result of Dokploy setup including provisioned service URLs\n */\ninterface DokploySetupResult {\n\tconfig: DokployDeployConfig;\n\tserviceUrls?: ServiceUrls;\n}\n\n/**\n * Provision docker compose services in Dokploy\n * @internal Exported for testing\n */\nexport async function provisionServices(\n\tapi: DokployApi,\n\tprojectId: string,\n\tenvironmentId: string | undefined,\n\tappName: string,\n\tservices?: DockerComposeServices,\n\texistingUrls?: Pick<ServiceUrls, 'DATABASE_URL' | 'REDIS_URL'>,\n): Promise<ServiceUrls | undefined> {\n\tlogger.log(\n\t\t`\\nš provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`,\n\t);\n\tif (!services || !environmentId) {\n\t\tlogger.log(' Skipping: no services or no environmentId');\n\t\treturn undefined;\n\t}\n\n\tconst serviceUrls: ServiceUrls = {};\n\n\tif (services.postgres) {\n\t\t// Skip if DATABASE_URL already exists in secrets\n\t\tif (existingUrls?.DATABASE_URL) {\n\t\t\tlogger.log('\\nš PostgreSQL: Already configured (skipping)');\n\t\t} else {\n\t\t\tlogger.log('\\nš Provisioning PostgreSQL...');\n\t\t\tconst postgresName = `${appName}-db`;\n\n\t\t\ttry {\n\t\t\t\t// Generate a random password for the database\n\t\t\t\tconst { randomBytes } = await import('node:crypto');\n\t\t\t\tconst databasePassword = randomBytes(16).toString('hex');\n\n\t\t\t\tconst postgres = await api.createPostgres(\n\t\t\t\t\tpostgresName,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t\t{ databasePassword },\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created PostgreSQL: ${postgres.postgresId}`);\n\n\t\t\t\t// Deploy the database\n\t\t\t\tawait api.deployPostgres(postgres.postgresId);\n\t\t\t\tlogger.log(' ā PostgreSQL deployed');\n\n\t\t\t\t// Store individual connection parameters\n\t\t\t\tserviceUrls.DATABASE_HOST = postgres.appName;\n\t\t\t\tserviceUrls.DATABASE_PORT = '5432';\n\t\t\t\tserviceUrls.DATABASE_NAME = postgres.databaseName;\n\t\t\t\tserviceUrls.DATABASE_USER = postgres.databaseUser;\n\t\t\t\tserviceUrls.DATABASE_PASSWORD = postgres.databasePassword;\n\n\t\t\t\t// Construct connection URL using internal docker network hostname\n\t\t\t\tserviceUrls.DATABASE_URL = `postgresql://${postgres.databaseUser}:${postgres.databasePassword}@${postgres.appName}:5432/${postgres.databaseName}`;\n\t\t\t\tlogger.log(` ā Database credentials configured`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` ā¹ PostgreSQL already exists`);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(` ā Failed to provision PostgreSQL: ${message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (services.redis) {\n\t\t// Skip if REDIS_URL already exists in secrets\n\t\tif (existingUrls?.REDIS_URL) {\n\t\t\tlogger.log('\\nš“ Redis: Already configured (skipping)');\n\t\t} else {\n\t\t\tlogger.log('\\nš“ Provisioning Redis...');\n\t\t\tconst redisName = `${appName}-cache`;\n\n\t\t\ttry {\n\t\t\t\t// Generate a random password for Redis\n\t\t\t\tconst { randomBytes } = await import('node:crypto');\n\t\t\t\tconst databasePassword = randomBytes(16).toString('hex');\n\n\t\t\t\tconst redis = await api.createRedis(\n\t\t\t\t\tredisName,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t\t{\n\t\t\t\t\t\tdatabasePassword,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created Redis: ${redis.redisId}`);\n\n\t\t\t\t// Deploy the redis instance\n\t\t\t\tawait api.deployRedis(redis.redisId);\n\t\t\t\tlogger.log(' ā Redis deployed');\n\n\t\t\t\t// Store individual connection parameters\n\t\t\t\tserviceUrls.REDIS_HOST = redis.appName;\n\t\t\t\tserviceUrls.REDIS_PORT = '6379';\n\t\t\t\tif (redis.databasePassword) {\n\t\t\t\t\tserviceUrls.REDIS_PASSWORD = redis.databasePassword;\n\t\t\t\t}\n\n\t\t\t\t// Construct connection URL\n\t\t\t\tconst password = redis.databasePassword\n\t\t\t\t\t? `:${redis.databasePassword}@`\n\t\t\t\t\t: '';\n\t\t\t\tserviceUrls.REDIS_URL = `redis://${password}${redis.appName}:6379`;\n\t\t\t\tlogger.log(` ā Redis credentials configured`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` ā¹ Redis already exists`);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(` ā Failed to provision Redis: ${message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Object.keys(serviceUrls).length > 0 ? serviceUrls : undefined;\n}\n\n/**\n * Ensure Dokploy is fully configured, recovering/creating resources as needed\n */\nasync function ensureDokploySetup(\n\tconfig: GkmConfig,\n\tdockerConfig: DockerDeployConfig,\n\tstage: string,\n\tservices?: DockerComposeServices,\n): Promise<DokploySetupResult> {\n\tlogger.log('\\nš§ Checking Dokploy setup...');\n\n\t// Read existing secrets to check if services are already configured\n\tconst { readStageSecrets } = await import('../secrets/storage');\n\tconst existingSecrets = await readStageSecrets(stage);\n\tconst existingUrls: { DATABASE_URL?: string; REDIS_URL?: string } = {\n\t\tDATABASE_URL: existingSecrets?.urls?.DATABASE_URL,\n\t\tREDIS_URL: existingSecrets?.urls?.REDIS_URL,\n\t};\n\n\t// Step 1: Ensure we have Dokploy credentials\n\tlet creds = await getDokployCredentials();\n\n\tif (!creds) {\n\t\tlogger.log(\"\\nš Dokploy credentials not found. Let's set them up.\");\n\t\tconst endpoint = await prompt(\n\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t);\n\t\tconst normalizedEndpoint = endpoint.replace(/\\/$/, '');\n\n\t\ttry {\n\t\t\tnew URL(normalizedEndpoint);\n\t\t} catch {\n\t\t\tthrow new Error('Invalid URL format');\n\t\t}\n\n\t\tlogger.log(\n\t\t\t`\\nGenerate a token at: ${normalizedEndpoint}/settings/profile\\n`,\n\t\t);\n\t\tconst token = await prompt('API Token: ', true);\n\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(normalizedEndpoint, token);\n\t\tif (!isValid) {\n\t\t\tthrow new Error('Invalid credentials. Please check your token.');\n\t\t}\n\n\t\tawait storeDokployCredentials(token, normalizedEndpoint);\n\t\tcreds = { token, endpoint: normalizedEndpoint };\n\t\tlogger.log('ā Credentials saved');\n\t}\n\n\tconst api = new DokployApi({ baseUrl: creds.endpoint, token: creds.token });\n\n\t// Step 2: Check if we have config in gkm.config.ts\n\tconst existingConfig = config.providers?.dokploy;\n\tif (\n\t\texistingConfig &&\n\t\ttypeof existingConfig !== 'boolean' &&\n\t\texistingConfig.applicationId &&\n\t\texistingConfig.projectId\n\t) {\n\t\tlogger.log('ā Dokploy config found in gkm.config.ts');\n\n\t\t// Verify the application still exists\n\t\ttry {\n\t\t\tconst projectDetails = await api.getProject(existingConfig.projectId);\n\t\t\tlogger.log('ā Project verified');\n\n\t\t\t// Get registry ID from config first, then from local storage\n\t\t\tconst storedRegistryId =\n\t\t\t\texistingConfig.registryId ?? (await getDokployRegistryId());\n\n\t\t\t// Get environment ID for service provisioning (match by stage name)\n\t\t\tconst environments = projectDetails.environments ?? [];\n\t\t\tlet environment = environments.find(\n\t\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t\t);\n\n\t\t\t// Create environment if it doesn't exist for this stage\n\t\t\tif (!environment) {\n\t\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\t\tenvironment = await api.createEnvironment(\n\t\t\t\t\texistingConfig.projectId,\n\t\t\t\t\tstage,\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created environment: ${environment.environmentId}`);\n\t\t\t}\n\n\t\t\tconst environmentId = environment.environmentId;\n\n\t\t\t// Provision services if configured\n\t\t\tlogger.log(\n\t\t\t\t` Services config: ${JSON.stringify(services)}, envId: ${environmentId}`,\n\t\t\t);\n\t\t\tconst serviceUrls = await provisionServices(\n\t\t\t\tapi,\n\t\t\t\texistingConfig.projectId,\n\t\t\t\tenvironmentId,\n\t\t\t\tdockerConfig.appName!,\n\t\t\t\tservices,\n\t\t\t\texistingUrls,\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tconfig: {\n\t\t\t\t\tendpoint: existingConfig.endpoint,\n\t\t\t\t\tprojectId: existingConfig.projectId,\n\t\t\t\t\tapplicationId: existingConfig.applicationId,\n\t\t\t\t\tregistry: existingConfig.registry,\n\t\t\t\t\tregistryId: storedRegistryId ?? undefined,\n\t\t\t\t},\n\t\t\t\tserviceUrls,\n\t\t\t};\n\t\t} catch {\n\t\t\tlogger.log('ā Project not found, will recover...');\n\t\t}\n\t}\n\n\t// Step 3: Find or create project\n\tlogger.log('\\nš Looking for project...');\n\tconst projectName = dockerConfig.projectName!;\n\tconst projects = await api.listProjects();\n\tlet project = projects.find(\n\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t);\n\n\tlet environmentId: string;\n\n\tif (project) {\n\t\tlogger.log(\n\t\t\t` Found existing project: ${project.name} (${project.projectId})`,\n\t\t);\n\n\t\t// Step 4: Get or create environment for existing project (match by stage)\n\t\tconst projectDetails = await api.getProject(project.projectId);\n\t\tconst environments = projectDetails.environments ?? [];\n\t\tconst matchingEnv = environments.find(\n\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t);\n\t\tif (matchingEnv) {\n\t\t\tenvironmentId = matchingEnv.environmentId;\n\t\t\tlogger.log(` Using environment: ${matchingEnv.name}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t\tlogger.log(` ā Created environment: ${stage}`);\n\t\t}\n\t} else {\n\t\tlogger.log(` Creating project: ${projectName}`);\n\t\tconst result = await api.createProject(projectName);\n\t\tproject = result.project;\n\t\t// Rename the default environment to match stage if different\n\t\tif (result.environment.name.toLowerCase() !== stage.toLowerCase()) {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t} else {\n\t\t\tenvironmentId = result.environment.environmentId;\n\t\t}\n\t\tlogger.log(` ā Created project: ${project.projectId}`);\n\t\tlogger.log(` ā Using environment: ${stage}`);\n\t}\n\n\t// Step 5: Find or create application\n\tlogger.log('\\nš¦ Looking for application...');\n\tconst appName = dockerConfig.appName!;\n\n\tlet applicationId: string;\n\n\t// Try to find existing app from config\n\tif (\n\t\texistingConfig &&\n\t\ttypeof existingConfig !== 'boolean' &&\n\t\texistingConfig.applicationId\n\t) {\n\t\tapplicationId = existingConfig.applicationId;\n\t\tlogger.log(` Using application from config: ${applicationId}`);\n\t} else {\n\t\t// Create new application\n\t\tlogger.log(` Creating application: ${appName}`);\n\t\tconst app = await api.createApplication(\n\t\t\tappName,\n\t\t\tproject.projectId,\n\t\t\tenvironmentId,\n\t\t);\n\t\tapplicationId = app.applicationId;\n\t\tlogger.log(` ā Created application: ${applicationId}`);\n\t}\n\n\t// Step 6: Ensure registry is set up\n\tlogger.log('\\nš³ Checking registry...');\n\tlet registryId = await getDokployRegistryId();\n\n\tif (registryId) {\n\t\t// Verify stored registry still exists\n\t\ttry {\n\t\t\tconst registry = await api.getRegistry(registryId);\n\t\t\tlogger.log(` Using registry: ${registry.registryName}`);\n\t\t} catch {\n\t\t\tlogger.log(' ā Stored registry not found, clearing...');\n\t\t\tregistryId = undefined;\n\t\t\tawait storeDokployRegistryId('');\n\t\t}\n\t}\n\n\tif (!registryId) {\n\t\tconst registries = await api.listRegistries();\n\n\t\tif (registries.length === 0) {\n\t\t\t// No registries exist\n\t\t\tif (dockerConfig.registry) {\n\t\t\t\tlogger.log(\" No registries found in Dokploy. Let's create one.\");\n\t\t\t\tlogger.log(` Registry URL: ${dockerConfig.registry}`);\n\n\t\t\t\tconst username = await prompt('Registry username: ');\n\t\t\t\tconst password = await prompt('Registry password/token: ', true);\n\n\t\t\t\tconst registry = await api.createRegistry(\n\t\t\t\t\t'Default Registry',\n\t\t\t\t\tdockerConfig.registry,\n\t\t\t\t\tusername,\n\t\t\t\t\tpassword,\n\t\t\t\t);\n\t\t\t\tregistryId = registry.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t\t} else {\n\t\t\t\tlogger.log(\n\t\t\t\t\t' ā No registry configured. Set docker.registry in gkm.config.ts',\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Show available registries and let user select or create new\n\t\t\tlogger.log(' Available registries:');\n\t\t\tregistries.forEach((reg, i) => {\n\t\t\t\tlogger.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);\n\t\t\t});\n\t\t\tif (dockerConfig.registry) {\n\t\t\t\tlogger.log(` ${registries.length + 1}. Create new registry`);\n\t\t\t}\n\n\t\t\tconst maxOption = dockerConfig.registry\n\t\t\t\t? registries.length + 1\n\t\t\t\t: registries.length;\n\t\t\tconst selection = await prompt(` Select registry (1-${maxOption}): `);\n\t\t\tconst index = parseInt(selection, 10) - 1;\n\n\t\t\tif (index >= 0 && index < registries.length) {\n\t\t\t\t// Selected existing registry\n\t\t\t\tregistryId = registries[index]!.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Selected: ${registries[index]!.registryName}`);\n\t\t\t} else if (dockerConfig.registry && index === registries.length) {\n\t\t\t\t// Create new registry\n\t\t\t\tlogger.log(`\\n Creating new registry...`);\n\t\t\t\tlogger.log(` Registry URL: ${dockerConfig.registry}`);\n\n\t\t\t\tconst username = await prompt(' Registry username: ');\n\t\t\t\tconst password = await prompt(' Registry password/token: ', true);\n\n\t\t\t\tconst registry = await api.createRegistry(\n\t\t\t\t\tdockerConfig.registry.replace(/^https?:\\/\\//, ''),\n\t\t\t\t\tdockerConfig.registry,\n\t\t\t\t\tusername,\n\t\t\t\t\tpassword,\n\t\t\t\t);\n\t\t\t\tregistryId = registry.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t\t} else {\n\t\t\t\tlogger.log(' ā Invalid selection, skipping registry setup');\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 7: Build and save config\n\tconst dokployConfig: DokployDeployConfig = {\n\t\tendpoint: creds.endpoint,\n\t\tprojectId: project.projectId,\n\t\tapplicationId,\n\t\tregistryId: registryId ?? undefined,\n\t};\n\n\t// Update gkm.config.ts\n\tawait updateConfig(dokployConfig);\n\n\tlogger.log('\\nā
Dokploy setup complete!');\n\tlogger.log(` Project: ${project.projectId}`);\n\tlogger.log(` Application: ${applicationId}`);\n\tif (registryId) {\n\t\tlogger.log(` Registry: ${registryId}`);\n\t}\n\n\t// Step 8: Provision docker compose services if configured\n\tconst serviceUrls = await provisionServices(\n\t\tapi,\n\t\tproject.projectId,\n\t\tenvironmentId,\n\t\tdockerConfig.appName!,\n\t\tservices,\n\t\texistingUrls,\n\t);\n\n\treturn {\n\t\tconfig: dokployConfig,\n\t\tserviceUrls,\n\t};\n}\n\n/**\n * Generate image tag from stage and timestamp\n */\nexport function generateTag(stage: string): string {\n\tconst timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);\n\treturn `${stage}-${timestamp}`;\n}\n\n/**\n * Deploy all apps in a workspace to Dokploy.\n * - Workspace maps to one Dokploy project\n * - Each app maps to one Dokploy application\n * - Deploys in dependency order (backends before dependent frontends)\n * - Syncs environment variables including {APP_NAME}_URL\n * @internal Exported for testing\n */\nexport async function workspaceDeployCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DeployOptions,\n): Promise<WorkspaceDeployResult> {\n\tconst { provider, stage, tag, skipBuild, apps: selectedApps } = options;\n\n\tif (provider !== 'dokploy') {\n\t\tthrow new Error(\n\t\t\t`Workspace deployment only supports Dokploy. Got: ${provider}`,\n\t\t);\n\t}\n\n\tlogger.log(`\\nš Deploying workspace \"${workspace.name}\" to Dokploy...`);\n\tlogger.log(` Stage: ${stage}`);\n\n\t// Generate tag if not provided\n\tconst imageTag = tag ?? generateTag(stage);\n\tlogger.log(` Tag: ${imageTag}`);\n\n\t// Get apps to deploy in dependency order\n\tconst buildOrder = getAppBuildOrder(workspace);\n\n\t// Filter to selected apps if specified\n\tlet appsToDeployNames = buildOrder;\n\tif (selectedApps && selectedApps.length > 0) {\n\t\t// Validate selected apps exist\n\t\tconst invalidApps = selectedApps.filter((name) => !workspace.apps[name]);\n\t\tif (invalidApps.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown apps: ${invalidApps.join(', ')}\\n` +\n\t\t\t\t\t`Available apps: ${Object.keys(workspace.apps).join(', ')}`,\n\t\t\t);\n\t\t}\n\t\t// Keep only selected apps, but maintain dependency order\n\t\tappsToDeployNames = buildOrder.filter((name) =>\n\t\t\tselectedApps.includes(name),\n\t\t);\n\t\tlogger.log(` Deploying apps: ${appsToDeployNames.join(', ')}`);\n\t} else {\n\t\tlogger.log(` Deploying all apps: ${appsToDeployNames.join(', ')}`);\n\t}\n\n\t// Filter apps by deploy target\n\t// In Phase 1, only 'dokploy' is supported. Other targets should have been\n\t// caught at config validation, but we handle it gracefully here too.\n\tconst dokployApps = appsToDeployNames.filter((name) => {\n\t\tconst app = workspace.apps[name]!;\n\t\tconst target = app.resolvedDeployTarget;\n\t\tif (!isDeployTargetSupported(target)) {\n\t\t\tlogger.log(\n\t\t\t\t` ā ļø Skipping ${name}: ${getDeployTargetError(target, name)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\tif (dokployApps.length === 0) {\n\t\tthrow new Error(\n\t\t\t'No apps to deploy. All selected apps have unsupported deploy targets.',\n\t\t);\n\t}\n\n\tif (dokployApps.length !== appsToDeployNames.length) {\n\t\tconst skipped = appsToDeployNames.filter(\n\t\t\t(name) => !dokployApps.includes(name),\n\t\t);\n\t\tlogger.log(\n\t\t\t` š ${skipped.length} app(s) skipped due to unsupported targets`,\n\t\t);\n\t}\n\n\tappsToDeployNames = dokployApps;\n\n\t// Ensure we have Dokploy credentials\n\tlet creds = await getDokployCredentials();\n\tif (!creds) {\n\t\tlogger.log(\"\\nš Dokploy credentials not found. Let's set them up.\");\n\t\tconst endpoint = await prompt(\n\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t);\n\t\tconst normalizedEndpoint = endpoint.replace(/\\/$/, '');\n\n\t\ttry {\n\t\t\tnew URL(normalizedEndpoint);\n\t\t} catch {\n\t\t\tthrow new Error('Invalid URL format');\n\t\t}\n\n\t\tlogger.log(\n\t\t\t`\\nGenerate a token at: ${normalizedEndpoint}/settings/profile\\n`,\n\t\t);\n\t\tconst token = await prompt('API Token: ', true);\n\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(normalizedEndpoint, token);\n\t\tif (!isValid) {\n\t\t\tthrow new Error('Invalid credentials. Please check your token.');\n\t\t}\n\n\t\tawait storeDokployCredentials(token, normalizedEndpoint);\n\t\tcreds = { token, endpoint: normalizedEndpoint };\n\t\tlogger.log('ā Credentials saved');\n\t}\n\n\tconst api = new DokployApi({ baseUrl: creds.endpoint, token: creds.token });\n\n\t// Find or create project for the workspace\n\tlogger.log('\\nš Setting up Dokploy project...');\n\tconst projectName = workspace.name;\n\tconst projects = await api.listProjects();\n\tlet project = projects.find(\n\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t);\n\n\tlet environmentId: string;\n\n\tif (project) {\n\t\tlogger.log(` Found existing project: ${project.name}`);\n\t\t// Get or create environment for stage\n\t\tconst projectDetails = await api.getProject(project.projectId);\n\t\tconst environments = projectDetails.environments ?? [];\n\t\tconst matchingEnv = environments.find(\n\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t);\n\t\tif (matchingEnv) {\n\t\t\tenvironmentId = matchingEnv.environmentId;\n\t\t\tlogger.log(` Using environment: ${matchingEnv.name}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t\tlogger.log(` ā Created environment: ${stage}`);\n\t\t}\n\t} else {\n\t\tlogger.log(` Creating project: ${projectName}`);\n\t\tconst result = await api.createProject(projectName);\n\t\tproject = result.project;\n\t\t// Create environment for stage if different from default\n\t\tif (result.environment.name.toLowerCase() !== stage.toLowerCase()) {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t} else {\n\t\t\tenvironmentId = result.environment.environmentId;\n\t\t}\n\t\tlogger.log(` ā Created project: ${project.projectId}`);\n\t}\n\n\t// Get or set up registry\n\tlogger.log('\\nš³ Checking registry...');\n\tlet registryId = await getDokployRegistryId();\n\tconst registry = workspace.deploy.dokploy?.registry;\n\n\tif (registryId) {\n\t\ttry {\n\t\t\tconst reg = await api.getRegistry(registryId);\n\t\t\tlogger.log(` Using registry: ${reg.registryName}`);\n\t\t} catch {\n\t\t\tlogger.log(' ā Stored registry not found, clearing...');\n\t\t\tregistryId = undefined;\n\t\t\tawait storeDokployRegistryId('');\n\t\t}\n\t}\n\n\tif (!registryId) {\n\t\tconst registries = await api.listRegistries();\n\t\tif (registries.length > 0) {\n\t\t\t// Use first available registry\n\t\t\tregistryId = registries[0]!.registryId;\n\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\tlogger.log(` Using registry: ${registries[0]!.registryName}`);\n\t\t} else if (registry) {\n\t\t\tlogger.log(\" No registries found in Dokploy. Let's create one.\");\n\t\t\tlogger.log(` Registry URL: ${registry}`);\n\n\t\t\tconst username = await prompt('Registry username: ');\n\t\t\tconst password = await prompt('Registry password/token: ', true);\n\n\t\t\tconst reg = await api.createRegistry(\n\t\t\t\t'Default Registry',\n\t\t\t\tregistry,\n\t\t\t\tusername,\n\t\t\t\tpassword,\n\t\t\t);\n\t\t\tregistryId = reg.registryId;\n\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t} else {\n\t\t\tlogger.log(\n\t\t\t\t' ā No registry configured. Set deploy.dokploy.registry in workspace config',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Provision infrastructure services if configured\n\tconst services = workspace.services;\n\tconst dockerServices = {\n\t\tpostgres: services.db !== undefined && services.db !== false,\n\t\tredis: services.cache !== undefined && services.cache !== false,\n\t};\n\n\tif (dockerServices.postgres || dockerServices.redis) {\n\t\tlogger.log('\\nš§ Provisioning infrastructure services...');\n\t\tawait provisionServices(\n\t\t\tapi,\n\t\t\tproject.projectId,\n\t\t\tenvironmentId,\n\t\t\tworkspace.name,\n\t\t\tdockerServices,\n\t\t);\n\t}\n\n\t// Track deployed app URLs for environment variable injection\n\tconst deployedAppUrls: Record<string, string> = {};\n\n\t// Deploy apps in dependency order\n\tlogger.log('\\nš¦ Deploying applications...');\n\tconst results: AppDeployResult[] = [];\n\n\tfor (const appName of appsToDeployNames) {\n\t\tconst app = workspace.apps[appName]!;\n\t\tconst appPath = app.path;\n\n\t\tlogger.log(\n\t\t\t`\\n ${app.type === 'backend' ? 'āļø' : 'š'} Deploying ${appName}...`,\n\t\t);\n\n\t\ttry {\n\t\t\t// Find or create application in Dokploy\n\t\t\tconst dokployAppName = `${workspace.name}-${appName}`;\n\t\t\tlet application: DokployApplication | undefined;\n\n\t\t\ttry {\n\t\t\t\t// Try to find existing application (Dokploy doesn't have a direct lookup)\n\t\t\t\t// We'll create a new one and handle the error if it exists\n\t\t\t\tapplication = await api.createApplication(\n\t\t\t\t\tdokployAppName,\n\t\t\t\t\tproject.projectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t);\n\t\t\t\tlogger.log(` Created application: ${application.applicationId}`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` Application already exists`);\n\t\t\t\t\t// For now, we'll continue without the applicationId\n\t\t\t\t\t// In a real implementation, we'd need to list and find the app\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build the app if not skipped\n\t\t\tif (!skipBuild) {\n\t\t\t\tlogger.log(` Building ${appName}...`);\n\t\t\t\t// For workspace, we need to build from the app directory\n\t\t\t\tconst originalCwd = process.cwd();\n\t\t\t\tconst fullAppPath = `${workspace.root}/${appPath}`;\n\n\t\t\t\ttry {\n\t\t\t\t\tprocess.chdir(fullAppPath);\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: 'server',\n\t\t\t\t\t\tproduction: true,\n\t\t\t\t\t\tstage,\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(originalCwd);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build Docker image\n\t\t\tconst imageName = `${workspace.name}-${appName}`;\n\t\t\tconst imageRef = registry\n\t\t\t\t? `${registry}/${imageName}:${imageTag}`\n\t\t\t\t: `${imageName}:${imageTag}`;\n\n\t\t\tlogger.log(` Building Docker image: ${imageRef}`);\n\n\t\t\tawait deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush: false,\n\t\t\t\tconfig: {\n\t\t\t\t\tregistry,\n\t\t\t\t\timageName,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Prepare environment variables\n\t\t\tconst envVars: string[] = [`NODE_ENV=production`, `PORT=${app.port}`];\n\n\t\t\t// Add dependency URLs\n\t\t\tfor (const dep of app.dependencies) {\n\t\t\t\tconst depUrl = deployedAppUrls[dep];\n\t\t\t\tif (depUrl) {\n\t\t\t\t\tenvVars.push(`${dep.toUpperCase()}_URL=${depUrl}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add infrastructure URLs for backend apps\n\t\t\tif (app.type === 'backend') {\n\t\t\t\tif (dockerServices.postgres) {\n\t\t\t\t\tenvVars.push(\n\t\t\t\t\t\t`DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@${workspace.name}-db:5432/app}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (dockerServices.redis) {\n\t\t\t\t\tenvVars.push(\n\t\t\t\t\t\t`REDIS_URL=\\${REDIS_URL:-redis://${workspace.name}-cache:6379}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Configure application in Dokploy\n\t\t\tif (application) {\n\t\t\t\t// Save Docker provider config\n\t\t\t\tawait api.saveDockerProvider(application.applicationId, imageRef, {\n\t\t\t\t\tregistryId,\n\t\t\t\t});\n\n\t\t\t\t// Save environment variables\n\t\t\t\tawait api.saveApplicationEnv(\n\t\t\t\t\tapplication.applicationId,\n\t\t\t\t\tenvVars.join('\\n'),\n\t\t\t\t);\n\n\t\t\t\t// Deploy\n\t\t\t\tlogger.log(` Deploying to Dokploy...`);\n\t\t\t\tawait api.deployApplication(application.applicationId);\n\n\t\t\t\t// Track this app's URL for dependent apps\n\t\t\t\t// Dokploy uses the appName as the internal hostname\n\t\t\t\tconst appUrl = `http://${dokployAppName}:${app.port}`;\n\t\t\t\tdeployedAppUrls[appName] = appUrl;\n\n\t\t\t\tresults.push({\n\t\t\t\t\tappName,\n\t\t\t\t\ttype: app.type,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tapplicationId: application.applicationId,\n\t\t\t\t\timageRef,\n\t\t\t\t});\n\n\t\t\t\tlogger.log(` ā ${appName} deployed successfully`);\n\t\t\t} else {\n\t\t\t\t// Application already exists, just track it\n\t\t\t\tconst appUrl = `http://${dokployAppName}:${app.port}`;\n\t\t\t\tdeployedAppUrls[appName] = appUrl;\n\n\t\t\t\tresults.push({\n\t\t\t\t\tappName,\n\t\t\t\t\ttype: app.type,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\timageRef,\n\t\t\t\t});\n\n\t\t\t\tlogger.log(` ā ${appName} image pushed (app already exists)`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : 'Unknown error';\n\t\t\tlogger.log(` ā Failed to deploy ${appName}: ${message}`);\n\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: message,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Summary\n\tconst successCount = results.filter((r) => r.success).length;\n\tconst failedCount = results.filter((r) => !r.success).length;\n\n\tlogger.log(`\\n${'ā'.repeat(50)}`);\n\tlogger.log(`\\nā
Workspace deployment complete!`);\n\tlogger.log(` Project: ${project.projectId}`);\n\tlogger.log(` Successful: ${successCount}`);\n\tif (failedCount > 0) {\n\t\tlogger.log(` Failed: ${failedCount}`);\n\t}\n\n\treturn {\n\t\tapps: results,\n\t\tprojectId: project.projectId,\n\t\tsuccessCount,\n\t\tfailedCount,\n\t};\n}\n\n/**\n * Main deploy command\n */\nexport async function deployCommand(\n\toptions: DeployOptions,\n): Promise<DeployResult | WorkspaceDeployResult> {\n\tconst { provider, stage, tag, skipPush, skipBuild } = options;\n\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace deploy mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceDeployCommand(loadedConfig.workspace, options);\n\t}\n\n\tlogger.log(`\\nš Deploying to ${provider}...`);\n\tlogger.log(` Stage: ${stage}`);\n\n\t// Single-app mode - use existing logic\n\tconst config = await loadConfig();\n\n\t// Generate tag if not provided\n\tconst imageTag = tag ?? generateTag(stage);\n\tlogger.log(` Tag: ${imageTag}`);\n\n\t// Resolve docker config for image reference\n\tconst dockerConfig = resolveDockerConfig(config);\n\tconst imageName = dockerConfig.imageName!;\n\tconst registry = dockerConfig.registry;\n\tconst imageRef = registry\n\t\t? `${registry}/${imageName}:${imageTag}`\n\t\t: `${imageName}:${imageTag}`;\n\n\t// For Dokploy, set up services BEFORE build so URLs are available\n\tlet dokployConfig: DokployDeployConfig | undefined;\n\tlet finalRegistry = registry;\n\n\tif (provider === 'dokploy') {\n\t\t// Extract docker compose services config\n\t\tconst composeServices = config.docker?.compose?.services;\n\t\tlogger.log(\n\t\t\t`\\nš Docker compose config: ${JSON.stringify(config.docker?.compose)}`,\n\t\t);\n\t\tconst dockerServices: DockerComposeServices | undefined = composeServices\n\t\t\t? Array.isArray(composeServices)\n\t\t\t\t? {\n\t\t\t\t\t\tpostgres: composeServices.includes('postgres'),\n\t\t\t\t\t\tredis: composeServices.includes('redis'),\n\t\t\t\t\t\trabbitmq: composeServices.includes('rabbitmq'),\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tpostgres: Boolean(composeServices.postgres),\n\t\t\t\t\t\tredis: Boolean(composeServices.redis),\n\t\t\t\t\t\trabbitmq: Boolean(composeServices.rabbitmq),\n\t\t\t\t\t}\n\t\t\t: undefined;\n\n\t\t// Ensure Dokploy is fully set up (credentials, project, app, registry, services)\n\t\tconst setupResult = await ensureDokploySetup(\n\t\t\tconfig,\n\t\t\tdockerConfig,\n\t\t\tstage,\n\t\t\tdockerServices,\n\t\t);\n\t\tdokployConfig = setupResult.config;\n\t\tfinalRegistry = dokployConfig.registry ?? dockerConfig.registry;\n\n\t\t// Save provisioned service URLs to secrets before build\n\t\tif (setupResult.serviceUrls) {\n\t\t\tconst { readStageSecrets, writeStageSecrets, initStageSecrets } =\n\t\t\t\tawait import('../secrets/storage');\n\t\t\tlet secrets = await readStageSecrets(stage);\n\n\t\t\t// Create secrets file if it doesn't exist\n\t\t\tif (!secrets) {\n\t\t\t\tlogger.log(` Creating secrets file for stage \"${stage}\"...`);\n\t\t\t\tsecrets = initStageSecrets(stage);\n\t\t\t}\n\n\t\t\tlet updated = false;\n\t\t\t// URL fields go to secrets.urls, individual params go to secrets.custom\n\t\t\tconst urlFields = ['DATABASE_URL', 'REDIS_URL', 'RABBITMQ_URL'] as const;\n\n\t\t\tfor (const [key, value] of Object.entries(setupResult.serviceUrls)) {\n\t\t\t\tif (!value) continue;\n\n\t\t\t\tif (urlFields.includes(key as (typeof urlFields)[number])) {\n\t\t\t\t\t// URL fields\n\t\t\t\t\tconst urlKey = key as keyof typeof secrets.urls;\n\t\t\t\t\tif (!secrets.urls[urlKey]) {\n\t\t\t\t\t\tsecrets.urls[urlKey] = value;\n\t\t\t\t\t\tlogger.log(` Saved ${key} to secrets.urls`);\n\t\t\t\t\t\tupdated = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Individual parameters (HOST, PORT, NAME, USER, PASSWORD)\n\t\t\t\t\tif (!secrets.custom[key]) {\n\t\t\t\t\t\tsecrets.custom[key] = value;\n\t\t\t\t\t\tlogger.log(` Saved ${key} to secrets.custom`);\n\t\t\t\t\t\tupdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\tawait writeStageSecrets(secrets);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build for production with secrets injection (unless skipped)\n\tlet masterKey: string | undefined;\n\tif (!skipBuild) {\n\t\tlogger.log(`\\nš¦ Building for production...`);\n\t\tconst buildResult = await buildCommand({\n\t\t\tprovider: 'server',\n\t\t\tproduction: true,\n\t\t\tstage,\n\t\t});\n\t\tmasterKey = buildResult.masterKey;\n\t} else {\n\t\tlogger.log(`\\nāļø Skipping build (--skip-build)`);\n\t}\n\n\t// Deploy based on provider\n\tlet result: DeployResult;\n\n\tswitch (provider) {\n\t\tcase 'docker': {\n\t\t\tresult = await deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush,\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: dockerConfig,\n\t\t\t});\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'dokploy': {\n\t\t\tif (!dokployConfig) {\n\t\t\t\tthrow new Error('Dokploy config not initialized');\n\t\t\t}\n\t\t\tconst finalImageRef = finalRegistry\n\t\t\t\t? `${finalRegistry}/${imageName}:${imageTag}`\n\t\t\t\t: `${imageName}:${imageTag}`;\n\n\t\t\t// First build and push the Docker image\n\t\t\tawait deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush: false, // Dokploy needs the image in registry\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: {\n\t\t\t\t\tregistry: finalRegistry,\n\t\t\t\t\timageName: dockerConfig.imageName,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Then trigger Dokploy deployment\n\t\t\tresult = await deployDokploy({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\timageRef: finalImageRef,\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: dokployConfig,\n\t\t\t});\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'aws-lambda': {\n\t\t\tlogger.log('\\nā ļø AWS Lambda deployment is not yet implemented.');\n\t\t\tlogger.log(' Use SST or AWS CDK for Lambda deployments.');\n\t\t\tresult = { imageRef, masterKey };\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault: {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown deploy provider: ${provider}\\n` +\n\t\t\t\t\t'Supported providers: docker, dokploy, aws-lambda',\n\t\t\t);\n\t\t}\n\t}\n\n\tlogger.log('\\nā
Deployment complete!');\n\n\treturn result;\n}\n\nexport type { DeployOptions, DeployProvider, DeployResult };\n","import { randomBytes } from 'node:crypto';\nimport type { ComposeServiceName } from '../types';\nimport type { ServiceCredentials, StageSecrets } from './types';\n\n/**\n * Generate a secure random password using URL-safe base64 characters.\n * @param length Password length (default: 32)\n */\nexport function generateSecurePassword(length = 32): string {\n\treturn randomBytes(Math.ceil((length * 3) / 4))\n\t\t.toString('base64url')\n\t\t.slice(0, length);\n}\n\n/** Default service configurations */\nconst SERVICE_DEFAULTS: Record<\n\tComposeServiceName,\n\tOmit<ServiceCredentials, 'password'>\n> = {\n\tpostgres: {\n\t\thost: 'postgres',\n\t\tport: 5432,\n\t\tusername: 'app',\n\t\tdatabase: 'app',\n\t},\n\tredis: {\n\t\thost: 'redis',\n\t\tport: 6379,\n\t\tusername: 'default',\n\t},\n\trabbitmq: {\n\t\thost: 'rabbitmq',\n\t\tport: 5672,\n\t\tusername: 'app',\n\t\tvhost: '/',\n\t},\n};\n\n/**\n * Generate credentials for a specific service.\n */\nexport function generateServiceCredentials(\n\tservice: ComposeServiceName,\n): ServiceCredentials {\n\tconst defaults = SERVICE_DEFAULTS[service];\n\treturn {\n\t\t...defaults,\n\t\tpassword: generateSecurePassword(),\n\t};\n}\n\n/**\n * Generate credentials for multiple services.\n */\nexport function generateServicesCredentials(\n\tservices: ComposeServiceName[],\n): StageSecrets['services'] {\n\tconst result: StageSecrets['services'] = {};\n\n\tfor (const service of services) {\n\t\tresult[service] = generateServiceCredentials(service);\n\t}\n\n\treturn result;\n}\n\n/**\n * Generate connection URL for PostgreSQL.\n */\nexport function generatePostgresUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, database } = creds;\n\treturn `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;\n}\n\n/**\n * Generate connection URL for Redis.\n */\nexport function generateRedisUrl(creds: ServiceCredentials): string {\n\tconst { password, host, port } = creds;\n\treturn `redis://:${encodeURIComponent(password)}@${host}:${port}`;\n}\n\n/**\n * Generate connection URL for RabbitMQ.\n */\nexport function generateRabbitmqUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, vhost } = creds;\n\tconst encodedVhost = encodeURIComponent(vhost ?? '/');\n\treturn `amqp://${username}:${encodeURIComponent(password)}@${host}:${port}/${encodedVhost}`;\n}\n\n/**\n * Generate connection URLs from service credentials.\n */\nexport function generateConnectionUrls(\n\tservices: StageSecrets['services'],\n): StageSecrets['urls'] {\n\tconst urls: StageSecrets['urls'] = {};\n\n\tif (services.postgres) {\n\t\turls.DATABASE_URL = generatePostgresUrl(services.postgres);\n\t}\n\n\tif (services.redis) {\n\t\turls.REDIS_URL = generateRedisUrl(services.redis);\n\t}\n\n\tif (services.rabbitmq) {\n\t\turls.RABBITMQ_URL = generateRabbitmqUrl(services.rabbitmq);\n\t}\n\n\treturn urls;\n}\n\n/**\n * Create a new StageSecrets object with generated credentials.\n */\nexport function createStageSecrets(\n\tstage: string,\n\tservices: ComposeServiceName[],\n): StageSecrets {\n\tconst now = new Date().toISOString();\n\tconst serviceCredentials = generateServicesCredentials(services);\n\tconst urls = generateConnectionUrls(serviceCredentials);\n\n\treturn {\n\t\tstage,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tservices: serviceCredentials,\n\t\turls,\n\t\tcustom: {},\n\t};\n}\n\n/**\n * Rotate password for a specific service.\n */\nexport function rotateServicePassword(\n\tsecrets: StageSecrets,\n\tservice: ComposeServiceName,\n): StageSecrets {\n\tconst currentCreds = secrets.services[service];\n\tif (!currentCreds) {\n\t\tthrow new Error(`Service \"${service}\" not configured in secrets`);\n\t}\n\n\tconst newCreds: ServiceCredentials = {\n\t\t...currentCreds,\n\t\tpassword: generateSecurePassword(),\n\t};\n\n\tconst newServices = {\n\t\t...secrets.services,\n\t\t[service]: newCreds,\n\t};\n\n\treturn {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tservices: newServices,\n\t\turls: generateConnectionUrls(newServices),\n\t};\n}\n","import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n// Load package.json - handles both bundled (flat dist/) and source (nested src/init/)\nfunction loadPackageJson(): { version: string } {\n\ttry {\n\t\t// Try flat dist path first (../package.json from dist/)\n\t\treturn require('../package.json');\n\t} catch {\n\t\t// Fall back to nested source path (../../package.json from src/init/)\n\t\treturn require('../../package.json');\n\t}\n}\n\nconst pkg = loadPackageJson();\n\n/**\n * CLI version from package.json (used for scaffolded projects)\n */\nexport const CLI_VERSION = `~${pkg.version}`;\n\n/**\n * Current released versions of @geekmidas packages\n * Update these when publishing new versions\n * Note: CLI version is read from package.json via CLI_VERSION\n */\nexport const GEEKMIDAS_VERSIONS = {\n\t'@geekmidas/audit': '~0.2.0',\n\t'@geekmidas/auth': '~0.2.0',\n\t'@geekmidas/cache': '~0.2.0',\n\t'@geekmidas/cli': CLI_VERSION,\n\t'@geekmidas/client': '~0.5.0',\n\t'@geekmidas/cloud': '~0.2.0',\n\t'@geekmidas/constructs': '~0.6.0',\n\t'@geekmidas/db': '~0.3.0',\n\t'@geekmidas/emailkit': '~0.2.0',\n\t'@geekmidas/envkit': '~0.5.0',\n\t'@geekmidas/errors': '~0.1.0',\n\t'@geekmidas/events': '~0.2.0',\n\t'@geekmidas/logger': '~0.4.0',\n\t'@geekmidas/rate-limit': '~0.3.0',\n\t'@geekmidas/schema': '~0.1.0',\n\t'@geekmidas/services': '~0.2.0',\n\t'@geekmidas/storage': '~0.1.0',\n\t'@geekmidas/studio': '~0.4.0',\n\t'@geekmidas/telescope': '~0.5.0',\n\t'@geekmidas/testkit': '~0.6.0',\n};\n\nexport type GeekmidasPackage = keyof typeof GEEKMIDAS_VERSIONS;\n\n/**\n * Get the version for a @geekmidas package\n */\nexport function getPackageVersion(pkg: GeekmidasPackage): string {\n\treturn GEEKMIDAS_VERSIONS[pkg]!;\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate auth app files for fullstack template\n * Uses better-auth with magic link authentication\n */\nexport function generateAuthAppFiles(\n\toptions: TemplateOptions,\n): GeneratedFile[] {\n\tif (!options.monorepo || options.template !== 'fullstack') {\n\t\treturn [];\n\t}\n\n\tconst packageName = `@${options.name}/auth`;\n\tconst modelsPackage = `@${options.name}/models`;\n\n\t// package.json for auth app\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tscripts: {\n\t\t\tdev: 'gkm dev --entry ./src/index.ts',\n\t\t\tbuild: 'tsc',\n\t\t\tstart: 'node dist/index.js',\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\t[modelsPackage]: 'workspace:*',\n\t\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t\t'@hono/node-server': '~1.13.0',\n\t\t\t'better-auth': '~1.2.0',\n\t\t\thono: '~4.8.0',\n\t\t\tkysely: '~0.27.0',\n\t\t\tpg: '~8.13.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t\t'@types/node': '~22.0.0',\n\t\t\t'@types/pg': '~8.11.0',\n\t\t\ttsx: '~4.20.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// tsconfig.json for auth app\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tnoEmit: true,\n\t\t\tbaseUrl: '.',\n\t\t\tpaths: {\n\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t},\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// src/config/env.ts\n\tconst envTs = `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed where needed\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`;\n\n\t// src/config/logger.ts\n\tconst loggerTs = `import { createLogger } from '@geekmidas/logger/${options.loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t// src/auth.ts - better-auth instance with magic link\n\tconst authTs = `import { betterAuth } from 'better-auth';\nimport { magicLink } from 'better-auth/plugins';\nimport pg from 'pg';\nimport { envParser } from './config/env.js';\nimport { logger } from './config/logger.js';\n\n// Parse auth-specific config (no defaults - values from secrets)\nconst authConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n baseUrl: get('BETTER_AUTH_URL').string(),\n trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),\n secret: get('BETTER_AUTH_SECRET').string(),\n }))\n .parse();\n\nexport const auth = betterAuth({\n database: new pg.Pool({\n connectionString: authConfig.databaseUrl,\n }),\n baseURL: authConfig.baseUrl,\n trustedOrigins: authConfig.trustedOrigins.split(','),\n secret: authConfig.secret,\n plugins: [\n magicLink({\n sendMagicLink: async ({ email, url }) => {\n // TODO: Implement email sending using @geekmidas/emailkit\n // For development, log the magic link\n logger.info({ email, url }, 'Magic link generated');\n console.log('\\\\n================================');\n console.log('MAGIC LINK FOR:', email);\n console.log(url);\n console.log('================================\\\\n');\n },\n expiresIn: 300, // 5 minutes\n }),\n ],\n emailAndPassword: {\n enabled: false, // Only magic link for now\n },\n});\n\nexport type Auth = typeof auth;\n`;\n\n\t// src/index.ts - Hono app entry point\n\tconst indexTs = `import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { serve } from '@hono/node-server';\nimport { auth } from './auth.js';\nimport { envParser } from './config/env.js';\nimport { logger } from './config/logger.js';\n\n// Parse server config (no defaults - values from secrets)\nconst serverConfig = envParser\n .create((get) => ({\n port: get('PORT').string().transform(Number),\n trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),\n }))\n .parse();\n\nconst app = new Hono();\n\n// CORS must be registered before routes\napp.use(\n '/api/auth/*',\n cors({\n origin: serverConfig.trustedOrigins.split(','),\n allowHeaders: ['Content-Type', 'Authorization'],\n allowMethods: ['POST', 'GET', 'OPTIONS'],\n credentials: true,\n }),\n);\n\n// Health check endpoint\napp.get('/health', (c) => {\n return c.json({\n status: 'ok',\n service: 'auth',\n timestamp: new Date().toISOString(),\n });\n});\n\n// Mount better-auth handler\napp.on(['POST', 'GET'], '/api/auth/*', (c) => {\n return auth.handler(c.req.raw);\n});\n\nlogger.info({ port: serverConfig.port }, 'Starting auth server');\n\nserve({\n fetch: app.fetch,\n port: serverConfig.port,\n}, (info) => {\n logger.info({ port: info.port }, 'Auth server running');\n});\n`;\n\n\t// .gitignore for auth app\n\tconst gitignore = `node_modules/\ndist/\n.env.local\n*.log\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'apps/auth/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/config/env.ts',\n\t\t\tcontent: envTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/config/logger.ts',\n\t\t\tcontent: loggerTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/auth.ts',\n\t\t\tcontent: authTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/index.ts',\n\t\t\tcontent: indexTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate configuration files (gkm.config.ts, tsconfig.json, biome.json, turbo.json)\n */\nexport function generateConfigFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\tconst { telescope, studio, routesStructure } = options;\n\tconst isServerless = template.name === 'serverless';\n\tconst hasWorker = template.name === 'worker';\n\tconst isFullstack = options.template === 'fullstack';\n\n\t// Get routes glob pattern based on structure\n\tconst getRoutesGlob = () => {\n\t\tswitch (routesStructure) {\n\t\t\tcase 'centralized-endpoints':\n\t\t\t\treturn './src/endpoints/**/*.ts';\n\t\t\tcase 'centralized-routes':\n\t\t\t\treturn './src/routes/**/*.ts';\n\t\t\tcase 'domain-based':\n\t\t\t\treturn './src/**/routes/*.ts';\n\t\t}\n\t};\n\n\t// For fullstack template, generate workspace config at root\n\t// Single app config is still generated for non-fullstack monorepo setups\n\tif (isFullstack) {\n\t\t// Workspace config is generated in monorepo.ts for fullstack\n\t\treturn generateSingleAppConfigFiles(options, template, {\n\t\t\ttelescope,\n\t\t\tstudio,\n\t\t\troutesStructure,\n\t\t\tisServerless,\n\t\t\thasWorker,\n\t\t\tgetRoutesGlob,\n\t\t});\n\t}\n\n\t// Build gkm.config.ts for single-app\n\tlet gkmConfig = `import { defineConfig } from '@geekmidas/cli/config';\n\nexport default defineConfig({\n routes: '${getRoutesGlob()}',\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',`;\n\n\tif (isServerless || hasWorker) {\n\t\tgkmConfig += `\n functions: './src/functions/**/*.ts',`;\n\t}\n\n\tif (hasWorker) {\n\t\tgkmConfig += `\n crons: './src/crons/**/*.ts',\n subscribers: './src/subscribers/**/*.ts',`;\n\t}\n\n\tif (telescope) {\n\t\tgkmConfig += `\n telescope: {\n enabled: true,\n path: '/__telescope',\n },`;\n\t}\n\n\tif (studio) {\n\t\tgkmConfig += `\n studio: './src/config/studio#studio',`;\n\t}\n\n\t// Always add openapi config (output path is fixed to .gkm/openapi.ts)\n\tgkmConfig += `\n openapi: {\n enabled: true,\n },`;\n\n\tgkmConfig += `\n});\n`;\n\n\t// Build tsconfig.json - extends root for monorepo, standalone for non-monorepo\n\t// Using noEmit: true since typecheck is done via turbo\n\tconst tsConfig = options.monorepo\n\t\t? {\n\t\t\t\textends: '../../tsconfig.json',\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\tnoEmit: true,\n\t\t\t\t\tbaseUrl: '.',\n\t\t\t\t\tpaths: {\n\t\t\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tinclude: ['src/**/*.ts'],\n\t\t\t\texclude: ['node_modules', 'dist'],\n\t\t\t}\n\t\t: {\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: 'ES2022',\n\t\t\t\t\tmodule: 'NodeNext',\n\t\t\t\t\tmoduleResolution: 'NodeNext',\n\t\t\t\t\tlib: ['ES2022'],\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tskipLibCheck: true,\n\t\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\t\tresolveJsonModule: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\tdeclarationMap: true,\n\t\t\t\t\toutDir: './dist',\n\t\t\t\t\trootDir: './src',\n\t\t\t\t},\n\t\t\t\tinclude: ['src/**/*.ts'],\n\t\t\t\texclude: ['node_modules', 'dist'],\n\t\t\t};\n\n\t// Skip biome.json and turbo.json for monorepo (they're at root)\n\tif (options.monorepo) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tpath: 'gkm.config.ts',\n\t\t\t\tcontent: gkmConfig,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: 'tsconfig.json',\n\t\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t\t},\n\t\t];\n\t}\n\n\t// Build biome.json\n\tconst biomeConfig = {\n\t\t$schema: 'https://biomejs.dev/schemas/2.3.0/schema.json',\n\t\tvcs: {\n\t\t\tenabled: true,\n\t\t\tclientKind: 'git',\n\t\t\tuseIgnoreFile: true,\n\t\t},\n\t\torganizeImports: {\n\t\t\tenabled: true,\n\t\t},\n\t\tformatter: {\n\t\t\tenabled: true,\n\t\t\tindentStyle: 'space',\n\t\t\tindentWidth: 2,\n\t\t\tlineWidth: 80,\n\t\t},\n\t\tjavascript: {\n\t\t\tformatter: {\n\t\t\t\tquoteStyle: 'single',\n\t\t\t\ttrailingCommas: 'all',\n\t\t\t\tsemicolons: 'always',\n\t\t\t\tarrowParentheses: 'always',\n\t\t\t},\n\t\t},\n\t\tlinter: {\n\t\t\tenabled: true,\n\t\t\trules: {\n\t\t\t\trecommended: true,\n\t\t\t\tcorrectness: {\n\t\t\t\t\tnoUnusedImports: 'error',\n\t\t\t\t\tnoUnusedVariables: 'error',\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\tnoNonNullAssertion: 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tfiles: {\n\t\t\tignore: ['node_modules', 'dist', '.gkm', 'coverage'],\n\t\t},\n\t};\n\n\t// Build turbo.json\n\tconst turboConfig = {\n\t\t$schema: 'https://turbo.build/schema.json',\n\t\ttasks: {\n\t\t\tbuild: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['dist/**'],\n\t\t\t},\n\t\t\tdev: {\n\t\t\t\tcache: false,\n\t\t\t\tpersistent: true,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\tcache: false,\n\t\t\t},\n\t\t\t'test:once': {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['coverage/**'],\n\t\t\t},\n\t\t\ttypecheck: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tfmt: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t},\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'gkm.config.ts',\n\t\t\tcontent: gkmConfig,\n\t\t},\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'biome.json',\n\t\t\tcontent: `${JSON.stringify(biomeConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'turbo.json',\n\t\t\tcontent: `${JSON.stringify(turboConfig, null, 2)}\\n`,\n\t\t},\n\t];\n}\n\n/**\n * Helper to generate config files for API app in fullstack template\n * (workspace config is at root, so no gkm.config.ts for app)\n */\ninterface ConfigHelperOptions {\n\ttelescope: boolean;\n\tstudio: boolean;\n\troutesStructure: string;\n\tisServerless: boolean;\n\thasWorker: boolean;\n\tgetRoutesGlob: () => string;\n}\n\nfunction generateSingleAppConfigFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n\t_helpers: ConfigHelperOptions,\n): GeneratedFile[] {\n\t// For fullstack, only generate tsconfig.json for the API app\n\t// The workspace gkm.config.ts is generated in monorepo.ts\n\t// Using noEmit: true since typecheck is done via turbo\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tnoEmit: true,\n\t\t\tbaseUrl: '.',\n\t\t\tpaths: {\n\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t},\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\nexport interface DatabaseAppConfig {\n\tname: string;\n\tpassword: string;\n}\n\n/**\n * Generate docker-compose.yml based on template and options\n */\nexport function generateDockerFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n\tdbApps?: DatabaseAppConfig[],\n): GeneratedFile[] {\n\tconst { database } = options;\n\tconst isServerless = template.name === 'serverless';\n\tconst hasWorker = template.name === 'worker';\n\tconst isFullstack = options.template === 'fullstack';\n\n\tconst services: string[] = [];\n\tconst volumes: string[] = [];\n\tconst files: GeneratedFile[] = [];\n\n\t// PostgreSQL database\n\tif (database) {\n\t\tconst initVolume =\n\t\t\tisFullstack && dbApps?.length\n\t\t\t\t? `\n - ./docker/postgres/init.sh:/docker-entrypoint-initdb.d/init.sh:ro`\n\t\t\t\t: '';\n\n\t\tconst envFile =\n\t\t\tisFullstack && dbApps?.length\n\t\t\t\t? `\n env_file:\n - ./docker/.env`\n\t\t\t\t: '';\n\n\t\tservices.push(` postgres:\n image: postgres:16-alpine\n container_name: ${options.name}-postgres\n restart: unless-stopped${envFile}\n environment:\n POSTGRES_USER: postgres\n POSTGRES_PASSWORD: postgres\n POSTGRES_DB: ${options.name.replace(/-/g, '_')}_dev\n ports:\n - '5432:5432'\n volumes:\n - postgres_data:/var/lib/postgresql/data${initVolume}\n healthcheck:\n test: ['CMD-SHELL', 'pg_isready -U postgres']\n interval: 5s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' postgres_data:');\n\n\t\t// Generate PostgreSQL init script and .env for fullstack template\n\t\tif (isFullstack && dbApps?.length) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'docker/postgres/init.sh',\n\t\t\t\tcontent: generatePostgresInitScript(dbApps),\n\t\t\t});\n\n\t\t\t// Generate .env file for docker-compose (contains db passwords)\n\t\t\tfiles.push({\n\t\t\t\tpath: 'docker/.env',\n\t\t\t\tcontent: generateDockerEnv(dbApps),\n\t\t\t});\n\t\t}\n\t}\n\n\t// Redis - different setup for serverless vs standard\n\tif (isServerless) {\n\t\t// Use serverless-redis-http for Lambda compatibility\n\t\tservices.push(` redis:\n image: redis:7-alpine\n container_name: ${options.name}-redis\n restart: unless-stopped\n ports:\n - '6379:6379'\n volumes:\n - redis_data:/data\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5\n\n serverless-redis:\n image: hiett/serverless-redis-http:latest\n container_name: ${options.name}-serverless-redis\n restart: unless-stopped\n ports:\n - '8079:80'\n environment:\n SRH_MODE: env\n SRH_TOKEN: local_dev_token\n SRH_CONNECTION_STRING: redis://redis:6379\n depends_on:\n redis:\n condition: service_healthy`);\n\t\tvolumes.push(' redis_data:');\n\t} else {\n\t\t// Standard Redis for non-serverless templates\n\t\tservices.push(` redis:\n image: redis:7-alpine\n container_name: ${options.name}-redis\n restart: unless-stopped\n ports:\n - '6379:6379'\n volumes:\n - redis_data:/data\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' redis_data:');\n\t}\n\n\t// RabbitMQ for worker template\n\tif (hasWorker) {\n\t\tservices.push(` rabbitmq:\n image: rabbitmq:3-management-alpine\n container_name: ${options.name}-rabbitmq\n restart: unless-stopped\n ports:\n - '5672:5672'\n - '15672:15672'\n environment:\n RABBITMQ_DEFAULT_USER: guest\n RABBITMQ_DEFAULT_PASS: guest\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n healthcheck:\n test: ['CMD', 'rabbitmq-diagnostics', 'check_running']\n interval: 10s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' rabbitmq_data:');\n\t}\n\n\t// Mailpit for email testing\n\tif (options.services?.mail) {\n\t\tservices.push(` mailpit:\n image: axllent/mailpit:latest\n container_name: ${options.name}-mailpit\n restart: unless-stopped\n ports:\n - '1025:1025'\n - '8025:8025'\n environment:\n MP_SMTP_AUTH_ACCEPT_ANY: 1\n MP_SMTP_AUTH_ALLOW_INSECURE: 1`);\n\t}\n\n\t// Build docker-compose.yml\n\tlet dockerCompose = `services:\n${services.join('\\n\\n')}\n`;\n\n\tif (volumes.length > 0) {\n\t\tdockerCompose += `\nvolumes:\n${volumes.join('\\n')}\n`;\n\t}\n\n\t// Add docker-compose.yml to files\n\tfiles.push({\n\t\tpath: 'docker-compose.yml',\n\t\tcontent: dockerCompose,\n\t});\n\n\treturn files;\n}\n\n/**\n * Generate .env file for docker-compose with database passwords\n */\nfunction generateDockerEnv(apps: DatabaseAppConfig[]): string {\n\tconst envVars = apps.map((app) => {\n\t\tconst envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\treturn `${envVar}=${app.password}`;\n\t});\n\n\treturn `# Auto-generated docker environment file\n# Contains database passwords for docker-compose postgres init\n# This file is gitignored - do not commit to version control\n${envVars.join('\\n')}\n`;\n}\n\n/**\n * Generate PostgreSQL init shell script that creates per-app users with separate schemas\n * Uses environment variables for passwords (more secure than hardcoded values)\n * - api user: uses public schema\n * - auth user: uses auth schema with search_path=auth\n */\nfunction generatePostgresInitScript(apps: DatabaseAppConfig[]): string {\n\tconst userCreations = apps.map((app) => {\n\t\tconst userName = app.name.replace(/-/g, '_');\n\t\tconst envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\tconst isApi = app.name === 'api';\n\t\tconst schemaName = isApi ? 'public' : userName;\n\n\t\tif (isApi) {\n\t\t\t// API user uses public schema\n\t\t\treturn `\n# Create ${app.name} user (uses public schema)\necho \"Creating user ${userName}...\"\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n CREATE USER ${userName} WITH PASSWORD '$${envVar}';\n GRANT ALL ON SCHEMA public TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${userName};\nEOSQL\n`;\n\t\t}\n\t\t// Other users get their own schema with search_path\n\t\treturn `\n# Create ${app.name} user with dedicated schema\necho \"Creating user ${userName} with schema ${schemaName}...\"\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n CREATE USER ${userName} WITH PASSWORD '$${envVar}';\n CREATE SCHEMA ${schemaName} AUTHORIZATION ${userName};\n ALTER USER ${userName} SET search_path TO ${schemaName};\n GRANT USAGE ON SCHEMA ${schemaName} TO ${userName};\n GRANT ALL ON ALL TABLES IN SCHEMA ${schemaName} TO ${userName};\n GRANT ALL ON ALL SEQUENCES IN SCHEMA ${schemaName} TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA ${schemaName} GRANT ALL ON TABLES TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA ${schemaName} GRANT ALL ON SEQUENCES TO ${userName};\nEOSQL\n`;\n\t});\n\n\treturn `#!/bin/bash\nset -e\n\n# Auto-generated PostgreSQL init script\n# Creates per-app users with separate schemas in a single database\n# - api: uses public schema\n# - auth: uses auth schema (search_path=auth)\n${userCreations.join('\\n')}\necho \"Database initialization complete!\"\n`;\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate environment-related files (.gitignore only).\n * Note: .env files are no longer generated. Use `gkm secrets:init` to initialize\n * encrypted secrets stored in `.gkm/secrets/{stage}.json` with keys stored at\n * `~/.gkm/{project-name}/{stage}.key`.\n */\nexport function generateEnvFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n): GeneratedFile[] {\n\tconst files: GeneratedFile[] = [];\n\n\t// Only add .gitignore for non-monorepo (monorepo has it at root)\n\tif (!options.monorepo) {\n\t\tconst gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n.gkm/\n\n# Environment (legacy - use gkm secrets instead)\n.env\n.env.local\n.env.*.local\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\npnpm-debug.log*\n\n# Test coverage\ncoverage/\n\n# TypeScript cache\n*.tsbuildinfo\n`;\n\t\tfiles.push({\n\t\t\tpath: '.gitignore',\n\t\t\tcontent: gitignore,\n\t\t});\n\t}\n\n\treturn files;\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\n\n/**\n * Generate packages/models for shared Zod schemas (monorepo only)\n */\nexport function generateModelsPackage(\n\toptions: TemplateOptions,\n): GeneratedFile[] {\n\tif (!options.monorepo) {\n\t\treturn [];\n\t}\n\n\t// Package name based on project name\n\tconst packageName = `@${options.name}/models`;\n\n\t// package.json for models\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\texports: {\n\t\t\t'./*': './src/*.ts',\n\t\t},\n\t\tscripts: {\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\tzod: '~4.1.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// tsconfig.json for models - extends root config\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tdeclaration: true,\n\t\t\tdeclarationMap: true,\n\t\t\toutDir: './dist',\n\t\t\trootDir: './src',\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// common.ts - shared utility schemas\n\tconst commonTs = `import { z } from 'zod';\n\n// ============================================\n// Common Schemas\n// ============================================\n\nexport const IdSchema = z.string().uuid();\n\nexport const TimestampsSchema = z.object({\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport const PaginationSchema = z.object({\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().positive().max(100).default(20),\n});\n\nexport const PaginatedResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>\n z.object({\n items: z.array(itemSchema),\n total: z.number(),\n page: z.number(),\n limit: z.number(),\n totalPages: z.number(),\n });\n\n// ============================================\n// Type Exports\n// ============================================\n\nexport type Id = z.infer<typeof IdSchema>;\nexport type Timestamps = z.infer<typeof TimestampsSchema>;\nexport type Pagination = z.infer<typeof PaginationSchema>;\n`;\n\n\t// user.ts - user-related schemas\n\tconst userTs = `import { z } from 'zod';\nimport { IdSchema, TimestampsSchema } from './common.js';\n\n// ============================================\n// User Schemas\n// ============================================\n\nexport const UserSchema = z.object({\n id: IdSchema,\n email: z.string().email(),\n name: z.string().min(1).max(100),\n ...TimestampsSchema.shape,\n});\n\nexport const CreateUserSchema = UserSchema.omit({\n id: true,\n createdAt: true,\n updatedAt: true,\n});\n\nexport const UpdateUserSchema = CreateUserSchema.partial();\n\n// ============================================\n// Response Schemas\n// ============================================\n\nexport const UserResponseSchema = UserSchema.pick({\n id: true,\n name: true,\n email: true,\n});\n\nexport const ListUsersResponseSchema = z.object({\n users: z.array(UserSchema.pick({ id: true, name: true })),\n});\n\n// ============================================\n// Type Exports\n// ============================================\n\nexport type User = z.infer<typeof UserSchema>;\nexport type CreateUser = z.infer<typeof CreateUserSchema>;\nexport type UpdateUser = z.infer<typeof UpdateUserSchema>;\nexport type UserResponse = z.infer<typeof UserResponseSchema>;\nexport type ListUsersResponse = z.infer<typeof ListUsersResponseSchema>;\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'packages/models/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/src/common.ts',\n\t\t\tcontent: commonTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/src/user.ts',\n\t\t\tcontent: userTs,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate monorepo root files (pnpm-workspace.yaml, root package.json, etc.)\n */\nexport function generateMonorepoFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n): GeneratedFile[] {\n\tif (!options.monorepo) {\n\t\treturn [];\n\t}\n\n\tconst isFullstack = options.template === 'fullstack';\n\n\t// Root package.json for monorepo\n\tconst rootPackageJson = {\n\t\tname: options.name,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tpackageManager: 'pnpm@10.13.1',\n\t\tscripts: {\n\t\t\tdev: isFullstack ? 'gkm dev' : 'turbo dev',\n\t\t\tbuild: isFullstack ? 'gkm build' : 'turbo build',\n\t\t\ttest: isFullstack ? 'gkm test' : 'turbo test',\n\t\t\t'test:once': isFullstack ? 'gkm test --run' : 'turbo test:once',\n\t\t\ttypecheck: 'turbo typecheck',\n\t\t\tlint: 'biome lint .',\n\t\t\tfmt: 'biome format . --write',\n\t\t\t'fmt:check': 'biome format .',\n\t\t\t...(options.deployTarget === 'dokploy'\n\t\t\t\t? { deploy: 'gkm deploy --provider dokploy --stage production' }\n\t\t\t\t: {}),\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@biomejs/biome': '~2.3.0',\n\t\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t\tturbo: '~2.3.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t\tvitest: '~4.0.0',\n\t\t},\n\t};\n\n\t// pnpm-workspace.yaml - detect folder structure from apiPath\n\tconst apiPathParts = options.apiPath.split('/');\n\tconst appsFolder = apiPathParts[0] || 'apps';\n\n\tconst pnpmWorkspace = `packages:\n - '${appsFolder}/*'\n - 'packages/*'\n`;\n\n\t// Root biome.json\n\tconst biomeConfig = {\n\t\t$schema: 'https://biomejs.dev/schemas/2.3.0/schema.json',\n\t\tvcs: {\n\t\t\tenabled: true,\n\t\t\tclientKind: 'git',\n\t\t\tuseIgnoreFile: true,\n\t\t},\n\t\torganizeImports: {\n\t\t\tenabled: true,\n\t\t},\n\t\tformatter: {\n\t\t\tenabled: true,\n\t\t\tindentStyle: 'space',\n\t\t\tindentWidth: 2,\n\t\t\tlineWidth: 80,\n\t\t},\n\t\tjavascript: {\n\t\t\tformatter: {\n\t\t\t\tquoteStyle: 'single',\n\t\t\t\ttrailingCommas: 'all',\n\t\t\t\tsemicolons: 'always',\n\t\t\t\tarrowParentheses: 'always',\n\t\t\t},\n\t\t},\n\t\tlinter: {\n\t\t\tenabled: true,\n\t\t\trules: {\n\t\t\t\trecommended: true,\n\t\t\t\tcorrectness: {\n\t\t\t\t\tnoUnusedImports: 'error',\n\t\t\t\t\tnoUnusedVariables: 'error',\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\tnoNonNullAssertion: 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tfiles: {\n\t\t\tignore: ['node_modules', 'dist', '.gkm', 'coverage'],\n\t\t},\n\t};\n\n\t// Root turbo.json\n\tconst turboConfig = {\n\t\t$schema: 'https://turbo.build/schema.json',\n\t\ttasks: {\n\t\t\tbuild: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['dist/**'],\n\t\t\t},\n\t\t\tdev: {\n\t\t\t\tcache: false,\n\t\t\t\tpersistent: true,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\tcache: false,\n\t\t\t},\n\t\t\t'test:once': {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['coverage/**'],\n\t\t\t},\n\t\t\ttypecheck: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tfmt: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t},\n\t};\n\n\t// Root .gitignore\n\tconst gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n.gkm/\n\n# Environment\n.env\n.env.local\n.env.*.local\ndocker/.env\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\npnpm-debug.log*\n\n# Test coverage\ncoverage/\n\n# TypeScript cache\n*.tsbuildinfo\n\n# Turbo\n.turbo/\n`;\n\n\t// Root tsconfig.json - base config for all packages\n\t// Using turbo typecheck to run tsc --noEmit in each app/package\n\tconst tsConfig = {\n\t\tcompilerOptions: {\n\t\t\ttarget: 'ES2022',\n\t\t\tmodule: 'NodeNext',\n\t\t\tmoduleResolution: 'NodeNext',\n\t\t\tlib: ['ES2022'],\n\t\t\tstrict: true,\n\t\t\tesModuleInterop: true,\n\t\t\tskipLibCheck: true,\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tresolveJsonModule: true,\n\t\t},\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// Vitest config for workspace\n\tconst vitestConfig = `import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environment: 'node',\n include: ['apps/**/*.{test,spec}.ts', 'packages/**/*.{test,spec}.ts'],\n exclude: ['**/node_modules/**', '**/dist/**'],\n coverage: {\n provider: 'v8',\n reporter: ['text', 'json', 'html'],\n exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'],\n },\n },\n});\n`;\n\n\tconst files: GeneratedFile[] = [\n\t\t{\n\t\t\tpath: 'package.json',\n\t\t\tcontent: `${JSON.stringify(rootPackageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'pnpm-workspace.yaml',\n\t\t\tcontent: pnpmWorkspace,\n\t\t},\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'biome.json',\n\t\t\tcontent: `${JSON.stringify(biomeConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'turbo.json',\n\t\t\tcontent: `${JSON.stringify(turboConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'vitest.config.ts',\n\t\t\tcontent: vitestConfig,\n\t\t},\n\t\t{\n\t\t\tpath: '.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n\n\t// Add workspace config for fullstack template\n\tif (isFullstack) {\n\t\tfiles.push({\n\t\t\tpath: 'gkm.config.ts',\n\t\t\tcontent: generateWorkspaceConfig(options),\n\t\t});\n\t}\n\n\treturn files;\n}\n\n/**\n * Generate gkm.config.ts with defineWorkspace for fullstack template\n */\nfunction generateWorkspaceConfig(options: TemplateOptions): string {\n\tconst { telescope, services, deployTarget, routesStructure } = options;\n\n\t// Get routes glob pattern\n\tconst getRoutesGlob = (): string => {\n\t\tswitch (routesStructure) {\n\t\t\tcase 'centralized-endpoints':\n\t\t\t\treturn './src/endpoints/**/*.ts';\n\t\t\tcase 'centralized-routes':\n\t\t\t\treturn './src/routes/**/*.ts';\n\t\t\tcase 'domain-based':\n\t\t\t\treturn './src/**/routes/*.ts';\n\t\t}\n\t};\n\n\tlet config = `import { defineWorkspace } from '@geekmidas/cli/config';\n\nexport default defineWorkspace({\n name: '${options.name}',\n apps: {\n api: {\n type: 'backend',\n path: 'apps/api',\n port: 3000,\n routes: '${getRoutesGlob()}',\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',`;\n\n\tif (telescope) {\n\t\tconfig += `\n telescope: {\n enabled: true,\n path: '/__telescope',\n },`;\n\t}\n\n\tconfig += `\n openapi: {\n enabled: true,\n },\n },\n auth: {\n type: 'backend',\n path: 'apps/auth',\n port: 3002,\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',\n },\n web: {\n type: 'frontend',\n framework: 'nextjs',\n path: 'apps/web',\n port: 3001,\n dependencies: ['api', 'auth'],\n client: {\n output: './src/api',\n },\n },\n },\n shared: {\n packages: ['packages/*'],\n models: {\n path: 'packages/models',\n schema: 'zod',\n },\n },`;\n\n\t// Add services if any are selected\n\tif (services.db || services.cache || services.mail) {\n\t\tconfig += `\n services: {`;\n\t\tif (services.db) {\n\t\t\tconfig += `\n db: true,`;\n\t\t}\n\t\tif (services.cache) {\n\t\t\tconfig += `\n cache: true,`;\n\t\t}\n\t\tif (services.mail) {\n\t\t\tconfig += `\n mail: true,`;\n\t\t}\n\t\tconfig += `\n },`;\n\t}\n\n\t// Add deploy config if dokploy is selected\n\tif (deployTarget === 'dokploy') {\n\t\tconfig += `\n deploy: {\n default: 'dokploy',\n },`;\n\t}\n\n\tconfig += `\n});\n`;\n\n\treturn config;\n}\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const apiTemplate: TemplateConfig = {\n\tname: 'api',\n\tdescription: 'Full API with auth, database, services',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/events': GEEKMIDAS_VERSIONS['@geekmidas/events'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@geekmidas/services': GEEKMIDAS_VERSIONS['@geekmidas/services'],\n\t\t'@geekmidas/errors': GEEKMIDAS_VERSIONS['@geekmidas/errors'],\n\t\t'@geekmidas/auth': GEEKMIDAS_VERSIONS['@geekmidas/auth'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure, monorepo, name } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Models package import path for monorepo\n\t\tconst modelsImport = monorepo ? `@${name}/models` : null;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based': {\n\t\t\t\t\tconst parts = file.split('/');\n\t\t\t\t\tif (parts.length === 1) {\n\t\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t\t\t}\n\t\t\t\t\treturn `src/${parts[0]}/routes/${parts.slice(1).join('/')}`;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\n\t\t\t// users endpoints\n\t\t\t{\n\t\t\t\tpath: getRoutePath('users/list.ts'),\n\t\t\t\tcontent: modelsImport\n\t\t\t\t\t? `import { e } from '@geekmidas/constructs/endpoints';\nimport { ListUsersResponseSchema } from '${modelsImport}/user';\n\nexport const listUsersEndpoint = e\n .get('/users')\n .output(ListUsersResponseSchema)\n .handle(async () => ({\n users: [\n { id: '1', name: 'Alice' },\n { id: '2', name: 'Bob' },\n ],\n }));\n`\n\t\t\t\t\t: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nconst UserSchema = z.object({\n id: z.string(),\n name: z.string(),\n});\n\nexport const listUsersEndpoint = e\n .get('/users')\n .output(z.object({\n users: z.array(UserSchema),\n }))\n .handle(async () => ({\n users: [\n { id: '1', name: 'Alice' },\n { id: '2', name: 'Bob' },\n ],\n }));\n`,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: getRoutePath('users/get.ts'),\n\t\t\t\tcontent: modelsImport\n\t\t\t\t\t? `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\nimport { UserResponseSchema } from '${modelsImport}/user';\n\nexport const getUserEndpoint = e\n .get('/users/:id')\n .params(z.object({ id: z.string() }))\n .output(UserResponseSchema)\n .handle(async ({ params }) => ({\n id: params.id,\n name: 'Alice',\n email: 'alice@example.com',\n }));\n`\n\t\t\t\t\t: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const getUserEndpoint = e\n .get('/users/:id')\n .params(z.object({ id: z.string() }))\n .output(z.object({\n id: z.string(),\n name: z.string(),\n email: z.string().email(),\n }))\n .handle(async ({ params }) => ({\n id: params.id,\n name: 'Alice',\n email: 'alice@example.com',\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add database service if enabled\n\t\tif (options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/services/database.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\n\n// Define your database schema\nexport interface Database {\n users: {\n id: string;\n name: string;\n email: string;\n created_at: Date;\n };\n}\n\nexport const databaseService = {\n serviceName: 'database' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to database');\n\n const config = envParser\n .create((get) => ({\n url: get('DATABASE_URL').string(),\n }))\n .parse();\n\n const db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: config.url }),\n }),\n });\n\n logger.info('Database connection established');\n return db;\n },\n} satisfies Service<'database', Kysely<Database>>;\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Studio config if enabled (requires database)\n\t\tif (options.studio && options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/studio.ts',\n\t\t\t\tcontent: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport type { Database } from '../services/database.js';\nimport { envParser } from './env.js';\n\n// Parse database config for Studio\nconst studioConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n }))\n .parse();\n\n// Create a Kysely instance for Studio\nconst db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),\n }),\n});\n\nexport const studio = new Studio<Database>({\n monitoring: {\n storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),\n },\n data: {\n db,\n cursor: { field: 'id', direction: Direction.Desc },\n },\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const minimalTemplate: TemplateConfig = {\n\tname: 'minimal',\n\tdescription: 'Basic health endpoint',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add database service if enabled\n\t\tif (options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/services/database.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\n\n// Define your database schema\nexport interface Database {\n // Add your tables here\n}\n\nexport const databaseService = {\n serviceName: 'database' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to database');\n\n const config = envParser\n .create((get) => ({\n url: get('DATABASE_URL').string(),\n }))\n .parse();\n\n const db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: config.url }),\n }),\n });\n\n logger.info('Database connection established');\n return db;\n },\n} satisfies Service<'database', Kysely<Database>>;\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Studio config if enabled (requires database)\n\t\tif (options.studio && options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/studio.ts',\n\t\t\t\tcontent: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport type { Database } from '../services/database.js';\nimport { envParser } from './env.js';\n\n// Parse database config for Studio\nconst studioConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n }))\n .parse();\n\n// Create a Kysely instance for Studio\nconst db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),\n }),\n});\n\nexport const studio = new Studio<Database>({\n monitoring: {\n storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),\n },\n data: {\n db,\n cursor: { field: 'id', direction: Direction.Desc },\n },\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const serverlessTemplate: TemplateConfig = {\n\tname: 'serverless',\n\tdescription: 'AWS Lambda handlers',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/cloud': GEEKMIDAS_VERSIONS['@geekmidas/cloud'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/aws-lambda': '~8.10.92',\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build --provider aws-apigatewayv2',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['dev', 'staging', 'prod']).default('dev'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n region: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n region: process.env.AWS_REGION || 'local',\n }));\n`,\n\t\t\t},\n\n\t\t\t// src/functions/hello.ts\n\t\t\t{\n\t\t\t\tpath: 'src/functions/hello.ts',\n\t\t\t\tcontent: `import { f } from '@geekmidas/constructs/functions';\nimport { z } from 'zod';\n\nexport const helloFunction = f\n .input(z.object({ name: z.string() }))\n .output(z.object({ message: z.string() }))\n .handle(async ({ input }) => ({\n message: \\`Hello, \\${input.name}!\\`,\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\n// Note: For production Lambda, consider using a persistent storage\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 50 }),\n enabled: process.env.STAGE === 'dev',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const workerTemplate: TemplateConfig = {\n\tname: 'worker',\n\tdescription: 'Background job processing',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/events': GEEKMIDAS_VERSIONS['@geekmidas/events'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\n\t\t\t// src/events/types.ts\n\t\t\t{\n\t\t\t\tpath: 'src/events/types.ts',\n\t\t\t\tcontent: `import type { PublishableMessage } from '@geekmidas/events';\n\n// Define your event types here\nexport type AppEvents =\n | PublishableMessage<'user.created', { userId: string; email: string }>\n | PublishableMessage<'user.updated', { userId: string; changes: Record<string, unknown> }>\n | PublishableMessage<'order.placed', { orderId: string; userId: string; total: number }>;\n`,\n\t\t\t},\n\n\t\t\t// src/events/publisher.ts\n\t\t\t{\n\t\t\t\tpath: 'src/events/publisher.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Publisher, type EventPublisher } from '@geekmidas/events';\nimport type { AppEvents } from './types.js';\n\nexport const eventsPublisherService = {\n serviceName: 'events' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to message broker');\n\n const config = envParser\n .create((get) => ({\n url: get('RABBITMQ_URL').string().default('amqp://localhost:5672'),\n }))\n .parse();\n\n const publisher = await Publisher.fromConnectionString<AppEvents>(\n \\`rabbitmq://\\${config.url.replace('amqp://', '')}?exchange=events\\`\n );\n\n logger.info('Message broker connection established');\n return publisher;\n },\n} satisfies Service<'events', EventPublisher<AppEvents>>;\n`,\n\t\t\t},\n\n\t\t\t// src/subscribers/user-events.ts\n\t\t\t{\n\t\t\t\tpath: 'src/subscribers/user-events.ts',\n\t\t\t\tcontent: `import { s } from '@geekmidas/constructs/subscribers';\nimport { eventsPublisherService } from '../events/publisher.js';\n\nexport const userEventsSubscriber = s\n .publisher(eventsPublisherService)\n .subscribe(['user.created', 'user.updated'])\n .handle(async ({ event, logger }) => {\n logger.info({ type: event.type, payload: event.payload }, 'Processing user event');\n\n switch (event.type) {\n case 'user.created':\n // Handle user creation\n logger.info({ userId: event.payload.userId }, 'New user created');\n break;\n case 'user.updated':\n // Handle user update\n logger.info({ userId: event.payload.userId }, 'User updated');\n break;\n }\n });\n`,\n\t\t\t},\n\n\t\t\t// src/crons/cleanup.ts\n\t\t\t{\n\t\t\t\tpath: 'src/crons/cleanup.ts',\n\t\t\t\tcontent: `import { cron } from '@geekmidas/constructs/crons';\n\n// Run every day at midnight\nexport const cleanupCron = cron('0 0 * * *')\n .handle(async ({ logger }) => {\n logger.info('Running cleanup job');\n\n // Add your cleanup logic here\n // e.g., delete old sessions, clean up temp files, etc.\n\n logger.info('Cleanup job completed');\n });\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { apiTemplate } from './api.js';\nimport { minimalTemplate } from './minimal.js';\nimport { serverlessTemplate } from './serverless.js';\nimport { workerTemplate } from './worker.js';\n\n/**\n * OpenAPI output path (fixed, not configurable)\n */\nexport const OPENAPI_OUTPUT_PATH = './.gkm/openapi.ts';\n\n/**\n * Logger implementation type\n */\nexport type LoggerType = 'pino' | 'console';\n\n/**\n * Routes structure pattern\n */\nexport type RoutesStructure =\n\t| 'centralized-endpoints'\n\t| 'centralized-routes'\n\t| 'domain-based';\n\n/**\n * Package manager type\n */\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\n/**\n * Deploy target type\n */\nexport type DeployTarget = 'dokploy' | 'none';\n\n/**\n * Services selection\n */\nexport interface ServicesSelection {\n\tdb: boolean;\n\tcache: boolean;\n\tmail: boolean;\n}\n\n/**\n * Options collected from user prompts\n */\nexport interface TemplateOptions {\n\tname: string;\n\ttemplate: TemplateName;\n\ttelescope: boolean;\n\tdatabase: boolean;\n\tstudio: boolean;\n\tloggerType: LoggerType;\n\troutesStructure: RoutesStructure;\n\tmonorepo: boolean;\n\t/** Path for the API app in monorepo (e.g., 'apps/api') */\n\tapiPath: string;\n\t/** Selected package manager */\n\tpackageManager: PackageManager;\n\t/** Deploy target */\n\tdeployTarget: DeployTarget;\n\t/** Services selection */\n\tservices: ServicesSelection;\n}\n\n/**\n * A file to be generated\n */\nexport interface GeneratedFile {\n\tpath: string;\n\tcontent: string;\n}\n\n/**\n * Template configuration\n */\nexport interface TemplateConfig {\n\tname: TemplateName;\n\tdescription: string;\n\tdependencies: Record<string, string>;\n\tdevDependencies: Record<string, string>;\n\tscripts: Record<string, string>;\n\tfiles: (options: TemplateOptions) => GeneratedFile[];\n}\n\nexport type TemplateName =\n\t| 'minimal'\n\t| 'api'\n\t| 'serverless'\n\t| 'worker'\n\t| 'fullstack';\n\n/**\n * All available templates\n */\nexport const templates: Record<\n\tExclude<TemplateName, 'fullstack'>,\n\tTemplateConfig\n> = {\n\tminimal: minimalTemplate,\n\tapi: apiTemplate,\n\tserverless: serverlessTemplate,\n\tworker: workerTemplate,\n};\n\n/**\n * Template choices for prompts (Story 1.11 simplified to api + fullstack)\n */\nexport const templateChoices = [\n\t{\n\t\ttitle: 'API',\n\t\tvalue: 'api' as TemplateName,\n\t\tdescription: 'Single backend API with endpoints',\n\t},\n\t{\n\t\ttitle: 'Fullstack',\n\t\tvalue: 'fullstack' as TemplateName,\n\t\tdescription: 'Monorepo with API + Next.js + shared models',\n\t},\n];\n\n/**\n * All template choices (includes advanced options)\n */\nexport const allTemplateChoices = [\n\t{\n\t\ttitle: 'Minimal',\n\t\tvalue: 'minimal' as TemplateName,\n\t\tdescription: 'Basic health endpoint',\n\t},\n\t{\n\t\ttitle: 'API',\n\t\tvalue: 'api' as TemplateName,\n\t\tdescription: 'Full API with auth, database, services',\n\t},\n\t{\n\t\ttitle: 'Fullstack',\n\t\tvalue: 'fullstack' as TemplateName,\n\t\tdescription: 'Monorepo with API + Next.js + shared models',\n\t},\n\t{\n\t\ttitle: 'Serverless',\n\t\tvalue: 'serverless' as TemplateName,\n\t\tdescription: 'AWS Lambda handlers',\n\t},\n\t{\n\t\ttitle: 'Worker',\n\t\tvalue: 'worker' as TemplateName,\n\t\tdescription: 'Background job processing',\n\t},\n];\n\n/**\n * Logger type choices for prompts\n */\nexport const loggerTypeChoices = [\n\t{\n\t\ttitle: 'Pino',\n\t\tvalue: 'pino' as LoggerType,\n\t\tdescription: 'Fast JSON logger for production (recommended)',\n\t},\n\t{\n\t\ttitle: 'Console',\n\t\tvalue: 'console' as LoggerType,\n\t\tdescription: 'Simple console logger for development',\n\t},\n];\n\n/**\n * Routes structure choices for prompts\n */\nexport const routesStructureChoices = [\n\t{\n\t\ttitle: 'Centralized (endpoints)',\n\t\tvalue: 'centralized-endpoints' as RoutesStructure,\n\t\tdescription: 'src/endpoints/**/*.ts',\n\t},\n\t{\n\t\ttitle: 'Centralized (routes)',\n\t\tvalue: 'centralized-routes' as RoutesStructure,\n\t\tdescription: 'src/routes/**/*.ts',\n\t},\n\t{\n\t\ttitle: 'Domain-based',\n\t\tvalue: 'domain-based' as RoutesStructure,\n\t\tdescription: 'src/**/routes/*.ts (e.g., src/users/routes/list.ts)',\n\t},\n];\n\n/**\n * Package manager choices for prompts\n */\nexport const packageManagerChoices = [\n\t{\n\t\ttitle: 'pnpm',\n\t\tvalue: 'pnpm' as PackageManager,\n\t\tdescription: 'Fast, disk space efficient (recommended)',\n\t},\n\t{\n\t\ttitle: 'npm',\n\t\tvalue: 'npm' as PackageManager,\n\t\tdescription: 'Node.js default package manager',\n\t},\n\t{\n\t\ttitle: 'yarn',\n\t\tvalue: 'yarn' as PackageManager,\n\t\tdescription: 'Yarn package manager',\n\t},\n\t{\n\t\ttitle: 'bun',\n\t\tvalue: 'bun' as PackageManager,\n\t\tdescription: 'Fast JavaScript runtime and package manager',\n\t},\n];\n\n/**\n * Deploy target choices for prompts\n */\nexport const deployTargetChoices = [\n\t{\n\t\ttitle: 'Dokploy',\n\t\tvalue: 'dokploy' as DeployTarget,\n\t\tdescription: 'Deploy to Dokploy (Docker-based hosting)',\n\t},\n\t{\n\t\ttitle: 'Configure later',\n\t\tvalue: 'none' as DeployTarget,\n\t\tdescription: 'Skip deployment setup for now',\n\t},\n];\n\n/**\n * Services choices for multi-select prompt\n */\nexport const servicesChoices = [\n\t{\n\t\ttitle: 'PostgreSQL',\n\t\tvalue: 'db',\n\t\tdescription: 'PostgreSQL database',\n\t},\n\t{\n\t\ttitle: 'Redis',\n\t\tvalue: 'cache',\n\t\tdescription: 'Redis cache',\n\t},\n\t{\n\t\ttitle: 'Mailpit',\n\t\tvalue: 'mail',\n\t\tdescription: 'Email testing service (dev only)',\n\t},\n];\n\n/**\n * Get a template by name\n */\nexport function getTemplate(name: TemplateName): TemplateConfig | null {\n\tif (name === 'fullstack') {\n\t\t// Fullstack template is handled specially, uses api template as base\n\t\treturn templates.api;\n\t}\n\tconst template = templates[name];\n\tif (!template) {\n\t\tthrow new Error(`Unknown template: ${name}`);\n\t}\n\treturn template;\n}\n\n/**\n * Check if a template is the fullstack monorepo template\n */\nexport function isFullstackTemplate(name: TemplateName): boolean {\n\treturn name === 'fullstack';\n}\n","import {\n\ttype GeneratedFile,\n\tOPENAPI_OUTPUT_PATH,\n\ttype TemplateConfig,\n\ttype TemplateOptions,\n} from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate package.json with dependencies based on template and options\n */\nexport function generatePackageJson(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\tconst { name, telescope, database, studio, monorepo } = options;\n\n\t// Start with template dependencies\n\tconst dependencies = { ...template.dependencies };\n\tconst devDependencies = { ...template.devDependencies };\n\tconst scripts = { ...template.scripts };\n\n\t// Add optional dependencies based on user choices\n\tif (telescope) {\n\t\tdependencies['@geekmidas/telescope'] =\n\t\t\tGEEKMIDAS_VERSIONS['@geekmidas/telescope'];\n\t}\n\n\tif (studio) {\n\t\tdependencies['@geekmidas/studio'] = GEEKMIDAS_VERSIONS['@geekmidas/studio'];\n\t}\n\n\tif (database) {\n\t\tdependencies['@geekmidas/db'] = GEEKMIDAS_VERSIONS['@geekmidas/db'];\n\t\tdependencies.kysely = '~0.28.2';\n\t\tdependencies.pg = '~8.16.0';\n\t\tdevDependencies['@types/pg'] = '~8.15.0';\n\t}\n\n\t// Add zod for schema validation (commonly used)\n\tdependencies.zod = '~4.1.0';\n\n\t// For monorepo apps, remove biome/turbo (they're at root) and lint/fmt scripts\n\tif (monorepo) {\n\t\tdelete devDependencies['@biomejs/biome'];\n\t\tdelete devDependencies.turbo;\n\t\tdelete scripts.lint;\n\t\tdelete scripts.fmt;\n\t\tdelete scripts['fmt:check'];\n\n\t\t// Add models package as dependency\n\t\tdependencies[`@${name}/models`] = 'workspace:*';\n\n\t\t// Remove zod from api package (it's in models)\n\t\tdelete dependencies.zod;\n\t}\n\n\t// Sort dependencies alphabetically\n\tconst sortObject = (obj: Record<string, string>) =>\n\t\tObject.fromEntries(\n\t\t\tObject.entries(obj).sort(([a], [b]) => a.localeCompare(b)),\n\t\t);\n\n\t// For monorepo, derive package name from apiPath (e.g., apps/api -> @name/api)\n\tlet packageName = name;\n\tif (monorepo && options.apiPath) {\n\t\tconst pathParts = options.apiPath.split('/');\n\t\tconst appName = pathParts[pathParts.length - 1] || 'api';\n\t\tpackageName = `@${name}/${appName}`;\n\t}\n\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\texports: {\n\t\t\t'./client': {\n\t\t\t\ttypes: OPENAPI_OUTPUT_PATH,\n\t\t\t\timport: OPENAPI_OUTPUT_PATH,\n\t\t\t},\n\t\t},\n\t\tscripts,\n\t\tdependencies: sortObject(dependencies),\n\t\tdevDependencies: sortObject(devDependencies),\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate source files from template\n */\nexport function generateSourceFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\treturn template.files(options);\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate Next.js web app files for fullstack template\n */\nexport function generateWebAppFiles(options: TemplateOptions): GeneratedFile[] {\n\tif (!options.monorepo || options.template !== 'fullstack') {\n\t\treturn [];\n\t}\n\n\tconst packageName = `@${options.name}/web`;\n\tconst modelsPackage = `@${options.name}/models`;\n\n\t// package.json for web app\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tscripts: {\n\t\t\tdev: 'next dev -p 3001',\n\t\t\tbuild: 'next build',\n\t\t\tstart: 'next start',\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\t[modelsPackage]: 'workspace:*',\n\t\t\t'@geekmidas/client': GEEKMIDAS_VERSIONS['@geekmidas/client'],\n\t\t\t'@tanstack/react-query': '~5.80.0',\n\t\t\tnext: '~16.1.0',\n\t\t\treact: '~19.2.0',\n\t\t\t'react-dom': '~19.2.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@types/node': '~22.0.0',\n\t\t\t'@types/react': '~19.0.0',\n\t\t\t'@types/react-dom': '~19.0.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// next.config.ts\n\tconst nextConfig = `import type { NextConfig } from 'next';\n\nconst nextConfig: NextConfig = {\n output: 'standalone',\n reactStrictMode: true,\n transpilePackages: ['${modelsPackage}'],\n};\n\nexport default nextConfig;\n`;\n\n\t// tsconfig.json for Next.js\n\t// Note: Next.js handles compilation, so noEmit: true\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tlib: ['dom', 'dom.iterable', 'ES2022'],\n\t\t\tallowJs: true,\n\t\t\tskipLibCheck: true,\n\t\t\tstrict: true,\n\t\t\tnoEmit: true,\n\t\t\tesModuleInterop: true,\n\t\t\tmodule: 'ESNext',\n\t\t\tmoduleResolution: 'bundler',\n\t\t\tresolveJsonModule: true,\n\t\t\tisolatedModules: true,\n\t\t\tjsx: 'preserve',\n\t\t\tincremental: true,\n\t\t\tplugins: [\n\t\t\t\t{\n\t\t\t\t\tname: 'next',\n\t\t\t\t},\n\t\t\t],\n\t\t\tpaths: {\n\t\t\t\t'@/*': ['./src/*'],\n\t\t\t\t[`${modelsPackage}`]: ['../../packages/models/src'],\n\t\t\t\t[`${modelsPackage}/*`]: ['../../packages/models/src/*'],\n\t\t\t},\n\t\t\tbaseUrl: '.',\n\t\t},\n\t\tinclude: ['next-env.d.ts', '**/*.ts', '**/*.tsx', '.next/types/**/*.ts'],\n\t\texclude: ['node_modules'],\n\t};\n\n\t// Providers with QueryClient\n\tconst providersTsx = `'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useState } from 'react';\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n const [queryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 60 * 1000,\n },\n },\n }),\n );\n\n return (\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n );\n}\n`;\n\n\t// API client setup\n\tconst apiIndexTs = `import { TypedFetcher } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\n\n// TODO: Run 'gkm openapi' to generate typed paths from your API\n// This is a placeholder that will be replaced by the generated openapi.ts\ninterface paths {\n '/health': {\n get: {\n responses: {\n 200: {\n content: {\n 'application/json': { status: string; timestamp: string };\n };\n };\n };\n };\n };\n '/users': {\n get: {\n responses: {\n 200: {\n content: {\n 'application/json': { users: Array<{ id: string; name: string }> };\n };\n };\n };\n };\n };\n}\n\nconst baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';\n\nconst fetcher = new TypedFetcher<paths>({ baseURL });\n\nconst hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher));\n\nexport const api = Object.assign(fetcher.request.bind(fetcher), hooks);\n`;\n\n\t// App layout\n\tconst layoutTsx = `import type { Metadata } from 'next';\nimport { Providers } from './providers';\n\nexport const metadata: Metadata = {\n title: '${options.name}',\n description: 'Created with gkm init',\n};\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}) {\n return (\n <html lang=\"en\">\n <body>\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n\n\t// Home page with API example\n\tconst pageTsx = `import { api } from '@/api';\n\nexport default async function Home() {\n // Type-safe API call using the generated client\n const health = await api('GET /health').catch(() => null);\n\n return (\n <main style={{ padding: '2rem', fontFamily: 'system-ui' }}>\n <h1>Welcome to ${options.name}</h1>\n\n <section style={{ marginTop: '2rem' }}>\n <h2>API Status</h2>\n {health ? (\n <pre style={{ background: '#f0f0f0', padding: '1rem', borderRadius: '8px' }}>\n {JSON.stringify(health, null, 2)}\n </pre>\n ) : (\n <p>Unable to connect to API</p>\n )}\n </section>\n\n <section style={{ marginTop: '2rem' }}>\n <h2>Next Steps</h2>\n <ul>\n <li>Run <code>gkm openapi</code> to generate typed API client</li>\n <li>Edit <code>apps/web/src/app/page.tsx</code> to customize this page</li>\n <li>Add API routes in <code>apps/api/src/endpoints/</code></li>\n <li>Define shared schemas in <code>packages/models/src/</code></li>\n </ul>\n </section>\n </main>\n );\n}\n`;\n\n\t// Environment file for web app\n\tconst envLocal = `# API URL for client-side requests\nNEXT_PUBLIC_API_URL=http://localhost:3000\n`;\n\n\t// .gitignore for Next.js\n\tconst gitignore = `.next/\nnode_modules/\n.env.local\n*.log\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'apps/web/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/next.config.ts',\n\t\t\tcontent: nextConfig,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/layout.tsx',\n\t\t\tcontent: layoutTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/providers.tsx',\n\t\t\tcontent: providersTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/page.tsx',\n\t\t\tcontent: pageTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/api/index.ts',\n\t\t\tcontent: apiIndexTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/.env.local',\n\t\t\tcontent: envLocal,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\n/**\n * Detect the package manager being used based on lockfiles or npm_config_user_agent\n */\nexport function detectPackageManager(\n\tcwd: string = process.cwd(),\n): PackageManager {\n\t// Check for lockfiles in cwd\n\tif (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n\tif (existsSync(join(cwd, 'yarn.lock'))) return 'yarn';\n\tif (existsSync(join(cwd, 'bun.lockb'))) return 'bun';\n\tif (existsSync(join(cwd, 'package-lock.json'))) return 'npm';\n\n\t// Check npm_config_user_agent (set when running via npx/pnpm dlx/etc)\n\tconst userAgent = process.env.npm_config_user_agent || '';\n\tif (userAgent.includes('pnpm')) return 'pnpm';\n\tif (userAgent.includes('yarn')) return 'yarn';\n\tif (userAgent.includes('bun')) return 'bun';\n\n\treturn 'npm';\n}\n\n/**\n * Validate project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): boolean | string {\n\tif (!name) {\n\t\treturn 'Project name is required';\n\t}\n\n\t// Check for valid npm package name characters\n\tif (!/^[a-z0-9-_@/.]+$/i.test(name)) {\n\t\treturn 'Project name can only contain letters, numbers, hyphens, underscores, @, /, and .';\n\t}\n\n\t// Check for reserved names\n\tconst reserved = ['node_modules', '.git', 'package.json', 'src'];\n\tif (reserved.includes(name.toLowerCase())) {\n\t\treturn `\"${name}\" is a reserved name`;\n\t}\n\n\treturn true;\n}\n\n/**\n * Check if a directory already exists at the target path\n */\nexport function checkDirectoryExists(\n\tname: string,\n\tcwd: string = process.cwd(),\n): boolean | string {\n\tconst targetPath = join(cwd, name);\n\tif (existsSync(targetPath)) {\n\t\treturn `Directory \"${name}\" already exists`;\n\t}\n\treturn true;\n}\n\n/**\n * Get the install command for a package manager\n */\nexport function getInstallCommand(pkgManager: PackageManager): string {\n\tswitch (pkgManager) {\n\t\tcase 'pnpm':\n\t\t\treturn 'pnpm install';\n\t\tcase 'yarn':\n\t\t\treturn 'yarn';\n\t\tcase 'bun':\n\t\t\treturn 'bun install';\n\t\tdefault:\n\t\t\treturn 'npm install';\n\t}\n}\n\n/**\n * Get the dev command for a package manager\n */\nexport function getRunCommand(\n\tpkgManager: PackageManager,\n\tscript: string,\n): string {\n\tswitch (pkgManager) {\n\t\tcase 'pnpm':\n\t\t\treturn `pnpm ${script}`;\n\t\tcase 'yarn':\n\t\t\treturn `yarn ${script}`;\n\t\tcase 'bun':\n\t\t\treturn `bun run ${script}`;\n\t\tdefault:\n\t\t\treturn `npm run ${script}`;\n\t}\n}\n","import { execSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport prompts from 'prompts';\nimport { createStageSecrets } from '../secrets/generator.js';\nimport { getKeyPath } from '../secrets/keystore.js';\nimport { writeStageSecrets } from '../secrets/storage.js';\nimport type { ComposeServiceName } from '../types.js';\nimport { generateAuthAppFiles } from './generators/auth.js';\nimport { generateConfigFiles } from './generators/config.js';\nimport {\n\ttype DatabaseAppConfig,\n\tgenerateDockerFiles,\n} from './generators/docker.js';\nimport { generateEnvFiles } from './generators/env.js';\nimport { generateModelsPackage } from './generators/models.js';\nimport { generateMonorepoFiles } from './generators/monorepo.js';\nimport { generatePackageJson } from './generators/package.js';\nimport { generateSourceFiles } from './generators/source.js';\nimport { generateWebAppFiles } from './generators/web.js';\nimport {\n\ttype DeployTarget,\n\tdeployTargetChoices,\n\tgetTemplate,\n\tisFullstackTemplate,\n\tloggerTypeChoices,\n\ttype PackageManager,\n\tpackageManagerChoices,\n\troutesStructureChoices,\n\ttype ServicesSelection,\n\tservicesChoices,\n\ttype TemplateName,\n\ttype TemplateOptions,\n\ttemplateChoices,\n} from './templates/index.js';\nimport {\n\tcheckDirectoryExists,\n\tdetectPackageManager,\n\tgetInstallCommand,\n\tgetRunCommand,\n\tvalidateProjectName,\n} from './utils.js';\n\nexport interface InitOptions {\n\t/** Project name */\n\tname?: string;\n\t/** Template to use */\n\ttemplate?: TemplateName;\n\t/** Skip dependency installation */\n\tskipInstall?: boolean;\n\t/** Use defaults for all prompts */\n\tyes?: boolean;\n\t/** Force monorepo setup (deprecated, use fullstack template) */\n\tmonorepo?: boolean;\n\t/** API app path in monorepo */\n\tapiPath?: string;\n\t/** Package manager to use */\n\tpm?: PackageManager;\n}\n\n/**\n * Generate a secure random password for database users\n */\nfunction generateDbPassword(): string {\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Generate database URL for an app\n * All apps connect to the same database, but use different users/schemas\n */\nfunction generateDbUrl(\n\tappName: string,\n\tpassword: string,\n\tprojectName: string,\n\thost = 'localhost',\n\tport = 5432,\n): string {\n\tconst userName = appName.replace(/-/g, '_');\n\tconst dbName = `${projectName.replace(/-/g, '_')}_dev`;\n\treturn `postgresql://${userName}:${password}@${host}:${port}/${dbName}`;\n}\n\n/**\n * Main init command - scaffolds a new project\n */\nexport async function initCommand(\n\tprojectName?: string,\n\toptions: InitOptions = {},\n): Promise<void> {\n\tconst cwd = process.cwd();\n\tconst detectedPkgManager = detectPackageManager(cwd);\n\n\t// Handle Ctrl+C gracefully\n\tprompts.override({});\n\tconst onCancel = () => {\n\t\tprocess.exit(0);\n\t};\n\n\t// Gather answers via prompts\n\tconst answers = await prompts(\n\t\t[\n\t\t\t{\n\t\t\t\ttype: projectName || options.name ? null : 'text',\n\t\t\t\tname: 'name',\n\t\t\t\tmessage: 'Project name:',\n\t\t\t\tinitial: 'my-app',\n\t\t\t\tvalidate: (value: string) => {\n\t\t\t\t\tconst nameValid = validateProjectName(value);\n\t\t\t\t\tif (nameValid !== true) return nameValid;\n\t\t\t\t\tconst dirValid = checkDirectoryExists(value, cwd);\n\t\t\t\t\tif (dirValid !== true) return dirValid;\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.template || options.yes ? null : 'select',\n\t\t\t\tname: 'template',\n\t\t\t\tmessage: 'Template:',\n\t\t\t\tchoices: templateChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'multiselect',\n\t\t\t\tname: 'services',\n\t\t\t\tmessage: 'Services (space to select, enter to confirm):',\n\t\t\t\tchoices: servicesChoices.map((c) => ({ ...c, selected: true })),\n\t\t\t\thint: '- Space to select. Return to submit',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'packageManager',\n\t\t\t\tmessage: 'Package manager:',\n\t\t\t\tchoices: packageManagerChoices,\n\t\t\t\tinitial: packageManagerChoices.findIndex(\n\t\t\t\t\t(c) => c.value === detectedPkgManager,\n\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'deployTarget',\n\t\t\t\tmessage: 'Deployment target:',\n\t\t\t\tchoices: deployTargetChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'confirm',\n\t\t\t\tname: 'telescope',\n\t\t\t\tmessage: 'Include Telescope (debugging dashboard)?',\n\t\t\t\tinitial: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'loggerType',\n\t\t\t\tmessage: 'Logger:',\n\t\t\t\tchoices: loggerTypeChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'routesStructure',\n\t\t\t\tmessage: 'Routes structure:',\n\t\t\t\tchoices: routesStructureChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t],\n\t\t{ onCancel },\n\t);\n\n\t// Build final options\n\tconst name = projectName || options.name || answers.name;\n\tif (!name) {\n\t\tconsole.error('Project name is required');\n\t\tprocess.exit(1);\n\t}\n\n\t// Validate name if provided via argument\n\tif (projectName || options.name) {\n\t\tconst nameToValidate = projectName || options.name!;\n\t\tconst nameValid = validateProjectName(nameToValidate);\n\t\tif (nameValid !== true) {\n\t\t\tconsole.error(nameValid);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tconst dirValid = checkDirectoryExists(nameToValidate, cwd);\n\t\tif (dirValid !== true) {\n\t\t\tconsole.error(dirValid);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tconst template: TemplateName = options.template || answers.template || 'api';\n\tconst isFullstack = isFullstackTemplate(template);\n\n\t// For fullstack, force monorepo mode\n\t// For api template, monorepo is optional (via --monorepo flag)\n\tconst monorepo = isFullstack || options.monorepo || false;\n\n\t// Parse services selection\n\tconst servicesArray: string[] = options.yes\n\t\t? ['db', 'cache', 'mail']\n\t\t: answers.services || [];\n\tconst services: ServicesSelection = {\n\t\tdb: servicesArray.includes('db'),\n\t\tcache: servicesArray.includes('cache'),\n\t\tmail: servicesArray.includes('mail'),\n\t};\n\n\tconst pkgManager: PackageManager = options.pm\n\t\t? options.pm\n\t\t: options.yes\n\t\t\t? 'pnpm'\n\t\t\t: (answers.packageManager ?? detectedPkgManager);\n\n\tconst deployTarget: DeployTarget = options.yes\n\t\t? 'dokploy'\n\t\t: (answers.deployTarget ?? 'dokploy');\n\n\tconst database = services.db;\n\tconst templateOptions: TemplateOptions = {\n\t\tname,\n\t\ttemplate,\n\t\ttelescope: options.yes ? true : (answers.telescope ?? true),\n\t\tdatabase,\n\t\tstudio: database,\n\t\tloggerType: options.yes ? 'pino' : (answers.loggerType ?? 'pino'),\n\t\troutesStructure: options.yes\n\t\t\t? 'centralized-endpoints'\n\t\t\t: (answers.routesStructure ?? 'centralized-endpoints'),\n\t\tmonorepo,\n\t\tapiPath: monorepo ? (options.apiPath ?? 'apps/api') : '',\n\t\tpackageManager: pkgManager,\n\t\tdeployTarget,\n\t\tservices,\n\t};\n\n\tconst targetDir = join(cwd, name);\n\tconst baseTemplate = getTemplate(templateOptions.template);\n\n\tconst isMonorepo = templateOptions.monorepo;\n\tconst apiPath = templateOptions.apiPath;\n\n\tconsole.log('\\nš Creating your project...\\n');\n\n\t// Create project directory\n\tawait mkdir(targetDir, { recursive: true });\n\n\t// For monorepo, app files go in the specified apiPath (e.g., apps/api)\n\tconst appDir = isMonorepo ? join(targetDir, apiPath) : targetDir;\n\tif (isMonorepo) {\n\t\tawait mkdir(appDir, { recursive: true });\n\t}\n\n\t// Generate per-app database configs for fullstack template\n\tconst dbApps: DatabaseAppConfig[] = [];\n\tif (isFullstack && services.db) {\n\t\tdbApps.push(\n\t\t\t{ name: 'api', password: generateDbPassword() },\n\t\t\t{ name: 'auth', password: generateDbPassword() },\n\t\t);\n\t}\n\n\t// Collect app files (backend/api)\n\t// Note: Docker files go to root for monorepo, so exclude them here\n\tconst appFiles = baseTemplate\n\t\t? [\n\t\t\t\t...generatePackageJson(templateOptions, baseTemplate),\n\t\t\t\t...generateConfigFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateEnvFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateSourceFiles(templateOptions, baseTemplate),\n\t\t\t\t...(isMonorepo\n\t\t\t\t\t? []\n\t\t\t\t\t: generateDockerFiles(templateOptions, baseTemplate, dbApps)),\n\t\t\t]\n\t\t: [];\n\n\t// For monorepo, docker files go at root level\n\tconst dockerFiles =\n\t\tisMonorepo && baseTemplate\n\t\t\t? generateDockerFiles(templateOptions, baseTemplate, dbApps)\n\t\t\t: [];\n\n\t// Collect root monorepo files (includes packages/models)\n\tconst rootFiles = baseTemplate\n\t\t? [\n\t\t\t\t...generateMonorepoFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateModelsPackage(templateOptions),\n\t\t\t]\n\t\t: [];\n\n\t// Collect web app files for fullstack template\n\tconst webAppFiles = isFullstack ? generateWebAppFiles(templateOptions) : [];\n\n\t// Collect auth app files for fullstack template\n\tconst authAppFiles = isFullstack ? generateAuthAppFiles(templateOptions) : [];\n\n\t// Write root files (for monorepo)\n\tfor (const { path, content } of rootFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write docker files at root for monorepo\n\tfor (const { path, content } of dockerFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write app files (backend)\n\tfor (const { path, content } of appFiles) {\n\t\tconst fullPath = join(appDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write web app files (frontend)\n\tfor (const { path, content } of webAppFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write auth app files (authentication service)\n\tfor (const { path, content } of authAppFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Initialize encrypted secrets for development stage\n\tconsole.log('š Initializing encrypted secrets...\\n');\n\tconst secretServices: ComposeServiceName[] = [];\n\tif (services.db) secretServices.push('postgres');\n\tif (services.cache) secretServices.push('redis');\n\n\tconst devSecrets = createStageSecrets('development', secretServices);\n\n\t// Add common custom secrets\n\tconst customSecrets: Record<string, string> = {\n\t\tNODE_ENV: 'development',\n\t\tPORT: '3000',\n\t\tLOG_LEVEL: 'debug',\n\t\tJWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n\t};\n\n\t// Add per-app database URLs and passwords for fullstack template\n\tif (isFullstack && dbApps.length > 0) {\n\t\tfor (const app of dbApps) {\n\t\t\t// Database URL for the app to use (all apps use same database, different users/schemas)\n\t\t\tconst urlKey = `${app.name.toUpperCase()}_DATABASE_URL`;\n\t\t\tcustomSecrets[urlKey] = generateDbUrl(app.name, app.password, name);\n\n\t\t\t// Database password for docker-compose init script\n\t\t\tconst passwordKey = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\t\tcustomSecrets[passwordKey] = app.password;\n\t\t}\n\n\t\t// Auth service secrets (better-auth)\n\t\tcustomSecrets.AUTH_PORT = '3002';\n\t\tcustomSecrets.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\t\tcustomSecrets.BETTER_AUTH_URL = 'http://localhost:3002';\n\t\tcustomSecrets.BETTER_AUTH_TRUSTED_ORIGINS =\n\t\t\t'http://localhost:3000,http://localhost:3001';\n\t}\n\n\tdevSecrets.custom = customSecrets;\n\n\tawait writeStageSecrets(devSecrets, targetDir);\n\tconst keyPath = getKeyPath('development', name);\n\tconsole.log(` Secrets: .gkm/secrets/development.json (encrypted)`);\n\tconsole.log(` Key: ${keyPath}\\n`);\n\n\t// Install dependencies\n\tif (!options.skipInstall) {\n\t\tconsole.log('\\nš¦ Installing dependencies...\\n');\n\t\ttry {\n\t\t\texecSync(getInstallCommand(pkgManager), {\n\t\t\t\tcwd: targetDir,\n\t\t\t\tstdio: 'inherit',\n\t\t\t});\n\t\t} catch {\n\t\t\tconsole.error('Failed to install dependencies');\n\t\t}\n\n\t\t// Format generated files with biome\n\t\ttry {\n\t\t\texecSync('npx @biomejs/biome format --write --unsafe .', {\n\t\t\t\tcwd: targetDir,\n\t\t\t\tstdio: 'inherit',\n\t\t\t});\n\t\t} catch {\n\t\t\t// Silently ignore format errors\n\t\t}\n\t}\n\n\t// Initialize git repository\n\tconsole.log('\\nš¦ Initializing git repository...\\n');\n\ttry {\n\t\texecSync('git init', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git branch -M main', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git add .', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git commit -m \"š Project created with @geekmidas/toolbox\"', {\n\t\t\tcwd: targetDir,\n\t\t\tstdio: 'pipe',\n\t\t});\n\t\tconsole.log(' Initialized git repository on branch main');\n\t} catch {\n\t\tconsole.log(' Could not initialize git repository (git may not be installed)');\n\t}\n\n\t// Print success message with next steps\n\tprintNextSteps(name, templateOptions, pkgManager);\n}\n\n/**\n * Print success message with next steps\n */\nfunction printNextSteps(\n\tprojectName: string,\n\toptions: TemplateOptions,\n\tpkgManager: PackageManager,\n): void {\n\tconst devCommand = getRunCommand(pkgManager, 'dev');\n\tconst cdCommand = `cd ${projectName}`;\n\n\tconsole.log(`\\n${'ā'.repeat(50)}`);\n\tconsole.log('\\nā
Project created successfully!\\n');\n\n\tconsole.log('Next steps:\\n');\n\tconsole.log(` ${cdCommand}`);\n\n\tif (options.services.db) {\n\t\tconsole.log(` # Start PostgreSQL (if not running)`);\n\t\tconsole.log(` docker compose up -d postgres`);\n\t}\n\n\tconsole.log(` ${devCommand}`);\n\tconsole.log('');\n\n\tif (options.monorepo) {\n\t\tconsole.log('š Project structure:');\n\t\tconsole.log(` ${projectName}/`);\n\t\tconsole.log(` āāā apps/`);\n\t\tconsole.log(` ā āāā api/ # Backend API`);\n\t\tif (isFullstackTemplate(options.template)) {\n\t\t\tconsole.log(` ā āāā auth/ # Auth service (better-auth)`);\n\t\t\tconsole.log(` ā āāā web/ # Next.js frontend`);\n\t\t}\n\t\tconsole.log(` āāā packages/`);\n\t\tconsole.log(` ā āāā models/ # Shared Zod schemas`);\n\t\tconsole.log(` āāā .gkm/secrets/ # Encrypted secrets`);\n\t\tconsole.log(` āāā gkm.config.ts # Workspace config`);\n\t\tconsole.log(` āāā turbo.json # Turbo config`);\n\t\tconsole.log('');\n\t}\n\n\tconsole.log('š Secrets management:');\n\tconsole.log(` gkm secrets:show --stage development # View secrets`);\n\tconsole.log(` gkm secrets:set KEY VALUE --stage development # Add secret`);\n\tconsole.log(\n\t\t` gkm secrets:init --stage production # Create production secrets`,\n\t);\n\tconsole.log('');\n\n\tif (options.deployTarget === 'dokploy') {\n\t\tconsole.log('š Deployment:');\n\t\tconsole.log(` ${getRunCommand(pkgManager, 'deploy')}`);\n\t\tconsole.log('');\n\t}\n\n\tconsole.log('š Documentation: https://docs.geekmidas.dev');\n\tconsole.log('');\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { loadConfig } from '../config';\nimport type { ComposeServiceName, ComposeServicesConfig } from '../types';\nimport { createStageSecrets, rotateServicePassword } from './generator';\nimport {\n\tmaskPassword,\n\treadStageSecrets,\n\tsecretsExist,\n\tsetCustomSecret,\n\twriteStageSecrets,\n} from './storage';\n\nconst logger = console;\n\nexport interface SecretsInitOptions {\n\tstage: string;\n\tforce?: boolean;\n}\n\nexport interface SecretsSetOptions {\n\tstage: string;\n}\n\nexport interface SecretsShowOptions {\n\tstage: string;\n\treveal?: boolean;\n}\n\nexport interface SecretsRotateOptions {\n\tstage: string;\n\tservice?: ComposeServiceName;\n}\n\nexport interface SecretsImportOptions {\n\tstage: string;\n\t/** Merge with existing secrets (default: true) */\n\tmerge?: boolean;\n}\n\n/**\n * Extract service names from compose config.\n */\nexport function getServicesFromConfig(\n\tservices: ComposeServicesConfig | ComposeServiceName[] | undefined,\n): ComposeServiceName[] {\n\tif (!services) {\n\t\treturn [];\n\t}\n\n\tif (Array.isArray(services)) {\n\t\treturn services;\n\t}\n\n\t// Object format - get keys where value is truthy\n\treturn (Object.entries(services) as [ComposeServiceName, unknown][])\n\t\t.filter(([, config]) => config)\n\t\t.map(([name]) => name);\n}\n\n/**\n * Initialize secrets for a stage.\n * Generates secure random passwords for configured services.\n */\nexport async function secretsInitCommand(\n\toptions: SecretsInitOptions,\n): Promise<void> {\n\tconst { stage, force } = options;\n\n\t// Check if secrets already exist\n\tif (!force && secretsExist(stage)) {\n\t\tlogger.error(\n\t\t\t`Secrets already exist for stage \"${stage}\". Use --force to overwrite.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Load config to get services\n\tconst config = await loadConfig();\n\tconst services = getServicesFromConfig(config.docker?.compose?.services);\n\n\tif (services.length === 0) {\n\t\tlogger.warn(\n\t\t\t'No services configured in docker.compose.services. Creating secrets with empty services.',\n\t\t);\n\t}\n\n\t// Generate secrets\n\tconst secrets = createStageSecrets(stage, services);\n\n\t// Write to file\n\tawait writeStageSecrets(secrets);\n\n\tlogger.log(`\\nā Secrets initialized for stage \"${stage}\"`);\n\tlogger.log(` Location: .gkm/secrets/${stage}.json`);\n\tlogger.log('\\n Generated credentials for:');\n\n\tfor (const service of services) {\n\t\tlogger.log(` - ${service}`);\n\t}\n\n\tif (secrets.urls.DATABASE_URL) {\n\t\tlogger.log(`\\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);\n\t}\n\tif (secrets.urls.REDIS_URL) {\n\t\tlogger.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);\n\t}\n\tif (secrets.urls.RABBITMQ_URL) {\n\t\tlogger.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);\n\t}\n\n\tlogger.log(`\\n Use \"gkm secrets:show --stage ${stage}\" to view secrets`);\n\tlogger.log(\n\t\t' Use \"gkm secrets:set <KEY> <VALUE> --stage ' +\n\t\t\tstage +\n\t\t\t'\" to add custom secrets',\n\t);\n}\n\n/**\n * Read all data from stdin.\n */\nasync function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk);\n\t}\n\n\treturn Buffer.concat(chunks).toString('utf-8').trim();\n}\n\n/**\n * Set a custom secret.\n * If value is not provided, reads from stdin.\n */\nexport async function secretsSetCommand(\n\tkey: string,\n\tvalue: string | undefined,\n\toptions: SecretsSetOptions,\n): Promise<void> {\n\tconst { stage } = options;\n\n\t// Read from stdin if value not provided\n\tlet secretValue = value;\n\tif (!secretValue) {\n\t\tif (process.stdin.isTTY) {\n\t\t\tlogger.error(\n\t\t\t\t'No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>',\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t'Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tsecretValue = await readStdin();\n\t\tif (!secretValue) {\n\t\t\tlogger.error('No value received from stdin');\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\ttry {\n\t\tawait setCustomSecret(stage, key, secretValue);\n\t\tlogger.log(`\\nā Secret \"${key}\" set for stage \"${stage}\"`);\n\t} catch (error) {\n\t\tlogger.error(\n\t\t\terror instanceof Error ? error.message : 'Failed to set secret',\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Show secrets for a stage.\n */\nexport async function secretsShowCommand(\n\toptions: SecretsShowOptions,\n): Promise<void> {\n\tconst { stage, reveal } = options;\n\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tlogger.log(`\\nSecrets for stage \"${stage}\":`);\n\tlogger.log(` Created: ${secrets.createdAt}`);\n\tlogger.log(` Updated: ${secrets.updatedAt}`);\n\n\t// Show service credentials\n\tlogger.log('\\nService Credentials:');\n\tfor (const [service, creds] of Object.entries(secrets.services)) {\n\t\tif (creds) {\n\t\t\tlogger.log(`\\n ${service}:`);\n\t\t\tlogger.log(` host: ${creds.host}`);\n\t\t\tlogger.log(` port: ${creds.port}`);\n\t\t\tlogger.log(` username: ${creds.username}`);\n\t\t\tlogger.log(\n\t\t\t\t` password: ${reveal ? creds.password : maskPassword(creds.password)}`,\n\t\t\t);\n\t\t\tif (creds.database) {\n\t\t\t\tlogger.log(` database: ${creds.database}`);\n\t\t\t}\n\t\t\tif (creds.vhost) {\n\t\t\t\tlogger.log(` vhost: ${creds.vhost}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Show URLs\n\tlogger.log('\\nConnection URLs:');\n\tif (secrets.urls.DATABASE_URL) {\n\t\tlogger.log(\n\t\t\t` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`,\n\t\t);\n\t}\n\tif (secrets.urls.REDIS_URL) {\n\t\tlogger.log(\n\t\t\t` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`,\n\t\t);\n\t}\n\tif (secrets.urls.RABBITMQ_URL) {\n\t\tlogger.log(\n\t\t\t` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`,\n\t\t);\n\t}\n\n\t// Show custom secrets\n\tconst customKeys = Object.keys(secrets.custom);\n\tif (customKeys.length > 0) {\n\t\tlogger.log('\\nCustom Secrets:');\n\t\tfor (const [key, value] of Object.entries(secrets.custom)) {\n\t\t\tlogger.log(` ${key}: ${reveal ? value : maskPassword(value)}`);\n\t\t}\n\t}\n\n\tif (!reveal) {\n\t\tlogger.log('\\nUse --reveal to show actual values');\n\t}\n}\n\n/**\n * Rotate passwords for services.\n */\nexport async function secretsRotateCommand(\n\toptions: SecretsRotateOptions,\n): Promise<void> {\n\tconst { stage, service } = options;\n\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tif (service) {\n\t\t// Rotate specific service\n\t\tif (!secrets.services[service]) {\n\t\t\tlogger.error(`Service \"${service}\" not configured in stage \"${stage}\"`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst updated = rotateServicePassword(secrets, service);\n\t\tawait writeStageSecrets(updated);\n\t\tlogger.log(`\\nā Password rotated for ${service} in stage \"${stage}\"`);\n\t} else {\n\t\t// Rotate all services\n\t\tlet updated = secrets;\n\t\tconst services = Object.keys(secrets.services) as ComposeServiceName[];\n\n\t\tfor (const svc of services) {\n\t\t\tupdated = rotateServicePassword(updated, svc);\n\t\t}\n\n\t\tawait writeStageSecrets(updated);\n\t\tlogger.log(\n\t\t\t`\\nā Passwords rotated for all services in stage \"${stage}\": ${services.join(', ')}`,\n\t\t);\n\t}\n\n\tlogger.log(`\\nUse \"gkm secrets:show --stage ${stage}\" to view new values`);\n}\n\n/**\n * Import secrets from a JSON file.\n */\nexport async function secretsImportCommand(\n\tfile: string,\n\toptions: SecretsImportOptions,\n): Promise<void> {\n\tconst { stage, merge = true } = options;\n\n\t// Check if file exists\n\tif (!existsSync(file)) {\n\t\tlogger.error(`File not found: ${file}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// Read and parse JSON file\n\tlet importedSecrets: Record<string, string>;\n\ttry {\n\t\tconst content = await readFile(file, 'utf-8');\n\t\timportedSecrets = JSON.parse(content);\n\n\t\t// Validate it's a flat object with string values\n\t\tif (typeof importedSecrets !== 'object' || importedSecrets === null) {\n\t\t\tthrow new Error('JSON must be an object');\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(importedSecrets)) {\n\t\t\tif (typeof value !== 'string') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for \"${key}\" must be a string, got ${typeof value}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tlogger.error(\n\t\t\t`Failed to parse JSON file: ${error instanceof Error ? error.message : 'Invalid JSON'}`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Check if secrets exist for stage\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Merge or replace custom secrets\n\tconst updatedCustom = merge\n\t\t? { ...secrets.custom, ...importedSecrets }\n\t\t: importedSecrets;\n\n\tconst updated = {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tcustom: updatedCustom,\n\t};\n\n\tawait writeStageSecrets(updated);\n\n\tconst importedCount = Object.keys(importedSecrets).length;\n\tconst totalCount = Object.keys(updatedCustom).length;\n\n\tlogger.log(`\\nā Imported ${importedCount} secrets for stage \"${stage}\"`);\n\n\tif (merge && totalCount > importedCount) {\n\t\tlogger.log(` Total custom secrets: ${totalCount}`);\n\t}\n\n\tlogger.log('\\n Imported keys:');\n\tfor (const key of Object.keys(importedSecrets)) {\n\t\tlogger.log(` - ${key}`);\n\t}\n}\n\n/**\n * Mask password in a URL for display.\n */\nexport function maskUrl(url: string): string {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.password) {\n\t\t\tparsed.password = maskPassword(parsed.password);\n\t\t}\n\t\treturn parsed.toString();\n\t} catch {\n\t\treturn url;\n\t}\n}\n","import { spawn } from 'node:child_process';\nimport { readStageSecrets, toEmbeddableSecrets } from '../secrets/storage';\n\nexport interface TestOptions {\n\t/** Stage to load secrets from (default: development) */\n\tstage?: string;\n\t/** Run tests once without watch mode */\n\trun?: boolean;\n\t/** Enable watch mode */\n\twatch?: boolean;\n\t/** Generate coverage report */\n\tcoverage?: boolean;\n\t/** Open Vitest UI */\n\tui?: boolean;\n\t/** Pattern to filter tests */\n\tpattern?: string;\n}\n\n/**\n * Run tests with secrets loaded from the specified stage.\n * Secrets are decrypted and injected into the environment.\n */\nexport async function testCommand(options: TestOptions = {}): Promise<void> {\n\tconst stage = options.stage ?? 'development';\n\n\tconsole.log(`\\nš§Ŗ Running tests with ${stage} secrets...\\n`);\n\n\t// Load and decrypt secrets\n\tlet envVars: Record<string, string> = {};\n\ttry {\n\t\tconst secrets = await readStageSecrets(stage);\n\t\tif (secrets) {\n\t\t\tenvVars = toEmbeddableSecrets(secrets);\n\t\t\tconsole.log(\n\t\t\t\t` Loaded ${Object.keys(envVars).length} secrets from ${stage}\\n`,\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(` No secrets found for ${stage}, running without secrets\\n`);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof Error && error.message.includes('key not found')) {\n\t\t\tconsole.log(\n\t\t\t\t` Decryption key not found for ${stage}, running without secrets\\n`,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t// Build vitest args\n\tconst args: string[] = [];\n\n\tif (options.run) {\n\t\targs.push('run');\n\t} else if (options.watch) {\n\t\targs.push('--watch');\n\t}\n\n\tif (options.coverage) {\n\t\targs.push('--coverage');\n\t}\n\n\tif (options.ui) {\n\t\targs.push('--ui');\n\t}\n\n\tif (options.pattern) {\n\t\targs.push(options.pattern);\n\t}\n\n\t// Run vitest with secrets in environment\n\tconst vitestProcess = spawn('npx', ['vitest', ...args], {\n\t\tcwd: process.cwd(),\n\t\tstdio: 'inherit',\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...envVars,\n\t\t\t// Ensure NODE_ENV is set to test\n\t\t\tNODE_ENV: 'test',\n\t\t},\n\t});\n\n\t// Wait for vitest to complete\n\treturn new Promise((resolve, reject) => {\n\t\tvitestProcess.on('close', (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Tests failed with exit code ${code}`));\n\t\t\t}\n\t\t});\n\n\t\tvitestProcess.on('error', (error) => {\n\t\t\treject(error);\n\t\t});\n\t});\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json';\nimport { loginCommand, logoutCommand, whoamiCommand } from './auth';\nimport { buildCommand } from './build/index';\nimport { type DeployProvider, deployCommand } from './deploy/index';\nimport { deployInitCommand, deployListCommand } from './deploy/init';\nimport { devCommand } from './dev/index';\nimport { type DockerOptions, dockerCommand } from './docker/index';\nimport { type InitOptions, initCommand } from './init/index';\nimport { openapiCommand } from './openapi';\nimport { generateReactQueryCommand } from './openapi-react-query';\nimport {\n\tsecretsImportCommand,\n\tsecretsInitCommand,\n\tsecretsRotateCommand,\n\tsecretsSetCommand,\n\tsecretsShowCommand,\n} from './secrets';\nimport { type TestOptions, testCommand } from './test/index';\nimport type { ComposeServiceName, LegacyProvider, MainProvider } from './types';\n\nconst program = new Command();\n\nprogram\n\t.name('gkm')\n\t.description('GeekMidas backend framework CLI')\n\t.version(pkg.version)\n\t.option('--cwd <path>', 'Change working directory');\n\nprogram\n\t.command('init')\n\t.description('Scaffold a new project')\n\t.argument('[name]', 'Project name')\n\t.option(\n\t\t'--template <template>',\n\t\t'Project template (minimal, api, serverless, worker)',\n\t)\n\t.option('--skip-install', 'Skip dependency installation', false)\n\t.option('-y, --yes', 'Skip prompts, use defaults', false)\n\t.option('--monorepo', 'Setup as monorepo with packages/models', false)\n\t.option('--api-path <path>', 'API app path in monorepo (default: apps/api)')\n\t.option('--pm <manager>', 'Package manager (pnpm, npm, yarn, bun)')\n\t.action(async (name: string | undefined, options: InitOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait initCommand(name, options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('build')\n\t.description('Build handlers from endpoints, functions, and crons')\n\t.option(\n\t\t'--provider <provider>',\n\t\t'Target provider for generated handlers (aws, server)',\n\t)\n\t.option(\n\t\t'--providers <providers>',\n\t\t'[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n\t)\n\t.option(\n\t\t'--enable-openapi',\n\t\t'Enable OpenAPI documentation generation for server builds',\n\t)\n\t.option('--production', 'Build for production (no dev tools, bundled output)')\n\t.option('--skip-bundle', 'Skip bundling step in production build')\n\t.option('--stage <stage>', 'Inject encrypted secrets for deployment stage')\n\t.action(\n\t\tasync (options: {\n\t\t\tprovider?: string;\n\t\t\tproviders?: string;\n\t\t\tenableOpenapi?: boolean;\n\t\t\tproduction?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tstage?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\t// Handle new single provider option\n\t\t\t\tif (options.provider) {\n\t\t\t\t\tif (!['aws', 'server'].includes(options.provider)) {\n\t\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\t}\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: options.provider as MainProvider,\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Handle legacy providers option\n\t\t\t\telse if (options.providers) {\n\t\t\t\t\tconst providerList = [\n\t\t\t\t\t\t...new Set(options.providers.split(',').map((p) => p.trim())),\n\t\t\t\t\t] as LegacyProvider[];\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tproviders: providerList,\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Default to config-driven build\n\t\t\t\telse {\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('dev')\n\t.description('Start development server with automatic reload')\n\t.option('-p, --port <port>', 'Port to run the development server on')\n\t.option('--entry <file>', 'Entry file to run (bypasses gkm config)')\n\t.option('--watch', 'Watch for file changes (default: true with --entry)')\n\t.option('--no-watch', 'Disable file watching')\n\t.option(\n\t\t'--enable-openapi',\n\t\t'Enable OpenAPI documentation for development server',\n\t\ttrue,\n\t)\n\t.action(\n\t\tasync (options: {\n\t\t\tport?: string;\n\t\t\tentry?: string;\n\t\t\twatch?: boolean;\n\t\t\tenableOpenapi?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tawait devCommand({\n\t\t\t\t\tport: options.port ? Number.parseInt(options.port, 10) : 3000,\n\t\t\t\t\tportExplicit: !!options.port,\n\t\t\t\t\tenableOpenApi: options.enableOpenapi ?? true,\n\t\t\t\t\tentry: options.entry,\n\t\t\t\t\twatch: options.watch,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('test')\n\t.description('Run tests with secrets loaded from environment')\n\t.option('--stage <stage>', 'Stage to load secrets from', 'development')\n\t.option('--run', 'Run tests once without watch mode')\n\t.option('--watch', 'Enable watch mode')\n\t.option('--coverage', 'Generate coverage report')\n\t.option('--ui', 'Open Vitest UI')\n\t.argument('[pattern]', 'Pattern to filter tests')\n\t.action(async (pattern: string | undefined, options: TestOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait testCommand({ ...options, pattern });\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('cron')\n\t.description('Manage cron jobs')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('Cron management - coming soon\\n');\n\t});\n\nprogram\n\t.command('function')\n\t.description('Manage serverless functions')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('Serverless function management - coming soon\\n');\n\t});\n\nprogram\n\t.command('api')\n\t.description('Manage REST API endpoints')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('REST API management - coming soon\\n');\n\t});\n\nprogram\n\t.command('openapi')\n\t.description('Generate OpenAPI specification from endpoints')\n\t.action(async () => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait openapiCommand({});\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('generate:react-query')\n\t.description('Generate React Query hooks from OpenAPI specification')\n\t.option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n\t.option(\n\t\t'--output <path>',\n\t\t'Output file path for generated hooks',\n\t\t'src/api/hooks.ts',\n\t)\n\t.option('--name <name>', 'API name prefix for generated code', 'API')\n\t.action(\n\t\tasync (options: { input?: string; output?: string; name?: string }) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\t\t\t\tawait generateReactQueryCommand(options);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('docker')\n\t.description('Generate Docker deployment files')\n\t.option('--build', 'Build Docker image after generating files')\n\t.option('--push', 'Push image to registry after building')\n\t.option('--tag <tag>', 'Image tag', 'latest')\n\t.option('--registry <registry>', 'Container registry URL')\n\t.option('--slim', 'Use slim Dockerfile (assumes pre-built bundle exists)')\n\t.option('--turbo', 'Use turbo prune for monorepo optimization')\n\t.option('--turbo-package <name>', 'Package name for turbo prune')\n\t.action(async (options: DockerOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait dockerCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('prepack')\n\t.description('Generate Docker files for production deployment')\n\t.option('--build', 'Build Docker image after generating files')\n\t.option('--push', 'Push image to registry after building')\n\t.option('--tag <tag>', 'Image tag', 'latest')\n\t.option('--registry <registry>', 'Container registry URL')\n\t.option('--slim', 'Build locally first, then use slim Dockerfile')\n\t.option('--skip-bundle', 'Skip bundling step (only with --slim)')\n\t.option('--turbo', 'Use turbo prune for monorepo optimization')\n\t.option('--turbo-package <name>', 'Package name for turbo prune')\n\t.action(\n\t\tasync (options: {\n\t\t\tbuild?: boolean;\n\t\t\tpush?: boolean;\n\t\t\ttag?: string;\n\t\t\tregistry?: string;\n\t\t\tslim?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tturbo?: boolean;\n\t\t\tturboPackage?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.slim) {\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: 'server',\n\t\t\t\t\t\tproduction: true,\n\t\t\t\t\t\tskipBundle: options.skipBundle,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait dockerCommand({\n\t\t\t\t\tbuild: options.build,\n\t\t\t\t\tpush: options.push,\n\t\t\t\t\ttag: options.tag,\n\t\t\t\t\tregistry: options.registry,\n\t\t\t\t\tslim: options.slim,\n\t\t\t\t\tturbo: options.turbo,\n\t\t\t\t\tturboPackage: options.turboPackage,\n\t\t\t\t});\n\t\t\t\tif (options.slim) {\n\t\t\t\t} else {\n\t\t\t\t}\n\n\t\t\t\tif (options.build) {\n\t\t\t\t\tconst tag = options.tag ?? 'latest';\n\t\t\t\t\tconst registry = options.registry;\n\t\t\t\t\tconst _imageRef = registry ? `${registry}/api:${tag}` : `api:${tag}`;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Secrets management commands\nprogram\n\t.command('secrets:init')\n\t.description('Initialize secrets for a deployment stage')\n\t.requiredOption('--stage <stage>', 'Stage name (e.g., production, staging)')\n\t.option('--force', 'Overwrite existing secrets')\n\t.action(async (options: { stage: string; force?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsInitCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:set')\n\t.description('Set a custom secret for a stage')\n\t.argument('<key>', 'Secret key (e.g., API_KEY)')\n\t.argument('[value]', 'Secret value (reads from stdin if omitted)')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.action(\n\t\tasync (\n\t\t\tkey: string,\n\t\t\tvalue: string | undefined,\n\t\t\toptions: { stage: string },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\t\t\t\tawait secretsSetCommand(key, value, options);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('secrets:show')\n\t.description('Show secrets for a stage')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option('--reveal', 'Show actual secret values (not masked)')\n\t.action(async (options: { stage: string; reveal?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsShowCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:rotate')\n\t.description('Rotate service passwords')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option(\n\t\t'--service <service>',\n\t\t'Specific service to rotate (postgres, redis, rabbitmq)',\n\t)\n\t.action(async (options: { stage: string; service?: ComposeServiceName }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsRotateCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:import')\n\t.description('Import secrets from a JSON file')\n\t.argument('<file>', 'JSON file path (e.g., secrets.json)')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option('--no-merge', 'Replace all custom secrets instead of merging')\n\t.action(async (file: string, options: { stage: string; merge?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsImportCommand(file, options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\n// Deploy command\nprogram\n\t.command('deploy')\n\t.description('Deploy application to a provider')\n\t.requiredOption(\n\t\t'--provider <provider>',\n\t\t'Deploy provider (docker, dokploy, aws-lambda)',\n\t)\n\t.requiredOption(\n\t\t'--stage <stage>',\n\t\t'Deployment stage (e.g., production, staging)',\n\t)\n\t.option('--tag <tag>', 'Image tag (default: stage-timestamp)')\n\t.option('--skip-push', 'Skip pushing image to registry')\n\t.option('--skip-build', 'Skip build step (use existing build)')\n\t.action(\n\t\tasync (options: {\n\t\t\tprovider: string;\n\t\t\tstage: string;\n\t\t\ttag?: string;\n\t\t\tskipPush?: boolean;\n\t\t\tskipBuild?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tconst validProviders = ['docker', 'dokploy', 'aws-lambda'];\n\t\t\t\tif (!validProviders.includes(options.provider)) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Invalid provider: ${options.provider}\\n` +\n\t\t\t\t\t\t\t`Valid providers: ${validProviders.join(', ')}`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tawait deployCommand({\n\t\t\t\t\tprovider: options.provider as DeployProvider,\n\t\t\t\t\tstage: options.stage,\n\t\t\t\t\ttag: options.tag,\n\t\t\t\t\tskipPush: options.skipPush,\n\t\t\t\t\tskipBuild: options.skipBuild,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(error instanceof Error ? error.message : 'Deploy failed');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Deploy init command - Initialize Dokploy project and application\nprogram\n\t.command('deploy:init')\n\t.description('Initialize Dokploy deployment (create project and application)')\n\t.option(\n\t\t'--endpoint <url>',\n\t\t'Dokploy server URL (uses stored credentials if logged in)',\n\t)\n\t.requiredOption('--project <name>', 'Project name (creates if not exists)')\n\t.requiredOption('--app <name>', 'Application name')\n\t.option('--project-id <id>', 'Use existing project ID instead of creating')\n\t.option('--registry-id <id>', 'Configure registry for the application')\n\t.action(\n\t\tasync (options: {\n\t\t\tendpoint?: string;\n\t\t\tproject: string;\n\t\t\tapp: string;\n\t\t\tprojectId?: string;\n\t\t\tregistryId?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tawait deployInitCommand({\n\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\tprojectName: options.project,\n\t\t\t\t\tappName: options.app,\n\t\t\t\t\tprojectId: options.projectId,\n\t\t\t\t\tregistryId: options.registryId,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: 'Failed to initialize deployment',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Deploy list command - List Dokploy resources\nprogram\n\t.command('deploy:list')\n\t.description('List Dokploy resources (projects, registries)')\n\t.option(\n\t\t'--endpoint <url>',\n\t\t'Dokploy server URL (uses stored credentials if logged in)',\n\t)\n\t.option('--projects', 'List projects')\n\t.option('--registries', 'List registries')\n\t.action(\n\t\tasync (options: {\n\t\t\tendpoint?: string;\n\t\t\tprojects?: boolean;\n\t\t\tregistries?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.projects) {\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'projects',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (options.registries) {\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'registries',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!options.projects && !options.registries) {\n\t\t\t\t\t// Default to listing both\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'projects',\n\t\t\t\t\t});\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'registries',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Failed to list resources',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Login command\nprogram\n\t.command('login')\n\t.description('Authenticate with a deployment service')\n\t.option('--service <service>', 'Service to login to (dokploy)', 'dokploy')\n\t.option('--token <token>', 'API token (will prompt if not provided)')\n\t.option('--endpoint <url>', 'Service endpoint URL')\n\t.action(\n\t\tasync (options: { service: string; token?: string; endpoint?: string }) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.service !== 'dokploy') {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Unknown service: ${options.service}. Supported: dokploy`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tawait loginCommand({\n\t\t\t\t\tservice: options.service as 'dokploy',\n\t\t\t\t\ttoken: options.token,\n\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Failed to login',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Logout command\nprogram\n\t.command('logout')\n\t.description('Remove stored credentials')\n\t.option(\n\t\t'--service <service>',\n\t\t'Service to logout from (dokploy, all)',\n\t\t'dokploy',\n\t)\n\t.action(async (options: { service: string }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\n\t\t\tawait logoutCommand({\n\t\t\t\tservice: options.service as 'dokploy' | 'all',\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\terror instanceof Error ? error.message : 'Failed to logout',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\n// Whoami command\nprogram\n\t.command('whoami')\n\t.description('Show current authentication status')\n\t.action(async () => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\n\t\t\tawait whoamiCommand();\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\terror instanceof Error ? error.message : 'Failed to get status',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["options?: CredentialOptions","credentials: StoredCredentials","token: string","endpoint: string","registryId: string","logger","endpoint: string","token: string","DokployApi","prompt","message: string","resolve","err: Error","char: Buffer","options: LoginOptions","options: LogoutOptions","config: GkmConfig","options: BuildOptions","providers: LegacyProvider[]","config","mainProvider: MainProvider","providersConfig?: ProvidersConfig","providersConfig: ProvidersConfig","config:\n\t\t| boolean\n\t\t| AWSApiGatewayConfig\n\t\t| AWSLambdaConfig\n\t\t| ServerConfig\n\t\t| undefined","context: BuildContext","constructs: GeneratedConstruct<\n\t\t\tCron<any, any, any, any, any, any, any, any>\n\t\t>[]","outputDir: string","options?: GeneratorOptions","logger","cronInfos: CronInfo[]","value: any","sourceFile: string","exportName: string","value: any","context: BuildContext","constructs: GeneratedConstruct<\n\t\t\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>\n\t\t>[]","outputDir: string","options?: GeneratorOptions","logger","functionInfos: FunctionInfo[]","sourceFile: string","exportName: string","value: any","context: BuildContext","constructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","logger","subscriberInfos: SubscriberInfo[]","sourceFile: string","exportName: string","_subscriber: Subscriber<any, any, any, any, any, any>","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","exports","logger","content: string","routes: string | string[] | undefined","workspace: NormalizedWorkspace","appName: string","frontendAppName: string","options: { force?: boolean }","results: ClientGenerationResult[]","dependencies","result: ClientGenerationResult","options: { force?: boolean; silent?: boolean }","allResults: ClientGenerationResult[]","backendAppName: string","dependentApps: string[]","logger","envConfig: string | string[] | undefined","cwd: string","loaded: string[]","missing: string[]","port: number","resolve","err: NodeJS.ErrnoException","preferredPort: number","config: GkmConfig['telescope']","config","isEnabled","telescopeConfig: TelescopeConfig","config: GkmConfig['studio']","studioConfig: StudioConfig","config: GkmConfig['hooks']","cliProduction: boolean","configProduction?: ProductionConfig","config: GkmConfig","options: DevOptions","appRoot: string","secretsRoot: string","workspaceAppName: string | undefined","workspaceAppPort: number | undefined","buildContext: BuildContext","runtime: Runtime","secretsJsonPath: string | undefined","rebuildTimeout: NodeJS.Timeout | null","workspace: NormalizedWorkspace","env: Record<string, string>","conflicts: { app1: string; app2: string; port: number }[]","appName: string","appPath: string","workspaceRoot: string","errors: string[]","warnings: string[]","pkg","results: FrontendValidationResult[]","appName?: string","secrets: Record<string, string>","servicesToStart: string[]","turboFilter: string[]","turboEnv: Record<string, string>","endpointWatcher: ReturnType<typeof chokidar.watch> | null","watchPatterns: string[]","regenerateTimeout: NodeJS.Timeout | null","changedBackends: string[]","config: any","context: BuildContext","provider: LegacyProvider","enableOpenApi: boolean","startDir: string","wrapperPath: string","entryPath: string","secretsJsonPath?: string","appName: string | undefined","watch: boolean","restartTimeout: NodeJS.Timeout | null","requestedPort: number","portExplicit: boolean","telescope: NormalizedTelescopeConfig | undefined","studio: NormalizedStudioConfig | undefined","logger","outputDir: string","routes: RouteInfo[]","functions: FunctionInfo[]","crons: CronInfo[]","subscribers: SubscriberInfo[]","appInfo: ServerAppInfo","logger","options: BuildOptions","config","buildContext: BuildContext","result: BuildResult","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","skipBundle: boolean","stage?: string","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo","masterKey: string | undefined","detectPackageManager","pm: 'pnpm' | 'npm' | 'yarn'","filter?: string","workspace: NormalizedWorkspace","results: AppBuildResult[]","name","resolve","_appName: string","app: NormalizedAppConfig","DEFAULT_SERVICE_IMAGES: Record<ComposeServiceName, string>","DEFAULT_SERVICE_VERSIONS: Record<ComposeServiceName, string>","serviceName: ComposeServiceName","services: ComposeServicesConfig | ComposeServiceName[]","name","config","version","options: ComposeOptions","options: Omit<ComposeOptions, 'services'>","workspace: NormalizedWorkspace","options: WorkspaceComposeOptions","serviceName: 'postgres' | 'redis'","config: boolean | { version?: string; image?: string } | undefined","defaults: Record<'postgres' | 'redis', string>","appName: string","app: NormalizedAppConfig","allApps: [string, NormalizedAppConfig][]","options: {\n\t\tregistry?: string;\n\t\thasPostgres: boolean;\n\t\thasRedis: boolean;\n\t}","dependencies: string[]","dependencies","LOCKFILES: [string, PackageManager][]","detectPackageManager","cwd: string","pm: PackageManager","commands: Record<PackageManager, string>","options: MultiStageDockerfileOptions","options: DockerTemplateOptions","resolveDockerConfig","config: GkmConfig","config","pkg","options: FrontendDockerfileOptions","options: FrontendDockerfileOptions & { healthCheckPath?: string }","logger","options: DockerOptions","config","pkg","result: DockerGeneratedFiles","cwd: string","imageName: string","appPath: string","workspace: NormalizedWorkspace","results: AppDockerResult[]","dockerfile: string","getAppNameFromCwd","pkg","logger","registry: string | undefined","imageName: string","tag: string","imageRef: string","options: DockerDeployOptions","config","config: GkmConfig","logger","getApiToken","createApi","endpoint: string","options: DokployDeployOptions","config","registryOptions: {\n\t\tregistryId?: string;\n\t\tusername?: string;\n\t\tpassword?: string;\n\t\tregistryUrl?: string;\n\t}","envVars: Record<string, string>","logger","providedEndpoint?: string","endpoint: string","config: DokployDeployConfig","cwd: string","config","newContent: string","options: DeployInitOptions","projectId: string","environmentId: string","options: {\n\tendpoint?: string;\n\tresource: 'projects' | 'registries';\n}","logger","message: string","resolve","char: Buffer","api: DokployApi","projectId: string","environmentId: string | undefined","appName: string","services?: DockerComposeServices","existingUrls?: Pick<ServiceUrls, 'DATABASE_URL' | 'REDIS_URL'>","serviceUrls: ServiceUrls","config: GkmConfig","dockerConfig: DockerDeployConfig","stage: string","existingUrls: { DATABASE_URL?: string; REDIS_URL?: string }","config","environmentId","serviceUrls","environmentId: string","applicationId: string","dokployConfig: DokployDeployConfig","workspace: NormalizedWorkspace","options: DeployOptions","name","deployedAppUrls: Record<string, string>","results: AppDeployResult[]","application: DokployApplication | undefined","envVars: string[]","dokployConfig: DokployDeployConfig | undefined","dockerServices: DockerComposeServices | undefined","masterKey: string | undefined","result: DeployResult","SERVICE_DEFAULTS: Record<\n\tComposeServiceName,\n\tOmit<ServiceCredentials, 'password'>\n>","service: ComposeServiceName","services: ComposeServiceName[]","result: StageSecrets['services']","creds: ServiceCredentials","services: StageSecrets['services']","urls: StageSecrets['urls']","stage: string","secrets: StageSecrets","newCreds: ServiceCredentials","require","options: TemplateOptions","options: TemplateOptions","template: TemplateConfig","_template: TemplateConfig","_helpers: ConfigHelperOptions","options: TemplateOptions","template: TemplateConfig","dbApps?: DatabaseAppConfig[]","services: string[]","volumes: string[]","files: GeneratedFile[]","apps: DatabaseAppConfig[]","options: TemplateOptions","_template: TemplateConfig","files: GeneratedFile[]","options: TemplateOptions","options: TemplateOptions","_template: TemplateConfig","files: GeneratedFile[]","config","apiTemplate: TemplateConfig","options: TemplateOptions","name","file: string","files: GeneratedFile[]","minimalTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","serverlessTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","workerTemplate: TemplateConfig","options: TemplateOptions","file: string","files: GeneratedFile[]","OPENAPI_OUTPUT_PATH","templates: Record<\n\tExclude<TemplateName, 'fullstack'>,\n\tTemplateConfig\n>","name: TemplateName","name","options: TemplateOptions","template: TemplateConfig","dependencies","devDependencies","scripts","name","obj: Record<string, string>","OPENAPI_OUTPUT_PATH","options: TemplateOptions","template: TemplateConfig","options: TemplateOptions","cwd: string","name: string","name","pkgManager: PackageManager","script: string","appName: string","password: string","projectName: string","projectName?: string","options: InitOptions","value: string","name","template: TemplateName","servicesArray: string[]","services: ServicesSelection","pkgManager: PackageManager","deployTarget: DeployTarget","templateOptions: TemplateOptions","isMonorepo","dbApps: DatabaseAppConfig[]","secretServices: ComposeServiceName[]","customSecrets: Record<string, string>","options: TemplateOptions","devCommand","services: ComposeServicesConfig | ComposeServiceName[] | undefined","config","name","options: SecretsInitOptions","chunks: Buffer[]","key: string","value: string | undefined","options: SecretsSetOptions","options: SecretsShowOptions","options: SecretsRotateOptions","file: string","options: SecretsImportOptions","importedSecrets: Record<string, string>","url: string","options: TestOptions","envVars: Record<string, string>","args: string[]","resolve","pkg","name: string | undefined","options: InitOptions","name","options: {\n\t\t\tprovider?: string;\n\t\t\tproviders?: string;\n\t\t\tenableOpenapi?: boolean;\n\t\t\tproduction?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tstage?: string;\n\t\t}","options: {\n\t\t\tport?: string;\n\t\t\tentry?: string;\n\t\t\twatch?: boolean;\n\t\t\tenableOpenapi?: boolean;\n\t\t}","pattern: string | undefined","options: TestOptions","options: { input?: string; output?: string; name?: string }","options: DockerOptions","options: {\n\t\t\tbuild?: boolean;\n\t\t\tpush?: boolean;\n\t\t\ttag?: string;\n\t\t\tregistry?: string;\n\t\t\tslim?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tturbo?: boolean;\n\t\t\tturboPackage?: string;\n\t\t}","options: { stage: string; force?: boolean }","key: string","value: string | undefined","options: { stage: string }","options: { stage: string; reveal?: boolean }","options: { stage: string; service?: ComposeServiceName }","file: string","options: { stage: string; merge?: boolean }","options: {\n\t\t\tprovider: string;\n\t\t\tstage: string;\n\t\t\ttag?: string;\n\t\t\tskipPush?: boolean;\n\t\t\tskipBuild?: boolean;\n\t\t}","options: {\n\t\t\tendpoint?: string;\n\t\t\tproject: string;\n\t\t\tapp: string;\n\t\t\tprojectId?: string;\n\t\t\tregistryId?: string;\n\t\t}","options: {\n\t\t\tendpoint?: string;\n\t\t\tprojects?: boolean;\n\t\t\tregistries?: boolean;\n\t\t}","options: { service: string; token?: string; endpoint?: string }","options: { service: string }"],"sources":["../package.json","../src/auth/credentials.ts","../src/auth/index.ts","../src/build/providerResolver.ts","../src/generators/CronGenerator.ts","../src/generators/FunctionGenerator.ts","../src/generators/SubscriberGenerator.ts","../src/workspace/client-generator.ts","../src/dev/index.ts","../src/build/manifests.ts","../src/build/index.ts","../src/docker/compose.ts","../src/docker/templates.ts","../src/docker/index.ts","../src/deploy/docker.ts","../src/deploy/dokploy.ts","../src/deploy/init.ts","../src/deploy/index.ts","../src/secrets/generator.ts","../src/init/versions.ts","../src/init/generators/auth.ts","../src/init/generators/config.ts","../src/init/generators/docker.ts","../src/init/generators/env.ts","../src/init/generators/models.ts","../src/init/generators/monorepo.ts","../src/init/templates/api.ts","../src/init/templates/minimal.ts","../src/init/templates/serverless.ts","../src/init/templates/worker.ts","../src/init/templates/index.ts","../src/init/generators/package.ts","../src/init/generators/source.ts","../src/init/generators/web.ts","../src/init/utils.ts","../src/init/index.ts","../src/secrets/index.ts","../src/test/index.ts","../src/index.ts"],"sourcesContent":["{\n\t\"name\": \"@geekmidas/cli\",\n\t\"version\": \"0.36.0\",\n\t\"description\": \"CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs\",\n\t\"private\": false,\n\t\"type\": \"module\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.mjs\",\n\t\t\t\"require\": \"./dist/index.cjs\"\n\t\t},\n\t\t\"./config\": {\n\t\t\t\"types\": \"./dist/config.d.ts\",\n\t\t\t\"import\": \"./dist/config.mjs\",\n\t\t\t\"require\": \"./dist/config.cjs\"\n\t\t},\n\t\t\"./workspace\": {\n\t\t\t\"types\": \"./dist/workspace/index.d.ts\",\n\t\t\t\"import\": \"./dist/workspace/index.mjs\",\n\t\t\t\"require\": \"./dist/workspace/index.cjs\"\n\t\t},\n\t\t\"./openapi\": {\n\t\t\t\"types\": \"./dist/openapi.d.ts\",\n\t\t\t\"import\": \"./dist/openapi.mjs\",\n\t\t\t\"require\": \"./dist/openapi.cjs\"\n\t\t},\n\t\t\"./openapi-react-query\": {\n\t\t\t\"types\": \"./dist/openapi-react-query.d.ts\",\n\t\t\t\"import\": \"./dist/openapi-react-query.mjs\",\n\t\t\t\"require\": \"./dist/openapi-react-query.cjs\"\n\t\t}\n\t},\n\t\"bin\": {\n\t\t\"gkm\": \"./dist/index.cjs\"\n\t},\n\t\"scripts\": {\n\t\t\"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n\t\t\"test\": \"vitest\",\n\t\t\"test:once\": \"vitest run\",\n\t\t\"test:coverage\": \"vitest run --coverage\"\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/geekmidas/toolbox\"\n\t},\n\t\"dependencies\": {\n\t\t\"@apidevtools/swagger-parser\": \"^10.1.0\",\n\t\t\"@geekmidas/constructs\": \"workspace:~\",\n\t\t\"@geekmidas/envkit\": \"workspace:~\",\n\t\t\"@geekmidas/errors\": \"workspace:~\",\n\t\t\"@geekmidas/logger\": \"workspace:~\",\n\t\t\"@geekmidas/schema\": \"workspace:~\",\n\t\t\"chokidar\": \"~4.0.3\",\n\t\t\"commander\": \"^12.1.0\",\n\t\t\"dotenv\": \"~17.2.3\",\n\t\t\"fast-glob\": \"^3.3.2\",\n\t\t\"hono\": \"~4.8.0\",\n\t\t\"lodash.kebabcase\": \"^4.1.1\",\n\t\t\"openapi-typescript\": \"^7.4.2\",\n\t\t\"prompts\": \"~2.4.2\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@geekmidas/testkit\": \"workspace:*\",\n\t\t\"@types/lodash.kebabcase\": \"^4.1.9\",\n\t\t\"@types/node\": \"~24.9.1\",\n\t\t\"@types/prompts\": \"~2.4.9\",\n\t\t\"typescript\": \"^5.8.2\",\n\t\t\"vitest\": \"^3.2.4\",\n\t\t\"zod\": \"~4.1.13\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"@geekmidas/telescope\": \"workspace:~\"\n\t},\n\t\"peerDependenciesMeta\": {\n\t\t\"@geekmidas/telescope\": {\n\t\t\t\"optional\": true\n\t\t}\n\t}\n}\n","import { existsSync, mkdirSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * Stored credentials for various services\n */\nexport interface StoredCredentials {\n\tdokploy?: {\n\t\t/** API token */\n\t\ttoken: string;\n\t\t/** Dokploy endpoint URL */\n\t\tendpoint: string;\n\t\t/** Registry ID in Dokploy (for Docker image pulls) */\n\t\tregistryId?: string;\n\t\t/** When the credentials were stored */\n\t\tstoredAt: string;\n\t};\n}\n\n/**\n * Options for credential operations\n */\nexport interface CredentialOptions {\n\t/** Root directory for credentials storage (default: user home directory) */\n\troot?: string;\n}\n\n/**\n * Get the path to the credentials directory\n */\nexport function getCredentialsDir(options?: CredentialOptions): string {\n\tconst root = options?.root ?? homedir();\n\treturn join(root, '.gkm');\n}\n\n/**\n * Get the path to the credentials file\n */\nexport function getCredentialsPath(options?: CredentialOptions): string {\n\treturn join(getCredentialsDir(options), 'credentials.json');\n}\n\n/**\n * Ensure the credentials directory exists\n */\nfunction ensureCredentialsDir(options?: CredentialOptions): void {\n\tconst dir = getCredentialsDir(options);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t}\n}\n\n/**\n * Read stored credentials from disk\n */\nexport async function readCredentials(\n\toptions?: CredentialOptions,\n): Promise<StoredCredentials> {\n\tconst path = getCredentialsPath(options);\n\n\tif (!existsSync(path)) {\n\t\treturn {};\n\t}\n\n\ttry {\n\t\tconst content = await readFile(path, 'utf-8');\n\t\treturn JSON.parse(content) as StoredCredentials;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Write credentials to disk\n */\nexport async function writeCredentials(\n\tcredentials: StoredCredentials,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tensureCredentialsDir(options);\n\tconst path = getCredentialsPath(options);\n\n\tawait writeFile(path, JSON.stringify(credentials, null, 2), {\n\t\tmode: 0o600, // Owner read/write only\n\t});\n}\n\n/**\n * Store Dokploy credentials\n */\nexport async function storeDokployCredentials(\n\ttoken: string,\n\tendpoint: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tcredentials.dokploy = {\n\t\ttoken,\n\t\tendpoint,\n\t\tstoredAt: new Date().toISOString(),\n\t};\n\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get stored Dokploy credentials\n */\nexport async function getDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<{\n\ttoken: string;\n\tendpoint: string;\n\tregistryId?: string;\n} | null> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\ttoken: credentials.dokploy.token,\n\t\tendpoint: credentials.dokploy.endpoint,\n\t\tregistryId: credentials.dokploy.registryId,\n\t};\n}\n\n/**\n * Remove Dokploy credentials\n */\nexport async function removeDokployCredentials(\n\toptions?: CredentialOptions,\n): Promise<boolean> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\treturn false;\n\t}\n\n\tdelete credentials.dokploy;\n\tawait writeCredentials(credentials, options);\n\treturn true;\n}\n\n/**\n * Remove all stored credentials\n */\nexport async function removeAllCredentials(\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst path = getCredentialsPath(options);\n\n\tif (existsSync(path)) {\n\t\tawait unlink(path);\n\t}\n}\n\n/**\n * Get Dokploy API token, checking stored credentials first, then environment\n */\nexport async function getDokployToken(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\t// First check environment variable (takes precedence)\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tif (envToken) {\n\t\treturn envToken;\n\t}\n\n\t// Then check stored credentials\n\tconst stored = await getDokployCredentials(options);\n\tif (stored) {\n\t\treturn stored.token;\n\t}\n\n\treturn null;\n}\n\n/**\n * Get Dokploy endpoint from stored credentials\n */\nexport async function getDokployEndpoint(\n\toptions?: CredentialOptions,\n): Promise<string | null> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.endpoint ?? null;\n}\n\n/**\n * Store Dokploy registry ID\n */\nexport async function storeDokployRegistryId(\n\tregistryId: string,\n\toptions?: CredentialOptions,\n): Promise<void> {\n\tconst credentials = await readCredentials(options);\n\n\tif (!credentials.dokploy) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found. Run \"gkm login --service dokploy\" first.',\n\t\t);\n\t}\n\n\tcredentials.dokploy.registryId = registryId;\n\tawait writeCredentials(credentials, options);\n}\n\n/**\n * Get Dokploy registry ID from stored credentials\n */\nexport async function getDokployRegistryId(\n\toptions?: CredentialOptions,\n): Promise<string | undefined> {\n\tconst stored = await getDokployCredentials(options);\n\treturn stored?.registryId ?? undefined;\n}\n","import { stdin as input, stdout as output } from 'node:process';\nimport * as readline from 'node:readline/promises';\nimport {\n\tgetCredentialsPath,\n\tgetDokployCredentials,\n\tremoveDokployCredentials,\n\tstoreDokployCredentials,\n} from './credentials';\n\nconst logger = console;\n\nexport interface LoginOptions {\n\t/** Service to login to */\n\tservice: 'dokploy';\n\t/** API token (if not provided, will prompt) */\n\ttoken?: string;\n\t/** Endpoint URL */\n\tendpoint?: string;\n}\n\nexport interface LogoutOptions {\n\t/** Service to logout from */\n\tservice?: 'dokploy' | 'all';\n}\n\n/**\n * Validate Dokploy token by making a test API call\n */\nexport async function validateDokployToken(\n\tendpoint: string,\n\ttoken: string,\n): Promise<boolean> {\n\tconst { DokployApi } = await import('../deploy/dokploy-api');\n\tconst api = new DokployApi({ baseUrl: endpoint, token });\n\treturn api.validateToken();\n}\n\n/**\n * Prompt for input (handles both TTY and non-TTY)\n */\nasync function prompt(message: string, hidden = false): Promise<string> {\n\tif (!process.stdin.isTTY) {\n\t\tthrow new Error(\n\t\t\t'Interactive input required. Please provide --token option.',\n\t\t);\n\t}\n\n\tif (hidden) {\n\t\t// For hidden input, use raw mode directly without readline\n\t\tprocess.stdout.write(message);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet value = '';\n\n\t\t\tconst cleanup = () => {\n\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\tprocess.stdin.pause();\n\t\t\t\tprocess.stdin.removeListener('data', onData);\n\t\t\t\tprocess.stdin.removeListener('error', onError);\n\t\t\t};\n\n\t\t\tconst onError = (err: Error) => {\n\t\t\t\tcleanup();\n\t\t\t\treject(err);\n\t\t\t};\n\n\t\t\tconst onData = (char: Buffer) => {\n\t\t\t\tconst c = char.toString();\n\n\t\t\t\tif (c === '\\n' || c === '\\r') {\n\t\t\t\t\tcleanup();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tresolve(value);\n\t\t\t\t} else if (c === '\\u0003') {\n\t\t\t\t\t// Ctrl+C\n\t\t\t\t\tcleanup();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t} else if (c === '\\u007F' || c === '\\b') {\n\t\t\t\t\t// Backspace\n\t\t\t\t\tif (value.length > 0) {\n\t\t\t\t\t\tvalue = value.slice(0, -1);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvalue += c;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t\tprocess.stdin.resume();\n\t\t\tprocess.stdin.on('data', onData);\n\t\t\tprocess.stdin.on('error', onError);\n\t\t});\n\t} else {\n\t\t// For visible input, use readline\n\t\tconst rl = readline.createInterface({ input, output });\n\t\ttry {\n\t\t\treturn await rl.question(message);\n\t\t} finally {\n\t\t\trl.close();\n\t\t}\n\t}\n}\n\n/**\n * Login to a service\n */\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n\tconst { service, token: providedToken, endpoint: providedEndpoint } = options;\n\n\tif (service === 'dokploy') {\n\t\tlogger.log('\\nš Logging in to Dokploy...\\n');\n\n\t\t// Get endpoint\n\t\tlet endpoint = providedEndpoint;\n\t\tif (!endpoint) {\n\t\t\tendpoint = await prompt(\n\t\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t\t);\n\t\t}\n\n\t\t// Normalize endpoint (remove trailing slash)\n\t\tendpoint = endpoint.replace(/\\/$/, '');\n\n\t\t// Validate endpoint format\n\t\ttry {\n\t\t\tnew URL(endpoint);\n\t\t} catch {\n\t\t\tlogger.error('Invalid URL format');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Get token\n\t\tlet token = providedToken;\n\t\tif (!token) {\n\t\t\tlogger.log(`\\nGenerate a token at: ${endpoint}/settings/profile\\n`);\n\t\t\ttoken = await prompt('API Token: ', true);\n\t\t}\n\n\t\tif (!token) {\n\t\t\tlogger.error('Token is required');\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Validate token\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(endpoint, token);\n\n\t\tif (!isValid) {\n\t\t\tlogger.error(\n\t\t\t\t'\\nā Invalid credentials. Please check your token and try again.',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\t// Store credentials\n\t\tawait storeDokployCredentials(token, endpoint);\n\n\t\tlogger.log('\\nā Successfully logged in to Dokploy!');\n\t\tlogger.log(` Endpoint: ${endpoint}`);\n\t\tlogger.log(` Credentials stored in: ${getCredentialsPath()}`);\n\t\tlogger.log(\n\t\t\t'\\nYou can now use deploy commands without setting DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n}\n\n/**\n * Logout from a service\n */\nexport async function logoutCommand(options: LogoutOptions): Promise<void> {\n\tconst { service = 'dokploy' } = options;\n\n\tif (service === 'all') {\n\t\tconst dokployRemoved = await removeDokployCredentials();\n\n\t\tif (dokployRemoved) {\n\t\t\tlogger.log('\\nā Logged out from all services');\n\t\t} else {\n\t\t\tlogger.log('\\nNo stored credentials found');\n\t\t}\n\t\treturn;\n\t}\n\n\tif (service === 'dokploy') {\n\t\tconst removed = await removeDokployCredentials();\n\n\t\tif (removed) {\n\t\t\tlogger.log('\\nā Logged out from Dokploy');\n\t\t} else {\n\t\t\tlogger.log('\\nNo Dokploy credentials found');\n\t\t}\n\t}\n}\n\n/**\n * Show current login status\n */\nexport async function whoamiCommand(): Promise<void> {\n\tlogger.log('\\nš Current credentials:\\n');\n\n\tconst dokploy = await getDokployCredentials();\n\n\tif (dokploy) {\n\t\tlogger.log(' Dokploy:');\n\t\tlogger.log(` Endpoint: ${dokploy.endpoint}`);\n\t\tlogger.log(` Token: ${maskToken(dokploy.token)}`);\n\t} else {\n\t\tlogger.log(' Dokploy: Not logged in');\n\t}\n\n\tlogger.log(`\\n Credentials file: ${getCredentialsPath()}`);\n}\n\n/**\n * Mask a token for display\n */\nexport function maskToken(token: string): string {\n\tif (token.length <= 8) {\n\t\treturn '****';\n\t}\n\treturn `${token.slice(0, 4)}...${token.slice(-4)}`;\n}\n\n// Re-export credentials utilities for use in other modules\nexport {\n\tgetDokployCredentials,\n\tgetDokployEndpoint,\n\tgetDokployRegistryId,\n\tgetDokployToken,\n\tstoreDokployCredentials,\n\tstoreDokployRegistryId,\n} from './credentials';\n","import type {\n\tAWSApiGatewayConfig,\n\tAWSLambdaConfig,\n\tBuildOptions,\n\tGkmConfig,\n\tLegacyProvider,\n\tMainProvider,\n\tProvidersConfig,\n\tServerConfig,\n} from '../types';\n\nexport interface ResolvedProviders {\n\tproviders: LegacyProvider[];\n\tenableOpenApi: boolean;\n}\n\n/**\n * Resolves provider configuration from the new simplified system\n * to the internal legacy format for backward compatibility\n */\nexport function resolveProviders(\n\tconfig: GkmConfig,\n\toptions: BuildOptions,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = options.enableOpenApi || false;\n\n\t// Handle legacy providers option (deprecated)\n\tif (options.providers) {\n\t\treturn {\n\t\t\tproviders: options.providers,\n\t\t\tenableOpenApi,\n\t\t};\n\t}\n\n\t// Handle new provider option\n\tif (options.provider) {\n\t\tconst resolvedProviders = resolveMainProvider(\n\t\t\toptions.provider,\n\t\t\tconfig.providers,\n\t\t);\n\t\tproviders.push(...resolvedProviders.providers);\n\t\tenableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;\n\t}\n\t// Default: build all configured providers\n\telse if (config.providers) {\n\t\tconst resolvedProviders = resolveAllConfiguredProviders(config.providers);\n\t\tproviders.push(...resolvedProviders.providers);\n\t\tenableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;\n\t}\n\t// Fallback: use default AWS configuration\n\telse {\n\t\tproviders.push('aws-apigatewayv2', 'aws-lambda');\n\t}\n\n\treturn {\n\t\tproviders: [...new Set(providers)], // Remove duplicates\n\t\tenableOpenApi,\n\t};\n}\n\nfunction resolveMainProvider(\n\tmainProvider: MainProvider,\n\tprovidersConfig?: ProvidersConfig,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = false;\n\n\tif (mainProvider === 'aws') {\n\t\tconst awsConfig = providersConfig?.aws;\n\n\t\t// Resolve API Gateway providers\n\t\tif (awsConfig?.apiGateway) {\n\t\t\tif (isEnabled(awsConfig.apiGateway.v1)) {\n\t\t\t\tproviders.push('aws-apigatewayv1');\n\t\t\t}\n\t\t\tif (isEnabled(awsConfig.apiGateway.v2)) {\n\t\t\t\tproviders.push('aws-apigatewayv2');\n\t\t\t}\n\t\t} else {\n\t\t\t// Default: enable v2 if no specific config\n\t\t\tproviders.push('aws-apigatewayv2');\n\t\t}\n\n\t\t// Resolve Lambda providers\n\t\tif (awsConfig?.lambda) {\n\t\t\tif (\n\t\t\t\tisEnabled(awsConfig.lambda.functions) ||\n\t\t\t\tisEnabled(awsConfig.lambda.crons)\n\t\t\t) {\n\t\t\t\tproviders.push('aws-lambda');\n\t\t\t}\n\t\t} else {\n\t\t\t// Default: enable lambda if no specific config\n\t\t\tproviders.push('aws-lambda');\n\t\t}\n\t} else if (mainProvider === 'server') {\n\t\tproviders.push('server');\n\t\tconst serverConfig = providersConfig?.server;\n\n\t\tif (typeof serverConfig === 'object' && serverConfig?.enableOpenApi) {\n\t\t\tenableOpenApi = true;\n\t\t}\n\t}\n\n\treturn { providers, enableOpenApi };\n}\n\nfunction resolveAllConfiguredProviders(\n\tprovidersConfig: ProvidersConfig,\n): ResolvedProviders {\n\tconst providers: LegacyProvider[] = [];\n\tlet enableOpenApi = false;\n\n\t// AWS providers\n\tif (providersConfig.aws) {\n\t\tconst awsProviders = resolveMainProvider('aws', providersConfig);\n\t\tproviders.push(...awsProviders.providers);\n\t}\n\n\t// Server provider\n\tif (providersConfig.server && isEnabled(providersConfig.server)) {\n\t\tproviders.push('server');\n\t\tif (\n\t\t\ttypeof providersConfig.server === 'object' &&\n\t\t\tprovidersConfig.server.enableOpenApi\n\t\t) {\n\t\t\tenableOpenApi = true;\n\t\t}\n\t}\n\n\treturn { providers, enableOpenApi };\n}\n\nfunction isEnabled(\n\tconfig:\n\t\t| boolean\n\t\t| AWSApiGatewayConfig\n\t\t| AWSLambdaConfig\n\t\t| ServerConfig\n\t\t| undefined,\n): boolean {\n\tif (config === undefined) return false;\n\tif (typeof config === 'boolean') return config;\n\treturn config.enabled !== false; // Default to true if enabled is not explicitly false\n}\n\n/**\n * Gets configuration for a specific AWS service\n */\nexport function getAWSServiceConfig<\n\tT extends AWSApiGatewayConfig | AWSLambdaConfig,\n>(\n\tconfig: GkmConfig,\n\tservice: 'apiGateway' | 'lambda',\n\tsubService?: 'v1' | 'v2' | 'functions' | 'crons',\n): T | undefined {\n\tconst awsConfig = config.providers?.aws;\n\tif (!awsConfig) return undefined;\n\n\tif (service === 'apiGateway' && awsConfig.apiGateway) {\n\t\tconst apiConfig = subService\n\t\t\t? awsConfig.apiGateway[subService as 'v1' | 'v2']\n\t\t\t: undefined;\n\t\treturn typeof apiConfig === 'object' ? (apiConfig as T) : undefined;\n\t}\n\n\tif (service === 'lambda' && awsConfig.lambda) {\n\t\tconst lambdaConfig = subService\n\t\t\t? awsConfig.lambda[subService as 'functions' | 'crons']\n\t\t\t: undefined;\n\t\treturn typeof lambdaConfig === 'object' ? (lambdaConfig as T) : undefined;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Gets server configuration\n */\nexport function getServerConfig(config: GkmConfig): ServerConfig | undefined {\n\tconst serverConfig = config.providers?.server;\n\treturn typeof serverConfig === 'object' ? serverConfig : undefined;\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Cron } from '@geekmidas/constructs/crons';\nimport type { BuildContext } from '../build/types';\nimport type { CronInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class CronGenerator extends ConstructGenerator<\n\tCron<any, any, any, any, any, any, any, any>,\n\tCronInfo[]\n> {\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<\n\t\t\tCron<any, any, any, any, any, any, any, any>\n\t\t>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<CronInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst cronInfos: CronInfo[] = [];\n\n\t\tif (constructs.length === 0 || provider !== 'aws-lambda') {\n\t\t\treturn cronInfos;\n\t\t}\n\n\t\t// Create crons subdirectory\n\t\tconst cronsDir = join(outputDir, 'crons');\n\t\tawait mkdir(cronsDir, { recursive: true });\n\n\t\t// Generate cron handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateCronHandler(\n\t\t\t\tcronsDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tcronInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\tschedule: construct.schedule || 'rate(1 hour)',\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated cron handler: ${key}`);\n\t\t}\n\n\t\treturn cronInfos;\n\t}\n\n\tisConstruct(\n\t\tvalue: any,\n\t): value is Cron<any, any, any, any, any, any, any, any> {\n\t\treturn Cron.isCron(value);\n\t}\n\n\tprivate async generateCronHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\t\tconst relativeLoggerPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.loggerPath,\n\t\t);\n\n\t\tconst content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSScheduledFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Function } from '@geekmidas/constructs/functions';\nimport type { BuildContext } from '../build/types';\nimport type { FunctionInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class FunctionGenerator extends ConstructGenerator<\n\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>,\n\tFunctionInfo[]\n> {\n\tisConstruct(\n\t\tvalue: any,\n\t): value is Function<\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany,\n\t\tany\n\t> {\n\t\treturn Function.isFunction(value);\n\t}\n\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<\n\t\t\tFunction<any, any, any, any, any, any, any, any, any, any, any, any>\n\t\t>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<FunctionInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst functionInfos: FunctionInfo[] = [];\n\n\t\tif (constructs.length === 0 || provider !== 'aws-lambda') {\n\t\t\treturn functionInfos;\n\t\t}\n\n\t\t// Create functions subdirectory\n\t\tconst functionsDir = join(outputDir, 'functions');\n\t\tawait mkdir(functionsDir, { recursive: true });\n\n\t\t// Generate function handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateFunctionHandler(\n\t\t\t\tfunctionsDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tfunctionInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated function handler: ${key}`);\n\t\t}\n\n\t\treturn functionInfos;\n\t}\n\n\tprivate async generateFunctionHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\t\tconst relativeLoggerPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.loggerPath,\n\t\t);\n\n\t\tconst content = `import { AWSLambdaFunction } from '@geekmidas/constructs/functions';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSLambdaFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Subscriber } from '@geekmidas/constructs/subscribers';\nimport type { BuildContext } from '../build/types';\nimport type { SubscriberInfo } from '../types';\nimport {\n\tConstructGenerator,\n\ttype GeneratedConstruct,\n\ttype GeneratorOptions,\n} from './Generator';\n\nexport class SubscriberGenerator extends ConstructGenerator<\n\tSubscriber<any, any, any, any, any, any>,\n\tSubscriberInfo[]\n> {\n\tisConstruct(value: any): value is Subscriber<any, any, any, any, any, any> {\n\t\treturn Subscriber.isSubscriber(value);\n\t}\n\n\tasync build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<SubscriberInfo[]> {\n\t\tconst provider = options?.provider || 'aws-lambda';\n\t\tconst logger = console;\n\t\tconst subscriberInfos: SubscriberInfo[] = [];\n\n\t\tif (provider === 'server') {\n\t\t\t// Generate subscribers.ts for server-based polling (even if empty)\n\t\t\tawait this.generateServerSubscribersFile(outputDir, constructs);\n\n\t\t\tlogger.log(\n\t\t\t\t`Generated server subscribers file with ${constructs.length} subscribers (polling mode)`,\n\t\t\t);\n\n\t\t\t// Return empty array as server subscribers don't have individual handlers\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\tif (constructs.length === 0) {\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\tif (provider !== 'aws-lambda') {\n\t\t\treturn subscriberInfos;\n\t\t}\n\n\t\t// Create subscribers subdirectory\n\t\tconst subscribersDir = join(outputDir, 'subscribers');\n\t\tawait mkdir(subscribersDir, { recursive: true });\n\n\t\t// Generate subscriber handlers\n\t\tfor (const { key, construct, path } of constructs) {\n\t\t\tconst handlerFile = await this.generateSubscriberHandler(\n\t\t\t\tsubscribersDir,\n\t\t\t\tpath.relative,\n\t\t\t\tkey,\n\t\t\t\tconstruct,\n\t\t\t\tcontext,\n\t\t\t);\n\n\t\t\tsubscriberInfos.push({\n\t\t\t\tname: key,\n\t\t\t\thandler: relative(process.cwd(), handlerFile).replace(\n\t\t\t\t\t/\\.ts$/,\n\t\t\t\t\t'.handler',\n\t\t\t\t),\n\t\t\t\tsubscribedEvents: construct.subscribedEvents || [],\n\t\t\t\ttimeout: construct.timeout,\n\t\t\t\tmemorySize: construct.memorySize,\n\t\t\t\tenvironment: await construct.getEnvironment(),\n\t\t\t});\n\n\t\t\tlogger.log(`Generated subscriber handler: ${key}`);\n\t\t}\n\n\t\treturn subscriberInfos;\n\t}\n\n\tprivate async generateSubscriberHandler(\n\t\toutputDir: string,\n\t\tsourceFile: string,\n\t\texportName: string,\n\t\t_subscriber: Subscriber<any, any, any, any, any, any>,\n\t\tcontext: BuildContext,\n\t): Promise<string> {\n\t\tconst handlerFileName = `${exportName}.ts`;\n\t\tconst handlerPath = join(outputDir, handlerFileName);\n\n\t\tconst relativePath = relative(dirname(handlerPath), sourceFile);\n\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\tconst relativeEnvParserPath = relative(\n\t\t\tdirname(handlerPath),\n\t\t\tcontext.envParserPath,\n\t\t);\n\n\t\tconst content = `import { AWSLambdaSubscriber } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\n\nconst adapter = new AWSLambdaSubscriber(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n\t\tawait writeFile(handlerPath, content);\n\t\treturn handlerPath;\n\t}\n\n\tprivate async generateServerSubscribersFile(\n\t\toutputDir: string,\n\t\tsubscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\t): Promise<string> {\n\t\t// Ensure output directory exists\n\t\tawait mkdir(outputDir, { recursive: true });\n\n\t\tconst subscribersFileName = 'subscribers.ts';\n\t\tconst subscribersPath = join(outputDir, subscribersFileName);\n\n\t\t// Group imports by file\n\t\tconst importsByFile = new Map<string, string[]>();\n\n\t\tfor (const { path, key } of subscribers) {\n\t\t\tconst relativePath = relative(dirname(subscribersPath), path.relative);\n\t\t\tconst importPath = relativePath.replace(/\\.ts$/, '.js');\n\n\t\t\tif (!importsByFile.has(importPath)) {\n\t\t\t\timportsByFile.set(importPath, []);\n\t\t\t}\n\t\t\timportsByFile.get(importPath)?.push(key);\n\t\t}\n\n\t\t// Generate import statements\n\t\tconst imports = Array.from(importsByFile.entries())\n\t\t\t.map(\n\t\t\t\t([importPath, exports]) =>\n\t\t\t\t\t`import { ${exports.join(', ')} } from '${importPath}';`,\n\t\t\t)\n\t\t\t.join('\\n');\n\n\t\tconst allExportNames = subscribers.map(({ key }) => key);\n\n\t\tconst content = `/**\n * Generated subscribers setup\n *\n * ā ļø WARNING: This is for LOCAL DEVELOPMENT ONLY\n * This uses event polling which is not suitable for production.\n *\n * For production, use AWS Lambda with SQS/SNS event source mappings.\n * Lambda automatically:\n * - Scales based on queue depth\n * - Handles batch processing and retries\n * - Manages dead letter queues\n * - Provides better cost optimization\n *\n * This polling implementation is useful for:\n * - Local development and testing\n * - Understanding event flow without Lambda deployment\n *\n * Supported connection strings:\n * - sqs://region/account-id/queue-name (SQS queue)\n * - sns://region/account-id/topic-name (SNS topic)\n * - rabbitmq://host:port/queue-name (RabbitMQ)\n * - basic://in-memory (In-memory for testing)\n */\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { EventConnectionFactory, Subscriber } from '@geekmidas/events';\nimport type { EventConnection, EventSubscriber } from '@geekmidas/events';\nimport { ServiceDiscovery } from '@geekmidas/services';\n${imports}\n\nconst subscribers = [\n ${allExportNames.join(',\\n ')}\n];\n\nconst activeSubscribers: EventSubscriber<any>[] = [];\n\nexport async function setupSubscribers(\n envParser: EnvironmentParser<any>,\n logger: Logger,\n): Promise<void> {\n logger.info('Setting up subscribers in polling mode (local development)');\n\n const config = envParser.create((get) => ({\n connectionString: get('EVENT_SUBSCRIBER_CONNECTION_STRING').string().optional(),\n })).parse();\n\n if (!config.connectionString) {\n logger.warn('EVENT_SUBSCRIBER_CONNECTION_STRING not configured, skipping subscriber setup');\n return;\n }\n\n const serviceDiscovery = ServiceDiscovery.getInstance(envParser);\n\n // Create connection once, outside the loop (more efficient)\n // EventConnectionFactory automatically determines the right connection type\n let connection: EventConnection;\n try {\n connection = await EventConnectionFactory.fromConnectionString(config.connectionString);\n\n const connectionType = new URL(config.connectionString).protocol.replace(':', '');\n logger.info({ connectionType }, 'Created shared event connection');\n } catch (error) {\n logger.error({ error }, 'Failed to create event connection');\n return;\n }\n\n for (const subscriber of subscribers) {\n try {\n // Create subscriber from shared connection\n const eventSubscriber = await Subscriber.fromConnection(connection);\n\n // Register services\n const services = subscriber.services.length > 0\n ? await serviceDiscovery.register(subscriber.services)\n : {};\n\n // Subscribe to events\n const subscribedEvents = subscriber.subscribedEvents || [];\n\n if (subscribedEvents.length === 0) {\n logger.warn({ subscriber: subscriber.constructor.name }, 'Subscriber has no subscribed events, skipping');\n continue;\n }\n\n await eventSubscriber.subscribe(subscribedEvents, async (event) => {\n try {\n // Process single event (batch of 1)\n await subscriber.handler({\n events: [event],\n services: services as any,\n logger: subscriber.logger,\n });\n\n logger.debug({ eventType: event.type }, 'Successfully processed event');\n } catch (error) {\n logger.error({ error, event }, 'Failed to process event');\n // Event will become visible again for retry\n }\n });\n\n activeSubscribers.push(eventSubscriber);\n\n logger.info(\n {\n events: subscribedEvents,\n },\n 'Subscriber started polling'\n );\n } catch (error) {\n logger.error({ error, subscriber: subscriber.constructor.name }, 'Failed to setup subscriber');\n }\n }\n\n // Setup graceful shutdown\n const shutdown = () => {\n logger.info('Stopping all subscribers');\n for (const eventSubscriber of activeSubscribers) {\n connection.stop();\n }\n };\n\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n}\n`;\n\n\t\tawait writeFile(subscribersPath, content);\n\t\treturn subscribersPath;\n\t}\n}\n","import { createHash } from 'node:crypto';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { EndpointGenerator } from '../generators/EndpointGenerator.js';\nimport { OpenApiTsGenerator } from '../generators/OpenApiTsGenerator.js';\nimport type { NormalizedWorkspace } from './types.js';\n\nconst logger = console;\n\n/**\n * Result of generating a client for a frontend app.\n */\nexport interface ClientGenerationResult {\n\tfrontendApp: string;\n\tbackendApp: string;\n\toutputPath: string;\n\tendpointCount: number;\n\tgenerated: boolean;\n\treason?: string;\n}\n\n/**\n * Cache of OpenAPI spec hashes to detect changes.\n */\nconst specHashCache = new Map<string, string>();\n\n/**\n * Calculate hash of content for change detection.\n */\nfunction hashContent(content: string): string {\n\treturn createHash('sha256').update(content).digest('hex').slice(0, 16);\n}\n\n/**\n * Normalize routes to an array of patterns.\n * @internal Exported for use in dev command\n */\nexport function normalizeRoutes(\n\troutes: string | string[] | undefined,\n): string[] {\n\tif (!routes) return [];\n\treturn Array.isArray(routes) ? routes : [routes];\n}\n\n/**\n * Get the first routes pattern as a string (for simple cases).\n * @internal Exported for use in dev command\n */\nexport function getFirstRoute(\n\troutes: string | string[] | undefined,\n): string | null {\n\tconst normalized = normalizeRoutes(routes);\n\treturn normalized[0] || null;\n}\n\n/**\n * Generate OpenAPI spec for a backend app.\n * Returns the spec content and endpoint count.\n */\nexport async function generateBackendOpenApi(\n\tworkspace: NormalizedWorkspace,\n\tappName: string,\n): Promise<{ content: string; endpointCount: number } | null> {\n\tconst app = workspace.apps[appName];\n\tif (!app || app.type !== 'backend' || !app.routes) {\n\t\treturn null;\n\t}\n\n\tconst appPath = join(workspace.root, app.path);\n\tconst routesPatterns = normalizeRoutes(app.routes);\n\n\tif (routesPatterns.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Load endpoints from all routes patterns\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst allLoadedEndpoints = [];\n\n\tfor (const pattern of routesPatterns) {\n\t\tconst fullPattern = join(appPath, pattern);\n\t\tconst loaded = await endpointGenerator.load(fullPattern);\n\t\tallLoadedEndpoints.push(...loaded);\n\t}\n\n\tconst loadedEndpoints = allLoadedEndpoints;\n\n\tif (loadedEndpoints.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst endpoints = loadedEndpoints.map(({ construct }) => construct);\n\n\tconst tsGenerator = new OpenApiTsGenerator();\n\tconst content = await tsGenerator.generate(endpoints, {\n\t\ttitle: `${appName} API`,\n\t\tversion: '1.0.0',\n\t\tdescription: `Auto-generated API client for ${appName}`,\n\t});\n\n\treturn { content, endpointCount: loadedEndpoints.length };\n}\n\n/**\n * Generate client for a frontend app from its backend dependencies.\n * Only regenerates if the OpenAPI spec has changed.\n */\nexport async function generateClientForFrontend(\n\tworkspace: NormalizedWorkspace,\n\tfrontendAppName: string,\n\toptions: { force?: boolean } = {},\n): Promise<ClientGenerationResult[]> {\n\tconst results: ClientGenerationResult[] = [];\n\tconst frontendApp = workspace.apps[frontendAppName];\n\n\tif (!frontendApp || frontendApp.type !== 'frontend') {\n\t\treturn results;\n\t}\n\n\tconst dependencies = frontendApp.dependencies || [];\n\tconst backendDeps = dependencies.filter((dep) => {\n\t\tconst depApp = workspace.apps[dep];\n\t\treturn depApp?.type === 'backend' && depApp.routes;\n\t});\n\n\tif (backendDeps.length === 0) {\n\t\treturn results;\n\t}\n\n\t// Determine output directory\n\tconst clientOutput = frontendApp.client?.output || 'src/api';\n\tconst frontendPath = join(workspace.root, frontendApp.path);\n\tconst outputDir = join(frontendPath, clientOutput);\n\n\tfor (const backendAppName of backendDeps) {\n\t\tconst result: ClientGenerationResult = {\n\t\t\tfrontendApp: frontendAppName,\n\t\t\tbackendApp: backendAppName,\n\t\t\toutputPath: '',\n\t\t\tendpointCount: 0,\n\t\t\tgenerated: false,\n\t\t};\n\n\t\ttry {\n\t\t\t// Generate OpenAPI spec for backend\n\t\t\tconst spec = await generateBackendOpenApi(workspace, backendAppName);\n\n\t\t\tif (!spec) {\n\t\t\t\tresult.reason = 'No endpoints found in backend';\n\t\t\t\tresults.push(result);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.endpointCount = spec.endpointCount;\n\n\t\t\t// Check if spec has changed (unless force)\n\t\t\tconst cacheKey = `${backendAppName}:${frontendAppName}`;\n\t\t\tconst newHash = hashContent(spec.content);\n\t\t\tconst oldHash = specHashCache.get(cacheKey);\n\n\t\t\tif (!options.force && oldHash === newHash) {\n\t\t\t\tresult.reason = 'No schema changes detected';\n\t\t\t\tresults.push(result);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Generate client file\n\t\t\tawait mkdir(outputDir, { recursive: true });\n\n\t\t\t// For single dependency, use openapi.ts; for multiple, use {backend}-api.ts\n\t\t\tconst fileName =\n\t\t\t\tbackendDeps.length === 1 ? 'openapi.ts' : `${backendAppName}-api.ts`;\n\t\t\tconst outputPath = join(outputDir, fileName);\n\n\t\t\t// Add header comment with backend reference\n\t\t\tconst backendRelPath = relative(\n\t\t\t\tdirname(outputPath),\n\t\t\t\tjoin(workspace.root, workspace.apps[backendAppName]!.path),\n\t\t\t);\n\n\t\t\tconst clientContent = `/**\n * Auto-generated API client for ${backendAppName}\n * Generated from: ${backendRelPath}\n *\n * DO NOT EDIT - This file is automatically regenerated when backend schemas change.\n */\n\n${spec.content}\n`;\n\n\t\t\tawait writeFile(outputPath, clientContent);\n\n\t\t\t// Update cache\n\t\t\tspecHashCache.set(cacheKey, newHash);\n\n\t\t\tresult.outputPath = outputPath;\n\t\t\tresult.generated = true;\n\t\t\tresults.push(result);\n\t\t} catch (error) {\n\t\t\tresult.reason = `Error: ${(error as Error).message}`;\n\t\t\tresults.push(result);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Generate clients for all frontend apps in the workspace.\n */\nexport async function generateAllClients(\n\tworkspace: NormalizedWorkspace,\n\toptions: { force?: boolean; silent?: boolean } = {},\n): Promise<ClientGenerationResult[]> {\n\tconst log = options.silent ? () => {} : logger.log.bind(logger);\n\tconst allResults: ClientGenerationResult[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend' && app.dependencies.length > 0) {\n\t\t\tconst results = await generateClientForFrontend(workspace, appName, {\n\t\t\t\tforce: options.force,\n\t\t\t});\n\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.generated) {\n\t\t\t\t\tlog(\n\t\t\t\t\t\t`š¦ Generated client for ${result.frontendApp} from ${result.backendApp} (${result.endpointCount} endpoints)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tallResults.push(result);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn allResults;\n}\n\n/**\n * Check if a file path matches endpoint patterns that could affect OpenAPI schema.\n * Returns true for changes that should trigger client regeneration.\n */\nexport function shouldRegenerateClient(\n\tfilePath: string,\n\troutesPattern: string,\n): boolean {\n\t// Normalize path separators\n\tconst normalizedPath = filePath.replace(/\\\\/g, '/');\n\tconst normalizedPattern = routesPattern.replace(/\\\\/g, '/');\n\n\t// Check if the file matches the routes pattern\n\t// This is a simple check - the file should be within the routes directory\n\tconst patternDir = normalizedPattern.split('*')[0] || '';\n\n\tif (!normalizedPath.includes(patternDir.replace('./', ''))) {\n\t\treturn false;\n\t}\n\n\t// Check file extension - only TypeScript endpoint files\n\tif (!normalizedPath.endsWith('.ts') && !normalizedPath.endsWith('.tsx')) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Get backend apps that a frontend depends on.\n */\nexport function getBackendDependencies(\n\tworkspace: NormalizedWorkspace,\n\tfrontendAppName: string,\n): string[] {\n\tconst frontendApp = workspace.apps[frontendAppName];\n\tif (!frontendApp || frontendApp.type !== 'frontend') {\n\t\treturn [];\n\t}\n\n\treturn frontendApp.dependencies.filter((dep) => {\n\t\tconst depApp = workspace.apps[dep];\n\t\treturn depApp?.type === 'backend' && depApp.routes;\n\t});\n}\n\n/**\n * Get frontend apps that depend on a backend app.\n */\nexport function getDependentFrontends(\n\tworkspace: NormalizedWorkspace,\n\tbackendAppName: string,\n): string[] {\n\tconst dependentApps: string[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend' && app.dependencies.includes(backendAppName)) {\n\t\t\tdependentApps.push(appName);\n\t\t}\n\t}\n\n\treturn dependentApps;\n}\n\n/**\n * Clear the spec hash cache (useful for testing).\n */\nexport function clearSpecHashCache(): void {\n\tspecHashCache.clear();\n}\n","import { type ChildProcess, execSync, spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { dirname, join, resolve } from 'node:path';\nimport chokidar from 'chokidar';\nimport { config as dotenvConfig } from 'dotenv';\nimport fg from 'fast-glob';\nimport { resolveProviders } from '../build/providerResolver';\nimport type {\n\tBuildContext,\n\tNormalizedHooksConfig,\n\tNormalizedProductionConfig,\n\tNormalizedStudioConfig,\n\tNormalizedTelescopeConfig,\n} from '../build/types';\nimport {\n\tgetAppNameFromCwd,\n\tloadAppConfig,\n\tloadWorkspaceConfig,\n\tparseModuleConfig,\n} from '../config';\nimport {\n\tCronGenerator,\n\tEndpointGenerator,\n\tFunctionGenerator,\n\tSubscriberGenerator,\n} from '../generators';\nimport {\n\tgenerateOpenApi,\n\tOPENAPI_OUTPUT_PATH,\n\tresolveOpenApiConfig,\n} from '../openapi';\nimport {\n\treadStageSecrets,\n\tsecretsExist,\n\ttoEmbeddableSecrets,\n} from '../secrets/storage.js';\nimport type {\n\tGkmConfig,\n\tLegacyProvider,\n\tProductionConfig,\n\tRuntime,\n\tServerConfig,\n\tStudioConfig,\n\tTelescopeConfig,\n} from '../types';\nimport {\n\tgenerateAllClients,\n\tgenerateClientForFrontend,\n\tgetDependentFrontends,\n\tnormalizeRoutes,\n} from '../workspace/client-generator.js';\nimport {\n\tgetAppBuildOrder,\n\tgetDependencyEnvVars,\n\ttype NormalizedWorkspace,\n} from '../workspace/index.js';\n\nconst logger = console;\n\n/**\n * Load environment files\n * @internal Exported for testing\n */\nexport function loadEnvFiles(\n\tenvConfig: string | string[] | undefined,\n\tcwd: string = process.cwd(),\n): { loaded: string[]; missing: string[] } {\n\tconst loaded: string[] = [];\n\tconst missing: string[] = [];\n\n\t// Normalize to array\n\tconst envFiles = envConfig\n\t\t? Array.isArray(envConfig)\n\t\t\t? envConfig\n\t\t\t: [envConfig]\n\t\t: ['.env'];\n\n\t// Load each env file in order (later files override earlier)\n\tfor (const envFile of envFiles) {\n\t\tconst envPath = resolve(cwd, envFile);\n\t\tif (existsSync(envPath)) {\n\t\t\tdotenvConfig({ path: envPath, override: true, quiet: true });\n\t\t\tloaded.push(envFile);\n\t\t} else if (envConfig) {\n\t\t\t// Only report as missing if explicitly configured\n\t\t\tmissing.push(envFile);\n\t\t}\n\t}\n\n\treturn { loaded, missing };\n}\n\n/**\n * Check if a port is available\n * @internal Exported for testing\n */\nexport async function isPortAvailable(port: number): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst server = createServer();\n\n\t\tserver.once('error', (err: NodeJS.ErrnoException) => {\n\t\t\tif (err.code === 'EADDRINUSE') {\n\t\t\t\tresolve(false);\n\t\t\t} else {\n\t\t\t\tresolve(false);\n\t\t\t}\n\t\t});\n\n\t\tserver.once('listening', () => {\n\t\t\tserver.close();\n\t\t\tresolve(true);\n\t\t});\n\n\t\tserver.listen(port);\n\t});\n}\n\n/**\n * Find an available port starting from the preferred port\n * @internal Exported for testing\n */\nexport async function findAvailablePort(\n\tpreferredPort: number,\n\tmaxAttempts = 10,\n): Promise<number> {\n\tfor (let i = 0; i < maxAttempts; i++) {\n\t\tconst port = preferredPort + i;\n\t\tif (await isPortAvailable(port)) {\n\t\t\treturn port;\n\t\t}\n\t\tlogger.log(`ā ļø Port ${port} is in use, trying ${port + 1}...`);\n\t}\n\n\tthrow new Error(\n\t\t`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`,\n\t);\n}\n\n/**\n * Normalize telescope configuration\n * @internal Exported for testing\n */\nexport function normalizeTelescopeConfig(\n\tconfig: GkmConfig['telescope'],\n): NormalizedTelescopeConfig | undefined {\n\tif (config === false) {\n\t\treturn undefined;\n\t}\n\n\t// Handle string path (e.g., './src/config/telescope')\n\tif (typeof config === 'string') {\n\t\tconst { path: telescopePath, importPattern: telescopeImportPattern } =\n\t\t\tparseModuleConfig(config, 'telescope');\n\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\ttelescopePath,\n\t\t\ttelescopeImportPattern,\n\t\t\tpath: '/__telescope',\n\t\t\tignore: [],\n\t\t\trecordBody: true,\n\t\t\tmaxEntries: 1000,\n\t\t\twebsocket: true,\n\t\t};\n\t}\n\n\t// Default to enabled in development mode\n\tconst isEnabled =\n\t\tconfig === true || config === undefined || config.enabled !== false;\n\n\tif (!isEnabled) {\n\t\treturn undefined;\n\t}\n\n\tconst telescopeConfig: TelescopeConfig =\n\t\ttypeof config === 'object' ? config : {};\n\n\treturn {\n\t\tenabled: true,\n\t\tpath: telescopeConfig.path ?? '/__telescope',\n\t\tignore: telescopeConfig.ignore ?? [],\n\t\trecordBody: telescopeConfig.recordBody ?? true,\n\t\tmaxEntries: telescopeConfig.maxEntries ?? 1000,\n\t\twebsocket: telescopeConfig.websocket ?? true,\n\t};\n}\n\n/**\n * Normalize studio configuration\n * @internal Exported for testing\n */\nexport function normalizeStudioConfig(\n\tconfig: GkmConfig['studio'],\n): NormalizedStudioConfig | undefined {\n\tif (config === false) {\n\t\treturn undefined;\n\t}\n\n\t// Handle string path (e.g., './src/config/studio')\n\tif (typeof config === 'string') {\n\t\tconst { path: studioPath, importPattern: studioImportPattern } =\n\t\t\tparseModuleConfig(config, 'studio');\n\n\t\treturn {\n\t\t\tenabled: true,\n\t\t\tstudioPath,\n\t\t\tstudioImportPattern,\n\t\t\tpath: '/__studio',\n\t\t\tschema: 'public',\n\t\t};\n\t}\n\n\t// Default to enabled in development mode\n\tconst isEnabled =\n\t\tconfig === true || config === undefined || config.enabled !== false;\n\n\tif (!isEnabled) {\n\t\treturn undefined;\n\t}\n\n\tconst studioConfig: StudioConfig = typeof config === 'object' ? config : {};\n\n\treturn {\n\t\tenabled: true,\n\t\tpath: studioConfig.path ?? '/__studio',\n\t\tschema: studioConfig.schema ?? 'public',\n\t};\n}\n\n/**\n * Normalize hooks configuration\n * @internal Exported for testing\n */\nexport function normalizeHooksConfig(\n\tconfig: GkmConfig['hooks'],\n\tcwd: string = process.cwd(),\n): NormalizedHooksConfig | undefined {\n\tif (!config?.server) {\n\t\treturn undefined;\n\t}\n\n\t// Resolve the path (handle .ts extension)\n\tconst serverPath = config.server.endsWith('.ts')\n\t\t? config.server\n\t\t: `${config.server}.ts`;\n\n\tconst resolvedPath = resolve(cwd, serverPath);\n\n\treturn {\n\t\tserverHooksPath: resolvedPath,\n\t};\n}\n\n/**\n * Normalize production configuration\n * @internal Exported for testing\n */\nexport function normalizeProductionConfig(\n\tcliProduction: boolean,\n\tconfigProduction?: ProductionConfig,\n): NormalizedProductionConfig | undefined {\n\t// Production mode is only enabled if --production CLI flag is passed\n\tif (!cliProduction) {\n\t\treturn undefined;\n\t}\n\n\t// Merge CLI flag with config options\n\tconst config = configProduction ?? {};\n\n\treturn {\n\t\tenabled: true,\n\t\tbundle: config.bundle ?? true,\n\t\tminify: config.minify ?? true,\n\t\thealthCheck: config.healthCheck ?? '/health',\n\t\tgracefulShutdown: config.gracefulShutdown ?? true,\n\t\texternal: config.external ?? [],\n\t\tsubscribers: config.subscribers ?? 'exclude',\n\t\topenapi: config.openapi ?? false,\n\t\toptimizedHandlers: config.optimizedHandlers ?? true, // Default to optimized handlers in production\n\t};\n}\n\n/**\n * Get production config from GkmConfig\n * @internal\n */\nexport function getProductionConfigFromGkm(\n\tconfig: GkmConfig,\n): ProductionConfig | undefined {\n\tconst serverConfig = config.providers?.server;\n\tif (typeof serverConfig === 'object') {\n\t\treturn (serverConfig as ServerConfig).production;\n\t}\n\treturn undefined;\n}\n\nexport interface DevOptions {\n\tport?: number;\n\tportExplicit?: boolean;\n\tenableOpenApi?: boolean;\n\t/** Specific app to run in workspace mode (default: all apps) */\n\tapp?: string;\n\t/** Filter apps by pattern (passed to turbo --filter) */\n\tfilter?: string;\n\t/** Entry file to run (bypasses gkm config) */\n\tentry?: string;\n\t/** Watch for file changes (default: true with --entry) */\n\twatch?: boolean;\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n\t// Handle --entry mode: run any file with secret injection\n\tif (options.entry) {\n\t\treturn entryDevCommand(options);\n\t}\n\n\t// Load default .env file BEFORE loading config\n\t// This ensures env vars are available when config and its dependencies are loaded\n\tconst defaultEnv = loadEnvFiles('.env');\n\tif (defaultEnv.loaded.length > 0) {\n\t\tlogger.log(`š¦ Loaded env: ${defaultEnv.loaded.join(', ')}`);\n\t}\n\n\t// Check if we're in an app subdirectory\n\tconst appName = getAppNameFromCwd();\n\tlet config: GkmConfig;\n\tlet appRoot: string = process.cwd();\n\tlet secretsRoot: string = process.cwd(); // Where .gkm/secrets/ lives\n\tlet workspaceAppName: string | undefined; // Set if in workspace mode\n\tlet workspaceAppPort: number | undefined; // Port from workspace config\n\n\tif (appName) {\n\t\t// Try to load app-specific config from workspace\n\t\ttry {\n\t\t\tconst appConfig = await loadAppConfig();\n\t\t\tconfig = appConfig.gkmConfig;\n\t\t\tappRoot = appConfig.appRoot;\n\t\t\tsecretsRoot = appConfig.workspaceRoot;\n\t\t\tworkspaceAppName = appConfig.appName;\n\t\t\tworkspaceAppPort = appConfig.app.port;\n\t\t\tlogger.log(`š¦ Running app: ${appConfig.appName} on port ${workspaceAppPort}`);\n\t\t} catch {\n\t\t\t// Not in a workspace or app not found in workspace - fall back to regular loading\n\t\t\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t\t\t// Route to workspace dev mode for multi-app workspaces\n\t\t\tif (loadedConfig.type === 'workspace') {\n\t\t\t\tlogger.log('š¦ Detected workspace configuration');\n\t\t\t\treturn workspaceDevCommand(loadedConfig.workspace, options);\n\t\t\t}\n\n\t\t\tconfig = loadedConfig.raw as GkmConfig;\n\t\t}\n\t} else {\n\t\t// Try to load workspace config\n\t\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t\t// Route to workspace dev mode for multi-app workspaces\n\t\tif (loadedConfig.type === 'workspace') {\n\t\t\tlogger.log('š¦ Detected workspace configuration');\n\t\t\treturn workspaceDevCommand(loadedConfig.workspace, options);\n\t\t}\n\n\t\t// Single-app mode - use existing logic\n\t\tconfig = loadedConfig.raw as GkmConfig;\n\t}\n\n\t// Load any additional env files specified in config\n\tif (config.env) {\n\t\tconst { loaded, missing } = loadEnvFiles(config.env, appRoot);\n\t\tif (loaded.length > 0) {\n\t\t\tlogger.log(`š¦ Loaded env: ${loaded.join(', ')}`);\n\t\t}\n\t\tif (missing.length > 0) {\n\t\t\tlogger.warn(`ā ļø Missing env files: ${missing.join(', ')}`);\n\t\t}\n\t}\n\n\t// Force server provider for dev mode\n\tconst resolved = resolveProviders(config, { provider: 'server' });\n\n\tlogger.log('š Starting development server...');\n\tlogger.log(`Loading routes from: ${config.routes}`);\n\tif (config.functions) {\n\t\tlogger.log(`Loading functions from: ${config.functions}`);\n\t}\n\tif (config.crons) {\n\t\tlogger.log(`Loading crons from: ${config.crons}`);\n\t}\n\tif (config.subscribers) {\n\t\tlogger.log(`Loading subscribers from: ${config.subscribers}`);\n\t}\n\tlogger.log(`Using envParser: ${config.envParser}`);\n\n\t// Parse envParser and logger configuration\n\tconst { path: envParserPath, importPattern: envParserImportPattern } =\n\t\tparseModuleConfig(config.envParser, 'envParser');\n\tconst { path: loggerPath, importPattern: loggerImportPattern } =\n\t\tparseModuleConfig(config.logger, 'logger');\n\n\t// Normalize telescope configuration\n\tconst telescope = normalizeTelescopeConfig(config.telescope);\n\tif (telescope) {\n\t\tlogger.log(`š Telescope enabled at ${telescope.path}`);\n\t}\n\n\t// Normalize studio configuration\n\tconst studio = normalizeStudioConfig(config.studio);\n\tif (studio) {\n\t\tlogger.log(`šļø Studio enabled at ${studio.path}`);\n\t}\n\n\t// Normalize hooks configuration\n\tconst hooks = normalizeHooksConfig(config.hooks, appRoot);\n\tif (hooks) {\n\t\tlogger.log(`šŖ Server hooks enabled from ${config.hooks?.server}`);\n\t}\n\n\t// Resolve OpenAPI configuration\n\tconst openApiConfig = resolveOpenApiConfig(config);\n\t// Enable OpenAPI docs endpoint if either root config or provider config enables it\n\tconst enableOpenApi = openApiConfig.enabled || resolved.enableOpenApi;\n\tif (enableOpenApi) {\n\t\tlogger.log(`š OpenAPI output: ${OPENAPI_OUTPUT_PATH}`);\n\t}\n\n\tconst buildContext: BuildContext = {\n\t\tenvParserPath,\n\t\tenvParserImportPattern,\n\t\tloggerPath,\n\t\tloggerImportPattern,\n\t\ttelescope,\n\t\tstudio,\n\t\thooks,\n\t};\n\n\t// Build initial version\n\tawait buildServer(\n\t\tconfig,\n\t\tbuildContext,\n\t\tresolved.providers[0] as LegacyProvider,\n\t\tenableOpenApi,\n\t\tappRoot,\n\t);\n\n\t// Generate OpenAPI spec on startup\n\tif (enableOpenApi) {\n\t\tawait generateOpenApi(config);\n\t}\n\n\t// Determine runtime (default to node)\n\tconst runtime: Runtime = config.runtime ?? 'node';\n\n\t// Load secrets for dev mode and write to JSON file\n\tlet secretsJsonPath: string | undefined;\n\tconst appSecrets = await loadSecretsForApp(secretsRoot, workspaceAppName);\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tconst secretsDir = join(secretsRoot, '.gkm');\n\t\tawait mkdir(secretsDir, { recursive: true });\n\t\tsecretsJsonPath = join(secretsDir, 'dev-secrets.json');\n\t\tawait writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));\n\t\tlogger.log(`š Loaded ${Object.keys(appSecrets).length} secret(s)`);\n\t}\n\n\t// Start the dev server\n\t// Priority: explicit --port option > workspace app port > default 3000\n\tconst devServer = new DevServer(\n\t\tresolved.providers[0] as LegacyProvider,\n\t\toptions.port ?? workspaceAppPort ?? 3000,\n\t\toptions.portExplicit ?? false,\n\t\tenableOpenApi,\n\t\ttelescope,\n\t\tstudio,\n\t\truntime,\n\t\tappRoot,\n\t\tsecretsJsonPath,\n\t);\n\n\tawait devServer.start();\n\n\t// Watch for file changes\n\tconst envParserFile = config.envParser.split('#')[0] ?? config.envParser;\n\tconst loggerFile = config.logger.split('#')[0] ?? config.logger;\n\n\t// Get hooks file path for watching\n\tconst hooksFileParts = config.hooks?.server?.split('#');\n\tconst hooksFile = hooksFileParts?.[0];\n\n\tconst watchPatterns = [\n\t\tconfig.routes,\n\t\t...(config.functions ? [config.functions] : []),\n\t\t...(config.crons ? [config.crons] : []),\n\t\t...(config.subscribers ? [config.subscribers] : []),\n\t\t// Add .ts extension if not present for config files\n\t\tenvParserFile.endsWith('.ts') ? envParserFile : `${envParserFile}.ts`,\n\t\tloggerFile.endsWith('.ts') ? loggerFile : `${loggerFile}.ts`,\n\t\t// Add hooks file to watch list\n\t\t...(hooksFile\n\t\t\t? [hooksFile.endsWith('.ts') ? hooksFile : `${hooksFile}.ts`]\n\t\t\t: []),\n\t]\n\t\t.flat()\n\t\t.filter((p): p is string => typeof p === 'string');\n\n\t// Normalize patterns - remove leading ./ when using cwd option\n\tconst normalizedPatterns = watchPatterns.map((p) =>\n\t\tp.startsWith('./') ? p.slice(2) : p,\n\t);\n\n\tlogger.log(`š Watching for changes in: ${normalizedPatterns.join(', ')}`);\n\n\t// Resolve glob patterns to actual files (chokidar 4.x doesn't support globs)\n\tconst resolvedFiles = await fg(normalizedPatterns, {\n\t\tcwd: appRoot,\n\t\tabsolute: false,\n\t\tonlyFiles: true,\n\t});\n\n\t// Also watch the directories for new files\n\tconst dirsToWatch = [\n\t\t...new Set(\n\t\t\tresolvedFiles.map((f) => {\n\t\t\t\tconst parts = f.split('/');\n\t\t\t\treturn parts.slice(0, -1).join('/');\n\t\t\t}),\n\t\t),\n\t];\n\n\tlogger.log(\n\t\t`š Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`,\n\t);\n\n\tconst watcher = chokidar.watch([...resolvedFiles, ...dirsToWatch], {\n\t\tignored: /(^|[/\\\\])\\../, // ignore dotfiles\n\t\tpersistent: true,\n\t\tignoreInitial: true,\n\t\tcwd: appRoot,\n\t});\n\n\twatcher.on('ready', () => {\n\t\tlogger.log('š File watcher ready');\n\t});\n\n\twatcher.on('error', (error) => {\n\t\tlogger.error('ā Watcher error:', error);\n\t});\n\n\tlet rebuildTimeout: NodeJS.Timeout | null = null;\n\n\twatcher.on('change', async (path) => {\n\t\tlogger.log(`š File changed: ${path}`);\n\n\t\t// Debounce rebuilds\n\t\tif (rebuildTimeout) {\n\t\t\tclearTimeout(rebuildTimeout);\n\t\t}\n\n\t\trebuildTimeout = setTimeout(async () => {\n\t\t\ttry {\n\t\t\t\tlogger.log('š Rebuilding...');\n\t\t\t\tawait buildServer(\n\t\t\t\t\tconfig,\n\t\t\t\t\tbuildContext,\n\t\t\t\t\tresolved.providers[0] as LegacyProvider,\n\t\t\t\t\tenableOpenApi,\n\t\t\t\t\tappRoot,\n\t\t\t\t);\n\n\t\t\t\t// Regenerate OpenAPI if enabled\n\t\t\t\tif (enableOpenApi) {\n\t\t\t\t\tawait generateOpenApi(config, { silent: true });\n\t\t\t\t}\n\n\t\t\t\tlogger.log('ā
Rebuild complete, restarting server...');\n\t\t\t\tawait devServer.restart();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('ā Rebuild failed:', (error as Error).message);\n\t\t\t}\n\t\t}, 300);\n\t});\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down...');\n\n\t\t// Use sync-style shutdown to ensure it completes before exit\n\t\tPromise.all([watcher.close(), devServer.stop()])\n\t\t\t.catch((err) => {\n\t\t\t\tlogger.error('Error during shutdown:', err);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tprocess.exit(0);\n\t\t\t});\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n}\n\n/**\n * Generate all dependency environment variables for all apps.\n * Returns a flat object with all {APP_NAME}_URL variables.\n * @internal Exported for testing\n */\nexport function generateAllDependencyEnvVars(\n\tworkspace: NormalizedWorkspace,\n\turlPrefix = 'http://localhost',\n): Record<string, string> {\n\tconst env: Record<string, string> = {};\n\n\tfor (const appName of Object.keys(workspace.apps)) {\n\t\tconst appEnv = getDependencyEnvVars(workspace, appName, urlPrefix);\n\t\tObject.assign(env, appEnv);\n\t}\n\n\treturn env;\n}\n\n/**\n * Check for port conflicts across all apps.\n * Returns list of conflicts if any ports are duplicated.\n * @internal Exported for testing\n */\nexport function checkPortConflicts(\n\tworkspace: NormalizedWorkspace,\n): { app1: string; app2: string; port: number }[] {\n\tconst conflicts: { app1: string; app2: string; port: number }[] = [];\n\tconst portToApp = new Map<number, string>();\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tconst existingApp = portToApp.get(app.port);\n\t\tif (existingApp) {\n\t\t\tconflicts.push({ app1: existingApp, app2: appName, port: app.port });\n\t\t} else {\n\t\t\tportToApp.set(app.port, appName);\n\t\t}\n\t}\n\n\treturn conflicts;\n}\n\n/**\n * Next.js config file patterns to check.\n */\nconst NEXTJS_CONFIG_FILES = [\n\t'next.config.js',\n\t'next.config.ts',\n\t'next.config.mjs',\n];\n\n/**\n * Validation result for a frontend app.\n */\nexport interface FrontendValidationResult {\n\tappName: string;\n\tvalid: boolean;\n\terrors: string[];\n\twarnings: string[];\n}\n\n/**\n * Validate a frontend (Next.js) app configuration.\n * Checks for Next.js config file and dependency.\n * @internal Exported for testing\n */\nexport async function validateFrontendApp(\n\tappName: string,\n\tappPath: string,\n\tworkspaceRoot: string,\n): Promise<FrontendValidationResult> {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\tconst fullPath = join(workspaceRoot, appPath);\n\n\t// Check for Next.js config file\n\tconst hasConfigFile = NEXTJS_CONFIG_FILES.some((file) =>\n\t\texistsSync(join(fullPath, file)),\n\t);\n\n\tif (!hasConfigFile) {\n\t\terrors.push(\n\t\t\t`Next.js config file not found. Expected one of: ${NEXTJS_CONFIG_FILES.join(', ')}`,\n\t\t);\n\t}\n\n\t// Check for package.json\n\tconst packageJsonPath = join(fullPath, 'package.json');\n\tif (existsSync(packageJsonPath)) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\tconst pkg = require(packageJsonPath);\n\t\t\tconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n\t\t\tif (!deps.next) {\n\t\t\t\terrors.push(\n\t\t\t\t\t'Next.js not found in dependencies. Run: pnpm add next react react-dom',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for dev script\n\t\t\tif (!pkg.scripts?.dev) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t'No \"dev\" script found in package.json. Turbo expects a \"dev\" script to run.',\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\terrors.push(`Failed to read package.json at ${packageJsonPath}`);\n\t\t}\n\t} else {\n\t\terrors.push(\n\t\t\t`package.json not found at ${appPath}. Run: pnpm init in the app directory.`,\n\t\t);\n\t}\n\n\treturn {\n\t\tappName,\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n/**\n * Validate all frontend apps in the workspace.\n * Returns validation results for each frontend app.\n * @internal Exported for testing\n */\nexport async function validateFrontendApps(\n\tworkspace: NormalizedWorkspace,\n): Promise<FrontendValidationResult[]> {\n\tconst results: FrontendValidationResult[] = [];\n\n\tfor (const [appName, app] of Object.entries(workspace.apps)) {\n\t\tif (app.type === 'frontend') {\n\t\t\tconst result = await validateFrontendApp(\n\t\t\t\tappName,\n\t\t\t\tapp.path,\n\t\t\t\tworkspace.root,\n\t\t\t);\n\t\t\tresults.push(result);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Load secrets for development stage.\n * Returns env vars to inject, or empty object if secrets not configured/found.\n * @internal Exported for testing\n */\nexport async function loadDevSecrets(\n\tworkspace: NormalizedWorkspace,\n): Promise<Record<string, string>> {\n\t// Check if secrets are enabled in workspace config\n\tif (!workspace.secrets.enabled) {\n\t\treturn {};\n\t}\n\n\t// Try 'dev' stage first, then 'development'\n\tconst stages = ['dev', 'development'];\n\n\tfor (const stage of stages) {\n\t\tif (secretsExist(stage, workspace.root)) {\n\t\t\tconst secrets = await readStageSecrets(stage, workspace.root);\n\t\t\tif (secrets) {\n\t\t\t\tlogger.log(`š Loading secrets from stage: ${stage}`);\n\t\t\t\treturn toEmbeddableSecrets(secrets);\n\t\t\t}\n\t\t}\n\t}\n\n\tlogger.warn(\n\t\t'ā ļø Secrets enabled but no dev/development secrets found. Run \"gkm secrets:init --stage dev\"',\n\t);\n\treturn {};\n}\n\n/**\n * Load secrets from a path for dev mode.\n * For single app: returns secrets as-is.\n * For workspace app: maps {APP}_DATABASE_URL ā DATABASE_URL.\n * @internal Exported for testing\n */\nexport async function loadSecretsForApp(\n\tsecretsRoot: string,\n\tappName?: string,\n): Promise<Record<string, string>> {\n\t// Try 'dev' stage first, then 'development'\n\tconst stages = ['dev', 'development'];\n\n\tlet secrets: Record<string, string> = {};\n\n\tfor (const stage of stages) {\n\t\tif (secretsExist(stage, secretsRoot)) {\n\t\t\tconst stageSecrets = await readStageSecrets(stage, secretsRoot);\n\t\t\tif (stageSecrets) {\n\t\t\t\tlogger.log(`š Loading secrets from stage: ${stage}`);\n\t\t\t\tsecrets = toEmbeddableSecrets(stageSecrets);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Object.keys(secrets).length === 0) {\n\t\treturn {};\n\t}\n\n\t// Single app mode - no mapping needed\n\tif (!appName) {\n\t\treturn secrets;\n\t}\n\n\t// Workspace app mode - map {APP}_* to generic names\n\tconst prefix = appName.toUpperCase();\n\tconst mapped = { ...secrets };\n\n\t// Map {APP}_DATABASE_URL ā DATABASE_URL\n\tconst appDbUrl = secrets[`${prefix}_DATABASE_URL`];\n\tif (appDbUrl) {\n\t\tmapped.DATABASE_URL = appDbUrl;\n\t}\n\n\treturn mapped;\n}\n\n/**\n * Start docker-compose services for the workspace.\n * @internal Exported for testing\n */\nexport async function startWorkspaceServices(\n\tworkspace: NormalizedWorkspace,\n): Promise<void> {\n\tconst services = workspace.services;\n\tif (!services.db && !services.cache && !services.mail) {\n\t\treturn;\n\t}\n\n\tconst servicesToStart: string[] = [];\n\n\tif (services.db) {\n\t\tservicesToStart.push('postgres');\n\t}\n\tif (services.cache) {\n\t\tservicesToStart.push('redis');\n\t}\n\tif (services.mail) {\n\t\tservicesToStart.push('mailpit');\n\t}\n\n\tif (servicesToStart.length === 0) {\n\t\treturn;\n\t}\n\n\tlogger.log(`š³ Starting services: ${servicesToStart.join(', ')}`);\n\n\ttry {\n\t\t// Check if docker-compose.yml exists\n\t\tconst composeFile = join(workspace.root, 'docker-compose.yml');\n\t\tif (!existsSync(composeFile)) {\n\t\t\tlogger.warn(\n\t\t\t\t'ā ļø No docker-compose.yml found. Services will not be started.',\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Start services with docker-compose\n\t\texecSync(`docker compose up -d ${servicesToStart.join(' ')}`, {\n\t\t\tcwd: workspace.root,\n\t\t\tstdio: 'inherit',\n\t\t});\n\n\t\tlogger.log('ā
Services started');\n\t} catch (error) {\n\t\tlogger.error('ā Failed to start services:', (error as Error).message);\n\t\tthrow error;\n\t}\n}\n\n/**\n * Workspace dev command - orchestrates multi-app development using Turbo.\n *\n * Flow:\n * 1. Check for port conflicts\n * 2. Start docker-compose services (db, cache, mail)\n * 3. Generate dependency URLs ({APP_NAME}_URL)\n * 4. Spawn turbo run dev with injected env vars\n */\nasync function workspaceDevCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DevOptions,\n): Promise<void> {\n\tconst appCount = Object.keys(workspace.apps).length;\n\tconst backendApps = Object.entries(workspace.apps).filter(\n\t\t([_, app]) => app.type === 'backend',\n\t);\n\tconst frontendApps = Object.entries(workspace.apps).filter(\n\t\t([_, app]) => app.type === 'frontend',\n\t);\n\n\tlogger.log(`\\nš Starting workspace: ${workspace.name}`);\n\tlogger.log(\n\t\t` ${backendApps.length} backend app(s), ${frontendApps.length} frontend app(s)`,\n\t);\n\n\t// Check for port conflicts\n\tconst conflicts = checkPortConflicts(workspace);\n\tif (conflicts.length > 0) {\n\t\tfor (const conflict of conflicts) {\n\t\t\tlogger.error(\n\t\t\t\t`ā Port conflict: Apps \"${conflict.app1}\" and \"${conflict.app2}\" both use port ${conflict.port}`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\n\t\t\t'Port conflicts detected. Please assign unique ports to each app.',\n\t\t);\n\t}\n\n\t// Validate frontend apps (Next.js setup)\n\tif (frontendApps.length > 0) {\n\t\tlogger.log('\\nš Validating frontend apps...');\n\t\tconst validationResults = await validateFrontendApps(workspace);\n\n\t\tlet hasErrors = false;\n\t\tfor (const result of validationResults) {\n\t\t\tif (!result.valid) {\n\t\t\t\thasErrors = true;\n\t\t\t\tlogger.error(\n\t\t\t\t\t`\\nā Frontend app \"${result.appName}\" validation failed:`,\n\t\t\t\t);\n\t\t\t\tfor (const error of result.errors) {\n\t\t\t\t\tlogger.error(` ⢠${error}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const warning of result.warnings) {\n\t\t\t\tlogger.warn(` ā ļø ${result.appName}: ${warning}`);\n\t\t\t}\n\t\t}\n\n\t\tif (hasErrors) {\n\t\t\tthrow new Error(\n\t\t\t\t'Frontend app validation failed. Fix the issues above and try again.',\n\t\t\t);\n\t\t}\n\t\tlogger.log('ā
Frontend apps validated');\n\t}\n\n\t// Generate initial clients for frontends with backend dependencies\n\tif (frontendApps.length > 0) {\n\t\tconst clientResults = await generateAllClients(workspace, { force: true });\n\t\tconst generatedCount = clientResults.filter((r) => r.generated).length;\n\t\tif (generatedCount > 0) {\n\t\t\tlogger.log(`\\nš¦ Generated ${generatedCount} API client(s)`);\n\t\t}\n\t}\n\n\t// Start docker-compose services\n\tawait startWorkspaceServices(workspace);\n\n\t// Load secrets if enabled\n\tconst secretsEnv = await loadDevSecrets(workspace);\n\tif (Object.keys(secretsEnv).length > 0) {\n\t\tlogger.log(` Loaded ${Object.keys(secretsEnv).length} secret(s)`);\n\t}\n\n\t// Generate dependency URLs\n\tconst dependencyEnv = generateAllDependencyEnvVars(workspace);\n\tif (Object.keys(dependencyEnv).length > 0) {\n\t\tlogger.log('š” Dependency URLs:');\n\t\tfor (const [key, value] of Object.entries(dependencyEnv)) {\n\t\t\tlogger.log(` ${key}=${value}`);\n\t\t}\n\t}\n\n\t// Build turbo filter\n\tlet turboFilter: string[] = [];\n\tif (options.app) {\n\t\t// Run specific app\n\t\tif (!workspace.apps[options.app]) {\n\t\t\tconst appNames = Object.keys(workspace.apps).join(', ');\n\t\t\tthrow new Error(\n\t\t\t\t`App \"${options.app}\" not found. Available apps: ${appNames}`,\n\t\t\t);\n\t\t}\n\t\tturboFilter = ['--filter', options.app];\n\t\tlogger.log(`\\nšÆ Running single app: ${options.app}`);\n\t} else if (options.filter) {\n\t\t// Use custom filter\n\t\tturboFilter = ['--filter', options.filter];\n\t\tlogger.log(`\\nš Using filter: ${options.filter}`);\n\t} else {\n\t\t// Run all apps\n\t\tlogger.log(`\\nšÆ Running all ${appCount} apps`);\n\t}\n\n\t// List apps and their ports\n\tconst buildOrder = getAppBuildOrder(workspace);\n\tlogger.log('\\nš Apps (in dependency order):');\n\tfor (const appName of buildOrder) {\n\t\tconst app = workspace.apps[appName];\n\t\tif (!app) continue;\n\t\tconst deps =\n\t\t\tapp.dependencies.length > 0\n\t\t\t\t? ` (depends on: ${app.dependencies.join(', ')})`\n\t\t\t\t: '';\n\t\tlogger.log(\n\t\t\t` ${app.type === 'backend' ? 'š§' : 'š'} ${appName} ā http://localhost:${app.port}${deps}`,\n\t\t);\n\t}\n\n\t// Find the config file path for GKM_CONFIG_PATH\n\tconst configFiles = ['gkm.config.ts', 'gkm.config.js', 'gkm.config.json'];\n\tlet configPath = '';\n\tfor (const file of configFiles) {\n\t\tconst fullPath = join(workspace.root, file);\n\t\tif (existsSync(fullPath)) {\n\t\t\tconfigPath = fullPath;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Prepare environment variables\n\t// Order matters: secrets first, then dependencies (dependencies can override)\n\tconst turboEnv: Record<string, string> = {\n\t\t...process.env,\n\t\t...secretsEnv,\n\t\t...dependencyEnv,\n\t\tNODE_ENV: 'development',\n\t\t// Inject config path so child processes can find the workspace config\n\t\t...(configPath ? { GKM_CONFIG_PATH: configPath } : {}),\n\t};\n\n\t// Spawn turbo run dev\n\tlogger.log('\\nš Starting turbo run dev...\\n');\n\n\tconst turboProcess = spawn('pnpm', ['turbo', 'run', 'dev', ...turboFilter], {\n\t\tcwd: workspace.root,\n\t\tstdio: 'inherit',\n\t\tenv: turboEnv,\n\t});\n\n\t// Set up file watcher for backend endpoint changes (smart client regeneration)\n\tlet endpointWatcher: ReturnType<typeof chokidar.watch> | null = null;\n\n\tif (frontendApps.length > 0 && backendApps.length > 0) {\n\t\t// Collect all backend route patterns to watch\n\t\tconst watchPatterns: string[] = [];\n\t\tconst backendRouteMap = new Map<string, string[]>(); // routes pattern -> backend app names\n\n\t\tfor (const [appName, app] of backendApps) {\n\t\t\tconst routePatterns = normalizeRoutes(app.routes);\n\t\t\tfor (const routePattern of routePatterns) {\n\t\t\t\tconst fullPattern = join(workspace.root, app.path, routePattern);\n\t\t\t\twatchPatterns.push(fullPattern);\n\n\t\t\t\t// Map pattern to app name for change detection\n\t\t\t\tconst patternKey = join(app.path, routePattern);\n\t\t\t\tconst existing = backendRouteMap.get(patternKey) || [];\n\t\t\t\tbackendRouteMap.set(patternKey, [...existing, appName]);\n\t\t\t}\n\t\t}\n\n\t\tif (watchPatterns.length > 0) {\n\t\t\t// Resolve glob patterns to files\n\t\t\tconst resolvedFiles = await fg(watchPatterns, {\n\t\t\t\tcwd: workspace.root,\n\t\t\t\tabsolute: true,\n\t\t\t\tonlyFiles: true,\n\t\t\t});\n\n\t\t\tif (resolvedFiles.length > 0) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`\\nš Watching ${resolvedFiles.length} endpoint file(s) for schema changes`,\n\t\t\t\t);\n\n\t\t\t\tendpointWatcher = chokidar.watch(resolvedFiles, {\n\t\t\t\t\tignored: /(^|[/\\\\])\\../,\n\t\t\t\t\tpersistent: true,\n\t\t\t\t\tignoreInitial: true,\n\t\t\t\t});\n\n\t\t\t\tlet regenerateTimeout: NodeJS.Timeout | null = null;\n\n\t\t\t\tendpointWatcher.on('change', async (changedPath) => {\n\t\t\t\t\t// Debounce regeneration\n\t\t\t\t\tif (regenerateTimeout) {\n\t\t\t\t\t\tclearTimeout(regenerateTimeout);\n\t\t\t\t\t}\n\n\t\t\t\t\tregenerateTimeout = setTimeout(async () => {\n\t\t\t\t\t\t// Find which backend app this file belongs to\n\t\t\t\t\t\tconst changedBackends: string[] = [];\n\n\t\t\t\t\t\tfor (const [appName, app] of backendApps) {\n\t\t\t\t\t\t\tconst routePatterns = normalizeRoutes(app.routes);\n\t\t\t\t\t\t\tfor (const routePattern of routePatterns) {\n\t\t\t\t\t\t\t\tconst routesDir = join(\n\t\t\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\t\t\tapp.path,\n\t\t\t\t\t\t\t\t\troutePattern.split('*')[0] || '',\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (changedPath.startsWith(routesDir.replace(/\\/$/, ''))) {\n\t\t\t\t\t\t\t\t\tchangedBackends.push(appName);\n\t\t\t\t\t\t\t\t\tbreak; // Found a match, no need to check other patterns\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (changedBackends.length === 0) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Find frontends that depend on changed backends\n\t\t\t\t\t\tconst affectedFrontends = new Set<string>();\n\t\t\t\t\t\tfor (const backend of changedBackends) {\n\t\t\t\t\t\t\tconst dependents = getDependentFrontends(workspace, backend);\n\t\t\t\t\t\t\tfor (const frontend of dependents) {\n\t\t\t\t\t\t\t\taffectedFrontends.add(frontend);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (affectedFrontends.size === 0) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Regenerate clients for affected frontends\n\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t`\\nš Detected schema change in ${changedBackends.join(', ')}`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tfor (const frontend of affectedFrontends) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst results = await generateClientForFrontend(\n\t\t\t\t\t\t\t\t\tworkspace,\n\t\t\t\t\t\t\t\t\tfrontend,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tfor (const result of results) {\n\t\t\t\t\t\t\t\t\tif (result.generated) {\n\t\t\t\t\t\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t\t\t\t\t\t` š¦ Regenerated client for ${result.frontendApp} (${result.endpointCount} endpoints)`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t\t` ā Failed to regenerate client for ${frontend}: ${(error as Error).message}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 500); // 500ms debounce\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down workspace...');\n\n\t\t// Close endpoint watcher\n\t\tif (endpointWatcher) {\n\t\t\tendpointWatcher.close().catch(() => {});\n\t\t}\n\n\t\t// Kill turbo process\n\t\tif (turboProcess.pid) {\n\t\t\ttry {\n\t\t\t\t// Try to kill the process group\n\t\t\t\tprocess.kill(-turboProcess.pid, 'SIGTERM');\n\t\t\t} catch {\n\t\t\t\t// Fall back to killing just the process\n\t\t\t\tturboProcess.kill('SIGTERM');\n\t\t\t}\n\t\t}\n\n\t\t// Give processes time to clean up\n\t\tsetTimeout(() => {\n\t\t\tprocess.exit(0);\n\t\t}, 2000);\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n\n\t// Wait for turbo to exit\n\treturn new Promise((resolve, reject) => {\n\t\tturboProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Turbo error:', error);\n\t\t\treject(error);\n\t\t});\n\n\t\tturboProcess.on('exit', (code) => {\n\t\t\t// Close watcher on exit\n\t\t\tif (endpointWatcher) {\n\t\t\t\tendpointWatcher.close().catch(() => {});\n\t\t\t}\n\n\t\t\tif (code !== null && code !== 0) {\n\t\t\t\treject(new Error(`Turbo exited with code ${code}`));\n\t\t\t} else {\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\t});\n}\n\nasync function buildServer(\n\tconfig: any,\n\tcontext: BuildContext,\n\tprovider: LegacyProvider,\n\tenableOpenApi: boolean,\n\tappRoot: string = process.cwd(),\n): Promise<void> {\n\t// Initialize generators\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst functionGenerator = new FunctionGenerator();\n\tconst cronGenerator = new CronGenerator();\n\tconst subscriberGenerator = new SubscriberGenerator();\n\n\t// Load all constructs (resolve paths relative to appRoot)\n\tconst [allEndpoints, allFunctions, allCrons, allSubscribers] =\n\t\tawait Promise.all([\n\t\t\tendpointGenerator.load(config.routes, appRoot),\n\t\t\tconfig.functions ? functionGenerator.load(config.functions, appRoot) : [],\n\t\t\tconfig.crons ? cronGenerator.load(config.crons, appRoot) : [],\n\t\t\tconfig.subscribers\n\t\t\t\t? subscriberGenerator.load(config.subscribers, appRoot)\n\t\t\t\t: [],\n\t\t]);\n\n\t// Ensure .gkm directory exists in app root\n\tconst outputDir = join(appRoot, '.gkm', provider);\n\tawait mkdir(outputDir, { recursive: true });\n\n\t// Build for server provider\n\tawait Promise.all([\n\t\tendpointGenerator.build(context, allEndpoints, outputDir, {\n\t\t\tprovider,\n\t\t\tenableOpenApi,\n\t\t}),\n\t\tfunctionGenerator.build(context, allFunctions, outputDir, { provider }),\n\t\tcronGenerator.build(context, allCrons, outputDir, { provider }),\n\t\tsubscriberGenerator.build(context, allSubscribers, outputDir, { provider }),\n\t]);\n}\n\n/**\n * Find the directory containing .gkm/secrets/.\n * Walks up from cwd until it finds one, or returns cwd.\n * @internal Exported for testing\n */\nexport function findSecretsRoot(startDir: string): string {\n\tlet dir = startDir;\n\twhile (dir !== '/') {\n\t\tif (existsSync(join(dir, '.gkm', 'secrets'))) {\n\t\t\treturn dir;\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn startDir;\n}\n\n/**\n * Create a wrapper script that injects secrets before importing the entry file.\n * @internal Exported for testing\n */\nexport async function createEntryWrapper(\n\twrapperPath: string,\n\tentryPath: string,\n\tsecretsJsonPath?: string,\n): Promise<void> {\n\tconst credentialsInjection = secretsJsonPath\n\t\t? `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { existsSync, readFileSync } from 'node:fs';\n\n// Inject dev secrets into Credentials (before app import)\nconst secretsPath = '${secretsJsonPath}';\nif (existsSync(secretsPath)) {\n Object.assign(Credentials, JSON.parse(readFileSync(secretsPath, 'utf-8')));\n}\n\n`\n\t\t: '';\n\n\t// Use dynamic import() to ensure secrets are assigned before the entry file loads\n\t// Static imports are hoisted, so Object.assign would run after the entry file is loaded\n\tconst content = `#!/usr/bin/env node\n/**\n * Entry wrapper generated by 'gkm dev --entry'\n */\n${credentialsInjection}// Import and run the user's entry file (dynamic import ensures secrets load first)\nawait import('${entryPath}');\n`;\n\n\tawait writeFile(wrapperPath, content);\n}\n\n/**\n * Run any TypeScript file with secret injection.\n * Does not require gkm.config.ts.\n */\nasync function entryDevCommand(options: DevOptions): Promise<void> {\n\tconst { entry, watch = true } = options;\n\n\tif (!entry) {\n\t\tthrow new Error('--entry requires a file path');\n\t}\n\n\tconst entryPath = resolve(process.cwd(), entry);\n\n\tif (!existsSync(entryPath)) {\n\t\tthrow new Error(`Entry file not found: ${entryPath}`);\n\t}\n\n\t// Load .env files\n\tconst defaultEnv = loadEnvFiles('.env');\n\tif (defaultEnv.loaded.length > 0) {\n\t\tlogger.log(`š¦ Loaded env: ${defaultEnv.loaded.join(', ')}`);\n\t}\n\n\t// Try to get workspace app config for port and secrets\n\tlet workspaceAppPort: number | undefined;\n\tlet secretsRoot: string = process.cwd();\n\tlet appName: string | undefined;\n\n\ttry {\n\t\tconst appConfig = await loadAppConfig();\n\t\tworkspaceAppPort = appConfig.app.port;\n\t\tsecretsRoot = appConfig.workspaceRoot;\n\t\tappName = appConfig.appName;\n\t\tlogger.log(`š¦ App: ${appName} (port ${workspaceAppPort})`);\n\t} catch {\n\t\t// Not in a workspace - use defaults\n\t\tsecretsRoot = findSecretsRoot(process.cwd());\n\t\tappName = getAppNameFromCwd() ?? undefined;\n\t\tif (appName) {\n\t\t\tlogger.log(`š¦ App name: ${appName}`);\n\t\t}\n\t}\n\n\t// Determine port: explicit --port > workspace config > default 3000\n\tconst port = options.port ?? workspaceAppPort ?? 3000;\n\n\tlogger.log(`š Starting entry file: ${entry} on port ${port}`);\n\n\t// Load secrets\n\tconst appSecrets = await loadSecretsForApp(secretsRoot, appName);\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tlogger.log(`š Loaded ${Object.keys(appSecrets).length} secret(s)`);\n\t} else {\n\t\tlogger.log(`ā ļø No secrets found in ${secretsRoot}/.gkm/secrets/`);\n\t}\n\n\t// Write secrets to temp JSON file\n\tlet secretsJsonPath: string | undefined;\n\tif (Object.keys(appSecrets).length > 0) {\n\t\tconst secretsDir = join(secretsRoot, '.gkm');\n\t\tawait mkdir(secretsDir, { recursive: true });\n\t\tsecretsJsonPath = join(secretsDir, 'dev-secrets.json');\n\t\tawait writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));\n\t}\n\n\t// Create wrapper entry that injects secrets before importing user's file\n\tconst wrapperDir = join(process.cwd(), '.gkm');\n\tawait mkdir(wrapperDir, { recursive: true });\n\tconst wrapperPath = join(wrapperDir, 'entry-wrapper.ts');\n\tawait createEntryWrapper(wrapperPath, entryPath, secretsJsonPath);\n\n\t// Start with tsx\n\tconst runner = new EntryRunner(wrapperPath, entryPath, watch, port);\n\tawait runner.start();\n\n\t// Handle graceful shutdown\n\tlet isShuttingDown = false;\n\tconst shutdown = () => {\n\t\tif (isShuttingDown) return;\n\t\tisShuttingDown = true;\n\n\t\tlogger.log('\\nš Shutting down...');\n\t\trunner.stop();\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on('SIGINT', shutdown);\n\tprocess.on('SIGTERM', shutdown);\n\n\t// Keep the process alive\n\tawait new Promise(() => {});\n}\n\n/**\n * Runs and watches a TypeScript entry file using tsx.\n */\nclass EntryRunner {\n\tprivate childProcess: ChildProcess | null = null;\n\tprivate watcher: ReturnType<typeof chokidar.watch> | null = null;\n\tprivate isRunning = false;\n\n\tconstructor(\n\t\tprivate wrapperPath: string,\n\t\tprivate entryPath: string,\n\t\tprivate watch: boolean,\n\t\tprivate port: number,\n\t) {}\n\n\tasync start(): Promise<void> {\n\t\tawait this.runProcess();\n\n\t\tif (this.watch) {\n\t\t\t// Watch the entry file's directory for changes\n\t\t\tconst watchDir = dirname(this.entryPath);\n\n\t\t\tthis.watcher = chokidar.watch(watchDir, {\n\t\t\t\tignored: /(^|[/\\\\])\\../,\n\t\t\t\tpersistent: true,\n\t\t\t\tignoreInitial: true,\n\t\t\t});\n\n\t\t\tlet restartTimeout: NodeJS.Timeout | null = null;\n\n\t\t\tthis.watcher.on('change', (path) => {\n\t\t\t\tlogger.log(`š File changed: ${path}`);\n\n\t\t\t\t// Debounce restarts\n\t\t\t\tif (restartTimeout) {\n\t\t\t\t\tclearTimeout(restartTimeout);\n\t\t\t\t}\n\n\t\t\t\trestartTimeout = setTimeout(async () => {\n\t\t\t\t\tlogger.log('š Restarting...');\n\t\t\t\t\tawait this.restart();\n\t\t\t\t}, 300);\n\t\t\t});\n\n\t\t\tlogger.log(`š Watching for changes in: ${watchDir}`);\n\t\t}\n\t}\n\n\tprivate async runProcess(): Promise<void> {\n\t\t// Pass PORT as environment variable\n\t\tconst env = { ...process.env, PORT: String(this.port) };\n\n\t\tthis.childProcess = spawn('npx', ['tsx', this.wrapperPath], {\n\t\t\tstdio: 'inherit',\n\t\t\tenv,\n\t\t\tdetached: true,\n\t\t});\n\n\t\tthis.isRunning = true;\n\n\t\tthis.childProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Process error:', error);\n\t\t});\n\n\t\tthis.childProcess.on('exit', (code) => {\n\t\t\tif (code !== null && code !== 0 && code !== 143) {\n\t\t\t\t// 143 = SIGTERM\n\t\t\t\tlogger.error(`ā Process exited with code ${code}`);\n\t\t\t}\n\t\t\tthis.isRunning = false;\n\t\t});\n\n\t\t// Give the process a moment to start\n\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\n\t\tif (this.isRunning) {\n\t\t\tlogger.log(`\\nš Running at http://localhost:${this.port}`);\n\t\t}\n\t}\n\n\tasync restart(): Promise<void> {\n\t\tthis.stopProcess();\n\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\tawait this.runProcess();\n\t}\n\n\tstop(): void {\n\t\tthis.watcher?.close();\n\t\tthis.stopProcess();\n\t}\n\n\tprivate stopProcess(): void {\n\t\tif (this.childProcess && this.isRunning) {\n\t\t\tconst pid = this.childProcess.pid;\n\t\t\tif (pid) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(-pid, 'SIGTERM');\n\t\t\t\t} catch {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 'SIGTERM');\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Process already dead\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.childProcess = null;\n\t\t\tthis.isRunning = false;\n\t\t}\n\t}\n}\n\nclass DevServer {\n\tprivate serverProcess: ChildProcess | null = null;\n\tprivate isRunning = false;\n\tprivate actualPort: number;\n\n\tconstructor(\n\t\tprivate provider: LegacyProvider,\n\t\tprivate requestedPort: number,\n\t\tprivate portExplicit: boolean,\n\t\tprivate enableOpenApi: boolean,\n\t\tprivate telescope: NormalizedTelescopeConfig | undefined,\n\t\tprivate studio: NormalizedStudioConfig | undefined,\n\t\tprivate runtime: Runtime = 'node',\n\t\tprivate appRoot: string = process.cwd(),\n\t\tprivate secretsJsonPath?: string,\n\t) {\n\t\tthis.actualPort = requestedPort;\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.isRunning) {\n\t\t\tawait this.stop();\n\t\t}\n\n\t\t// Check port availability\n\t\tif (this.portExplicit) {\n\t\t\t// Port was explicitly specified - throw if unavailable\n\t\t\tconst available = await isPortAvailable(this.requestedPort);\n\t\t\tif (!available) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Port ${this.requestedPort} is already in use. ` +\n\t\t\t\t\t\t`Either stop the process using that port or omit -p/--port to auto-select an available port.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.actualPort = this.requestedPort;\n\t\t} else {\n\t\t\t// Find an available port starting from the default\n\t\t\tthis.actualPort = await findAvailablePort(this.requestedPort);\n\n\t\t\tif (this.actualPort !== this.requestedPort) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`ā¹ļø Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst serverEntryPath = join(\n\t\t\tthis.appRoot,\n\t\t\t'.gkm',\n\t\t\tthis.provider,\n\t\t\t'server.ts',\n\t\t);\n\n\t\t// Create server entry file\n\t\tawait this.createServerEntry();\n\n\t\tlogger.log(`\\n⨠Starting server on port ${this.actualPort}...`);\n\n\t\t// Start the server using tsx (TypeScript execution)\n\t\t// Use detached: true so we can kill the entire process tree\n\t\tthis.serverProcess = spawn(\n\t\t\t'npx',\n\t\t\t['tsx', serverEntryPath, '--port', this.actualPort.toString()],\n\t\t\t{\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, NODE_ENV: 'development' },\n\t\t\t\tdetached: true,\n\t\t\t},\n\t\t);\n\n\t\tthis.isRunning = true;\n\n\t\tthis.serverProcess.on('error', (error) => {\n\t\t\tlogger.error('ā Server error:', error);\n\t\t});\n\n\t\tthis.serverProcess.on('exit', (code, signal) => {\n\t\t\tif (code !== null && code !== 0 && signal !== 'SIGTERM') {\n\t\t\t\tlogger.error(`ā Server exited with code ${code}`);\n\t\t\t}\n\t\t\tthis.isRunning = false;\n\t\t});\n\n\t\t// Give the server a moment to start\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\n\n\t\tif (this.isRunning) {\n\t\t\tlogger.log(`\\nš Server running at http://localhost:${this.actualPort}`);\n\t\t\tif (this.enableOpenApi) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`š API Docs available at http://localhost:${this.actualPort}/__docs`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.telescope) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`š Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.studio) {\n\t\t\t\tlogger.log(\n\t\t\t\t\t`šļø Studio available at http://localhost:${this.actualPort}${this.studio.path}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tconst port = this.actualPort;\n\n\t\tif (this.serverProcess && this.isRunning) {\n\t\t\tconst pid = this.serverProcess.pid;\n\n\t\t\t// Use SIGKILL directly since the server ignores SIGTERM\n\t\t\tif (pid) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(-pid, 'SIGKILL');\n\t\t\t\t} catch {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 'SIGKILL');\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Process might already be dead\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.serverProcess = null;\n\t\t\tthis.isRunning = false;\n\t\t}\n\n\t\t// Also kill any processes still holding the port\n\t\tthis.killProcessesOnPort(port);\n\t}\n\n\tprivate killProcessesOnPort(port: number): void {\n\t\ttry {\n\t\t\t// Use lsof to find PIDs on the port and kill them with -9\n\t\t\texecSync(`lsof -ti tcp:${port} | xargs kill -9 2>/dev/null || true`, {\n\t\t\t\tstdio: 'ignore',\n\t\t\t});\n\t\t} catch {\n\t\t\t// Ignore errors - port may already be free\n\t\t}\n\t}\n\n\tasync restart(): Promise<void> {\n\t\tconst portToReuse = this.actualPort;\n\t\tawait this.stop();\n\n\t\t// Wait for port to be released (up to 3 seconds)\n\t\tlet attempts = 0;\n\t\twhile (attempts < 30) {\n\t\t\tif (await isPortAvailable(portToReuse)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t\tattempts++;\n\t\t}\n\n\t\t// Force reuse the same port\n\t\tthis.requestedPort = portToReuse;\n\t\tawait this.start();\n\t}\n\n\tprivate async createServerEntry(): Promise<void> {\n\t\tconst { writeFile: fsWriteFile } = await import('node:fs/promises');\n\t\tconst { relative, dirname } = await import('node:path');\n\n\t\tconst serverPath = join(this.appRoot, '.gkm', this.provider, 'server.ts');\n\n\t\tconst relativeAppPath = relative(\n\t\t\tdirname(serverPath),\n\t\t\tjoin(dirname(serverPath), 'app.js'),\n\t\t);\n\n\t\t// Generate credentials injection code if secrets are available\n\t\tconst credentialsInjection = this.secretsJsonPath\n\t\t\t? `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { existsSync, readFileSync } from 'node:fs';\n\n// Inject dev secrets into Credentials (must happen before app import)\nconst secretsPath = '${this.secretsJsonPath}';\nif (existsSync(secretsPath)) {\n Object.assign(Credentials, JSON.parse(readFileSync(secretsPath, 'utf-8')));\n}\n\n`\n\t\t\t: '';\n\n\t\tconst serveCode =\n\t\t\tthis.runtime === 'bun'\n\t\t\t\t? `Bun.serve({\n port,\n fetch: app.fetch,\n });`\n\t\t\t\t: `const { serve } = await import('@hono/node-server');\n const server = serve({\n fetch: app.fetch,\n port,\n });\n // Inject WebSocket support if available\n const injectWs = (app as any).__injectWebSocket;\n if (injectWs) {\n injectWs(server);\n console.log('š Telescope real-time updates enabled');\n }`;\n\n\t\tconst content = `#!/usr/bin/env node\n/**\n * Development server entry point\n * This file is auto-generated by 'gkm dev'\n */\n${credentialsInjection}import { createApp } from './${relativeAppPath.startsWith('.') ? relativeAppPath : `./${relativeAppPath}`}';\n\nconst port = process.argv.includes('--port')\n ? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])\n : 3000;\n\n// createApp is async to support optional WebSocket setup\nconst { app, start } = await createApp(undefined, ${this.enableOpenApi});\n\n// Start the server\nstart({\n port,\n serve: async (app, port) => {\n ${serveCode}\n },\n}).catch((error) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n});\n`;\n\n\t\tawait fsWriteFile(serverPath, content);\n\t}\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type {\n\tCronInfo,\n\tFunctionInfo,\n\tRouteInfo,\n\tSubscriberInfo,\n} from '../types';\n\nconst logger = console;\n\nexport type ManifestProvider = 'aws' | 'server';\n\nexport interface ServerAppInfo {\n\thandler: string;\n\tendpoints: string;\n}\n\nexport async function generateAwsManifest(\n\toutputDir: string,\n\troutes: RouteInfo[],\n\tfunctions: FunctionInfo[],\n\tcrons: CronInfo[],\n\tsubscribers: SubscriberInfo[],\n): Promise<void> {\n\tconst manifestDir = join(outputDir, 'manifest');\n\tawait mkdir(manifestDir, { recursive: true });\n\n\t// Filter out 'ALL' method routes (server-specific)\n\tconst awsRoutes = routes.filter((r) => r.method !== 'ALL');\n\n\tconst content = `export const manifest = {\n routes: ${JSON.stringify(awsRoutes, null, 2)},\n functions: ${JSON.stringify(functions, null, 2)},\n crons: ${JSON.stringify(crons, null, 2)},\n subscribers: ${JSON.stringify(subscribers, null, 2)},\n} as const;\n\n// Derived types\nexport type Route = (typeof manifest.routes)[number];\nexport type Function = (typeof manifest.functions)[number];\nexport type Cron = (typeof manifest.crons)[number];\nexport type Subscriber = (typeof manifest.subscribers)[number];\n\n// Useful union types\nexport type Authorizer = Route['authorizer'];\nexport type HttpMethod = Route['method'];\nexport type RoutePath = Route['path'];\n`;\n\n\tconst manifestPath = join(manifestDir, 'aws.ts');\n\tawait writeFile(manifestPath, content);\n\n\tlogger.log(\n\t\t`Generated AWS manifest with ${awsRoutes.length} routes, ${functions.length} functions, ${crons.length} crons, ${subscribers.length} subscribers`,\n\t);\n\tlogger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);\n}\n\nexport async function generateServerManifest(\n\toutputDir: string,\n\tappInfo: ServerAppInfo,\n\troutes: RouteInfo[],\n\tsubscribers: SubscriberInfo[],\n): Promise<void> {\n\tconst manifestDir = join(outputDir, 'manifest');\n\tawait mkdir(manifestDir, { recursive: true });\n\n\t// For server, extract route metadata (path, method, authorizer)\n\tconst serverRoutes = routes\n\t\t.filter((r) => r.method !== 'ALL')\n\t\t.map((r) => ({\n\t\t\tpath: r.path,\n\t\t\tmethod: r.method,\n\t\t\tauthorizer: r.authorizer,\n\t\t}));\n\n\t// Server subscribers only need name and events\n\tconst serverSubscribers = subscribers.map((s) => ({\n\t\tname: s.name,\n\t\tsubscribedEvents: s.subscribedEvents,\n\t}));\n\n\tconst content = `export const manifest = {\n app: ${JSON.stringify(appInfo, null, 2)},\n routes: ${JSON.stringify(serverRoutes, null, 2)},\n subscribers: ${JSON.stringify(serverSubscribers, null, 2)},\n} as const;\n\n// Derived types\nexport type Route = (typeof manifest.routes)[number];\nexport type Subscriber = (typeof manifest.subscribers)[number];\n\n// Useful union types\nexport type Authorizer = Route['authorizer'];\nexport type HttpMethod = Route['method'];\nexport type RoutePath = Route['path'];\n`;\n\n\tconst manifestPath = join(manifestDir, 'server.ts');\n\tawait writeFile(manifestPath, content);\n\n\tlogger.log(\n\t\t`Generated server manifest with ${serverRoutes.length} routes, ${serverSubscribers.length} subscribers`,\n\t);\n\tlogger.log(`Manifest: ${relative(process.cwd(), manifestPath)}`);\n}\n","import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig, loadWorkspaceConfig, parseModuleConfig } from '../config';\nimport {\n\tgetProductionConfigFromGkm,\n\tnormalizeHooksConfig,\n\tnormalizeProductionConfig,\n\tnormalizeStudioConfig,\n\tnormalizeTelescopeConfig,\n} from '../dev';\nimport {\n\tCronGenerator,\n\tEndpointGenerator,\n\tFunctionGenerator,\n\ttype GeneratedConstruct,\n\tSubscriberGenerator,\n} from '../generators';\nimport type {\n\tBuildOptions,\n\tBuildResult,\n\tLegacyProvider,\n\tRouteInfo,\n} from '../types';\nimport {\n\tgetAppBuildOrder,\n\ttype NormalizedAppConfig,\n\ttype NormalizedWorkspace,\n} from '../workspace/index.js';\nimport {\n\tgenerateAwsManifest,\n\tgenerateServerManifest,\n\ttype ServerAppInfo,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(\n\toptions: BuildOptions,\n): Promise<BuildResult> {\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace build mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceBuildCommand(loadedConfig.workspace, options);\n\t}\n\n\t// Single-app build - use existing logic\n\tconst config = await loadConfig();\n\n\t// Resolve providers from new config format\n\tconst resolved = resolveProviders(config, options);\n\n\t// Normalize production configuration\n\tconst productionConfigFromGkm = getProductionConfigFromGkm(config);\n\tconst production = normalizeProductionConfig(\n\t\toptions.production ?? false,\n\t\tproductionConfigFromGkm,\n\t);\n\n\tif (production) {\n\t\tlogger.log(`š Building for PRODUCTION`);\n\t}\n\n\tlogger.log(`Building with providers: ${resolved.providers.join(', ')}`);\n\tlogger.log(`Loading routes from: ${config.routes}`);\n\tif (config.functions) {\n\t\tlogger.log(`Loading functions from: ${config.functions}`);\n\t}\n\tif (config.crons) {\n\t\tlogger.log(`Loading crons from: ${config.crons}`);\n\t}\n\tif (config.subscribers) {\n\t\tlogger.log(`Loading subscribers from: ${config.subscribers}`);\n\t}\n\tlogger.log(`Using envParser: ${config.envParser}`);\n\n\t// Parse envParser and logger configuration\n\tconst { path: envParserPath, importPattern: envParserImportPattern } =\n\t\tparseModuleConfig(config.envParser, 'envParser');\n\tconst { path: loggerPath, importPattern: loggerImportPattern } =\n\t\tparseModuleConfig(config.logger, 'logger');\n\n\t// Normalize telescope configuration (disabled in production)\n\tconst telescope = production\n\t\t? undefined\n\t\t: normalizeTelescopeConfig(config.telescope);\n\tif (telescope) {\n\t\tlogger.log(`š Telescope enabled at ${telescope.path}`);\n\t}\n\n\t// Normalize studio configuration (disabled in production)\n\tconst studio = production ? undefined : normalizeStudioConfig(config.studio);\n\tif (studio) {\n\t\tlogger.log(`šļø Studio enabled at ${studio.path}`);\n\t}\n\n\t// Normalize hooks configuration\n\tconst hooks = normalizeHooksConfig(config.hooks);\n\tif (hooks) {\n\t\tlogger.log(`šŖ Server hooks enabled`);\n\t}\n\n\t// Extract docker compose services for env var auto-population\n\tconst services = config.docker?.compose?.services;\n\tconst dockerServices = services\n\t\t? Array.isArray(services)\n\t\t\t? {\n\t\t\t\t\tpostgres: services.includes('postgres'),\n\t\t\t\t\tredis: services.includes('redis'),\n\t\t\t\t\trabbitmq: services.includes('rabbitmq'),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tpostgres: Boolean(services.postgres),\n\t\t\t\t\tredis: Boolean(services.redis),\n\t\t\t\t\trabbitmq: Boolean(services.rabbitmq),\n\t\t\t\t}\n\t\t: undefined;\n\n\tconst buildContext: BuildContext = {\n\t\tenvParserPath,\n\t\tenvParserImportPattern,\n\t\tloggerPath,\n\t\tloggerImportPattern,\n\t\ttelescope,\n\t\tstudio,\n\t\thooks,\n\t\tproduction,\n\t\tdockerServices,\n\t};\n\n\t// Initialize generators\n\tconst endpointGenerator = new EndpointGenerator();\n\tconst functionGenerator = new FunctionGenerator();\n\tconst cronGenerator = new CronGenerator();\n\tconst subscriberGenerator = new SubscriberGenerator();\n\n\t// Load all constructs in parallel\n\tconst [allEndpoints, allFunctions, allCrons, allSubscribers] =\n\t\tawait Promise.all([\n\t\t\tendpointGenerator.load(config.routes),\n\t\t\tconfig.functions ? functionGenerator.load(config.functions) : [],\n\t\t\tconfig.crons ? cronGenerator.load(config.crons) : [],\n\t\t\tconfig.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n\t\t]);\n\n\tlogger.log(`Found ${allEndpoints.length} endpoints`);\n\tlogger.log(`Found ${allFunctions.length} functions`);\n\tlogger.log(`Found ${allCrons.length} crons`);\n\tlogger.log(`Found ${allSubscribers.length} subscribers`);\n\n\tif (\n\t\tallEndpoints.length === 0 &&\n\t\tallFunctions.length === 0 &&\n\t\tallCrons.length === 0 &&\n\t\tallSubscribers.length === 0\n\t) {\n\t\tlogger.log(\n\t\t\t'No endpoints, functions, crons, or subscribers found to process',\n\t\t);\n\t\treturn {};\n\t}\n\n\t// Ensure .gkm directory exists\n\tconst rootOutputDir = join(process.cwd(), '.gkm');\n\tawait mkdir(rootOutputDir, { recursive: true });\n\n\t// Build for each provider and generate per-provider manifests\n\tlet result: BuildResult = {};\n\tfor (const provider of resolved.providers) {\n\t\tconst providerResult = await buildForProvider(\n\t\t\tprovider,\n\t\t\tbuildContext,\n\t\t\trootOutputDir,\n\t\t\tendpointGenerator,\n\t\t\tfunctionGenerator,\n\t\t\tcronGenerator,\n\t\t\tsubscriberGenerator,\n\t\t\tallEndpoints,\n\t\t\tallFunctions,\n\t\t\tallCrons,\n\t\t\tallSubscribers,\n\t\t\tresolved.enableOpenApi,\n\t\t\toptions.skipBundle ?? false,\n\t\t\toptions.stage,\n\t\t);\n\t\t// Keep the master key from the server provider\n\t\tif (providerResult.masterKey) {\n\t\t\tresult = providerResult;\n\t\t}\n\t}\n\treturn result;\n}\n\nasync function buildForProvider(\n\tprovider: LegacyProvider,\n\tcontext: BuildContext,\n\trootOutputDir: string,\n\tendpointGenerator: EndpointGenerator,\n\tfunctionGenerator: FunctionGenerator,\n\tcronGenerator: CronGenerator,\n\tsubscriberGenerator: SubscriberGenerator,\n\tendpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n\tfunctions: GeneratedConstruct<Function<any, any, any, any>>[],\n\tcrons: GeneratedConstruct<Cron<any, any, any, any>>[],\n\tsubscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n\tenableOpenApi: boolean,\n\tskipBundle: boolean,\n\tstage?: string,\n): Promise<BuildResult> {\n\tconst outputDir = join(process.cwd(), '.gkm', provider);\n\n\t// Ensure output directory exists\n\tawait mkdir(outputDir, { recursive: true });\n\n\tlogger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n\t// Build all constructs in parallel\n\tconst [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n\t\t[\n\t\t\tendpointGenerator.build(context, endpoints, outputDir, {\n\t\t\t\tprovider,\n\t\t\t\tenableOpenApi,\n\t\t\t}),\n\t\t\tfunctionGenerator.build(context, functions, outputDir, { provider }),\n\t\t\tcronGenerator.build(context, crons, outputDir, { provider }),\n\t\t\tsubscriberGenerator.build(context, subscribers, outputDir, { provider }),\n\t\t],\n\t);\n\n\tlogger.log(\n\t\t`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n\t);\n\n\t// Generate provider-specific manifest\n\tif (provider === 'server') {\n\t\t// For server, collect actual route metadata from endpoint constructs\n\t\tconst routeMetadata: RouteInfo[] = await Promise.all(\n\t\t\tendpoints.map(async ({ construct }) => ({\n\t\t\t\tpath: construct._path,\n\t\t\t\tmethod: construct.method,\n\t\t\t\thandler: '', // Not needed for server manifest\n\t\t\t\tauthorizer: construct.authorizer?.name ?? 'none',\n\t\t\t})),\n\t\t);\n\n\t\tconst appInfo: ServerAppInfo = {\n\t\t\thandler: relative(process.cwd(), join(outputDir, 'app.ts')),\n\t\t\tendpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n\t\t};\n\n\t\tawait generateServerManifest(\n\t\t\trootOutputDir,\n\t\t\tappInfo,\n\t\t\trouteMetadata,\n\t\t\tsubscriberInfos,\n\t\t);\n\n\t\t// Bundle for production if enabled\n\t\tlet masterKey: string | undefined;\n\t\tif (context.production?.bundle && !skipBundle) {\n\t\t\tlogger.log(`\\nš¦ Bundling production server...`);\n\t\t\tconst { bundleServer } = await import('./bundler');\n\n\t\t\t// Collect all constructs for environment variable validation\n\t\t\tconst allConstructs = [\n\t\t\t\t...endpoints.map((e) => e.construct),\n\t\t\t\t...functions.map((f) => f.construct),\n\t\t\t\t...crons.map((c) => c.construct),\n\t\t\t\t...subscribers.map((s) => s.construct),\n\t\t\t];\n\n\t\t\t// Get docker compose services for auto-populating env vars\n\t\t\tconst dockerServices = context.dockerServices;\n\n\t\t\tconst bundleResult = await bundleServer({\n\t\t\t\tentryPoint: join(outputDir, 'server.ts'),\n\t\t\t\toutputDir: join(outputDir, 'dist'),\n\t\t\t\tminify: context.production.minify,\n\t\t\t\tsourcemap: false,\n\t\t\t\texternal: context.production.external,\n\t\t\t\tstage,\n\t\t\t\tconstructs: allConstructs,\n\t\t\t\tdockerServices,\n\t\t\t});\n\t\t\tmasterKey = bundleResult.masterKey;\n\t\t\tlogger.log(`ā
Bundle complete: .gkm/server/dist/server.mjs`);\n\n\t\t\t// Display master key if secrets were injected\n\t\t\tif (masterKey) {\n\t\t\t\tlogger.log(`\\nš Secrets encrypted for deployment`);\n\t\t\t\tlogger.log(` Deploy with: GKM_MASTER_KEY=${masterKey}`);\n\t\t\t}\n\t\t}\n\n\t\treturn { masterKey };\n\t} else {\n\t\t// For AWS providers, generate AWS manifest\n\t\tawait generateAwsManifest(\n\t\t\trootOutputDir,\n\t\t\troutes,\n\t\t\tfunctionInfos,\n\t\t\tcronInfos,\n\t\t\tsubscriberInfos,\n\t\t);\n\t}\n\n\treturn {};\n}\n\n/**\n * Result of building a single app in a workspace.\n */\nexport interface AppBuildResult {\n\tappName: string;\n\ttype: 'backend' | 'frontend';\n\tsuccess: boolean;\n\toutputPath?: string;\n\terror?: string;\n}\n\n/**\n * Result of workspace build command.\n */\nexport interface WorkspaceBuildResult extends BuildResult {\n\tapps: AppBuildResult[];\n}\n\n/**\n * Detect available package manager.\n * @internal Exported for testing\n */\nexport function detectPackageManager(): 'pnpm' | 'npm' | 'yarn' {\n\tif (existsSync('pnpm-lock.yaml')) return 'pnpm';\n\tif (existsSync('yarn.lock')) return 'yarn';\n\treturn 'npm';\n}\n\n/**\n * Get the turbo command for running builds.\n * @internal Exported for testing\n */\nexport function getTurboCommand(\n\tpm: 'pnpm' | 'npm' | 'yarn',\n\tfilter?: string,\n): string {\n\tconst filterArg = filter ? ` --filter=${filter}` : '';\n\tswitch (pm) {\n\t\tcase 'pnpm':\n\t\t\treturn `pnpm exec turbo run build${filterArg}`;\n\t\tcase 'yarn':\n\t\t\treturn `yarn turbo run build${filterArg}`;\n\t\tcase 'npm':\n\t\t\treturn `npx turbo run build${filterArg}`;\n\t}\n}\n\n/**\n * Build all apps in a workspace using Turbo for dependency-ordered parallel builds.\n * @internal Exported for testing\n */\nexport async function workspaceBuildCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: BuildOptions,\n): Promise<WorkspaceBuildResult> {\n\tconst results: AppBuildResult[] = [];\n\tconst apps = Object.entries(workspace.apps);\n\tconst backendApps = apps.filter(([, app]) => app.type === 'backend');\n\tconst frontendApps = apps.filter(([, app]) => app.type === 'frontend');\n\n\tlogger.log(`\\nšļø Building workspace: ${workspace.name}`);\n\tlogger.log(\n\t\t` Backend apps: ${backendApps.map(([name]) => name).join(', ') || 'none'}`,\n\t);\n\tlogger.log(\n\t\t` Frontend apps: ${frontendApps.map(([name]) => name).join(', ') || 'none'}`,\n\t);\n\n\tif (options.production) {\n\t\tlogger.log(` š Production mode enabled`);\n\t}\n\n\t// Get build order (topologically sorted by dependencies)\n\tconst buildOrder = getAppBuildOrder(workspace);\n\tlogger.log(` Build order: ${buildOrder.join(' ā ')}`);\n\n\t// Use Turbo for parallel builds with dependency awareness\n\tconst pm = detectPackageManager();\n\tlogger.log(`\\nš¦ Using ${pm} with Turbo for parallel builds...\\n`);\n\n\ttry {\n\t\t// Run turbo build which handles dependency ordering and parallelization\n\t\tconst turboCommand = getTurboCommand(pm);\n\t\tlogger.log(`Running: ${turboCommand}`);\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tconst child = spawn(turboCommand, {\n\t\t\t\tshell: true,\n\t\t\t\tcwd: workspace.root,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: {\n\t\t\t\t\t...process.env,\n\t\t\t\t\t// Pass production flag to builds\n\t\t\t\t\tNODE_ENV: options.production ? 'production' : 'development',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tchild.on('close', (code) => {\n\t\t\t\tif (code === 0) {\n\t\t\t\t\tresolve();\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Turbo build failed with exit code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tchild.on('error', (err) => {\n\t\t\t\treject(err);\n\t\t\t});\n\t\t});\n\n\t\t// Mark all apps as successful\n\t\tfor (const [appName, app] of apps) {\n\t\t\tconst outputPath = getAppOutputPath(workspace, appName, app);\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: true,\n\t\t\t\toutputPath,\n\t\t\t});\n\t\t}\n\n\t\tlogger.log(`\\nā
Workspace build complete!`);\n\n\t\t// Summary\n\t\tlogger.log(`\\nš Build Summary:`);\n\t\tfor (const result of results) {\n\t\t\tconst icon = result.type === 'backend' ? 'āļø' : 'š';\n\t\t\tlogger.log(\n\t\t\t\t` ${icon} ${result.appName}: ${result.outputPath || 'built'}`,\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\tconst errorMessage =\n\t\t\terror instanceof Error ? error.message : 'Build failed';\n\t\tlogger.log(`\\nā Build failed: ${errorMessage}`);\n\n\t\t// Mark all apps as failed\n\t\tfor (const [appName, app] of apps) {\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage,\n\t\t\t});\n\t\t}\n\n\t\tthrow error;\n\t}\n\n\treturn { apps: results };\n}\n\n/**\n * Get the output path for a built app.\n */\nfunction getAppOutputPath(\n\tworkspace: NormalizedWorkspace,\n\t_appName: string,\n\tapp: NormalizedAppConfig,\n): string {\n\tconst appPath = join(workspace.root, app.path);\n\n\tif (app.type === 'frontend') {\n\t\t// Next.js standalone output\n\t\treturn join(appPath, '.next');\n\t} else {\n\t\t// Backend .gkm output\n\t\treturn join(appPath, '.gkm');\n\t}\n}\n","import type {\n\tComposeServiceName,\n\tComposeServicesConfig,\n\tServiceConfig,\n} from '../types';\nimport type {\n\tNormalizedAppConfig,\n\tNormalizedWorkspace,\n} from '../workspace/types.js';\n\n/** Default Docker images for services */\nexport const DEFAULT_SERVICE_IMAGES: Record<ComposeServiceName, string> = {\n\tpostgres: 'postgres',\n\tredis: 'redis',\n\trabbitmq: 'rabbitmq',\n};\n\n/** Default Docker image versions for services */\nexport const DEFAULT_SERVICE_VERSIONS: Record<ComposeServiceName, string> = {\n\tpostgres: '16-alpine',\n\tredis: '7-alpine',\n\trabbitmq: '3-management-alpine',\n};\n\nexport interface ComposeOptions {\n\timageName: string;\n\tregistry: string;\n\tport: number;\n\thealthCheckPath: string;\n\t/** Services config - object format or legacy array format */\n\tservices: ComposeServicesConfig | ComposeServiceName[];\n}\n\n/** Get the default full image reference for a service */\nfunction getDefaultImage(serviceName: ComposeServiceName): string {\n\treturn `${DEFAULT_SERVICE_IMAGES[serviceName]}:${DEFAULT_SERVICE_VERSIONS[serviceName]}`;\n}\n\n/** Normalize services config to a consistent format - returns Map of service name to full image reference */\nfunction normalizeServices(\n\tservices: ComposeServicesConfig | ComposeServiceName[],\n): Map<ComposeServiceName, string> {\n\tconst result = new Map<ComposeServiceName, string>();\n\n\tif (Array.isArray(services)) {\n\t\t// Legacy array format - use default images\n\t\tfor (const name of services) {\n\t\t\tresult.set(name, getDefaultImage(name));\n\t\t}\n\t} else {\n\t\t// Object format\n\t\tfor (const [name, config] of Object.entries(services)) {\n\t\t\tconst serviceName = name as ComposeServiceName;\n\t\t\tif (config === true) {\n\t\t\t\t// boolean true - use default image\n\t\t\t\tresult.set(serviceName, getDefaultImage(serviceName));\n\t\t\t} else if (config && typeof config === 'object') {\n\t\t\t\tconst serviceConfig = config as ServiceConfig;\n\t\t\t\tif (serviceConfig.image) {\n\t\t\t\t\t// Full image reference provided\n\t\t\t\t\tresult.set(serviceName, serviceConfig.image);\n\t\t\t\t} else {\n\t\t\t\t\t// Version only - use default image name with custom version\n\t\t\t\t\tconst version =\n\t\t\t\t\t\tserviceConfig.version ?? DEFAULT_SERVICE_VERSIONS[serviceName];\n\t\t\t\t\tresult.set(\n\t\t\t\t\t\tserviceName,\n\t\t\t\t\t\t`${DEFAULT_SERVICE_IMAGES[serviceName]}:${version}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// false or undefined - skip\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Generate docker-compose.yml for production deployment\n */\nexport function generateDockerCompose(options: ComposeOptions): string {\n\tconst { imageName, registry, port, healthCheckPath, services } = options;\n\n\t// Normalize services to Map<name, version>\n\tconst serviceMap = normalizeServices(services);\n\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\tlet yaml = `version: '3.8'\n\nservices:\n api:\n build:\n context: ../..\n dockerfile: .gkm/docker/Dockerfile\n image: ${imageRef}\\${IMAGE_NAME:-${imageName}}:\\${TAG:-latest}\n container_name: ${imageName}\n restart: unless-stopped\n ports:\n - \"\\${PORT:-${port}}:${port}\"\n environment:\n - NODE_ENV=production\n`;\n\n\t// Add environment variables based on services\n\tif (serviceMap.has('postgres')) {\n\t\tyaml += ` - DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/app}\n`;\n\t}\n\n\tif (serviceMap.has('redis')) {\n\t\tyaml += ` - REDIS_URL=\\${REDIS_URL:-redis://redis:6379}\n`;\n\t}\n\n\tif (serviceMap.has('rabbitmq')) {\n\t\tyaml += ` - RABBITMQ_URL=\\${RABBITMQ_URL:-amqp://rabbitmq:5672}\n`;\n\t}\n\n\tyaml += ` healthcheck:\n test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${port}${healthCheckPath}\"]\n interval: 30s\n timeout: 3s\n retries: 3\n`;\n\n\t// Add depends_on if there are services\n\tif (serviceMap.size > 0) {\n\t\tyaml += ` depends_on:\n`;\n\t\tfor (const serviceName of serviceMap.keys()) {\n\t\t\tyaml += ` ${serviceName}:\n condition: service_healthy\n`;\n\t\t}\n\t}\n\n\tyaml += ` networks:\n - app-network\n`;\n\n\t// Add service definitions with images\n\tconst postgresImage = serviceMap.get('postgres');\n\tif (postgresImage) {\n\t\tyaml += `\n postgres:\n image: ${postgresImage}\n container_name: postgres\n restart: unless-stopped\n environment:\n POSTGRES_USER: \\${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: \\${POSTGRES_PASSWORD:-postgres}\n POSTGRES_DB: \\${POSTGRES_DB:-app}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\tconst redisImage = serviceMap.get('redis');\n\tif (redisImage) {\n\t\tyaml += `\n redis:\n image: ${redisImage}\n container_name: redis\n restart: unless-stopped\n volumes:\n - redis_data:/data\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\tconst rabbitmqImage = serviceMap.get('rabbitmq');\n\tif (rabbitmqImage) {\n\t\tyaml += `\n rabbitmq:\n image: ${rabbitmqImage}\n container_name: rabbitmq\n restart: unless-stopped\n environment:\n RABBITMQ_DEFAULT_USER: \\${RABBITMQ_USER:-guest}\n RABBITMQ_DEFAULT_PASS: \\${RABBITMQ_PASSWORD:-guest}\n ports:\n - \"15672:15672\" # Management UI\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n healthcheck:\n test: [\"CMD\", \"rabbitmq-diagnostics\", \"-q\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 5\n networks:\n - app-network\n`;\n\t}\n\n\t// Add volumes\n\tyaml += `\nvolumes:\n`;\n\n\tif (serviceMap.has('postgres')) {\n\t\tyaml += ` postgres_data:\n`;\n\t}\n\n\tif (serviceMap.has('redis')) {\n\t\tyaml += ` redis_data:\n`;\n\t}\n\n\tif (serviceMap.has('rabbitmq')) {\n\t\tyaml += ` rabbitmq_data:\n`;\n\t}\n\n\t// Add networks\n\tyaml += `\nnetworks:\n app-network:\n driver: bridge\n`;\n\n\treturn yaml;\n}\n\n/**\n * Generate a minimal docker-compose.yml for API only\n */\nexport function generateMinimalDockerCompose(\n\toptions: Omit<ComposeOptions, 'services'>,\n): string {\n\tconst { imageName, registry, port, healthCheckPath } = options;\n\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\treturn `version: '3.8'\n\nservices:\n api:\n build:\n context: ../..\n dockerfile: .gkm/docker/Dockerfile\n image: ${imageRef}\\${IMAGE_NAME:-${imageName}}:\\${TAG:-latest}\n container_name: ${imageName}\n restart: unless-stopped\n ports:\n - \"\\${PORT:-${port}}:${port}\"\n environment:\n - NODE_ENV=production\n healthcheck:\n test: [\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${port}${healthCheckPath}\"]\n interval: 30s\n timeout: 3s\n retries: 3\n networks:\n - app-network\n\nnetworks:\n app-network:\n driver: bridge\n`;\n}\n\n/**\n * Options for workspace compose generation.\n */\nexport interface WorkspaceComposeOptions {\n\t/** Container registry URL */\n\tregistry?: string;\n}\n\n/**\n * Generate docker-compose.yml for a workspace with all apps as services.\n * Apps can communicate with each other via service names.\n * @internal Exported for testing\n */\nexport function generateWorkspaceCompose(\n\tworkspace: NormalizedWorkspace,\n\toptions: WorkspaceComposeOptions = {},\n): string {\n\tconst { registry } = options;\n\tconst apps = Object.entries(workspace.apps);\n\tconst services = workspace.services;\n\n\t// Determine which infrastructure services to include\n\tconst hasPostgres = services.db !== undefined && services.db !== false;\n\tconst hasRedis = services.cache !== undefined && services.cache !== false;\n\tconst hasMail = services.mail !== undefined && services.mail !== false;\n\n\t// Get image versions from config\n\tconst postgresImage = getInfraServiceImage('postgres', services.db);\n\tconst redisImage = getInfraServiceImage('redis', services.cache);\n\n\tlet yaml = `# Docker Compose for ${workspace.name} workspace\n# Generated by gkm - do not edit manually\n\nservices:\n`;\n\n\t// Generate service for each app\n\tfor (const [appName, app] of apps) {\n\t\tyaml += generateAppService(appName, app, apps, {\n\t\t\tregistry,\n\t\t\thasPostgres,\n\t\t\thasRedis,\n\t\t});\n\t}\n\n\t// Add infrastructure services\n\tif (hasPostgres) {\n\t\tyaml += `\n postgres:\n image: ${postgresImage}\n container_name: ${workspace.name}-postgres\n restart: unless-stopped\n environment:\n POSTGRES_USER: \\${POSTGRES_USER:-postgres}\n POSTGRES_PASSWORD: \\${POSTGRES_PASSWORD:-postgres}\n POSTGRES_DB: \\${POSTGRES_DB:-app}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - workspace-network\n`;\n\t}\n\n\tif (hasRedis) {\n\t\tyaml += `\n redis:\n image: ${redisImage}\n container_name: ${workspace.name}-redis\n restart: unless-stopped\n volumes:\n - redis_data:/data\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 5s\n timeout: 5s\n retries: 5\n networks:\n - workspace-network\n`;\n\t}\n\n\tif (hasMail) {\n\t\tyaml += `\n mailpit:\n image: axllent/mailpit:latest\n container_name: ${workspace.name}-mailpit\n restart: unless-stopped\n ports:\n - \"8025:8025\" # Web UI\n - \"1025:1025\" # SMTP\n networks:\n - workspace-network\n`;\n\t}\n\n\t// Add volumes section\n\tyaml += `\nvolumes:\n`;\n\n\tif (hasPostgres) {\n\t\tyaml += ` postgres_data:\n`;\n\t}\n\n\tif (hasRedis) {\n\t\tyaml += ` redis_data:\n`;\n\t}\n\n\t// Add networks section\n\tyaml += `\nnetworks:\n workspace-network:\n driver: bridge\n`;\n\n\treturn yaml;\n}\n\n/**\n * Get infrastructure service image with version.\n */\nfunction getInfraServiceImage(\n\tserviceName: 'postgres' | 'redis',\n\tconfig: boolean | { version?: string; image?: string } | undefined,\n): string {\n\tconst defaults: Record<'postgres' | 'redis', string> = {\n\t\tpostgres: 'postgres:16-alpine',\n\t\tredis: 'redis:7-alpine',\n\t};\n\n\tif (!config || config === true) {\n\t\treturn defaults[serviceName];\n\t}\n\n\tif (typeof config === 'object') {\n\t\tif (config.image) {\n\t\t\treturn config.image;\n\t\t}\n\t\tif (config.version) {\n\t\t\tconst baseImage = serviceName === 'postgres' ? 'postgres' : 'redis';\n\t\t\treturn `${baseImage}:${config.version}`;\n\t\t}\n\t}\n\n\treturn defaults[serviceName];\n}\n\n/**\n * Generate a service definition for an app.\n */\nfunction generateAppService(\n\tappName: string,\n\tapp: NormalizedAppConfig,\n\tallApps: [string, NormalizedAppConfig][],\n\toptions: {\n\t\tregistry?: string;\n\t\thasPostgres: boolean;\n\t\thasRedis: boolean;\n\t},\n): string {\n\tconst { registry, hasPostgres, hasRedis } = options;\n\tconst imageRef = registry ? `\\${REGISTRY:-${registry}}/` : '';\n\n\t// Health check path - frontends use /, backends use /health\n\tconst healthCheckPath = app.type === 'frontend' ? '/' : '/health';\n\tconst healthCheckCmd =\n\t\tapp.type === 'frontend'\n\t\t\t? `[\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${app.port}/\"]`\n\t\t\t: `[\"CMD\", \"wget\", \"-q\", \"--spider\", \"http://localhost:${app.port}${healthCheckPath}\"]`;\n\n\tlet yaml = `\n ${appName}:\n build:\n context: .\n dockerfile: .gkm/docker/Dockerfile.${appName}\n image: ${imageRef}\\${${appName.toUpperCase()}_IMAGE:-${appName}}:\\${TAG:-latest}\n container_name: ${appName}\n restart: unless-stopped\n ports:\n - \"\\${${appName.toUpperCase()}_PORT:-${app.port}}:${app.port}\"\n environment:\n - NODE_ENV=production\n - PORT=${app.port}\n`;\n\n\t// Add dependency URLs - apps can reach other apps by service name\n\tfor (const dep of app.dependencies) {\n\t\tconst depApp = allApps.find(([name]) => name === dep)?.[1];\n\t\tif (depApp) {\n\t\t\tyaml += ` - ${dep.toUpperCase()}_URL=http://${dep}:${depApp.port}\n`;\n\t\t}\n\t}\n\n\t// Add infrastructure service URLs for backend apps\n\tif (app.type === 'backend') {\n\t\tif (hasPostgres) {\n\t\t\tyaml += ` - DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/app}\n`;\n\t\t}\n\t\tif (hasRedis) {\n\t\t\tyaml += ` - REDIS_URL=\\${REDIS_URL:-redis://redis:6379}\n`;\n\t\t}\n\t}\n\n\tyaml += ` healthcheck:\n test: ${healthCheckCmd}\n interval: 30s\n timeout: 3s\n retries: 3\n`;\n\n\t// Add depends_on for dependencies and infrastructure\n\tconst dependencies: string[] = [...app.dependencies];\n\tif (app.type === 'backend') {\n\t\tif (hasPostgres) dependencies.push('postgres');\n\t\tif (hasRedis) dependencies.push('redis');\n\t}\n\n\tif (dependencies.length > 0) {\n\t\tyaml += ` depends_on:\n`;\n\t\tfor (const dep of dependencies) {\n\t\t\tyaml += ` ${dep}:\n condition: service_healthy\n`;\n\t\t}\n\t}\n\n\tyaml += ` networks:\n - workspace-network\n`;\n\n\treturn yaml;\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\nimport type { DockerConfig, GkmConfig } from '../types';\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\nexport interface DockerTemplateOptions {\n\timageName: string;\n\tbaseImage: string;\n\tport: number;\n\thealthCheckPath: string;\n\t/** Whether the build is pre-built (slim Dockerfile) or needs building */\n\tprebuilt: boolean;\n\t/** Detected package manager */\n\tpackageManager: PackageManager;\n}\n\nexport interface FrontendDockerfileOptions {\n\timageName: string;\n\tbaseImage: string;\n\tport: number;\n\t/** App path relative to workspace root */\n\tappPath: string;\n\t/** Package name for turbo prune */\n\tturboPackage: string;\n\t/** Detected package manager */\n\tpackageManager: PackageManager;\n}\n\nexport interface MultiStageDockerfileOptions extends DockerTemplateOptions {\n\t/** Enable turbo prune for monorepo optimization */\n\tturbo?: boolean;\n\t/** Package name for turbo prune (defaults to current directory name) */\n\tturboPackage?: string;\n}\n\nconst LOCKFILES: [string, PackageManager][] = [\n\t['pnpm-lock.yaml', 'pnpm'],\n\t['bun.lockb', 'bun'],\n\t['yarn.lock', 'yarn'],\n\t['package-lock.json', 'npm'],\n];\n\n/**\n * Detect package manager from lockfiles\n * Walks up the directory tree to find lockfile (for monorepos)\n */\nexport function detectPackageManager(\n\tcwd: string = process.cwd(),\n): PackageManager {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\t// Walk up the directory tree\n\twhile (dir !== root) {\n\t\tfor (const [lockfile, pm] of LOCKFILES) {\n\t\t\tif (existsSync(join(dir, lockfile))) {\n\t\t\t\treturn pm;\n\t\t\t}\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\t// Check root directory\n\tfor (const [lockfile, pm] of LOCKFILES) {\n\t\tif (existsSync(join(root, lockfile))) {\n\t\t\treturn pm;\n\t\t}\n\t}\n\n\treturn 'pnpm'; // default\n}\n\n/**\n * Find the lockfile path by walking up the directory tree\n * Returns the full path to the lockfile, or null if not found\n */\nexport function findLockfilePath(cwd: string = process.cwd()): string | null {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\t// Walk up the directory tree\n\twhile (dir !== root) {\n\t\tfor (const [lockfile] of LOCKFILES) {\n\t\t\tconst lockfilePath = join(dir, lockfile);\n\t\t\tif (existsSync(lockfilePath)) {\n\t\t\t\treturn lockfilePath;\n\t\t\t}\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\t// Check root directory\n\tfor (const [lockfile] of LOCKFILES) {\n\t\tconst lockfilePath = join(root, lockfile);\n\t\tif (existsSync(lockfilePath)) {\n\t\t\treturn lockfilePath;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get the lockfile name for a package manager\n */\nexport function getLockfileName(pm: PackageManager): string {\n\tconst lockfileMap: Record<PackageManager, string> = {\n\t\tpnpm: 'pnpm-lock.yaml',\n\t\tnpm: 'package-lock.json',\n\t\tyarn: 'yarn.lock',\n\t\tbun: 'bun.lockb',\n\t};\n\treturn lockfileMap[pm];\n}\n\n/**\n * Check if we're in a monorepo (lockfile is in a parent directory)\n */\nexport function isMonorepo(cwd: string = process.cwd()): boolean {\n\tconst lockfilePath = findLockfilePath(cwd);\n\tif (!lockfilePath) {\n\t\treturn false;\n\t}\n\n\t// Check if lockfile is in a parent directory (not in cwd)\n\tconst lockfileDir = dirname(lockfilePath);\n\treturn lockfileDir !== cwd;\n}\n\n/**\n * Check if turbo.json exists (walks up directory tree)\n */\nexport function hasTurboConfig(cwd: string = process.cwd()): boolean {\n\tlet dir = cwd;\n\tconst root = parse(dir).root;\n\n\twhile (dir !== root) {\n\t\tif (existsSync(join(dir, 'turbo.json'))) {\n\t\t\treturn true;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\n\treturn existsSync(join(root, 'turbo.json'));\n}\n\n/**\n * Get install command for turbo builds (without frozen lockfile)\n * Turbo prune creates a subset that may not perfectly match the lockfile\n */\nfunction getTurboInstallCmd(pm: PackageManager): string {\n\tconst commands: Record<PackageManager, string> = {\n\t\tpnpm: 'pnpm install',\n\t\tnpm: 'npm install',\n\t\tyarn: 'yarn install',\n\t\tbun: 'bun install',\n\t};\n\treturn commands[pm];\n}\n\n/**\n * Get package manager specific commands and paths\n */\nfunction getPmConfig(pm: PackageManager) {\n\tconst configs = {\n\t\tpnpm: {\n\t\t\tinstall: 'corepack enable && corepack prepare pnpm@latest --activate',\n\t\t\tlockfile: 'pnpm-lock.yaml',\n\t\t\tfetch: 'pnpm fetch',\n\t\t\tinstallCmd: 'pnpm install --frozen-lockfile --offline',\n\t\t\tcacheTarget: '/root/.local/share/pnpm/store',\n\t\t\tcacheId: 'pnpm',\n\t\t\trun: 'pnpm',\n\t\t\texec: 'pnpm exec',\n\t\t\tdlx: 'pnpm dlx',\n\t\t\taddGlobal: 'pnpm add -g',\n\t\t},\n\t\tnpm: {\n\t\t\tinstall: '', // npm comes with node\n\t\t\tlockfile: 'package-lock.json',\n\t\t\tfetch: '', // npm doesn't have fetch\n\t\t\tinstallCmd: 'npm ci',\n\t\t\tcacheTarget: '/root/.npm',\n\t\t\tcacheId: 'npm',\n\t\t\trun: 'npm run',\n\t\t\texec: 'npx',\n\t\t\tdlx: 'npx',\n\t\t\taddGlobal: 'npm install -g',\n\t\t},\n\t\tyarn: {\n\t\t\tinstall: 'corepack enable && corepack prepare yarn@stable --activate',\n\t\t\tlockfile: 'yarn.lock',\n\t\t\tfetch: '', // yarn doesn't have fetch\n\t\t\tinstallCmd: 'yarn install --frozen-lockfile',\n\t\t\tcacheTarget: '/root/.yarn/cache',\n\t\t\tcacheId: 'yarn',\n\t\t\trun: 'yarn',\n\t\t\texec: 'yarn exec',\n\t\t\tdlx: 'yarn dlx',\n\t\t\taddGlobal: 'yarn global add',\n\t\t},\n\t\tbun: {\n\t\t\tinstall: 'npm install -g bun',\n\t\t\tlockfile: 'bun.lockb',\n\t\t\tfetch: '', // bun doesn't have fetch\n\t\t\tinstallCmd: 'bun install --frozen-lockfile',\n\t\t\tcacheTarget: '/root/.bun/install/cache',\n\t\t\tcacheId: 'bun',\n\t\t\trun: 'bun run',\n\t\t\texec: 'bunx',\n\t\t\tdlx: 'bunx',\n\t\t\taddGlobal: 'bun add -g',\n\t\t},\n\t};\n\treturn configs[pm];\n}\n\n/**\n * Generate a multi-stage Dockerfile for building from source\n * Optimized for build speed with:\n * - BuildKit cache mounts for package manager store\n * - pnpm fetch for better layer caching (when using pnpm)\n * - Optional turbo prune for monorepos\n */\nexport function generateMultiStageDockerfile(\n\toptions: MultiStageDockerfileOptions,\n): string {\n\tconst {\n\t\tbaseImage,\n\t\tport,\n\t\thealthCheckPath,\n\t\tturbo,\n\t\tturboPackage,\n\t\tpackageManager,\n\t} = options;\n\n\tif (turbo) {\n\t\treturn generateTurboDockerfile({\n\t\t\t...options,\n\t\t\tturboPackage: turboPackage ?? 'api',\n\t\t});\n\t}\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install\n\t\t? `\\n# Install ${packageManager}\\nRUN ${pm.install}\\n`\n\t\t: '';\n\tconst hasFetch = packageManager === 'pnpm';\n\n\t// pnpm has fetch which allows better caching\n\tconst depsStage = hasFetch\n\t\t? `# Copy lockfile first for better caching\nCOPY ${pm.lockfile} ./\n\n# Fetch dependencies (downloads to virtual store, cached separately)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.fetch}\n\n# Copy package.json after fetch\nCOPY package.json ./\n\n# Install from cache (fast - no network needed)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.installCmd}`\n\t\t: `# Copy package files\nCOPY package.json ${pm.lockfile} ./\n\n# Install dependencies with cache\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${pm.installCmd}`;\n\n\treturn `# syntax=docker/dockerfile:1\n# Stage 1: Dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n${installPm}\n${depsStage}\n\n# Stage 2: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy source (deps already installed)\nCOPY . .\n\n# Debug: Show node_modules/.bin contents and build production server\nRUN echo \"=== node_modules/.bin contents ===\" && \\\n ls -la node_modules/.bin/ 2>/dev/null || echo \"node_modules/.bin not found\" && \\\n echo \"=== Checking for gkm ===\" && \\\n which gkm 2>/dev/null || echo \"gkm not in PATH\" && \\\n ls -la node_modules/.bin/gkm 2>/dev/null || echo \"gkm binary not found in node_modules/.bin\" && \\\n echo \"=== Running build ===\" && \\\n ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 3: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\n# Install tini for proper signal handling as PID 1\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy bundled server\nCOPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./\n\n# Environment\nENV NODE_ENV=production\nENV PORT=${port}\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\n# Switch to non-root user\nUSER hono\n\nEXPOSE ${port}\n\n# Use tini as entrypoint to handle PID 1 responsibilities\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate a Dockerfile optimized for Turbo monorepos\n * Uses turbo prune to create minimal Docker context\n */\nfunction generateTurboDockerfile(options: MultiStageDockerfileOptions): string {\n\tconst { baseImage, port, healthCheckPath, turboPackage, packageManager } =\n\t\toptions;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\n\t// For turbo builds, we can't use --frozen-lockfile because turbo prune\n\t// creates a subset that may not perfectly match. Use relaxed install.\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\n\t// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies (no frozen-lockfile since turbo prune creates a subset)\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Debug: Show node_modules/.bin contents and build production server\nRUN echo \"=== node_modules/.bin contents ===\" && \\\n ls -la node_modules/.bin/ 2>/dev/null || echo \"node_modules/.bin not found\" && \\\n echo \"=== Checking for gkm ===\" && \\\n which gkm 2>/dev/null || echo \"gkm not in PATH\" && \\\n ls -la node_modules/.bin/gkm 2>/dev/null || echo \"gkm binary not found in node_modules/.bin\" && \\\n echo \"=== Running build ===\" && \\\n ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\nRUN apk add --no-cache tini\n\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\nCOPY --from=builder --chown=hono:nodejs /app/.gkm/server/dist/server.mjs ./\n\nENV NODE_ENV=production\nENV PORT=${port}\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\nUSER hono\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate a slim Dockerfile for pre-built bundles\n */\nexport function generateSlimDockerfile(options: DockerTemplateOptions): string {\n\tconst { baseImage, port, healthCheckPath } = options;\n\n\treturn `# Slim Dockerfile for pre-built production bundle\nFROM ${baseImage}\n\nWORKDIR /app\n\n# Install tini for proper signal handling as PID 1\n# Handles SIGTERM propagation and zombie process reaping\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy pre-built bundle\nCOPY .gkm/server/dist/server.mjs ./\n\n# Environment\nENV NODE_ENV=production\nENV PORT=${port}\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\n# Switch to non-root user\nUSER hono\n\nEXPOSE ${port}\n\n# Use tini as entrypoint to handle PID 1 responsibilities\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n\n/**\n * Generate .dockerignore file\n */\nexport function generateDockerignore(): string {\n\treturn `# Dependencies\nnode_modules\n.pnpm-store\n\n# Build output (except what we need)\n.gkm/aws*\n.gkm/server/*.ts\n!.gkm/server/dist\n\n# IDE and editor\n.idea\n.vscode\n*.swp\n*.swo\n\n# Git\n.git\n.gitignore\n\n# Logs\n*.log\nnpm-debug.log*\npnpm-debug.log*\n\n# Test files\n**/*.test.ts\n**/*.spec.ts\n**/__tests__\ncoverage\n\n# Documentation\ndocs\n*.md\n!README.md\n\n# Environment files (handle secrets separately)\n.env\n.env.*\n!.env.example\n\n# Docker files (don't copy recursively)\nDockerfile*\ndocker-compose*\n.dockerignore\n`;\n}\n\n/**\n * Generate docker-entrypoint.sh for custom startup logic\n */\nexport function generateDockerEntrypoint(): string {\n\treturn `#!/bin/sh\nset -e\n\n# Run any custom startup scripts here\n# Example: wait for database\n# until nc -z $DB_HOST $DB_PORT; do\n# echo \"Waiting for database...\"\n# sleep 1\n# done\n\n# Execute the main command\nexec \"$@\"\n`;\n}\n\n/**\n * Resolve Docker configuration from GkmConfig with defaults\n */\nexport function resolveDockerConfig(\n\tconfig: GkmConfig,\n): Required<Omit<DockerConfig, 'compose'>> & Pick<DockerConfig, 'compose'> {\n\tconst docker = config.docker ?? {};\n\n\t// Try to get image name from package.json name\n\tlet defaultImageName = 'api';\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\tconst pkg = require(`${process.cwd()}/package.json`);\n\t\tif (pkg.name) {\n\t\t\t// Remove scope and use just the package name\n\t\t\tdefaultImageName = pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore if package.json doesn't exist\n\t}\n\n\treturn {\n\t\tregistry: docker.registry ?? '',\n\t\timageName: docker.imageName ?? defaultImageName,\n\t\tbaseImage: docker.baseImage ?? 'node:22-alpine',\n\t\tport: docker.port ?? 3000,\n\t\tcompose: docker.compose,\n\t};\n}\n\n/**\n * Generate a Dockerfile for Next.js frontend apps using standalone output.\n * Uses turbo prune for monorepo optimization.\n * @internal Exported for testing\n */\nexport function generateNextjsDockerfile(\n\toptions: FrontendDockerfileOptions,\n): string {\n\tconst { baseImage, port, appPath, turboPackage, packageManager } = options;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\n\t// For turbo builds, we can't use --frozen-lockfile because turbo prune\n\t// creates a subset that may not perfectly match. Use relaxed install.\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\n\t// Use pnpm dlx for pnpm (avoids global bin dir issues in Docker)\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Next.js standalone Dockerfile with turbo prune optimization\n\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Set Next.js to produce standalone output\nENV NEXT_TELEMETRY_DISABLED=1\n\n# Build the application\nRUN ${turboCmd} run build --filter=${turboPackage}\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\n# Install tini for proper signal handling\nRUN apk add --no-cache tini\n\n# Create non-root user\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 nextjs\n\n# Set environment\nENV NODE_ENV=production\nENV NEXT_TELEMETRY_DISABLED=1\nENV PORT=${port}\nENV HOSTNAME=\"0.0.0.0\"\n\n# Copy static files and standalone output\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/standalone ./\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/.next/static ./${appPath}/.next/static\nCOPY --from=builder --chown=nextjs:nodejs /app/${appPath}/public ./${appPath}/public\n\n# Health check\nHEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}/ || exit 1\n\nUSER nextjs\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"${appPath}/server.js\"]\n`;\n}\n\n/**\n * Generate a Dockerfile for backend apps in a workspace.\n * Uses turbo prune for monorepo optimization.\n * @internal Exported for testing\n */\nexport function generateBackendDockerfile(\n\toptions: FrontendDockerfileOptions & { healthCheckPath?: string },\n): string {\n\tconst {\n\t\tbaseImage,\n\t\tport,\n\t\tappPath,\n\t\tturboPackage,\n\t\tpackageManager,\n\t\thealthCheckPath = '/health',\n\t} = options;\n\n\tconst pm = getPmConfig(packageManager);\n\tconst installPm = pm.install ? `RUN ${pm.install}` : '';\n\tconst turboInstallCmd = getTurboInstallCmd(packageManager);\n\tconst turboCmd = packageManager === 'pnpm' ? 'pnpm dlx turbo' : 'npx turbo';\n\n\treturn `# syntax=docker/dockerfile:1\n# Backend Dockerfile with turbo prune optimization\n\n# Stage 1: Prune monorepo\nFROM ${baseImage} AS pruner\n\nWORKDIR /app\n\n${installPm}\n\nCOPY . .\n\n# Prune to only include necessary packages\nRUN ${turboCmd} prune ${turboPackage} --docker\n\n# Stage 2: Install dependencies\nFROM ${baseImage} AS deps\n\nWORKDIR /app\n\n${installPm}\n\n# Copy pruned lockfile and package.jsons\nCOPY --from=pruner /app/out/${pm.lockfile} ./\nCOPY --from=pruner /app/out/json/ ./\n\n# Install dependencies\nRUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\\\\n ${turboInstallCmd}\n\n# Stage 3: Build\nFROM deps AS builder\n\nWORKDIR /app\n\n# Copy pruned source\nCOPY --from=pruner /app/out/full/ ./\n\n# Build production server using gkm\nRUN cd ${appPath} && ./node_modules/.bin/gkm build --provider server --production\n\n# Stage 4: Production\nFROM ${baseImage} AS runner\n\nWORKDIR /app\n\nRUN apk add --no-cache tini\n\nRUN addgroup --system --gid 1001 nodejs && \\\\\n adduser --system --uid 1001 hono\n\n# Copy bundled server\nCOPY --from=builder --chown=hono:nodejs /app/${appPath}/.gkm/server/dist/server.mjs ./\n\nENV NODE_ENV=production\nENV PORT=${port}\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\\\\n CMD wget -q --spider http://localhost:${port}${healthCheckPath} || exit 1\n\nUSER hono\n\nEXPOSE ${port}\n\nENTRYPOINT [\"/sbin/tini\", \"--\"]\nCMD [\"node\", \"server.mjs\"]\n`;\n}\n","import { execSync } from 'node:child_process';\nimport { copyFileSync, existsSync, unlinkSync } from 'node:fs';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { loadConfig, loadWorkspaceConfig } from '../config';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport {\n\tgenerateDockerCompose,\n\tgenerateMinimalDockerCompose,\n\tgenerateWorkspaceCompose,\n} from './compose';\nimport {\n\tdetectPackageManager,\n\tfindLockfilePath,\n\tgenerateBackendDockerfile,\n\tgenerateDockerEntrypoint,\n\tgenerateDockerignore,\n\tgenerateMultiStageDockerfile,\n\tgenerateNextjsDockerfile,\n\tgenerateSlimDockerfile,\n\thasTurboConfig,\n\tisMonorepo,\n\tresolveDockerConfig,\n} from './templates';\n\nexport {\n\tdetectPackageManager,\n\tfindLockfilePath,\n\thasTurboConfig,\n\tisMonorepo,\n} from './templates';\n\nconst logger = console;\n\nexport interface DockerOptions {\n\t/** Build Docker image after generating files */\n\tbuild?: boolean;\n\t/** Push image to registry after building */\n\tpush?: boolean;\n\t/** Image tag (default: 'latest') */\n\ttag?: string;\n\t/** Container registry URL */\n\tregistry?: string;\n\t/** Use slim Dockerfile (requires pre-built bundle from `gkm build --production`) */\n\tslim?: boolean;\n\t/** Enable turbo prune for monorepo optimization */\n\tturbo?: boolean;\n\t/** Package name for turbo prune (defaults to package.json name) */\n\tturboPackage?: string;\n}\n\nexport interface DockerGeneratedFiles {\n\tdockerfile: string;\n\tdockerCompose: string;\n\tdockerignore: string;\n\tentrypoint: string;\n}\n\n/**\n * Docker command implementation\n * Generates Dockerfile, docker-compose.yml, and related files\n *\n * Default: Multi-stage Dockerfile that builds from source inside Docker\n * --slim: Slim Dockerfile that copies pre-built bundle (requires prior build)\n */\nexport async function dockerCommand(\n\toptions: DockerOptions,\n): Promise<DockerGeneratedFiles | WorkspaceDockerResult> {\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace docker mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceDockerCommand(loadedConfig.workspace, options);\n\t}\n\n\t// Single-app mode - use existing logic\n\tconst config = await loadConfig();\n\tconst dockerConfig = resolveDockerConfig(config);\n\n\t// Get health check path from production config\n\tconst serverConfig =\n\t\ttypeof config.providers?.server === 'object'\n\t\t\t? config.providers.server\n\t\t\t: undefined;\n\tconst healthCheckPath = serverConfig?.production?.healthCheck ?? '/health';\n\n\t// Determine Dockerfile type\n\t// Default: Multi-stage (builds inside Docker for reproducibility)\n\t// --slim: Requires pre-built bundle\n\tconst useSlim = options.slim === true;\n\n\tif (useSlim) {\n\t\t// Verify pre-built bundle exists for slim mode\n\t\tconst distDir = join(process.cwd(), '.gkm', 'server', 'dist');\n\t\tconst hasBuild = existsSync(join(distDir, 'server.mjs'));\n\n\t\tif (!hasBuild) {\n\t\t\tthrow new Error(\n\t\t\t\t'Slim Dockerfile requires a pre-built bundle. Run `gkm build --provider server --production` first, or omit --slim to use multi-stage build.',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Generate Docker files\n\tconst dockerDir = join(process.cwd(), '.gkm', 'docker');\n\tawait mkdir(dockerDir, { recursive: true });\n\n\t// Detect package manager from lockfiles\n\tconst packageManager = detectPackageManager();\n\tconst inMonorepo = isMonorepo();\n\tconst hasTurbo = hasTurboConfig();\n\n\t// Auto-enable turbo for monorepos with turbo.json\n\tlet useTurbo = options.turbo ?? false;\n\tif (inMonorepo && !useSlim) {\n\t\tif (hasTurbo) {\n\t\t\tuseTurbo = true;\n\t\t\tlogger.log(' Detected monorepo with turbo.json - using turbo prune');\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t'Monorepo detected but turbo.json not found.\\n\\n' +\n\t\t\t\t\t'Docker builds in monorepos require Turborepo for proper dependency isolation.\\n\\n' +\n\t\t\t\t\t'To fix this:\\n' +\n\t\t\t\t\t' 1. Install turbo: pnpm add -Dw turbo\\n' +\n\t\t\t\t\t' 2. Create turbo.json in your monorepo root\\n' +\n\t\t\t\t\t' 3. Run this command again\\n\\n' +\n\t\t\t\t\t'See: https://turbo.build/repo/docs/guides/tools/docker',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Get the actual package name from package.json for turbo prune\n\tlet turboPackage = options.turboPackage ?? dockerConfig.imageName;\n\tif (useTurbo && !options.turboPackage) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\t\tconst pkg = require(`${process.cwd()}/package.json`);\n\t\t\tif (pkg.name) {\n\t\t\t\tturboPackage = pkg.name;\n\t\t\t\tlogger.log(` Turbo package: ${turboPackage}`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall back to imageName\n\t\t}\n\t}\n\n\tconst templateOptions = {\n\t\timageName: dockerConfig.imageName,\n\t\tbaseImage: dockerConfig.baseImage,\n\t\tport: dockerConfig.port,\n\t\thealthCheckPath,\n\t\tprebuilt: useSlim,\n\t\tturbo: useTurbo,\n\t\tturboPackage,\n\t\tpackageManager,\n\t};\n\n\t// Generate Dockerfile\n\tconst dockerfile = useSlim\n\t\t? generateSlimDockerfile(templateOptions)\n\t\t: generateMultiStageDockerfile(templateOptions);\n\n\tconst dockerMode = useSlim ? 'slim' : useTurbo ? 'turbo' : 'multi-stage';\n\n\tconst dockerfilePath = join(dockerDir, 'Dockerfile');\n\tawait writeFile(dockerfilePath, dockerfile);\n\tlogger.log(\n\t\t`Generated: .gkm/docker/Dockerfile (${dockerMode}, ${packageManager})`,\n\t);\n\n\t// Generate docker-compose.yml\n\tconst composeOptions = {\n\t\timageName: dockerConfig.imageName,\n\t\tregistry: options.registry ?? dockerConfig.registry,\n\t\tport: dockerConfig.port,\n\t\thealthCheckPath,\n\t\tservices: dockerConfig.compose?.services ?? {},\n\t};\n\n\t// Check if there are any services configured\n\tconst hasServices = Array.isArray(composeOptions.services)\n\t\t? composeOptions.services.length > 0\n\t\t: Object.keys(composeOptions.services).length > 0;\n\n\tconst dockerCompose = hasServices\n\t\t? generateDockerCompose(composeOptions)\n\t\t: generateMinimalDockerCompose(composeOptions);\n\n\tconst composePath = join(dockerDir, 'docker-compose.yml');\n\tawait writeFile(composePath, dockerCompose);\n\tlogger.log('Generated: .gkm/docker/docker-compose.yml');\n\n\t// Generate .dockerignore in project root (Docker looks for it there)\n\tconst dockerignore = generateDockerignore();\n\tconst dockerignorePath = join(process.cwd(), '.dockerignore');\n\tawait writeFile(dockerignorePath, dockerignore);\n\tlogger.log('Generated: .dockerignore (project root)');\n\n\t// Generate docker-entrypoint.sh\n\tconst entrypoint = generateDockerEntrypoint();\n\tconst entrypointPath = join(dockerDir, 'docker-entrypoint.sh');\n\tawait writeFile(entrypointPath, entrypoint);\n\tlogger.log('Generated: .gkm/docker/docker-entrypoint.sh');\n\n\tconst result: DockerGeneratedFiles = {\n\t\tdockerfile: dockerfilePath,\n\t\tdockerCompose: composePath,\n\t\tdockerignore: dockerignorePath,\n\t\tentrypoint: entrypointPath,\n\t};\n\n\t// Build Docker image if requested\n\tif (options.build) {\n\t\tawait buildDockerImage(dockerConfig.imageName, options);\n\t}\n\n\t// Push Docker image if requested\n\tif (options.push) {\n\t\tawait pushDockerImage(dockerConfig.imageName, options);\n\t}\n\n\treturn result;\n}\n\n/**\n * Ensure lockfile exists in the build context\n * For monorepos, copies from workspace root if needed\n * Returns cleanup function if file was copied\n */\nfunction ensureLockfile(cwd: string): (() => void) | null {\n\tconst lockfilePath = findLockfilePath(cwd);\n\n\tif (!lockfilePath) {\n\t\tlogger.warn(\n\t\t\t'\\nā ļø No lockfile found. Docker build may fail or use stale dependencies.',\n\t\t);\n\t\treturn null;\n\t}\n\n\tconst lockfileName = basename(lockfilePath);\n\tconst localLockfile = join(cwd, lockfileName);\n\n\t// If lockfile exists locally (same directory), nothing to do\n\tif (lockfilePath === localLockfile) {\n\t\treturn null;\n\t}\n\n\tlogger.log(` Copying ${lockfileName} from monorepo root...`);\n\tcopyFileSync(lockfilePath, localLockfile);\n\n\t// Return cleanup function\n\treturn () => {\n\t\ttry {\n\t\t\tunlinkSync(localLockfile);\n\t\t} catch {\n\t\t\t// Ignore cleanup errors\n\t\t}\n\t};\n}\n\n/**\n * Build Docker image\n * Uses BuildKit for cache mount support\n */\nasync function buildDockerImage(\n\timageName: string,\n\toptions: DockerOptions,\n): Promise<void> {\n\tconst tag = options.tag ?? 'latest';\n\tconst registry = options.registry;\n\n\tconst fullImageName = registry\n\t\t? `${registry}/${imageName}:${tag}`\n\t\t: `${imageName}:${tag}`;\n\n\tlogger.log(`\\nš³ Building Docker image: ${fullImageName}`);\n\n\tconst cwd = process.cwd();\n\n\t// Ensure lockfile exists (copy from monorepo root if needed)\n\tconst cleanup = ensureLockfile(cwd);\n\n\ttry {\n\t\t// Use BuildKit for cache mount support (required for --mount=type=cache)\n\t\texecSync(\n\t\t\t`DOCKER_BUILDKIT=1 docker build -f .gkm/docker/Dockerfile -t ${fullImageName} .`,\n\t\t\t{\n\t\t\t\tcwd,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, DOCKER_BUILDKIT: '1' },\n\t\t\t},\n\t\t);\n\t\tlogger.log(`ā
Docker image built: ${fullImageName}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to build Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t} finally {\n\t\t// Clean up copied lockfile\n\t\tcleanup?.();\n\t}\n}\n\n/**\n * Push Docker image to registry\n */\nasync function pushDockerImage(\n\timageName: string,\n\toptions: DockerOptions,\n): Promise<void> {\n\tconst tag = options.tag ?? 'latest';\n\tconst registry = options.registry;\n\n\tif (!registry) {\n\t\tthrow new Error(\n\t\t\t'Registry is required to push Docker image. Use --registry or configure docker.registry in gkm.config.ts',\n\t\t);\n\t}\n\n\tconst fullImageName = `${registry}/${imageName}:${tag}`;\n\n\tlogger.log(`\\nš Pushing Docker image: ${fullImageName}`);\n\n\ttry {\n\t\texecSync(`docker push ${fullImageName}`, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t});\n\t\tlogger.log(`ā
Docker image pushed: ${fullImageName}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to push Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Result of generating Docker files for a single app in a workspace.\n */\nexport interface AppDockerResult {\n\tappName: string;\n\ttype: 'backend' | 'frontend';\n\tdockerfile: string;\n\timageName: string;\n}\n\n/**\n * Result of workspace docker command.\n */\nexport interface WorkspaceDockerResult {\n\tapps: AppDockerResult[];\n\tdockerCompose: string;\n\tdockerignore: string;\n}\n\n/**\n * Get the package name from package.json in an app directory.\n */\nfunction getAppPackageName(appPath: string): string | undefined {\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-require-imports\n\t\tconst pkg = require(`${appPath}/package.json`);\n\t\treturn pkg.name;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Generate Dockerfiles for all apps in a workspace.\n * @internal Exported for testing\n */\nexport async function workspaceDockerCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DockerOptions,\n): Promise<WorkspaceDockerResult> {\n\tconst results: AppDockerResult[] = [];\n\tconst apps = Object.entries(workspace.apps);\n\n\tlogger.log(`\\nš³ Generating Dockerfiles for workspace: ${workspace.name}`);\n\n\t// Create docker output directory\n\tconst dockerDir = join(workspace.root, '.gkm', 'docker');\n\tawait mkdir(dockerDir, { recursive: true });\n\n\t// Detect package manager\n\tconst packageManager = detectPackageManager(workspace.root);\n\tlogger.log(` Package manager: ${packageManager}`);\n\n\t// Generate Dockerfile for each app\n\tfor (const [appName, app] of apps) {\n\t\tconst appPath = app.path;\n\t\tconst fullAppPath = join(workspace.root, appPath);\n\n\t\t// Get package name for turbo prune (use package.json name or app name)\n\t\tconst turboPackage = getAppPackageName(fullAppPath) ?? appName;\n\n\t\t// Determine image name\n\t\tconst imageName = appName;\n\n\t\tlogger.log(`\\n š Generating Dockerfile for ${appName} (${app.type})`);\n\n\t\tlet dockerfile: string;\n\n\t\tif (app.type === 'frontend') {\n\t\t\t// Generate Next.js Dockerfile\n\t\t\tdockerfile = generateNextjsDockerfile({\n\t\t\t\timageName,\n\t\t\t\tbaseImage: 'node:22-alpine',\n\t\t\t\tport: app.port,\n\t\t\t\tappPath,\n\t\t\t\tturboPackage,\n\t\t\t\tpackageManager,\n\t\t\t});\n\t\t} else {\n\t\t\t// Generate backend Dockerfile\n\t\t\tdockerfile = generateBackendDockerfile({\n\t\t\t\timageName,\n\t\t\t\tbaseImage: 'node:22-alpine',\n\t\t\t\tport: app.port,\n\t\t\t\tappPath,\n\t\t\t\tturboPackage,\n\t\t\t\tpackageManager,\n\t\t\t\thealthCheckPath: '/health',\n\t\t\t});\n\t\t}\n\n\t\t// Write Dockerfile with app-specific name\n\t\tconst dockerfilePath = join(dockerDir, `Dockerfile.${appName}`);\n\t\tawait writeFile(dockerfilePath, dockerfile);\n\t\tlogger.log(` Generated: .gkm/docker/Dockerfile.${appName}`);\n\n\t\tresults.push({\n\t\t\tappName,\n\t\t\ttype: app.type,\n\t\t\tdockerfile: dockerfilePath,\n\t\t\timageName,\n\t\t});\n\t}\n\n\t// Generate shared .dockerignore\n\tconst dockerignore = generateDockerignore();\n\tconst dockerignorePath = join(workspace.root, '.dockerignore');\n\tawait writeFile(dockerignorePath, dockerignore);\n\tlogger.log(`\\n Generated: .dockerignore (workspace root)`);\n\n\t// Generate docker-compose.yml for workspace\n\tconst dockerCompose = generateWorkspaceCompose(workspace, {\n\t\tregistry: options.registry,\n\t});\n\tconst composePath = join(dockerDir, 'docker-compose.yml');\n\tawait writeFile(composePath, dockerCompose);\n\tlogger.log(` Generated: .gkm/docker/docker-compose.yml`);\n\n\t// Summary\n\tlogger.log(\n\t\t`\\nā
Generated ${results.length} Dockerfile(s) + docker-compose.yml`,\n\t);\n\tlogger.log('\\nš Build commands:');\n\tfor (const result of results) {\n\t\tconst icon = result.type === 'backend' ? 'āļø' : 'š';\n\t\tlogger.log(\n\t\t\t` ${icon} docker build -f .gkm/docker/Dockerfile.${result.appName} -t ${result.imageName} .`,\n\t\t);\n\t}\n\tlogger.log('\\nš Run all services:');\n\tlogger.log(' docker compose -f .gkm/docker/docker-compose.yml up --build');\n\n\treturn {\n\t\tapps: results,\n\t\tdockerCompose: composePath,\n\t\tdockerignore: dockerignorePath,\n\t};\n}\n","import { execSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport type { GkmConfig } from '../config';\nimport { dockerCommand, findLockfilePath, isMonorepo } from '../docker';\nimport type { DeployResult, DockerDeployConfig } from './types';\n\n/**\n * Get app name from package.json in the current working directory\n * Used for Dokploy app/project naming\n */\nexport function getAppNameFromCwd(): string | undefined {\n\tconst packageJsonPath = join(process.cwd(), 'package.json');\n\n\tif (!existsSync(packageJsonPath)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\t\tif (pkg.name) {\n\t\t\t// Strip org scope if present (e.g., @myorg/app -> app)\n\t\t\treturn pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore parse errors\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Get app name from package.json adjacent to the lockfile (project root)\n * Used for Docker image naming\n */\nexport function getAppNameFromPackageJson(): string | undefined {\n\tconst cwd = process.cwd();\n\n\t// Find the lockfile to determine the project root\n\tconst lockfilePath = findLockfilePath(cwd);\n\tif (!lockfilePath) {\n\t\treturn undefined;\n\t}\n\n\t// Use the package.json adjacent to the lockfile\n\tconst projectRoot = dirname(lockfilePath);\n\tconst packageJsonPath = join(projectRoot, 'package.json');\n\n\tif (!existsSync(packageJsonPath)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\t\tif (pkg.name) {\n\t\t\t// Strip org scope if present (e.g., @myorg/app -> app)\n\t\t\treturn pkg.name.replace(/^@[^/]+\\//, '');\n\t\t}\n\t} catch {\n\t\t// Ignore parse errors\n\t}\n\n\treturn undefined;\n}\n\nconst logger = console;\n\nexport interface DockerDeployOptions {\n\t/** Deployment stage */\n\tstage: string;\n\t/** Image tag */\n\ttag: string;\n\t/** Skip pushing to registry */\n\tskipPush?: boolean;\n\t/** Master key from build */\n\tmasterKey?: string;\n\t/** Docker config from gkm.config */\n\tconfig: DockerDeployConfig;\n}\n\n/**\n * Get the full image reference\n */\nexport function getImageRef(\n\tregistry: string | undefined,\n\timageName: string,\n\ttag: string,\n): string {\n\tif (registry) {\n\t\treturn `${registry}/${imageName}:${tag}`;\n\t}\n\treturn `${imageName}:${tag}`;\n}\n\n/**\n * Build Docker image\n */\nasync function buildImage(imageRef: string): Promise<void> {\n\tlogger.log(`\\nšØ Building Docker image: ${imageRef}`);\n\n\tconst cwd = process.cwd();\n\tconst inMonorepo = isMonorepo(cwd);\n\n\t// Generate appropriate Dockerfile\n\tif (inMonorepo) {\n\t\tlogger.log(' Generating Dockerfile for monorepo (turbo prune)...');\n\t} else {\n\t\tlogger.log(' Generating Dockerfile...');\n\t}\n\tawait dockerCommand({});\n\n\t// Determine build context and Dockerfile path\n\tlet buildCwd = cwd;\n\tlet dockerfilePath = '.gkm/docker/Dockerfile';\n\n\tif (inMonorepo) {\n\t\t// For monorepos, build from root so turbo prune can access all packages\n\t\tconst lockfilePath = findLockfilePath(cwd);\n\t\tif (lockfilePath) {\n\t\t\tconst monorepoRoot = dirname(lockfilePath);\n\t\t\tconst appRelPath = relative(monorepoRoot, cwd);\n\t\t\tdockerfilePath = join(appRelPath, '.gkm/docker/Dockerfile');\n\t\t\tbuildCwd = monorepoRoot;\n\t\t\tlogger.log(` Building from monorepo root: ${monorepoRoot}`);\n\t\t}\n\t}\n\n\ttry {\n\t\t// Build for linux/amd64 to ensure compatibility with most cloud servers\n\t\texecSync(\n\t\t\t`DOCKER_BUILDKIT=1 docker build --platform linux/amd64 -f ${dockerfilePath} -t ${imageRef} .`,\n\t\t\t{\n\t\t\t\tcwd: buildCwd,\n\t\t\t\tstdio: 'inherit',\n\t\t\t\tenv: { ...process.env, DOCKER_BUILDKIT: '1' },\n\t\t\t},\n\t\t);\n\t\tlogger.log(`ā
Image built: ${imageRef}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to build Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Push Docker image to registry\n */\nasync function pushImage(imageRef: string): Promise<void> {\n\tlogger.log(`\\nāļø Pushing image: ${imageRef}`);\n\n\ttry {\n\t\texecSync(`docker push ${imageRef}`, {\n\t\t\tcwd: process.cwd(),\n\t\t\tstdio: 'inherit',\n\t\t});\n\t\tlogger.log(`ā
Image pushed: ${imageRef}`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to push Docker image: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t);\n\t}\n}\n\n/**\n * Deploy using Docker (build and optionally push image)\n */\nexport async function deployDocker(\n\toptions: DockerDeployOptions,\n): Promise<DeployResult> {\n\tconst { stage, tag, skipPush, masterKey, config } = options;\n\n\t// imageName should always be set by resolveDockerConfig\n\tconst imageName = config.imageName!;\n\tconst imageRef = getImageRef(config.registry, imageName, tag);\n\n\t// Build image\n\tawait buildImage(imageRef);\n\n\t// Push to registry if not skipped\n\tif (!skipPush) {\n\t\tif (!config.registry) {\n\t\t\tlogger.warn(\n\t\t\t\t'\\nā ļø No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts',\n\t\t\t);\n\t\t} else {\n\t\t\tawait pushImage(imageRef);\n\t\t}\n\t}\n\n\t// Output deployment info\n\tlogger.log('\\nā
Docker deployment ready!');\n\tlogger.log(`\\nš Deployment details:`);\n\tlogger.log(` Image: ${imageRef}`);\n\tlogger.log(` Stage: ${stage}`);\n\n\tif (masterKey) {\n\t\tlogger.log(`\\nš Deploy with this environment variable:`);\n\t\tlogger.log(` GKM_MASTER_KEY=${masterKey}`);\n\t\tlogger.log('\\n Example docker run:');\n\t\tlogger.log(` docker run -e GKM_MASTER_KEY=${masterKey} ${imageRef}`);\n\t}\n\n\treturn {\n\t\timageRef,\n\t\tmasterKey,\n\t};\n}\n\n/**\n * Resolve Docker deploy config from gkm config\n * - imageName: from config, or cwd package.json, or 'app' (for Docker image)\n * - projectName: from root package.json, or 'app' (for Dokploy project)\n * - appName: from cwd package.json, or projectName (for Dokploy app within project)\n */\nexport function resolveDockerConfig(config: GkmConfig): DockerDeployConfig {\n\t// projectName comes from root package.json (monorepo name)\n\tconst projectName = getAppNameFromPackageJson() ?? 'app';\n\n\t// appName comes from cwd package.json (the app being deployed)\n\tconst appName = getAppNameFromCwd() ?? projectName;\n\n\t// imageName defaults to appName (cwd package.json)\n\tconst imageName = config.docker?.imageName ?? appName;\n\n\treturn {\n\t\tregistry: config.docker?.registry,\n\t\timageName,\n\t\tprojectName,\n\t\tappName,\n\t};\n}\n","import { getDokployRegistryId, getDokployToken } from '../auth';\nimport { DokployApi } from './dokploy-api';\nimport type { DeployResult, DokployDeployConfig } from './types';\n\nconst logger = console;\n\nexport interface DokployDeployOptions {\n\t/** Deployment stage */\n\tstage: string;\n\t/** Image tag */\n\ttag: string;\n\t/** Image reference */\n\timageRef: string;\n\t/** Master key from build */\n\tmasterKey?: string;\n\t/** Dokploy config from gkm.config */\n\tconfig: DokployDeployConfig;\n}\n\n/**\n * Get the Dokploy API token from stored credentials or environment\n */\nasync function getApiToken(): Promise<string> {\n\tconst token = await getDokployToken();\n\tif (!token) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found.\\n' +\n\t\t\t\t'Run \"gkm login --service dokploy\" to authenticate, or set DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n\treturn token;\n}\n\n/**\n * Create a Dokploy API client\n */\nasync function createApi(endpoint: string): Promise<DokployApi> {\n\tconst token = await getApiToken();\n\treturn new DokployApi({ baseUrl: endpoint, token });\n}\n\n/**\n * Deploy to Dokploy\n */\nexport async function deployDokploy(\n\toptions: DokployDeployOptions,\n): Promise<DeployResult> {\n\tconst { stage, imageRef, masterKey, config } = options;\n\n\tlogger.log(`\\nšÆ Deploying to Dokploy...`);\n\tlogger.log(` Endpoint: ${config.endpoint}`);\n\tlogger.log(` Application: ${config.applicationId}`);\n\n\tconst api = await createApi(config.endpoint);\n\n\t// Configure Docker provider with the image\n\tlogger.log(` Configuring Docker image: ${imageRef}`);\n\n\t// Determine registry credentials\n\tconst registryOptions: {\n\t\tregistryId?: string;\n\t\tusername?: string;\n\t\tpassword?: string;\n\t\tregistryUrl?: string;\n\t} = {};\n\n\tif (config.registryId) {\n\t\t// Use registry ID from config\n\t\tregistryOptions.registryId = config.registryId;\n\t\tlogger.log(` Using Dokploy registry: ${config.registryId}`);\n\t} else {\n\t\t// Try stored registry ID from credentials\n\t\tconst storedRegistryId = await getDokployRegistryId();\n\t\tif (storedRegistryId) {\n\t\t\tregistryOptions.registryId = storedRegistryId;\n\t\t\tlogger.log(` Using stored Dokploy registry: ${storedRegistryId}`);\n\t\t} else if (config.registryCredentials) {\n\t\t\t// Use explicit credentials from config\n\t\t\tregistryOptions.username = config.registryCredentials.username;\n\t\t\tregistryOptions.password = config.registryCredentials.password;\n\t\t\tregistryOptions.registryUrl = config.registryCredentials.registryUrl;\n\t\t\tlogger.log(\n\t\t\t\t` Using registry credentials for: ${config.registryCredentials.registryUrl}`,\n\t\t\t);\n\t\t} else {\n\t\t\t// Try environment variables\n\t\t\tconst username = process.env.DOCKER_REGISTRY_USERNAME;\n\t\t\tconst password = process.env.DOCKER_REGISTRY_PASSWORD;\n\t\t\tconst registryUrl = process.env.DOCKER_REGISTRY_URL || config.registry;\n\n\t\t\tif (username && password && registryUrl) {\n\t\t\t\tregistryOptions.username = username;\n\t\t\t\tregistryOptions.password = password;\n\t\t\t\tregistryOptions.registryUrl = registryUrl;\n\t\t\t\tlogger.log(` Using registry credentials from environment`);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait api.saveDockerProvider(config.applicationId, imageRef, registryOptions);\n\tlogger.log(' ā Docker provider configured');\n\n\t// Prepare environment variables\n\tconst envVars: Record<string, string> = {};\n\n\tif (masterKey) {\n\t\tenvVars.GKM_MASTER_KEY = masterKey;\n\t}\n\n\t// Update environment if we have variables to set\n\tif (Object.keys(envVars).length > 0) {\n\t\tlogger.log(' Updating environment variables...');\n\n\t\t// Convert env vars to the format Dokploy expects (KEY=VALUE per line)\n\t\tconst envString = Object.entries(envVars)\n\t\t\t.map(([key, value]) => `${key}=${value}`)\n\t\t\t.join('\\n');\n\n\t\tawait api.saveApplicationEnv(config.applicationId, envString);\n\t\tlogger.log(' ā Environment variables updated');\n\t}\n\n\t// Trigger deployment\n\tlogger.log(' Triggering deployment...');\n\tawait api.deployApplication(config.applicationId);\n\tlogger.log(' ā Deployment triggered');\n\n\tlogger.log('\\nā
Dokploy deployment initiated!');\n\tlogger.log(`\\nš Deployment details:`);\n\tlogger.log(` Image: ${imageRef}`);\n\tlogger.log(` Stage: ${stage}`);\n\tlogger.log(` Application ID: ${config.applicationId}`);\n\n\tif (masterKey) {\n\t\tlogger.log(`\\nš GKM_MASTER_KEY has been set in Dokploy environment`);\n\t}\n\n\t// Construct the probable deployment URL\n\tconst deploymentUrl = `${config.endpoint}/project/${config.projectId}`;\n\tlogger.log(`\\nš View deployment: ${deploymentUrl}`);\n\n\treturn {\n\t\timageRef,\n\t\tmasterKey,\n\t\turl: deploymentUrl,\n\t};\n}\n\n/**\n * Validate Dokploy configuration\n */\nexport function validateDokployConfig(\n\tconfig: Partial<DokployDeployConfig> | undefined,\n): config is DokployDeployConfig {\n\tif (!config) {\n\t\treturn false;\n\t}\n\n\tconst required = ['endpoint', 'projectId', 'applicationId'] as const;\n\tconst missing = required.filter((key) => !config[key]);\n\n\tif (missing.length > 0) {\n\t\tthrow new Error(\n\t\t\t`Missing Dokploy configuration: ${missing.join(', ')}\\n` +\n\t\t\t\t'Configure in gkm.config.ts:\\n' +\n\t\t\t\t' providers: {\\n' +\n\t\t\t\t' dokploy: {\\n' +\n\t\t\t\t\" endpoint: 'https://dokploy.example.com',\\n\" +\n\t\t\t\t\" projectId: 'proj_xxx',\\n\" +\n\t\t\t\t\" applicationId: 'app_xxx',\\n\" +\n\t\t\t\t' },\\n' +\n\t\t\t\t' }',\n\t\t);\n\t}\n\n\treturn true;\n}\n","import { existsSync } from 'node:fs';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport {\n\tgetDokployCredentials,\n\tgetDokployRegistryId,\n\tgetDokployToken,\n\tstoreDokployRegistryId,\n} from '../auth';\nimport { DokployApi } from './dokploy-api';\nimport type { DokployDeployConfig } from './types';\n\nconst logger = console;\n\nexport interface DeployInitOptions {\n\t/** Dokploy endpoint URL (optional if logged in) */\n\tendpoint?: string;\n\t/** Project name (creates new or uses existing) */\n\tprojectName: string;\n\t/** Application name */\n\tappName: string;\n\t/** Use existing project ID instead of creating/finding */\n\tprojectId?: string;\n\t/** Registry ID in Dokploy (optional, uses stored if available) */\n\tregistryId?: string;\n}\n\nexport interface RegistrySetupOptions {\n\t/** Dokploy endpoint URL (optional if logged in) */\n\tendpoint?: string;\n\t/** Registry name (for display in Dokploy) */\n\tregistryName: string;\n\t/** Registry URL (e.g., ghcr.io, docker.io) */\n\tregistryUrl: string;\n\t/** Registry username */\n\tusername: string;\n\t/** Registry password or token */\n\tpassword: string;\n\t/** Image prefix (optional, e.g., org-name) */\n\timagePrefix?: string;\n}\n\n/**\n * Get the Dokploy API token from stored credentials or environment\n */\nasync function getApiToken(): Promise<string> {\n\tconst token = await getDokployToken();\n\tif (!token) {\n\t\tthrow new Error(\n\t\t\t'Dokploy credentials not found.\\n' +\n\t\t\t\t'Run \"gkm login --service dokploy\" to authenticate, or set DOKPLOY_API_TOKEN.',\n\t\t);\n\t}\n\treturn token;\n}\n\n/**\n * Get Dokploy endpoint from options or stored credentials\n */\nasync function getEndpoint(providedEndpoint?: string): Promise<string> {\n\tif (providedEndpoint) {\n\t\treturn providedEndpoint;\n\t}\n\n\tconst stored = await getDokployCredentials();\n\tif (stored) {\n\t\treturn stored.endpoint;\n\t}\n\n\tthrow new Error(\n\t\t'Dokploy endpoint not specified.\\n' +\n\t\t\t'Either run \"gkm login --service dokploy\" first, or provide --endpoint.',\n\t);\n}\n\n/**\n * Create a Dokploy API client\n */\nasync function createApi(endpoint: string): Promise<DokployApi> {\n\tconst token = await getApiToken();\n\treturn new DokployApi({ baseUrl: endpoint, token });\n}\n\n/**\n * Update gkm.config.ts with Dokploy configuration\n */\nexport async function updateConfig(\n\tconfig: DokployDeployConfig,\n\tcwd: string = process.cwd(),\n): Promise<void> {\n\tconst configPath = join(cwd, 'gkm.config.ts');\n\n\tif (!existsSync(configPath)) {\n\t\tlogger.warn(\n\t\t\t'\\n gkm.config.ts not found. Add this configuration manually:\\n',\n\t\t);\n\t\tlogger.log(` providers: {`);\n\t\tlogger.log(` dokploy: {`);\n\t\tlogger.log(` endpoint: '${config.endpoint}',`);\n\t\tlogger.log(` projectId: '${config.projectId}',`);\n\t\tlogger.log(` applicationId: '${config.applicationId}',`);\n\t\tlogger.log(` },`);\n\t\tlogger.log(` },`);\n\t\treturn;\n\t}\n\n\tconst content = await readFile(configPath, 'utf-8');\n\n\t// Check if providers.dokploy already exists\n\tif (content.includes('dokploy:') && content.includes('applicationId:')) {\n\t\tlogger.log('\\n Dokploy config already exists in gkm.config.ts');\n\t\tlogger.log(' Updating with new values...');\n\t}\n\n\t// Build the dokploy config string\n\tconst registryLine = config.registryId\n\t\t? `\\n\\t\\t\\tregistryId: '${config.registryId}',`\n\t\t: '';\n\tconst dokployConfigStr = `dokploy: {\n\t\t\tendpoint: '${config.endpoint}',\n\t\t\tprojectId: '${config.projectId}',\n\t\t\tapplicationId: '${config.applicationId}',${registryLine}\n\t\t}`;\n\n\t// Try to add or update the dokploy config\n\tlet newContent: string;\n\n\tif (content.includes('providers:')) {\n\t\t// Add dokploy to existing providers\n\t\tif (content.includes('dokploy:')) {\n\t\t\t// Update existing dokploy config (handle multi-line with registryId)\n\t\t\tnewContent = content.replace(/dokploy:\\s*\\{[^}]*\\}/s, dokployConfigStr);\n\t\t} else {\n\t\t\t// Add dokploy to providers\n\t\t\tnewContent = content.replace(\n\t\t\t\t/providers:\\s*\\{/,\n\t\t\t\t`providers: {\\n\\t\\t${dokployConfigStr},`,\n\t\t\t);\n\t\t}\n\t} else {\n\t\t// Add providers section before the closing of defineConfig\n\t\tnewContent = content.replace(\n\t\t\t/}\\s*\\)\\s*;?\\s*$/,\n\t\t\t`\n\tproviders: {\n\t\t${dokployConfigStr},\n\t},\n});`,\n\t\t);\n\t}\n\n\tawait writeFile(configPath, newContent);\n\tlogger.log('\\n ā Updated gkm.config.ts with Dokploy configuration');\n}\n\n/**\n * Initialize Dokploy deployment configuration\n */\nexport async function deployInitCommand(\n\toptions: DeployInitOptions,\n): Promise<DokployDeployConfig> {\n\tconst {\n\t\tprojectName,\n\t\tappName,\n\t\tprojectId: existingProjectId,\n\t\tregistryId,\n\t} = options;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš Initializing Dokploy deployment...`);\n\tlogger.log(` Endpoint: ${endpoint}`);\n\n\t// Step 1: Find or create project\n\tlet projectId: string;\n\n\tif (existingProjectId) {\n\t\tprojectId = existingProjectId;\n\t\tlogger.log(`\\nš Using existing project: ${projectId}`);\n\t} else {\n\t\tlogger.log(`\\nš Looking for project: ${projectName}`);\n\n\t\tconst projects = await api.listProjects();\n\t\tconst existingProject = projects.find(\n\t\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t\t);\n\n\t\tif (existingProject) {\n\t\t\tprojectId = existingProject.projectId;\n\t\t\tlogger.log(` Found existing project: ${projectId}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating new project...`);\n\t\t\tconst result = await api.createProject(projectName);\n\t\t\tprojectId = result.project.projectId;\n\t\t\tlogger.log(` ā Created project: ${projectId}`);\n\t\t}\n\t}\n\n\t// Step 2: Get project to find environment\n\tconst project = await api.getProject(projectId);\n\tlet environmentId: string;\n\n\tconst firstEnv = project.environments?.[0];\n\tif (firstEnv) {\n\t\tenvironmentId = firstEnv.environmentId;\n\t} else {\n\t\t// Create a default environment\n\t\tlogger.log(` Creating production environment...`);\n\t\tconst env = await api.createEnvironment(projectId, 'production');\n\t\tenvironmentId = env.environmentId;\n\t}\n\n\t// Step 3: Create application\n\tlogger.log(`\\nš¦ Creating application: ${appName}`);\n\tconst application = await api.createApplication(\n\t\tappName,\n\t\tprojectId,\n\t\tenvironmentId,\n\t);\n\tlogger.log(` ā Created application: ${application.applicationId}`);\n\n\t// Step 4: Configure registry if provided\n\tif (registryId) {\n\t\tlogger.log(`\\nš§ Configuring registry: ${registryId}`);\n\t\tawait api.updateApplication(application.applicationId, { registryId });\n\t\tlogger.log(` ā Registry configured`);\n\t} else {\n\t\t// List available registries\n\t\ttry {\n\t\t\tconst registries = await api.listRegistries();\n\t\t\tif (registries.length > 0) {\n\t\t\t\tlogger.log(`\\nš Available registries:`);\n\t\t\t\tfor (const reg of registries) {\n\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t` - ${reg.registryName}: ${reg.registryUrl} (${reg.registryId})`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlogger.log(`\\n To use a registry, run with --registry-id <id>`);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore registry listing errors\n\t\t}\n\t}\n\n\t// Step 5: Build config\n\tconst config: DokployDeployConfig = {\n\t\tendpoint,\n\t\tprojectId,\n\t\tapplicationId: application.applicationId,\n\t};\n\n\t// Step 6: Update gkm.config.ts\n\tawait updateConfig(config);\n\n\tlogger.log(`\\nā
Dokploy deployment initialized!`);\n\tlogger.log(`\\nš Configuration:`);\n\tlogger.log(` Project ID: ${projectId}`);\n\tlogger.log(` Application ID: ${application.applicationId}`);\n\tlogger.log(`\\nš View in Dokploy: ${endpoint}/project/${projectId}`);\n\tlogger.log(`\\nš Next steps:`);\n\tlogger.log(` 1. Initialize secrets: gkm secrets:init --stage production`);\n\tlogger.log(` 2. Deploy: gkm deploy --provider dokploy --stage production`);\n\n\treturn config;\n}\n\n/**\n * List available Dokploy resources\n */\nexport async function deployListCommand(options: {\n\tendpoint?: string;\n\tresource: 'projects' | 'registries';\n}): Promise<void> {\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tconst { resource } = options;\n\n\tif (resource === 'projects') {\n\t\tlogger.log(`\\nš Projects in ${endpoint}:`);\n\t\tconst projects = await api.listProjects();\n\n\t\tif (projects.length === 0) {\n\t\t\tlogger.log(' No projects found');\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const project of projects) {\n\t\t\tlogger.log(`\\n ${project.name} (${project.projectId})`);\n\t\t\tif (project.description) {\n\t\t\t\tlogger.log(` ${project.description}`);\n\t\t\t}\n\t\t}\n\t} else if (resource === 'registries') {\n\t\tlogger.log(`\\nš³ Registries in ${endpoint}:`);\n\t\tconst registries = await api.listRegistries();\n\n\t\tif (registries.length === 0) {\n\t\t\tlogger.log(' No registries configured');\n\t\t\tlogger.log(' Run \"gkm registry:setup\" to configure a registry');\n\t\t\treturn;\n\t\t}\n\n\t\tconst storedRegistryId = await getDokployRegistryId();\n\n\t\tfor (const registry of registries) {\n\t\t\tconst isDefault = registry.registryId === storedRegistryId;\n\t\t\tconst marker = isDefault ? ' (default)' : '';\n\t\t\tlogger.log(\n\t\t\t\t`\\n ${registry.registryName}${marker} (${registry.registryId})`,\n\t\t\t);\n\t\t\tlogger.log(` URL: ${registry.registryUrl}`);\n\t\t\tlogger.log(` Username: ${registry.username}`);\n\t\t\tif (registry.imagePrefix) {\n\t\t\t\tlogger.log(` Prefix: ${registry.imagePrefix}`);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Setup a Docker registry in Dokploy\n */\nexport async function registrySetupCommand(\n\toptions: RegistrySetupOptions,\n): Promise<string> {\n\tconst { registryName, registryUrl, username, password, imagePrefix } =\n\t\toptions;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš³ Setting up Docker registry in Dokploy...`);\n\tlogger.log(` Endpoint: ${endpoint}`);\n\n\t// Check if registry with same URL already exists\n\tconst existingRegistries = await api.listRegistries();\n\tconst existing = existingRegistries.find(\n\t\t(r) =>\n\t\t\tr.registryUrl === registryUrl ||\n\t\t\tr.registryName.toLowerCase() === registryName.toLowerCase(),\n\t);\n\n\tlet registryId: string;\n\n\tif (existing) {\n\t\tlogger.log(`\\nš Found existing registry: ${existing.registryName}`);\n\t\tlogger.log(` Updating credentials...`);\n\n\t\tawait api.updateRegistry(existing.registryId, {\n\t\t\tregistryName,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\timagePrefix,\n\t\t});\n\n\t\tregistryId = existing.registryId;\n\t\tlogger.log(` ā Registry updated: ${registryId}`);\n\t} else {\n\t\tlogger.log(`\\nš¦ Creating registry: ${registryName}`);\n\n\t\tconst registry = await api.createRegistry(\n\t\t\tregistryName,\n\t\t\tregistryUrl,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\t{ imagePrefix },\n\t\t);\n\n\t\tregistryId = registry.registryId;\n\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t}\n\n\t// Store registry ID in credentials\n\tawait storeDokployRegistryId(registryId);\n\tlogger.log(`\\nš¾ Saved registry ID to ~/.gkm/credentials.json`);\n\n\tlogger.log(`\\nā
Registry setup complete!`);\n\tlogger.log(`\\nš Registry Details:`);\n\tlogger.log(` ID: ${registryId}`);\n\tlogger.log(` Name: ${registryName}`);\n\tlogger.log(` URL: ${registryUrl}`);\n\tlogger.log(` Username: ${username}`);\n\tif (imagePrefix) {\n\t\tlogger.log(` Prefix: ${imagePrefix}`);\n\t}\n\n\tlogger.log(\n\t\t`\\nš The registry ID is now stored and will be used automatically`,\n\t);\n\tlogger.log(` when deploying with \"gkm deploy --provider dokploy\"`);\n\n\treturn registryId;\n}\n\n/**\n * Use an existing registry (set as default)\n */\nexport async function registryUseCommand(options: {\n\tendpoint?: string;\n\tregistryId: string;\n}): Promise<void> {\n\tconst { registryId } = options;\n\n\tconst endpoint = await getEndpoint(options.endpoint);\n\tconst api = await createApi(endpoint);\n\n\tlogger.log(`\\nš§ Setting default registry...`);\n\n\t// Verify the registry exists\n\ttry {\n\t\tconst registry = await api.getRegistry(registryId);\n\t\tlogger.log(` Found registry: ${registry.registryName}`);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Registry not found: ${registryId}\\n` +\n\t\t\t\t'Run \"gkm deploy:list registries\" to see available registries.',\n\t\t);\n\t}\n\n\t// Store registry ID in credentials\n\tawait storeDokployRegistryId(registryId);\n\n\tlogger.log(`\\nā
Default registry set: ${registryId}`);\n\tlogger.log(` This registry will be used for future deployments.`);\n}\n","import { stdin as input, stdout as output } from 'node:process';\nimport * as readline from 'node:readline/promises';\nimport {\n\tgetDokployCredentials,\n\tgetDokployRegistryId,\n\tstoreDokployCredentials,\n\tvalidateDokployToken,\n} from '../auth';\nimport { storeDokployRegistryId } from '../auth/credentials';\nimport { buildCommand } from '../build/index';\nimport { type GkmConfig, loadConfig, loadWorkspaceConfig } from '../config';\nimport {\n\tgetAppBuildOrder,\n\tgetDeployTargetError,\n\tisDeployTargetSupported,\n} from '../workspace/index.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport { deployDocker, resolveDockerConfig } from './docker';\nimport { deployDokploy } from './dokploy';\nimport { DokployApi, type DokployApplication } from './dokploy-api';\nimport { updateConfig } from './init';\nimport type {\n\tAppDeployResult,\n\tDeployOptions,\n\tDeployProvider,\n\tDeployResult,\n\tDockerDeployConfig,\n\tDokployDeployConfig,\n\tWorkspaceDeployResult,\n} from './types';\n\nconst logger = console;\n\n/**\n * Prompt for input\n */\nasync function prompt(message: string, hidden = false): Promise<string> {\n\tif (!process.stdin.isTTY) {\n\t\tthrow new Error('Interactive input required. Please configure manually.');\n\t}\n\n\tif (hidden) {\n\t\tprocess.stdout.write(message);\n\t\treturn new Promise((resolve) => {\n\t\t\tlet value = '';\n\t\t\tconst onData = (char: Buffer) => {\n\t\t\t\tconst c = char.toString();\n\t\t\t\tif (c === '\\n' || c === '\\r') {\n\t\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\t\tprocess.stdin.pause();\n\t\t\t\t\tprocess.stdin.removeListener('data', onData);\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tresolve(value);\n\t\t\t\t} else if (c === '\\u0003') {\n\t\t\t\t\tprocess.stdin.setRawMode(false);\n\t\t\t\t\tprocess.stdin.pause();\n\t\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t} else if (c === '\\u007F' || c === '\\b') {\n\t\t\t\t\tif (value.length > 0) value = value.slice(0, -1);\n\t\t\t\t} else {\n\t\t\t\t\tvalue += c;\n\t\t\t\t}\n\t\t\t};\n\t\t\tprocess.stdin.setRawMode(true);\n\t\t\tprocess.stdin.resume();\n\t\t\tprocess.stdin.on('data', onData);\n\t\t});\n\t}\n\n\tconst rl = readline.createInterface({ input, output });\n\ttry {\n\t\treturn await rl.question(message);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\n/**\n * Docker compose services that can be provisioned\n */\ninterface DockerComposeServices {\n\tpostgres?: boolean;\n\tredis?: boolean;\n\trabbitmq?: boolean;\n}\n\n/**\n * Service URLs including both connection URLs and individual parameters\n */\ninterface ServiceUrls {\n\tDATABASE_URL?: string;\n\tDATABASE_HOST?: string;\n\tDATABASE_PORT?: string;\n\tDATABASE_NAME?: string;\n\tDATABASE_USER?: string;\n\tDATABASE_PASSWORD?: string;\n\tREDIS_URL?: string;\n\tREDIS_HOST?: string;\n\tREDIS_PORT?: string;\n\tREDIS_PASSWORD?: string;\n}\n\n/**\n * Result of Dokploy setup including provisioned service URLs\n */\ninterface DokploySetupResult {\n\tconfig: DokployDeployConfig;\n\tserviceUrls?: ServiceUrls;\n}\n\n/**\n * Provision docker compose services in Dokploy\n * @internal Exported for testing\n */\nexport async function provisionServices(\n\tapi: DokployApi,\n\tprojectId: string,\n\tenvironmentId: string | undefined,\n\tappName: string,\n\tservices?: DockerComposeServices,\n\texistingUrls?: Pick<ServiceUrls, 'DATABASE_URL' | 'REDIS_URL'>,\n): Promise<ServiceUrls | undefined> {\n\tlogger.log(\n\t\t`\\nš provisionServices called: services=${JSON.stringify(services)}, envId=${environmentId}`,\n\t);\n\tif (!services || !environmentId) {\n\t\tlogger.log(' Skipping: no services or no environmentId');\n\t\treturn undefined;\n\t}\n\n\tconst serviceUrls: ServiceUrls = {};\n\n\tif (services.postgres) {\n\t\t// Skip if DATABASE_URL already exists in secrets\n\t\tif (existingUrls?.DATABASE_URL) {\n\t\t\tlogger.log('\\nš PostgreSQL: Already configured (skipping)');\n\t\t} else {\n\t\t\tlogger.log('\\nš Provisioning PostgreSQL...');\n\t\t\tconst postgresName = `${appName}-db`;\n\n\t\t\ttry {\n\t\t\t\t// Generate a random password for the database\n\t\t\t\tconst { randomBytes } = await import('node:crypto');\n\t\t\t\tconst databasePassword = randomBytes(16).toString('hex');\n\n\t\t\t\tconst postgres = await api.createPostgres(\n\t\t\t\t\tpostgresName,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t\t{ databasePassword },\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created PostgreSQL: ${postgres.postgresId}`);\n\n\t\t\t\t// Deploy the database\n\t\t\t\tawait api.deployPostgres(postgres.postgresId);\n\t\t\t\tlogger.log(' ā PostgreSQL deployed');\n\n\t\t\t\t// Store individual connection parameters\n\t\t\t\tserviceUrls.DATABASE_HOST = postgres.appName;\n\t\t\t\tserviceUrls.DATABASE_PORT = '5432';\n\t\t\t\tserviceUrls.DATABASE_NAME = postgres.databaseName;\n\t\t\t\tserviceUrls.DATABASE_USER = postgres.databaseUser;\n\t\t\t\tserviceUrls.DATABASE_PASSWORD = postgres.databasePassword;\n\n\t\t\t\t// Construct connection URL using internal docker network hostname\n\t\t\t\tserviceUrls.DATABASE_URL = `postgresql://${postgres.databaseUser}:${postgres.databasePassword}@${postgres.appName}:5432/${postgres.databaseName}`;\n\t\t\t\tlogger.log(` ā Database credentials configured`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` ā¹ PostgreSQL already exists`);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(` ā Failed to provision PostgreSQL: ${message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (services.redis) {\n\t\t// Skip if REDIS_URL already exists in secrets\n\t\tif (existingUrls?.REDIS_URL) {\n\t\t\tlogger.log('\\nš“ Redis: Already configured (skipping)');\n\t\t} else {\n\t\t\tlogger.log('\\nš“ Provisioning Redis...');\n\t\t\tconst redisName = `${appName}-cache`;\n\n\t\t\ttry {\n\t\t\t\t// Generate a random password for Redis\n\t\t\t\tconst { randomBytes } = await import('node:crypto');\n\t\t\t\tconst databasePassword = randomBytes(16).toString('hex');\n\n\t\t\t\tconst redis = await api.createRedis(\n\t\t\t\t\tredisName,\n\t\t\t\t\tprojectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t\t{\n\t\t\t\t\t\tdatabasePassword,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created Redis: ${redis.redisId}`);\n\n\t\t\t\t// Deploy the redis instance\n\t\t\t\tawait api.deployRedis(redis.redisId);\n\t\t\t\tlogger.log(' ā Redis deployed');\n\n\t\t\t\t// Store individual connection parameters\n\t\t\t\tserviceUrls.REDIS_HOST = redis.appName;\n\t\t\t\tserviceUrls.REDIS_PORT = '6379';\n\t\t\t\tif (redis.databasePassword) {\n\t\t\t\t\tserviceUrls.REDIS_PASSWORD = redis.databasePassword;\n\t\t\t\t}\n\n\t\t\t\t// Construct connection URL\n\t\t\t\tconst password = redis.databasePassword\n\t\t\t\t\t? `:${redis.databasePassword}@`\n\t\t\t\t\t: '';\n\t\t\t\tserviceUrls.REDIS_URL = `redis://${password}${redis.appName}:6379`;\n\t\t\t\tlogger.log(` ā Redis credentials configured`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` ā¹ Redis already exists`);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(` ā Failed to provision Redis: ${message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Object.keys(serviceUrls).length > 0 ? serviceUrls : undefined;\n}\n\n/**\n * Ensure Dokploy is fully configured, recovering/creating resources as needed\n */\nasync function ensureDokploySetup(\n\tconfig: GkmConfig,\n\tdockerConfig: DockerDeployConfig,\n\tstage: string,\n\tservices?: DockerComposeServices,\n): Promise<DokploySetupResult> {\n\tlogger.log('\\nš§ Checking Dokploy setup...');\n\n\t// Read existing secrets to check if services are already configured\n\tconst { readStageSecrets } = await import('../secrets/storage');\n\tconst existingSecrets = await readStageSecrets(stage);\n\tconst existingUrls: { DATABASE_URL?: string; REDIS_URL?: string } = {\n\t\tDATABASE_URL: existingSecrets?.urls?.DATABASE_URL,\n\t\tREDIS_URL: existingSecrets?.urls?.REDIS_URL,\n\t};\n\n\t// Step 1: Ensure we have Dokploy credentials\n\tlet creds = await getDokployCredentials();\n\n\tif (!creds) {\n\t\tlogger.log(\"\\nš Dokploy credentials not found. Let's set them up.\");\n\t\tconst endpoint = await prompt(\n\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t);\n\t\tconst normalizedEndpoint = endpoint.replace(/\\/$/, '');\n\n\t\ttry {\n\t\t\tnew URL(normalizedEndpoint);\n\t\t} catch {\n\t\t\tthrow new Error('Invalid URL format');\n\t\t}\n\n\t\tlogger.log(\n\t\t\t`\\nGenerate a token at: ${normalizedEndpoint}/settings/profile\\n`,\n\t\t);\n\t\tconst token = await prompt('API Token: ', true);\n\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(normalizedEndpoint, token);\n\t\tif (!isValid) {\n\t\t\tthrow new Error('Invalid credentials. Please check your token.');\n\t\t}\n\n\t\tawait storeDokployCredentials(token, normalizedEndpoint);\n\t\tcreds = { token, endpoint: normalizedEndpoint };\n\t\tlogger.log('ā Credentials saved');\n\t}\n\n\tconst api = new DokployApi({ baseUrl: creds.endpoint, token: creds.token });\n\n\t// Step 2: Check if we have config in gkm.config.ts\n\tconst existingConfig = config.providers?.dokploy;\n\tif (\n\t\texistingConfig &&\n\t\ttypeof existingConfig !== 'boolean' &&\n\t\texistingConfig.applicationId &&\n\t\texistingConfig.projectId\n\t) {\n\t\tlogger.log('ā Dokploy config found in gkm.config.ts');\n\n\t\t// Verify the application still exists\n\t\ttry {\n\t\t\tconst projectDetails = await api.getProject(existingConfig.projectId);\n\t\t\tlogger.log('ā Project verified');\n\n\t\t\t// Get registry ID from config first, then from local storage\n\t\t\tconst storedRegistryId =\n\t\t\t\texistingConfig.registryId ?? (await getDokployRegistryId());\n\n\t\t\t// Get environment ID for service provisioning (match by stage name)\n\t\t\tconst environments = projectDetails.environments ?? [];\n\t\t\tlet environment = environments.find(\n\t\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t\t);\n\n\t\t\t// Create environment if it doesn't exist for this stage\n\t\t\tif (!environment) {\n\t\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\t\tenvironment = await api.createEnvironment(\n\t\t\t\t\texistingConfig.projectId,\n\t\t\t\t\tstage,\n\t\t\t\t);\n\t\t\t\tlogger.log(` ā Created environment: ${environment.environmentId}`);\n\t\t\t}\n\n\t\t\tconst environmentId = environment.environmentId;\n\n\t\t\t// Provision services if configured\n\t\t\tlogger.log(\n\t\t\t\t` Services config: ${JSON.stringify(services)}, envId: ${environmentId}`,\n\t\t\t);\n\t\t\tconst serviceUrls = await provisionServices(\n\t\t\t\tapi,\n\t\t\t\texistingConfig.projectId,\n\t\t\t\tenvironmentId,\n\t\t\t\tdockerConfig.appName!,\n\t\t\t\tservices,\n\t\t\t\texistingUrls,\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tconfig: {\n\t\t\t\t\tendpoint: existingConfig.endpoint,\n\t\t\t\t\tprojectId: existingConfig.projectId,\n\t\t\t\t\tapplicationId: existingConfig.applicationId,\n\t\t\t\t\tregistry: existingConfig.registry,\n\t\t\t\t\tregistryId: storedRegistryId ?? undefined,\n\t\t\t\t},\n\t\t\t\tserviceUrls,\n\t\t\t};\n\t\t} catch {\n\t\t\tlogger.log('ā Project not found, will recover...');\n\t\t}\n\t}\n\n\t// Step 3: Find or create project\n\tlogger.log('\\nš Looking for project...');\n\tconst projectName = dockerConfig.projectName!;\n\tconst projects = await api.listProjects();\n\tlet project = projects.find(\n\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t);\n\n\tlet environmentId: string;\n\n\tif (project) {\n\t\tlogger.log(\n\t\t\t` Found existing project: ${project.name} (${project.projectId})`,\n\t\t);\n\n\t\t// Step 4: Get or create environment for existing project (match by stage)\n\t\tconst projectDetails = await api.getProject(project.projectId);\n\t\tconst environments = projectDetails.environments ?? [];\n\t\tconst matchingEnv = environments.find(\n\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t);\n\t\tif (matchingEnv) {\n\t\t\tenvironmentId = matchingEnv.environmentId;\n\t\t\tlogger.log(` Using environment: ${matchingEnv.name}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t\tlogger.log(` ā Created environment: ${stage}`);\n\t\t}\n\t} else {\n\t\tlogger.log(` Creating project: ${projectName}`);\n\t\tconst result = await api.createProject(projectName);\n\t\tproject = result.project;\n\t\t// Rename the default environment to match stage if different\n\t\tif (result.environment.name.toLowerCase() !== stage.toLowerCase()) {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t} else {\n\t\t\tenvironmentId = result.environment.environmentId;\n\t\t}\n\t\tlogger.log(` ā Created project: ${project.projectId}`);\n\t\tlogger.log(` ā Using environment: ${stage}`);\n\t}\n\n\t// Step 5: Find or create application\n\tlogger.log('\\nš¦ Looking for application...');\n\tconst appName = dockerConfig.appName!;\n\n\tlet applicationId: string;\n\n\t// Try to find existing app from config\n\tif (\n\t\texistingConfig &&\n\t\ttypeof existingConfig !== 'boolean' &&\n\t\texistingConfig.applicationId\n\t) {\n\t\tapplicationId = existingConfig.applicationId;\n\t\tlogger.log(` Using application from config: ${applicationId}`);\n\t} else {\n\t\t// Create new application\n\t\tlogger.log(` Creating application: ${appName}`);\n\t\tconst app = await api.createApplication(\n\t\t\tappName,\n\t\t\tproject.projectId,\n\t\t\tenvironmentId,\n\t\t);\n\t\tapplicationId = app.applicationId;\n\t\tlogger.log(` ā Created application: ${applicationId}`);\n\t}\n\n\t// Step 6: Ensure registry is set up\n\tlogger.log('\\nš³ Checking registry...');\n\tlet registryId = await getDokployRegistryId();\n\n\tif (registryId) {\n\t\t// Verify stored registry still exists\n\t\ttry {\n\t\t\tconst registry = await api.getRegistry(registryId);\n\t\t\tlogger.log(` Using registry: ${registry.registryName}`);\n\t\t} catch {\n\t\t\tlogger.log(' ā Stored registry not found, clearing...');\n\t\t\tregistryId = undefined;\n\t\t\tawait storeDokployRegistryId('');\n\t\t}\n\t}\n\n\tif (!registryId) {\n\t\tconst registries = await api.listRegistries();\n\n\t\tif (registries.length === 0) {\n\t\t\t// No registries exist\n\t\t\tif (dockerConfig.registry) {\n\t\t\t\tlogger.log(\" No registries found in Dokploy. Let's create one.\");\n\t\t\t\tlogger.log(` Registry URL: ${dockerConfig.registry}`);\n\n\t\t\t\tconst username = await prompt('Registry username: ');\n\t\t\t\tconst password = await prompt('Registry password/token: ', true);\n\n\t\t\t\tconst registry = await api.createRegistry(\n\t\t\t\t\t'Default Registry',\n\t\t\t\t\tdockerConfig.registry,\n\t\t\t\t\tusername,\n\t\t\t\t\tpassword,\n\t\t\t\t);\n\t\t\t\tregistryId = registry.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t\t} else {\n\t\t\t\tlogger.log(\n\t\t\t\t\t' ā No registry configured. Set docker.registry in gkm.config.ts',\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Show available registries and let user select or create new\n\t\t\tlogger.log(' Available registries:');\n\t\t\tregistries.forEach((reg, i) => {\n\t\t\t\tlogger.log(` ${i + 1}. ${reg.registryName} (${reg.registryUrl})`);\n\t\t\t});\n\t\t\tif (dockerConfig.registry) {\n\t\t\t\tlogger.log(` ${registries.length + 1}. Create new registry`);\n\t\t\t}\n\n\t\t\tconst maxOption = dockerConfig.registry\n\t\t\t\t? registries.length + 1\n\t\t\t\t: registries.length;\n\t\t\tconst selection = await prompt(` Select registry (1-${maxOption}): `);\n\t\t\tconst index = parseInt(selection, 10) - 1;\n\n\t\t\tif (index >= 0 && index < registries.length) {\n\t\t\t\t// Selected existing registry\n\t\t\t\tregistryId = registries[index]!.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Selected: ${registries[index]!.registryName}`);\n\t\t\t} else if (dockerConfig.registry && index === registries.length) {\n\t\t\t\t// Create new registry\n\t\t\t\tlogger.log(`\\n Creating new registry...`);\n\t\t\t\tlogger.log(` Registry URL: ${dockerConfig.registry}`);\n\n\t\t\t\tconst username = await prompt(' Registry username: ');\n\t\t\t\tconst password = await prompt(' Registry password/token: ', true);\n\n\t\t\t\tconst registry = await api.createRegistry(\n\t\t\t\t\tdockerConfig.registry.replace(/^https?:\\/\\//, ''),\n\t\t\t\t\tdockerConfig.registry,\n\t\t\t\t\tusername,\n\t\t\t\t\tpassword,\n\t\t\t\t);\n\t\t\t\tregistryId = registry.registryId;\n\t\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t\t} else {\n\t\t\t\tlogger.log(' ā Invalid selection, skipping registry setup');\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 7: Build and save config\n\tconst dokployConfig: DokployDeployConfig = {\n\t\tendpoint: creds.endpoint,\n\t\tprojectId: project.projectId,\n\t\tapplicationId,\n\t\tregistryId: registryId ?? undefined,\n\t};\n\n\t// Update gkm.config.ts\n\tawait updateConfig(dokployConfig);\n\n\tlogger.log('\\nā
Dokploy setup complete!');\n\tlogger.log(` Project: ${project.projectId}`);\n\tlogger.log(` Application: ${applicationId}`);\n\tif (registryId) {\n\t\tlogger.log(` Registry: ${registryId}`);\n\t}\n\n\t// Step 8: Provision docker compose services if configured\n\tconst serviceUrls = await provisionServices(\n\t\tapi,\n\t\tproject.projectId,\n\t\tenvironmentId,\n\t\tdockerConfig.appName!,\n\t\tservices,\n\t\texistingUrls,\n\t);\n\n\treturn {\n\t\tconfig: dokployConfig,\n\t\tserviceUrls,\n\t};\n}\n\n/**\n * Generate image tag from stage and timestamp\n */\nexport function generateTag(stage: string): string {\n\tconst timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);\n\treturn `${stage}-${timestamp}`;\n}\n\n/**\n * Deploy all apps in a workspace to Dokploy.\n * - Workspace maps to one Dokploy project\n * - Each app maps to one Dokploy application\n * - Deploys in dependency order (backends before dependent frontends)\n * - Syncs environment variables including {APP_NAME}_URL\n * @internal Exported for testing\n */\nexport async function workspaceDeployCommand(\n\tworkspace: NormalizedWorkspace,\n\toptions: DeployOptions,\n): Promise<WorkspaceDeployResult> {\n\tconst { provider, stage, tag, skipBuild, apps: selectedApps } = options;\n\n\tif (provider !== 'dokploy') {\n\t\tthrow new Error(\n\t\t\t`Workspace deployment only supports Dokploy. Got: ${provider}`,\n\t\t);\n\t}\n\n\tlogger.log(`\\nš Deploying workspace \"${workspace.name}\" to Dokploy...`);\n\tlogger.log(` Stage: ${stage}`);\n\n\t// Generate tag if not provided\n\tconst imageTag = tag ?? generateTag(stage);\n\tlogger.log(` Tag: ${imageTag}`);\n\n\t// Get apps to deploy in dependency order\n\tconst buildOrder = getAppBuildOrder(workspace);\n\n\t// Filter to selected apps if specified\n\tlet appsToDeployNames = buildOrder;\n\tif (selectedApps && selectedApps.length > 0) {\n\t\t// Validate selected apps exist\n\t\tconst invalidApps = selectedApps.filter((name) => !workspace.apps[name]);\n\t\tif (invalidApps.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown apps: ${invalidApps.join(', ')}\\n` +\n\t\t\t\t\t`Available apps: ${Object.keys(workspace.apps).join(', ')}`,\n\t\t\t);\n\t\t}\n\t\t// Keep only selected apps, but maintain dependency order\n\t\tappsToDeployNames = buildOrder.filter((name) =>\n\t\t\tselectedApps.includes(name),\n\t\t);\n\t\tlogger.log(` Deploying apps: ${appsToDeployNames.join(', ')}`);\n\t} else {\n\t\tlogger.log(` Deploying all apps: ${appsToDeployNames.join(', ')}`);\n\t}\n\n\t// Filter apps by deploy target\n\t// In Phase 1, only 'dokploy' is supported. Other targets should have been\n\t// caught at config validation, but we handle it gracefully here too.\n\tconst dokployApps = appsToDeployNames.filter((name) => {\n\t\tconst app = workspace.apps[name]!;\n\t\tconst target = app.resolvedDeployTarget;\n\t\tif (!isDeployTargetSupported(target)) {\n\t\t\tlogger.log(\n\t\t\t\t` ā ļø Skipping ${name}: ${getDeployTargetError(target, name)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t});\n\n\tif (dokployApps.length === 0) {\n\t\tthrow new Error(\n\t\t\t'No apps to deploy. All selected apps have unsupported deploy targets.',\n\t\t);\n\t}\n\n\tif (dokployApps.length !== appsToDeployNames.length) {\n\t\tconst skipped = appsToDeployNames.filter(\n\t\t\t(name) => !dokployApps.includes(name),\n\t\t);\n\t\tlogger.log(\n\t\t\t` š ${skipped.length} app(s) skipped due to unsupported targets`,\n\t\t);\n\t}\n\n\tappsToDeployNames = dokployApps;\n\n\t// Ensure we have Dokploy credentials\n\tlet creds = await getDokployCredentials();\n\tif (!creds) {\n\t\tlogger.log(\"\\nš Dokploy credentials not found. Let's set them up.\");\n\t\tconst endpoint = await prompt(\n\t\t\t'Dokploy URL (e.g., https://dokploy.example.com): ',\n\t\t);\n\t\tconst normalizedEndpoint = endpoint.replace(/\\/$/, '');\n\n\t\ttry {\n\t\t\tnew URL(normalizedEndpoint);\n\t\t} catch {\n\t\t\tthrow new Error('Invalid URL format');\n\t\t}\n\n\t\tlogger.log(\n\t\t\t`\\nGenerate a token at: ${normalizedEndpoint}/settings/profile\\n`,\n\t\t);\n\t\tconst token = await prompt('API Token: ', true);\n\n\t\tlogger.log('\\nValidating credentials...');\n\t\tconst isValid = await validateDokployToken(normalizedEndpoint, token);\n\t\tif (!isValid) {\n\t\t\tthrow new Error('Invalid credentials. Please check your token.');\n\t\t}\n\n\t\tawait storeDokployCredentials(token, normalizedEndpoint);\n\t\tcreds = { token, endpoint: normalizedEndpoint };\n\t\tlogger.log('ā Credentials saved');\n\t}\n\n\tconst api = new DokployApi({ baseUrl: creds.endpoint, token: creds.token });\n\n\t// Find or create project for the workspace\n\tlogger.log('\\nš Setting up Dokploy project...');\n\tconst projectName = workspace.name;\n\tconst projects = await api.listProjects();\n\tlet project = projects.find(\n\t\t(p) => p.name.toLowerCase() === projectName.toLowerCase(),\n\t);\n\n\tlet environmentId: string;\n\n\tif (project) {\n\t\tlogger.log(` Found existing project: ${project.name}`);\n\t\t// Get or create environment for stage\n\t\tconst projectDetails = await api.getProject(project.projectId);\n\t\tconst environments = projectDetails.environments ?? [];\n\t\tconst matchingEnv = environments.find(\n\t\t\t(e) => e.name.toLowerCase() === stage.toLowerCase(),\n\t\t);\n\t\tif (matchingEnv) {\n\t\t\tenvironmentId = matchingEnv.environmentId;\n\t\t\tlogger.log(` Using environment: ${matchingEnv.name}`);\n\t\t} else {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t\tlogger.log(` ā Created environment: ${stage}`);\n\t\t}\n\t} else {\n\t\tlogger.log(` Creating project: ${projectName}`);\n\t\tconst result = await api.createProject(projectName);\n\t\tproject = result.project;\n\t\t// Create environment for stage if different from default\n\t\tif (result.environment.name.toLowerCase() !== stage.toLowerCase()) {\n\t\t\tlogger.log(` Creating \"${stage}\" environment...`);\n\t\t\tconst env = await api.createEnvironment(project.projectId, stage);\n\t\t\tenvironmentId = env.environmentId;\n\t\t} else {\n\t\t\tenvironmentId = result.environment.environmentId;\n\t\t}\n\t\tlogger.log(` ā Created project: ${project.projectId}`);\n\t}\n\n\t// Get or set up registry\n\tlogger.log('\\nš³ Checking registry...');\n\tlet registryId = await getDokployRegistryId();\n\tconst registry = workspace.deploy.dokploy?.registry;\n\n\tif (registryId) {\n\t\ttry {\n\t\t\tconst reg = await api.getRegistry(registryId);\n\t\t\tlogger.log(` Using registry: ${reg.registryName}`);\n\t\t} catch {\n\t\t\tlogger.log(' ā Stored registry not found, clearing...');\n\t\t\tregistryId = undefined;\n\t\t\tawait storeDokployRegistryId('');\n\t\t}\n\t}\n\n\tif (!registryId) {\n\t\tconst registries = await api.listRegistries();\n\t\tif (registries.length > 0) {\n\t\t\t// Use first available registry\n\t\t\tregistryId = registries[0]!.registryId;\n\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\tlogger.log(` Using registry: ${registries[0]!.registryName}`);\n\t\t} else if (registry) {\n\t\t\tlogger.log(\" No registries found in Dokploy. Let's create one.\");\n\t\t\tlogger.log(` Registry URL: ${registry}`);\n\n\t\t\tconst username = await prompt('Registry username: ');\n\t\t\tconst password = await prompt('Registry password/token: ', true);\n\n\t\t\tconst reg = await api.createRegistry(\n\t\t\t\t'Default Registry',\n\t\t\t\tregistry,\n\t\t\t\tusername,\n\t\t\t\tpassword,\n\t\t\t);\n\t\t\tregistryId = reg.registryId;\n\t\t\tawait storeDokployRegistryId(registryId);\n\t\t\tlogger.log(` ā Registry created: ${registryId}`);\n\t\t} else {\n\t\t\tlogger.log(\n\t\t\t\t' ā No registry configured. Set deploy.dokploy.registry in workspace config',\n\t\t\t);\n\t\t}\n\t}\n\n\t// Provision infrastructure services if configured\n\tconst services = workspace.services;\n\tconst dockerServices = {\n\t\tpostgres: services.db !== undefined && services.db !== false,\n\t\tredis: services.cache !== undefined && services.cache !== false,\n\t};\n\n\tif (dockerServices.postgres || dockerServices.redis) {\n\t\tlogger.log('\\nš§ Provisioning infrastructure services...');\n\t\tawait provisionServices(\n\t\t\tapi,\n\t\t\tproject.projectId,\n\t\t\tenvironmentId,\n\t\t\tworkspace.name,\n\t\t\tdockerServices,\n\t\t);\n\t}\n\n\t// Track deployed app URLs for environment variable injection\n\tconst deployedAppUrls: Record<string, string> = {};\n\n\t// Deploy apps in dependency order\n\tlogger.log('\\nš¦ Deploying applications...');\n\tconst results: AppDeployResult[] = [];\n\n\tfor (const appName of appsToDeployNames) {\n\t\tconst app = workspace.apps[appName]!;\n\t\tconst appPath = app.path;\n\n\t\tlogger.log(\n\t\t\t`\\n ${app.type === 'backend' ? 'āļø' : 'š'} Deploying ${appName}...`,\n\t\t);\n\n\t\ttry {\n\t\t\t// Find or create application in Dokploy\n\t\t\tconst dokployAppName = `${workspace.name}-${appName}`;\n\t\t\tlet application: DokployApplication | undefined;\n\n\t\t\ttry {\n\t\t\t\t// Try to find existing application (Dokploy doesn't have a direct lookup)\n\t\t\t\t// We'll create a new one and handle the error if it exists\n\t\t\t\tapplication = await api.createApplication(\n\t\t\t\t\tdokployAppName,\n\t\t\t\t\tproject.projectId,\n\t\t\t\t\tenvironmentId,\n\t\t\t\t);\n\t\t\t\tlogger.log(` Created application: ${application.applicationId}`);\n\t\t\t} catch (error) {\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : 'Unknown error';\n\t\t\t\tif (\n\t\t\t\t\tmessage.includes('already exists') ||\n\t\t\t\t\tmessage.includes('duplicate')\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(` Application already exists`);\n\t\t\t\t\t// For now, we'll continue without the applicationId\n\t\t\t\t\t// In a real implementation, we'd need to list and find the app\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build the app if not skipped\n\t\t\tif (!skipBuild) {\n\t\t\t\tlogger.log(` Building ${appName}...`);\n\t\t\t\t// For workspace, we need to build from the app directory\n\t\t\t\tconst originalCwd = process.cwd();\n\t\t\t\tconst fullAppPath = `${workspace.root}/${appPath}`;\n\n\t\t\t\ttry {\n\t\t\t\t\tprocess.chdir(fullAppPath);\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: 'server',\n\t\t\t\t\t\tproduction: true,\n\t\t\t\t\t\tstage,\n\t\t\t\t\t});\n\t\t\t\t} finally {\n\t\t\t\t\tprocess.chdir(originalCwd);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build Docker image\n\t\t\tconst imageName = `${workspace.name}-${appName}`;\n\t\t\tconst imageRef = registry\n\t\t\t\t? `${registry}/${imageName}:${imageTag}`\n\t\t\t\t: `${imageName}:${imageTag}`;\n\n\t\t\tlogger.log(` Building Docker image: ${imageRef}`);\n\n\t\t\tawait deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush: false,\n\t\t\t\tconfig: {\n\t\t\t\t\tregistry,\n\t\t\t\t\timageName,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Prepare environment variables\n\t\t\tconst envVars: string[] = [`NODE_ENV=production`, `PORT=${app.port}`];\n\n\t\t\t// Add dependency URLs\n\t\t\tfor (const dep of app.dependencies) {\n\t\t\t\tconst depUrl = deployedAppUrls[dep];\n\t\t\t\tif (depUrl) {\n\t\t\t\t\tenvVars.push(`${dep.toUpperCase()}_URL=${depUrl}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add infrastructure URLs for backend apps\n\t\t\tif (app.type === 'backend') {\n\t\t\t\tif (dockerServices.postgres) {\n\t\t\t\t\tenvVars.push(\n\t\t\t\t\t\t`DATABASE_URL=\\${DATABASE_URL:-postgresql://postgres:postgres@${workspace.name}-db:5432/app}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (dockerServices.redis) {\n\t\t\t\t\tenvVars.push(\n\t\t\t\t\t\t`REDIS_URL=\\${REDIS_URL:-redis://${workspace.name}-cache:6379}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Configure application in Dokploy\n\t\t\tif (application) {\n\t\t\t\t// Save Docker provider config\n\t\t\t\tawait api.saveDockerProvider(application.applicationId, imageRef, {\n\t\t\t\t\tregistryId,\n\t\t\t\t});\n\n\t\t\t\t// Save environment variables\n\t\t\t\tawait api.saveApplicationEnv(\n\t\t\t\t\tapplication.applicationId,\n\t\t\t\t\tenvVars.join('\\n'),\n\t\t\t\t);\n\n\t\t\t\t// Deploy\n\t\t\t\tlogger.log(` Deploying to Dokploy...`);\n\t\t\t\tawait api.deployApplication(application.applicationId);\n\n\t\t\t\t// Track this app's URL for dependent apps\n\t\t\t\t// Dokploy uses the appName as the internal hostname\n\t\t\t\tconst appUrl = `http://${dokployAppName}:${app.port}`;\n\t\t\t\tdeployedAppUrls[appName] = appUrl;\n\n\t\t\t\tresults.push({\n\t\t\t\t\tappName,\n\t\t\t\t\ttype: app.type,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tapplicationId: application.applicationId,\n\t\t\t\t\timageRef,\n\t\t\t\t});\n\n\t\t\t\tlogger.log(` ā ${appName} deployed successfully`);\n\t\t\t} else {\n\t\t\t\t// Application already exists, just track it\n\t\t\t\tconst appUrl = `http://${dokployAppName}:${app.port}`;\n\t\t\t\tdeployedAppUrls[appName] = appUrl;\n\n\t\t\t\tresults.push({\n\t\t\t\t\tappName,\n\t\t\t\t\ttype: app.type,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\timageRef,\n\t\t\t\t});\n\n\t\t\t\tlogger.log(` ā ${appName} image pushed (app already exists)`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : 'Unknown error';\n\t\t\tlogger.log(` ā Failed to deploy ${appName}: ${message}`);\n\n\t\t\tresults.push({\n\t\t\t\tappName,\n\t\t\t\ttype: app.type,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: message,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Summary\n\tconst successCount = results.filter((r) => r.success).length;\n\tconst failedCount = results.filter((r) => !r.success).length;\n\n\tlogger.log(`\\n${'ā'.repeat(50)}`);\n\tlogger.log(`\\nā
Workspace deployment complete!`);\n\tlogger.log(` Project: ${project.projectId}`);\n\tlogger.log(` Successful: ${successCount}`);\n\tif (failedCount > 0) {\n\t\tlogger.log(` Failed: ${failedCount}`);\n\t}\n\n\treturn {\n\t\tapps: results,\n\t\tprojectId: project.projectId,\n\t\tsuccessCount,\n\t\tfailedCount,\n\t};\n}\n\n/**\n * Main deploy command\n */\nexport async function deployCommand(\n\toptions: DeployOptions,\n): Promise<DeployResult | WorkspaceDeployResult> {\n\tconst { provider, stage, tag, skipPush, skipBuild } = options;\n\n\t// Load config with workspace detection\n\tconst loadedConfig = await loadWorkspaceConfig();\n\n\t// Route to workspace deploy mode for multi-app workspaces\n\tif (loadedConfig.type === 'workspace') {\n\t\tlogger.log('š¦ Detected workspace configuration');\n\t\treturn workspaceDeployCommand(loadedConfig.workspace, options);\n\t}\n\n\tlogger.log(`\\nš Deploying to ${provider}...`);\n\tlogger.log(` Stage: ${stage}`);\n\n\t// Single-app mode - use existing logic\n\tconst config = await loadConfig();\n\n\t// Generate tag if not provided\n\tconst imageTag = tag ?? generateTag(stage);\n\tlogger.log(` Tag: ${imageTag}`);\n\n\t// Resolve docker config for image reference\n\tconst dockerConfig = resolveDockerConfig(config);\n\tconst imageName = dockerConfig.imageName!;\n\tconst registry = dockerConfig.registry;\n\tconst imageRef = registry\n\t\t? `${registry}/${imageName}:${imageTag}`\n\t\t: `${imageName}:${imageTag}`;\n\n\t// For Dokploy, set up services BEFORE build so URLs are available\n\tlet dokployConfig: DokployDeployConfig | undefined;\n\tlet finalRegistry = registry;\n\n\tif (provider === 'dokploy') {\n\t\t// Extract docker compose services config\n\t\tconst composeServices = config.docker?.compose?.services;\n\t\tlogger.log(\n\t\t\t`\\nš Docker compose config: ${JSON.stringify(config.docker?.compose)}`,\n\t\t);\n\t\tconst dockerServices: DockerComposeServices | undefined = composeServices\n\t\t\t? Array.isArray(composeServices)\n\t\t\t\t? {\n\t\t\t\t\t\tpostgres: composeServices.includes('postgres'),\n\t\t\t\t\t\tredis: composeServices.includes('redis'),\n\t\t\t\t\t\trabbitmq: composeServices.includes('rabbitmq'),\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tpostgres: Boolean(composeServices.postgres),\n\t\t\t\t\t\tredis: Boolean(composeServices.redis),\n\t\t\t\t\t\trabbitmq: Boolean(composeServices.rabbitmq),\n\t\t\t\t\t}\n\t\t\t: undefined;\n\n\t\t// Ensure Dokploy is fully set up (credentials, project, app, registry, services)\n\t\tconst setupResult = await ensureDokploySetup(\n\t\t\tconfig,\n\t\t\tdockerConfig,\n\t\t\tstage,\n\t\t\tdockerServices,\n\t\t);\n\t\tdokployConfig = setupResult.config;\n\t\tfinalRegistry = dokployConfig.registry ?? dockerConfig.registry;\n\n\t\t// Save provisioned service URLs to secrets before build\n\t\tif (setupResult.serviceUrls) {\n\t\t\tconst { readStageSecrets, writeStageSecrets, initStageSecrets } =\n\t\t\t\tawait import('../secrets/storage');\n\t\t\tlet secrets = await readStageSecrets(stage);\n\n\t\t\t// Create secrets file if it doesn't exist\n\t\t\tif (!secrets) {\n\t\t\t\tlogger.log(` Creating secrets file for stage \"${stage}\"...`);\n\t\t\t\tsecrets = initStageSecrets(stage);\n\t\t\t}\n\n\t\t\tlet updated = false;\n\t\t\t// URL fields go to secrets.urls, individual params go to secrets.custom\n\t\t\tconst urlFields = ['DATABASE_URL', 'REDIS_URL', 'RABBITMQ_URL'] as const;\n\n\t\t\tfor (const [key, value] of Object.entries(setupResult.serviceUrls)) {\n\t\t\t\tif (!value) continue;\n\n\t\t\t\tif (urlFields.includes(key as (typeof urlFields)[number])) {\n\t\t\t\t\t// URL fields\n\t\t\t\t\tconst urlKey = key as keyof typeof secrets.urls;\n\t\t\t\t\tif (!secrets.urls[urlKey]) {\n\t\t\t\t\t\tsecrets.urls[urlKey] = value;\n\t\t\t\t\t\tlogger.log(` Saved ${key} to secrets.urls`);\n\t\t\t\t\t\tupdated = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Individual parameters (HOST, PORT, NAME, USER, PASSWORD)\n\t\t\t\t\tif (!secrets.custom[key]) {\n\t\t\t\t\t\tsecrets.custom[key] = value;\n\t\t\t\t\t\tlogger.log(` Saved ${key} to secrets.custom`);\n\t\t\t\t\t\tupdated = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updated) {\n\t\t\t\tawait writeStageSecrets(secrets);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Build for production with secrets injection (unless skipped)\n\tlet masterKey: string | undefined;\n\tif (!skipBuild) {\n\t\tlogger.log(`\\nš¦ Building for production...`);\n\t\tconst buildResult = await buildCommand({\n\t\t\tprovider: 'server',\n\t\t\tproduction: true,\n\t\t\tstage,\n\t\t});\n\t\tmasterKey = buildResult.masterKey;\n\t} else {\n\t\tlogger.log(`\\nāļø Skipping build (--skip-build)`);\n\t}\n\n\t// Deploy based on provider\n\tlet result: DeployResult;\n\n\tswitch (provider) {\n\t\tcase 'docker': {\n\t\t\tresult = await deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush,\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: dockerConfig,\n\t\t\t});\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'dokploy': {\n\t\t\tif (!dokployConfig) {\n\t\t\t\tthrow new Error('Dokploy config not initialized');\n\t\t\t}\n\t\t\tconst finalImageRef = finalRegistry\n\t\t\t\t? `${finalRegistry}/${imageName}:${imageTag}`\n\t\t\t\t: `${imageName}:${imageTag}`;\n\n\t\t\t// First build and push the Docker image\n\t\t\tawait deployDocker({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\tskipPush: false, // Dokploy needs the image in registry\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: {\n\t\t\t\t\tregistry: finalRegistry,\n\t\t\t\t\timageName: dockerConfig.imageName,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Then trigger Dokploy deployment\n\t\t\tresult = await deployDokploy({\n\t\t\t\tstage,\n\t\t\t\ttag: imageTag,\n\t\t\t\timageRef: finalImageRef,\n\t\t\t\tmasterKey,\n\t\t\t\tconfig: dokployConfig,\n\t\t\t});\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'aws-lambda': {\n\t\t\tlogger.log('\\nā ļø AWS Lambda deployment is not yet implemented.');\n\t\t\tlogger.log(' Use SST or AWS CDK for Lambda deployments.');\n\t\t\tresult = { imageRef, masterKey };\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault: {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown deploy provider: ${provider}\\n` +\n\t\t\t\t\t'Supported providers: docker, dokploy, aws-lambda',\n\t\t\t);\n\t\t}\n\t}\n\n\tlogger.log('\\nā
Deployment complete!');\n\n\treturn result;\n}\n\nexport type { DeployOptions, DeployProvider, DeployResult };\n","import { randomBytes } from 'node:crypto';\nimport type { ComposeServiceName } from '../types';\nimport type { ServiceCredentials, StageSecrets } from './types';\n\n/**\n * Generate a secure random password using URL-safe base64 characters.\n * @param length Password length (default: 32)\n */\nexport function generateSecurePassword(length = 32): string {\n\treturn randomBytes(Math.ceil((length * 3) / 4))\n\t\t.toString('base64url')\n\t\t.slice(0, length);\n}\n\n/** Default service configurations */\nconst SERVICE_DEFAULTS: Record<\n\tComposeServiceName,\n\tOmit<ServiceCredentials, 'password'>\n> = {\n\tpostgres: {\n\t\thost: 'postgres',\n\t\tport: 5432,\n\t\tusername: 'app',\n\t\tdatabase: 'app',\n\t},\n\tredis: {\n\t\thost: 'redis',\n\t\tport: 6379,\n\t\tusername: 'default',\n\t},\n\trabbitmq: {\n\t\thost: 'rabbitmq',\n\t\tport: 5672,\n\t\tusername: 'app',\n\t\tvhost: '/',\n\t},\n};\n\n/**\n * Generate credentials for a specific service.\n */\nexport function generateServiceCredentials(\n\tservice: ComposeServiceName,\n): ServiceCredentials {\n\tconst defaults = SERVICE_DEFAULTS[service];\n\treturn {\n\t\t...defaults,\n\t\tpassword: generateSecurePassword(),\n\t};\n}\n\n/**\n * Generate credentials for multiple services.\n */\nexport function generateServicesCredentials(\n\tservices: ComposeServiceName[],\n): StageSecrets['services'] {\n\tconst result: StageSecrets['services'] = {};\n\n\tfor (const service of services) {\n\t\tresult[service] = generateServiceCredentials(service);\n\t}\n\n\treturn result;\n}\n\n/**\n * Generate connection URL for PostgreSQL.\n */\nexport function generatePostgresUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, database } = creds;\n\treturn `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;\n}\n\n/**\n * Generate connection URL for Redis.\n */\nexport function generateRedisUrl(creds: ServiceCredentials): string {\n\tconst { password, host, port } = creds;\n\treturn `redis://:${encodeURIComponent(password)}@${host}:${port}`;\n}\n\n/**\n * Generate connection URL for RabbitMQ.\n */\nexport function generateRabbitmqUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, vhost } = creds;\n\tconst encodedVhost = encodeURIComponent(vhost ?? '/');\n\treturn `amqp://${username}:${encodeURIComponent(password)}@${host}:${port}/${encodedVhost}`;\n}\n\n/**\n * Generate connection URLs from service credentials.\n */\nexport function generateConnectionUrls(\n\tservices: StageSecrets['services'],\n): StageSecrets['urls'] {\n\tconst urls: StageSecrets['urls'] = {};\n\n\tif (services.postgres) {\n\t\turls.DATABASE_URL = generatePostgresUrl(services.postgres);\n\t}\n\n\tif (services.redis) {\n\t\turls.REDIS_URL = generateRedisUrl(services.redis);\n\t}\n\n\tif (services.rabbitmq) {\n\t\turls.RABBITMQ_URL = generateRabbitmqUrl(services.rabbitmq);\n\t}\n\n\treturn urls;\n}\n\n/**\n * Create a new StageSecrets object with generated credentials.\n */\nexport function createStageSecrets(\n\tstage: string,\n\tservices: ComposeServiceName[],\n): StageSecrets {\n\tconst now = new Date().toISOString();\n\tconst serviceCredentials = generateServicesCredentials(services);\n\tconst urls = generateConnectionUrls(serviceCredentials);\n\n\treturn {\n\t\tstage,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tservices: serviceCredentials,\n\t\turls,\n\t\tcustom: {},\n\t};\n}\n\n/**\n * Rotate password for a specific service.\n */\nexport function rotateServicePassword(\n\tsecrets: StageSecrets,\n\tservice: ComposeServiceName,\n): StageSecrets {\n\tconst currentCreds = secrets.services[service];\n\tif (!currentCreds) {\n\t\tthrow new Error(`Service \"${service}\" not configured in secrets`);\n\t}\n\n\tconst newCreds: ServiceCredentials = {\n\t\t...currentCreds,\n\t\tpassword: generateSecurePassword(),\n\t};\n\n\tconst newServices = {\n\t\t...secrets.services,\n\t\t[service]: newCreds,\n\t};\n\n\treturn {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tservices: newServices,\n\t\turls: generateConnectionUrls(newServices),\n\t};\n}\n","import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n// Load package.json - handles both bundled (flat dist/) and source (nested src/init/)\nfunction loadPackageJson(): { version: string } {\n\ttry {\n\t\t// Try flat dist path first (../package.json from dist/)\n\t\treturn require('../package.json');\n\t} catch {\n\t\t// Fall back to nested source path (../../package.json from src/init/)\n\t\treturn require('../../package.json');\n\t}\n}\n\nconst pkg = loadPackageJson();\n\n/**\n * CLI version from package.json (used for scaffolded projects)\n */\nexport const CLI_VERSION = `~${pkg.version}`;\n\n/**\n * Current released versions of @geekmidas packages\n * Update these when publishing new versions\n * Note: CLI version is read from package.json via CLI_VERSION\n */\nexport const GEEKMIDAS_VERSIONS = {\n\t'@geekmidas/audit': '~0.2.0',\n\t'@geekmidas/auth': '~0.2.0',\n\t'@geekmidas/cache': '~0.2.0',\n\t'@geekmidas/cli': CLI_VERSION,\n\t'@geekmidas/client': '~0.5.0',\n\t'@geekmidas/cloud': '~0.2.0',\n\t'@geekmidas/constructs': '~0.6.0',\n\t'@geekmidas/db': '~0.3.0',\n\t'@geekmidas/emailkit': '~0.2.0',\n\t'@geekmidas/envkit': '~0.5.0',\n\t'@geekmidas/errors': '~0.1.0',\n\t'@geekmidas/events': '~0.2.0',\n\t'@geekmidas/logger': '~0.4.0',\n\t'@geekmidas/rate-limit': '~0.3.0',\n\t'@geekmidas/schema': '~0.1.0',\n\t'@geekmidas/services': '~0.2.0',\n\t'@geekmidas/storage': '~0.1.0',\n\t'@geekmidas/studio': '~0.4.0',\n\t'@geekmidas/telescope': '~0.5.0',\n\t'@geekmidas/testkit': '~0.6.0',\n};\n\nexport type GeekmidasPackage = keyof typeof GEEKMIDAS_VERSIONS;\n\n/**\n * Get the version for a @geekmidas package\n */\nexport function getPackageVersion(pkg: GeekmidasPackage): string {\n\treturn GEEKMIDAS_VERSIONS[pkg]!;\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate auth app files for fullstack template\n * Uses better-auth with magic link authentication\n */\nexport function generateAuthAppFiles(\n\toptions: TemplateOptions,\n): GeneratedFile[] {\n\tif (!options.monorepo || options.template !== 'fullstack') {\n\t\treturn [];\n\t}\n\n\tconst packageName = `@${options.name}/auth`;\n\tconst modelsPackage = `@${options.name}/models`;\n\n\t// package.json for auth app\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tscripts: {\n\t\t\tdev: 'gkm dev --entry ./src/index.ts',\n\t\t\tbuild: 'tsc',\n\t\t\tstart: 'node dist/index.js',\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\t[modelsPackage]: 'workspace:*',\n\t\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t\t'@hono/node-server': '~1.13.0',\n\t\t\t'better-auth': '~1.2.0',\n\t\t\thono: '~4.8.0',\n\t\t\tkysely: '~0.27.0',\n\t\t\tpg: '~8.13.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t\t'@types/node': '~22.0.0',\n\t\t\t'@types/pg': '~8.11.0',\n\t\t\ttsx: '~4.20.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// tsconfig.json for auth app\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tnoEmit: true,\n\t\t\tbaseUrl: '.',\n\t\t\tpaths: {\n\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t},\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// src/config/env.ts\n\tconst envTs = `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed where needed\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`;\n\n\t// src/config/logger.ts\n\tconst loggerTs = `import { createLogger } from '@geekmidas/logger/${options.loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t// src/auth.ts - better-auth instance with magic link\n\tconst authTs = `import { betterAuth } from 'better-auth';\nimport { magicLink } from 'better-auth/plugins';\nimport pg from 'pg';\nimport { envParser } from './config/env.js';\nimport { logger } from './config/logger.js';\n\n// Parse auth-specific config (no defaults - values from secrets)\nconst authConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n baseUrl: get('BETTER_AUTH_URL').string(),\n trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),\n secret: get('BETTER_AUTH_SECRET').string(),\n }))\n .parse();\n\nexport const auth = betterAuth({\n database: new pg.Pool({\n connectionString: authConfig.databaseUrl,\n }),\n baseURL: authConfig.baseUrl,\n trustedOrigins: authConfig.trustedOrigins.split(','),\n secret: authConfig.secret,\n plugins: [\n magicLink({\n sendMagicLink: async ({ email, url }) => {\n // TODO: Implement email sending using @geekmidas/emailkit\n // For development, log the magic link\n logger.info({ email, url }, 'Magic link generated');\n console.log('\\\\n================================');\n console.log('MAGIC LINK FOR:', email);\n console.log(url);\n console.log('================================\\\\n');\n },\n expiresIn: 300, // 5 minutes\n }),\n ],\n emailAndPassword: {\n enabled: false, // Only magic link for now\n },\n});\n\nexport type Auth = typeof auth;\n`;\n\n\t// src/index.ts - Hono app entry point\n\tconst indexTs = `import { Hono } from 'hono';\nimport { cors } from 'hono/cors';\nimport { serve } from '@hono/node-server';\nimport { auth } from './auth.js';\nimport { envParser } from './config/env.js';\nimport { logger } from './config/logger.js';\n\n// Parse server config (no defaults - values from secrets)\nconst serverConfig = envParser\n .create((get) => ({\n port: get('PORT').string().transform(Number),\n trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),\n }))\n .parse();\n\nconst app = new Hono();\n\n// CORS must be registered before routes\napp.use(\n '/api/auth/*',\n cors({\n origin: serverConfig.trustedOrigins.split(','),\n allowHeaders: ['Content-Type', 'Authorization'],\n allowMethods: ['POST', 'GET', 'OPTIONS'],\n credentials: true,\n }),\n);\n\n// Health check endpoint\napp.get('/health', (c) => {\n return c.json({\n status: 'ok',\n service: 'auth',\n timestamp: new Date().toISOString(),\n });\n});\n\n// Mount better-auth handler\napp.on(['POST', 'GET'], '/api/auth/*', (c) => {\n return auth.handler(c.req.raw);\n});\n\nlogger.info({ port: serverConfig.port }, 'Starting auth server');\n\nserve({\n fetch: app.fetch,\n port: serverConfig.port,\n}, (info) => {\n logger.info({ port: info.port }, 'Auth server running');\n});\n`;\n\n\t// .gitignore for auth app\n\tconst gitignore = `node_modules/\ndist/\n.env.local\n*.log\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'apps/auth/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/config/env.ts',\n\t\t\tcontent: envTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/config/logger.ts',\n\t\t\tcontent: loggerTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/auth.ts',\n\t\t\tcontent: authTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/src/index.ts',\n\t\t\tcontent: indexTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/auth/.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate configuration files (gkm.config.ts, tsconfig.json, biome.json, turbo.json)\n */\nexport function generateConfigFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\tconst { telescope, studio, routesStructure } = options;\n\tconst isServerless = template.name === 'serverless';\n\tconst hasWorker = template.name === 'worker';\n\tconst isFullstack = options.template === 'fullstack';\n\n\t// Get routes glob pattern based on structure\n\tconst getRoutesGlob = () => {\n\t\tswitch (routesStructure) {\n\t\t\tcase 'centralized-endpoints':\n\t\t\t\treturn './src/endpoints/**/*.ts';\n\t\t\tcase 'centralized-routes':\n\t\t\t\treturn './src/routes/**/*.ts';\n\t\t\tcase 'domain-based':\n\t\t\t\treturn './src/**/routes/*.ts';\n\t\t}\n\t};\n\n\t// For fullstack template, generate workspace config at root\n\t// Single app config is still generated for non-fullstack monorepo setups\n\tif (isFullstack) {\n\t\t// Workspace config is generated in monorepo.ts for fullstack\n\t\treturn generateSingleAppConfigFiles(options, template, {\n\t\t\ttelescope,\n\t\t\tstudio,\n\t\t\troutesStructure,\n\t\t\tisServerless,\n\t\t\thasWorker,\n\t\t\tgetRoutesGlob,\n\t\t});\n\t}\n\n\t// Build gkm.config.ts for single-app\n\tlet gkmConfig = `import { defineConfig } from '@geekmidas/cli/config';\n\nexport default defineConfig({\n routes: '${getRoutesGlob()}',\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',`;\n\n\tif (isServerless || hasWorker) {\n\t\tgkmConfig += `\n functions: './src/functions/**/*.ts',`;\n\t}\n\n\tif (hasWorker) {\n\t\tgkmConfig += `\n crons: './src/crons/**/*.ts',\n subscribers: './src/subscribers/**/*.ts',`;\n\t}\n\n\tif (telescope) {\n\t\tgkmConfig += `\n telescope: {\n enabled: true,\n path: '/__telescope',\n },`;\n\t}\n\n\tif (studio) {\n\t\tgkmConfig += `\n studio: './src/config/studio#studio',`;\n\t}\n\n\t// Always add openapi config (output path is fixed to .gkm/openapi.ts)\n\tgkmConfig += `\n openapi: {\n enabled: true,\n },`;\n\n\tgkmConfig += `\n});\n`;\n\n\t// Build tsconfig.json - extends root for monorepo, standalone for non-monorepo\n\t// Using noEmit: true since typecheck is done via turbo\n\tconst tsConfig = options.monorepo\n\t\t? {\n\t\t\t\textends: '../../tsconfig.json',\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\tnoEmit: true,\n\t\t\t\t\tbaseUrl: '.',\n\t\t\t\t\tpaths: {\n\t\t\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tinclude: ['src/**/*.ts'],\n\t\t\t\texclude: ['node_modules', 'dist'],\n\t\t\t}\n\t\t: {\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\ttarget: 'ES2022',\n\t\t\t\t\tmodule: 'NodeNext',\n\t\t\t\t\tmoduleResolution: 'NodeNext',\n\t\t\t\t\tlib: ['ES2022'],\n\t\t\t\t\tstrict: true,\n\t\t\t\t\tesModuleInterop: true,\n\t\t\t\t\tskipLibCheck: true,\n\t\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\t\tresolveJsonModule: true,\n\t\t\t\t\tdeclaration: true,\n\t\t\t\t\tdeclarationMap: true,\n\t\t\t\t\toutDir: './dist',\n\t\t\t\t\trootDir: './src',\n\t\t\t\t},\n\t\t\t\tinclude: ['src/**/*.ts'],\n\t\t\t\texclude: ['node_modules', 'dist'],\n\t\t\t};\n\n\t// Skip biome.json and turbo.json for monorepo (they're at root)\n\tif (options.monorepo) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tpath: 'gkm.config.ts',\n\t\t\t\tcontent: gkmConfig,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: 'tsconfig.json',\n\t\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t\t},\n\t\t];\n\t}\n\n\t// Build biome.json\n\tconst biomeConfig = {\n\t\t$schema: 'https://biomejs.dev/schemas/2.3.0/schema.json',\n\t\tvcs: {\n\t\t\tenabled: true,\n\t\t\tclientKind: 'git',\n\t\t\tuseIgnoreFile: true,\n\t\t},\n\t\torganizeImports: {\n\t\t\tenabled: true,\n\t\t},\n\t\tformatter: {\n\t\t\tenabled: true,\n\t\t\tindentStyle: 'space',\n\t\t\tindentWidth: 2,\n\t\t\tlineWidth: 80,\n\t\t},\n\t\tjavascript: {\n\t\t\tformatter: {\n\t\t\t\tquoteStyle: 'single',\n\t\t\t\ttrailingCommas: 'all',\n\t\t\t\tsemicolons: 'always',\n\t\t\t\tarrowParentheses: 'always',\n\t\t\t},\n\t\t},\n\t\tlinter: {\n\t\t\tenabled: true,\n\t\t\trules: {\n\t\t\t\trecommended: true,\n\t\t\t\tcorrectness: {\n\t\t\t\t\tnoUnusedImports: 'error',\n\t\t\t\t\tnoUnusedVariables: 'error',\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\tnoNonNullAssertion: 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tfiles: {\n\t\t\tignore: ['node_modules', 'dist', '.gkm', 'coverage'],\n\t\t},\n\t};\n\n\t// Build turbo.json\n\tconst turboConfig = {\n\t\t$schema: 'https://turbo.build/schema.json',\n\t\ttasks: {\n\t\t\tbuild: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['dist/**'],\n\t\t\t},\n\t\t\tdev: {\n\t\t\t\tcache: false,\n\t\t\t\tpersistent: true,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\tcache: false,\n\t\t\t},\n\t\t\t'test:once': {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['coverage/**'],\n\t\t\t},\n\t\t\ttypecheck: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tfmt: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t},\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'gkm.config.ts',\n\t\t\tcontent: gkmConfig,\n\t\t},\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'biome.json',\n\t\t\tcontent: `${JSON.stringify(biomeConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'turbo.json',\n\t\t\tcontent: `${JSON.stringify(turboConfig, null, 2)}\\n`,\n\t\t},\n\t];\n}\n\n/**\n * Helper to generate config files for API app in fullstack template\n * (workspace config is at root, so no gkm.config.ts for app)\n */\ninterface ConfigHelperOptions {\n\ttelescope: boolean;\n\tstudio: boolean;\n\troutesStructure: string;\n\tisServerless: boolean;\n\thasWorker: boolean;\n\tgetRoutesGlob: () => string;\n}\n\nfunction generateSingleAppConfigFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n\t_helpers: ConfigHelperOptions,\n): GeneratedFile[] {\n\t// For fullstack, only generate tsconfig.json for the API app\n\t// The workspace gkm.config.ts is generated in monorepo.ts\n\t// Using noEmit: true since typecheck is done via turbo\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tnoEmit: true,\n\t\t\tbaseUrl: '.',\n\t\t\tpaths: {\n\t\t\t\t[`@${options.name}/*`]: ['../../packages/*/src'],\n\t\t\t},\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\nexport interface DatabaseAppConfig {\n\tname: string;\n\tpassword: string;\n}\n\n/**\n * Generate docker-compose.yml based on template and options\n */\nexport function generateDockerFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n\tdbApps?: DatabaseAppConfig[],\n): GeneratedFile[] {\n\tconst { database } = options;\n\tconst isServerless = template.name === 'serverless';\n\tconst hasWorker = template.name === 'worker';\n\tconst isFullstack = options.template === 'fullstack';\n\n\tconst services: string[] = [];\n\tconst volumes: string[] = [];\n\tconst files: GeneratedFile[] = [];\n\n\t// PostgreSQL database\n\tif (database) {\n\t\tconst initVolume =\n\t\t\tisFullstack && dbApps?.length\n\t\t\t\t? `\n - ./docker/postgres/init.sh:/docker-entrypoint-initdb.d/init.sh:ro`\n\t\t\t\t: '';\n\n\t\tconst envFile =\n\t\t\tisFullstack && dbApps?.length\n\t\t\t\t? `\n env_file:\n - ./docker/.env`\n\t\t\t\t: '';\n\n\t\tservices.push(` postgres:\n image: postgres:16-alpine\n container_name: ${options.name}-postgres\n restart: unless-stopped${envFile}\n environment:\n POSTGRES_USER: postgres\n POSTGRES_PASSWORD: postgres\n POSTGRES_DB: ${options.name.replace(/-/g, '_')}_dev\n ports:\n - '5432:5432'\n volumes:\n - postgres_data:/var/lib/postgresql/data${initVolume}\n healthcheck:\n test: ['CMD-SHELL', 'pg_isready -U postgres']\n interval: 5s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' postgres_data:');\n\n\t\t// Generate PostgreSQL init script and .env for fullstack template\n\t\tif (isFullstack && dbApps?.length) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'docker/postgres/init.sh',\n\t\t\t\tcontent: generatePostgresInitScript(dbApps),\n\t\t\t});\n\n\t\t\t// Generate .env file for docker-compose (contains db passwords)\n\t\t\tfiles.push({\n\t\t\t\tpath: 'docker/.env',\n\t\t\t\tcontent: generateDockerEnv(dbApps),\n\t\t\t});\n\t\t}\n\t}\n\n\t// Redis - different setup for serverless vs standard\n\tif (isServerless) {\n\t\t// Use serverless-redis-http for Lambda compatibility\n\t\tservices.push(` redis:\n image: redis:7-alpine\n container_name: ${options.name}-redis\n restart: unless-stopped\n ports:\n - '6379:6379'\n volumes:\n - redis_data:/data\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5\n\n serverless-redis:\n image: hiett/serverless-redis-http:latest\n container_name: ${options.name}-serverless-redis\n restart: unless-stopped\n ports:\n - '8079:80'\n environment:\n SRH_MODE: env\n SRH_TOKEN: local_dev_token\n SRH_CONNECTION_STRING: redis://redis:6379\n depends_on:\n redis:\n condition: service_healthy`);\n\t\tvolumes.push(' redis_data:');\n\t} else {\n\t\t// Standard Redis for non-serverless templates\n\t\tservices.push(` redis:\n image: redis:7-alpine\n container_name: ${options.name}-redis\n restart: unless-stopped\n ports:\n - '6379:6379'\n volumes:\n - redis_data:/data\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 5s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' redis_data:');\n\t}\n\n\t// RabbitMQ for worker template\n\tif (hasWorker) {\n\t\tservices.push(` rabbitmq:\n image: rabbitmq:3-management-alpine\n container_name: ${options.name}-rabbitmq\n restart: unless-stopped\n ports:\n - '5672:5672'\n - '15672:15672'\n environment:\n RABBITMQ_DEFAULT_USER: guest\n RABBITMQ_DEFAULT_PASS: guest\n volumes:\n - rabbitmq_data:/var/lib/rabbitmq\n healthcheck:\n test: ['CMD', 'rabbitmq-diagnostics', 'check_running']\n interval: 10s\n timeout: 5s\n retries: 5`);\n\t\tvolumes.push(' rabbitmq_data:');\n\t}\n\n\t// Mailpit for email testing\n\tif (options.services?.mail) {\n\t\tservices.push(` mailpit:\n image: axllent/mailpit:latest\n container_name: ${options.name}-mailpit\n restart: unless-stopped\n ports:\n - '1025:1025'\n - '8025:8025'\n environment:\n MP_SMTP_AUTH_ACCEPT_ANY: 1\n MP_SMTP_AUTH_ALLOW_INSECURE: 1`);\n\t}\n\n\t// Build docker-compose.yml\n\tlet dockerCompose = `services:\n${services.join('\\n\\n')}\n`;\n\n\tif (volumes.length > 0) {\n\t\tdockerCompose += `\nvolumes:\n${volumes.join('\\n')}\n`;\n\t}\n\n\t// Add docker-compose.yml to files\n\tfiles.push({\n\t\tpath: 'docker-compose.yml',\n\t\tcontent: dockerCompose,\n\t});\n\n\treturn files;\n}\n\n/**\n * Generate .env file for docker-compose with database passwords\n */\nfunction generateDockerEnv(apps: DatabaseAppConfig[]): string {\n\tconst envVars = apps.map((app) => {\n\t\tconst envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\treturn `${envVar}=${app.password}`;\n\t});\n\n\treturn `# Auto-generated docker environment file\n# Contains database passwords for docker-compose postgres init\n# This file is gitignored - do not commit to version control\n${envVars.join('\\n')}\n`;\n}\n\n/**\n * Generate PostgreSQL init shell script that creates per-app users with separate schemas\n * Uses environment variables for passwords (more secure than hardcoded values)\n * - api user: uses public schema\n * - auth user: uses auth schema with search_path=auth\n */\nfunction generatePostgresInitScript(apps: DatabaseAppConfig[]): string {\n\tconst userCreations = apps.map((app) => {\n\t\tconst userName = app.name.replace(/-/g, '_');\n\t\tconst envVar = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\tconst isApi = app.name === 'api';\n\t\tconst schemaName = isApi ? 'public' : userName;\n\n\t\tif (isApi) {\n\t\t\t// API user uses public schema\n\t\t\treturn `\n# Create ${app.name} user (uses public schema)\necho \"Creating user ${userName}...\"\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n CREATE USER ${userName} WITH PASSWORD '$${envVar}';\n GRANT ALL ON SCHEMA public TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${userName};\nEOSQL\n`;\n\t\t}\n\t\t// Other users get their own schema with search_path\n\t\treturn `\n# Create ${app.name} user with dedicated schema\necho \"Creating user ${userName} with schema ${schemaName}...\"\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname \"$POSTGRES_DB\" <<-EOSQL\n CREATE USER ${userName} WITH PASSWORD '$${envVar}';\n CREATE SCHEMA ${schemaName} AUTHORIZATION ${userName};\n ALTER USER ${userName} SET search_path TO ${schemaName};\n GRANT USAGE ON SCHEMA ${schemaName} TO ${userName};\n GRANT ALL ON ALL TABLES IN SCHEMA ${schemaName} TO ${userName};\n GRANT ALL ON ALL SEQUENCES IN SCHEMA ${schemaName} TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA ${schemaName} GRANT ALL ON TABLES TO ${userName};\n ALTER DEFAULT PRIVILEGES IN SCHEMA ${schemaName} GRANT ALL ON SEQUENCES TO ${userName};\nEOSQL\n`;\n\t});\n\n\treturn `#!/bin/bash\nset -e\n\n# Auto-generated PostgreSQL init script\n# Creates per-app users with separate schemas in a single database\n# - api: uses public schema\n# - auth: uses auth schema (search_path=auth)\n${userCreations.join('\\n')}\necho \"Database initialization complete!\"\n`;\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate environment-related files (.gitignore only).\n * Note: .env files are no longer generated. Use `gkm secrets:init` to initialize\n * encrypted secrets stored in `.gkm/secrets/{stage}.json` with keys stored at\n * `~/.gkm/{project-name}/{stage}.key`.\n */\nexport function generateEnvFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n): GeneratedFile[] {\n\tconst files: GeneratedFile[] = [];\n\n\t// Only add .gitignore for non-monorepo (monorepo has it at root)\n\tif (!options.monorepo) {\n\t\tconst gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n.gkm/\n\n# Environment (legacy - use gkm secrets instead)\n.env\n.env.local\n.env.*.local\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\npnpm-debug.log*\n\n# Test coverage\ncoverage/\n\n# TypeScript cache\n*.tsbuildinfo\n`;\n\t\tfiles.push({\n\t\t\tpath: '.gitignore',\n\t\t\tcontent: gitignore,\n\t\t});\n\t}\n\n\treturn files;\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\n\n/**\n * Generate packages/models for shared Zod schemas (monorepo only)\n */\nexport function generateModelsPackage(\n\toptions: TemplateOptions,\n): GeneratedFile[] {\n\tif (!options.monorepo) {\n\t\treturn [];\n\t}\n\n\t// Package name based on project name\n\tconst packageName = `@${options.name}/models`;\n\n\t// package.json for models\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\texports: {\n\t\t\t'./*': './src/*.ts',\n\t\t},\n\t\tscripts: {\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\tzod: '~4.1.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// tsconfig.json for models - extends root config\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tdeclaration: true,\n\t\t\tdeclarationMap: true,\n\t\t\toutDir: './dist',\n\t\t\trootDir: './src',\n\t\t},\n\t\tinclude: ['src/**/*.ts'],\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// common.ts - shared utility schemas\n\tconst commonTs = `import { z } from 'zod';\n\n// ============================================\n// Common Schemas\n// ============================================\n\nexport const IdSchema = z.string().uuid();\n\nexport const TimestampsSchema = z.object({\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n});\n\nexport const PaginationSchema = z.object({\n page: z.coerce.number().int().positive().default(1),\n limit: z.coerce.number().int().positive().max(100).default(20),\n});\n\nexport const PaginatedResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>\n z.object({\n items: z.array(itemSchema),\n total: z.number(),\n page: z.number(),\n limit: z.number(),\n totalPages: z.number(),\n });\n\n// ============================================\n// Type Exports\n// ============================================\n\nexport type Id = z.infer<typeof IdSchema>;\nexport type Timestamps = z.infer<typeof TimestampsSchema>;\nexport type Pagination = z.infer<typeof PaginationSchema>;\n`;\n\n\t// user.ts - user-related schemas\n\tconst userTs = `import { z } from 'zod';\nimport { IdSchema, TimestampsSchema } from './common.js';\n\n// ============================================\n// User Schemas\n// ============================================\n\nexport const UserSchema = z.object({\n id: IdSchema,\n email: z.string().email(),\n name: z.string().min(1).max(100),\n ...TimestampsSchema.shape,\n});\n\nexport const CreateUserSchema = UserSchema.omit({\n id: true,\n createdAt: true,\n updatedAt: true,\n});\n\nexport const UpdateUserSchema = CreateUserSchema.partial();\n\n// ============================================\n// Response Schemas\n// ============================================\n\nexport const UserResponseSchema = UserSchema.pick({\n id: true,\n name: true,\n email: true,\n});\n\nexport const ListUsersResponseSchema = z.object({\n users: z.array(UserSchema.pick({ id: true, name: true })),\n});\n\n// ============================================\n// Type Exports\n// ============================================\n\nexport type User = z.infer<typeof UserSchema>;\nexport type CreateUser = z.infer<typeof CreateUserSchema>;\nexport type UpdateUser = z.infer<typeof UpdateUserSchema>;\nexport type UserResponse = z.infer<typeof UserResponseSchema>;\nexport type ListUsersResponse = z.infer<typeof ListUsersResponseSchema>;\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'packages/models/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/src/common.ts',\n\t\t\tcontent: commonTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'packages/models/src/user.ts',\n\t\t\tcontent: userTs,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate monorepo root files (pnpm-workspace.yaml, root package.json, etc.)\n */\nexport function generateMonorepoFiles(\n\toptions: TemplateOptions,\n\t_template: TemplateConfig,\n): GeneratedFile[] {\n\tif (!options.monorepo) {\n\t\treturn [];\n\t}\n\n\tconst isFullstack = options.template === 'fullstack';\n\n\t// Root package.json for monorepo\n\tconst rootPackageJson = {\n\t\tname: options.name,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tpackageManager: 'pnpm@10.13.1',\n\t\tscripts: {\n\t\t\tdev: isFullstack ? 'gkm dev' : 'turbo dev',\n\t\t\tbuild: isFullstack ? 'gkm build' : 'turbo build',\n\t\t\ttest: isFullstack ? 'gkm test' : 'turbo test',\n\t\t\t'test:once': isFullstack ? 'gkm test --run' : 'turbo test:once',\n\t\t\ttypecheck: 'turbo typecheck',\n\t\t\tlint: 'biome lint .',\n\t\t\tfmt: 'biome format . --write',\n\t\t\t'fmt:check': 'biome format .',\n\t\t\t...(options.deployTarget === 'dokploy'\n\t\t\t\t? { deploy: 'gkm deploy --provider dokploy --stage production' }\n\t\t\t\t: {}),\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@biomejs/biome': '~2.3.0',\n\t\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t\tturbo: '~2.3.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t\tvitest: '~4.0.0',\n\t\t},\n\t};\n\n\t// pnpm-workspace.yaml - detect folder structure from apiPath\n\tconst apiPathParts = options.apiPath.split('/');\n\tconst appsFolder = apiPathParts[0] || 'apps';\n\n\tconst pnpmWorkspace = `packages:\n - '${appsFolder}/*'\n - 'packages/*'\n`;\n\n\t// Root biome.json\n\tconst biomeConfig = {\n\t\t$schema: 'https://biomejs.dev/schemas/2.3.0/schema.json',\n\t\tvcs: {\n\t\t\tenabled: true,\n\t\t\tclientKind: 'git',\n\t\t\tuseIgnoreFile: true,\n\t\t},\n\t\torganizeImports: {\n\t\t\tenabled: true,\n\t\t},\n\t\tformatter: {\n\t\t\tenabled: true,\n\t\t\tindentStyle: 'space',\n\t\t\tindentWidth: 2,\n\t\t\tlineWidth: 80,\n\t\t},\n\t\tjavascript: {\n\t\t\tformatter: {\n\t\t\t\tquoteStyle: 'single',\n\t\t\t\ttrailingCommas: 'all',\n\t\t\t\tsemicolons: 'always',\n\t\t\t\tarrowParentheses: 'always',\n\t\t\t},\n\t\t},\n\t\tlinter: {\n\t\t\tenabled: true,\n\t\t\trules: {\n\t\t\t\trecommended: true,\n\t\t\t\tcorrectness: {\n\t\t\t\t\tnoUnusedImports: 'error',\n\t\t\t\t\tnoUnusedVariables: 'error',\n\t\t\t\t},\n\t\t\t\tstyle: {\n\t\t\t\t\tnoNonNullAssertion: 'off',\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tfiles: {\n\t\t\tignore: ['node_modules', 'dist', '.gkm', 'coverage'],\n\t\t},\n\t};\n\n\t// Root turbo.json\n\tconst turboConfig = {\n\t\t$schema: 'https://turbo.build/schema.json',\n\t\ttasks: {\n\t\t\tbuild: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['dist/**'],\n\t\t\t},\n\t\t\tdev: {\n\t\t\t\tcache: false,\n\t\t\t\tpersistent: true,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\tcache: false,\n\t\t\t},\n\t\t\t'test:once': {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: ['coverage/**'],\n\t\t\t},\n\t\t\ttypecheck: {\n\t\t\t\tdependsOn: ['^build'],\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tlint: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t\tfmt: {\n\t\t\t\toutputs: [],\n\t\t\t},\n\t\t},\n\t};\n\n\t// Root .gitignore\n\tconst gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n.gkm/\n\n# Environment\n.env\n.env.local\n.env.*.local\ndocker/.env\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\npnpm-debug.log*\n\n# Test coverage\ncoverage/\n\n# TypeScript cache\n*.tsbuildinfo\n\n# Turbo\n.turbo/\n`;\n\n\t// Root tsconfig.json - base config for all packages\n\t// Using turbo typecheck to run tsc --noEmit in each app/package\n\tconst tsConfig = {\n\t\tcompilerOptions: {\n\t\t\ttarget: 'ES2022',\n\t\t\tmodule: 'NodeNext',\n\t\t\tmoduleResolution: 'NodeNext',\n\t\t\tlib: ['ES2022'],\n\t\t\tstrict: true,\n\t\t\tesModuleInterop: true,\n\t\t\tskipLibCheck: true,\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tresolveJsonModule: true,\n\t\t},\n\t\texclude: ['node_modules', 'dist'],\n\t};\n\n\t// Vitest config for workspace\n\tconst vitestConfig = `import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n globals: true,\n environment: 'node',\n include: ['apps/**/*.{test,spec}.ts', 'packages/**/*.{test,spec}.ts'],\n exclude: ['**/node_modules/**', '**/dist/**'],\n coverage: {\n provider: 'v8',\n reporter: ['text', 'json', 'html'],\n exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'],\n },\n },\n});\n`;\n\n\tconst files: GeneratedFile[] = [\n\t\t{\n\t\t\tpath: 'package.json',\n\t\t\tcontent: `${JSON.stringify(rootPackageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'pnpm-workspace.yaml',\n\t\t\tcontent: pnpmWorkspace,\n\t\t},\n\t\t{\n\t\t\tpath: 'tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'biome.json',\n\t\t\tcontent: `${JSON.stringify(biomeConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'turbo.json',\n\t\t\tcontent: `${JSON.stringify(turboConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'vitest.config.ts',\n\t\t\tcontent: vitestConfig,\n\t\t},\n\t\t{\n\t\t\tpath: '.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n\n\t// Add workspace config for fullstack template\n\tif (isFullstack) {\n\t\tfiles.push({\n\t\t\tpath: 'gkm.config.ts',\n\t\t\tcontent: generateWorkspaceConfig(options),\n\t\t});\n\t}\n\n\treturn files;\n}\n\n/**\n * Generate gkm.config.ts with defineWorkspace for fullstack template\n */\nfunction generateWorkspaceConfig(options: TemplateOptions): string {\n\tconst { telescope, services, deployTarget, routesStructure } = options;\n\n\t// Get routes glob pattern\n\tconst getRoutesGlob = (): string => {\n\t\tswitch (routesStructure) {\n\t\t\tcase 'centralized-endpoints':\n\t\t\t\treturn './src/endpoints/**/*.ts';\n\t\t\tcase 'centralized-routes':\n\t\t\t\treturn './src/routes/**/*.ts';\n\t\t\tcase 'domain-based':\n\t\t\t\treturn './src/**/routes/*.ts';\n\t\t}\n\t};\n\n\tlet config = `import { defineWorkspace } from '@geekmidas/cli/config';\n\nexport default defineWorkspace({\n name: '${options.name}',\n apps: {\n api: {\n type: 'backend',\n path: 'apps/api',\n port: 3000,\n routes: '${getRoutesGlob()}',\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',`;\n\n\tif (telescope) {\n\t\tconfig += `\n telescope: {\n enabled: true,\n path: '/__telescope',\n },`;\n\t}\n\n\tconfig += `\n openapi: {\n enabled: true,\n },\n },\n auth: {\n type: 'backend',\n path: 'apps/auth',\n port: 3002,\n envParser: './src/config/env#envParser',\n logger: './src/config/logger#logger',\n },\n web: {\n type: 'frontend',\n framework: 'nextjs',\n path: 'apps/web',\n port: 3001,\n dependencies: ['api', 'auth'],\n client: {\n output: './src/api',\n },\n },\n },\n shared: {\n packages: ['packages/*'],\n models: {\n path: 'packages/models',\n schema: 'zod',\n },\n },`;\n\n\t// Add services if any are selected\n\tif (services.db || services.cache || services.mail) {\n\t\tconfig += `\n services: {`;\n\t\tif (services.db) {\n\t\t\tconfig += `\n db: true,`;\n\t\t}\n\t\tif (services.cache) {\n\t\t\tconfig += `\n cache: true,`;\n\t\t}\n\t\tif (services.mail) {\n\t\t\tconfig += `\n mail: true,`;\n\t\t}\n\t\tconfig += `\n },`;\n\t}\n\n\t// Add deploy config if dokploy is selected\n\tif (deployTarget === 'dokploy') {\n\t\tconfig += `\n deploy: {\n default: 'dokploy',\n },`;\n\t}\n\n\tconfig += `\n});\n`;\n\n\treturn config;\n}\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const apiTemplate: TemplateConfig = {\n\tname: 'api',\n\tdescription: 'Full API with auth, database, services',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/events': GEEKMIDAS_VERSIONS['@geekmidas/events'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@geekmidas/services': GEEKMIDAS_VERSIONS['@geekmidas/services'],\n\t\t'@geekmidas/errors': GEEKMIDAS_VERSIONS['@geekmidas/errors'],\n\t\t'@geekmidas/auth': GEEKMIDAS_VERSIONS['@geekmidas/auth'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure, monorepo, name } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Models package import path for monorepo\n\t\tconst modelsImport = monorepo ? `@${name}/models` : null;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based': {\n\t\t\t\t\tconst parts = file.split('/');\n\t\t\t\t\tif (parts.length === 1) {\n\t\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t\t\t}\n\t\t\t\t\treturn `src/${parts[0]}/routes/${parts.slice(1).join('/')}`;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\n\t\t\t// users endpoints\n\t\t\t{\n\t\t\t\tpath: getRoutePath('users/list.ts'),\n\t\t\t\tcontent: modelsImport\n\t\t\t\t\t? `import { e } from '@geekmidas/constructs/endpoints';\nimport { ListUsersResponseSchema } from '${modelsImport}/user';\n\nexport const listUsersEndpoint = e\n .get('/users')\n .output(ListUsersResponseSchema)\n .handle(async () => ({\n users: [\n { id: '1', name: 'Alice' },\n { id: '2', name: 'Bob' },\n ],\n }));\n`\n\t\t\t\t\t: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nconst UserSchema = z.object({\n id: z.string(),\n name: z.string(),\n});\n\nexport const listUsersEndpoint = e\n .get('/users')\n .output(z.object({\n users: z.array(UserSchema),\n }))\n .handle(async () => ({\n users: [\n { id: '1', name: 'Alice' },\n { id: '2', name: 'Bob' },\n ],\n }));\n`,\n\t\t\t},\n\t\t\t{\n\t\t\t\tpath: getRoutePath('users/get.ts'),\n\t\t\t\tcontent: modelsImport\n\t\t\t\t\t? `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\nimport { UserResponseSchema } from '${modelsImport}/user';\n\nexport const getUserEndpoint = e\n .get('/users/:id')\n .params(z.object({ id: z.string() }))\n .output(UserResponseSchema)\n .handle(async ({ params }) => ({\n id: params.id,\n name: 'Alice',\n email: 'alice@example.com',\n }));\n`\n\t\t\t\t\t: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const getUserEndpoint = e\n .get('/users/:id')\n .params(z.object({ id: z.string() }))\n .output(z.object({\n id: z.string(),\n name: z.string(),\n email: z.string().email(),\n }))\n .handle(async ({ params }) => ({\n id: params.id,\n name: 'Alice',\n email: 'alice@example.com',\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add database service if enabled\n\t\tif (options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/services/database.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\n\n// Define your database schema\nexport interface Database {\n users: {\n id: string;\n name: string;\n email: string;\n created_at: Date;\n };\n}\n\nexport const databaseService = {\n serviceName: 'database' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to database');\n\n const config = envParser\n .create((get) => ({\n url: get('DATABASE_URL').string(),\n }))\n .parse();\n\n const db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: config.url }),\n }),\n });\n\n logger.info('Database connection established');\n return db;\n },\n} satisfies Service<'database', Kysely<Database>>;\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Studio config if enabled (requires database)\n\t\tif (options.studio && options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/studio.ts',\n\t\t\t\tcontent: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport type { Database } from '../services/database.js';\nimport { envParser } from './env.js';\n\n// Parse database config for Studio\nconst studioConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n }))\n .parse();\n\n// Create a Kysely instance for Studio\nconst db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),\n }),\n});\n\nexport const studio = new Studio<Database>({\n monitoring: {\n storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),\n },\n data: {\n db,\n cursor: { field: 'id', direction: Direction.Desc },\n },\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const minimalTemplate: TemplateConfig = {\n\tname: 'minimal',\n\tdescription: 'Basic health endpoint',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add database service if enabled\n\t\tif (options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/services/database.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\n\n// Define your database schema\nexport interface Database {\n // Add your tables here\n}\n\nexport const databaseService = {\n serviceName: 'database' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to database');\n\n const config = envParser\n .create((get) => ({\n url: get('DATABASE_URL').string(),\n }))\n .parse();\n\n const db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: config.url }),\n }),\n });\n\n logger.info('Database connection established');\n return db;\n },\n} satisfies Service<'database', Kysely<Database>>;\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\t// Add Studio config if enabled (requires database)\n\t\tif (options.studio && options.database) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/studio.ts',\n\t\t\t\tcontent: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';\nimport { Kysely, PostgresDialect } from 'kysely';\nimport pg from 'pg';\nimport type { Database } from '../services/database.js';\nimport { envParser } from './env.js';\n\n// Parse database config for Studio\nconst studioConfig = envParser\n .create((get) => ({\n databaseUrl: get('DATABASE_URL').string(),\n }))\n .parse();\n\n// Create a Kysely instance for Studio\nconst db = new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),\n }),\n});\n\nexport const studio = new Studio<Database>({\n monitoring: {\n storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),\n },\n data: {\n db,\n cursor: { field: 'id', direction: Direction.Desc },\n },\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const serverlessTemplate: TemplateConfig = {\n\tname: 'serverless',\n\tdescription: 'AWS Lambda handlers',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/cloud': GEEKMIDAS_VERSIONS['@geekmidas/cloud'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/aws-lambda': '~8.10.92',\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build --provider aws-apigatewayv2',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['dev', 'staging', 'prod']).default('dev'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n region: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n region: process.env.AWS_REGION || 'local',\n }));\n`,\n\t\t\t},\n\n\t\t\t// src/functions/hello.ts\n\t\t\t{\n\t\t\t\tpath: 'src/functions/hello.ts',\n\t\t\t\tcontent: `import { f } from '@geekmidas/constructs/functions';\nimport { z } from 'zod';\n\nexport const helloFunction = f\n .input(z.object({ name: z.string() }))\n .output(z.object({ message: z.string() }))\n .handle(async ({ input }) => ({\n message: \\`Hello, \\${input.name}!\\`,\n }));\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\n// Note: For production Lambda, consider using a persistent storage\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 50 }),\n enabled: process.env.STAGE === 'dev',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { GEEKMIDAS_VERSIONS } from '../versions.js';\nimport type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from './index.js';\n\nexport const workerTemplate: TemplateConfig = {\n\tname: 'worker',\n\tdescription: 'Background job processing',\n\n\tdependencies: {\n\t\t'@geekmidas/audit': GEEKMIDAS_VERSIONS['@geekmidas/audit'],\n\t\t'@geekmidas/constructs': GEEKMIDAS_VERSIONS['@geekmidas/constructs'],\n\t\t'@geekmidas/envkit': GEEKMIDAS_VERSIONS['@geekmidas/envkit'],\n\t\t'@geekmidas/events': GEEKMIDAS_VERSIONS['@geekmidas/events'],\n\t\t'@geekmidas/logger': GEEKMIDAS_VERSIONS['@geekmidas/logger'],\n\t\t'@geekmidas/rate-limit': GEEKMIDAS_VERSIONS['@geekmidas/rate-limit'],\n\t\t'@geekmidas/schema': GEEKMIDAS_VERSIONS['@geekmidas/schema'],\n\t\t'@hono/node-server': '~1.14.1',\n\t\thono: '~4.8.2',\n\t\tpino: '~9.6.0',\n\t},\n\n\tdevDependencies: {\n\t\t'@biomejs/biome': '~2.3.0',\n\t\t'@geekmidas/cli': GEEKMIDAS_VERSIONS['@geekmidas/cli'],\n\t\t'@types/node': '~22.0.0',\n\t\ttsx: '~4.20.0',\n\t\tturbo: '~2.3.0',\n\t\ttypescript: '~5.8.2',\n\t\tvitest: '~4.0.0',\n\t},\n\n\tscripts: {\n\t\tdev: 'gkm dev',\n\t\tbuild: 'gkm build',\n\t\ttest: 'vitest',\n\t\t'test:once': 'vitest run',\n\t\ttypecheck: 'tsc --noEmit',\n\t\tlint: 'biome lint .',\n\t\tfmt: 'biome format . --write',\n\t\t'fmt:check': 'biome format .',\n\t},\n\n\tfiles: (options: TemplateOptions): GeneratedFile[] => {\n\t\tconst { loggerType, routesStructure } = options;\n\n\t\tconst loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';\n\nexport const logger = createLogger();\n`;\n\n\t\t// Get route path based on structure\n\t\tconst getRoutePath = (file: string) => {\n\t\t\tswitch (routesStructure) {\n\t\t\t\tcase 'centralized-endpoints':\n\t\t\t\t\treturn `src/endpoints/${file}`;\n\t\t\t\tcase 'centralized-routes':\n\t\t\t\t\treturn `src/routes/${file}`;\n\t\t\t\tcase 'domain-based':\n\t\t\t\t\treturn `src/${file.replace('.ts', '')}/routes/index.ts`;\n\t\t\t}\n\t\t};\n\n\t\tconst files: GeneratedFile[] = [\n\t\t\t// src/config/env.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/env.ts',\n\t\t\t\tcontent: `import { Credentials } from '@geekmidas/envkit/credentials';\nimport { EnvironmentParser } from '@geekmidas/envkit';\n\nexport const envParser = new EnvironmentParser({ ...process.env, ...Credentials });\n\n// Global config - only minimal shared values\n// Service-specific config should be parsed in each service\nexport const config = envParser\n .create((get) => ({\n nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),\n stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),\n }))\n .parse();\n`,\n\t\t\t},\n\n\t\t\t// src/config/logger.ts\n\t\t\t{\n\t\t\t\tpath: 'src/config/logger.ts',\n\t\t\t\tcontent: loggerContent,\n\t\t\t},\n\n\t\t\t// health endpoint\n\t\t\t{\n\t\t\t\tpath: getRoutePath('health.ts'),\n\t\t\t\tcontent: `import { e } from '@geekmidas/constructs/endpoints';\nimport { z } from 'zod';\n\nexport const healthEndpoint = e\n .get('/health')\n .output(z.object({\n status: z.string(),\n timestamp: z.string(),\n }))\n .handle(async () => ({\n status: 'ok',\n timestamp: new Date().toISOString(),\n }));\n`,\n\t\t\t},\n\n\t\t\t// src/events/types.ts\n\t\t\t{\n\t\t\t\tpath: 'src/events/types.ts',\n\t\t\t\tcontent: `import type { PublishableMessage } from '@geekmidas/events';\n\n// Define your event types here\nexport type AppEvents =\n | PublishableMessage<'user.created', { userId: string; email: string }>\n | PublishableMessage<'user.updated', { userId: string; changes: Record<string, unknown> }>\n | PublishableMessage<'order.placed', { orderId: string; userId: string; total: number }>;\n`,\n\t\t\t},\n\n\t\t\t// src/events/publisher.ts\n\t\t\t{\n\t\t\t\tpath: 'src/events/publisher.ts',\n\t\t\t\tcontent: `import type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport { Publisher, type EventPublisher } from '@geekmidas/events';\nimport type { AppEvents } from './types.js';\n\nexport const eventsPublisherService = {\n serviceName: 'events' as const,\n async register({ envParser, context }: ServiceRegisterOptions) {\n const logger = context.getLogger();\n logger.info('Connecting to message broker');\n\n const config = envParser\n .create((get) => ({\n url: get('RABBITMQ_URL').string().default('amqp://localhost:5672'),\n }))\n .parse();\n\n const publisher = await Publisher.fromConnectionString<AppEvents>(\n \\`rabbitmq://\\${config.url.replace('amqp://', '')}?exchange=events\\`\n );\n\n logger.info('Message broker connection established');\n return publisher;\n },\n} satisfies Service<'events', EventPublisher<AppEvents>>;\n`,\n\t\t\t},\n\n\t\t\t// src/subscribers/user-events.ts\n\t\t\t{\n\t\t\t\tpath: 'src/subscribers/user-events.ts',\n\t\t\t\tcontent: `import { s } from '@geekmidas/constructs/subscribers';\nimport { eventsPublisherService } from '../events/publisher.js';\n\nexport const userEventsSubscriber = s\n .publisher(eventsPublisherService)\n .subscribe(['user.created', 'user.updated'])\n .handle(async ({ event, logger }) => {\n logger.info({ type: event.type, payload: event.payload }, 'Processing user event');\n\n switch (event.type) {\n case 'user.created':\n // Handle user creation\n logger.info({ userId: event.payload.userId }, 'New user created');\n break;\n case 'user.updated':\n // Handle user update\n logger.info({ userId: event.payload.userId }, 'User updated');\n break;\n }\n });\n`,\n\t\t\t},\n\n\t\t\t// src/crons/cleanup.ts\n\t\t\t{\n\t\t\t\tpath: 'src/crons/cleanup.ts',\n\t\t\t\tcontent: `import { cron } from '@geekmidas/constructs/crons';\n\n// Run every day at midnight\nexport const cleanupCron = cron('0 0 * * *')\n .handle(async ({ logger }) => {\n logger.info('Running cleanup job');\n\n // Add your cleanup logic here\n // e.g., delete old sessions, clean up temp files, etc.\n\n logger.info('Cleanup job completed');\n });\n`,\n\t\t\t},\n\t\t];\n\n\t\t// Add Telescope config if enabled\n\t\tif (options.telescope) {\n\t\t\tfiles.push({\n\t\t\t\tpath: 'src/config/telescope.ts',\n\t\t\t\tcontent: `import { Telescope } from '@geekmidas/telescope';\nimport { InMemoryStorage } from '@geekmidas/telescope/storage/memory';\n\nexport const telescope = new Telescope({\n storage: new InMemoryStorage({ maxEntries: 100 }),\n enabled: process.env.NODE_ENV === 'development',\n});\n`,\n\t\t\t});\n\t\t}\n\n\t\treturn files;\n\t},\n};\n","import { apiTemplate } from './api.js';\nimport { minimalTemplate } from './minimal.js';\nimport { serverlessTemplate } from './serverless.js';\nimport { workerTemplate } from './worker.js';\n\n/**\n * OpenAPI output path (fixed, not configurable)\n */\nexport const OPENAPI_OUTPUT_PATH = './.gkm/openapi.ts';\n\n/**\n * Logger implementation type\n */\nexport type LoggerType = 'pino' | 'console';\n\n/**\n * Routes structure pattern\n */\nexport type RoutesStructure =\n\t| 'centralized-endpoints'\n\t| 'centralized-routes'\n\t| 'domain-based';\n\n/**\n * Package manager type\n */\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\n/**\n * Deploy target type\n */\nexport type DeployTarget = 'dokploy' | 'none';\n\n/**\n * Services selection\n */\nexport interface ServicesSelection {\n\tdb: boolean;\n\tcache: boolean;\n\tmail: boolean;\n}\n\n/**\n * Options collected from user prompts\n */\nexport interface TemplateOptions {\n\tname: string;\n\ttemplate: TemplateName;\n\ttelescope: boolean;\n\tdatabase: boolean;\n\tstudio: boolean;\n\tloggerType: LoggerType;\n\troutesStructure: RoutesStructure;\n\tmonorepo: boolean;\n\t/** Path for the API app in monorepo (e.g., 'apps/api') */\n\tapiPath: string;\n\t/** Selected package manager */\n\tpackageManager: PackageManager;\n\t/** Deploy target */\n\tdeployTarget: DeployTarget;\n\t/** Services selection */\n\tservices: ServicesSelection;\n}\n\n/**\n * A file to be generated\n */\nexport interface GeneratedFile {\n\tpath: string;\n\tcontent: string;\n}\n\n/**\n * Template configuration\n */\nexport interface TemplateConfig {\n\tname: TemplateName;\n\tdescription: string;\n\tdependencies: Record<string, string>;\n\tdevDependencies: Record<string, string>;\n\tscripts: Record<string, string>;\n\tfiles: (options: TemplateOptions) => GeneratedFile[];\n}\n\nexport type TemplateName =\n\t| 'minimal'\n\t| 'api'\n\t| 'serverless'\n\t| 'worker'\n\t| 'fullstack';\n\n/**\n * All available templates\n */\nexport const templates: Record<\n\tExclude<TemplateName, 'fullstack'>,\n\tTemplateConfig\n> = {\n\tminimal: minimalTemplate,\n\tapi: apiTemplate,\n\tserverless: serverlessTemplate,\n\tworker: workerTemplate,\n};\n\n/**\n * Template choices for prompts (Story 1.11 simplified to api + fullstack)\n */\nexport const templateChoices = [\n\t{\n\t\ttitle: 'API',\n\t\tvalue: 'api' as TemplateName,\n\t\tdescription: 'Single backend API with endpoints',\n\t},\n\t{\n\t\ttitle: 'Fullstack',\n\t\tvalue: 'fullstack' as TemplateName,\n\t\tdescription: 'Monorepo with API + Next.js + shared models',\n\t},\n];\n\n/**\n * All template choices (includes advanced options)\n */\nexport const allTemplateChoices = [\n\t{\n\t\ttitle: 'Minimal',\n\t\tvalue: 'minimal' as TemplateName,\n\t\tdescription: 'Basic health endpoint',\n\t},\n\t{\n\t\ttitle: 'API',\n\t\tvalue: 'api' as TemplateName,\n\t\tdescription: 'Full API with auth, database, services',\n\t},\n\t{\n\t\ttitle: 'Fullstack',\n\t\tvalue: 'fullstack' as TemplateName,\n\t\tdescription: 'Monorepo with API + Next.js + shared models',\n\t},\n\t{\n\t\ttitle: 'Serverless',\n\t\tvalue: 'serverless' as TemplateName,\n\t\tdescription: 'AWS Lambda handlers',\n\t},\n\t{\n\t\ttitle: 'Worker',\n\t\tvalue: 'worker' as TemplateName,\n\t\tdescription: 'Background job processing',\n\t},\n];\n\n/**\n * Logger type choices for prompts\n */\nexport const loggerTypeChoices = [\n\t{\n\t\ttitle: 'Pino',\n\t\tvalue: 'pino' as LoggerType,\n\t\tdescription: 'Fast JSON logger for production (recommended)',\n\t},\n\t{\n\t\ttitle: 'Console',\n\t\tvalue: 'console' as LoggerType,\n\t\tdescription: 'Simple console logger for development',\n\t},\n];\n\n/**\n * Routes structure choices for prompts\n */\nexport const routesStructureChoices = [\n\t{\n\t\ttitle: 'Centralized (endpoints)',\n\t\tvalue: 'centralized-endpoints' as RoutesStructure,\n\t\tdescription: 'src/endpoints/**/*.ts',\n\t},\n\t{\n\t\ttitle: 'Centralized (routes)',\n\t\tvalue: 'centralized-routes' as RoutesStructure,\n\t\tdescription: 'src/routes/**/*.ts',\n\t},\n\t{\n\t\ttitle: 'Domain-based',\n\t\tvalue: 'domain-based' as RoutesStructure,\n\t\tdescription: 'src/**/routes/*.ts (e.g., src/users/routes/list.ts)',\n\t},\n];\n\n/**\n * Package manager choices for prompts\n */\nexport const packageManagerChoices = [\n\t{\n\t\ttitle: 'pnpm',\n\t\tvalue: 'pnpm' as PackageManager,\n\t\tdescription: 'Fast, disk space efficient (recommended)',\n\t},\n\t{\n\t\ttitle: 'npm',\n\t\tvalue: 'npm' as PackageManager,\n\t\tdescription: 'Node.js default package manager',\n\t},\n\t{\n\t\ttitle: 'yarn',\n\t\tvalue: 'yarn' as PackageManager,\n\t\tdescription: 'Yarn package manager',\n\t},\n\t{\n\t\ttitle: 'bun',\n\t\tvalue: 'bun' as PackageManager,\n\t\tdescription: 'Fast JavaScript runtime and package manager',\n\t},\n];\n\n/**\n * Deploy target choices for prompts\n */\nexport const deployTargetChoices = [\n\t{\n\t\ttitle: 'Dokploy',\n\t\tvalue: 'dokploy' as DeployTarget,\n\t\tdescription: 'Deploy to Dokploy (Docker-based hosting)',\n\t},\n\t{\n\t\ttitle: 'Configure later',\n\t\tvalue: 'none' as DeployTarget,\n\t\tdescription: 'Skip deployment setup for now',\n\t},\n];\n\n/**\n * Services choices for multi-select prompt\n */\nexport const servicesChoices = [\n\t{\n\t\ttitle: 'PostgreSQL',\n\t\tvalue: 'db',\n\t\tdescription: 'PostgreSQL database',\n\t},\n\t{\n\t\ttitle: 'Redis',\n\t\tvalue: 'cache',\n\t\tdescription: 'Redis cache',\n\t},\n\t{\n\t\ttitle: 'Mailpit',\n\t\tvalue: 'mail',\n\t\tdescription: 'Email testing service (dev only)',\n\t},\n];\n\n/**\n * Get a template by name\n */\nexport function getTemplate(name: TemplateName): TemplateConfig | null {\n\tif (name === 'fullstack') {\n\t\t// Fullstack template is handled specially, uses api template as base\n\t\treturn templates.api;\n\t}\n\tconst template = templates[name];\n\tif (!template) {\n\t\tthrow new Error(`Unknown template: ${name}`);\n\t}\n\treturn template;\n}\n\n/**\n * Check if a template is the fullstack monorepo template\n */\nexport function isFullstackTemplate(name: TemplateName): boolean {\n\treturn name === 'fullstack';\n}\n","import {\n\ttype GeneratedFile,\n\tOPENAPI_OUTPUT_PATH,\n\ttype TemplateConfig,\n\ttype TemplateOptions,\n} from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate package.json with dependencies based on template and options\n */\nexport function generatePackageJson(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\tconst { name, telescope, database, studio, monorepo } = options;\n\n\t// Start with template dependencies\n\tconst dependencies = { ...template.dependencies };\n\tconst devDependencies = { ...template.devDependencies };\n\tconst scripts = { ...template.scripts };\n\n\t// Add optional dependencies based on user choices\n\tif (telescope) {\n\t\tdependencies['@geekmidas/telescope'] =\n\t\t\tGEEKMIDAS_VERSIONS['@geekmidas/telescope'];\n\t}\n\n\tif (studio) {\n\t\tdependencies['@geekmidas/studio'] = GEEKMIDAS_VERSIONS['@geekmidas/studio'];\n\t}\n\n\tif (database) {\n\t\tdependencies['@geekmidas/db'] = GEEKMIDAS_VERSIONS['@geekmidas/db'];\n\t\tdependencies.kysely = '~0.28.2';\n\t\tdependencies.pg = '~8.16.0';\n\t\tdevDependencies['@types/pg'] = '~8.15.0';\n\t}\n\n\t// Add zod for schema validation (commonly used)\n\tdependencies.zod = '~4.1.0';\n\n\t// For monorepo apps, remove biome/turbo (they're at root) and lint/fmt scripts\n\tif (monorepo) {\n\t\tdelete devDependencies['@biomejs/biome'];\n\t\tdelete devDependencies.turbo;\n\t\tdelete scripts.lint;\n\t\tdelete scripts.fmt;\n\t\tdelete scripts['fmt:check'];\n\n\t\t// Add models package as dependency\n\t\tdependencies[`@${name}/models`] = 'workspace:*';\n\n\t\t// Remove zod from api package (it's in models)\n\t\tdelete dependencies.zod;\n\t}\n\n\t// Sort dependencies alphabetically\n\tconst sortObject = (obj: Record<string, string>) =>\n\t\tObject.fromEntries(\n\t\t\tObject.entries(obj).sort(([a], [b]) => a.localeCompare(b)),\n\t\t);\n\n\t// For monorepo, derive package name from apiPath (e.g., apps/api -> @name/api)\n\tlet packageName = name;\n\tif (monorepo && options.apiPath) {\n\t\tconst pathParts = options.apiPath.split('/');\n\t\tconst appName = pathParts[pathParts.length - 1] || 'api';\n\t\tpackageName = `@${name}/${appName}`;\n\t}\n\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\texports: {\n\t\t\t'./client': {\n\t\t\t\ttypes: OPENAPI_OUTPUT_PATH,\n\t\t\t\timport: OPENAPI_OUTPUT_PATH,\n\t\t\t},\n\t\t},\n\t\tscripts,\n\t\tdependencies: sortObject(dependencies),\n\t\tdevDependencies: sortObject(devDependencies),\n\t};\n\n\treturn [\n\t\t{\n\t\t\tpath: 'package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t];\n}\n","import type {\n\tGeneratedFile,\n\tTemplateConfig,\n\tTemplateOptions,\n} from '../templates/index.js';\n\n/**\n * Generate source files from template\n */\nexport function generateSourceFiles(\n\toptions: TemplateOptions,\n\ttemplate: TemplateConfig,\n): GeneratedFile[] {\n\treturn template.files(options);\n}\n","import type { GeneratedFile, TemplateOptions } from '../templates/index.js';\nimport { GEEKMIDAS_VERSIONS } from '../versions.js';\n\n/**\n * Generate Next.js web app files for fullstack template\n */\nexport function generateWebAppFiles(options: TemplateOptions): GeneratedFile[] {\n\tif (!options.monorepo || options.template !== 'fullstack') {\n\t\treturn [];\n\t}\n\n\tconst packageName = `@${options.name}/web`;\n\tconst modelsPackage = `@${options.name}/models`;\n\n\t// package.json for web app\n\tconst packageJson = {\n\t\tname: packageName,\n\t\tversion: '0.0.1',\n\t\tprivate: true,\n\t\ttype: 'module',\n\t\tscripts: {\n\t\t\tdev: 'next dev -p 3001',\n\t\t\tbuild: 'next build',\n\t\t\tstart: 'next start',\n\t\t\ttypecheck: 'tsc --noEmit',\n\t\t},\n\t\tdependencies: {\n\t\t\t[modelsPackage]: 'workspace:*',\n\t\t\t'@geekmidas/client': GEEKMIDAS_VERSIONS['@geekmidas/client'],\n\t\t\t'@tanstack/react-query': '~5.80.0',\n\t\t\tnext: '~16.1.0',\n\t\t\treact: '~19.2.0',\n\t\t\t'react-dom': '~19.2.0',\n\t\t},\n\t\tdevDependencies: {\n\t\t\t'@types/node': '~22.0.0',\n\t\t\t'@types/react': '~19.0.0',\n\t\t\t'@types/react-dom': '~19.0.0',\n\t\t\ttypescript: '~5.8.2',\n\t\t},\n\t};\n\n\t// next.config.ts\n\tconst nextConfig = `import type { NextConfig } from 'next';\n\nconst nextConfig: NextConfig = {\n output: 'standalone',\n reactStrictMode: true,\n transpilePackages: ['${modelsPackage}'],\n};\n\nexport default nextConfig;\n`;\n\n\t// tsconfig.json for Next.js\n\t// Note: Next.js handles compilation, so noEmit: true\n\tconst tsConfig = {\n\t\textends: '../../tsconfig.json',\n\t\tcompilerOptions: {\n\t\t\tlib: ['dom', 'dom.iterable', 'ES2022'],\n\t\t\tallowJs: true,\n\t\t\tskipLibCheck: true,\n\t\t\tstrict: true,\n\t\t\tnoEmit: true,\n\t\t\tesModuleInterop: true,\n\t\t\tmodule: 'ESNext',\n\t\t\tmoduleResolution: 'bundler',\n\t\t\tresolveJsonModule: true,\n\t\t\tisolatedModules: true,\n\t\t\tjsx: 'preserve',\n\t\t\tincremental: true,\n\t\t\tplugins: [\n\t\t\t\t{\n\t\t\t\t\tname: 'next',\n\t\t\t\t},\n\t\t\t],\n\t\t\tpaths: {\n\t\t\t\t'@/*': ['./src/*'],\n\t\t\t\t[`${modelsPackage}`]: ['../../packages/models/src'],\n\t\t\t\t[`${modelsPackage}/*`]: ['../../packages/models/src/*'],\n\t\t\t},\n\t\t\tbaseUrl: '.',\n\t\t},\n\t\tinclude: ['next-env.d.ts', '**/*.ts', '**/*.tsx', '.next/types/**/*.ts'],\n\t\texclude: ['node_modules'],\n\t};\n\n\t// Providers with QueryClient\n\tconst providersTsx = `'use client';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { useState } from 'react';\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n const [queryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 60 * 1000,\n },\n },\n }),\n );\n\n return (\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n );\n}\n`;\n\n\t// API client setup\n\tconst apiIndexTs = `import { TypedFetcher } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\n\n// TODO: Run 'gkm openapi' to generate typed paths from your API\n// This is a placeholder that will be replaced by the generated openapi.ts\ninterface paths {\n '/health': {\n get: {\n responses: {\n 200: {\n content: {\n 'application/json': { status: string; timestamp: string };\n };\n };\n };\n };\n };\n '/users': {\n get: {\n responses: {\n 200: {\n content: {\n 'application/json': { users: Array<{ id: string; name: string }> };\n };\n };\n };\n };\n };\n}\n\nconst baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';\n\nconst fetcher = new TypedFetcher<paths>({ baseURL });\n\nconst hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher));\n\nexport const api = Object.assign(fetcher.request.bind(fetcher), hooks);\n`;\n\n\t// App layout\n\tconst layoutTsx = `import type { Metadata } from 'next';\nimport { Providers } from './providers';\n\nexport const metadata: Metadata = {\n title: '${options.name}',\n description: 'Created with gkm init',\n};\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode;\n}) {\n return (\n <html lang=\"en\">\n <body>\n <Providers>{children}</Providers>\n </body>\n </html>\n );\n}\n`;\n\n\t// Home page with API example\n\tconst pageTsx = `import { api } from '@/api';\n\nexport default async function Home() {\n // Type-safe API call using the generated client\n const health = await api('GET /health').catch(() => null);\n\n return (\n <main style={{ padding: '2rem', fontFamily: 'system-ui' }}>\n <h1>Welcome to ${options.name}</h1>\n\n <section style={{ marginTop: '2rem' }}>\n <h2>API Status</h2>\n {health ? (\n <pre style={{ background: '#f0f0f0', padding: '1rem', borderRadius: '8px' }}>\n {JSON.stringify(health, null, 2)}\n </pre>\n ) : (\n <p>Unable to connect to API</p>\n )}\n </section>\n\n <section style={{ marginTop: '2rem' }}>\n <h2>Next Steps</h2>\n <ul>\n <li>Run <code>gkm openapi</code> to generate typed API client</li>\n <li>Edit <code>apps/web/src/app/page.tsx</code> to customize this page</li>\n <li>Add API routes in <code>apps/api/src/endpoints/</code></li>\n <li>Define shared schemas in <code>packages/models/src/</code></li>\n </ul>\n </section>\n </main>\n );\n}\n`;\n\n\t// Environment file for web app\n\tconst envLocal = `# API URL for client-side requests\nNEXT_PUBLIC_API_URL=http://localhost:3000\n`;\n\n\t// .gitignore for Next.js\n\tconst gitignore = `.next/\nnode_modules/\n.env.local\n*.log\n`;\n\n\treturn [\n\t\t{\n\t\t\tpath: 'apps/web/package.json',\n\t\t\tcontent: `${JSON.stringify(packageJson, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/next.config.ts',\n\t\t\tcontent: nextConfig,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/tsconfig.json',\n\t\t\tcontent: `${JSON.stringify(tsConfig, null, 2)}\\n`,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/layout.tsx',\n\t\t\tcontent: layoutTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/providers.tsx',\n\t\t\tcontent: providersTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/app/page.tsx',\n\t\t\tcontent: pageTsx,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/src/api/index.ts',\n\t\t\tcontent: apiIndexTs,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/.env.local',\n\t\t\tcontent: envLocal,\n\t\t},\n\t\t{\n\t\t\tpath: 'apps/web/.gitignore',\n\t\t\tcontent: gitignore,\n\t\t},\n\t];\n}\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';\n\n/**\n * Detect the package manager being used based on lockfiles or npm_config_user_agent\n */\nexport function detectPackageManager(\n\tcwd: string = process.cwd(),\n): PackageManager {\n\t// Check for lockfiles in cwd\n\tif (existsSync(join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\n\tif (existsSync(join(cwd, 'yarn.lock'))) return 'yarn';\n\tif (existsSync(join(cwd, 'bun.lockb'))) return 'bun';\n\tif (existsSync(join(cwd, 'package-lock.json'))) return 'npm';\n\n\t// Check npm_config_user_agent (set when running via npx/pnpm dlx/etc)\n\tconst userAgent = process.env.npm_config_user_agent || '';\n\tif (userAgent.includes('pnpm')) return 'pnpm';\n\tif (userAgent.includes('yarn')) return 'yarn';\n\tif (userAgent.includes('bun')) return 'bun';\n\n\treturn 'npm';\n}\n\n/**\n * Validate project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): boolean | string {\n\tif (!name) {\n\t\treturn 'Project name is required';\n\t}\n\n\t// Check for valid npm package name characters\n\tif (!/^[a-z0-9-_@/.]+$/i.test(name)) {\n\t\treturn 'Project name can only contain letters, numbers, hyphens, underscores, @, /, and .';\n\t}\n\n\t// Check for reserved names\n\tconst reserved = ['node_modules', '.git', 'package.json', 'src'];\n\tif (reserved.includes(name.toLowerCase())) {\n\t\treturn `\"${name}\" is a reserved name`;\n\t}\n\n\treturn true;\n}\n\n/**\n * Check if a directory already exists at the target path\n */\nexport function checkDirectoryExists(\n\tname: string,\n\tcwd: string = process.cwd(),\n): boolean | string {\n\tconst targetPath = join(cwd, name);\n\tif (existsSync(targetPath)) {\n\t\treturn `Directory \"${name}\" already exists`;\n\t}\n\treturn true;\n}\n\n/**\n * Get the install command for a package manager\n */\nexport function getInstallCommand(pkgManager: PackageManager): string {\n\tswitch (pkgManager) {\n\t\tcase 'pnpm':\n\t\t\treturn 'pnpm install';\n\t\tcase 'yarn':\n\t\t\treturn 'yarn';\n\t\tcase 'bun':\n\t\t\treturn 'bun install';\n\t\tdefault:\n\t\t\treturn 'npm install';\n\t}\n}\n\n/**\n * Get the dev command for a package manager\n */\nexport function getRunCommand(\n\tpkgManager: PackageManager,\n\tscript: string,\n): string {\n\tswitch (pkgManager) {\n\t\tcase 'pnpm':\n\t\t\treturn `pnpm ${script}`;\n\t\tcase 'yarn':\n\t\t\treturn `yarn ${script}`;\n\t\tcase 'bun':\n\t\t\treturn `bun run ${script}`;\n\t\tdefault:\n\t\t\treturn `npm run ${script}`;\n\t}\n}\n","import { execSync } from 'node:child_process';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport prompts from 'prompts';\nimport { createStageSecrets } from '../secrets/generator.js';\nimport { getKeyPath } from '../secrets/keystore.js';\nimport { writeStageSecrets } from '../secrets/storage.js';\nimport type { ComposeServiceName } from '../types.js';\nimport { generateAuthAppFiles } from './generators/auth.js';\nimport { generateConfigFiles } from './generators/config.js';\nimport {\n\ttype DatabaseAppConfig,\n\tgenerateDockerFiles,\n} from './generators/docker.js';\nimport { generateEnvFiles } from './generators/env.js';\nimport { generateModelsPackage } from './generators/models.js';\nimport { generateMonorepoFiles } from './generators/monorepo.js';\nimport { generatePackageJson } from './generators/package.js';\nimport { generateSourceFiles } from './generators/source.js';\nimport { generateWebAppFiles } from './generators/web.js';\nimport {\n\ttype DeployTarget,\n\tdeployTargetChoices,\n\tgetTemplate,\n\tisFullstackTemplate,\n\tloggerTypeChoices,\n\ttype PackageManager,\n\tpackageManagerChoices,\n\troutesStructureChoices,\n\ttype ServicesSelection,\n\tservicesChoices,\n\ttype TemplateName,\n\ttype TemplateOptions,\n\ttemplateChoices,\n} from './templates/index.js';\nimport {\n\tcheckDirectoryExists,\n\tdetectPackageManager,\n\tgetInstallCommand,\n\tgetRunCommand,\n\tvalidateProjectName,\n} from './utils.js';\n\nexport interface InitOptions {\n\t/** Project name */\n\tname?: string;\n\t/** Template to use */\n\ttemplate?: TemplateName;\n\t/** Skip dependency installation */\n\tskipInstall?: boolean;\n\t/** Use defaults for all prompts */\n\tyes?: boolean;\n\t/** Force monorepo setup (deprecated, use fullstack template) */\n\tmonorepo?: boolean;\n\t/** API app path in monorepo */\n\tapiPath?: string;\n\t/** Package manager to use */\n\tpm?: PackageManager;\n}\n\n/**\n * Generate a secure random password for database users\n */\nfunction generateDbPassword(): string {\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Generate database URL for an app\n * All apps connect to the same database, but use different users/schemas\n */\nfunction generateDbUrl(\n\tappName: string,\n\tpassword: string,\n\tprojectName: string,\n\thost = 'localhost',\n\tport = 5432,\n): string {\n\tconst userName = appName.replace(/-/g, '_');\n\tconst dbName = `${projectName.replace(/-/g, '_')}_dev`;\n\treturn `postgresql://${userName}:${password}@${host}:${port}/${dbName}`;\n}\n\n/**\n * Main init command - scaffolds a new project\n */\nexport async function initCommand(\n\tprojectName?: string,\n\toptions: InitOptions = {},\n): Promise<void> {\n\tconst cwd = process.cwd();\n\tconst detectedPkgManager = detectPackageManager(cwd);\n\n\t// Handle Ctrl+C gracefully\n\tprompts.override({});\n\tconst onCancel = () => {\n\t\tprocess.exit(0);\n\t};\n\n\t// Gather answers via prompts\n\tconst answers = await prompts(\n\t\t[\n\t\t\t{\n\t\t\t\ttype: projectName || options.name ? null : 'text',\n\t\t\t\tname: 'name',\n\t\t\t\tmessage: 'Project name:',\n\t\t\t\tinitial: 'my-app',\n\t\t\t\tvalidate: (value: string) => {\n\t\t\t\t\tconst nameValid = validateProjectName(value);\n\t\t\t\t\tif (nameValid !== true) return nameValid;\n\t\t\t\t\tconst dirValid = checkDirectoryExists(value, cwd);\n\t\t\t\t\tif (dirValid !== true) return dirValid;\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.template || options.yes ? null : 'select',\n\t\t\t\tname: 'template',\n\t\t\t\tmessage: 'Template:',\n\t\t\t\tchoices: templateChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'multiselect',\n\t\t\t\tname: 'services',\n\t\t\t\tmessage: 'Services (space to select, enter to confirm):',\n\t\t\t\tchoices: servicesChoices.map((c) => ({ ...c, selected: true })),\n\t\t\t\thint: '- Space to select. Return to submit',\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'packageManager',\n\t\t\t\tmessage: 'Package manager:',\n\t\t\t\tchoices: packageManagerChoices,\n\t\t\t\tinitial: packageManagerChoices.findIndex(\n\t\t\t\t\t(c) => c.value === detectedPkgManager,\n\t\t\t\t),\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'deployTarget',\n\t\t\t\tmessage: 'Deployment target:',\n\t\t\t\tchoices: deployTargetChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'confirm',\n\t\t\t\tname: 'telescope',\n\t\t\t\tmessage: 'Include Telescope (debugging dashboard)?',\n\t\t\t\tinitial: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'loggerType',\n\t\t\t\tmessage: 'Logger:',\n\t\t\t\tchoices: loggerTypeChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: options.yes ? null : 'select',\n\t\t\t\tname: 'routesStructure',\n\t\t\t\tmessage: 'Routes structure:',\n\t\t\t\tchoices: routesStructureChoices,\n\t\t\t\tinitial: 0,\n\t\t\t},\n\t\t],\n\t\t{ onCancel },\n\t);\n\n\t// Build final options\n\tconst name = projectName || options.name || answers.name;\n\tif (!name) {\n\t\tconsole.error('Project name is required');\n\t\tprocess.exit(1);\n\t}\n\n\t// Validate name if provided via argument\n\tif (projectName || options.name) {\n\t\tconst nameToValidate = projectName || options.name!;\n\t\tconst nameValid = validateProjectName(nameToValidate);\n\t\tif (nameValid !== true) {\n\t\t\tconsole.error(nameValid);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tconst dirValid = checkDirectoryExists(nameToValidate, cwd);\n\t\tif (dirValid !== true) {\n\t\t\tconsole.error(dirValid);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tconst template: TemplateName = options.template || answers.template || 'api';\n\tconst isFullstack = isFullstackTemplate(template);\n\n\t// For fullstack, force monorepo mode\n\t// For api template, monorepo is optional (via --monorepo flag)\n\tconst monorepo = isFullstack || options.monorepo || false;\n\n\t// Parse services selection\n\tconst servicesArray: string[] = options.yes\n\t\t? ['db', 'cache', 'mail']\n\t\t: answers.services || [];\n\tconst services: ServicesSelection = {\n\t\tdb: servicesArray.includes('db'),\n\t\tcache: servicesArray.includes('cache'),\n\t\tmail: servicesArray.includes('mail'),\n\t};\n\n\tconst pkgManager: PackageManager = options.pm\n\t\t? options.pm\n\t\t: options.yes\n\t\t\t? 'pnpm'\n\t\t\t: (answers.packageManager ?? detectedPkgManager);\n\n\tconst deployTarget: DeployTarget = options.yes\n\t\t? 'dokploy'\n\t\t: (answers.deployTarget ?? 'dokploy');\n\n\tconst database = services.db;\n\tconst templateOptions: TemplateOptions = {\n\t\tname,\n\t\ttemplate,\n\t\ttelescope: options.yes ? true : (answers.telescope ?? true),\n\t\tdatabase,\n\t\tstudio: database,\n\t\tloggerType: options.yes ? 'pino' : (answers.loggerType ?? 'pino'),\n\t\troutesStructure: options.yes\n\t\t\t? 'centralized-endpoints'\n\t\t\t: (answers.routesStructure ?? 'centralized-endpoints'),\n\t\tmonorepo,\n\t\tapiPath: monorepo ? (options.apiPath ?? 'apps/api') : '',\n\t\tpackageManager: pkgManager,\n\t\tdeployTarget,\n\t\tservices,\n\t};\n\n\tconst targetDir = join(cwd, name);\n\tconst baseTemplate = getTemplate(templateOptions.template);\n\n\tconst isMonorepo = templateOptions.monorepo;\n\tconst apiPath = templateOptions.apiPath;\n\n\tconsole.log('\\nš Creating your project...\\n');\n\n\t// Create project directory\n\tawait mkdir(targetDir, { recursive: true });\n\n\t// For monorepo, app files go in the specified apiPath (e.g., apps/api)\n\tconst appDir = isMonorepo ? join(targetDir, apiPath) : targetDir;\n\tif (isMonorepo) {\n\t\tawait mkdir(appDir, { recursive: true });\n\t}\n\n\t// Generate per-app database configs for fullstack template\n\tconst dbApps: DatabaseAppConfig[] = [];\n\tif (isFullstack && services.db) {\n\t\tdbApps.push(\n\t\t\t{ name: 'api', password: generateDbPassword() },\n\t\t\t{ name: 'auth', password: generateDbPassword() },\n\t\t);\n\t}\n\n\t// Collect app files (backend/api)\n\t// Note: Docker files go to root for monorepo, so exclude them here\n\tconst appFiles = baseTemplate\n\t\t? [\n\t\t\t\t...generatePackageJson(templateOptions, baseTemplate),\n\t\t\t\t...generateConfigFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateEnvFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateSourceFiles(templateOptions, baseTemplate),\n\t\t\t\t...(isMonorepo\n\t\t\t\t\t? []\n\t\t\t\t\t: generateDockerFiles(templateOptions, baseTemplate, dbApps)),\n\t\t\t]\n\t\t: [];\n\n\t// For monorepo, docker files go at root level\n\tconst dockerFiles =\n\t\tisMonorepo && baseTemplate\n\t\t\t? generateDockerFiles(templateOptions, baseTemplate, dbApps)\n\t\t\t: [];\n\n\t// Collect root monorepo files (includes packages/models)\n\tconst rootFiles = baseTemplate\n\t\t? [\n\t\t\t\t...generateMonorepoFiles(templateOptions, baseTemplate),\n\t\t\t\t...generateModelsPackage(templateOptions),\n\t\t\t]\n\t\t: [];\n\n\t// Collect web app files for fullstack template\n\tconst webAppFiles = isFullstack ? generateWebAppFiles(templateOptions) : [];\n\n\t// Collect auth app files for fullstack template\n\tconst authAppFiles = isFullstack ? generateAuthAppFiles(templateOptions) : [];\n\n\t// Write root files (for monorepo)\n\tfor (const { path, content } of rootFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write docker files at root for monorepo\n\tfor (const { path, content } of dockerFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write app files (backend)\n\tfor (const { path, content } of appFiles) {\n\t\tconst fullPath = join(appDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write web app files (frontend)\n\tfor (const { path, content } of webAppFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Write auth app files (authentication service)\n\tfor (const { path, content } of authAppFiles) {\n\t\tconst fullPath = join(targetDir, path);\n\t\tawait mkdir(dirname(fullPath), { recursive: true });\n\t\tawait writeFile(fullPath, content);\n\t}\n\n\t// Initialize encrypted secrets for development stage\n\tconsole.log('š Initializing encrypted secrets...\\n');\n\tconst secretServices: ComposeServiceName[] = [];\n\tif (services.db) secretServices.push('postgres');\n\tif (services.cache) secretServices.push('redis');\n\n\tconst devSecrets = createStageSecrets('development', secretServices);\n\n\t// Add common custom secrets\n\tconst customSecrets: Record<string, string> = {\n\t\tNODE_ENV: 'development',\n\t\tPORT: '3000',\n\t\tLOG_LEVEL: 'debug',\n\t\tJWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n\t};\n\n\t// Add per-app database URLs and passwords for fullstack template\n\tif (isFullstack && dbApps.length > 0) {\n\t\tfor (const app of dbApps) {\n\t\t\t// Database URL for the app to use (all apps use same database, different users/schemas)\n\t\t\tconst urlKey = `${app.name.toUpperCase()}_DATABASE_URL`;\n\t\t\tcustomSecrets[urlKey] = generateDbUrl(app.name, app.password, name);\n\n\t\t\t// Database password for docker-compose init script\n\t\t\tconst passwordKey = `${app.name.toUpperCase()}_DB_PASSWORD`;\n\t\t\tcustomSecrets[passwordKey] = app.password;\n\t\t}\n\n\t\t// Auth service secrets (better-auth)\n\t\tcustomSecrets.AUTH_PORT = '3002';\n\t\tcustomSecrets.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\t\tcustomSecrets.BETTER_AUTH_URL = 'http://localhost:3002';\n\t\tcustomSecrets.BETTER_AUTH_TRUSTED_ORIGINS =\n\t\t\t'http://localhost:3000,http://localhost:3001';\n\t}\n\n\tdevSecrets.custom = customSecrets;\n\n\tawait writeStageSecrets(devSecrets, targetDir);\n\tconst keyPath = getKeyPath('development', name);\n\tconsole.log(` Secrets: .gkm/secrets/development.json (encrypted)`);\n\tconsole.log(` Key: ${keyPath}\\n`);\n\n\t// Install dependencies\n\tif (!options.skipInstall) {\n\t\tconsole.log('\\nš¦ Installing dependencies...\\n');\n\t\ttry {\n\t\t\texecSync(getInstallCommand(pkgManager), {\n\t\t\t\tcwd: targetDir,\n\t\t\t\tstdio: 'inherit',\n\t\t\t});\n\t\t} catch {\n\t\t\tconsole.error('Failed to install dependencies');\n\t\t}\n\n\t\t// Format generated files with biome\n\t\ttry {\n\t\t\texecSync('npx @biomejs/biome format --write --unsafe .', {\n\t\t\t\tcwd: targetDir,\n\t\t\t\tstdio: 'inherit',\n\t\t\t});\n\t\t} catch {\n\t\t\t// Silently ignore format errors\n\t\t}\n\t}\n\n\t// Initialize git repository\n\tconsole.log('\\nš¦ Initializing git repository...\\n');\n\ttry {\n\t\texecSync('git init', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git branch -M main', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git add .', { cwd: targetDir, stdio: 'pipe' });\n\t\texecSync('git commit -m \"š Project created with @geekmidas/toolbox\"', {\n\t\t\tcwd: targetDir,\n\t\t\tstdio: 'pipe',\n\t\t});\n\t\tconsole.log(' Initialized git repository on branch main');\n\t} catch {\n\t\tconsole.log(' Could not initialize git repository (git may not be installed)');\n\t}\n\n\t// Print success message with next steps\n\tprintNextSteps(name, templateOptions, pkgManager);\n}\n\n/**\n * Print success message with next steps\n */\nfunction printNextSteps(\n\tprojectName: string,\n\toptions: TemplateOptions,\n\tpkgManager: PackageManager,\n): void {\n\tconst devCommand = getRunCommand(pkgManager, 'dev');\n\tconst cdCommand = `cd ${projectName}`;\n\n\tconsole.log(`\\n${'ā'.repeat(50)}`);\n\tconsole.log('\\nā
Project created successfully!\\n');\n\n\tconsole.log('Next steps:\\n');\n\tconsole.log(` ${cdCommand}`);\n\n\tif (options.services.db) {\n\t\tconsole.log(` # Start PostgreSQL (if not running)`);\n\t\tconsole.log(` docker compose up -d postgres`);\n\t}\n\n\tconsole.log(` ${devCommand}`);\n\tconsole.log('');\n\n\tif (options.monorepo) {\n\t\tconsole.log('š Project structure:');\n\t\tconsole.log(` ${projectName}/`);\n\t\tconsole.log(` āāā apps/`);\n\t\tconsole.log(` ā āāā api/ # Backend API`);\n\t\tif (isFullstackTemplate(options.template)) {\n\t\t\tconsole.log(` ā āāā auth/ # Auth service (better-auth)`);\n\t\t\tconsole.log(` ā āāā web/ # Next.js frontend`);\n\t\t}\n\t\tconsole.log(` āāā packages/`);\n\t\tconsole.log(` ā āāā models/ # Shared Zod schemas`);\n\t\tconsole.log(` āāā .gkm/secrets/ # Encrypted secrets`);\n\t\tconsole.log(` āāā gkm.config.ts # Workspace config`);\n\t\tconsole.log(` āāā turbo.json # Turbo config`);\n\t\tconsole.log('');\n\t}\n\n\tconsole.log('š Secrets management:');\n\tconsole.log(` gkm secrets:show --stage development # View secrets`);\n\tconsole.log(` gkm secrets:set KEY VALUE --stage development # Add secret`);\n\tconsole.log(\n\t\t` gkm secrets:init --stage production # Create production secrets`,\n\t);\n\tconsole.log('');\n\n\tif (options.deployTarget === 'dokploy') {\n\t\tconsole.log('š Deployment:');\n\t\tconsole.log(` ${getRunCommand(pkgManager, 'deploy')}`);\n\t\tconsole.log('');\n\t}\n\n\tconsole.log('š Documentation: https://docs.geekmidas.dev');\n\tconsole.log('');\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { loadConfig } from '../config';\nimport type { ComposeServiceName, ComposeServicesConfig } from '../types';\nimport { createStageSecrets, rotateServicePassword } from './generator';\nimport {\n\tmaskPassword,\n\treadStageSecrets,\n\tsecretsExist,\n\tsetCustomSecret,\n\twriteStageSecrets,\n} from './storage';\n\nconst logger = console;\n\nexport interface SecretsInitOptions {\n\tstage: string;\n\tforce?: boolean;\n}\n\nexport interface SecretsSetOptions {\n\tstage: string;\n}\n\nexport interface SecretsShowOptions {\n\tstage: string;\n\treveal?: boolean;\n}\n\nexport interface SecretsRotateOptions {\n\tstage: string;\n\tservice?: ComposeServiceName;\n}\n\nexport interface SecretsImportOptions {\n\tstage: string;\n\t/** Merge with existing secrets (default: true) */\n\tmerge?: boolean;\n}\n\n/**\n * Extract service names from compose config.\n */\nexport function getServicesFromConfig(\n\tservices: ComposeServicesConfig | ComposeServiceName[] | undefined,\n): ComposeServiceName[] {\n\tif (!services) {\n\t\treturn [];\n\t}\n\n\tif (Array.isArray(services)) {\n\t\treturn services;\n\t}\n\n\t// Object format - get keys where value is truthy\n\treturn (Object.entries(services) as [ComposeServiceName, unknown][])\n\t\t.filter(([, config]) => config)\n\t\t.map(([name]) => name);\n}\n\n/**\n * Initialize secrets for a stage.\n * Generates secure random passwords for configured services.\n */\nexport async function secretsInitCommand(\n\toptions: SecretsInitOptions,\n): Promise<void> {\n\tconst { stage, force } = options;\n\n\t// Check if secrets already exist\n\tif (!force && secretsExist(stage)) {\n\t\tlogger.error(\n\t\t\t`Secrets already exist for stage \"${stage}\". Use --force to overwrite.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Load config to get services\n\tconst config = await loadConfig();\n\tconst services = getServicesFromConfig(config.docker?.compose?.services);\n\n\tif (services.length === 0) {\n\t\tlogger.warn(\n\t\t\t'No services configured in docker.compose.services. Creating secrets with empty services.',\n\t\t);\n\t}\n\n\t// Generate secrets\n\tconst secrets = createStageSecrets(stage, services);\n\n\t// Write to file\n\tawait writeStageSecrets(secrets);\n\n\tlogger.log(`\\nā Secrets initialized for stage \"${stage}\"`);\n\tlogger.log(` Location: .gkm/secrets/${stage}.json`);\n\tlogger.log('\\n Generated credentials for:');\n\n\tfor (const service of services) {\n\t\tlogger.log(` - ${service}`);\n\t}\n\n\tif (secrets.urls.DATABASE_URL) {\n\t\tlogger.log(`\\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);\n\t}\n\tif (secrets.urls.REDIS_URL) {\n\t\tlogger.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);\n\t}\n\tif (secrets.urls.RABBITMQ_URL) {\n\t\tlogger.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);\n\t}\n\n\tlogger.log(`\\n Use \"gkm secrets:show --stage ${stage}\" to view secrets`);\n\tlogger.log(\n\t\t' Use \"gkm secrets:set <KEY> <VALUE> --stage ' +\n\t\t\tstage +\n\t\t\t'\" to add custom secrets',\n\t);\n}\n\n/**\n * Read all data from stdin.\n */\nasync function readStdin(): Promise<string> {\n\tconst chunks: Buffer[] = [];\n\n\tfor await (const chunk of process.stdin) {\n\t\tchunks.push(chunk);\n\t}\n\n\treturn Buffer.concat(chunks).toString('utf-8').trim();\n}\n\n/**\n * Set a custom secret.\n * If value is not provided, reads from stdin.\n */\nexport async function secretsSetCommand(\n\tkey: string,\n\tvalue: string | undefined,\n\toptions: SecretsSetOptions,\n): Promise<void> {\n\tconst { stage } = options;\n\n\t// Read from stdin if value not provided\n\tlet secretValue = value;\n\tif (!secretValue) {\n\t\tif (process.stdin.isTTY) {\n\t\t\tlogger.error(\n\t\t\t\t'No value provided. Use: gkm secrets:set KEY VALUE --stage <stage>',\n\t\t\t);\n\t\t\tlogger.error(\n\t\t\t\t'Or pipe from stdin: echo \"value\" | gkm secrets:set KEY --stage <stage>',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tsecretValue = await readStdin();\n\t\tif (!secretValue) {\n\t\t\tlogger.error('No value received from stdin');\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\ttry {\n\t\tawait setCustomSecret(stage, key, secretValue);\n\t\tlogger.log(`\\nā Secret \"${key}\" set for stage \"${stage}\"`);\n\t} catch (error) {\n\t\tlogger.error(\n\t\t\terror instanceof Error ? error.message : 'Failed to set secret',\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n\n/**\n * Show secrets for a stage.\n */\nexport async function secretsShowCommand(\n\toptions: SecretsShowOptions,\n): Promise<void> {\n\tconst { stage, reveal } = options;\n\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tlogger.log(`\\nSecrets for stage \"${stage}\":`);\n\tlogger.log(` Created: ${secrets.createdAt}`);\n\tlogger.log(` Updated: ${secrets.updatedAt}`);\n\n\t// Show service credentials\n\tlogger.log('\\nService Credentials:');\n\tfor (const [service, creds] of Object.entries(secrets.services)) {\n\t\tif (creds) {\n\t\t\tlogger.log(`\\n ${service}:`);\n\t\t\tlogger.log(` host: ${creds.host}`);\n\t\t\tlogger.log(` port: ${creds.port}`);\n\t\t\tlogger.log(` username: ${creds.username}`);\n\t\t\tlogger.log(\n\t\t\t\t` password: ${reveal ? creds.password : maskPassword(creds.password)}`,\n\t\t\t);\n\t\t\tif (creds.database) {\n\t\t\t\tlogger.log(` database: ${creds.database}`);\n\t\t\t}\n\t\t\tif (creds.vhost) {\n\t\t\t\tlogger.log(` vhost: ${creds.vhost}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Show URLs\n\tlogger.log('\\nConnection URLs:');\n\tif (secrets.urls.DATABASE_URL) {\n\t\tlogger.log(\n\t\t\t` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`,\n\t\t);\n\t}\n\tif (secrets.urls.REDIS_URL) {\n\t\tlogger.log(\n\t\t\t` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`,\n\t\t);\n\t}\n\tif (secrets.urls.RABBITMQ_URL) {\n\t\tlogger.log(\n\t\t\t` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`,\n\t\t);\n\t}\n\n\t// Show custom secrets\n\tconst customKeys = Object.keys(secrets.custom);\n\tif (customKeys.length > 0) {\n\t\tlogger.log('\\nCustom Secrets:');\n\t\tfor (const [key, value] of Object.entries(secrets.custom)) {\n\t\t\tlogger.log(` ${key}: ${reveal ? value : maskPassword(value)}`);\n\t\t}\n\t}\n\n\tif (!reveal) {\n\t\tlogger.log('\\nUse --reveal to show actual values');\n\t}\n}\n\n/**\n * Rotate passwords for services.\n */\nexport async function secretsRotateCommand(\n\toptions: SecretsRotateOptions,\n): Promise<void> {\n\tconst { stage, service } = options;\n\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tif (service) {\n\t\t// Rotate specific service\n\t\tif (!secrets.services[service]) {\n\t\t\tlogger.error(`Service \"${service}\" not configured in stage \"${stage}\"`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconst updated = rotateServicePassword(secrets, service);\n\t\tawait writeStageSecrets(updated);\n\t\tlogger.log(`\\nā Password rotated for ${service} in stage \"${stage}\"`);\n\t} else {\n\t\t// Rotate all services\n\t\tlet updated = secrets;\n\t\tconst services = Object.keys(secrets.services) as ComposeServiceName[];\n\n\t\tfor (const svc of services) {\n\t\t\tupdated = rotateServicePassword(updated, svc);\n\t\t}\n\n\t\tawait writeStageSecrets(updated);\n\t\tlogger.log(\n\t\t\t`\\nā Passwords rotated for all services in stage \"${stage}\": ${services.join(', ')}`,\n\t\t);\n\t}\n\n\tlogger.log(`\\nUse \"gkm secrets:show --stage ${stage}\" to view new values`);\n}\n\n/**\n * Import secrets from a JSON file.\n */\nexport async function secretsImportCommand(\n\tfile: string,\n\toptions: SecretsImportOptions,\n): Promise<void> {\n\tconst { stage, merge = true } = options;\n\n\t// Check if file exists\n\tif (!existsSync(file)) {\n\t\tlogger.error(`File not found: ${file}`);\n\t\tprocess.exit(1);\n\t}\n\n\t// Read and parse JSON file\n\tlet importedSecrets: Record<string, string>;\n\ttry {\n\t\tconst content = await readFile(file, 'utf-8');\n\t\timportedSecrets = JSON.parse(content);\n\n\t\t// Validate it's a flat object with string values\n\t\tif (typeof importedSecrets !== 'object' || importedSecrets === null) {\n\t\t\tthrow new Error('JSON must be an object');\n\t\t}\n\n\t\tfor (const [key, value] of Object.entries(importedSecrets)) {\n\t\t\tif (typeof value !== 'string') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for \"${key}\" must be a string, got ${typeof value}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tlogger.error(\n\t\t\t`Failed to parse JSON file: ${error instanceof Error ? error.message : 'Invalid JSON'}`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Check if secrets exist for stage\n\tconst secrets = await readStageSecrets(stage);\n\n\tif (!secrets) {\n\t\tlogger.error(\n\t\t\t`No secrets found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// Merge or replace custom secrets\n\tconst updatedCustom = merge\n\t\t? { ...secrets.custom, ...importedSecrets }\n\t\t: importedSecrets;\n\n\tconst updated = {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tcustom: updatedCustom,\n\t};\n\n\tawait writeStageSecrets(updated);\n\n\tconst importedCount = Object.keys(importedSecrets).length;\n\tconst totalCount = Object.keys(updatedCustom).length;\n\n\tlogger.log(`\\nā Imported ${importedCount} secrets for stage \"${stage}\"`);\n\n\tif (merge && totalCount > importedCount) {\n\t\tlogger.log(` Total custom secrets: ${totalCount}`);\n\t}\n\n\tlogger.log('\\n Imported keys:');\n\tfor (const key of Object.keys(importedSecrets)) {\n\t\tlogger.log(` - ${key}`);\n\t}\n}\n\n/**\n * Mask password in a URL for display.\n */\nexport function maskUrl(url: string): string {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.password) {\n\t\t\tparsed.password = maskPassword(parsed.password);\n\t\t}\n\t\treturn parsed.toString();\n\t} catch {\n\t\treturn url;\n\t}\n}\n","import { spawn } from 'node:child_process';\nimport { readStageSecrets, toEmbeddableSecrets } from '../secrets/storage';\n\nexport interface TestOptions {\n\t/** Stage to load secrets from (default: development) */\n\tstage?: string;\n\t/** Run tests once without watch mode */\n\trun?: boolean;\n\t/** Enable watch mode */\n\twatch?: boolean;\n\t/** Generate coverage report */\n\tcoverage?: boolean;\n\t/** Open Vitest UI */\n\tui?: boolean;\n\t/** Pattern to filter tests */\n\tpattern?: string;\n}\n\n/**\n * Run tests with secrets loaded from the specified stage.\n * Secrets are decrypted and injected into the environment.\n */\nexport async function testCommand(options: TestOptions = {}): Promise<void> {\n\tconst stage = options.stage ?? 'development';\n\n\tconsole.log(`\\nš§Ŗ Running tests with ${stage} secrets...\\n`);\n\n\t// Load and decrypt secrets\n\tlet envVars: Record<string, string> = {};\n\ttry {\n\t\tconst secrets = await readStageSecrets(stage);\n\t\tif (secrets) {\n\t\t\tenvVars = toEmbeddableSecrets(secrets);\n\t\t\tconsole.log(\n\t\t\t\t` Loaded ${Object.keys(envVars).length} secrets from ${stage}\\n`,\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(` No secrets found for ${stage}, running without secrets\\n`);\n\t\t}\n\t} catch (error) {\n\t\tif (error instanceof Error && error.message.includes('key not found')) {\n\t\t\tconsole.log(\n\t\t\t\t` Decryption key not found for ${stage}, running without secrets\\n`,\n\t\t\t);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t// Build vitest args\n\tconst args: string[] = [];\n\n\tif (options.run) {\n\t\targs.push('run');\n\t} else if (options.watch) {\n\t\targs.push('--watch');\n\t}\n\n\tif (options.coverage) {\n\t\targs.push('--coverage');\n\t}\n\n\tif (options.ui) {\n\t\targs.push('--ui');\n\t}\n\n\tif (options.pattern) {\n\t\targs.push(options.pattern);\n\t}\n\n\t// Run vitest with secrets in environment\n\tconst vitestProcess = spawn('npx', ['vitest', ...args], {\n\t\tcwd: process.cwd(),\n\t\tstdio: 'inherit',\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...envVars,\n\t\t\t// Ensure NODE_ENV is set to test\n\t\t\tNODE_ENV: 'test',\n\t\t},\n\t});\n\n\t// Wait for vitest to complete\n\treturn new Promise((resolve, reject) => {\n\t\tvitestProcess.on('close', (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Tests failed with exit code ${code}`));\n\t\t\t}\n\t\t});\n\n\t\tvitestProcess.on('error', (error) => {\n\t\t\treject(error);\n\t\t});\n\t});\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json';\nimport { loginCommand, logoutCommand, whoamiCommand } from './auth';\nimport { buildCommand } from './build/index';\nimport { type DeployProvider, deployCommand } from './deploy/index';\nimport { deployInitCommand, deployListCommand } from './deploy/init';\nimport { devCommand } from './dev/index';\nimport { type DockerOptions, dockerCommand } from './docker/index';\nimport { type InitOptions, initCommand } from './init/index';\nimport { openapiCommand } from './openapi';\nimport { generateReactQueryCommand } from './openapi-react-query';\nimport {\n\tsecretsImportCommand,\n\tsecretsInitCommand,\n\tsecretsRotateCommand,\n\tsecretsSetCommand,\n\tsecretsShowCommand,\n} from './secrets';\nimport { type TestOptions, testCommand } from './test/index';\nimport type { ComposeServiceName, LegacyProvider, MainProvider } from './types';\n\nconst program = new Command();\n\nprogram\n\t.name('gkm')\n\t.description('GeekMidas backend framework CLI')\n\t.version(pkg.version)\n\t.option('--cwd <path>', 'Change working directory');\n\nprogram\n\t.command('init')\n\t.description('Scaffold a new project')\n\t.argument('[name]', 'Project name')\n\t.option(\n\t\t'--template <template>',\n\t\t'Project template (minimal, api, serverless, worker)',\n\t)\n\t.option('--skip-install', 'Skip dependency installation', false)\n\t.option('-y, --yes', 'Skip prompts, use defaults', false)\n\t.option('--monorepo', 'Setup as monorepo with packages/models', false)\n\t.option('--api-path <path>', 'API app path in monorepo (default: apps/api)')\n\t.option('--pm <manager>', 'Package manager (pnpm, npm, yarn, bun)')\n\t.action(async (name: string | undefined, options: InitOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait initCommand(name, options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('build')\n\t.description('Build handlers from endpoints, functions, and crons')\n\t.option(\n\t\t'--provider <provider>',\n\t\t'Target provider for generated handlers (aws, server)',\n\t)\n\t.option(\n\t\t'--providers <providers>',\n\t\t'[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n\t)\n\t.option(\n\t\t'--enable-openapi',\n\t\t'Enable OpenAPI documentation generation for server builds',\n\t)\n\t.option('--production', 'Build for production (no dev tools, bundled output)')\n\t.option('--skip-bundle', 'Skip bundling step in production build')\n\t.option('--stage <stage>', 'Inject encrypted secrets for deployment stage')\n\t.action(\n\t\tasync (options: {\n\t\t\tprovider?: string;\n\t\t\tproviders?: string;\n\t\t\tenableOpenapi?: boolean;\n\t\t\tproduction?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tstage?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\t// Handle new single provider option\n\t\t\t\tif (options.provider) {\n\t\t\t\t\tif (!['aws', 'server'].includes(options.provider)) {\n\t\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\t}\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: options.provider as MainProvider,\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Handle legacy providers option\n\t\t\t\telse if (options.providers) {\n\t\t\t\t\tconst providerList = [\n\t\t\t\t\t\t...new Set(options.providers.split(',').map((p) => p.trim())),\n\t\t\t\t\t] as LegacyProvider[];\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tproviders: providerList,\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Default to config-driven build\n\t\t\t\telse {\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tenableOpenApi: options.enableOpenapi || false,\n\t\t\t\t\t\tproduction: options.production || false,\n\t\t\t\t\t\tskipBundle: options.skipBundle || false,\n\t\t\t\t\t\tstage: options.stage,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('dev')\n\t.description('Start development server with automatic reload')\n\t.option('-p, --port <port>', 'Port to run the development server on')\n\t.option('--entry <file>', 'Entry file to run (bypasses gkm config)')\n\t.option('--watch', 'Watch for file changes (default: true with --entry)')\n\t.option('--no-watch', 'Disable file watching')\n\t.option(\n\t\t'--enable-openapi',\n\t\t'Enable OpenAPI documentation for development server',\n\t\ttrue,\n\t)\n\t.action(\n\t\tasync (options: {\n\t\t\tport?: string;\n\t\t\tentry?: string;\n\t\t\twatch?: boolean;\n\t\t\tenableOpenapi?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tawait devCommand({\n\t\t\t\t\tport: options.port ? Number.parseInt(options.port, 10) : 3000,\n\t\t\t\t\tportExplicit: !!options.port,\n\t\t\t\t\tenableOpenApi: options.enableOpenapi ?? true,\n\t\t\t\t\tentry: options.entry,\n\t\t\t\t\twatch: options.watch,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('test')\n\t.description('Run tests with secrets loaded from environment')\n\t.option('--stage <stage>', 'Stage to load secrets from', 'development')\n\t.option('--run', 'Run tests once without watch mode')\n\t.option('--watch', 'Enable watch mode')\n\t.option('--coverage', 'Generate coverage report')\n\t.option('--ui', 'Open Vitest UI')\n\t.argument('[pattern]', 'Pattern to filter tests')\n\t.action(async (pattern: string | undefined, options: TestOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait testCommand({ ...options, pattern });\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('cron')\n\t.description('Manage cron jobs')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('Cron management - coming soon\\n');\n\t});\n\nprogram\n\t.command('function')\n\t.description('Manage serverless functions')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('Serverless function management - coming soon\\n');\n\t});\n\nprogram\n\t.command('api')\n\t.description('Manage REST API endpoints')\n\t.action(() => {\n\t\tconst globalOptions = program.opts();\n\t\tif (globalOptions.cwd) {\n\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t}\n\t\tprocess.stdout.write('REST API management - coming soon\\n');\n\t});\n\nprogram\n\t.command('openapi')\n\t.description('Generate OpenAPI specification from endpoints')\n\t.action(async () => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait openapiCommand({});\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('generate:react-query')\n\t.description('Generate React Query hooks from OpenAPI specification')\n\t.option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n\t.option(\n\t\t'--output <path>',\n\t\t'Output file path for generated hooks',\n\t\t'src/api/hooks.ts',\n\t)\n\t.option('--name <name>', 'API name prefix for generated code', 'API')\n\t.action(\n\t\tasync (options: { input?: string; output?: string; name?: string }) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\t\t\t\tawait generateReactQueryCommand(options);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('docker')\n\t.description('Generate Docker deployment files')\n\t.option('--build', 'Build Docker image after generating files')\n\t.option('--push', 'Push image to registry after building')\n\t.option('--tag <tag>', 'Image tag', 'latest')\n\t.option('--registry <registry>', 'Container registry URL')\n\t.option('--slim', 'Use slim Dockerfile (assumes pre-built bundle exists)')\n\t.option('--turbo', 'Use turbo prune for monorepo optimization')\n\t.option('--turbo-package <name>', 'Package name for turbo prune')\n\t.action(async (options: DockerOptions) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait dockerCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('prepack')\n\t.description('Generate Docker files for production deployment')\n\t.option('--build', 'Build Docker image after generating files')\n\t.option('--push', 'Push image to registry after building')\n\t.option('--tag <tag>', 'Image tag', 'latest')\n\t.option('--registry <registry>', 'Container registry URL')\n\t.option('--slim', 'Build locally first, then use slim Dockerfile')\n\t.option('--skip-bundle', 'Skip bundling step (only with --slim)')\n\t.option('--turbo', 'Use turbo prune for monorepo optimization')\n\t.option('--turbo-package <name>', 'Package name for turbo prune')\n\t.action(\n\t\tasync (options: {\n\t\t\tbuild?: boolean;\n\t\t\tpush?: boolean;\n\t\t\ttag?: string;\n\t\t\tregistry?: string;\n\t\t\tslim?: boolean;\n\t\t\tskipBundle?: boolean;\n\t\t\tturbo?: boolean;\n\t\t\tturboPackage?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.slim) {\n\t\t\t\t\tawait buildCommand({\n\t\t\t\t\t\tprovider: 'server',\n\t\t\t\t\t\tproduction: true,\n\t\t\t\t\t\tskipBundle: options.skipBundle,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait dockerCommand({\n\t\t\t\t\tbuild: options.build,\n\t\t\t\t\tpush: options.push,\n\t\t\t\t\ttag: options.tag,\n\t\t\t\t\tregistry: options.registry,\n\t\t\t\t\tslim: options.slim,\n\t\t\t\t\tturbo: options.turbo,\n\t\t\t\t\tturboPackage: options.turboPackage,\n\t\t\t\t});\n\t\t\t\tif (options.slim) {\n\t\t\t\t} else {\n\t\t\t\t}\n\n\t\t\t\tif (options.build) {\n\t\t\t\t\tconst tag = options.tag ?? 'latest';\n\t\t\t\t\tconst registry = options.registry;\n\t\t\t\t\tconst _imageRef = registry ? `${registry}/api:${tag}` : `api:${tag}`;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Secrets management commands\nprogram\n\t.command('secrets:init')\n\t.description('Initialize secrets for a deployment stage')\n\t.requiredOption('--stage <stage>', 'Stage name (e.g., production, staging)')\n\t.option('--force', 'Overwrite existing secrets')\n\t.action(async (options: { stage: string; force?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsInitCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:set')\n\t.description('Set a custom secret for a stage')\n\t.argument('<key>', 'Secret key (e.g., API_KEY)')\n\t.argument('[value]', 'Secret value (reads from stdin if omitted)')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.action(\n\t\tasync (\n\t\t\tkey: string,\n\t\t\tvalue: string | undefined,\n\t\t\toptions: { stage: string },\n\t\t) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\t\t\t\tawait secretsSetCommand(key, value, options);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Command failed',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\nprogram\n\t.command('secrets:show')\n\t.description('Show secrets for a stage')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option('--reveal', 'Show actual secret values (not masked)')\n\t.action(async (options: { stage: string; reveal?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsShowCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:rotate')\n\t.description('Rotate service passwords')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option(\n\t\t'--service <service>',\n\t\t'Specific service to rotate (postgres, redis, rabbitmq)',\n\t)\n\t.action(async (options: { stage: string; service?: ComposeServiceName }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsRotateCommand(options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram\n\t.command('secrets:import')\n\t.description('Import secrets from a JSON file')\n\t.argument('<file>', 'JSON file path (e.g., secrets.json)')\n\t.requiredOption('--stage <stage>', 'Stage name')\n\t.option('--no-merge', 'Replace all custom secrets instead of merging')\n\t.action(async (file: string, options: { stage: string; merge?: boolean }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\t\t\tawait secretsImportCommand(file, options);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : 'Command failed');\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\n// Deploy command\nprogram\n\t.command('deploy')\n\t.description('Deploy application to a provider')\n\t.requiredOption(\n\t\t'--provider <provider>',\n\t\t'Deploy provider (docker, dokploy, aws-lambda)',\n\t)\n\t.requiredOption(\n\t\t'--stage <stage>',\n\t\t'Deployment stage (e.g., production, staging)',\n\t)\n\t.option('--tag <tag>', 'Image tag (default: stage-timestamp)')\n\t.option('--skip-push', 'Skip pushing image to registry')\n\t.option('--skip-build', 'Skip build step (use existing build)')\n\t.action(\n\t\tasync (options: {\n\t\t\tprovider: string;\n\t\t\tstage: string;\n\t\t\ttag?: string;\n\t\t\tskipPush?: boolean;\n\t\t\tskipBuild?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tconst validProviders = ['docker', 'dokploy', 'aws-lambda'];\n\t\t\t\tif (!validProviders.includes(options.provider)) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Invalid provider: ${options.provider}\\n` +\n\t\t\t\t\t\t\t`Valid providers: ${validProviders.join(', ')}`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tawait deployCommand({\n\t\t\t\t\tprovider: options.provider as DeployProvider,\n\t\t\t\t\tstage: options.stage,\n\t\t\t\t\ttag: options.tag,\n\t\t\t\t\tskipPush: options.skipPush,\n\t\t\t\t\tskipBuild: options.skipBuild,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(error instanceof Error ? error.message : 'Deploy failed');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Deploy init command - Initialize Dokploy project and application\nprogram\n\t.command('deploy:init')\n\t.description('Initialize Dokploy deployment (create project and application)')\n\t.option(\n\t\t'--endpoint <url>',\n\t\t'Dokploy server URL (uses stored credentials if logged in)',\n\t)\n\t.requiredOption('--project <name>', 'Project name (creates if not exists)')\n\t.requiredOption('--app <name>', 'Application name')\n\t.option('--project-id <id>', 'Use existing project ID instead of creating')\n\t.option('--registry-id <id>', 'Configure registry for the application')\n\t.action(\n\t\tasync (options: {\n\t\t\tendpoint?: string;\n\t\t\tproject: string;\n\t\t\tapp: string;\n\t\t\tprojectId?: string;\n\t\t\tregistryId?: string;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tawait deployInitCommand({\n\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\tprojectName: options.project,\n\t\t\t\t\tappName: options.app,\n\t\t\t\t\tprojectId: options.projectId,\n\t\t\t\t\tregistryId: options.registryId,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: 'Failed to initialize deployment',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Deploy list command - List Dokploy resources\nprogram\n\t.command('deploy:list')\n\t.description('List Dokploy resources (projects, registries)')\n\t.option(\n\t\t'--endpoint <url>',\n\t\t'Dokploy server URL (uses stored credentials if logged in)',\n\t)\n\t.option('--projects', 'List projects')\n\t.option('--registries', 'List registries')\n\t.action(\n\t\tasync (options: {\n\t\t\tendpoint?: string;\n\t\t\tprojects?: boolean;\n\t\t\tregistries?: boolean;\n\t\t}) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.projects) {\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'projects',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (options.registries) {\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'registries',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!options.projects && !options.registries) {\n\t\t\t\t\t// Default to listing both\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'projects',\n\t\t\t\t\t});\n\t\t\t\t\tawait deployListCommand({\n\t\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t\t\tresource: 'registries',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Failed to list resources',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Login command\nprogram\n\t.command('login')\n\t.description('Authenticate with a deployment service')\n\t.option('--service <service>', 'Service to login to (dokploy)', 'dokploy')\n\t.option('--token <token>', 'API token (will prompt if not provided)')\n\t.option('--endpoint <url>', 'Service endpoint URL')\n\t.action(\n\t\tasync (options: { service: string; token?: string; endpoint?: string }) => {\n\t\t\ttry {\n\t\t\t\tconst globalOptions = program.opts();\n\t\t\t\tif (globalOptions.cwd) {\n\t\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t\t}\n\n\t\t\t\tif (options.service !== 'dokploy') {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Unknown service: ${options.service}. Supported: dokploy`,\n\t\t\t\t\t);\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\n\t\t\t\tawait loginCommand({\n\t\t\t\t\tservice: options.service as 'dokploy',\n\t\t\t\t\ttoken: options.token,\n\t\t\t\t\tendpoint: options.endpoint,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\terror instanceof Error ? error.message : 'Failed to login',\n\t\t\t\t);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t},\n\t);\n\n// Logout command\nprogram\n\t.command('logout')\n\t.description('Remove stored credentials')\n\t.option(\n\t\t'--service <service>',\n\t\t'Service to logout from (dokploy, all)',\n\t\t'dokploy',\n\t)\n\t.action(async (options: { service: string }) => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\n\t\t\tawait logoutCommand({\n\t\t\t\tservice: options.service as 'dokploy' | 'all',\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\terror instanceof Error ? error.message : 'Failed to logout',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\n// Whoami command\nprogram\n\t.command('whoami')\n\t.description('Show current authentication status')\n\t.action(async () => {\n\t\ttry {\n\t\t\tconst globalOptions = program.opts();\n\t\t\tif (globalOptions.cwd) {\n\t\t\t\tprocess.chdir(globalOptions.cwd);\n\t\t\t}\n\n\t\t\tawait whoamiCommand();\n\t\t} catch (error) {\n\t\t\tconsole.error(\n\t\t\t\terror instanceof Error ? error.message : 'Failed to get status',\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram.parse();\n"],"mappings":"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"}
|