laracrew 0.2.2 → 0.3.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/program.ts","../src/core/config/errors.ts","../src/core/config/load.ts","../src/core/config/paths.ts","../src/core/config/schema.ts","../src/cli/render/colors.ts","../src/cli/commands/doctor.ts","../src/core/health/probes.ts","../src/core/process/spawn.ts","../src/core/events/bus.ts","../src/core/config/resolve.ts","../src/core/laravel/env.ts","../src/core/config/interpolate.ts","../src/core/process/supervisor.ts","../src/core/events/types.ts","../src/core/logs/file-sink.ts","../src/core/logs/ring-buffer.ts","../src/core/logs/sanitize.ts","../src/core/process/stop.ts","../src/core/process/managed-process.ts","../src/cli/render/output.ts","../src/cli/render/plain.ts","../src/tui/model.ts","../src/tui/keys.ts","../src/tui/theme.ts","../src/tui/screen.ts","../src/tui/terminal.ts","../src/tui/app.ts","../src/cli/commands/up.ts","../src/cli/commands/init.ts","../src/cli/commands/templates.ts","../src/cli/commands/link.ts","../src/cli/commands/logs.ts","../src/core/logs/read.ts","../src/cli/commands/ls.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { ConfigError } from '../core/config/errors.js';\nimport { listStacks } from '../core/config/load.js';\nimport { loadGlobalConfig } from '../core/config/load.js';\nimport { paint } from './render/colors.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { initCommand } from './commands/init.js';\nimport { linkCommand, unlinkCommandAction } from './commands/link.js';\nimport { logsCommand } from './commands/logs.js';\nimport { lsCommand } from './commands/ls.js';\nimport { upCommand } from './commands/up.js';\n\n/** Replaced by tsup at build time; only the `tsx` dev path falls through to the lookup below. */\ndeclare const __LARACREW_VERSION__: string | undefined;\n\n/** Walks up from this file to laracrew's own package.json — the depth differs dev vs bundled. */\nconst versionFromPackageJson = (): string => {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let up = 0; up < 5; up += 1) {\n try {\n const pkg = JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf8')) as {\n name?: string;\n version?: string;\n };\n if (pkg.name === 'laracrew' && pkg.version) return pkg.version;\n } catch {\n /* keep walking */\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return '0.0.0-unknown';\n};\n\nexport const VERSION =\n typeof __LARACREW_VERSION__ === 'string' ? __LARACREW_VERSION__ : versionFromPackageJson();\n\n/**\n * Picks the stack when the user did not name one: the configured default, else the only\n * stack that exists, else an error that lists the options.\n */\nexport const resolveStackName = (explicit: string | undefined, env: NodeJS.ProcessEnv = process.env): string => {\n if (explicit) return explicit;\n\n const configured = loadGlobalConfig(env).defaultStack;\n if (configured) return configured;\n\n const stacks = listStacks(env);\n if (stacks.length === 1) return stacks[0]!;\n if (stacks.length === 0) {\n throw new ConfigError('no stacks defined yet — run `laracrew init`');\n }\n throw new ConfigError(\n `several stacks exist, so name one: ${stacks.join(', ')}`,\n { details: ['or set `defaultStack:` in ~/.laracrew/config.yaml'] },\n );\n};\n\nconst collect = (value: string, previous: string[]): string[] => [...previous, value];\n\nexport const buildProgram = (): Command => {\n const program = new Command();\n\n program\n .name('laracrew')\n .description('Boot and supervise all the long-running processes of your projects with one command.')\n .version(VERSION, '-v, --version')\n .showHelpAfterError();\n\n program\n .command('init')\n .description('create ~/.laracrew')\n .option('--examples', 'also write a runnable demo stack and a two-project template')\n .action((options: { examples?: boolean }) => {\n initCommand({ examples: options.examples ?? false });\n });\n\n program\n .command('ls')\n .alias('list')\n .description('list stacks, projects and tasks')\n .option('--json', 'machine-readable output')\n .action((options: { json?: boolean }) => {\n process.exitCode = lsCommand(process.env, options.json ?? false);\n });\n\n program\n .command('up')\n .argument('[stack]', 'stack to boot')\n .description('boot a stack and supervise it')\n .option('--only <selector>', 'only these services or groups (repeatable, comma-separated)', collect, [])\n .option('--except <selector>', 'skip these services or groups (repeatable, comma-separated)', collect, [])\n .option('--profile <name>', 'apply a profile from the stack')\n .option('--plain', 'prefixed interleaved logs instead of the full-screen view')\n .option('--json', 'newline-delimited JSON events')\n .action(async (stack: string | undefined, options: Record<string, unknown>) => {\n const name = resolveStackName(stack);\n process.exitCode = await upCommand(name, {\n only: options.only as string[],\n except: options.except as string[],\n profile: options.profile as string | undefined,\n plain: options.plain as boolean | undefined,\n json: options.json as boolean | undefined,\n });\n });\n\n program\n .command('logs')\n .argument('[service]', 'service to read; omit for every service in the stack')\n .description('read what a stack wrote to disk, after the fact')\n .option('--stack <name>', 'which stack (defaults the same way `up` does)')\n .option('-n, --lines <count>', 'how many lines to show', (value: string) => Number(value), 200)\n .option('-f, --follow', 'keep printing new lines as they arrive')\n .option('--since <window>', 'only lines newer than this: 10m, 2h, 1d, or a date')\n .option('--all', 'merge every service in the stack')\n .option('--list', 'list the services that have a log file')\n .action(async (service: string | undefined, options: Record<string, unknown>) => {\n process.exitCode = await logsCommand(service, {\n stack: resolveStackName(options.stack as string | undefined),\n lines: options.lines as number,\n follow: options.follow as boolean | undefined,\n since: options.since as string | undefined,\n all: options.all as boolean | undefined,\n list: options.list as boolean | undefined,\n });\n });\n\n program\n .command('link')\n .argument('[stack]', 'stack to give its own global command')\n .description('install a global command that boots one stack')\n .option('--as <name>', 'name the command something other than the stack name')\n .option('--all', 'link every stack that declares `command:` in its stack.yaml')\n .option('--dir <path>', 'install into this directory instead of the npm global bin')\n .option('--force', 'overwrite a name that is taken or reserved')\n .action((stack: string | undefined, options: Record<string, unknown>) => {\n process.exitCode = linkCommand(\n stack,\n {\n as: options.as as string | undefined,\n all: options.all as boolean | undefined,\n dir: options.dir as string | undefined,\n force: options.force as boolean | undefined,\n },\n process.env,\n );\n });\n\n program\n .command('unlink')\n .argument('<name>', 'the global command to remove')\n .description('remove a global command laracrew installed')\n .action((name: string) => {\n process.exitCode = unlinkCommandAction(name);\n });\n\n program\n .command('doctor')\n .argument('[stack]', 'stack to check')\n .description('check a stack before booting it')\n .action(async (stack: string | undefined) => {\n process.exitCode = await doctorCommand(resolveStackName(stack));\n });\n\n return program;\n};\n\nexport const run = async (argv: string[] = process.argv): Promise<void> => {\n try {\n await buildProgram().parseAsync(argv);\n } catch (error) {\n if (error instanceof ConfigError) {\n console.error(`${paint('red', 'config error')}\\n${error.format()}`);\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n};\n","import type { ZodError, ZodIssue } from 'zod';\n\n/**\n * Config problems are the most common failure a user hits, so they get a real error type\n * with file/line context and a suggestion — never a raw zod issue tree.\n */\nexport class ConfigError extends Error {\n readonly file?: string;\n readonly details: string[];\n\n constructor(message: string, opts: { file?: string; details?: string[]; cause?: unknown } = {}) {\n super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined);\n this.name = 'ConfigError';\n this.file = opts.file;\n this.details = opts.details ?? [];\n }\n\n /** Multi-line, terminal-ready rendering. */\n format(): string {\n const head = this.file ? `${this.file}\\n ${this.message}` : this.message;\n if (this.details.length === 0) return head;\n return `${head}\\n${this.details.map((d) => ` - ${d}`).join('\\n')}`;\n }\n}\n\nconst levenshtein = (a: string, b: string): number => {\n const rows = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array<number>(b.length).fill(0)]);\n for (let j = 0; j <= b.length; j++) rows[0]![j] = j;\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n rows[i]![j] = Math.min(rows[i - 1]![j]! + 1, rows[i]![j - 1]! + 1, rows[i - 1]![j - 1]! + cost);\n }\n }\n return rows[a.length]![b.length]!;\n};\n\n/** \"watchs\" -> \"watch\". Returns undefined when nothing is close enough to be helpful. */\nexport const didYouMean = (input: string, candidates: readonly string[]): string | undefined => {\n let best: { word: string; distance: number } | undefined;\n for (const candidate of candidates) {\n const distance = levenshtein(input.toLowerCase(), candidate.toLowerCase());\n if (!best || distance < best.distance) best = { word: candidate, distance };\n }\n if (!best) return undefined;\n const threshold = Math.max(2, Math.floor(input.length / 3));\n return best.distance <= threshold ? best.word : undefined;\n};\n\nconst pathOf = (issue: ZodIssue): string =>\n issue.path.length === 0\n ? '(root)'\n : issue.path\n .map((segment, index) => (typeof segment === 'number' ? `[${segment}]` : index === 0 ? segment : `.${segment}`))\n .join('');\n\n/** Turns a ZodError into one readable line per problem, with spelling suggestions. */\nexport const formatZodIssues = (error: ZodError, knownKeys: readonly string[] = []): string[] =>\n error.issues.map((issue) => {\n if (issue.code === 'unrecognized_keys') {\n return issue.keys\n .map((key) => {\n const suggestion = didYouMean(key, knownKeys);\n const at = pathOf(issue);\n const where = at === '(root)' ? '' : ` at ${at}`;\n return suggestion\n ? `unknown field \"${key}\"${where} — did you mean \"${suggestion}\"?`\n : `unknown field \"${key}\"${where}`;\n })\n .join('; ');\n }\n return `${pathOf(issue)}: ${issue.message}`;\n });\n\n/** Every field name the schema knows about, used to power \"did you mean\". */\nexport const KNOWN_SERVICE_KEYS = [\n 'name',\n 'project',\n 'cmd',\n 'cwd',\n 'env',\n 'groups',\n 'needs',\n 'ready',\n 'restart',\n 'backoff',\n 'stop',\n 'watch',\n 'metrics',\n 'url',\n 'external',\n 'autostart',\n 'enabled',\n 'color',\n] as const;\n\nexport const KNOWN_STACK_KEYS = [\n 'name',\n 'description',\n 'command',\n 'use',\n 'projects',\n 'defaults',\n 'services',\n 'profiles',\n 'hooks',\n] as const;\n\nexport const ALL_KNOWN_KEYS = [...KNOWN_SERVICE_KEYS, ...KNOWN_STACK_KEYS] as const;\n","import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport type { z } from 'zod';\nimport { ConfigError, formatZodIssues, ALL_KNOWN_KEYS } from './errors.js';\nimport { paths, stackDir, stackFile, taskFile } from './paths.js';\nimport {\n globalConfigSchema,\n projectsFileSchema,\n stackSchema,\n taskSchema,\n type GlobalConfig,\n type ProjectConfig,\n type StackConfig,\n type TaskConfig,\n} from './schema.js';\n\n/** Parses YAML, converting a syntax error into a ConfigError that names the line. */\nexport const parseYaml = (source: string, file: string): unknown => {\n try {\n return YAML.parse(source, { prettyErrors: true }) ?? {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ConfigError(`invalid YAML: ${message}`, { file, cause: error });\n }\n};\n\nexport const readYamlFile = (file: string): unknown => {\n let source: string;\n try {\n source = readFileSync(file, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ConfigError(`file not found`, { file, cause: error });\n }\n throw error;\n }\n return parseYaml(source, file);\n};\n\n// Generic over the schema, not its output: `.default()` makes input and output differ.\nconst validate = <S extends z.ZodTypeAny>(schema: S, value: unknown, file: string): z.infer<S> => {\n const result = schema.safeParse(value);\n if (result.success) return result.data;\n throw new ConfigError('this file does not match the laracrew schema', {\n file,\n details: formatZodIssues(result.error, ALL_KNOWN_KEYS),\n });\n};\n\n/** ~/.laracrew/config.yaml — absent means \"all defaults\". */\nexport const loadGlobalConfig = (env: NodeJS.ProcessEnv = process.env): GlobalConfig => {\n const file = paths(env).configFile;\n if (!existsSync(file)) return globalConfigSchema.parse({});\n return validate(globalConfigSchema, readYamlFile(file), file);\n};\n\n/** ~/.laracrew/projects.yaml — absent means \"no shared projects\". */\nexport const loadSharedProjects = (env: NodeJS.ProcessEnv = process.env): Record<string, ProjectConfig> => {\n const file = paths(env).projectsFile;\n if (!existsSync(file)) return {};\n return validate(projectsFileSchema, readYamlFile(file), file).projects;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * Merges a stack's optional `services/*.yaml` fragments into the main document.\n * Each fragment is either a list of services or `{ services: [...] }`.\n */\nconst mergeServiceFragments = (document: unknown, dir: string): unknown => {\n const servicesDir = path.join(dir, 'services');\n if (!existsSync(servicesDir) || !statSync(servicesDir).isDirectory()) return document;\n if (!isRecord(document)) return document;\n\n const extra: unknown[] = [];\n for (const entry of readdirSync(servicesDir).sort()) {\n if (!/\\.ya?ml$/i.test(entry)) continue;\n const file = path.join(servicesDir, entry);\n const fragment = readYamlFile(file);\n if (Array.isArray(fragment)) {\n extra.push(...fragment);\n } else if (isRecord(fragment) && Array.isArray(fragment.services)) {\n extra.push(...fragment.services);\n } else {\n throw new ConfigError('a service fragment must be a list of services, or { services: [...] }', { file });\n }\n }\n\n if (extra.length === 0) return document;\n const existing = Array.isArray(document.services) ? document.services : [];\n return { ...document, services: [...existing, ...extra] };\n};\n\nexport interface LoadedStack {\n config: StackConfig;\n file: string;\n dir: string;\n}\n\n/** Loads ~/.laracrew/stacks/<name>/stack.yaml plus its fragments. */\nexport const loadStack = (name: string, env: NodeJS.ProcessEnv = process.env): LoadedStack => {\n const dir = stackDir(name, env);\n const file = stackFile(name, env);\n\n if (!existsSync(file)) {\n const available = listStacks(env);\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}.` : ' Run `laracrew init` first.';\n throw new ConfigError(`no stack named \"${name}\".${hint}`, { file });\n }\n\n const document = mergeServiceFragments(readYamlFile(file), dir);\n const config = validate(stackSchema, document, file);\n\n if (config.name !== name) {\n throw new ConfigError(\n `stack folder is \"${name}\" but \\`name:\\` says \"${config.name}\" — they must match`,\n { file },\n );\n }\n\n return { config, file, dir };\n};\n\nexport const listStacks = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const dir = paths(env).stacksDir;\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && existsSync(path.join(dir, entry.name, 'stack.yaml')))\n .map((entry) => entry.name)\n .sort();\n};\n\nexport const listTasks = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const dir = paths(env).tasksDir;\n if (!existsSync(dir)) return [];\n return readdirSync(dir)\n .filter((entry) => /\\.ya?ml$/i.test(entry))\n .map((entry) => entry.replace(/\\.ya?ml$/i, ''))\n .sort();\n};\n\nexport const loadTask = (name: string, env: NodeJS.ProcessEnv = process.env): { config: TaskConfig; file: string } => {\n const file = taskFile(name, env);\n if (!existsSync(file)) {\n const available = listTasks(env);\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}.` : '';\n throw new ConfigError(`no task named \"${name}\".${hint}`, { file });\n }\n return { config: validate(taskSchema, readYamlFile(file), file), file };\n};\n","import { homedir } from 'node:os';\nimport path from 'node:path';\n\n/**\n * Everything laracrew owns lives under one root. `LARACREW_HOME` overrides it,\n * which is what the test suite uses to stay out of the real home directory.\n */\nexport const home = (env: NodeJS.ProcessEnv = process.env): string =>\n env.LARACREW_HOME ? path.resolve(env.LARACREW_HOME) : path.join(homedir(), '.laracrew');\n\nexport interface HomePaths {\n root: string;\n configFile: string;\n projectsFile: string;\n stacksDir: string;\n tasksDir: string;\n fragmentsDir: string;\n logsDir: string;\n runDir: string;\n}\n\nexport const paths = (env: NodeJS.ProcessEnv = process.env): HomePaths => {\n const root = home(env);\n return {\n root,\n configFile: path.join(root, 'config.yaml'),\n projectsFile: path.join(root, 'projects.yaml'),\n stacksDir: path.join(root, 'stacks'),\n tasksDir: path.join(root, 'tasks'),\n fragmentsDir: path.join(root, 'fragments'),\n logsDir: path.join(root, 'logs'),\n runDir: path.join(root, 'run'),\n };\n};\n\nexport const stackDir = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).stacksDir, name);\n\nexport const stackFile = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(stackDir(name, env), 'stack.yaml');\n\nexport const taskFile = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).tasksDir, `${name}.yaml`);\n","import { z } from 'zod';\n\n/**\n * The on-disk shape of ~/.laracrew files. Everything here is what the *user* writes;\n * `resolve.ts` turns it into the fully-defaulted runtime shape the supervisor consumes.\n */\n\nexport const restartPolicy = z.enum(['never', 'on-failure', 'always']);\nexport type RestartPolicy = z.infer<typeof restartPolicy>;\n\nexport const watchStrategy = z.enum(['restart', 'artisan-queue-restart', 'none']);\nexport type WatchStrategy = z.infer<typeof watchStrategy>;\n\nexport const readyProbeSchema = z\n .object({\n tcp: z.string().optional(), // \"127.0.0.1:6379\"\n http: z.string().url().optional(),\n logMatch: z.string().optional(), // regex source\n delayMs: z.number().int().nonnegative().optional(),\n timeoutMs: z.number().int().positive().default(30_000),\n intervalMs: z.number().int().positive().default(250),\n })\n .strict()\n .refine((p) => Boolean(p.tcp ?? p.http ?? p.logMatch ?? p.delayMs !== undefined), {\n message: 'a `ready` probe needs one of: tcp, http, logMatch, delayMs',\n });\nexport type ReadyProbe = z.infer<typeof readyProbeSchema>;\n\nexport const backoffSchema = z\n .object({\n initialMs: z.number().int().positive().default(1_000),\n maxMs: z.number().int().positive().default(30_000),\n factor: z.number().positive().default(2),\n maxRestarts: z.number().int().nonnegative().default(10),\n /** Stay up this long and the attempt counter resets, so a slow leak can't exhaust it. */\n resetAfterMs: z.number().int().positive().default(60_000),\n })\n .strict();\nexport type Backoff = z.infer<typeof backoffSchema>;\n\n/** `cmd` accepts a shell line or an argv array. The array form skips shell parsing. */\nexport const commandSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]);\n\nexport const stopPolicySchema = z\n .object({\n /**\n * Step 1 of the stop ladder: any command that asks the process to finish what it is\n * holding and exit by itself — `celery control shutdown`, `docker compose stop`, a\n * drain script. Runs in the service's cwd; laracrew waits `graceMs` for the exit.\n */\n exec: commandSchema.optional(),\n /** Sugar for `exec` on a Laravel project: runs `<php> artisan <this>` from its root. */\n artisan: z.string().optional(),\n signal: z.string().default('SIGTERM'),\n graceMs: z.number().int().positive().default(10_000),\n })\n .strict();\nexport type StopPolicy = z.infer<typeof stopPolicySchema>;\n\nexport const watchSchema = z\n .object({\n paths: z.array(z.string()).min(1),\n ignore: z.array(z.string()).default([]),\n strategy: watchStrategy.default('restart'),\n debounceMs: z.number().int().nonnegative().default(800),\n })\n .strict();\nexport type WatchConfig = z.infer<typeof watchSchema>;\n\nexport const metricsSchema = z\n .object({\n queues: z.array(z.string()).default([]),\n streams: z\n .array(z.object({ key: z.string(), group: z.string() }).strict())\n .default([]),\n })\n .strict();\nexport type MetricsConfig = z.infer<typeof metricsSchema>;\n\nexport const serviceSchema = z\n .object({\n name: z.string().min(1),\n project: z.string().optional(),\n cmd: commandSchema.optional(),\n cwd: z.string().optional(),\n env: z.record(z.string()).default({}),\n groups: z.array(z.string()).default([]),\n needs: z.array(z.string()).default([]),\n ready: readyProbeSchema.optional(),\n restart: restartPolicy.optional(),\n backoff: backoffSchema.partial().optional(),\n stop: stopPolicySchema.partial().optional(),\n watch: watchSchema.optional(),\n metrics: metricsSchema.optional(),\n url: z.string().optional(),\n /** Health-checked but never spawned: Redis, MySQL, a Docker service. */\n external: z.boolean().default(false),\n /** false = defined but not launched; press `s` in the TUI to start it when you need it. */\n autostart: z.boolean().default(true),\n enabled: z.boolean().default(true),\n color: z.string().optional(),\n })\n .strict()\n .refine((s) => s.external || s.cmd !== undefined, {\n message: 'a service needs a `cmd` unless it is marked `external: true`',\n });\nexport type ServiceConfig = z.infer<typeof serviceSchema>;\n\nexport const projectSchema = z\n .object({\n path: z.string().min(1),\n php: z.string().default('php'),\n envFile: z.string().default('.env'),\n color: z.string().optional(),\n })\n .strict();\nexport type ProjectConfig = z.infer<typeof projectSchema>;\n\nexport const projectsFileSchema = z\n .object({ projects: z.record(projectSchema).default({}) })\n .strict();\n\nexport const profileSchema = z\n .object({\n only: z.array(z.string()).default([]),\n except: z.array(z.string()).default([]),\n })\n .strict();\nexport type ProfileConfig = z.infer<typeof profileSchema>;\n\nexport const stackDefaultsSchema = z\n .object({\n restart: restartPolicy.default('on-failure'),\n backoff: backoffSchema.partial().default({}),\n stop: stopPolicySchema.partial().default({}),\n logs: z\n .object({\n /** Lines kept in memory per service, for the live log view. */\n maxLines: z.number().int().positive().default(5_000),\n /**\n * On by default: an in-memory buffer holds minutes, and losing the exception you\n * just watched scroll past is the fastest way to stop trusting the tool.\n */\n toFile: z.boolean().default(true),\n /** Rotate a service's log once it passes this size. */\n maxFileBytes: z.number().int().positive().default(5_000_000),\n /** How many rotated files to keep beside the current one. */\n keepFiles: z.number().int().nonnegative().default(1),\n })\n .strict()\n .default({}),\n })\n .strict();\nexport type StackDefaults = z.infer<typeof stackDefaultsSchema>;\n\nexport const stackSchema = z\n .object({\n name: z.string().min(1),\n description: z.string().optional(),\n /** The global command name `laracrew link` installs for this stack. Defaults to `name`. */\n command: z.string().min(1).optional(),\n /** Project keys pulled in from ~/.laracrew/projects.yaml. */\n use: z.array(z.string()).default([]),\n /** Projects declared inline; merged over the shared ones. */\n projects: z.record(projectSchema).default({}),\n defaults: stackDefaultsSchema.default({}),\n services: z.array(serviceSchema).min(1),\n profiles: z.record(profileSchema).default({}),\n hooks: z\n .object({ preUp: z.string().nullish(), postDown: z.string().nullish() })\n .strict()\n .default({}),\n })\n .strict();\nexport type StackConfig = z.infer<typeof stackSchema>;\n\nexport const globalConfigSchema = z\n .object({\n theme: z.enum(['auto', 'dark', 'light', 'mono', 'high-contrast']).default('auto'),\n editor: z.string().optional(),\n defaultStack: z.string().optional(),\n metricsIntervalMs: z.number().int().positive().default(2_000),\n })\n .strict();\nexport type GlobalConfig = z.infer<typeof globalConfigSchema>;\n\nexport const taskStepSchema: z.ZodType<TaskStep, z.ZodTypeDef, unknown> = z.lazy(() =>\n z.union([\n z\n .object({\n project: z.string().optional(),\n cwd: z.string().optional(),\n cmd: commandSchema,\n continueOnError: z.boolean().default(false),\n })\n .strict(),\n z.object({ parallel: z.array(taskStepSchema).min(1) }).strict(),\n ]),\n);\nexport type TaskStep =\n | { project?: string; cwd?: string; cmd: string | string[]; continueOnError: boolean }\n | { parallel: TaskStep[] };\n\nexport const taskSchema = z\n .object({\n name: z.string().min(1),\n description: z.string().optional(),\n pauseServices: z.array(z.string()).default([]),\n steps: z.array(taskStepSchema).min(1),\n })\n .strict();\nexport type TaskConfig = z.infer<typeof taskSchema>;\n","/**\n * A 40-line colour helper instead of a dependency. Honours NO_COLOR and FORCE_COLOR,\n * because laracrew output is piped into other tools as often as it is read.\n */\n\nconst CODES = {\n reset: 0,\n bold: 1,\n dim: 2,\n italic: 3,\n underline: 4,\n black: 30,\n red: 31,\n green: 32,\n yellow: 33,\n blue: 34,\n magenta: 35,\n cyan: 36,\n white: 37,\n gray: 90,\n} as const;\n\nexport type ColorName = keyof typeof CODES;\n\nexport const supportsColor = (stream: { isTTY?: boolean } = process.stdout, env = process.env): boolean => {\n if (env.NO_COLOR !== undefined && env.NO_COLOR !== '') return false;\n if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== '0') return true;\n if (env.TERM === 'dumb') return false;\n return Boolean(stream.isTTY);\n};\n\nexport interface Painter {\n (name: ColorName, text: string): string;\n readonly enabled: boolean;\n}\n\nexport const createPainter = (enabled: boolean): Painter => {\n const paint = ((name: ColorName, text: string): string =>\n enabled ? `\u001b[${CODES[name]}m${text}\u001b[${CODES.reset}m` : text) as {\n (name: ColorName, text: string): string;\n enabled: boolean;\n };\n paint.enabled = enabled;\n return paint as Painter;\n};\n\n/** The default painter, decided once from the real stdout. */\nexport const paint: Painter = createPainter(supportsColor());\n\n/** Falls back to cyan for a colour name the user invented in their config. */\nexport const asColorName = (value: string | undefined): ColorName =>\n value && value in CODES ? (value as ColorName) : 'cyan';\n\n/** Visible width, ignoring the ANSI we may have added. */\nexport const stripAnsi = (text: string): string => text.replace(/\u001b\\[[0-9;]*m/g, '');\n\nexport const padEnd = (text: string, width: number): string => {\n const visible = stripAnsi(text).length;\n return visible >= width ? text : text + ' '.repeat(width - visible);\n};\n","import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { ConfigError } from '../../core/config/errors.js';\nimport type { ResolvedProject, ResolvedService, ResolvedStack } from '../../core/config/resolve.js';\nimport { describeProbe, httpProbe, isPortFree, tcpProbe } from '../../core/health/probes.js';\nimport { runOnce } from '../../core/process/spawn.js';\nimport { paint } from '../render/colors.js';\nimport { prepareStack } from './up.js';\n\nexport interface Finding {\n level: 'ok' | 'warn' | 'error';\n message: string;\n hint?: string;\n}\n\nconst PORT_IN_COMMAND = /--port[= ](\\d{2,5})/g;\n\n/** The command line a service will actually run, in one form the pattern checks can match. */\nconst commandLine = (service: ResolvedService): string => {\n if (!service.command) return '';\n return service.command.kind === 'shell'\n ? service.command.line\n : [service.command.file, ...service.command.args].join(' ');\n};\n\n/** `php`, `php8.2`, `C:\\php\\php.exe` — anywhere in the line, not just at the front. */\nconst PHP_BINARY = /(^|[\\\\/\\s\"'])php[\\d.]*(\\.exe)?(\\s|$)/i;\n\n/**\n * Which projects are PHP projects at all.\n *\n * laracrew supervises any process, so a stack can be pure Node, Python or Go. Running\n * `php --version` for those projects is noise on a machine that has PHP and a blocking\n * error on one that does not — so every Laravel-specific check is gated on this.\n */\nconst phpProjects = (stack: ResolvedStack): Set<string> => {\n const keys = new Set<string>();\n for (const service of stack.services) {\n const key = service.project?.key;\n if (!key) continue;\n const line = commandLine(service);\n const php = stack.projects[key]?.php;\n // `stop.artisan` runs `<php> artisan ...`, so it needs PHP whatever the service itself is.\n if (service.stop.artisan || PHP_BINARY.test(line) || (php !== undefined && line.startsWith(php))) {\n keys.add(key);\n }\n }\n return keys;\n};\n\n/** Env keys whose value being \"redis\" means the project talks to Redis. */\nconst REDIS_DRIVER_KEYS = [\n 'QUEUE_CONNECTION',\n 'CACHE_STORE',\n 'CACHE_DRIVER',\n 'SESSION_DRIVER',\n 'BROADCAST_CONNECTION',\n 'BROADCAST_DRIVER',\n];\n\n/**\n * Which projects talk to Redis — from their own env, or from what their services run.\n * Without this every project defaults to 127.0.0.1:6379, so two Node projects with no\n * `.env` would be reported as sharing a Redis namespace neither of them uses.\n */\nconst redisProjects = (stack: ResolvedStack): Set<string> => {\n const keys = new Set<string>();\n\n for (const [key, project] of Object.entries(stack.projects)) {\n const declared = Object.keys(project.env).some((name) => name.startsWith('REDIS_'));\n const driver = REDIS_DRIVER_KEYS.some((name) => project.env[name]?.toLowerCase() === 'redis');\n if (declared || driver) keys.add(key);\n }\n\n for (const service of stack.services) {\n const key = service.project?.key;\n if (!key) continue;\n // Horizon is Redis-only, and declared metrics are read straight off Redis.\n if (service.metrics || /\\b(redis|horizon)\\b/i.test(commandLine(service))) keys.add(key);\n }\n\n return keys;\n};\n\n/** Ports the stack will try to bind: ${port:N} tokens plus anything passed as --port. */\nexport const declaredPorts = (stack: ResolvedStack): number[] => {\n const ports = new Set<number>(stack.ports);\n for (const service of stack.services) {\n for (const match of commandLine(service).matchAll(PORT_IN_COMMAND)) {\n const port = Number(match[1]);\n if (Number.isInteger(port)) ports.add(port);\n }\n }\n return [...ports].sort((a, b) => a - b);\n};\n\n/** redis://[user:pass@]host:port[/db] — the usual form outside Laravel. */\nconst parseRedisUrl = (url: string): { host: string; port: string } | undefined => {\n try {\n const parsed = new URL(url);\n return parsed.hostname ? { host: parsed.hostname, port: parsed.port || '6379' } : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst redisTargetOf = (project: ResolvedProject): string => {\n const url = project.env.REDIS_URL ? parseRedisUrl(project.env.REDIS_URL) : undefined;\n const host = project.env.REDIS_HOST ?? url?.host ?? '127.0.0.1';\n const port = project.env.REDIS_PORT ?? url?.port ?? '6379';\n return `${host}:${port}`;\n};\n\n/** Laravel's Str::slug($value, '_'). */\nconst slug = (value: string): string =>\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '');\n\n/**\n * The prefix Laravel will actually use. Most projects never set REDIS_PREFIX, and the\n * framework default is derived from APP_NAME — so two apps on one Redis database are usually\n * isolated anyway. Reading only REDIS_PREFIX here would cry wolf on every normal setup.\n */\nexport const redisPrefixOf = (project: ResolvedProject): string =>\n project.env.REDIS_PREFIX ?? `${slug(project.env.APP_NAME ?? 'laravel')}_database_`;\n\n/** Which Redis logical namespace a project writes into — host:port/db + prefix. */\nconst redisNamespaceOf = (project: ResolvedProject): string =>\n `${redisTargetOf(project)}/${project.env.REDIS_DB ?? '0'}#${redisPrefixOf(project)}`;\n\nconst checkProjects = (stack: ResolvedStack, php: Set<string>, redis: Set<string>): Finding[] => {\n const findings: Finding[] = [];\n\n for (const project of Object.values(stack.projects)) {\n if (!existsSync(project.path)) {\n findings.push({ level: 'error', message: `project \"${project.key}\": path does not exist — ${project.path}` });\n continue;\n }\n // Only a project something runs `php` for is expected to have an artisan file.\n if (php.has(project.key) && !existsSync(path.join(project.path, 'artisan'))) {\n findings.push({\n level: 'warn',\n message: `project \"${project.key}\": no \\`artisan\\` file in ${project.path}`,\n hint: 'laracrew will still run the commands, but this does not look like a Laravel root',\n });\n }\n // A Node or Python project with no .env is normal; one whose checks need it is not.\n if (Object.keys(project.env).length === 0 && (php.has(project.key) || redis.has(project.key))) {\n findings.push({\n level: 'warn',\n message: `project \"${project.key}\": ${project.envFile} is missing or empty`,\n hint: 'queue/Redis checks and ${project.env:...} tokens need it',\n });\n }\n }\n\n return findings;\n};\n\n/** The check that pays for this whole command: two apps quietly sharing one Redis namespace. */\nconst checkRedisCollisions = (stack: ResolvedStack, redis: Set<string>): Finding[] => {\n const findings: Finding[] = [];\n // Projects that never touch Redis would otherwise all collide on the synthesized default.\n const projects = Object.values(stack.projects).filter((project) => redis.has(project.key));\n\n const byNamespace = new Map<string, ResolvedProject[]>();\n for (const project of projects) {\n const namespace = redisNamespaceOf(project);\n byNamespace.set(namespace, [...(byNamespace.get(namespace) ?? []), project]);\n }\n\n for (const [namespace, sharing] of byNamespace) {\n if (sharing.length < 2) continue;\n\n const queuesByProject = new Map<string, Set<string>>();\n const streamsByProject = new Map<string, Set<string>>();\n for (const service of stack.services) {\n if (!service.project || !service.metrics) continue;\n const key = service.project.key;\n for (const queue of service.metrics.queues) {\n queuesByProject.set(key, (queuesByProject.get(key) ?? new Set()).add(queue));\n }\n for (const stream of service.metrics.streams) {\n streamsByProject.set(key, (streamsByProject.get(key) ?? new Set()).add(`${stream.key}/${stream.group}`));\n }\n }\n\n const names = sharing.map((project) => project.key);\n const overlap = (map: Map<string, Set<string>>): string[] => {\n const counts = new Map<string, number>();\n for (const key of names) {\n for (const value of map.get(key) ?? []) counts.set(value, (counts.get(value) ?? 0) + 1);\n }\n return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value);\n };\n\n const sharedQueues = overlap(queuesByProject);\n const sharedStreams = overlap(streamsByProject);\n\n if (sharedQueues.length > 0) {\n findings.push({\n level: 'error',\n message: `${names.join(' and ')} share Redis ${namespace} AND queue(s): ${sharedQueues.join(', ')}`,\n hint: \"each project's workers will steal the other's jobs — set a different REDIS_DB or REDIS_PREFIX\",\n });\n }\n if (sharedStreams.length > 0) {\n findings.push({\n level: 'error',\n message: `${names.join(' and ')} share Redis ${namespace} AND stream/group: ${sharedStreams.join(', ')}`,\n hint: 'two consumers in one group split the entries between them — give each project its own group name',\n });\n }\n if (sharedQueues.length === 0 && sharedStreams.length === 0) {\n findings.push({\n level: 'warn',\n message: `${names.join(' and ')} share Redis ${namespace}`,\n hint: 'no queue or stream overlap declared, but cache and session keys can still collide',\n });\n }\n }\n\n // Same server and database, different prefix: worth stating plainly, because it is the\n // thing standing between two projects' queues.\n const byServer = new Map<string, ResolvedProject[]>();\n for (const project of projects) {\n const server = `${redisTargetOf(project)}/${project.env.REDIS_DB ?? '0'}`;\n byServer.set(server, [...(byServer.get(server) ?? []), project]);\n }\n for (const [server, sharing] of byServer) {\n if (sharing.length < 2) continue;\n const prefixes = new Set(sharing.map(redisPrefixOf));\n if (prefixes.size === sharing.length) {\n findings.push({\n level: 'ok',\n message: `${sharing.map((p) => p.key).join(' and ')} share Redis ${server} but are isolated by prefix (${[...prefixes].join(', ')})`,\n });\n }\n }\n\n return findings;\n};\n\nconst checkQueueConnections = (stack: ResolvedStack): Finding[] => {\n const findings: Finding[] = [];\n const workerProjects = new Set(\n stack.services\n .filter((service) => {\n // A service you start by hand is a deliberate choice, not a misconfiguration.\n if (!service.autostart) return false;\n return /\\b(queue:work|queue:listen|horizon)\\b/.test(commandLine(service));\n })\n .map((service) => service.project?.key)\n .filter((key): key is string => Boolean(key)),\n );\n\n for (const key of workerProjects) {\n const project = stack.projects[key];\n if (!project) continue;\n const connection = project.env.QUEUE_CONNECTION;\n if (connection === undefined) continue;\n if (connection === 'sync') {\n findings.push({\n level: 'error',\n message: `project \"${key}\" runs a queue worker but QUEUE_CONNECTION=sync`,\n hint: 'jobs run inline on dispatch, so the worker will sit idle forever — set it to redis or database',\n });\n }\n }\n\n return findings;\n};\n\n/** Only for projects something actually runs PHP for — a Node or Python stack needs none. */\nconst checkPhp = async (stack: ResolvedStack, php: Set<string>): Promise<Finding[]> => {\n const binaries = new Set(\n Object.values(stack.projects)\n .filter((project) => php.has(project.key))\n .map((project) => project.php),\n );\n const findings: Finding[] = [];\n\n for (const binary of binaries) {\n try {\n const result = await runOnce({ kind: 'argv', file: binary, args: ['--version'] }, {\n cwd: process.cwd(),\n timeoutMs: 8_000,\n });\n if (result.code === 0) {\n const version = result.stdout.split('\\n')[0]?.trim() ?? '';\n findings.push({ level: 'ok', message: `php: ${version}` });\n } else {\n findings.push({ level: 'error', message: `\"${binary} --version\" exited with code ${result.code}` });\n }\n } catch {\n findings.push({\n level: 'error',\n message: `cannot run \"${binary}\"`,\n hint: 'put PHP on PATH, or set an absolute path in projects.yaml',\n });\n }\n }\n\n return findings;\n};\n\nconst checkPorts = async (stack: ResolvedStack): Promise<Finding[]> => {\n const findings: Finding[] = [];\n for (const port of declaredPorts(stack)) {\n const free = await isPortFree(port);\n findings.push(\n free\n ? { level: 'ok', message: `port ${port} is free` }\n : {\n level: 'error',\n message: `port ${port} is already in use`,\n hint: 'something else is bound to it — a stale worker from a previous run, most likely',\n },\n );\n }\n return findings;\n};\n\n/**\n * The language-agnostic dependency check: every `external: true` service is something the\n * stack expects to already be running, and it already declares how to test for it.\n */\nconst checkExternalServices = async (stack: ResolvedStack): Promise<Finding[]> => {\n const external = stack.services.filter((service) => service.external && (service.ready?.tcp ?? service.ready?.http));\n\n return Promise.all(\n external.map(async (service): Promise<Finding> => {\n const probe = service.ready!;\n const label = describeProbe(probe);\n const result = probe.http\n ? await httpProbe(probe.http, 2_000)\n : await tcpProbe(probe.tcp!, 2_000);\n\n return result.ok\n ? { level: 'ok', message: `${service.name} is reachable — ${label}` }\n : {\n level: 'warn',\n message: `${service.name} is not reachable — ${label}${result.detail ? ` (${result.detail})` : ''}`,\n hint: 'laracrew never starts an external service; anything that needs it will wait at its gate',\n };\n }),\n );\n};\n\n/** Ports already covered by an external service's own gate, so they are not probed twice. */\nconst externalTcpTargets = (stack: ResolvedStack): Set<string> =>\n new Set(\n stack.services\n .filter((service) => service.external && service.ready?.tcp)\n .map((service) => service.ready!.tcp!),\n );\n\nconst checkRedisReachable = async (stack: ResolvedStack, redis: Set<string>): Promise<Finding[]> => {\n const covered = externalTcpTargets(stack);\n const targets = new Set(\n Object.values(stack.projects)\n .filter((project) => redis.has(project.key))\n .map(redisTargetOf)\n .filter((target) => !covered.has(target)),\n );\n\n const findings: Finding[] = [];\n for (const target of targets) {\n const result = await tcpProbe(target, 2_000);\n findings.push(\n result.ok\n ? { level: 'ok', message: `redis reachable at ${target}` }\n : { level: 'warn', message: `redis not reachable at ${target}${result.detail ? ` (${result.detail})` : ''}` },\n );\n }\n return findings;\n};\n\nexport const runDoctor = async (stackName: string, env: NodeJS.ProcessEnv = process.env): Promise<Finding[]> => {\n let stack: ResolvedStack;\n try {\n stack = prepareStack(stackName, { env });\n } catch (error) {\n if (error instanceof ConfigError) return [{ level: 'error', message: error.format() }];\n throw error;\n }\n\n // Classified once: every Laravel-specific check below is gated on these, so a stack with\n // no PHP in it gets no PHP findings and a stack with no Redis gets no Redis findings.\n const php = phpProjects(stack);\n const redis = redisProjects(stack);\n\n const findings: Finding[] = [\n { level: 'ok', message: `stack \"${stack.name}\" is valid — ${stack.services.length} services` },\n ...checkProjects(stack, php, redis),\n ...checkQueueConnections(stack),\n ...checkRedisCollisions(stack, redis),\n ];\n\n const async = await Promise.all([\n checkPhp(stack, php),\n checkPorts(stack),\n checkExternalServices(stack),\n checkRedisReachable(stack, redis),\n ]);\n return [...findings, ...async.flat()];\n};\n\nexport const doctorCommand = async (stackName: string, env: NodeJS.ProcessEnv = process.env): Promise<number> => {\n const findings = await runDoctor(stackName, env);\n\n const glyph = { ok: paint('green', '✔'), warn: paint('yellow', '▲'), error: paint('red', '✖') };\n for (const finding of findings) {\n console.log(`${glyph[finding.level]} ${finding.message}`);\n if (finding.hint) console.log(` ${paint('gray', finding.hint)}`);\n }\n\n const errors = findings.filter((finding) => finding.level === 'error').length;\n const warnings = findings.filter((finding) => finding.level === 'warn').length;\n\n console.log(\n `\\n${errors === 0 ? paint('green', 'no blocking problems') : paint('red', `${errors} problem(s)`)}` +\n (warnings > 0 ? paint('yellow', `, ${warnings} warning(s)`) : ''),\n );\n\n return errors > 0 ? 1 : 0;\n};\n","import net from 'node:net';\nimport type { ReadyProbe } from '../config/schema.js';\n\nexport interface ProbeResult {\n ok: boolean;\n detail?: string;\n}\n\nexport const tcpProbe = (target: string, timeoutMs = 2_000): Promise<ProbeResult> =>\n new Promise((resolve) => {\n const lastColon = target.lastIndexOf(':');\n const host = lastColon === -1 ? '127.0.0.1' : target.slice(0, lastColon) || '127.0.0.1';\n const port = Number(lastColon === -1 ? target : target.slice(lastColon + 1));\n\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n resolve({ ok: false, detail: `\"${target}\" is not host:port` });\n return;\n }\n\n const socket = net.connect({ host, port });\n const finish = (result: ProbeResult) => {\n socket.removeAllListeners();\n socket.destroy();\n resolve(result);\n };\n\n socket.setTimeout(timeoutMs);\n socket.once('connect', () => finish({ ok: true }));\n socket.once('timeout', () => finish({ ok: false, detail: 'connect timed out' }));\n socket.once('error', (error) => finish({ ok: false, detail: (error as NodeJS.ErrnoException).code ?? error.message }));\n });\n\nexport const httpProbe = async (url: string, timeoutMs = 2_000): Promise<ProbeResult> => {\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(timeoutMs),\n redirect: 'manual',\n headers: { 'user-agent': 'laracrew' },\n });\n // Any answer means the server is up; a 404 on /up still proves it is listening.\n if (response.status >= 500) return { ok: false, detail: `HTTP ${response.status}` };\n return { ok: true, detail: `HTTP ${response.status}` };\n } catch (error) {\n return { ok: false, detail: error instanceof Error ? error.message : String(error) };\n }\n};\n\n/** True when the port is free to bind — used by `doctor` to report clashes before booting. */\nexport const isPortFree = (port: number, host = '127.0.0.1'): Promise<boolean> =>\n new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => server.close(() => resolve(true)));\n server.listen(port, host);\n });\n\nexport interface WaitOptions {\n timeoutMs: number;\n intervalMs: number;\n signal?: AbortSignal;\n}\n\n/** Polls `probe` until it passes, the timeout expires, or the caller aborts. */\nexport const waitFor = async (\n probe: () => Promise<ProbeResult>,\n options: WaitOptions,\n): Promise<ProbeResult> => {\n const deadline = Date.now() + options.timeoutMs;\n let last: ProbeResult = { ok: false, detail: 'not attempted' };\n\n while (Date.now() < deadline) {\n if (options.signal?.aborted) return { ok: false, detail: 'aborted' };\n last = await probe();\n if (last.ok) return last;\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(options.intervalMs, remaining), options.signal);\n }\n\n return { ok: false, detail: last.detail ?? 'timed out' };\n};\n\nexport const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n resolve();\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n\n/** A human-readable label for what we are waiting on, shown in the boot screen. */\nexport const describeProbe = (probe: ReadyProbe): string => {\n if (probe.http) return `http ${probe.http}`;\n if (probe.tcp) return `tcp ${probe.tcp}`;\n if (probe.logMatch) return `log /${probe.logMatch}/`;\n if (probe.delayMs !== undefined) return `wait ${probe.delayMs}ms`;\n return 'spawn';\n};\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process';\nimport type { Command, ResolvedService } from '../config/resolve.js';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\n/**\n * On Windows, `npm`/`npx`/`yarn`/`pnpm` are .cmd shims. Recent Node refuses to spawn them\n * without a shell, so these have to go through cmd.exe even in argv form.\n */\nconst SHIM_NAMES = new Set(['npm', 'npx', 'yarn', 'pnpm', 'bun', 'composer']);\n\nconst needsShell = (file: string): boolean => {\n if (!IS_WINDOWS) return false;\n const base = file.replace(/\\\\/g, '/').split('/').pop() ?? file;\n if (/\\.(cmd|bat)$/i.test(base)) return true;\n return SHIM_NAMES.has(base.replace(/\\.[^.]+$/, '').toLowerCase());\n};\n\n/** A quoted, human-readable rendering of the command — used in logs and the TUI header. */\nexport const describeCommand = (command: Command): string =>\n command.kind === 'shell'\n ? command.line\n : [command.file, ...command.args].map((part) => (part.includes(' ') ? `\"${part}\"` : part)).join(' ');\n\nexport const buildEnv = (service: ResolvedService, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => ({\n ...base,\n ...service.env,\n LARACREW: '1',\n LARACREW_SERVICE: service.name,\n ...(service.project ? { LARACREW_PROJECT: service.project.key } : {}),\n});\n\nexport interface SpawnedChild {\n child: ChildProcess;\n description: string;\n}\n\nexport const spawnService = (service: ResolvedService, base: NodeJS.ProcessEnv = process.env): SpawnedChild => {\n const command = service.command;\n if (!command) throw new Error(`service \"${service.name}\" has no command to run`);\n\n const options: SpawnOptions = {\n cwd: service.cwd,\n env: buildEnv(service, base),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n // POSIX: a new process group means one kill(-pid) takes the whole tree down.\n // Windows has no equivalent, so stop.ts uses `taskkill /T` there instead.\n detached: !IS_WINDOWS,\n };\n\n const child =\n command.kind === 'shell'\n ? spawn(command.line, { ...options, shell: true })\n : spawn(command.file, command.args, { ...options, shell: needsShell(command.file) });\n\n return { child, description: describeCommand(command) };\n};\n\n/** Runs a short-lived command to completion; used for artisan hooks and task steps. */\nexport const runOnce = (\n command: Command,\n options: { cwd: string; env?: NodeJS.ProcessEnv; timeoutMs?: number },\n): Promise<{ code: number | null; stdout: string; stderr: string }> =>\n new Promise((resolve, reject) => {\n const spawnOptions: SpawnOptions = {\n cwd: options.cwd,\n env: options.env ?? process.env,\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n };\n\n const child =\n command.kind === 'shell'\n ? spawn(command.line, { ...spawnOptions, shell: true })\n : spawn(command.file, command.args, { ...spawnOptions, shell: needsShell(command.file) });\n\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8');\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8');\n });\n\n const timer = options.timeoutMs\n ? setTimeout(() => {\n child.kill('SIGKILL');\n }, options.timeoutMs)\n : undefined;\n timer?.unref?.();\n\n child.once('error', (error) => {\n if (timer) clearTimeout(timer);\n reject(error);\n });\n child.once('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ code, stdout, stderr });\n });\n });\n","import type { EventListener, LaracrewEvent } from './types.js';\n\n/**\n * Deliberately not an EventEmitter: subscribers get *every* event, which keeps the\n * renderers dumb and makes the daemon's IPC stream a straight passthrough.\n */\nexport class EventBus {\n #listeners = new Set<EventListener>();\n\n subscribe(listener: EventListener): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n emit(event: LaracrewEvent): void {\n for (const listener of this.#listeners) {\n try {\n listener(event);\n } catch (error) {\n // A broken renderer must never take the supervisor down with it.\n process.emitWarning(\n `laracrew: event listener threw: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n /** Resolves on the first event matching `predicate`, or rejects on timeout. */\n next(predicate: (event: LaracrewEvent) => boolean, timeoutMs = 10_000): Promise<LaracrewEvent> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n unsubscribe();\n reject(new Error('timed out waiting for event'));\n }, timeoutMs);\n timer.unref?.();\n\n const unsubscribe = this.subscribe((event) => {\n if (!predicate(event)) return;\n clearTimeout(timer);\n unsubscribe();\n resolve(event);\n });\n });\n }\n\n get size(): number {\n return this.#listeners.size;\n }\n}\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readProjectEnv } from '../laravel/env.js';\nimport { ConfigError, didYouMean } from './errors.js';\nimport { interpolateDeep, type InterpolationContext } from './interpolate.js';\nimport type { LoadedStack } from './load.js';\nimport {\n backoffSchema,\n stopPolicySchema,\n type Backoff,\n type MetricsConfig,\n type ProjectConfig,\n type ReadyProbe,\n type RestartPolicy,\n type ServiceConfig,\n type StopPolicy,\n type WatchConfig,\n} from './schema.js';\n\nexport type Command =\n | { kind: 'shell'; line: string }\n | { kind: 'argv'; file: string; args: string[] };\n\nexport interface ResolvedProject {\n key: string;\n path: string;\n php: string;\n envFile: string;\n env: Record<string, string>;\n color: string;\n}\n\n/** Step 1 of the stop ladder, already resolved to something runnable. */\nexport interface GracefulStop {\n command: Command;\n cwd: string;\n}\n\nexport interface ResolvedService {\n name: string;\n project?: ResolvedProject;\n command?: Command;\n /** From `stop.exec`, or from `stop.artisan` on a project. Absent = go straight to the signal. */\n graceful?: GracefulStop;\n cwd: string;\n env: Record<string, string>;\n groups: string[];\n needs: string[];\n ready?: ReadyProbe;\n restart: RestartPolicy;\n backoff: Backoff;\n stop: StopPolicy;\n watch?: WatchConfig;\n metrics?: MetricsConfig;\n url?: string;\n external: boolean;\n /** false = created but not launched by `up`; the user starts it on demand. */\n autostart: boolean;\n color: string;\n}\n\nexport interface ResolvedStack {\n name: string;\n description?: string;\n dir: string;\n file: string;\n services: ResolvedService[];\n /** Topologically sorted groups; everything in a level can start in parallel. */\n levels: string[][];\n projects: Record<string, ResolvedProject>;\n ports: number[];\n logs: { maxLines: number; toFile: boolean; maxFileBytes: number; keepFiles: number };\n}\n\nexport interface ResolveOptions {\n profile?: string;\n only?: string[];\n except?: string[];\n env?: NodeJS.ProcessEnv;\n sharedProjects?: Record<string, ProjectConfig>;\n}\n\nconst PALETTE = ['cyan', 'magenta', 'green', 'yellow', 'blue', 'red'] as const;\n\nconst toCommand = (cmd: string | string[]): Command =>\n Array.isArray(cmd)\n ? { kind: 'argv', file: cmd[0]!, args: cmd.slice(1) }\n : { kind: 'shell', line: cmd };\n\n/** Matches a service against a selector: its exact name, or one of its groups. */\nconst matches = (service: ResolvedService, selectors: string[]): boolean =>\n selectors.some((selector) => service.name === selector || service.groups.includes(selector));\n\nconst resolveProjects = (\n stack: LoadedStack,\n shared: Record<string, ProjectConfig>,\n): Record<string, ResolvedProject> => {\n const wanted = new Map<string, ProjectConfig>();\n\n for (const key of stack.config.use) {\n const project = shared[key];\n if (!project) {\n const suggestion = didYouMean(key, Object.keys(shared));\n throw new ConfigError(\n `\\`use:\\` refers to project \"${key}\", which is not in projects.yaml` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n wanted.set(key, project);\n }\n // Inline definitions win over shared ones with the same key.\n for (const [key, project] of Object.entries(stack.config.projects)) wanted.set(key, project);\n\n const out: Record<string, ResolvedProject> = {};\n let index = 0;\n for (const [key, project] of wanted) {\n const root = path.resolve(project.path);\n out[key] = {\n key,\n path: root,\n php: project.php,\n envFile: project.envFile,\n env: readProjectEnv(root, project.envFile),\n color: project.color ?? PALETTE[index % PALETTE.length]!,\n };\n index += 1;\n }\n return out;\n};\n\nconst mergeService = (\n raw: ServiceConfig,\n stack: LoadedStack,\n projects: Record<string, ResolvedProject>,\n ports: Set<number>,\n processEnv: NodeJS.ProcessEnv,\n colorIndex: number,\n): ResolvedService => {\n const defaults = stack.config.defaults;\n\n let project: ResolvedProject | undefined;\n if (raw.project) {\n project = projects[raw.project];\n if (!project) {\n const suggestion = didYouMean(raw.project, Object.keys(projects));\n throw new ConfigError(\n `service \"${raw.name}\" refers to project \"${raw.project}\", which this stack does not define` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n }\n\n const ctx: InterpolationContext = {\n env: processEnv,\n stackDir: stack.dir,\n ports,\n ...(project ? { project: { path: project.path, env: project.env } } : {}),\n };\n\n let service: ServiceConfig;\n try {\n service = interpolateDeep(raw, ctx);\n } catch (error) {\n if (error instanceof ConfigError) {\n throw new ConfigError(`service \"${raw.name}\": ${error.message}`, { file: stack.file, cause: error });\n }\n throw error;\n }\n\n const cwd = service.cwd\n ? path.resolve(project?.path ?? stack.dir, service.cwd)\n : (project?.path ?? stack.dir);\n\n // A service declaring its own graceful step replaces the inherited one, whichever kind it is.\n const inheritedStop = { ...defaults.stop };\n const ownStop = service.stop ?? {};\n if (ownStop.exec !== undefined) delete inheritedStop.artisan;\n if (ownStop.artisan !== undefined) delete inheritedStop.exec;\n const stop = stopPolicySchema.parse({ ...inheritedStop, ...ownStop });\n\n if (stop.exec !== undefined && stop.artisan !== undefined) {\n throw new ConfigError(\n `service \"${service.name}\" declares both \\`stop.exec\\` and \\`stop.artisan\\``,\n { file: stack.file, details: ['keep one — `artisan` is only shorthand for an `exec` that runs artisan'] },\n );\n }\n if (stop.artisan !== undefined && !project) {\n throw new ConfigError(\n `service \"${service.name}\" declares \\`stop.artisan\\` but belongs to no project`,\n {\n file: stack.file,\n details: ['`artisan` runs `<project php> artisan ...`, so it needs a project', 'for any other command use `stop.exec`'],\n },\n );\n }\n\n const graceful: GracefulStop | undefined = stop.exec\n ? { command: toCommand(stop.exec), cwd }\n : stop.artisan && project\n ? // artisan must run from the Laravel root even when the service sets its own cwd.\n { command: { kind: 'argv', file: project.php, args: ['artisan', ...stop.artisan.split(/\\s+/)] }, cwd: project.path }\n : undefined;\n\n return {\n name: service.name,\n ...(project ? { project } : {}),\n ...(service.cmd ? { command: toCommand(service.cmd) } : {}),\n ...(graceful ? { graceful } : {}),\n cwd,\n env: { ...service.env },\n groups: service.groups,\n needs: service.needs,\n ...(service.ready ? { ready: service.ready } : {}),\n restart: service.restart ?? defaults.restart,\n backoff: backoffSchema.parse({ ...defaults.backoff, ...(service.backoff ?? {}) }),\n stop,\n ...(service.watch ? { watch: service.watch } : {}),\n ...(service.metrics ? { metrics: service.metrics } : {}),\n ...(service.url ? { url: service.url } : {}),\n external: service.external,\n autostart: service.autostart,\n color: service.color ?? project?.color ?? PALETTE[colorIndex % PALETTE.length]!,\n };\n};\n\n/**\n * Kahn's algorithm, but it keeps each \"level\" so the supervisor can start independent\n * services in parallel instead of one at a time. Throws with the actual cycle members.\n */\nexport const topoLevels = (services: ResolvedService[], file?: string): string[][] => {\n const names = new Set(services.map((s) => s.name));\n const remaining = new Map<string, Set<string>>();\n\n for (const service of services) {\n for (const need of service.needs) {\n if (!names.has(need)) {\n const suggestion = didYouMean(need, [...names]);\n throw new ConfigError(\n `service \"${service.name}\" needs \"${need}\", which is not in this stack` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n file ? { file } : {},\n );\n }\n }\n remaining.set(service.name, new Set(service.needs));\n }\n\n const levels: string[][] = [];\n const done = new Set<string>();\n\n while (done.size < services.length) {\n const level = [...remaining.entries()]\n .filter(([name, needs]) => !done.has(name) && [...needs].every((need) => done.has(need)))\n .map(([name]) => name);\n\n if (level.length === 0) {\n const stuck = services.filter((s) => !done.has(s.name)).map((s) => s.name);\n throw new ConfigError(\n `dependency cycle between: ${stuck.join(' -> ')}`,\n file ? { file } : {},\n );\n }\n\n for (const name of level) done.add(name);\n levels.push(level);\n }\n\n return levels;\n};\n\nexport const resolveStack = (stack: LoadedStack, options: ResolveOptions = {}): ResolvedStack => {\n const processEnv = options.env ?? process.env;\n const projects = resolveProjects(stack, options.sharedProjects ?? {});\n const ports = new Set<number>();\n\n const seen = new Set<string>();\n for (const service of stack.config.services) {\n if (seen.has(service.name)) {\n throw new ConfigError(`two services are both named \"${service.name}\"`, { file: stack.file });\n }\n seen.add(service.name);\n }\n\n let services = stack.config.services\n .filter((service) => service.enabled)\n .map((service, index) => mergeService(service, stack, projects, ports, processEnv, index));\n\n // Profile first, then explicit CLI flags, so --only can override a profile.\n const profile = options.profile ? stack.config.profiles[options.profile] : undefined;\n if (options.profile && !profile) {\n const suggestion = didYouMean(options.profile, Object.keys(stack.config.profiles));\n throw new ConfigError(\n `no profile \"${options.profile}\" in this stack` + (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n\n const only = options.only?.length ? options.only : profile?.only;\n const except = options.except?.length ? options.except : profile?.except;\n\n if (only?.length) services = services.filter((service) => matches(service, only));\n if (except?.length) services = services.filter((service) => !matches(service, except));\n\n if (services.length === 0) {\n throw new ConfigError('the selection matched no services', { file: stack.file });\n }\n\n // A filtered-out dependency must not block the survivors.\n const kept = new Set(services.map((service) => service.name));\n services = services.map((service) => ({\n ...service,\n needs: service.needs.filter((need) => kept.has(need)),\n }));\n\n // An auto-started service cannot depend on one the user has to start by hand — that would\n // leave it waiting on a gate nobody opened.\n const manual = new Set(\n services.filter((service) => !service.autostart && !service.external).map((service) => service.name),\n );\n for (const service of services) {\n if (!service.autostart) continue;\n const blocked = service.needs.filter((need) => manual.has(need));\n if (blocked.length > 0) {\n throw new ConfigError(\n `service \"${service.name}\" starts at launch but needs \"${blocked.join('\", \"')}\", which ${\n blocked.length === 1 ? 'does' : 'do'\n } not`,\n { file: stack.file, details: ['give it `autostart: false` too, or start the dependency at launch'] },\n );\n }\n }\n\n for (const service of services) {\n if (!service.external && !existsSync(service.cwd)) {\n throw new ConfigError(\n `service \"${service.name}\" has cwd \"${service.cwd}\", which does not exist`,\n { file: stack.file },\n );\n }\n }\n\n return {\n name: stack.config.name,\n ...(stack.config.description ? { description: stack.config.description } : {}),\n dir: stack.dir,\n file: stack.file,\n services,\n levels: topoLevels(services, stack.file),\n projects,\n ports: [...ports].sort((a, b) => a - b),\n logs: stack.config.defaults.logs,\n };\n};\n","import { readFileSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * A .env reader with no side effects — it never touches process.env, because laracrew\n * reads several projects' files in one run and they routinely disagree.\n */\nexport const parseEnv = (content: string): Record<string, string> => {\n const out: Record<string, string> = {};\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === '' || line.startsWith('#')) continue;\n\n const withoutExport = line.startsWith('export ') ? line.slice('export '.length).trim() : line;\n const eq = withoutExport.indexOf('=');\n if (eq === -1) continue;\n\n const key = withoutExport.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(key)) continue;\n\n let value = withoutExport.slice(eq + 1).trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"') && value.length >= 2) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\") && value.length >= 2)\n ) {\n const quote = value[0];\n value = value.slice(1, -1);\n // Only double quotes carry escapes, matching Laravel/phpdotenv behaviour.\n if (quote === '\"') value = value.replace(/\\\\n/g, '\\n').replace(/\\\\r/g, '\\r').replace(/\\\\\"/g, '\"');\n } else {\n const hash = value.indexOf(' #');\n if (hash !== -1) value = value.slice(0, hash).trim();\n }\n\n out[key] = value;\n }\n\n return out;\n};\n\n/** Reads `<projectPath>/<envFile>`; a missing file is not an error, just an empty environment. */\nexport const readProjectEnv = (projectPath: string, envFile = '.env'): Record<string, string> => {\n try {\n return parseEnv(readFileSync(path.join(projectPath, envFile), 'utf8'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return {};\n throw error;\n }\n};\n","import { ConfigError } from './errors.js';\n\nexport interface InterpolationContext {\n /** process env of laracrew itself */\n env: NodeJS.ProcessEnv;\n /** the current service's project, when it has one */\n project?: { path: string; env: Record<string, string> };\n /** the stack's own folder, for hooks and fragments */\n stackDir?: string;\n /** collected by ${port:N} so `doctor` can report clashes */\n ports?: Set<number>;\n}\n\nconst TOKEN = /\\$\\{([^}]*)\\}/g;\n\nconst splitOnce = (input: string, separator: string): [string, string | undefined] => {\n const index = input.indexOf(separator);\n return index === -1 ? [input, undefined] : [input.slice(0, index), input.slice(index + separator.length)];\n};\n\n/**\n * Supported tokens:\n * ${env:FOO} laracrew's own environment\n * ${env:FOO:fallback} with a default when unset\n * ${project.path} the service's project root\n * ${project.env:REDIS_PORT} a value from that project's .env\n * ${stack.dir} the stack folder\n * ${port:8000} a port, recorded for collision checks\n */\nexport const interpolate = (input: string, ctx: InterpolationContext): string =>\n input.replace(TOKEN, (match, body: string) => {\n const [scheme, rest] = splitOnce(body.trim(), ':');\n\n switch (scheme) {\n case 'env': {\n if (!rest) throw new ConfigError(`\\${env:...} needs a variable name, got \"${match}\"`);\n const [key, fallback] = splitOnce(rest, ':');\n const value = ctx.env[key];\n if (value !== undefined) return value;\n if (fallback !== undefined) return fallback;\n throw new ConfigError(`environment variable \"${key}\" is not set (used in \"${match}\")`);\n }\n\n case 'project.path': {\n if (!ctx.project) throw new ConfigError(`\"${match}\" used on a service that has no \\`project\\``);\n return ctx.project.path;\n }\n\n case 'project.env': {\n if (!ctx.project) throw new ConfigError(`\"${match}\" used on a service that has no \\`project\\``);\n if (!rest) throw new ConfigError(`\\${project.env:...} needs a variable name, got \"${match}\"`);\n const [key, fallback] = splitOnce(rest, ':');\n const value = ctx.project.env[key];\n if (value !== undefined) return value;\n if (fallback !== undefined) return fallback;\n throw new ConfigError(`\"${key}\" is not in the project's .env (used in \"${match}\")`);\n }\n\n case 'stack.dir': {\n if (!ctx.stackDir) throw new ConfigError(`\"${match}\" used outside a stack folder`);\n return ctx.stackDir;\n }\n\n case 'port': {\n const port = Number(rest);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`\"${match}\" is not a valid port number`);\n }\n ctx.ports?.add(port);\n return String(port);\n }\n\n default:\n throw new ConfigError(\n `unknown token \"${match}\" — supported: \\${env:VAR}, \\${project.path}, \\${project.env:VAR}, \\${stack.dir}, \\${port:N}`,\n );\n }\n });\n\n/** Walks any parsed-YAML value and interpolates every string in it. */\nexport const interpolateDeep = <T>(value: T, ctx: InterpolationContext): T => {\n if (typeof value === 'string') return interpolate(value, ctx) as unknown as T;\n if (Array.isArray(value)) return value.map((item) => interpolateDeep(item, ctx)) as unknown as T;\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n // Guard against prototype pollution from a hand-written YAML file.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n out[key] = interpolateDeep(item, ctx);\n }\n return out as unknown as T;\n }\n return value;\n};\n","import path from 'node:path';\nimport type { ResolvedStack } from '../config/resolve.js';\nimport type { EventBus } from '../events/bus.js';\nimport { isLive, type ServiceState } from '../events/types.js';\nimport { LogWriter } from '../logs/file-sink.js';\nimport { paths } from '../config/paths.js';\nimport { ManagedProcess } from './managed-process.js';\n\nexport interface SupervisorOptions {\n env?: NodeJS.ProcessEnv;\n /** Override where log files land. Defaults to ~/.laracrew/logs/<stack>. */\n logDir?: string;\n}\n\nexport interface ServiceSnapshot {\n name: string;\n state: ServiceState;\n pid?: number;\n uptimeMs?: number;\n restarts: number;\n autostart: boolean;\n groups: string[];\n project?: string;\n url?: string;\n command?: string;\n external: boolean;\n color: string;\n}\n\n/**\n * Owns the whole fleet: starts it in dependency order, stops it in reverse, and never\n * leaves a half-started stack behind when a readiness gate fails.\n */\nexport class Supervisor {\n readonly stack: ResolvedStack;\n\n #bus: EventBus;\n #processes = new Map<string, ManagedProcess>();\n #startedOrder: string[] = [];\n #shuttingDown = false;\n #logWriter?: LogWriter;\n\n constructor(stack: ResolvedStack, bus: EventBus, options: SupervisorOptions = {}) {\n this.stack = stack;\n this.#bus = bus;\n\n for (const service of stack.services) {\n this.#processes.set(\n service.name,\n new ManagedProcess(service, bus, {\n logCapacity: stack.logs.maxLines,\n ...(options.env ? { env: options.env } : {}),\n }),\n );\n }\n\n if (stack.logs.toFile) {\n this.#logWriter = new LogWriter({\n dir: options.logDir ?? path.join(paths(options.env ?? process.env).logsDir, stack.name),\n services: stack.services.map((service) => service.name),\n maxBytes: stack.logs.maxFileBytes,\n keep: stack.logs.keepFiles,\n });\n this.#logWriter.attach(bus);\n }\n }\n\n /** Where a service's output is being written, if anywhere. */\n logFileFor(service: string): string | undefined {\n return this.#logWriter?.fileFor(service);\n }\n\n get(name: string): ManagedProcess | undefined {\n return this.#processes.get(name);\n }\n\n get processes(): ManagedProcess[] {\n return [...this.#processes.values()];\n }\n\n snapshot(): ServiceSnapshot[] {\n return this.processes.map((process) => ({\n name: process.service.name,\n state: process.state,\n ...(process.pid !== undefined ? { pid: process.pid } : {}),\n ...(process.uptimeMs !== undefined && isLive(process.state) ? { uptimeMs: process.uptimeMs } : {}),\n restarts: process.restarts,\n autostart: process.service.autostart,\n groups: process.service.groups,\n ...(process.service.project ? { project: process.service.project.key } : {}),\n ...(process.service.url ? { url: process.service.url } : {}),\n external: process.service.external,\n color: process.service.color,\n }));\n }\n\n /**\n * Starts every level in order; everything inside a level goes in parallel.\n * A failure rolls back what already started, so Ctrl-C is never needed to clean up.\n */\n async up(): Promise<void> {\n const startedAt = Date.now();\n this.#bus.emit({\n type: 'stack:starting',\n stack: this.stack.name,\n services: this.stack.services.map((service) => service.name),\n at: startedAt,\n });\n\n for (const level of this.stack.levels) {\n // `autostart: false` services stay in `queued` — defined, visible, startable on demand.\n const toStart = level.filter((name) => this.#processes.get(name)?.service.autostart !== false);\n\n const results = await Promise.allSettled(\n toStart.map(async (name) => {\n const process = this.#processes.get(name)!;\n await process.start();\n this.#startedOrder.push(name);\n }),\n );\n\n const failures = results\n .map((result, index) => ({ result, name: toStart[index]! }))\n .filter((entry): entry is { result: PromiseRejectedResult; name: string } => entry.result.status === 'rejected');\n\n if (failures.length > 0) {\n const reasons = failures.map((failure) => {\n const error: unknown = failure.result.reason;\n return error instanceof Error ? error.message : String(error);\n });\n for (const reason of reasons) {\n this.#bus.emit({ type: 'notice', level: 'error', message: reason, at: Date.now() });\n }\n await this.down('boot failed');\n throw new Error(`could not boot \"${this.stack.name}\":\\n ${reasons.join('\\n ')}`);\n }\n }\n\n this.#bus.emit({\n type: 'stack:ready',\n stack: this.stack.name,\n durationMs: Date.now() - startedAt,\n at: Date.now(),\n });\n }\n\n /** Reverse topological order, parallel within a level. */\n async down(reason?: string): Promise<void> {\n if (this.#shuttingDown) return;\n this.#shuttingDown = true;\n\n this.#bus.emit({ type: 'stack:stopping', stack: this.stack.name, at: Date.now() });\n if (reason) {\n this.#bus.emit({ type: 'notice', level: 'info', message: `stopping: ${reason}`, at: Date.now() });\n }\n\n for (const level of [...this.stack.levels].reverse()) {\n await Promise.all(\n level.map(async (name) => {\n const process = this.#processes.get(name);\n if (!process) return;\n try {\n await process.dispose();\n } catch (error) {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: name,\n message: `stop failed: ${error instanceof Error ? error.message : String(error)}`,\n at: Date.now(),\n });\n }\n }),\n );\n }\n\n this.#bus.emit({ type: 'stack:stopped', stack: this.stack.name, at: Date.now() });\n // Flush and close the log files last, so the shutdown itself is recorded.\n await this.#logWriter?.close();\n this.#shuttingDown = false;\n }\n\n async restart(name: string): Promise<void> {\n const process = this.#requireProcess(name);\n await process.restart();\n }\n\n /**\n * Restarts every service that is `running` right now and nothing else: a stopped or idle\n * service stays where it is, a failed one is not resurrected, one still starting is left to\n * finish. Dependency order, parallel within a level, so a dependency is back and ready\n * before the services that need it are bounced. Returns the names restarted, in that order.\n */\n async restartRunning(): Promise<string[]> {\n const isTarget = (process: ManagedProcess): boolean => !process.service.external && process.state === 'running';\n const wanted = new Set(this.processes.filter(isTarget).map((process) => process.service.name));\n if (wanted.size === 0) return [];\n\n this.#bus.emit({\n type: 'notice',\n level: 'info',\n message: `restarting ${wanted.size} running service${wanted.size === 1 ? '' : 's'}: ${[...wanted].join(', ')}`,\n at: Date.now(),\n });\n\n const restarted = new Set<string>();\n for (const level of this.stack.levels) {\n await Promise.all(\n level\n .filter((name) => wanted.has(name))\n .map(async (name) => {\n const process = this.#processes.get(name)!;\n // It was running when the key was pressed; if it died or was stopped since, leave it.\n if (!isTarget(process)) return;\n try {\n await process.restart();\n restarted.add(name);\n } catch (error) {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: name,\n message: `restart failed: ${error instanceof Error ? error.message : String(error)}`,\n at: Date.now(),\n });\n }\n }),\n );\n }\n\n return this.stack.levels.flat().filter((name) => restarted.has(name));\n }\n\n async stopService(name: string): Promise<void> {\n await this.#requireProcess(name).stop();\n }\n\n async startService(name: string): Promise<void> {\n await this.#requireProcess(name).start();\n }\n\n /** Every service carrying `group`, in dependency order. */\n servicesInGroup(group: string): string[] {\n return this.stack.services.filter((service) => service.groups.includes(group)).map((service) => service.name);\n }\n\n #requireProcess(name: string): ManagedProcess {\n const process = this.#processes.get(name);\n if (!process) {\n const available = [...this.#processes.keys()].join(', ');\n throw new Error(`no service \"${name}\" in stack \"${this.stack.name}\". Available: ${available}`);\n }\n return process;\n }\n}\n","/**\n * The single vocabulary every renderer speaks. `core/` emits these; the TUI, the plain\n * printer, the JSON printer and the daemon's IPC stream are all just subscribers.\n * Nothing in core may import a renderer.\n */\n\nexport type ServiceState =\n | 'queued'\n | 'starting'\n | 'ready'\n | 'running'\n | 'stopping'\n | 'stopped'\n | 'crashed'\n | 'backoff'\n | 'failed';\n\n/** States from which the service is not going to produce more output on its own. */\nexport const TERMINAL_STATES: ReadonlySet<ServiceState> = new Set(['stopped', 'failed']);\n\nexport const isLive = (state: ServiceState): boolean =>\n state === 'starting' || state === 'ready' || state === 'running';\n\nexport interface LogLine {\n service: string;\n stream: 'stdout' | 'stderr' | 'system';\n line: string;\n at: number;\n}\n\nexport type LaracrewEvent =\n | { type: 'stack:starting'; stack: string; services: string[]; at: number }\n | { type: 'stack:ready'; stack: string; durationMs: number; at: number }\n | { type: 'stack:stopping'; stack: string; at: number }\n | { type: 'stack:stopped'; stack: string; at: number }\n | {\n type: 'service:state';\n service: string;\n from: ServiceState;\n to: ServiceState;\n detail?: string;\n at: number;\n }\n | { type: 'service:spawned'; service: string; pid: number; command: string; cwd: string; at: number }\n | { type: 'service:ready'; service: string; durationMs: number; probe: string; at: number }\n | {\n type: 'service:exit';\n service: string;\n code: number | null;\n signal: NodeJS.Signals | null;\n intentional: boolean;\n at: number;\n }\n | { type: 'service:restart'; service: string; attempt: number; maxAttempts: number; delayMs: number; at: number }\n | { type: 'service:log'; log: LogLine }\n | { type: 'notice'; level: 'info' | 'warn' | 'error'; message: string; service?: string; at: number };\n\nexport type EventListener = (event: LaracrewEvent) => void;\n","import { closeSync, existsSync, mkdirSync, openSync, renameSync, rmSync, statSync, writeSync } from 'node:fs';\nimport path from 'node:path';\nimport { stripAnsi } from '../../cli/render/colors.js';\nimport type { EventBus } from '../events/bus.js';\nimport type { LogLine } from '../events/types.js';\n\n/**\n * In-memory ring buffers hold three minutes of a busy stack. \"I saw an exception scroll past\n * and now it's gone\" is the single fastest way to stop trusting a process manager, so every\n * line also goes to disk.\n *\n * Files are plain text with a sortable local timestamp and no ANSI, so `grep` and `--since`\n * both work on them.\n */\n\nexport interface FileSinkOptions {\n maxBytes: number;\n /** How many rotated files to keep beside the current one. */\n keep: number;\n}\n\n/** `2026-09-19 11:23:45.123` — local time, because you think in local time. */\nexport const stamp = (at: number): string => {\n const date = new Date(at);\n const pad = (value: number, width = 2): string => String(value).padStart(width, '0');\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`\n );\n};\n\n/** Parses a line written by this sink back into its parts. */\nexport const parseLine = (raw: string): { at: number; stream: string; line: string } | undefined => {\n const match = /^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}) (stdout|stderr|system) (.*)$/s.exec(raw);\n if (!match) return undefined;\n const at = new Date(match[1]!.replace(' ', 'T')).getTime();\n return { at: Number.isNaN(at) ? 0 : at, stream: match[2]!, line: match[3]! };\n};\n\n/** `api:queue` is not a legal Windows filename. */\nexport const safeFileName = (service: string): string =>\n service.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'service';\n\n/**\n * Builds one filename per service, disambiguating the rare case where two service names\n * sanitise to the same thing (`api:queue` and `api-queue`).\n */\nexport const fileNamesFor = (services: readonly string[]): Map<string, string> => {\n const used = new Set<string>();\n const out = new Map<string, string>();\n\n for (const service of services) {\n const base = safeFileName(service);\n let candidate = base;\n let index = 2;\n while (used.has(candidate)) candidate = `${base}-${index++}`;\n used.add(candidate);\n out.set(service, `${candidate}.log`);\n }\n\n return out;\n};\n\n/**\n * One append-only file, rotated by size.\n *\n * Writes go through a held file descriptor with `writeSync` rather than a WriteStream. A\n * stream's `end()` is asynchronous, so rotation would rename the file while the handle was\n * still open — which Windows refuses outright, silently costing you the rotation. A\n * descriptor closes deterministically, and a synchronous write also means a line is on disk\n * before the process that logged it can crash.\n */\nexport class FileSink {\n readonly file: string;\n #fd?: number;\n #bytes = 0;\n #closed = false;\n readonly #options: FileSinkOptions;\n\n constructor(file: string, options: FileSinkOptions) {\n this.file = file;\n this.#options = options;\n }\n\n #open(): number | undefined {\n if (this.#fd !== undefined) return this.#fd;\n\n try {\n mkdirSync(path.dirname(this.file), { recursive: true });\n this.#bytes = existsSync(this.file) ? statSync(this.file).size : 0;\n this.#fd = openSync(this.file, 'a');\n return this.#fd;\n } catch {\n // A disk problem must never take the supervisor down with it.\n this.#closed = true;\n return undefined;\n }\n }\n\n write(entry: LogLine): void {\n if (this.#closed) return;\n\n const fd = this.#open();\n if (fd === undefined) return;\n\n const text = `${stamp(entry.at)} ${entry.stream} ${stripAnsi(entry.line)}\\n`;\n try {\n writeSync(fd, text);\n } catch {\n this.#closeHandle();\n this.#closed = true;\n return;\n }\n\n this.#bytes += Buffer.byteLength(text);\n if (this.#bytes >= this.#options.maxBytes) this.#rotate();\n }\n\n #closeHandle(): void {\n if (this.#fd === undefined) return;\n try {\n closeSync(this.#fd);\n } catch {\n /* already gone */\n }\n this.#fd = undefined;\n }\n\n #rotate(): void {\n // The handle must be closed before the rename, or Windows rejects it outright.\n this.#closeHandle();\n this.#bytes = 0;\n\n try {\n if (this.#options.keep <= 0) {\n rmSync(this.file, { force: true });\n return;\n }\n\n // Drop the oldest, shift the rest along, then move the current file to .1\n const oldest = `${this.file}.${this.#options.keep}`;\n if (existsSync(oldest)) rmSync(oldest, { force: true });\n\n for (let index = this.#options.keep - 1; index >= 1; index -= 1) {\n const from = `${this.file}.${index}`;\n if (existsSync(from)) renameSync(from, `${this.file}.${index + 1}`);\n }\n\n if (existsSync(this.file)) renameSync(this.file, `${this.file}.1`);\n } catch {\n // Losing a rotation is survivable; losing the process is not.\n }\n }\n\n close(): Promise<void> {\n this.#closed = true;\n this.#closeHandle();\n return Promise.resolve();\n }\n}\n\nexport interface LogWriterOptions {\n dir: string;\n services: readonly string[];\n maxBytes?: number;\n keep?: number;\n}\n\n/**\n * Routes every `service:log` event to the right file. Lives in core and subscribes to the\n * bus like any other renderer, so it works identically under the TUI, `--plain` and `--json`.\n */\nexport class LogWriter {\n readonly dir: string;\n readonly #sinks = new Map<string, FileSink>();\n readonly #names: Map<string, string>;\n #unsubscribe?: () => void;\n\n constructor(options: LogWriterOptions) {\n this.dir = options.dir;\n this.#names = fileNamesFor(options.services);\n\n const sinkOptions: FileSinkOptions = {\n maxBytes: options.maxBytes ?? 5_000_000,\n keep: options.keep ?? 1,\n };\n for (const [service, fileName] of this.#names) {\n this.#sinks.set(service, new FileSink(path.join(this.dir, fileName), sinkOptions));\n }\n }\n\n /** The file a given service writes to — used by `laracrew logs`. */\n fileFor(service: string): string | undefined {\n const name = this.#names.get(service);\n return name ? path.join(this.dir, name) : undefined;\n }\n\n attach(bus: EventBus): () => void {\n this.#unsubscribe = bus.subscribe((event) => {\n if (event.type !== 'service:log') return;\n this.#sinks.get(event.log.service)?.write(event.log);\n });\n return this.#unsubscribe;\n }\n\n async close(): Promise<void> {\n this.#unsubscribe?.();\n this.#unsubscribe = undefined;\n await Promise.all([...this.#sinks.values()].map((sink) => sink.close()));\n }\n}\n","import type { LogLine } from '../events/types.js';\n\n/**\n * Bounded per-service history. A chatty worker must not grow the heap forever, and the\n * TUI only ever renders a window of this anyway.\n */\nexport class RingBuffer<T = LogLine> {\n #items: (T | undefined)[];\n #next = 0;\n #count = 0;\n #dropped = 0;\n\n constructor(readonly capacity: number) {\n if (!Number.isInteger(capacity) || capacity < 1) {\n throw new RangeError(`RingBuffer capacity must be a positive integer, got ${capacity}`);\n }\n this.#items = Array.from({ length: capacity });\n }\n\n push(item: T): void {\n if (this.#count === this.capacity) this.#dropped += 1;\n this.#items[this.#next] = item;\n this.#next = (this.#next + 1) % this.capacity;\n this.#count = Math.min(this.#count + 1, this.capacity);\n }\n\n /** Oldest to newest. */\n toArray(): T[] {\n const out: T[] = [];\n const start = this.#count === this.capacity ? this.#next : 0;\n for (let i = 0; i < this.#count; i += 1) {\n out.push(this.#items[(start + i) % this.capacity]!);\n }\n return out;\n }\n\n /** The last `n` items, oldest to newest — what a log pane actually needs. */\n tail(n: number): T[] {\n if (n >= this.#count) return this.toArray();\n const out: T[] = [];\n for (let i = this.#count - n; i < this.#count; i += 1) {\n const start = this.#count === this.capacity ? this.#next : 0;\n out.push(this.#items[(start + i) % this.capacity]!);\n }\n return out;\n }\n\n clear(): void {\n this.#items = Array.from({ length: this.capacity });\n this.#next = 0;\n this.#count = 0;\n this.#dropped = 0;\n }\n\n get size(): number {\n return this.#count;\n }\n\n /** How many items fell off the back — worth showing in the UI. */\n get dropped(): number {\n return this.#dropped;\n }\n}\n","/**\n * Child output goes straight into a framed TUI, so anything that moves the cursor would\n * corrupt the frame. Colour (SGR) is kept — Laravel colours its own output and that is\n * worth preserving.\n *\n * The escape characters are built with String.fromCharCode instead of being written as\n * literals, so this file holds no raw control bytes for an editor or a diff to mangle.\n */\n\nconst ESC = String.fromCharCode(27);\nconst BEL = String.fromCharCode(7);\n\n/** CSI: ESC [ params intermediates final — colour, cursor moves, erase. */\nconst CSI = new RegExp(ESC + '\\\\[[0-?]*[ -/]*[@-~]', 'g');\n\n/** OSC: ESC ] ... BEL or ST — window titles and hyperlinks. */\nconst OSC = new RegExp(ESC + '\\\\][^' + BEL + ESC + ']*(?:' + BEL + '|' + ESC + '\\\\\\\\)', 'g');\n\n/** Single-character escapes that have no business mid-line. */\nconst SINGLE = new RegExp(ESC + '[=>78MD]', 'g');\n\nconst TAB = 9;\nconst ESC_CODE = 27;\n\nexport const sanitize = (input: string): string => {\n let out = input.replace(OSC, '').replace(SINGLE, '');\n\n // Keep colour, drop everything that would move or erase.\n out = out.replace(CSI, (seq) => (seq.endsWith('m') ? seq : ''));\n\n // Progress bars redraw with \\r; only the final state is meaningful in a log.\n if (out.includes('\\r')) {\n const segments = out.split('\\r').filter((segment) => segment !== '');\n out = segments.length > 0 ? segments[segments.length - 1]! : '';\n }\n\n // Strip the remaining control characters. ESC survives because the SGR sequences\n // kept above still need it.\n return out.replace(/\\p{Cc}/gu, (character) => {\n const code = character.charCodeAt(0);\n return code === TAB || code === ESC_CODE ? character : '';\n });\n};\n\n/**\n * Turns a stream of arbitrary chunks into whole lines. Children write when they feel like\n * it, so a line routinely arrives split across two chunks.\n */\nexport class LineSplitter {\n #buffer = '';\n readonly #maxLineLength: number;\n\n constructor(maxLineLength = 16_384) {\n this.#maxLineLength = maxLineLength;\n }\n\n push(chunk: string | Buffer): string[] {\n this.#buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');\n\n const lines: string[] = [];\n let index = this.#buffer.indexOf('\\n');\n while (index !== -1) {\n const line = this.#buffer.slice(0, index).replace(/\\r$/, '');\n lines.push(sanitize(line));\n this.#buffer = this.#buffer.slice(index + 1);\n index = this.#buffer.indexOf('\\n');\n }\n\n // A child that never emits a newline (a progress bar, a hung prompt) must not grow\n // the buffer without bound.\n if (this.#buffer.length > this.#maxLineLength) {\n lines.push(sanitize(this.#buffer));\n this.#buffer = '';\n }\n\n return lines;\n }\n\n /** Emits whatever is left when the stream closes. */\n flush(): string[] {\n if (this.#buffer === '') return [];\n const line = sanitize(this.#buffer.replace(/\\r$/, ''));\n this.#buffer = '';\n return line === '' ? [] : [line];\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\nexport const isAlive = (pid: number): boolean => {\n try {\n // Signal 0 performs the permission/existence check without delivering anything.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\n/**\n * `php artisan serve` spawns a child PHP server and `npm run dev` spawns Vite. Killing only\n * the parent orphans those and leaves the port bound — the single most common way a dev\n * process manager ruins your afternoon. So every kill is a tree kill.\n */\nexport const killTree = async (pid: number, signal: NodeJS.Signals = 'SIGKILL'): Promise<void> => {\n if (IS_WINDOWS) {\n await new Promise<void>((resolve) => {\n const killer = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n killer.once('error', () => resolve());\n killer.once('close', () => resolve());\n });\n return;\n }\n\n try {\n // Negative pid = the whole process group created by `detached: true`.\n process.kill(-pid, signal);\n } catch {\n try {\n process.kill(pid, signal);\n } catch {\n /* already gone */\n }\n }\n};\n\nexport const waitForExit = (child: ChildProcess, timeoutMs: number): Promise<boolean> =>\n new Promise((resolve) => {\n if (child.exitCode !== null || child.signalCode !== null) {\n resolve(true);\n return;\n }\n const timer = setTimeout(() => {\n child.removeListener('close', onClose);\n resolve(false);\n }, timeoutMs);\n timer.unref?.();\n\n const onClose = () => {\n clearTimeout(timer);\n resolve(true);\n };\n child.once('close', onClose);\n });\n\nexport interface StopLadderOptions {\n child: ChildProcess;\n /** Step 1: the service's own graceful shutdown, e.g. `php artisan queue:restart`. */\n graceful?: () => Promise<void>;\n signal: NodeJS.Signals;\n graceMs: number;\n onStep?: (step: string) => void;\n}\n\nexport type StopOutcome = 'graceful' | 'signal' | 'tree-kill' | 'already-gone' | 'survived';\n\n/**\n * Ordered stop, each step only attempted if the previous one timed out:\n * 1. Graceful command (the process finishes what it holds, then exits by itself)\n * 2. Signal (POSIX only — Windows has no real SIGTERM)\n * 3. Tree kill (taskkill /T /F, or kill the process group)\n */\nexport const stopLadder = async (options: StopLadderOptions): Promise<StopOutcome> => {\n const { child, graceful, signal, graceMs, onStep } = options;\n const pid = child.pid;\n\n if (pid === undefined || child.exitCode !== null || child.signalCode !== null) return 'already-gone';\n\n if (graceful) {\n onStep?.('graceful');\n try {\n await graceful();\n if (await waitForExit(child, graceMs)) return 'graceful';\n } catch {\n // A failed graceful hook is not fatal; fall through to the harder steps.\n }\n }\n\n if (!IS_WINDOWS) {\n onStep?.('signal');\n try {\n process.kill(-pid, signal);\n } catch {\n try {\n child.kill(signal);\n } catch {\n return 'already-gone';\n }\n }\n if (await waitForExit(child, Math.min(graceMs, 5_000))) return 'signal';\n }\n\n onStep?.('tree-kill');\n await killTree(pid);\n if (await waitForExit(child, 5_000)) return 'tree-kill';\n\n return isAlive(pid) ? 'survived' : 'tree-kill';\n};\n","import type { ChildProcess } from 'node:child_process';\nimport type { ResolvedService } from '../config/resolve.js';\nimport type { EventBus } from '../events/bus.js';\nimport type { LogLine, ServiceState } from '../events/types.js';\nimport { RingBuffer } from '../logs/ring-buffer.js';\nimport { LineSplitter } from '../logs/sanitize.js';\nimport { describeProbe, httpProbe, sleep, tcpProbe, waitFor, type ProbeResult } from '../health/probes.js';\nimport { describeCommand, runOnce, spawnService } from './spawn.js';\nimport { stopLadder } from './stop.js';\n\nexport interface ManagedProcessOptions {\n logCapacity?: number;\n env?: NodeJS.ProcessEnv;\n}\n\n/** One supervised child: its state machine, its logs, and its restart policy. */\nexport class ManagedProcess {\n readonly service: ResolvedService;\n readonly logs: RingBuffer<LogLine>;\n\n #bus: EventBus;\n #env: NodeJS.ProcessEnv;\n #child?: ChildProcess;\n #state: ServiceState = 'queued';\n #intentionalStop = false;\n #restarts = 0;\n #attempt = 0;\n #startedAt?: number;\n #readyAt?: number;\n #backoffTimer?: NodeJS.Timeout;\n #logWatchers = new Set<(line: string) => void>();\n #disposed = false;\n\n constructor(service: ResolvedService, bus: EventBus, options: ManagedProcessOptions = {}) {\n this.service = service;\n this.#bus = bus;\n this.#env = options.env ?? process.env;\n this.logs = new RingBuffer<LogLine>(options.logCapacity ?? 5_000);\n }\n\n get state(): ServiceState {\n return this.#state;\n }\n get pid(): number | undefined {\n return this.#child?.pid;\n }\n get restarts(): number {\n return this.#restarts;\n }\n get startedAt(): number | undefined {\n return this.#startedAt;\n }\n get uptimeMs(): number | undefined {\n return this.#startedAt === undefined ? undefined : Date.now() - this.#startedAt;\n }\n get readyDurationMs(): number | undefined {\n return this.#readyAt !== undefined && this.#startedAt !== undefined ? this.#readyAt - this.#startedAt : undefined;\n }\n\n #setState(to: ServiceState, detail?: string): void {\n if (this.#state === to) return;\n const from = this.#state;\n this.#state = to;\n this.#bus.emit({\n type: 'service:state',\n service: this.service.name,\n from,\n to,\n ...(detail ? { detail } : {}),\n at: Date.now(),\n });\n }\n\n #log(line: string, stream: LogLine['stream'] = 'system'): void {\n const entry: LogLine = { service: this.service.name, stream, line, at: Date.now() };\n this.logs.push(entry);\n this.#bus.emit({ type: 'service:log', log: entry });\n for (const watcher of this.#logWatchers) watcher(line);\n }\n\n /**\n * Spawns (unless external) and resolves once the readiness probe passes.\n * Rejects when the gate fails, which is what aborts a boot.\n */\n async start(): Promise<void> {\n if (this.#disposed) throw new Error(`service \"${this.service.name}\" has been disposed`);\n this.#intentionalStop = false;\n this.#setState('starting');\n this.#startedAt = Date.now();\n this.#readyAt = undefined;\n\n if (this.service.external) {\n await this.#awaitReady();\n return;\n }\n\n const { child, description } = spawnService(this.service, this.#env);\n this.#child = child;\n\n child.once('error', (error) => {\n this.#log(`failed to spawn: ${error.message}`, 'stderr');\n this.#setState('failed', error.message);\n });\n\n this.#pipe(child, 'stdout');\n this.#pipe(child, 'stderr');\n child.once('close', (code, signal) => this.#onExit(code, signal));\n\n if (child.pid !== undefined) {\n this.#bus.emit({\n type: 'service:spawned',\n service: this.service.name,\n pid: child.pid,\n command: description,\n cwd: this.service.cwd,\n at: Date.now(),\n });\n }\n\n await this.#awaitReady();\n }\n\n #pipe(child: ChildProcess, stream: 'stdout' | 'stderr'): void {\n const source = child[stream];\n if (!source) return;\n const splitter = new LineSplitter();\n source.setEncoding('utf8');\n source.on('data', (chunk: string) => {\n for (const line of splitter.push(chunk)) this.#log(line, stream);\n });\n source.once('end', () => {\n for (const line of splitter.flush()) this.#log(line, stream);\n });\n }\n\n async #awaitReady(): Promise<void> {\n const probe = this.service.ready;\n\n if (!probe) {\n this.#readyAt = Date.now();\n this.#setState('running');\n return;\n }\n\n const label = describeProbe(probe);\n const result = await this.#runProbe(probe);\n\n if (!result.ok) {\n this.#setState('failed', `readiness gate failed: ${label}${result.detail ? ` (${result.detail})` : ''}`);\n throw new Error(\n `service \"${this.service.name}\" never became ready: ${label}${result.detail ? ` — ${result.detail}` : ''}`,\n );\n }\n\n this.#readyAt = Date.now();\n this.#bus.emit({\n type: 'service:ready',\n service: this.service.name,\n durationMs: this.readyDurationMs ?? 0,\n probe: label,\n at: Date.now(),\n });\n this.#setState(this.service.external ? 'ready' : 'running');\n }\n\n async #runProbe(probe: NonNullable<ResolvedService['ready']>): Promise<ProbeResult> {\n if (probe.delayMs !== undefined && !probe.tcp && !probe.http && !probe.logMatch) {\n await sleep(probe.delayMs);\n return { ok: true };\n }\n if (probe.logMatch) return this.#waitForLogMatch(probe.logMatch, probe.timeoutMs);\n if (probe.http) {\n const url = probe.http;\n return waitFor(() => httpProbe(url, probe.intervalMs * 4), {\n timeoutMs: probe.timeoutMs,\n intervalMs: probe.intervalMs,\n });\n }\n const target = probe.tcp!;\n return waitFor(() => tcpProbe(target, probe.intervalMs * 4), {\n timeoutMs: probe.timeoutMs,\n intervalMs: probe.intervalMs,\n });\n }\n\n /** Readiness by output, for tools that announce themselves (Vite, Reverb). */\n #waitForLogMatch(source: string, timeoutMs: number): Promise<ProbeResult> {\n let pattern: RegExp;\n try {\n pattern = new RegExp(source);\n } catch (error) {\n return Promise.resolve({ ok: false, detail: `invalid logMatch regex: ${String(error)}` });\n }\n\n // Lines that already arrived count — the child may be faster than this gate.\n for (const entry of this.logs.toArray()) {\n if (pattern.test(entry.line)) return Promise.resolve({ ok: true, detail: 'matched buffered output' });\n }\n\n return new Promise((resolve) => {\n const done = (result: ProbeResult) => {\n clearTimeout(timer);\n this.#logWatchers.delete(watcher);\n resolve(result);\n };\n const watcher = (line: string) => {\n if (pattern.test(line)) done({ ok: true });\n };\n const timer = setTimeout(() => done({ ok: false, detail: 'no matching output' }), timeoutMs);\n timer.unref?.();\n this.#logWatchers.add(watcher);\n });\n }\n\n #onExit(code: number | null, signal: NodeJS.Signals | null): void {\n const wasIntentional = this.#intentionalStop;\n const uptime = this.uptimeMs ?? 0;\n this.#child = undefined;\n\n this.#bus.emit({\n type: 'service:exit',\n service: this.service.name,\n code,\n signal,\n intentional: wasIntentional,\n at: Date.now(),\n });\n\n if (wasIntentional || this.#disposed) {\n this.#setState('stopped');\n return;\n }\n\n // A long, healthy run means the earlier failures are ancient history.\n if (uptime >= this.service.backoff.resetAfterMs) this.#attempt = 0;\n\n const clean = code === 0 && signal === null;\n const policy = this.service.restart;\n const shouldRestart = policy === 'always' || (policy === 'on-failure' && !clean);\n\n this.#setState('crashed', signal ? `killed by ${signal}` : `exit code ${code}`);\n\n if (!shouldRestart) {\n this.#setState(clean ? 'stopped' : 'failed', clean ? undefined : `exited with code ${code}`);\n return;\n }\n\n if (this.#attempt >= this.service.backoff.maxRestarts) {\n this.#setState('failed', `gave up after ${this.#attempt} restarts`);\n return;\n }\n\n this.#attempt += 1;\n this.#restarts += 1;\n const { initialMs, factor, maxMs } = this.service.backoff;\n const delayMs = Math.min(Math.round(initialMs * factor ** (this.#attempt - 1)), maxMs);\n\n this.#setState('backoff', `restarting in ${delayMs}ms`);\n this.#bus.emit({\n type: 'service:restart',\n service: this.service.name,\n attempt: this.#attempt,\n maxAttempts: this.service.backoff.maxRestarts,\n delayMs,\n at: Date.now(),\n });\n\n this.#backoffTimer = setTimeout(() => {\n this.#backoffTimer = undefined;\n if (this.#disposed || this.#intentionalStop) return;\n void this.start().catch((error: unknown) => {\n this.#log(`restart failed: ${error instanceof Error ? error.message : String(error)}`, 'stderr');\n });\n }, delayMs);\n this.#backoffTimer.unref?.();\n }\n\n /**\n * Step 1 of the stop ladder: ask the process to finish what it is holding and exit by\n * itself. What that command is — `queue:restart`, `celery control shutdown`, a drain\n * script — was decided in `resolve.ts`; this only runs it.\n */\n #graceful(): (() => Promise<void>) | undefined {\n const graceful = this.service.graceful;\n if (!graceful) return undefined;\n\n return async () => {\n this.#log(`stop: ${describeCommand(graceful.command)}`);\n await runOnce(graceful.command, { cwd: graceful.cwd, env: this.#env, timeoutMs: 15_000 });\n };\n }\n\n async stop(): Promise<void> {\n this.#intentionalStop = true;\n\n if (this.#backoffTimer) {\n clearTimeout(this.#backoffTimer);\n this.#backoffTimer = undefined;\n }\n\n if (this.service.external) {\n this.#setState('stopped');\n return;\n }\n\n const child = this.#child;\n if (!child) {\n this.#setState('stopped');\n return;\n }\n\n this.#setState('stopping');\n\n const graceful = this.#graceful();\n const outcome = await stopLadder({\n child,\n ...(graceful ? { graceful } : {}),\n signal: this.service.stop.signal as NodeJS.Signals,\n graceMs: this.service.stop.graceMs,\n onStep: (step) => this.#log(`stop: ${step}`),\n });\n\n if (outcome === 'survived') {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: this.service.name,\n message: `process ${child.pid} survived the stop ladder — kill it manually`,\n at: Date.now(),\n });\n }\n\n this.#setState('stopped');\n }\n\n async restart(): Promise<void> {\n await this.stop();\n this.#attempt = 0;\n this.#restarts += 1;\n await this.start();\n }\n\n async dispose(): Promise<void> {\n this.#disposed = true;\n await this.stop();\n this.#logWatchers.clear();\n }\n}\n","import { EventEmitter } from 'node:events';\n\n/**\n * `laracrew up --json | head` closes the pipe under us. Without this, Node turns the EPIPE\n * into an unhandled 'error' event and kills the process — which skips the shutdown path and\n * orphans every child. So a broken pipe is treated as \"the reader left\": stop writing, then\n * shut the stack down cleanly.\n */\n\nexport interface WritableLike extends EventEmitter {\n write(chunk: string): boolean;\n}\n\nlet closed = false;\nconst handlers = new Set<() => void>();\n\nexport const outputClosed = (): boolean => closed;\n\n/** Registers a callback for when stdout goes away. Returns an unsubscribe function. */\nexport const onOutputClosed = (handler: () => void): (() => void) => {\n handlers.add(handler);\n if (closed) handler();\n return () => {\n handlers.delete(handler);\n };\n};\n\nconst markClosed = (): void => {\n if (closed) return;\n closed = true;\n for (const handler of handlers) {\n try {\n handler();\n } catch {\n // Nothing useful left to do — stdout is already gone.\n }\n }\n};\n\nconst isPipeError = (error: NodeJS.ErrnoException): boolean =>\n error.code === 'EPIPE' || error.code === 'ERR_STREAM_DESTROYED' || error.code === 'ERR_STREAM_WRITE_AFTER_END';\n\nexport const installPipeGuards = (streams: WritableLike[] = [process.stdout, process.stderr]): void => {\n for (const stream of streams) {\n stream.on('error', (error: NodeJS.ErrnoException) => {\n if (isPipeError(error)) {\n markClosed();\n return;\n }\n throw error;\n });\n }\n};\n\n/** The write every renderer should use: a no-op once the reader has gone. */\nexport const write = (text: string, stream: WritableLike = process.stdout): void => {\n if (closed) return;\n try {\n stream.write(text);\n } catch (error) {\n if (isPipeError(error as NodeJS.ErrnoException)) markClosed();\n else throw error;\n }\n};\n\n/** Test seam — the module-level flag would otherwise leak between cases. */\nexport const resetOutputState = (): void => {\n closed = false;\n handlers.clear();\n};\n","import type { EventBus } from '../../core/events/bus.js';\nimport type { LaracrewEvent } from '../../core/events/types.js';\nimport type { ResolvedStack } from '../../core/config/resolve.js';\nimport { asColorName, padEnd, paint as defaultPaint, type Painter } from './colors.js';\nimport { write as safeWrite } from './output.js';\n\nexport interface PlainRendererOptions {\n stack: ResolvedStack;\n write?: (text: string) => void;\n painter?: Painter;\n timestamps?: boolean;\n now?: () => Date;\n}\n\nconst time = (date: Date): string =>\n `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(\n date.getSeconds(),\n ).padStart(2, '0')}`;\n\n/**\n * `concurrently`-style interleaved output: one fixed-width, coloured prefix per service.\n * This is what runs when stdout is not a TTY, and what CI sees.\n */\nexport const attachPlainRenderer = (bus: EventBus, options: PlainRendererOptions): (() => void) => {\n const write = options.write ?? ((text: string) => safeWrite(text));\n const painter = options.painter ?? defaultPaint;\n const showTime = options.timestamps ?? true;\n const now = options.now ?? (() => new Date());\n\n const colorOf = new Map(options.stack.services.map((service) => [service.name, asColorName(service.color)]));\n const width = Math.max(8, ...options.stack.services.map((service) => service.name.length), 'laracrew'.length);\n\n const line = (service: string, text: string, colorName = colorOf.get(service) ?? 'cyan') => {\n const stamp = showTime ? painter('gray', `${time(now())} `) : '';\n const prefix = painter(colorName, padEnd(service, width));\n write(`${stamp}${prefix} ${painter('gray', '|')} ${text}\\n`);\n };\n\n const system = (text: string, level: 'info' | 'warn' | 'error' = 'info') => {\n const color = level === 'error' ? 'red' : level === 'warn' ? 'yellow' : 'gray';\n line('laracrew', painter(color, text), 'bold');\n };\n\n const handle = (event: LaracrewEvent): void => {\n switch (event.type) {\n case 'service:log':\n line(event.log.service, event.log.line);\n break;\n\n case 'stack:starting': {\n system(`starting ${event.stack} (${event.services.length} services)`);\n const manual = options.stack.services.filter((service) => !service.autostart && !service.external);\n if (manual.length > 0) {\n system(`not launched (autostart: false): ${manual.map((service) => service.name).join(', ')}`);\n }\n break;\n }\n\n case 'stack:ready':\n system(`${event.stack} ready in ${(event.durationMs / 1000).toFixed(1)}s`);\n break;\n\n case 'stack:stopping':\n system(`stopping ${event.stack}…`);\n break;\n\n case 'stack:stopped':\n system(`${event.stack} stopped`);\n break;\n\n case 'service:spawned':\n line(event.service, painter('gray', `$ ${event.command}`));\n break;\n\n case 'service:ready':\n line(event.service, painter('green', `ready (${event.probe}) in ${event.durationMs}ms`));\n break;\n\n case 'service:exit':\n if (!event.intentional) {\n line(\n event.service,\n painter('red', `exited (${event.signal ? `signal ${event.signal}` : `code ${event.code}`})`),\n );\n }\n break;\n\n case 'service:restart':\n line(\n event.service,\n painter('yellow', `restarting in ${event.delayMs}ms (attempt ${event.attempt}/${event.maxAttempts})`),\n );\n break;\n\n case 'service:state':\n if (event.to === 'failed') {\n line(event.service, painter('red', `failed${event.detail ? `: ${event.detail}` : ''}`));\n }\n break;\n\n case 'notice':\n if (event.service) {\n line(event.service, painter(event.level === 'error' ? 'red' : 'yellow', event.message));\n } else {\n system(event.message, event.level);\n }\n break;\n\n default:\n break;\n }\n };\n\n return bus.subscribe(handle);\n};\n","import type { Supervisor } from '../core/process/supervisor.js';\nimport type { LogLine, ServiceState } from '../core/events/types.js';\nimport { describeProbe } from '../core/health/probes.js';\n\n/**\n * What the views render. Built by polling the supervisor rather than by streaming events:\n * the ring buffers already hold everything, so a poll is cheaper than a re-render per line\n * and a chatty worker cannot stall the UI.\n */\n\nexport interface ProcessRow {\n index: number;\n name: string;\n state: ServiceState;\n pid: number | undefined;\n uptimeMs: number | undefined;\n restarts: number;\n external: boolean;\n autostart: boolean;\n /** What laracrew waits on, e.g. \"tcp 127.0.0.1:6379\". Shown for dependencies. */\n probe: string | undefined;\n project: string | undefined;\n command: string | undefined;\n cwd: string;\n url: string | undefined;\n groups: string[];\n logLines: number;\n}\n\nexport interface StackView {\n name: string;\n /** Processes laracrew starts and stops. Indices here are what the digit keys select. */\n rows: ProcessRow[];\n /** `external: true` services — health-checked, never managed. Not selectable. */\n dependencies: ProcessRow[];\n running: number;\n total: number;\n restarts: number;\n failed: number;\n dependenciesDown: number;\n}\n\nconst commandOf = (supervisor: Supervisor, name: string): string | undefined => {\n const service = supervisor.stack.services.find((entry) => entry.name === name);\n if (!service?.command) return undefined;\n return service.command.kind === 'shell'\n ? service.command.line\n : [service.command.file, ...service.command.args].join(' ');\n};\n\nexport const buildStackView = (supervisor: Supervisor): StackView => {\n const all: ProcessRow[] = supervisor.processes.map((managed) => ({\n index: -1, // assigned below, once externals are out of the way\n name: managed.service.name,\n state: managed.state,\n pid: managed.pid,\n uptimeMs: managed.uptimeMs,\n restarts: managed.restarts,\n external: managed.service.external,\n autostart: managed.service.autostart,\n probe: managed.service.ready ? describeProbe(managed.service.ready) : undefined,\n project: managed.service.project?.key,\n command: commandOf(supervisor, managed.service.name),\n cwd: managed.service.cwd,\n url: managed.service.url,\n groups: managed.service.groups,\n logLines: managed.logs.size,\n }));\n\n // Externals are checked, not run. Keeping them out of the numbered list means a digit key\n // always selects something laracrew can actually start and stop.\n const dependencies = all.filter((row) => row.external);\n const rows = all.filter((row) => !row.external).map((row, index) => ({ ...row, index }));\n\n return {\n name: supervisor.stack.name,\n rows,\n dependencies,\n running: rows.filter((row) => row.state === 'running' || row.state === 'ready').length,\n total: rows.length,\n restarts: rows.reduce((sum, row) => sum + row.restarts, 0),\n failed: rows.filter((row) => row.state === 'failed' || row.state === 'crashed').length,\n dependenciesDown: dependencies.filter((row) => row.state !== 'ready' && row.state !== 'running').length,\n };\n};\n\nexport const logsFor = (supervisor: Supervisor, name: string, limit: number): LogLine[] =>\n supervisor.get(name)?.logs.tail(limit) ?? [];\n\n/** Merged view: the newest `limit` lines across every service, oldest first. */\nexport const mergedLogs = (supervisor: Supervisor, limit: number): LogLine[] => {\n const perService = Math.max(20, Math.ceil(limit / Math.max(1, supervisor.processes.length)) * 4);\n const all: LogLine[] = [];\n for (const managed of supervisor.processes) all.push(...managed.logs.tail(perService));\n all.sort((a, b) => a.at - b.at);\n return all.slice(-limit);\n};\n","import type { UiState } from './screen.js';\n\n/**\n * Key handling as a pure function: state and keypress in, new state plus an optional command\n * out. The app performs the commands; this file stays trivially testable.\n */\n\nexport interface Key {\n name: string;\n ctrl?: boolean;\n shift?: boolean;\n}\n\nexport type Command =\n | { type: 'none' }\n | { type: 'quit' }\n | { type: 'force-quit' }\n | { type: 'restart'; index: number }\n | { type: 'restart-running' }\n | { type: 'toggle'; index: number };\n\nexport interface KeyResult {\n ui: UiState;\n command: Command;\n}\n\nconst none = (ui: UiState): KeyResult => ({ ui, command: { type: 'none' } });\n\nexport const handleKey = (ui: UiState, key: Key, rowCount: number): KeyResult => {\n // Ctrl-C always means stop, wherever you are.\n if (key.ctrl && key.name === 'c') {\n return { ui: { ...ui, confirmQuit: false }, command: { type: ui.phase === 'stopping' ? 'force-quit' : 'quit' } };\n }\n\n if (ui.confirmQuit) {\n if (key.name === 'y' || key.name === 'return') {\n return { ui: { ...ui, confirmQuit: false }, command: { type: 'quit' } };\n }\n return none({ ...ui, confirmQuit: false, note: 'Ready for commands.' });\n }\n\n if (ui.view === 'help') {\n return none({ ...ui, view: 'overview' });\n }\n\n const clamp = (index: number): number => Math.min(Math.max(0, index), Math.max(0, rowCount - 1));\n const inLogView = ui.view === 'log' || ui.view === 'merged';\n\n switch (key.name) {\n case 'q':\n return none({ ...ui, confirmQuit: true });\n\n case '?':\n\n return none({ ...ui, view: 'help' });\n\n case 'escape':\n return none({ ...ui, view: 'overview', scrollBack: 0, follow: true });\n\n case 's':\n if (inLogView) return none({ ...ui, view: 'overview', scrollBack: 0, follow: true });\n return { ui, command: { type: 'toggle', index: ui.selected } };\n\n case 't':\n return { ui, command: { type: 'toggle', index: ui.selected } };\n\n case 'r':\n // Shift-R bounces every running process; plain r only the selected one.\n if (key.shift) return { ui, command: { type: 'restart-running' } };\n return { ui, command: { type: 'restart', index: ui.selected } };\n\n case 'a':\n return none({ ...ui, view: ui.view === 'merged' ? 'overview' : 'merged', scrollBack: 0, follow: true });\n\n case 'return':\n case 'v':\n if (ui.view === 'overview') return none({ ...ui, view: 'log', scrollBack: 0, follow: true });\n return none(ui);\n\n case 'up':\n case 'k':\n if (inLogView) return none({ ...ui, scrollBack: ui.scrollBack + 1, follow: false });\n return none({ ...ui, selected: clamp(ui.selected - 1) });\n\n case 'down':\n case 'j':\n if (inLogView) {\n const scrollBack = Math.max(0, ui.scrollBack - 1);\n return none({ ...ui, scrollBack, follow: scrollBack === 0 });\n }\n return none({ ...ui, selected: clamp(ui.selected + 1) });\n\n case 'pageup':\n if (inLogView) return none({ ...ui, scrollBack: ui.scrollBack + 10, follow: false });\n return none({ ...ui, selected: clamp(ui.selected - 5) });\n\n case 'pagedown':\n if (inLogView) {\n const scrollBack = Math.max(0, ui.scrollBack - 10);\n return none({ ...ui, scrollBack, follow: scrollBack === 0 });\n }\n return none({ ...ui, selected: clamp(ui.selected + 5) });\n\n case 'g':\n if (inLogView) {\n // Shift-G is \"bottom\", plain g is \"top\".\n return key.shift\n ? none({ ...ui, scrollBack: 0, follow: true })\n : none({ ...ui, scrollBack: Number.MAX_SAFE_INTEGER, follow: false });\n }\n return none({ ...ui, selected: key.shift ? clamp(rowCount - 1) : 0 });\n\n case 'f':\n if (inLogView) return none({ ...ui, follow: !ui.follow, scrollBack: ui.follow ? ui.scrollBack : 0 });\n return none(ui);\n\n case 'home':\n return inLogView ? none({ ...ui, scrollBack: Number.MAX_SAFE_INTEGER, follow: false }) : none({ ...ui, selected: 0 });\n\n case 'end':\n return inLogView ? none({ ...ui, scrollBack: 0, follow: true }) : none({ ...ui, selected: clamp(rowCount - 1) });\n\n default: {\n // A digit jumps straight to that process and opens its log — the fast path.\n if (/^[0-9]$/.test(key.name)) {\n const index = Number(key.name);\n if (index < rowCount) {\n return none({ ...ui, selected: index, view: 'log', scrollBack: 0, follow: true });\n }\n }\n return none(ui);\n }\n }\n};\n","import type { ServiceState } from '../core/events/types.js';\n\n/**\n * Restrained on purpose: colour carries state, nothing else. The glyph and the word always\n * say the same thing, so a mono terminal loses nothing.\n */\n\nconst asciiOnly = (env: NodeJS.ProcessEnv = process.env): boolean =>\n env.LARACREW_ASCII === '1' || env.TERM === 'dumb';\n\nexport interface Glyphs {\n running: string;\n ready: string;\n starting: string;\n stopped: string;\n failed: string;\n queued: string;\n branch: string;\n lastBranch: string;\n pipe: string;\n pointer: string;\n restart: string;\n rule: string;\n dot: string;\n tick: string;\n}\n\nconst UNICODE: Glyphs = {\n running: '●',\n ready: '●',\n starting: '◐',\n stopped: '◼',\n failed: '✖',\n queued: '○',\n branch: '├─',\n lastBranch: '└─',\n pipe: '│',\n pointer: '▸',\n restart: '⟳',\n rule: '─',\n dot: '·',\n tick: '✔',\n};\n\nconst ASCII: Glyphs = {\n running: '*',\n ready: '*',\n starting: 'o',\n stopped: '#',\n failed: 'X',\n queued: '.',\n branch: '|-',\n lastBranch: '`-',\n pipe: '|',\n pointer: '>',\n restart: 'r',\n rule: '-',\n dot: '.',\n tick: 'v',\n};\n\nexport const glyphs = (env: NodeJS.ProcessEnv = process.env): Glyphs => (asciiOnly(env) ? ASCII : UNICODE);\n\nexport type StateColor = 'green' | 'yellow' | 'red' | 'gray' | 'cyan';\n\nexport interface StateStyle {\n glyph: keyof Glyphs;\n color: StateColor;\n label: string;\n}\n\nexport const STATE_STYLE: Record<ServiceState, StateStyle> = {\n queued: { glyph: 'queued', color: 'gray', label: 'QUEUED' },\n starting: { glyph: 'starting', color: 'yellow', label: 'STARTING' },\n ready: { glyph: 'ready', color: 'cyan', label: 'READY' },\n running: { glyph: 'running', color: 'green', label: 'RUNNING' },\n stopping: { glyph: 'starting', color: 'yellow', label: 'STOPPING' },\n stopped: { glyph: 'stopped', color: 'gray', label: 'STOPPED' },\n crashed: { glyph: 'failed', color: 'red', label: 'CRASHED' },\n backoff: { glyph: 'starting', color: 'yellow', label: 'RESTARTING' },\n failed: { glyph: 'failed', color: 'red', label: 'FAILED' },\n};\n\n/** 00:15:27 — the header clock. */\nexport const formatUptime = (ms: number | undefined): string => {\n if (ms === undefined || ms < 0) return '--:--:--';\n const total = Math.floor(ms / 1000);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n return [hours, minutes, seconds].map((part) => String(part).padStart(2, '0')).join(':');\n};\n\n/** 1m 02s — compact, for a table column. */\nexport const formatDuration = (ms: number | undefined): string => {\n if (ms === undefined || ms < 0) return '—';\n const total = Math.floor(ms / 1000);\n if (total < 60) return `${total}s`;\n const minutes = Math.floor(total / 60);\n const seconds = total % 60;\n if (minutes < 60) return `${minutes}m ${String(seconds).padStart(2, '0')}s`;\n const hours = Math.floor(minutes / 60);\n return `${hours}h ${String(minutes % 60).padStart(2, '0')}m`;\n};\n\nexport const formatClock = (at: number): string => {\n const date = new Date(at);\n return [date.getHours(), date.getMinutes(), date.getSeconds()]\n .map((part) => String(part).padStart(2, '0'))\n .join(':');\n};\n","import type { LogLine } from '../core/events/types.js';\nimport { stripAnsi } from '../cli/render/colors.js';\nimport type { ProcessRow, StackView } from './model.js';\nimport { STATE_STYLE, formatClock, formatDuration, formatUptime, type Glyphs } from './theme.js';\n\n/**\n * Pure rendering: state in, lines of text out. No terminal, no timers, no framework — which\n * makes every screen directly unit-testable and keeps a repaint to one string write.\n */\n\nexport type ViewName = 'overview' | 'log' | 'merged' | 'help';\n\nexport interface UiState {\n view: ViewName;\n selected: number;\n /** Log views stick to the bottom until you scroll up. */\n follow: boolean;\n scrollBack: number;\n confirmQuit: boolean;\n phase: 'booting' | 'running' | 'stopping';\n note: string;\n}\n\nexport const initialUiState = (): UiState => ({\n view: 'overview',\n selected: 0,\n follow: true,\n scrollBack: 0,\n confirmQuit: false,\n phase: 'booting',\n note: 'Booting…',\n});\n\nexport interface Size {\n columns: number;\n rows: number;\n}\n\nexport interface Painter {\n (color: string, text: string): string;\n enabled: boolean;\n}\n\nexport interface RenderInput {\n stack: StackView;\n ui: UiState;\n size: Size;\n glyph: Glyphs;\n paint: Painter;\n /** Lines for the log views; ignored by the overview. */\n logs: LogLine[];\n uptimeMs: number;\n}\n\nconst pad = (text: string, width: number): string => {\n const visible = stripAnsi(text).length;\n return visible >= width ? text : text + ' '.repeat(width - visible);\n};\n\nconst truncate = (text: string, width: number): string => {\n if (width <= 1) return '';\n return stripAnsi(text).length <= width ? text : `${text.slice(0, Math.max(0, width - 1))}…`;\n};\n\nconst rule = (width: number, glyph: Glyphs): string => glyph.rule.repeat(Math.max(0, width));\n\n// ---------------------------------------------------------------- header\n\nconst header = ({ stack, ui, size, paint, glyph, uptimeMs }: RenderInput): string[] => {\n const title = `laracrew ${glyph.dot} ${stack.name}`;\n const health =\n stack.failed > 0\n ? paint('red', `${stack.failed} failed`)\n : stack.dependenciesDown > 0\n ? paint('red', `${stack.dependenciesDown} dependency down`)\n : ui.phase === 'booting'\n ? paint('yellow', 'booting')\n : paint('green', 'all healthy');\n\n const idle = stack.rows.filter((entry) => !entry.autostart && entry.state === 'queued').length;\n const right = [\n `up ${formatUptime(uptimeMs)}`,\n `${stack.running}/${stack.total} running`,\n idle > 0 ? `${idle} idle` : '',\n stack.restarts > 0 ? `${glyph.restart}${stack.restarts}` : '',\n ]\n .filter(Boolean)\n .join(` ${glyph.dot} `);\n\n const left = ` ${paint('bold', title)}`;\n const gap = Math.max(1, size.columns - stripAnsi(left).length - stripAnsi(right).length - stripAnsi(health).length - 5);\n\n return [\n '',\n `${left}${' '.repeat(gap)}${paint('gray', right)} ${health}`,\n paint('gray', ` ${rule(Math.max(0, size.columns - 4), glyph)}`),\n ];\n};\n\n// ---------------------------------------------------------------- key legend\n\nconst KEYS: Record<ViewName, [string, string][]> = {\n overview: [\n ['up/down', 'select'],\n ['enter', 'inspect log'],\n ['0-9', 'jump'],\n ['r', 'restart'],\n ['R', 'restart all running'],\n ['s', 'stop/start'],\n ['a', 'all logs'],\n ['?', 'help'],\n ['q', 'quit'],\n ],\n log: [\n ['esc', 'back to stack'],\n ['up/down', 'scroll'],\n ['g/G', 'top/bottom'],\n ['f', 'follow'],\n ['r', 'restart'],\n ['R', 'restart all running'],\n ['q', 'quit'],\n ],\n merged: [\n ['esc', 'back to stack'],\n ['up/down', 'scroll'],\n ['g/G', 'top/bottom'],\n ['f', 'follow'],\n ['R', 'restart all running'],\n ['q', 'quit'],\n ],\n help: [['any key', 'back']],\n};\n\nconst legend = ({ ui, paint, size }: RenderInput): string[] => {\n const pairs = KEYS[ui.view].map(([key, label]) => `${paint('cyan', key)} ${paint('gray', label)}`);\n\n const lines: string[] = [];\n let current = ' ';\n let currentWidth = 2;\n for (const pair of pairs) {\n const width = stripAnsi(pair).length + 3;\n if (currentWidth + width > size.columns - 2 && currentWidth > 2) {\n lines.push(current);\n current = ' ';\n currentWidth = 2;\n }\n current += `${pair} `;\n currentWidth += width;\n }\n if (currentWidth > 2) lines.push(current);\n return lines;\n};\n\n// ---------------------------------------------------------------- overview\n\nconst processLine = (\n row: ProcessRow,\n isSelected: boolean,\n isLast: boolean,\n nameWidth: number,\n { paint, glyph, size }: RenderInput,\n): string => {\n const style = STATE_STYLE[row.state];\n const branch = isLast ? glyph.lastBranch : glyph.branch;\n const pointer = isSelected ? paint('cyan', glyph.pointer) : ' ';\n const name = isSelected ? paint('cyan', pad(row.name, nameWidth)) : pad(row.name, nameWidth);\n\n // A service that was never meant to launch reads as \"idle\", not \"queued\" — it is not\n // waiting for anything, it is waiting for you.\n const manual = !row.autostart && row.state === 'queued';\n const label = manual ? 'idle' : style.label.toLowerCase();\n const labelColor = manual ? 'gray' : style.color;\n\n const detail = row.external\n ? paint('gray', 'external')\n : manual\n ? paint('cyan', 'press s')\n : row.state === 'running' || row.state === 'ready'\n ? paint('gray', formatDuration(row.uptimeMs))\n : '';\n\n const restarts = row.restarts > 0 ? paint('yellow', ` ${glyph.restart}${row.restarts}`) : '';\n\n const line =\n ` ${paint('gray', branch)} ${pointer} ${paint('gray', `[${row.index}]`)} ` +\n `${paint(labelColor, glyph[style.glyph])} ${name}` +\n `${paint(labelColor, pad(label, 11))}${pad(detail, 9)}${restarts}`;\n\n return truncate(line, size.columns + (line.length - stripAnsi(line).length));\n};\n\n/** Health-checked, never managed — so no index and no branch glyph. */\nconst dependencyLine = (row: ProcessRow, nameWidth: number, { paint, glyph, size }: RenderInput): string => {\n const style = STATE_STYLE[row.state];\n const label = row.state === 'ready' || row.state === 'running' ? 'ready' : style.label.toLowerCase();\n const color = row.state === 'ready' || row.state === 'running' ? 'green' : style.color;\n\n const line =\n ` ${paint(color, glyph[style.glyph])} ${pad(row.name, nameWidth)}` +\n `${paint(color, pad(label, 11))}${paint('gray', row.probe ?? '')}`;\n\n return truncate(line, size.columns + (line.length - stripAnsi(line).length));\n};\n\nconst dependencies = (input: RenderInput, nameWidth: number): string[] => {\n const { stack, paint } = input;\n if (stack.dependencies.length === 0) return [];\n\n return [\n ` ${paint('bold', 'DEPENDENT SERVICES')} ${paint('gray', '(checked, not managed)')}`,\n ...stack.dependencies.map((row) => dependencyLine(row, nameWidth, input)),\n '',\n ];\n};\n\nconst overview = (input: RenderInput, bodyRows: number): string[] => {\n const { stack, ui, paint, glyph } = input;\n const nameWidth =\n Math.max(12, ...[...stack.rows, ...stack.dependencies].map((row) => row.name.length)) + 2;\n\n const dependencyLines = dependencies(input, nameWidth);\n\n const lines: string[] = [\n ` ${paint('bold', 'STACK DETAILS')} ${paint('gray', '(process tree)')}`,\n '',\n ...dependencyLines,\n ` ${paint('gray', `processes (${stack.rows.length} managed)`)}`,\n paint('gray', ` ${glyph.pipe}`),\n ];\n\n if (stack.rows.length === 0) {\n lines.push(` ${paint('gray', `${glyph.lastBranch} nothing to manage in this stack`)}`);\n return lines;\n }\n\n // Keep the selection visible when the list is taller than the terminal.\n const capacity = Math.max(3, bodyRows - 5 - dependencyLines.length);\n let start = 0;\n if (stack.rows.length > capacity) {\n start = Math.min(Math.max(0, ui.selected - Math.floor(capacity / 2)), stack.rows.length - capacity);\n }\n const visible = stack.rows.slice(start, start + capacity);\n\n if (start > 0) lines.push(paint('gray', ` ${glyph.pipe} ${start} more above`));\n\n for (const [offset, row] of visible.entries()) {\n const index = start + offset;\n lines.push(processLine(row, index === ui.selected, index === stack.rows.length - 1, nameWidth, input));\n }\n\n const hiddenBelow = stack.rows.length - (start + visible.length);\n if (hiddenBelow > 0) lines.push(paint('gray', ` ${glyph.pipe} ${hiddenBelow} more below`));\n\n lines.push(paint('gray', ` ${glyph.pipe}`));\n lines.push(` ${paint('gray', `${glyph.lastBranch} ${input.ui.note}`)}`);\n\n return lines;\n};\n\n// ---------------------------------------------------------------- log views\n\nconst logHeader = (row: ProcessRow | undefined, input: RenderInput): string[] => {\n const { paint, glyph, size } = input;\n if (!row) return [` ${paint('gray', 'no process selected')}`];\n\n const style = STATE_STYLE[row.state];\n const meta = [\n paint(style.color, style.label.toLowerCase()),\n row.pid !== undefined ? paint('gray', `pid ${row.pid}`) : '',\n row.state === 'running' ? paint('gray', `up ${formatDuration(row.uptimeMs)}`) : '',\n row.restarts > 0 ? paint('yellow', `${glyph.restart}${row.restarts}`) : '',\n ]\n .filter(Boolean)\n .join(paint('gray', ` ${glyph.dot} `));\n\n const lines = [` ${paint('bold', row.name)} ${meta}`];\n if (row.command) lines.push(` ${paint('gray', truncate(`$ ${row.command}`, size.columns - 4))}`);\n lines.push(` ${paint('gray', truncate(row.cwd, size.columns - 4))}`);\n lines.push(paint('gray', ` ${rule(Math.max(0, size.columns - 4), glyph)}`));\n return lines;\n};\n\nconst logBody = (input: RenderInput, bodyRows: number, withServiceName: boolean): string[] => {\n const { logs, ui, paint, size } = input;\n const capacity = Math.max(1, bodyRows);\n\n if (logs.length === 0) {\n return [` ${paint('gray', 'no output yet')}`];\n }\n\n const end = Math.max(capacity, logs.length - ui.scrollBack);\n const window = logs.slice(Math.max(0, end - capacity), end);\n\n const nameWidth = withServiceName\n ? Math.max(...logs.map((line) => line.service.length))\n : 0;\n\n return window.map((line) => {\n const stamp = paint('gray', formatClock(line.at));\n const who = withServiceName ? ` ${paint('cyan', pad(line.service, nameWidth))}` : '';\n const body = line.stream === 'stderr' ? paint('red', line.line) : line.line;\n const rendered = ` ${stamp}${who} ${paint('gray', '|')} ${body}`;\n return truncate(rendered, size.columns + (rendered.length - stripAnsi(rendered).length));\n });\n};\n\n// ---------------------------------------------------------------- help\n\nconst help = ({ paint, glyph }: RenderInput): string[] => [\n ` ${paint('bold', 'KEYS')}`,\n '',\n ...[\n ['up / down, j / k', 'move the selection'],\n ['0 - 9', 'jump straight to that process and open its log'],\n ['enter, v', 'inspect the selected process log'],\n ['esc, s', 'back to the stack overview'],\n ['a', 'merged log across every service'],\n ['r', 'restart the selected process (graceful)'],\n ['R', 'restart every running process, in dependency order; stopped and idle stay put'],\n ['t', 'toggle the selected process: stop if running, start if stopped'],\n ['f', 'follow / pause tailing in a log view'],\n ['g / G', 'jump to the top / bottom of a log'],\n ['?', 'this help'],\n ['q, ctrl-c', 'quit — stops every process first'],\n ].map(([key, label]) => ` ${paint('cyan', pad(key!, 20))}${paint('gray', label!)}`),\n '',\n ` ${paint('gray', `The overview never streams logs — that is deliberate. Open one ${glyph.dot} read it ${glyph.dot} go back.`)}`,\n];\n\n// ---------------------------------------------------------------- shutdown\n\nexport const renderShutdown = (input: RenderInput): string[] => {\n const { stack, paint, glyph } = input;\n const lines = ['', ` ${paint('bold', `Stopping ${stack.name}…`)}`, ''];\n\n for (const row of stack.rows) {\n const done = row.state === 'stopped' || row.state === 'failed';\n const mark = done ? paint('green', glyph.tick) : paint('yellow', glyph.starting);\n const label = done ? paint('gray', 'stopped') : paint('yellow', 'stopping…');\n lines.push(` ${mark} ${pad(row.name, 22)}${label}`);\n }\n\n lines.push('', ` ${paint('gray', 'ctrl-c again to force')}`);\n return lines;\n};\n\n// ---------------------------------------------------------------- frame\n\n/** The whole screen, as lines. Callers just write this. */\nexport const renderFrame = (input: RenderInput): string[] => {\n if (input.ui.phase === 'stopping') return renderShutdown(input);\n\n const top = header(input);\n const keys = legend(input);\n const chrome = top.length + keys.length + 3;\n const bodyRows = Math.max(3, input.size.rows - chrome);\n\n let body: string[];\n switch (input.ui.view) {\n case 'help':\n body = help(input);\n break;\n case 'log': {\n const row = input.stack.rows[input.ui.selected];\n const head = logHeader(row, input);\n body = [...head, ...logBody(input, bodyRows - head.length, false)];\n break;\n }\n case 'merged':\n body = [\n ` ${input.paint('bold', 'ALL SERVICES')}`,\n input.paint('gray', ` ${rule(Math.max(0, input.size.columns - 4), input.glyph)}`),\n ...logBody(input, bodyRows - 2, true),\n ];\n break;\n default:\n body = overview(input, bodyRows);\n }\n\n const status = input.ui.confirmQuit\n ? ` ${input.paint('yellow', 'Quit and stop every process? (y/n)')}`\n : input.ui.view !== 'overview'\n ? ` ${input.paint('gray', input.ui.note)}`\n : '';\n\n return [...top, '', ...keys, ...body, '', ...(status ? [status] : [])];\n};\n","import readline from 'node:readline';\nimport { stripAnsi } from '../cli/render/colors.js';\nimport type { Key } from './keys.js';\nimport type { Size } from './screen.js';\n\nconst ESC = String.fromCharCode(27);\nconst CSI = `${ESC}[`;\n\n/** The escape codes a full-screen CLI actually needs. */\nexport const codes = {\n altScreenOn: `${CSI}?1049h`,\n altScreenOff: `${CSI}?1049l`,\n hideCursor: `${CSI}?25l`,\n showCursor: `${CSI}?25h`,\n home: `${CSI}H`,\n clearLine: `${CSI}K`,\n clearBelow: `${CSI}J`,\n};\n\nexport interface TerminalOptions {\n stdout?: NodeJS.WriteStream;\n stdin?: NodeJS.ReadStream;\n}\n\n/**\n * Drives a full-screen view over plain ANSI: enter the alternate screen buffer (so the user's\n * scrollback survives), then repaint by homing the cursor and clearing to end-of-line per row.\n * No clear-then-draw, so there is no flicker, and no framework.\n */\nexport class Terminal {\n readonly #stdout: NodeJS.WriteStream;\n readonly #stdin: NodeJS.ReadStream;\n #lastFrame: string[] = [];\n #active = false;\n #onKey?: (key: Key) => void;\n #onResize?: () => void;\n #keyListener?: (str: string | undefined, key: readline.Key) => void;\n #resizeListener?: () => void;\n\n constructor(options: TerminalOptions = {}) {\n this.#stdout = options.stdout ?? process.stdout;\n this.#stdin = options.stdin ?? process.stdin;\n }\n\n get size(): Size {\n return {\n columns: Math.max(40, this.#stdout.columns ?? 80),\n rows: Math.max(10, this.#stdout.rows ?? 24),\n };\n }\n\n start(handlers: { onKey: (key: Key) => void; onResize?: () => void }): void {\n if (this.#active) return;\n this.#active = true;\n this.#onKey = handlers.onKey;\n if (handlers.onResize) this.#onResize = handlers.onResize;\n\n this.#stdout.write(codes.altScreenOn + codes.hideCursor);\n\n readline.emitKeypressEvents(this.#stdin);\n if (this.#stdin.isTTY) this.#stdin.setRawMode(true);\n this.#stdin.resume();\n\n this.#keyListener = (_str, key) => {\n if (!key) return;\n this.#onKey?.({\n name: key.name ?? key.sequence ?? '',\n ...(key.ctrl ? { ctrl: true } : {}),\n ...(key.shift ? { shift: true } : {}),\n });\n };\n this.#stdin.on('keypress', this.#keyListener);\n\n this.#resizeListener = () => {\n this.#lastFrame = []; // force a full repaint at the new width\n this.#onResize?.();\n };\n this.#stdout.on('resize', this.#resizeListener);\n }\n\n /** Repaints only the lines that changed. */\n paint(lines: string[]): void {\n if (!this.#active) return;\n const { rows, columns } = this.size;\n const frame = lines.slice(0, rows - 1).map((line) => clip(line, columns));\n\n let output = codes.home;\n const height = Math.max(frame.length, this.#lastFrame.length);\n\n for (let index = 0; index < height; index += 1) {\n const line = frame[index] ?? '';\n if (this.#lastFrame[index] === line) {\n output += `${CSI}${index + 2};1H`; // nothing changed: skip to the next row\n continue;\n }\n output += `${CSI}${index + 1};1H${line}${codes.clearLine}`;\n }\n\n output += codes.clearBelow;\n this.#stdout.write(output);\n this.#lastFrame = frame;\n }\n\n stop(): void {\n if (!this.#active) return;\n this.#active = false;\n\n if (this.#keyListener) this.#stdin.off('keypress', this.#keyListener);\n if (this.#resizeListener) this.#stdout.off('resize', this.#resizeListener);\n if (this.#stdin.isTTY) this.#stdin.setRawMode(false);\n this.#stdin.pause();\n\n this.#stdout.write(codes.showCursor + codes.altScreenOff);\n this.#lastFrame = [];\n }\n}\n\n/** Trims a line to the terminal width without counting the invisible colour codes. */\nexport const clip = (line: string, columns: number): string => {\n const visible = stripAnsi(line).length;\n if (visible <= columns) return line;\n\n let out = '';\n let width = 0;\n let index = 0;\n while (index < line.length && width < columns) {\n if (line[index] === ESC) {\n const end = line.indexOf('m', index);\n if (end === -1) break;\n out += line.slice(index, end + 1);\n index = end + 1;\n continue;\n }\n out += line[index];\n width += 1;\n index += 1;\n }\n return out;\n};\n","import type { EventBus } from '../core/events/bus.js';\nimport type { Supervisor } from '../core/process/supervisor.js';\nimport { createPainter, supportsColor, type ColorName } from '../cli/render/colors.js';\nimport { buildStackView, logsFor, mergedLogs } from './model.js';\nimport { handleKey, type Command } from './keys.js';\nimport { initialUiState, renderFrame, type Painter, type UiState } from './screen.js';\nimport { Terminal } from './terminal.js';\nimport { glyphs } from './theme.js';\n\nexport interface TuiOptions {\n stdout?: NodeJS.WriteStream;\n stdin?: NodeJS.ReadStream;\n env?: NodeJS.ProcessEnv;\n /** Repaint interval. 250ms keeps uptime ticking without burning CPU. */\n frameMs?: number;\n}\n\nconst MAX_LOG_LINES = 400;\n\n/**\n * The whole UI: poll the supervisor, render a frame, handle keys. Deliberately a loop and not\n * an event stream — a worker emitting 500 lines/s must not cause 500 repaints.\n */\nexport const runTui = async (\n supervisor: Supervisor,\n bus: EventBus,\n options: TuiOptions = {},\n): Promise<number> => {\n const env = options.env ?? process.env;\n const stdout = options.stdout ?? process.stdout;\n const terminal = new Terminal({\n stdout,\n ...(options.stdin ? { stdin: options.stdin } : {}),\n });\n\n const basePainter = createPainter(supportsColor(stdout, env));\n const paint: Painter = Object.assign(\n (color: string, text: string) => basePainter(color as ColorName, text),\n { enabled: basePainter.enabled },\n );\n\n const glyph = glyphs(env);\n const startedAt = Date.now();\n\n let ui: UiState = initialUiState();\n let exitCode = 0;\n let stopping = false;\n let finished = false;\n\n const setNote = (note: string): void => {\n ui = { ...ui, note };\n };\n\n // Lifecycle events become the one-line status note; log events are ignored here on purpose.\n const unsubscribe = bus.subscribe((event) => {\n switch (event.type) {\n case 'stack:ready':\n ui = { ...ui, phase: 'running' };\n setNote(`Ready in ${(event.durationMs / 1000).toFixed(1)}s. Awaiting keyboard input…`);\n break;\n case 'service:restart':\n setNote(`${event.service} restarting in ${event.delayMs}ms (attempt ${event.attempt}/${event.maxAttempts})`);\n break;\n case 'service:exit':\n if (!event.intentional) {\n setNote(`${event.service} exited with ${event.signal ? `signal ${event.signal}` : `code ${event.code}`}`);\n }\n break;\n case 'notice':\n if (event.level !== 'info') setNote(`${event.service ? `${event.service}: ` : ''}${event.message}`);\n break;\n default:\n break;\n }\n });\n\n const draw = (): void => {\n const stack = buildStackView(supervisor);\n const selectedRow = stack.rows[ui.selected];\n\n const logs =\n ui.view === 'log' && selectedRow\n ? logsFor(supervisor, selectedRow.name, MAX_LOG_LINES)\n : ui.view === 'merged'\n ? mergedLogs(supervisor, MAX_LOG_LINES)\n : [];\n\n terminal.paint(\n renderFrame({\n stack,\n ui,\n size: terminal.size,\n glyph,\n paint,\n logs,\n uptimeMs: Date.now() - startedAt,\n }),\n );\n };\n\n const shutdown = async (reason: string): Promise<void> => {\n if (stopping) return;\n stopping = true;\n ui = { ...ui, phase: 'stopping' };\n draw();\n await supervisor.down(reason);\n finished = true;\n };\n\n const perform = (command: Command): void => {\n const stack = buildStackView(supervisor);\n const row = stack.rows['index' in command ? command.index : ui.selected];\n\n switch (command.type) {\n case 'quit':\n void shutdown('user quit');\n break;\n\n case 'force-quit':\n // Second ctrl-c during shutdown: stop waiting.\n terminal.stop();\n process.exit(130);\n break;\n\n case 'restart':\n if (!row) break;\n setNote(`restarting ${row.name}…`);\n void supervisor\n .restart(row.name)\n .then(() => setNote(`${row.name} restarted`))\n .catch((error: unknown) => setNote(`restart failed: ${error instanceof Error ? error.message : String(error)}`));\n break;\n\n case 'restart-running':\n setNote('restarting every running process…');\n void supervisor\n .restartRunning()\n .then((names) =>\n setNote(\n names.length === 0\n ? 'nothing is running — nothing to restart'\n : `restarted ${names.length} process${names.length === 1 ? '' : 'es'}: ${names.join(', ')}`,\n ),\n )\n .catch((error: unknown) => setNote(`restart failed: ${error instanceof Error ? error.message : String(error)}`));\n break;\n\n case 'toggle': {\n if (!row) break;\n if (row.external) {\n setNote(`${row.name} is external — laracrew does not start or stop it`);\n break;\n }\n const live = row.state === 'running' || row.state === 'ready' || row.state === 'starting';\n setNote(`${live ? 'stopping' : 'starting'} ${row.name}…`);\n const action = live ? supervisor.stopService(row.name) : supervisor.startService(row.name);\n void action\n .then(() => setNote(`${row.name} ${live ? 'stopped' : 'started'}`))\n .catch((error: unknown) => setNote(error instanceof Error ? error.message : String(error)));\n break;\n }\n\n default:\n break;\n }\n };\n\n terminal.start({\n onKey: (key) => {\n // Externals are not in the selectable list, so bound by managed rows only.\n const rowCount = buildStackView(supervisor).rows.length;\n const result = handleKey(ui, key, rowCount);\n ui = result.ui;\n perform(result.command);\n draw();\n },\n onResize: draw,\n });\n\n const timer = setInterval(draw, options.frameMs ?? 250);\n timer.unref?.();\n\n const onSignal = (): void => {\n void shutdown('received signal');\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n draw();\n\n try {\n await supervisor.up();\n } catch (error) {\n ui = { ...ui, phase: 'running' };\n setNote(error instanceof Error ? error.message : String(error));\n exitCode = 1;\n draw();\n }\n\n // Idle until the user quits or every service has finished on its own.\n await new Promise<void>((resolve) => {\n const check = setInterval(() => {\n if (finished) {\n clearInterval(check);\n resolve();\n return;\n }\n if (stopping) return;\n const anyLive = supervisor.processes.some(\n (managed) => managed.state !== 'stopped' && managed.state !== 'failed',\n );\n if (!anyLive) {\n clearInterval(check);\n void shutdown('all services finished').then(resolve);\n }\n }, 200);\n check.unref?.();\n });\n\n clearInterval(timer);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n unsubscribe();\n terminal.stop();\n\n return exitCode;\n};\n","import { EventBus } from '../../core/events/bus.js';\nimport { loadSharedProjects, loadStack } from '../../core/config/load.js';\nimport { resolveStack, type ResolvedStack } from '../../core/config/resolve.js';\nimport { Supervisor } from '../../core/process/supervisor.js';\nimport { attachPlainRenderer } from '../render/plain.js';\nimport { paint } from '../render/colors.js';\nimport { onOutputClosed, write as safeWrite } from '../render/output.js';\nimport { runTui } from '../../tui/app.js';\n\nexport interface UpOptions {\n only?: string[];\n except?: string[];\n profile?: string;\n plain?: boolean;\n json?: boolean;\n env?: NodeJS.ProcessEnv;\n}\n\nconst splitList = (values: string[] | undefined): string[] =>\n (values ?? []).flatMap((value) => value.split(',')).map((value) => value.trim()).filter(Boolean);\n\nexport const prepareStack = (name: string, options: UpOptions = {}): ResolvedStack => {\n const env = options.env ?? process.env;\n const loaded = loadStack(name, env);\n return resolveStack(loaded, {\n sharedProjects: loadSharedProjects(env),\n env,\n ...(options.profile ? { profile: options.profile } : {}),\n only: splitList(options.only),\n except: splitList(options.except),\n });\n};\n\nconst attachJsonRenderer = (bus: EventBus): (() => void) =>\n bus.subscribe((event) => process.stdout.write(`${JSON.stringify(event)}\\n`));\n\n/**\n * Boots a stack and keeps running until the fleet stops or the user interrupts.\n * The TUI lands in M2; until then every run uses the plain renderer.\n */\n/** The TUI is the default, but only when there is a real terminal to draw on. */\nexport const shouldUseTui = (options: UpOptions, stdout: { isTTY?: boolean } = process.stdout): boolean =>\n !options.plain && !options.json && Boolean(stdout.isTTY);\n\nexport const upCommand = async (name: string, options: UpOptions = {}): Promise<number> => {\n const stack = prepareStack(name, options);\n const bus = new EventBus();\n\n if (shouldUseTui(options)) {\n const supervisor = new Supervisor(stack, bus, options.env ? { env: options.env } : {});\n return runTui(supervisor, bus, options.env ? { env: options.env } : {});\n }\n\n const detach = options.json ? attachJsonRenderer(bus) : attachPlainRenderer(bus, { stack });\n\n const supervisor = new Supervisor(stack, bus, options.env ? { env: options.env } : {});\n\n let exitCode = 0;\n let stopping = false;\n\n const shutdown = async (reason: string): Promise<void> => {\n if (stopping) return;\n stopping = true;\n await supervisor.down(reason);\n };\n\n const onSignal = (signal: NodeJS.Signals) => {\n if (stopping) {\n // Second interrupt: the user is done being patient.\n console.error(paint('red', '\\nforced exit — some children may survive'));\n process.exit(130);\n }\n void shutdown(`received ${signal}`);\n };\n\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n // `laracrew up --json | head` closes the pipe; that is a request to stop, not a crash.\n const releaseOutputHook = onOutputClosed(() => {\n void shutdown('output closed');\n });\n\n try {\n await supervisor.up();\n await waitUntilIdle(supervisor, () => stopping);\n } catch (error) {\n console.error(paint('red', error instanceof Error ? error.message : String(error)));\n exitCode = 1;\n } finally {\n await shutdown('done');\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n releaseOutputHook();\n detach();\n }\n\n return exitCode;\n};\n\n/** Resolves when every service has reached a terminal state, or a stop was requested. */\nconst waitUntilIdle = (supervisor: Supervisor, stopRequested: () => boolean): Promise<void> =>\n new Promise((resolve) => {\n const check = () => {\n if (stopRequested()) {\n clearInterval(timer);\n resolve();\n return;\n }\n const anyLive = supervisor.processes.some(\n (process) => process.state !== 'stopped' && process.state !== 'failed',\n );\n if (!anyLive) {\n clearInterval(timer);\n resolve();\n }\n };\n const timer = setInterval(check, 250);\n timer.unref?.();\n });\n","import { mkdirSync, writeFileSync, existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { paths } from '../../core/config/paths.js';\nimport { paint } from '../render/colors.js';\nimport {\n CONFIG_YAML,\n EXAMPLE_STACK_YAML,\n HOME_README,\n PROJECTS_YAML,\n REAL_STACK_TEMPLATE,\n RESET_TASK_YAML,\n} from './templates.js';\n\nexport interface InitOptions {\n /** Also write the demo stack, the two-project template and the sample task. */\n examples?: boolean;\n}\n\nexport interface InitResult {\n root: string;\n created: string[];\n skipped: string[];\n examples: boolean;\n}\n\n/** Idempotent: re-running never overwrites something you edited. */\nexport const runInit = (env: NodeJS.ProcessEnv = process.env, options: InitOptions = {}): InitResult => {\n const home = paths(env);\n const created: string[] = [];\n const skipped: string[] = [];\n\n for (const dir of [home.root, home.stacksDir, home.tasksDir, home.fragmentsDir, home.logsDir, home.runDir]) {\n mkdirSync(dir, { recursive: true });\n }\n\n const files: [string, string][] = [\n [home.configFile, CONFIG_YAML],\n [home.projectsFile, PROJECTS_YAML],\n [path.join(home.root, 'README.md'), HOME_README],\n ];\n\n if (options.examples) {\n mkdirSync(path.join(home.stacksDir, 'example'), { recursive: true });\n mkdirSync(path.join(home.stacksDir, 'dual'), { recursive: true });\n files.push(\n [path.join(home.stacksDir, 'example', 'stack.yaml'), EXAMPLE_STACK_YAML],\n [path.join(home.stacksDir, 'dual', 'stack.yaml'), REAL_STACK_TEMPLATE],\n [path.join(home.tasksDir, 'reset.yaml'), RESET_TASK_YAML],\n );\n }\n\n for (const [file, contents] of files) {\n if (existsSync(file)) {\n skipped.push(file);\n continue;\n }\n writeFileSync(file, contents, 'utf8');\n created.push(file);\n }\n\n return { root: home.root, created, skipped, examples: options.examples ?? false };\n};\n\nexport const initCommand = (options: InitOptions = {}, env: NodeJS.ProcessEnv = process.env): void => {\n const result = runInit(env, options);\n\n console.log(`${paint('bold', 'laracrew')} home: ${result.root}`);\n for (const file of result.created) console.log(` ${paint('green', '+')} ${path.relative(result.root, file)}`);\n for (const file of result.skipped) {\n console.log(` ${paint('gray', '·')} ${path.relative(result.root, file)} ${paint('gray', '(kept)')}`);\n }\n\n if (result.examples) {\n console.log(`\n${paint('bold', 'Next:')}\n ${paint('cyan', 'laracrew up example')} run the demo stack — proves it works, no Laravel needed\n ${paint('cyan', 'laracrew link example')} install it as a global command you can type from anywhere\n edit ${paint('gray', path.join(result.root, 'projects.yaml'))} with your project paths,\n then ${paint('cyan', 'laracrew doctor dual')} and ${paint('cyan', 'laracrew up dual')}\n`);\n return;\n }\n\n console.log(`\n${paint('bold', 'Next:')}\n ${paint('cyan', 'laracrew init --examples')} add a runnable demo stack and a two-project template\n or write your own at ${paint('gray', path.join(result.root, 'stacks', '<name>', 'stack.yaml'))}\n then ${paint('cyan', 'laracrew ls')} and ${paint('cyan', 'laracrew up <name>')}\n`);\n};\n","/**\n * Kept as string constants rather than shipped files: no path resolution to get wrong\n * between `tsx src/index.ts` and the bundled `dist/index.js`, and nothing to forget in\n * package.json#files.\n */\n\nexport const CONFIG_YAML = `# laracrew global preferences\n# theme: auto | dark | light | mono | high-contrast\ntheme: auto\n\n# Polling interval for queue depth and stream lag, in milliseconds.\nmetricsIntervalMs: 2000\n\n# The stack \\`laracrew up\\` boots when you don't name one.\n# defaultStack: dual\n`;\n\nexport const PROJECTS_YAML = `# Your projects, referenced by key from any stack. A project is just a root directory\n# plus the defaults its services inherit — cwd, .env and colour. Any language.\n# Paths may use forward slashes on Windows.\n#\n# Declaring projects here is optional: a service can carry its own \\`cwd\\` instead.\nprojects: {}\n\n# Example — delete the \\`{}\\` above and uncomment:\n#\n# projects:\n# api:\n# path: D:/work/api\n# php: php # only used by \\`stop: { artisan: ... }\\`; ignore it for non-PHP projects\n# envFile: .env # read for \\${project.env:KEY} tokens, and by \\`doctor\\`\n# color: cyan\n# web:\n# path: D:/work/web\n# envFile: .env\n# color: magenta\n`;\n\n/** A stack that actually runs on a fresh install, so `laracrew up example` works immediately. */\nexport const EXAMPLE_STACK_YAML = `# A runnable demo stack — no Laravel project required.\n# Try: laracrew up example\n# Then: laracrew up example --only workers\nname: example\ndescription: Three fake services that prove laracrew works on this machine\n\n# \\`laracrew link example\\` installs this as a global command you can run from anywhere.\ncommand: demo\n\ndefaults:\n restart: on-failure\n backoff: { initialMs: 500, maxMs: 5000, factor: 2, maxRestarts: 5 }\n stop: { graceMs: 5000 }\n\nservices:\n - name: demo:heartbeat\n cmd: [\"node\", \"-e\", \"let n=0; setInterval(() => console.log('heartbeat ' + (++n)), 1000)\"]\n groups: [workers]\n color: cyan\n\n - name: demo:worker\n cmd: [\"node\", \"-e\", \"let n=0; setInterval(() => console.log('processed job #' + (++n)), 1700)\"]\n groups: [workers]\n needs: [demo:heartbeat]\n color: magenta\n\n - name: demo:slow-starter\n cmd: [\"node\", \"-e\", \"setTimeout(() => console.log('listening on 9'), 1200); setInterval(() => {}, 1000)\"]\n groups: [http]\n ready: { logMatch: \"listening on\", timeoutMs: 10000 }\n color: green\n\nprofiles:\n quiet:\n except: [http]\n`;\n\nexport const REAL_STACK_TEMPLATE = `# Two interconnected Laravel projects: queues, Redis stream listeners, schedulers.\n# Fill in the project paths in ~/.laracrew/projects.yaml first, then: laracrew up dual\nname: dual\ndescription: API + Portal with queues, streams and schedulers\n\n# Run \\`laracrew link dual\\` and this whole set boots by typing \\`dual\\` from anywhere.\ncommand: dual\n\nuse: [api, portal]\n\ndefaults:\n restart: on-failure\n backoff: { initialMs: 1000, maxMs: 30000, factor: 2, maxRestarts: 10 }\n stop: { graceMs: 10000 }\n logs: { maxLines: 5000, toFile: false }\n\nservices:\n - name: redis\n external: true # laracrew checks it, never starts it\n ready: { tcp: \"127.0.0.1:6379\" }\n\n - name: api:serve\n project: api\n cmd: php artisan serve --port=\\${port:8000}\n groups: [http]\n needs: [redis]\n ready: { http: \"http://127.0.0.1:8000/up\", timeoutMs: 20000 }\n url: http://127.0.0.1:8000\n\n - name: api:queue\n project: api\n cmd: php artisan queue:work redis --queue=high,default --tries=3 --timeout=90\n groups: [workers]\n needs: [redis]\n stop: { artisan: \"queue:restart\", graceMs: 15000 }\n watch:\n paths: [app, config, routes, database]\n strategy: artisan-queue-restart\n debounceMs: 800\n metrics:\n queues: [high, default]\n\n - name: api:streams\n project: api\n cmd: php artisan streams:listen orders\n groups: [workers, streams]\n needs: [redis]\n metrics:\n streams:\n - { key: orders, group: api-consumers }\n\n - name: api:schedule\n project: api\n cmd: php artisan schedule:work\n groups: [workers]\n needs: [redis]\n\n - name: portal:serve\n project: portal\n cmd: php artisan serve --port=\\${port:8001}\n groups: [http]\n needs: [redis, api:serve] # don't boot until the API answers\n ready: { http: \"http://127.0.0.1:8001/up\", timeoutMs: 20000 }\n url: http://127.0.0.1:8001\n\n - name: portal:queue\n project: portal\n cmd: php artisan queue:work redis --queue=default --tries=3\n groups: [workers]\n needs: [redis, api:serve]\n stop: { artisan: \"queue:restart\" }\n watch: { paths: [app, config], strategy: artisan-queue-restart }\n metrics: { queues: [default] }\n\n - name: portal:streams\n project: portal\n cmd: php artisan streams:listen inventory\n groups: [workers, streams]\n needs: [redis]\n metrics:\n streams:\n - { key: inventory, group: portal-consumers }\n\nprofiles:\n light:\n except: [assets]\n workers-only:\n only: [workers]\n`;\n\nexport const RESET_TASK_YAML = `# laracrew run reset\nname: reset\ndescription: Wipe and reseed both databases in the right order\npauseServices: [workers] # stopped before the steps, restarted after\nsteps:\n - { project: api, cmd: php artisan migrate:fresh --seed }\n - { project: portal, cmd: php artisan migrate:fresh --seed }\n - parallel:\n - { project: api, cmd: php artisan cache:clear }\n - { project: portal, cmd: php artisan cache:clear }\n`;\n\nexport const HOME_README = `# ~/.laracrew\n\nYour laracrew configuration. Safe to keep in git — nothing here is secret unless you put\nsecrets in it.\n\n config.yaml global preferences\n projects.yaml your Laravel projects, referenced by key\n stacks/<name>/ one folder per stack; stack.yaml is the definition\n tasks/<name>.yaml one-shot sequences (laracrew run <name>)\n fragments/ shared YAML any stack can reuse\n logs/ per-run log files, when defaults.logs.toFile is on\n\nStart here:\n\n laracrew init --examples # add a demo stack and a two-project template\n laracrew ls # what is defined\n laracrew doctor <stack> # check a stack before booting it\n laracrew link <stack> # give a stack its own global command\n`;\n","import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { ConfigError } from '../../core/config/errors.js';\nimport { listStacks, loadStack } from '../../core/config/load.js';\nimport { paths } from '../../core/config/paths.js';\nimport { paint } from '../render/colors.js';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\n/** Stamped into every generated file so we never overwrite something we did not write. */\nexport const MARKER = 'laracrew-generated';\n\nconst RESERVED = new Set(['laracrew', 'node', 'npm', 'npx', 'php', 'git', 'cd', 'ls', 'rm', 'sh', 'bash']);\nconst VALID_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;\n\nexport interface ShimTarget {\n /** Absolute path to the node binary that should run laracrew. */\n node: string;\n /** Absolute path to laracrew's entry script. */\n entry: string;\n stack: string;\n}\n\n/**\n * The script the shim must hand to node. This is `process.argv[1]` — the entry Node was\n * actually given — not a path derived from this module's own location: tsup bundles the\n * whole program into one file, so any relative walk from here is wrong in a build.\n */\nexport const entryScript = (argv: string[] = process.argv): string => {\n const main = argv[1];\n if (!main) return fileURLToPath(import.meta.url);\n\n const resolved = path.resolve(main);\n if (!resolved.endsWith('.ts')) return resolved;\n\n // Running from TypeScript source (`npm run dev`): a shim cannot invoke .ts with plain\n // node, so point it at the built bundle instead.\n const dist = path.join(path.dirname(path.dirname(resolved)), 'dist', 'index.js');\n if (existsSync(dist)) return dist;\n\n throw new ConfigError('run `npm run build` first — a generated command has to point at dist/index.js');\n};\n\n/** Where laracrew is running from — embedded in the shim so PATH changes can't break it. */\nexport const currentTarget = (stack: string): ShimTarget => ({\n node: process.execPath,\n entry: entryScript(),\n stack,\n});\n\nconst forward = (value: string): string => value.replace(/\\\\/g, '/');\n\nexport const shShim = ({ node, entry, stack }: ShimTarget): string =>\n `#!/bin/sh\n# ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\nexec \"${forward(node)}\" \"${forward(entry)}\" up ${stack} \"$@\"\n`;\n\nexport const cmdShim = ({ node, entry, stack }: ShimTarget): string =>\n `@ECHO OFF\\r\nREM ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\\r\n\"${node}\" \"${entry}\" up ${stack} %*\\r\n`;\n\nexport const ps1Shim = ({ node, entry, stack }: ShimTarget): string =>\n `#!/usr/bin/env pwsh\n# ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\n& \"${node}\" \"${entry}\" up ${stack} @args\nexit $LASTEXITCODE\n`;\n\n/** The files one command needs: three on Windows (sh, cmd, PowerShell), one elsewhere. */\nexport const shimFiles = (name: string, target: ShimTarget): { file: string; contents: string; exec: boolean }[] => {\n const posix = { file: name, contents: shShim(target), exec: true };\n if (!IS_WINDOWS) return [posix];\n return [\n posix, // Git Bash reads the extensionless file\n { file: `${name}.cmd`, contents: cmdShim(target), exec: false },\n { file: `${name}.ps1`, contents: ps1Shim(target), exec: true },\n ];\n};\n\nconst pathDirs = (env: NodeJS.ProcessEnv): string[] =>\n (env.PATH ?? env.Path ?? '').split(path.delimiter).filter(Boolean);\n\nconst samePath = (a: string, b: string): boolean =>\n IS_WINDOWS ? a.toLowerCase() === b.toLowerCase() : a === b;\n\n/** The directory on PATH that holds the `laracrew` command itself. */\nconst ownBinDir = (env: NodeJS.ProcessEnv): string | undefined => {\n for (const dir of pathDirs(env)) {\n for (const candidate of IS_WINDOWS ? ['laracrew.cmd', 'laracrew'] : ['laracrew']) {\n try {\n if (existsSync(path.join(dir, candidate))) return dir;\n } catch {\n // An unreadable PATH entry is not our problem.\n }\n }\n }\n return undefined;\n};\n\n/**\n * Wherever `laracrew` itself lives is by definition on PATH and writable by whoever\n * installed it, so sibling commands belong there. Asking npm for its prefix would mean\n * spawning npm on every call — slower, and it trips Node's shell-argument deprecation.\n */\nexport const resolveBinDir = (env: NodeJS.ProcessEnv = process.env): { dir: string; onPath: boolean } => {\n if (env.LARACREW_BIN) return { dir: path.resolve(env.LARACREW_BIN), onPath: true };\n\n const own = ownBinDir(env);\n if (own) return { dir: own, onPath: true };\n\n // Not installed globally (running from source): try npm's default prefix.\n const conventional = IS_WINDOWS\n ? env.APPDATA\n ? path.join(env.APPDATA, 'npm')\n : undefined\n : path.dirname(process.execPath);\n\n if (conventional && existsSync(conventional) && pathDirs(env).some((dir) => samePath(dir, conventional))) {\n return { dir: conventional, onPath: true };\n }\n\n return { dir: path.join(paths(env).root, 'bin'), onPath: false };\n};\n\nconst isOurs = (file: string): boolean => {\n try {\n return readFileSync(file, 'utf8').includes(MARKER);\n } catch {\n return false;\n }\n};\n\nexport interface LinkResult {\n name: string;\n stack: string;\n dir: string;\n onPath: boolean;\n files: string[];\n replaced: boolean;\n}\n\nexport const linkStack = (\n stackName: string,\n options: { as?: string; dir?: string; force?: boolean; env?: NodeJS.ProcessEnv } = {},\n): LinkResult => {\n const env = options.env ?? process.env;\n const { config } = loadStack(stackName, env); // validates before we create anything\n\n const name = options.as ?? config.command ?? stackName;\n\n if (!VALID_NAME.test(name)) {\n throw new ConfigError(\n `\"${name}\" is not a usable command name — letters, digits, dot, dash and underscore only`,\n );\n }\n if (RESERVED.has(name.toLowerCase()) && !options.force) {\n throw new ConfigError(`\"${name}\" would shadow an important command`, {\n details: ['pick another with `--as <name>`, or pass --force if you really mean it'],\n });\n }\n\n const resolved = options.dir ? { dir: path.resolve(options.dir), onPath: true } : resolveBinDir(env);\n mkdirSync(resolved.dir, { recursive: true });\n\n const target = currentTarget(stackName);\n const planned = shimFiles(name, target);\n\n let replaced = false;\n for (const { file } of planned) {\n const full = path.join(resolved.dir, file);\n if (!existsSync(full)) continue;\n if (isOurs(full)) {\n replaced = true;\n continue;\n }\n if (!options.force) {\n throw new ConfigError(`\"${full}\" already exists and was not created by laracrew`, {\n details: ['choose another name with `--as <name>`, or pass --force to overwrite'],\n });\n }\n replaced = true;\n }\n\n const written: string[] = [];\n for (const { file, contents, exec } of planned) {\n const full = path.join(resolved.dir, file);\n writeFileSync(full, contents, 'utf8');\n if (exec && !IS_WINDOWS) chmodSync(full, 0o755);\n else if (exec) {\n try {\n chmodSync(full, 0o755);\n } catch {\n // Windows ignores the mode; Git Bash still honours the shebang.\n }\n }\n written.push(full);\n }\n\n return { name, stack: stackName, dir: resolved.dir, onPath: resolved.onPath, files: written, replaced };\n};\n\nexport const unlinkCommandName = (\n name: string,\n options: { dir?: string; env?: NodeJS.ProcessEnv } = {},\n): string[] => {\n const env = options.env ?? process.env;\n const dir = options.dir ? path.resolve(options.dir) : resolveBinDir(env).dir;\n\n const removed: string[] = [];\n for (const candidate of [name, `${name}.cmd`, `${name}.ps1`]) {\n const full = path.join(dir, candidate);\n if (!existsSync(full)) continue;\n if (!isOurs(full)) {\n throw new ConfigError(`\"${full}\" was not created by laracrew — leaving it alone`);\n }\n unlinkSync(full);\n removed.push(full);\n }\n\n if (removed.length === 0) throw new ConfigError(`no laracrew command named \"${name}\" in ${dir}`);\n return removed;\n};\n\nexport interface InstalledLink {\n name: string;\n stack: string;\n file: string;\n}\n\n/** Every command in the bin directory that laracrew generated. */\nexport const listLinks = (options: { dir?: string; env?: NodeJS.ProcessEnv } = {}): InstalledLink[] => {\n const env = options.env ?? process.env;\n const dir = options.dir ? path.resolve(options.dir) : resolveBinDir(env).dir;\n if (!existsSync(dir)) return [];\n\n const found: InstalledLink[] = [];\n for (const entry of readdirSync(dir).sort()) {\n if (entry.endsWith('.cmd') || entry.endsWith('.ps1')) continue;\n const full = path.join(dir, entry);\n let contents: string;\n try {\n contents = readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n if (!contents.includes(MARKER)) continue;\n const stack = /\\bup ([^\\s\"]+)/.exec(contents)?.[1];\n if (stack) found.push({ name: entry, stack, file: full });\n }\n return found;\n};\n\nexport const linkCommand = (\n stackName: string | undefined,\n options: { as?: string; dir?: string; force?: boolean; all?: boolean },\n env: NodeJS.ProcessEnv = process.env,\n): number => {\n const stacks = options.all ? listStacks(env) : stackName ? [stackName] : [];\n if (stacks.length === 0) {\n throw new ConfigError('name a stack to link, or pass --all');\n }\n\n const results: LinkResult[] = [];\n for (const stack of stacks) {\n // With --all, a stack that opts out by having no `command:` is skipped rather than\n // silently claiming a global name derived from its folder.\n if (options.all) {\n const { config } = loadStack(stack, env);\n if (!config.command) continue;\n }\n results.push(\n linkStack(stack, {\n ...(options.as ? { as: options.as } : {}),\n ...(options.dir ? { dir: options.dir } : {}),\n ...(options.force ? { force: options.force } : {}),\n env,\n }),\n );\n }\n\n if (results.length === 0) {\n console.log(paint('yellow', 'nothing to link — add `command: <name>` to the stacks you want a command for'));\n return 0;\n }\n\n for (const result of results) {\n const verb = result.replaced ? 'updated' : 'created';\n console.log(\n `${paint('green', verb)} ${paint('bold', result.name)} ${paint('gray', `-> laracrew up ${result.stack}`)}`,\n );\n }\n\n const first = results[0]!;\n console.log(paint('gray', `\\nin ${first.dir}`));\n\n if (!first.onPath) {\n console.log(\n `\\n${paint('yellow', 'that directory is not on your PATH.')} Add it once:\\n` +\n (IS_WINDOWS\n ? ` ${paint('cyan', `setx PATH \"%PATH%;${first.dir}\"`)} ${paint('gray', '(then reopen the terminal)')}`\n : ` ${paint('cyan', `echo 'export PATH=\"$PATH:${first.dir}\"' >> ~/.bashrc`)}`),\n );\n } else {\n console.log(`\\nRun it from anywhere: ${paint('cyan', first.name)}`);\n console.log(paint('gray', `Flags pass straight through: ${first.name} --only workers`));\n }\n\n return 0;\n};\n\nexport const unlinkCommandAction = (name: string, env: NodeJS.ProcessEnv = process.env): number => {\n const removed = unlinkCommandName(name, { env });\n for (const file of removed) console.log(`${paint('red', 'removed')} ${file}`);\n return 0;\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport path from 'node:path';\nimport { ConfigError, didYouMean } from '../../core/config/errors.js';\nimport { paths } from '../../core/config/paths.js';\nimport { fileNamesFor } from '../../core/logs/file-sink.js';\nimport { followFile, parseSince, tailFile, toEntries } from '../../core/logs/read.js';\nimport type { LogLine } from '../../core/events/types.js';\nimport { asColorName, padEnd, paint } from '../render/colors.js';\nimport { write as safeWrite } from '../render/output.js';\nimport { prepareStack } from './up.js';\n\nexport interface LogsOptions {\n stack?: string;\n lines?: number;\n follow?: boolean;\n since?: string;\n all?: boolean;\n list?: boolean;\n env?: NodeJS.ProcessEnv;\n}\n\nexport const logDirFor = (stackName: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).logsDir, stackName);\n\ninterface Target {\n service: string;\n file: string;\n color: string;\n}\n\n/** Every service of a stack that has a log file on disk. */\nexport const targetsFor = (stackName: string, env: NodeJS.ProcessEnv = process.env): Target[] => {\n const stack = prepareStack(stackName, { env });\n const dir = logDirFor(stackName, env);\n const names = fileNamesFor(stack.services.map((service) => service.name));\n\n return stack.services\n .map((service) => ({\n service: service.name,\n file: path.join(dir, names.get(service.name)!),\n color: service.color,\n }))\n .filter((target) => existsSync(target.file));\n};\n\nconst formatEntry = (entry: LogLine, width: number, withName: boolean): string => {\n const time = new Date(entry.at || Date.now());\n const clock = [time.getHours(), time.getMinutes(), time.getSeconds()]\n .map((part) => String(part).padStart(2, '0'))\n .join(':');\n\n const who = withName ? `${paint(asColorName(undefined), padEnd(entry.service, width))} ` : '';\n const body = entry.stream === 'stderr' ? paint('red', entry.line) : entry.line;\n return `${paint('gray', clock)} ${who}${paint('gray', '|')} ${body}\\n`;\n};\n\nexport const logsCommand = async (service: string | undefined, options: LogsOptions = {}): Promise<number> => {\n const env = options.env ?? process.env;\n const stackName = options.stack;\n if (!stackName) throw new ConfigError('name a stack with --stack, or run `laracrew logs` from a known stack');\n\n const dir = logDirFor(stackName, env);\n const available = targetsFor(stackName, env);\n\n if (options.list) {\n if (available.length === 0) {\n console.log(paint('yellow', `no log files yet in ${dir}`));\n console.log(paint('gray', 'they appear once the stack has run at least once'));\n return 0;\n }\n console.log(paint('gray', dir));\n for (const target of available) {\n console.log(` ${paint('cyan', target.service)} ${paint('gray', path.basename(target.file))}`);\n }\n return 0;\n }\n\n if (available.length === 0) {\n console.error(paint('yellow', `no log files in ${dir}`));\n console.error(\n paint(\n 'gray',\n 'run the stack at least once, and check `defaults.logs.toFile` is not set to false',\n ),\n );\n return 1;\n }\n\n let selected: Target[];\n if (options.all || !service) {\n selected = available;\n } else {\n const match = available.find((target) => target.service === service);\n if (!match) {\n const suggestion = didYouMean(\n service,\n available.map((target) => target.service),\n );\n throw new ConfigError(\n `no log for service \"${service}\" in stack \"${stackName}\"` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { details: [`available: ${available.map((target) => target.service).join(', ')}`] },\n );\n }\n selected = [match];\n }\n\n const withName = selected.length > 1;\n const width = Math.max(...selected.map((target) => target.service.length));\n const limit = options.lines ?? 200;\n const since = options.since ? parseSince(options.since) : undefined;\n\n if (options.since && since === undefined) {\n throw new ConfigError(`could not read --since \"${options.since}\"`, {\n details: ['try a relative window like 10m, 2h, 1d, or an absolute date'],\n });\n }\n\n // History first, merged across services and ordered by time.\n const history: LogLine[] = [];\n for (const target of selected) {\n // When filtering by time we need a wider net than `limit`, since the matching lines\n // may be spread across a much longer file.\n history.push(...toEntries(target.service, tailFile(target.file, since ? Math.max(limit, 5_000) : limit)));\n }\n\n history.sort((a, b) => a.at - b.at);\n const filtered = since ? history.filter((entry) => entry.at >= since) : history;\n for (const entry of filtered.slice(-limit)) safeWrite(formatEntry(entry, width, withName));\n\n if (!options.follow) return 0;\n\n // Then tail.\n const controller = new AbortController();\n const stops = selected.map((target) =>\n followFile(target.file, {\n signal: controller.signal,\n onLines: (lines) => {\n for (const entry of toEntries(target.service, lines)) {\n safeWrite(formatEntry(entry, width, withName));\n }\n },\n }),\n );\n\n await new Promise<void>((resolve) => {\n const finish = (): void => {\n controller.abort();\n for (const stop of stops) stop();\n resolve();\n };\n process.once('SIGINT', finish);\n process.once('SIGTERM', finish);\n });\n\n return 0;\n};\n\n/** Stacks that have a log directory, for a helpful error when none is named. */\nexport const stacksWithLogs = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const root = paths(env).logsDir;\n if (!existsSync(root)) return [];\n return readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n};\n","import { openSync, readSync, closeSync, statSync, existsSync } from 'node:fs';\nimport type { LogLine } from '../events/types.js';\nimport { parseLine } from './file-sink.js';\n\n/**\n * Reading back what the sink wrote. Tailing reads from the end of the file rather than\n * loading it, so a rotated-but-still-large log does not cost a heap allocation.\n */\n\nconst CHUNK = 64 * 1024;\n\n/** The last `limit` lines of a file, oldest first, without reading the whole thing. */\nexport const tailFile = (file: string, limit: number): string[] => {\n if (!existsSync(file) || limit <= 0) return [];\n\n const size = statSync(file).size;\n if (size === 0) return [];\n\n const handle = openSync(file, 'r');\n try {\n let position = size;\n let text = '';\n let newlines = 0;\n\n while (position > 0 && newlines <= limit) {\n const length = Math.min(CHUNK, position);\n position -= length;\n\n const buffer = Buffer.alloc(length);\n readSync(handle, buffer, 0, length, position);\n const chunk = buffer.toString('utf8');\n\n text = chunk + text;\n newlines = 0;\n for (const character of text) if (character === '\\n') newlines += 1;\n }\n\n const lines = text.split('\\n');\n if (lines.at(-1) === '') lines.pop();\n return lines.slice(-limit);\n } finally {\n closeSync(handle);\n }\n};\n\n/** Turns raw file lines into log entries, keeping unparseable lines rather than dropping them. */\nexport const toEntries = (service: string, lines: readonly string[]): LogLine[] =>\n lines.map((raw) => {\n const parsed = parseLine(raw);\n if (!parsed) return { service, stream: 'stdout' as const, line: raw, at: 0 };\n return {\n service,\n stream: (parsed.stream === 'stderr' ? 'stderr' : parsed.stream === 'system' ? 'system' : 'stdout') as\n | 'stdout'\n | 'stderr'\n | 'system',\n line: parsed.line,\n at: parsed.at,\n };\n });\n\n/**\n * `10m`, `2h`, `90s`, `1d`, or anything `Date` understands. Returns a timestamp in ms.\n */\nexport const parseSince = (input: string): number | undefined => {\n const relative = /^(\\d+)\\s*(s|m|h|d)$/i.exec(input.trim());\n if (relative) {\n const amount = Number(relative[1]);\n const unit = relative[2]!.toLowerCase();\n const ms = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 }[unit] ?? 0;\n return Date.now() - amount * ms;\n }\n\n const absolute = new Date(input).getTime();\n return Number.isNaN(absolute) ? undefined : absolute;\n};\n\nexport interface FollowOptions {\n /** How often to check for new bytes. Polling is steadier than fs.watch across platforms. */\n intervalMs?: number;\n signal?: AbortSignal;\n onLines: (lines: string[]) => void;\n}\n\n/**\n * Watches a file for appended lines. Handles the file being rotated out from under us by\n * noticing the size shrank and starting again from the top.\n */\nexport const followFile = (file: string, options: FollowOptions): (() => void) => {\n let position = existsSync(file) ? statSync(file).size : 0;\n let carry = '';\n\n const read = (): void => {\n if (!existsSync(file)) return;\n\n const size = statSync(file).size;\n if (size === position) return;\n\n // Rotation: the file we were reading was renamed and a fresh one took its place.\n if (size < position) {\n position = 0;\n carry = '';\n }\n\n const length = size - position;\n const handle = openSync(file, 'r');\n try {\n const buffer = Buffer.alloc(length);\n readSync(handle, buffer, 0, length, position);\n position = size;\n\n const text = carry + buffer.toString('utf8');\n const lines = text.split('\\n');\n carry = lines.pop() ?? '';\n if (lines.length > 0) options.onLines(lines);\n } finally {\n closeSync(handle);\n }\n };\n\n const timer = setInterval(read, options.intervalMs ?? 300);\n timer.unref?.();\n\n const stop = (): void => clearInterval(timer);\n options.signal?.addEventListener('abort', stop, { once: true });\n return stop;\n};\n","import { existsSync } from 'node:fs';\nimport { listStacks, listTasks, loadSharedProjects, loadStack } from '../../core/config/load.js';\nimport { paths } from '../../core/config/paths.js';\nimport { ConfigError } from '../../core/config/errors.js';\nimport { listLinks } from './link.js';\nimport { padEnd, paint } from '../render/colors.js';\n\nexport const lsCommand = (env: NodeJS.ProcessEnv = process.env, json = false): number => {\n const home = paths(env);\n\n if (!existsSync(home.root)) {\n console.error(`${paint('yellow', 'no laracrew home yet')} — run ${paint('cyan', 'laracrew init')}`);\n return 1;\n }\n\n const stackNames = listStacks(env);\n const taskNames = listTasks(env);\n const projects = loadSharedProjects(env);\n\n const linkedByStack = new Map(listLinks({ env }).map((link) => [link.stack, link.name] as const));\n\n const stacks = stackNames.map((name) => {\n try {\n const { config } = loadStack(name, env);\n return {\n name,\n description: config.description ?? '',\n services: config.services.length,\n profiles: Object.keys(config.profiles),\n command: linkedByStack.get(name) ?? null,\n valid: true,\n };\n } catch (error) {\n return {\n name,\n description: error instanceof ConfigError ? error.message : 'invalid',\n services: 0,\n profiles: [],\n command: linkedByStack.get(name) ?? null,\n valid: false,\n };\n }\n });\n\n if (json) {\n console.log(JSON.stringify({ root: home.root, stacks, tasks: taskNames, projects }, null, 2));\n return 0;\n }\n\n console.log(paint('gray', home.root));\n\n console.log(`\\n${paint('bold', 'STACKS')}`);\n if (stacks.length === 0) console.log(paint('gray', ' none'));\n const width = Math.max(4, ...stacks.map((stack) => stack.name.length));\n for (const stack of stacks) {\n const label = stack.valid ? paint('cyan', padEnd(stack.name, width)) : paint('red', padEnd(stack.name, width));\n const meta = stack.valid ? paint('gray', `${stack.services} services`) : paint('red', 'invalid');\n console.log(` ${label} ${meta} ${paint('gray', stack.description)}`);\n if (stack.command) {\n console.log(` ${' '.repeat(width)} ${paint('green', `$ ${stack.command}`)} ${paint('gray', '(global command)')}`);\n }\n if (stack.profiles.length > 0) {\n console.log(` ${' '.repeat(width)} ${paint('gray', `profiles: ${stack.profiles.join(', ')}`)}`);\n }\n }\n\n console.log(`\\n${paint('bold', 'PROJECTS')}`);\n const projectKeys = Object.keys(projects);\n if (projectKeys.length === 0) console.log(paint('gray', ' none — add them to projects.yaml'));\n const projectWidth = Math.max(4, ...projectKeys.map((key) => key.length));\n for (const [key, project] of Object.entries(projects)) {\n const exists = existsSync(project.path);\n console.log(\n ` ${paint('magenta', padEnd(key, projectWidth))} ${project.path} ${\n exists ? '' : paint('red', '(missing)')\n }`,\n );\n }\n\n console.log(`\\n${paint('bold', 'TASKS')}`);\n if (taskNames.length === 0) console.log(paint('gray', ' none'));\n for (const task of taskNames) console.log(` ${paint('green', task)}`);\n\n console.log('');\n return 0;\n};\n","import { run } from './cli/program.js';\nimport { paint } from './cli/render/colors.js';\nimport { installPipeGuards } from './cli/render/output.js';\n\ninstallPipeGuards();\n\nrun().catch((error: unknown) => {\n // Set exitCode rather than calling process.exit(), which truncates pending stdout writes.\n console.error(paint('red', error instanceof Error ? (error.stack ?? error.message) : String(error)));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["readFileSync","path","fileURLToPath","path","path","paint","existsSync","path","path","existsSync","readFileSync","path","path","existsSync","path","existsSync","statSync","path","pad","path","existsSync","statSync","spawn","IS_WINDOWS","path","process","write","stamp","dependencies","paint","stamp","ESC","CSI","handlers","paint","supervisor","process","existsSync","path","mkdirSync","existsSync","path","home","mkdirSync","path","existsSync","existsSync","mkdirSync","readFileSync","readdirSync","writeFileSync","path","IS_WINDOWS","path","existsSync","readFileSync","mkdirSync","writeFileSync","readdirSync","existsSync","readdirSync","path","openSync","closeSync","statSync","existsSync","existsSync","statSync","openSync","closeSync","path","existsSync","time","existsSync","home","existsSync"]}
1
+ {"version":3,"sources":["../src/cli/program.ts","../src/core/config/errors.ts","../src/core/config/load.ts","../src/core/config/paths.ts","../src/core/config/schema.ts","../src/cli/render/colors.ts","../src/core/logs/sanitize.ts","../src/tui/theme.ts","../src/cli/render/marks.ts","../src/cli/commands/doctor.ts","../src/core/health/probes.ts","../src/core/process/spawn.ts","../src/core/events/bus.ts","../src/core/config/resolve.ts","../src/core/laravel/env.ts","../src/core/config/interpolate.ts","../src/core/process/supervisor.ts","../src/core/events/types.ts","../src/core/logs/file-sink.ts","../src/core/logs/ring-buffer.ts","../src/core/process/stop.ts","../src/core/process/managed-process.ts","../src/cli/render/output.ts","../src/cli/render/plain.ts","../src/tui/model.ts","../src/tui/keys.ts","../src/tui/screen.ts","../src/tui/terminal.ts","../src/tui/app.ts","../src/cli/commands/up.ts","../src/cli/commands/draft.ts","../src/cli/commands/link.ts","../src/cli/commands/init.ts","../src/cli/commands/templates.ts","../src/cli/commands/logs.ts","../src/core/logs/read.ts","../src/cli/commands/ls.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { ConfigError } from '../core/config/errors.js';\nimport { listStacks } from '../core/config/load.js';\nimport { loadGlobalConfig } from '../core/config/load.js';\nimport { color } from './render/colors.js';\nimport { marks } from './render/marks.js';\nimport { doctorCommand } from './commands/doctor.js';\nimport { draftAddCommand, draftCommand, draftPublishCommand } from './commands/draft.js';\nimport { initCommand } from './commands/init.js';\nimport { linkCommand, unlinkCommandAction } from './commands/link.js';\nimport { logsCommand } from './commands/logs.js';\nimport { lsCommand } from './commands/ls.js';\nimport { upCommand } from './commands/up.js';\n\n/** Replaced by tsup at build time; only the `tsx` dev path falls through to the lookup below. */\ndeclare const __LARACREW_VERSION__: string | undefined;\n\n/** Walks up from this file to laracrew's own package.json — the depth differs dev vs bundled. */\nconst versionFromPackageJson = (): string => {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let up = 0; up < 5; up += 1) {\n try {\n const pkg = JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf8')) as {\n name?: string;\n version?: string;\n };\n if (pkg.name === 'laracrew' && pkg.version) return pkg.version;\n } catch {\n /* keep walking */\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return '0.0.0-unknown';\n};\n\nexport const VERSION =\n typeof __LARACREW_VERSION__ === 'string' ? __LARACREW_VERSION__ : versionFromPackageJson();\n\n/**\n * Picks the stack when the user did not name one: the configured default, else the only\n * stack that exists, else an error that lists the options.\n */\nexport const resolveStackName = (explicit: string | undefined, env: NodeJS.ProcessEnv = process.env): string => {\n if (explicit) return explicit;\n\n const configured = loadGlobalConfig(env).defaultStack;\n if (configured) return configured;\n\n const stacks = listStacks(env);\n if (stacks.length === 1) return stacks[0]!;\n if (stacks.length === 0) {\n throw new ConfigError('no stacks defined yet — run `laracrew init`');\n }\n throw new ConfigError(\n `several stacks exist, so name one: ${stacks.join(', ')}`,\n { details: ['or set `defaultStack:` in ~/.laracrew/config.yaml'] },\n );\n};\n\nconst collect = (value: string, previous: string[]): string[] => [...previous, value];\n\nexport const buildProgram = (): Command => {\n const program = new Command();\n\n program\n .name('laracrew')\n .description('Boot and supervise all the long-running processes of your projects with one command.')\n .version(VERSION, '-v, --version')\n .showHelpAfterError()\n .configureHelp({\n styleTitle: (text) => color.bold(text),\n styleCommandText: (text) => color.cyan(text),\n styleSubcommandText: (text) => color.cyan(text),\n styleOptionText: (text) => color.green(text),\n styleArgumentText: (text) => color.yellow(text),\n })\n .configureOutput({\n // One colour decision for the whole program — ours, so NO_COLOR is honoured here too.\n getOutHasColors: () => color.level > 0,\n getErrHasColors: () => color.level > 0,\n outputError: (message, write) => write(`${marks().fail} ${color.red(message.trimEnd())}\n`),\n });\n\n program\n .command('init')\n .description('create ~/.laracrew')\n .option('--examples', 'also write a runnable demo stack and a two-project template')\n .action((options: { examples?: boolean }) => {\n initCommand({ examples: options.examples ?? false });\n });\n\n const draft = program\n .command('draft')\n .description('build a stack step by step in the current folder, then publish it')\n .argument('[name]', 'start a draft with this stack name, or show it if it exists; omit to show the only draft here')\n .option('--force', 'start over when a draft of that name already exists here')\n .action((name: string | undefined, options: { force?: boolean }) => {\n process.exitCode = draftCommand(name, options);\n });\n\n draft\n .command('add')\n .description('append a service to the draft in this folder')\n .requiredOption('--command, --cmd <line>', 'what to run, e.g. \"php artisan queue:work\"')\n .option('--project <key>', 'the project it runs in — any short key, e.g. api')\n .option('--path <dir>', \"the project's folder, or where the command runs when there is no --project; defaults to this folder\")\n .option('--name <service>', 'service name (default: project + command, e.g. api:queue:work)')\n .option('--default-state <state>', '\"running\" (default) or \"stopped\": defined, but idle until you start it')\n .option('--draft <name>', 'which draft, when this folder holds several')\n .action((options: Record<string, unknown>) => {\n process.exitCode = draftAddCommand({\n command: (options.command ?? options.cmd) as string,\n project: options.project as string | undefined,\n path: options.path as string | undefined,\n name: options.name as string | undefined,\n state: options.defaultState as string | undefined,\n draft: options.draft as string | undefined,\n });\n });\n\n draft\n .command('publish')\n .description('validate the draft and install it as a stack in ~/.laracrew')\n .option('--force', 'replace a stack of the same name')\n .option('--link', 'also install the global command, as `laracrew link` would')\n .option('--draft <name>', 'which draft, when this folder holds several')\n .action((options: { force?: boolean; link?: boolean; draft?: string }) => {\n process.exitCode = draftPublishCommand(options);\n });\n\n program\n .command('ls')\n .alias('list')\n .description('list stacks, projects and tasks')\n .option('--json', 'machine-readable output')\n .action((options: { json?: boolean }) => {\n process.exitCode = lsCommand(process.env, options.json ?? false);\n });\n\n program\n .command('up')\n .argument('[stack]', 'stack to boot')\n .description('boot a stack and supervise it')\n .option('--only <selector>', 'only these services or groups (repeatable, comma-separated)', collect, [])\n .option('--except <selector>', 'skip these services or groups (repeatable, comma-separated)', collect, [])\n .option('--profile <name>', 'apply a profile from the stack')\n .option('--plain', 'prefixed interleaved logs instead of the full-screen view')\n .option('--json', 'newline-delimited JSON events')\n .action(async (stack: string | undefined, options: Record<string, unknown>) => {\n const name = resolveStackName(stack);\n process.exitCode = await upCommand(name, {\n only: options.only as string[],\n except: options.except as string[],\n profile: options.profile as string | undefined,\n plain: options.plain as boolean | undefined,\n json: options.json as boolean | undefined,\n });\n });\n\n program\n .command('logs')\n .argument('[service]', 'service to read; omit for every service in the stack')\n .description('read what a stack wrote to disk, after the fact')\n .option('--stack <name>', 'which stack (defaults the same way `up` does)')\n .option('-n, --lines <count>', 'how many lines to show', (value: string) => Number(value), 200)\n .option('-f, --follow', 'keep printing new lines as they arrive')\n .option('--since <window>', 'only lines newer than this: 10m, 2h, 1d, or a date')\n .option('--all', 'merge every service in the stack')\n .option('--list', 'list the services that have a log file')\n .action(async (service: string | undefined, options: Record<string, unknown>) => {\n process.exitCode = await logsCommand(service, {\n stack: resolveStackName(options.stack as string | undefined),\n lines: options.lines as number,\n follow: options.follow as boolean | undefined,\n since: options.since as string | undefined,\n all: options.all as boolean | undefined,\n list: options.list as boolean | undefined,\n });\n });\n\n program\n .command('link')\n .argument('[stack]', 'stack to give its own global command')\n .description('install a global command that boots one stack')\n .option('--as <name>', 'name the command something other than the stack name')\n .option('--all', 'link every stack that declares `command:` in its stack.yaml')\n .option('--dir <path>', 'install into this directory instead of the npm global bin')\n .option('--force', 'overwrite a name that is taken or reserved')\n .action((stack: string | undefined, options: Record<string, unknown>) => {\n process.exitCode = linkCommand(\n stack,\n {\n as: options.as as string | undefined,\n all: options.all as boolean | undefined,\n dir: options.dir as string | undefined,\n force: options.force as boolean | undefined,\n },\n process.env,\n );\n });\n\n program\n .command('unlink')\n .argument('<name>', 'the global command to remove')\n .description('remove a global command laracrew installed')\n .action((name: string) => {\n process.exitCode = unlinkCommandAction(name);\n });\n\n program\n .command('doctor')\n .argument('[stack]', 'stack to check')\n .description('check a stack before booting it')\n .action(async (stack: string | undefined) => {\n process.exitCode = await doctorCommand(resolveStackName(stack));\n });\n\n return program;\n};\n\n/** `ConfigError.format()` with the parts told apart by colour: heading, file, message, hints. */\nconst renderConfigError = (error: ConfigError): string => {\n const lines = [`${marks().fail} ${color.red.bold('config error')}`];\n if (error.file) lines.push(` ${color.gray(error.file)}`);\n lines.push(` ${error.message}`);\n for (const detail of error.details) lines.push(` ${color.gray('-')} ${detail}`);\n return lines.join('\\n');\n};\n\nexport const run = async (argv: string[] = process.argv): Promise<void> => {\n try {\n await buildProgram().parseAsync(argv);\n } catch (error) {\n if (error instanceof ConfigError) {\n console.error(renderConfigError(error));\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n};\n","import type { ZodError, ZodIssue } from 'zod';\n\n/**\n * Config problems are the most common failure a user hits, so they get a real error type\n * with file/line context and a suggestion — never a raw zod issue tree.\n */\nexport class ConfigError extends Error {\n readonly file?: string;\n readonly details: string[];\n\n constructor(message: string, opts: { file?: string; details?: string[]; cause?: unknown } = {}) {\n super(message, opts.cause !== undefined ? { cause: opts.cause } : undefined);\n this.name = 'ConfigError';\n this.file = opts.file;\n this.details = opts.details ?? [];\n }\n\n /** Multi-line, terminal-ready rendering. */\n format(): string {\n const head = this.file ? `${this.file}\\n ${this.message}` : this.message;\n if (this.details.length === 0) return head;\n return `${head}\\n${this.details.map((d) => ` - ${d}`).join('\\n')}`;\n }\n}\n\nconst levenshtein = (a: string, b: string): number => {\n const rows = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array<number>(b.length).fill(0)]);\n for (let j = 0; j <= b.length; j++) rows[0]![j] = j;\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n rows[i]![j] = Math.min(rows[i - 1]![j]! + 1, rows[i]![j - 1]! + 1, rows[i - 1]![j - 1]! + cost);\n }\n }\n return rows[a.length]![b.length]!;\n};\n\n/** \"watchs\" -> \"watch\". Returns undefined when nothing is close enough to be helpful. */\nexport const didYouMean = (input: string, candidates: readonly string[]): string | undefined => {\n let best: { word: string; distance: number } | undefined;\n for (const candidate of candidates) {\n const distance = levenshtein(input.toLowerCase(), candidate.toLowerCase());\n if (!best || distance < best.distance) best = { word: candidate, distance };\n }\n if (!best) return undefined;\n const threshold = Math.max(2, Math.floor(input.length / 3));\n return best.distance <= threshold ? best.word : undefined;\n};\n\nconst pathOf = (issue: ZodIssue): string =>\n issue.path.length === 0\n ? '(root)'\n : issue.path\n .map((segment, index) => (typeof segment === 'number' ? `[${segment}]` : index === 0 ? segment : `.${segment}`))\n .join('');\n\n/** Turns a ZodError into one readable line per problem, with spelling suggestions. */\nexport const formatZodIssues = (error: ZodError, knownKeys: readonly string[] = []): string[] =>\n error.issues.map((issue) => {\n if (issue.code === 'unrecognized_keys') {\n return issue.keys\n .map((key) => {\n const suggestion = didYouMean(key, knownKeys);\n const at = pathOf(issue);\n const where = at === '(root)' ? '' : ` at ${at}`;\n return suggestion\n ? `unknown field \"${key}\"${where} — did you mean \"${suggestion}\"?`\n : `unknown field \"${key}\"${where}`;\n })\n .join('; ');\n }\n return `${pathOf(issue)}: ${issue.message}`;\n });\n\n/** Every field name the schema knows about, used to power \"did you mean\". */\nexport const KNOWN_SERVICE_KEYS = [\n 'name',\n 'project',\n 'cmd',\n 'cwd',\n 'env',\n 'groups',\n 'needs',\n 'ready',\n 'restart',\n 'backoff',\n 'stop',\n 'watch',\n 'metrics',\n 'url',\n 'external',\n 'autostart',\n 'enabled',\n 'color',\n] as const;\n\nexport const KNOWN_STACK_KEYS = [\n 'name',\n 'description',\n 'command',\n 'use',\n 'projects',\n 'defaults',\n 'services',\n 'profiles',\n 'hooks',\n] as const;\n\nexport const ALL_KNOWN_KEYS = [...KNOWN_SERVICE_KEYS, ...KNOWN_STACK_KEYS] as const;\n","import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport type { z } from 'zod';\nimport { ConfigError, formatZodIssues, ALL_KNOWN_KEYS } from './errors.js';\nimport { paths, stackDir, stackFile, taskFile } from './paths.js';\nimport {\n globalConfigSchema,\n projectsFileSchema,\n stackSchema,\n taskSchema,\n type GlobalConfig,\n type ProjectConfig,\n type StackConfig,\n type TaskConfig,\n} from './schema.js';\n\n/** Parses YAML, converting a syntax error into a ConfigError that names the line. */\nexport const parseYaml = (source: string, file: string): unknown => {\n try {\n return YAML.parse(source, { prettyErrors: true }) ?? {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ConfigError(`invalid YAML: ${message}`, { file, cause: error });\n }\n};\n\nexport const readYamlFile = (file: string): unknown => {\n let source: string;\n try {\n source = readFileSync(file, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new ConfigError(`file not found`, { file, cause: error });\n }\n throw error;\n }\n return parseYaml(source, file);\n};\n\n// Generic over the schema, not its output: `.default()` makes input and output differ.\nconst validate = <S extends z.ZodTypeAny>(schema: S, value: unknown, file: string): z.infer<S> => {\n const result = schema.safeParse(value);\n if (result.success) return result.data;\n throw new ConfigError('this file does not match the laracrew schema', {\n file,\n details: formatZodIssues(result.error, ALL_KNOWN_KEYS),\n });\n};\n\n/** ~/.laracrew/config.yaml — absent means \"all defaults\". */\nexport const loadGlobalConfig = (env: NodeJS.ProcessEnv = process.env): GlobalConfig => {\n const file = paths(env).configFile;\n if (!existsSync(file)) return globalConfigSchema.parse({});\n return validate(globalConfigSchema, readYamlFile(file), file);\n};\n\n/** ~/.laracrew/projects.yaml — absent means \"no shared projects\". */\nexport const loadSharedProjects = (env: NodeJS.ProcessEnv = process.env): Record<string, ProjectConfig> => {\n const file = paths(env).projectsFile;\n if (!existsSync(file)) return {};\n return validate(projectsFileSchema, readYamlFile(file), file).projects;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/**\n * Merges a stack's optional `services/*.yaml` fragments into the main document.\n * Each fragment is either a list of services or `{ services: [...] }`.\n */\nconst mergeServiceFragments = (document: unknown, dir: string): unknown => {\n const servicesDir = path.join(dir, 'services');\n if (!existsSync(servicesDir) || !statSync(servicesDir).isDirectory()) return document;\n if (!isRecord(document)) return document;\n\n const extra: unknown[] = [];\n for (const entry of readdirSync(servicesDir).sort()) {\n if (!/\\.ya?ml$/i.test(entry)) continue;\n const file = path.join(servicesDir, entry);\n const fragment = readYamlFile(file);\n if (Array.isArray(fragment)) {\n extra.push(...fragment);\n } else if (isRecord(fragment) && Array.isArray(fragment.services)) {\n extra.push(...fragment.services);\n } else {\n throw new ConfigError('a service fragment must be a list of services, or { services: [...] }', { file });\n }\n }\n\n if (extra.length === 0) return document;\n const existing = Array.isArray(document.services) ? document.services : [];\n return { ...document, services: [...existing, ...extra] };\n};\n\n/** A stack document from anywhere — a draft, a fragment under test — checked like a real one. */\nexport const validateStack = (document: unknown, file: string): StackConfig => validate(stackSchema, document, file);\n\nexport interface LoadedStack {\n config: StackConfig;\n file: string;\n dir: string;\n}\n\n/** Loads ~/.laracrew/stacks/<name>/stack.yaml plus its fragments. */\nexport const loadStack = (name: string, env: NodeJS.ProcessEnv = process.env): LoadedStack => {\n const dir = stackDir(name, env);\n const file = stackFile(name, env);\n\n if (!existsSync(file)) {\n const available = listStacks(env);\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}.` : ' Run `laracrew init` first.';\n throw new ConfigError(`no stack named \"${name}\".${hint}`, { file });\n }\n\n const document = mergeServiceFragments(readYamlFile(file), dir);\n const config = validate(stackSchema, document, file);\n\n if (config.name !== name) {\n throw new ConfigError(\n `stack folder is \"${name}\" but \\`name:\\` says \"${config.name}\" — they must match`,\n { file },\n );\n }\n\n return { config, file, dir };\n};\n\nexport const listStacks = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const dir = paths(env).stacksDir;\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && existsSync(path.join(dir, entry.name, 'stack.yaml')))\n .map((entry) => entry.name)\n .sort();\n};\n\nexport const listTasks = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const dir = paths(env).tasksDir;\n if (!existsSync(dir)) return [];\n return readdirSync(dir)\n .filter((entry) => /\\.ya?ml$/i.test(entry))\n .map((entry) => entry.replace(/\\.ya?ml$/i, ''))\n .sort();\n};\n\nexport const loadTask = (name: string, env: NodeJS.ProcessEnv = process.env): { config: TaskConfig; file: string } => {\n const file = taskFile(name, env);\n if (!existsSync(file)) {\n const available = listTasks(env);\n const hint = available.length > 0 ? ` Available: ${available.join(', ')}.` : '';\n throw new ConfigError(`no task named \"${name}\".${hint}`, { file });\n }\n return { config: validate(taskSchema, readYamlFile(file), file), file };\n};\n","import { homedir } from 'node:os';\nimport path from 'node:path';\n\n/**\n * Everything laracrew owns lives under one root. `LARACREW_HOME` overrides it,\n * which is what the test suite uses to stay out of the real home directory.\n */\nexport const home = (env: NodeJS.ProcessEnv = process.env): string =>\n env.LARACREW_HOME ? path.resolve(env.LARACREW_HOME) : path.join(homedir(), '.laracrew');\n\nexport interface HomePaths {\n root: string;\n configFile: string;\n projectsFile: string;\n stacksDir: string;\n tasksDir: string;\n fragmentsDir: string;\n logsDir: string;\n runDir: string;\n}\n\nexport const paths = (env: NodeJS.ProcessEnv = process.env): HomePaths => {\n const root = home(env);\n return {\n root,\n configFile: path.join(root, 'config.yaml'),\n projectsFile: path.join(root, 'projects.yaml'),\n stacksDir: path.join(root, 'stacks'),\n tasksDir: path.join(root, 'tasks'),\n fragmentsDir: path.join(root, 'fragments'),\n logsDir: path.join(root, 'logs'),\n runDir: path.join(root, 'run'),\n };\n};\n\nexport const stackDir = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).stacksDir, name);\n\nexport const stackFile = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(stackDir(name, env), 'stack.yaml');\n\nexport const taskFile = (name: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).tasksDir, `${name}.yaml`);\n","import { z } from 'zod';\n\n/**\n * The on-disk shape of ~/.laracrew files. Everything here is what the *user* writes;\n * `resolve.ts` turns it into the fully-defaulted runtime shape the supervisor consumes.\n */\n\nexport const restartPolicy = z.enum(['never', 'on-failure', 'always']);\nexport type RestartPolicy = z.infer<typeof restartPolicy>;\n\nexport const watchStrategy = z.enum(['restart', 'artisan-queue-restart', 'none']);\nexport type WatchStrategy = z.infer<typeof watchStrategy>;\n\nexport const readyProbeSchema = z\n .object({\n tcp: z.string().optional(), // \"127.0.0.1:6379\"\n http: z.string().url().optional(),\n logMatch: z.string().optional(), // regex source\n delayMs: z.number().int().nonnegative().optional(),\n timeoutMs: z.number().int().positive().default(30_000),\n intervalMs: z.number().int().positive().default(250),\n })\n .strict()\n .refine((p) => Boolean(p.tcp ?? p.http ?? p.logMatch ?? p.delayMs !== undefined), {\n message: 'a `ready` probe needs one of: tcp, http, logMatch, delayMs',\n });\nexport type ReadyProbe = z.infer<typeof readyProbeSchema>;\n\nexport const backoffSchema = z\n .object({\n initialMs: z.number().int().positive().default(1_000),\n maxMs: z.number().int().positive().default(30_000),\n factor: z.number().positive().default(2),\n maxRestarts: z.number().int().nonnegative().default(10),\n /** Stay up this long and the attempt counter resets, so a slow leak can't exhaust it. */\n resetAfterMs: z.number().int().positive().default(60_000),\n })\n .strict();\nexport type Backoff = z.infer<typeof backoffSchema>;\n\n/** `cmd` accepts a shell line or an argv array. The array form skips shell parsing. */\nexport const commandSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]);\n\nexport const stopPolicySchema = z\n .object({\n /**\n * Step 1 of the stop ladder: any command that asks the process to finish what it is\n * holding and exit by itself — `celery control shutdown`, `docker compose stop`, a\n * drain script. Runs in the service's cwd; laracrew waits `graceMs` for the exit.\n */\n exec: commandSchema.optional(),\n /** Sugar for `exec` on a Laravel project: runs `<php> artisan <this>` from its root. */\n artisan: z.string().optional(),\n signal: z.string().default('SIGTERM'),\n graceMs: z.number().int().positive().default(10_000),\n })\n .strict();\nexport type StopPolicy = z.infer<typeof stopPolicySchema>;\n\nexport const watchSchema = z\n .object({\n paths: z.array(z.string()).min(1),\n ignore: z.array(z.string()).default([]),\n strategy: watchStrategy.default('restart'),\n debounceMs: z.number().int().nonnegative().default(800),\n })\n .strict();\nexport type WatchConfig = z.infer<typeof watchSchema>;\n\nexport const metricsSchema = z\n .object({\n queues: z.array(z.string()).default([]),\n streams: z\n .array(z.object({ key: z.string(), group: z.string() }).strict())\n .default([]),\n })\n .strict();\nexport type MetricsConfig = z.infer<typeof metricsSchema>;\n\nexport const serviceSchema = z\n .object({\n name: z.string().min(1),\n project: z.string().optional(),\n cmd: commandSchema.optional(),\n cwd: z.string().optional(),\n env: z.record(z.string()).default({}),\n groups: z.array(z.string()).default([]),\n needs: z.array(z.string()).default([]),\n ready: readyProbeSchema.optional(),\n restart: restartPolicy.optional(),\n backoff: backoffSchema.partial().optional(),\n stop: stopPolicySchema.partial().optional(),\n watch: watchSchema.optional(),\n metrics: metricsSchema.optional(),\n url: z.string().optional(),\n /** Health-checked but never spawned: Redis, MySQL, a Docker service. */\n external: z.boolean().default(false),\n /** false = defined but not launched; press `s` in the TUI to start it when you need it. */\n autostart: z.boolean().default(true),\n enabled: z.boolean().default(true),\n color: z.string().optional(),\n })\n .strict()\n .refine((s) => s.external || s.cmd !== undefined, {\n message: 'a service needs a `cmd` unless it is marked `external: true`',\n });\nexport type ServiceConfig = z.infer<typeof serviceSchema>;\n\nexport const projectSchema = z\n .object({\n path: z.string().min(1),\n php: z.string().default('php'),\n envFile: z.string().default('.env'),\n color: z.string().optional(),\n })\n .strict();\nexport type ProjectConfig = z.infer<typeof projectSchema>;\n\nexport const projectsFileSchema = z\n .object({ projects: z.record(projectSchema).default({}) })\n .strict();\n\nexport const profileSchema = z\n .object({\n only: z.array(z.string()).default([]),\n except: z.array(z.string()).default([]),\n })\n .strict();\nexport type ProfileConfig = z.infer<typeof profileSchema>;\n\nexport const stackDefaultsSchema = z\n .object({\n restart: restartPolicy.default('on-failure'),\n backoff: backoffSchema.partial().default({}),\n stop: stopPolicySchema.partial().default({}),\n logs: z\n .object({\n /** Lines kept in memory per service, for the live log view. */\n maxLines: z.number().int().positive().default(5_000),\n /**\n * On by default: an in-memory buffer holds minutes, and losing the exception you\n * just watched scroll past is the fastest way to stop trusting the tool.\n */\n toFile: z.boolean().default(true),\n /** Rotate a service's log once it passes this size. */\n maxFileBytes: z.number().int().positive().default(5_000_000),\n /** How many rotated files to keep beside the current one. */\n keepFiles: z.number().int().nonnegative().default(1),\n })\n .strict()\n .default({}),\n })\n .strict();\nexport type StackDefaults = z.infer<typeof stackDefaultsSchema>;\n\nexport const stackSchema = z\n .object({\n name: z.string().min(1),\n description: z.string().optional(),\n /** The global command name `laracrew link` installs for this stack. Defaults to `name`. */\n command: z.string().min(1).optional(),\n /** Project keys pulled in from ~/.laracrew/projects.yaml. */\n use: z.array(z.string()).default([]),\n /** Projects declared inline; merged over the shared ones. */\n projects: z.record(projectSchema).default({}),\n defaults: stackDefaultsSchema.default({}),\n services: z.array(serviceSchema).min(1),\n profiles: z.record(profileSchema).default({}),\n hooks: z\n .object({ preUp: z.string().nullish(), postDown: z.string().nullish() })\n .strict()\n .default({}),\n })\n .strict();\nexport type StackConfig = z.infer<typeof stackSchema>;\n\nexport const globalConfigSchema = z\n .object({\n theme: z.enum(['auto', 'dark', 'light', 'mono', 'high-contrast']).default('auto'),\n editor: z.string().optional(),\n defaultStack: z.string().optional(),\n metricsIntervalMs: z.number().int().positive().default(2_000),\n })\n .strict();\nexport type GlobalConfig = z.infer<typeof globalConfigSchema>;\n\nexport const taskStepSchema: z.ZodType<TaskStep, z.ZodTypeDef, unknown> = z.lazy(() =>\n z.union([\n z\n .object({\n project: z.string().optional(),\n cwd: z.string().optional(),\n cmd: commandSchema,\n continueOnError: z.boolean().default(false),\n })\n .strict(),\n z.object({ parallel: z.array(taskStepSchema).min(1) }).strict(),\n ]),\n);\nexport type TaskStep =\n | { project?: string; cwd?: string; cmd: string | string[]; continueOnError: boolean }\n | { parallel: TaskStep[] };\n\nexport const taskSchema = z\n .object({\n name: z.string().min(1),\n description: z.string().optional(),\n pauseServices: z.array(z.string()).default([]),\n steps: z.array(taskStepSchema).min(1),\n })\n .strict();\nexport type TaskConfig = z.infer<typeof taskSchema>;\n","/**\n * Colour for everything laracrew prints, decided once, here. chalk produces the escape codes;\n * the on/off decision stays ours because chalk does not read NO_COLOR, and laracrew output is\n * piped into other tools as often as it is read.\n *\n * Import `color` from this module, never the `chalk` package itself.\n */\n\nimport { Chalk, supportsColor as chalkDetected, type ChalkInstance } from 'chalk';\nimport { stripAnsi } from '../../core/logs/sanitize.js';\n\nconst NAMES = [\n 'reset',\n 'bold',\n 'dim',\n 'italic',\n 'underline',\n 'black',\n 'red',\n 'green',\n 'yellow',\n 'blue',\n 'magenta',\n 'cyan',\n 'white',\n 'gray',\n] as const;\n\nexport type ColorName = (typeof NAMES)[number];\n\nexport const supportsColor = (stream: { isTTY?: boolean } = process.stdout, env = process.env): boolean => {\n if (env.NO_COLOR !== undefined && env.NO_COLOR !== '') return false;\n if (env.FORCE_COLOR !== undefined) return env.FORCE_COLOR !== '0' && env.FORCE_COLOR !== 'false';\n if (env.TERM === 'dumb') return false;\n return Boolean(stream.isTTY);\n};\n\n/** Off, or whatever depth chalk found on this terminal — never less than the 16 basic colours. */\nconst levelFor = (enabled: boolean): 0 | 1 | 2 | 3 =>\n enabled ? (Math.max(1, chalkDetected ? chalkDetected.level : 1) as 1 | 2 | 3) : 0;\n\nexport const createColor = (enabled: boolean): ChalkInstance => new Chalk({ level: levelFor(enabled) });\n\n/** `color.bold.cyan('…')` — the instance every command prints with. */\nexport const color: ChalkInstance = createColor(supportsColor());\n\nexport interface Painter {\n (name: ColorName, text: string): string;\n readonly enabled: boolean;\n}\n\n/** `paint('red', text)`: the injectable form the TUI renders through, so screens stay pure. */\nexport const createPainter = (enabled: boolean): Painter => {\n const chalk = createColor(enabled);\n return Object.assign((name: ColorName, text: string): string => chalk[name](text), { enabled });\n};\n\n/** The default painter, decided once from the real stdout. */\nexport const paint: Painter = createPainter(supportsColor());\n\n/** Falls back to cyan for a colour name the user invented in their config. */\nexport const asColorName = (value: string | undefined): ColorName =>\n value && (NAMES as readonly string[]).includes(value) ? (value as ColorName) : 'cyan';\n\nexport { stripAnsi };\n\nexport const padEnd = (text: string, width: number): string => {\n const visible = stripAnsi(text).length;\n return visible >= width ? text : text + ' '.repeat(width - visible);\n};\n","/**\n * Child output goes straight into a framed TUI, so anything that moves the cursor would\n * corrupt the frame. Colour (SGR) is kept — Laravel colours its own output and that is\n * worth preserving.\n *\n * The escape characters are built with String.fromCharCode instead of being written as\n * literals, so this file holds no raw control bytes for an editor or a diff to mangle.\n */\n\nconst ESC = String.fromCharCode(27);\nconst BEL = String.fromCharCode(7);\n\n/** CSI: ESC [ params intermediates final — colour, cursor moves, erase. */\nconst CSI = new RegExp(ESC + '\\\\[[0-?]*[ -/]*[@-~]', 'g');\n\n/** OSC: ESC ] ... BEL or ST — window titles and hyperlinks. */\nconst OSC = new RegExp(ESC + '\\\\][^' + BEL + ESC + ']*(?:' + BEL + '|' + ESC + '\\\\\\\\)', 'g');\n\n/** Single-character escapes that have no business mid-line. */\nconst SINGLE = new RegExp(ESC + '[=>78MD]', 'g');\n\n/** Colour (SGR) sequences only — what laracrew itself adds, and what a log file should not keep. */\nconst SGR = new RegExp(ESC + '\\\\[[0-9;]*m', 'g');\n\nexport const stripAnsi = (text: string): string => text.replace(SGR, '');\n\nconst TAB = 9;\nconst ESC_CODE = 27;\n\nexport const sanitize = (input: string): string => {\n let out = input.replace(OSC, '').replace(SINGLE, '');\n\n // Keep colour, drop everything that would move or erase.\n out = out.replace(CSI, (seq) => (seq.endsWith('m') ? seq : ''));\n\n // Progress bars redraw with \\r; only the final state is meaningful in a log.\n if (out.includes('\\r')) {\n const segments = out.split('\\r').filter((segment) => segment !== '');\n out = segments.length > 0 ? segments[segments.length - 1]! : '';\n }\n\n // Strip the remaining control characters. ESC survives because the SGR sequences\n // kept above still need it.\n return out.replace(/\\p{Cc}/gu, (character) => {\n const code = character.charCodeAt(0);\n return code === TAB || code === ESC_CODE ? character : '';\n });\n};\n\n/**\n * Turns a stream of arbitrary chunks into whole lines. Children write when they feel like\n * it, so a line routinely arrives split across two chunks.\n */\nexport class LineSplitter {\n #buffer = '';\n readonly #maxLineLength: number;\n\n constructor(maxLineLength = 16_384) {\n this.#maxLineLength = maxLineLength;\n }\n\n push(chunk: string | Buffer): string[] {\n this.#buffer += typeof chunk === 'string' ? chunk : chunk.toString('utf8');\n\n const lines: string[] = [];\n let index = this.#buffer.indexOf('\\n');\n while (index !== -1) {\n const line = this.#buffer.slice(0, index).replace(/\\r$/, '');\n lines.push(sanitize(line));\n this.#buffer = this.#buffer.slice(index + 1);\n index = this.#buffer.indexOf('\\n');\n }\n\n // A child that never emits a newline (a progress bar, a hung prompt) must not grow\n // the buffer without bound.\n if (this.#buffer.length > this.#maxLineLength) {\n lines.push(sanitize(this.#buffer));\n this.#buffer = '';\n }\n\n return lines;\n }\n\n /** Emits whatever is left when the stream closes. */\n flush(): string[] {\n if (this.#buffer === '') return [];\n const line = sanitize(this.#buffer.replace(/\\r$/, ''));\n this.#buffer = '';\n return line === '' ? [] : [line];\n }\n}\n","import type { ServiceState } from '../core/events/types.js';\n\n/**\n * Restrained on purpose: colour carries state, nothing else. The glyph and the word always\n * say the same thing, so a mono terminal loses nothing.\n */\n\nconst asciiOnly = (env: NodeJS.ProcessEnv = process.env): boolean =>\n env.LARACREW_ASCII === '1' || env.TERM === 'dumb';\n\nexport interface Glyphs {\n running: string;\n ready: string;\n starting: string;\n stopped: string;\n failed: string;\n queued: string;\n branch: string;\n lastBranch: string;\n pipe: string;\n pointer: string;\n restart: string;\n rule: string;\n dot: string;\n tick: string;\n warn: string;\n arrow: string;\n}\n\nconst UNICODE: Glyphs = {\n running: '●',\n ready: '●',\n starting: '◐',\n stopped: '◼',\n failed: '✖',\n queued: '○',\n branch: '├─',\n lastBranch: '└─',\n pipe: '│',\n pointer: '▸',\n restart: '⟳',\n rule: '─',\n dot: '·',\n tick: '✔',\n warn: '▲',\n arrow: '→',\n};\n\nconst ASCII: Glyphs = {\n running: '*',\n ready: '*',\n starting: 'o',\n stopped: '#',\n failed: 'X',\n queued: '.',\n branch: '|-',\n lastBranch: '`-',\n pipe: '|',\n pointer: '>',\n restart: 'r',\n rule: '-',\n dot: '.',\n tick: 'v',\n warn: '!',\n arrow: '->',\n};\n\nexport const glyphs = (env: NodeJS.ProcessEnv = process.env): Glyphs => (asciiOnly(env) ? ASCII : UNICODE);\n\nexport type StateColor = 'green' | 'yellow' | 'red' | 'gray' | 'cyan';\n\nexport interface StateStyle {\n glyph: keyof Glyphs;\n color: StateColor;\n label: string;\n}\n\nexport const STATE_STYLE: Record<ServiceState, StateStyle> = {\n queued: { glyph: 'queued', color: 'gray', label: 'QUEUED' },\n starting: { glyph: 'starting', color: 'yellow', label: 'STARTING' },\n ready: { glyph: 'ready', color: 'cyan', label: 'READY' },\n running: { glyph: 'running', color: 'green', label: 'RUNNING' },\n stopping: { glyph: 'starting', color: 'yellow', label: 'STOPPING' },\n stopped: { glyph: 'stopped', color: 'gray', label: 'STOPPED' },\n crashed: { glyph: 'failed', color: 'red', label: 'CRASHED' },\n backoff: { glyph: 'starting', color: 'yellow', label: 'RESTARTING' },\n failed: { glyph: 'failed', color: 'red', label: 'FAILED' },\n};\n\n/** 00:15:27 — the header clock. */\nexport const formatUptime = (ms: number | undefined): string => {\n if (ms === undefined || ms < 0) return '--:--:--';\n const total = Math.floor(ms / 1000);\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor((total % 3600) / 60);\n const seconds = total % 60;\n return [hours, minutes, seconds].map((part) => String(part).padStart(2, '0')).join(':');\n};\n\n/** 1m 02s — compact, for a table column. */\nexport const formatDuration = (ms: number | undefined): string => {\n if (ms === undefined || ms < 0) return '—';\n const total = Math.floor(ms / 1000);\n if (total < 60) return `${total}s`;\n const minutes = Math.floor(total / 60);\n const seconds = total % 60;\n if (minutes < 60) return `${minutes}m ${String(seconds).padStart(2, '0')}s`;\n const hours = Math.floor(minutes / 60);\n return `${hours}h ${String(minutes % 60).padStart(2, '0')}m`;\n};\n\nexport const formatClock = (at: number): string => {\n const date = new Date(at);\n return [date.getHours(), date.getMinutes(), date.getSeconds()]\n .map((part) => String(part).padStart(2, '0'))\n .join(':');\n};\n","import { glyphs } from '../../tui/theme.js';\nimport { color, padEnd } from './colors.js';\n\n/**\n * The status vocabulary every command shares — one glyph, one colour, one meaning — so a tick\n * in `init` says the same thing as a tick in `doctor`. ASCII under LARACREW_ASCII=1 or\n * TERM=dumb, like the TUI.\n */\nexport interface Marks {\n ok: string;\n fail: string;\n warn: string;\n skip: string;\n hint: string;\n arrow: string;\n}\n\nexport const marks = (env: NodeJS.ProcessEnv = process.env): Marks => {\n const glyph = glyphs(env);\n return {\n ok: color.green(glyph.tick),\n fail: color.red(glyph.failed),\n warn: color.yellow(glyph.warn),\n skip: color.gray(glyph.dot),\n hint: color.cyan(glyph.pointer),\n arrow: color.gray(glyph.arrow),\n };\n};\n\n/**\n * A \"Next\" block: `▸ command why` rows aligned on the command. A row with an empty command\n * continues the one above it.\n */\nexport const nextSteps = (rows: [command: string, why: string][], env: NodeJS.ProcessEnv = process.env): string => {\n const mark = marks(env);\n const width = Math.max(...rows.map(([command]) => command.length));\n const lines = rows.map(([command, why]) =>\n command ? ` ${mark.hint} ${color.cyan(padEnd(command, width))} ${why}` : `${' '.repeat(width + 6)}${why}`,\n );\n return [color.bold('Next'), ...lines].join('\\n');\n};\n","import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { ConfigError } from '../../core/config/errors.js';\nimport type { ResolvedProject, ResolvedService, ResolvedStack } from '../../core/config/resolve.js';\nimport { describeProbe, httpProbe, isPortFree, tcpProbe } from '../../core/health/probes.js';\nimport { runOnce } from '../../core/process/spawn.js';\nimport { color } from '../render/colors.js';\nimport { marks } from '../render/marks.js';\nimport { glyphs } from '../../tui/theme.js';\nimport { prepareStack } from './up.js';\n\nexport interface Finding {\n level: 'ok' | 'warn' | 'error';\n message: string;\n hint?: string;\n}\n\nconst PORT_IN_COMMAND = /--port[= ](\\d{2,5})/g;\n\n/** The command line a service will actually run, in one form the pattern checks can match. */\nconst commandLine = (service: ResolvedService): string => {\n if (!service.command) return '';\n return service.command.kind === 'shell'\n ? service.command.line\n : [service.command.file, ...service.command.args].join(' ');\n};\n\n/** `php`, `php8.2`, `C:\\php\\php.exe` — anywhere in the line, not just at the front. */\nconst PHP_BINARY = /(^|[\\\\/\\s\"'])php[\\d.]*(\\.exe)?(\\s|$)/i;\n\n/**\n * Which projects are PHP projects at all.\n *\n * laracrew supervises any process, so a stack can be pure Node, Python or Go. Running\n * `php --version` for those projects is noise on a machine that has PHP and a blocking\n * error on one that does not — so every Laravel-specific check is gated on this.\n */\nconst phpProjects = (stack: ResolvedStack): Set<string> => {\n const keys = new Set<string>();\n for (const service of stack.services) {\n const key = service.project?.key;\n if (!key) continue;\n const line = commandLine(service);\n const php = stack.projects[key]?.php;\n // `stop.artisan` runs `<php> artisan ...`, so it needs PHP whatever the service itself is.\n if (service.stop.artisan || PHP_BINARY.test(line) || (php !== undefined && line.startsWith(php))) {\n keys.add(key);\n }\n }\n return keys;\n};\n\n/** Env keys whose value being \"redis\" means the project talks to Redis. */\nconst REDIS_DRIVER_KEYS = [\n 'QUEUE_CONNECTION',\n 'CACHE_STORE',\n 'CACHE_DRIVER',\n 'SESSION_DRIVER',\n 'BROADCAST_CONNECTION',\n 'BROADCAST_DRIVER',\n];\n\n/**\n * Which projects talk to Redis — from their own env, or from what their services run.\n * Without this every project defaults to 127.0.0.1:6379, so two Node projects with no\n * `.env` would be reported as sharing a Redis namespace neither of them uses.\n */\nconst redisProjects = (stack: ResolvedStack): Set<string> => {\n const keys = new Set<string>();\n\n for (const [key, project] of Object.entries(stack.projects)) {\n const declared = Object.keys(project.env).some((name) => name.startsWith('REDIS_'));\n const driver = REDIS_DRIVER_KEYS.some((name) => project.env[name]?.toLowerCase() === 'redis');\n if (declared || driver) keys.add(key);\n }\n\n for (const service of stack.services) {\n const key = service.project?.key;\n if (!key) continue;\n // Horizon is Redis-only, and declared metrics are read straight off Redis.\n if (service.metrics || /\\b(redis|horizon)\\b/i.test(commandLine(service))) keys.add(key);\n }\n\n return keys;\n};\n\n/** Ports the stack will try to bind: ${port:N} tokens plus anything passed as --port. */\nexport const declaredPorts = (stack: ResolvedStack): number[] => {\n const ports = new Set<number>(stack.ports);\n for (const service of stack.services) {\n for (const match of commandLine(service).matchAll(PORT_IN_COMMAND)) {\n const port = Number(match[1]);\n if (Number.isInteger(port)) ports.add(port);\n }\n }\n return [...ports].sort((a, b) => a - b);\n};\n\n/** redis://[user:pass@]host:port[/db] — the usual form outside Laravel. */\nconst parseRedisUrl = (url: string): { host: string; port: string } | undefined => {\n try {\n const parsed = new URL(url);\n return parsed.hostname ? { host: parsed.hostname, port: parsed.port || '6379' } : undefined;\n } catch {\n return undefined;\n }\n};\n\nconst redisTargetOf = (project: ResolvedProject): string => {\n const url = project.env.REDIS_URL ? parseRedisUrl(project.env.REDIS_URL) : undefined;\n const host = project.env.REDIS_HOST ?? url?.host ?? '127.0.0.1';\n const port = project.env.REDIS_PORT ?? url?.port ?? '6379';\n return `${host}:${port}`;\n};\n\n/** Laravel's Str::slug($value, '_'). */\nconst slug = (value: string): string =>\n value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_+|_+$/g, '');\n\n/**\n * The prefix Laravel will actually use. Most projects never set REDIS_PREFIX, and the\n * framework default is derived from APP_NAME — so two apps on one Redis database are usually\n * isolated anyway. Reading only REDIS_PREFIX here would cry wolf on every normal setup.\n */\nexport const redisPrefixOf = (project: ResolvedProject): string =>\n project.env.REDIS_PREFIX ?? `${slug(project.env.APP_NAME ?? 'laravel')}_database_`;\n\n/** Which Redis logical namespace a project writes into — host:port/db + prefix. */\nconst redisNamespaceOf = (project: ResolvedProject): string =>\n `${redisTargetOf(project)}/${project.env.REDIS_DB ?? '0'}#${redisPrefixOf(project)}`;\n\nconst checkProjects = (stack: ResolvedStack, php: Set<string>, redis: Set<string>): Finding[] => {\n const findings: Finding[] = [];\n\n for (const project of Object.values(stack.projects)) {\n if (!existsSync(project.path)) {\n findings.push({ level: 'error', message: `project \"${project.key}\": path does not exist — ${project.path}` });\n continue;\n }\n // Only a project something runs `php` for is expected to have an artisan file.\n if (php.has(project.key) && !existsSync(path.join(project.path, 'artisan'))) {\n findings.push({\n level: 'warn',\n message: `project \"${project.key}\": no \\`artisan\\` file in ${project.path}`,\n hint: 'laracrew will still run the commands, but this does not look like a Laravel root',\n });\n }\n // A Node or Python project with no .env is normal; one whose checks need it is not.\n if (Object.keys(project.env).length === 0 && (php.has(project.key) || redis.has(project.key))) {\n findings.push({\n level: 'warn',\n message: `project \"${project.key}\": ${project.envFile} is missing or empty`,\n hint: 'queue/Redis checks and ${project.env:...} tokens need it',\n });\n }\n }\n\n return findings;\n};\n\n/** The check that pays for this whole command: two apps quietly sharing one Redis namespace. */\nconst checkRedisCollisions = (stack: ResolvedStack, redis: Set<string>): Finding[] => {\n const findings: Finding[] = [];\n // Projects that never touch Redis would otherwise all collide on the synthesized default.\n const projects = Object.values(stack.projects).filter((project) => redis.has(project.key));\n\n const byNamespace = new Map<string, ResolvedProject[]>();\n for (const project of projects) {\n const namespace = redisNamespaceOf(project);\n byNamespace.set(namespace, [...(byNamespace.get(namespace) ?? []), project]);\n }\n\n for (const [namespace, sharing] of byNamespace) {\n if (sharing.length < 2) continue;\n\n const queuesByProject = new Map<string, Set<string>>();\n const streamsByProject = new Map<string, Set<string>>();\n for (const service of stack.services) {\n if (!service.project || !service.metrics) continue;\n const key = service.project.key;\n for (const queue of service.metrics.queues) {\n queuesByProject.set(key, (queuesByProject.get(key) ?? new Set()).add(queue));\n }\n for (const stream of service.metrics.streams) {\n streamsByProject.set(key, (streamsByProject.get(key) ?? new Set()).add(`${stream.key}/${stream.group}`));\n }\n }\n\n const names = sharing.map((project) => project.key);\n const overlap = (map: Map<string, Set<string>>): string[] => {\n const counts = new Map<string, number>();\n for (const key of names) {\n for (const value of map.get(key) ?? []) counts.set(value, (counts.get(value) ?? 0) + 1);\n }\n return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value);\n };\n\n const sharedQueues = overlap(queuesByProject);\n const sharedStreams = overlap(streamsByProject);\n\n if (sharedQueues.length > 0) {\n findings.push({\n level: 'error',\n message: `${names.join(' and ')} share Redis ${namespace} AND queue(s): ${sharedQueues.join(', ')}`,\n hint: \"each project's workers will steal the other's jobs — set a different REDIS_DB or REDIS_PREFIX\",\n });\n }\n if (sharedStreams.length > 0) {\n findings.push({\n level: 'error',\n message: `${names.join(' and ')} share Redis ${namespace} AND stream/group: ${sharedStreams.join(', ')}`,\n hint: 'two consumers in one group split the entries between them — give each project its own group name',\n });\n }\n if (sharedQueues.length === 0 && sharedStreams.length === 0) {\n findings.push({\n level: 'warn',\n message: `${names.join(' and ')} share Redis ${namespace}`,\n hint: 'no queue or stream overlap declared, but cache and session keys can still collide',\n });\n }\n }\n\n // Same server and database, different prefix: worth stating plainly, because it is the\n // thing standing between two projects' queues.\n const byServer = new Map<string, ResolvedProject[]>();\n for (const project of projects) {\n const server = `${redisTargetOf(project)}/${project.env.REDIS_DB ?? '0'}`;\n byServer.set(server, [...(byServer.get(server) ?? []), project]);\n }\n for (const [server, sharing] of byServer) {\n if (sharing.length < 2) continue;\n const prefixes = new Set(sharing.map(redisPrefixOf));\n if (prefixes.size === sharing.length) {\n findings.push({\n level: 'ok',\n message: `${sharing.map((p) => p.key).join(' and ')} share Redis ${server} but are isolated by prefix (${[...prefixes].join(', ')})`,\n });\n }\n }\n\n return findings;\n};\n\nconst checkQueueConnections = (stack: ResolvedStack): Finding[] => {\n const findings: Finding[] = [];\n const workerProjects = new Set(\n stack.services\n .filter((service) => {\n // A service you start by hand is a deliberate choice, not a misconfiguration.\n if (!service.autostart) return false;\n return /\\b(queue:work|queue:listen|horizon)\\b/.test(commandLine(service));\n })\n .map((service) => service.project?.key)\n .filter((key): key is string => Boolean(key)),\n );\n\n for (const key of workerProjects) {\n const project = stack.projects[key];\n if (!project) continue;\n const connection = project.env.QUEUE_CONNECTION;\n if (connection === undefined) continue;\n if (connection === 'sync') {\n findings.push({\n level: 'error',\n message: `project \"${key}\" runs a queue worker but QUEUE_CONNECTION=sync`,\n hint: 'jobs run inline on dispatch, so the worker will sit idle forever — set it to redis or database',\n });\n }\n }\n\n return findings;\n};\n\n/** Only for projects something actually runs PHP for — a Node or Python stack needs none. */\nconst checkPhp = async (stack: ResolvedStack, php: Set<string>): Promise<Finding[]> => {\n const binaries = new Set(\n Object.values(stack.projects)\n .filter((project) => php.has(project.key))\n .map((project) => project.php),\n );\n const findings: Finding[] = [];\n\n for (const binary of binaries) {\n try {\n const result = await runOnce({ kind: 'argv', file: binary, args: ['--version'] }, {\n cwd: process.cwd(),\n timeoutMs: 8_000,\n });\n if (result.code === 0) {\n const version = result.stdout.split('\\n')[0]?.trim() ?? '';\n findings.push({ level: 'ok', message: `php: ${version}` });\n } else {\n findings.push({ level: 'error', message: `\"${binary} --version\" exited with code ${result.code}` });\n }\n } catch {\n findings.push({\n level: 'error',\n message: `cannot run \"${binary}\"`,\n hint: 'put PHP on PATH, or set an absolute path in projects.yaml',\n });\n }\n }\n\n return findings;\n};\n\nconst checkPorts = async (stack: ResolvedStack): Promise<Finding[]> => {\n const findings: Finding[] = [];\n for (const port of declaredPorts(stack)) {\n const free = await isPortFree(port);\n findings.push(\n free\n ? { level: 'ok', message: `port ${port} is free` }\n : {\n level: 'error',\n message: `port ${port} is already in use`,\n hint: 'something else is bound to it — a stale worker from a previous run, most likely',\n },\n );\n }\n return findings;\n};\n\n/**\n * The language-agnostic dependency check: every `external: true` service is something the\n * stack expects to already be running, and it already declares how to test for it.\n */\nconst checkExternalServices = async (stack: ResolvedStack): Promise<Finding[]> => {\n const external = stack.services.filter((service) => service.external && (service.ready?.tcp ?? service.ready?.http));\n\n return Promise.all(\n external.map(async (service): Promise<Finding> => {\n const probe = service.ready!;\n const label = describeProbe(probe);\n const result = probe.http\n ? await httpProbe(probe.http, 2_000)\n : await tcpProbe(probe.tcp!, 2_000);\n\n return result.ok\n ? { level: 'ok', message: `${service.name} is reachable — ${label}` }\n : {\n level: 'warn',\n message: `${service.name} is not reachable — ${label}${result.detail ? ` (${result.detail})` : ''}`,\n hint: 'laracrew never starts an external service; anything that needs it will wait at its gate',\n };\n }),\n );\n};\n\n/** Ports already covered by an external service's own gate, so they are not probed twice. */\nconst externalTcpTargets = (stack: ResolvedStack): Set<string> =>\n new Set(\n stack.services\n .filter((service) => service.external && service.ready?.tcp)\n .map((service) => service.ready!.tcp!),\n );\n\nconst checkRedisReachable = async (stack: ResolvedStack, redis: Set<string>): Promise<Finding[]> => {\n const covered = externalTcpTargets(stack);\n const targets = new Set(\n Object.values(stack.projects)\n .filter((project) => redis.has(project.key))\n .map(redisTargetOf)\n .filter((target) => !covered.has(target)),\n );\n\n const findings: Finding[] = [];\n for (const target of targets) {\n const result = await tcpProbe(target, 2_000);\n findings.push(\n result.ok\n ? { level: 'ok', message: `redis reachable at ${target}` }\n : { level: 'warn', message: `redis not reachable at ${target}${result.detail ? ` (${result.detail})` : ''}` },\n );\n }\n return findings;\n};\n\nexport const runDoctor = async (stackName: string, env: NodeJS.ProcessEnv = process.env): Promise<Finding[]> => {\n let stack: ResolvedStack;\n try {\n stack = prepareStack(stackName, { env });\n } catch (error) {\n if (error instanceof ConfigError) return [{ level: 'error', message: error.format() }];\n throw error;\n }\n\n // Classified once: every Laravel-specific check below is gated on these, so a stack with\n // no PHP in it gets no PHP findings and a stack with no Redis gets no Redis findings.\n const php = phpProjects(stack);\n const redis = redisProjects(stack);\n\n const findings: Finding[] = [\n { level: 'ok', message: `stack \"${stack.name}\" is valid — ${stack.services.length} services` },\n ...checkProjects(stack, php, redis),\n ...checkQueueConnections(stack),\n ...checkRedisCollisions(stack, redis),\n ];\n\n const async = await Promise.all([\n checkPhp(stack, php),\n checkPorts(stack),\n checkExternalServices(stack),\n checkRedisReachable(stack, redis),\n ]);\n return [...findings, ...async.flat()];\n};\n\nexport const doctorCommand = async (stackName: string, env: NodeJS.ProcessEnv = process.env): Promise<number> => {\n const findings = await runDoctor(stackName, env);\n const mark = marks(env);\n\n console.log(`${color.bold('doctor')} ${color.gray(glyphs(env).dot)} ${color.cyan.bold(stackName)}\\n`);\n\n const lead = { ok: mark.ok, warn: mark.warn, error: mark.fail };\n const tone = { ok: (text: string) => text, warn: color.yellow, error: color.red };\n for (const finding of findings) {\n console.log(`${lead[finding.level]} ${tone[finding.level](finding.message)}`);\n if (finding.hint) console.log(` ${color.gray(finding.hint)}`);\n }\n\n const errors = findings.filter((finding) => finding.level === 'error').length;\n const warnings = findings.filter((finding) => finding.level === 'warn').length;\n const count = (n: number, noun: string): string => `${n} ${noun}${n === 1 ? '' : 's'}`;\n const tail = warnings > 0 ? color.yellow(`, ${count(warnings, 'warning')}`) : '';\n\n console.log(\n errors === 0\n ? `\\n${mark.ok} ${color.green.bold('no blocking problems')}${tail}`\n : `\\n${mark.fail} ${color.red.bold(count(errors, 'problem'))}${tail}`,\n );\n\n return errors > 0 ? 1 : 0;\n};\n","import net from 'node:net';\nimport type { ReadyProbe } from '../config/schema.js';\n\nexport interface ProbeResult {\n ok: boolean;\n detail?: string;\n}\n\nexport const tcpProbe = (target: string, timeoutMs = 2_000): Promise<ProbeResult> =>\n new Promise((resolve) => {\n const lastColon = target.lastIndexOf(':');\n const host = lastColon === -1 ? '127.0.0.1' : target.slice(0, lastColon) || '127.0.0.1';\n const port = Number(lastColon === -1 ? target : target.slice(lastColon + 1));\n\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n resolve({ ok: false, detail: `\"${target}\" is not host:port` });\n return;\n }\n\n const socket = net.connect({ host, port });\n const finish = (result: ProbeResult) => {\n socket.removeAllListeners();\n socket.destroy();\n resolve(result);\n };\n\n socket.setTimeout(timeoutMs);\n socket.once('connect', () => finish({ ok: true }));\n socket.once('timeout', () => finish({ ok: false, detail: 'connect timed out' }));\n socket.once('error', (error) => finish({ ok: false, detail: (error as NodeJS.ErrnoException).code ?? error.message }));\n });\n\nexport const httpProbe = async (url: string, timeoutMs = 2_000): Promise<ProbeResult> => {\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(timeoutMs),\n redirect: 'manual',\n headers: { 'user-agent': 'laracrew' },\n });\n // Any answer means the server is up; a 404 on /up still proves it is listening.\n if (response.status >= 500) return { ok: false, detail: `HTTP ${response.status}` };\n return { ok: true, detail: `HTTP ${response.status}` };\n } catch (error) {\n return { ok: false, detail: error instanceof Error ? error.message : String(error) };\n }\n};\n\n/** True when the port is free to bind — used by `doctor` to report clashes before booting. */\nexport const isPortFree = (port: number, host = '127.0.0.1'): Promise<boolean> =>\n new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => server.close(() => resolve(true)));\n server.listen(port, host);\n });\n\nexport interface WaitOptions {\n timeoutMs: number;\n intervalMs: number;\n signal?: AbortSignal;\n}\n\n/** Polls `probe` until it passes, the timeout expires, or the caller aborts. */\nexport const waitFor = async (\n probe: () => Promise<ProbeResult>,\n options: WaitOptions,\n): Promise<ProbeResult> => {\n const deadline = Date.now() + options.timeoutMs;\n let last: ProbeResult = { ok: false, detail: 'not attempted' };\n\n while (Date.now() < deadline) {\n if (options.signal?.aborted) return { ok: false, detail: 'aborted' };\n last = await probe();\n if (last.ok) return last;\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(options.intervalMs, remaining), options.signal);\n }\n\n return { ok: false, detail: last.detail ?? 'timed out' };\n};\n\nexport const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>\n new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n resolve();\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n\n/** A human-readable label for what we are waiting on, shown in the boot screen. */\nexport const describeProbe = (probe: ReadyProbe): string => {\n if (probe.http) return `http ${probe.http}`;\n if (probe.tcp) return `tcp ${probe.tcp}`;\n if (probe.logMatch) return `log /${probe.logMatch}/`;\n if (probe.delayMs !== undefined) return `wait ${probe.delayMs}ms`;\n return 'spawn';\n};\n","import { spawn, type ChildProcess, type SpawnOptions } from 'node:child_process';\nimport type { Command, ResolvedService } from '../config/resolve.js';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\n/**\n * On Windows, `npm`/`npx`/`yarn`/`pnpm` are .cmd shims. Recent Node refuses to spawn them\n * without a shell, so these have to go through cmd.exe even in argv form.\n */\nconst SHIM_NAMES = new Set(['npm', 'npx', 'yarn', 'pnpm', 'bun', 'composer']);\n\nconst needsShell = (file: string): boolean => {\n if (!IS_WINDOWS) return false;\n const base = file.replace(/\\\\/g, '/').split('/').pop() ?? file;\n if (/\\.(cmd|bat)$/i.test(base)) return true;\n return SHIM_NAMES.has(base.replace(/\\.[^.]+$/, '').toLowerCase());\n};\n\n/** A quoted, human-readable rendering of the command — used in logs and the TUI header. */\nexport const describeCommand = (command: Command): string =>\n command.kind === 'shell'\n ? command.line\n : [command.file, ...command.args].map((part) => (part.includes(' ') ? `\"${part}\"` : part)).join(' ');\n\nexport const buildEnv = (service: ResolvedService, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv => ({\n ...base,\n ...service.env,\n LARACREW: '1',\n LARACREW_SERVICE: service.name,\n ...(service.project ? { LARACREW_PROJECT: service.project.key } : {}),\n});\n\nexport interface SpawnedChild {\n child: ChildProcess;\n description: string;\n}\n\nexport const spawnService = (service: ResolvedService, base: NodeJS.ProcessEnv = process.env): SpawnedChild => {\n const command = service.command;\n if (!command) throw new Error(`service \"${service.name}\" has no command to run`);\n\n const options: SpawnOptions = {\n cwd: service.cwd,\n env: buildEnv(service, base),\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n // POSIX: a new process group means one kill(-pid) takes the whole tree down.\n // Windows has no equivalent, so stop.ts uses `taskkill /T` there instead.\n detached: !IS_WINDOWS,\n };\n\n const child =\n command.kind === 'shell'\n ? spawn(command.line, { ...options, shell: true })\n : spawn(command.file, command.args, { ...options, shell: needsShell(command.file) });\n\n return { child, description: describeCommand(command) };\n};\n\n/** Runs a short-lived command to completion; used for artisan hooks and task steps. */\nexport const runOnce = (\n command: Command,\n options: { cwd: string; env?: NodeJS.ProcessEnv; timeoutMs?: number },\n): Promise<{ code: number | null; stdout: string; stderr: string }> =>\n new Promise((resolve, reject) => {\n const spawnOptions: SpawnOptions = {\n cwd: options.cwd,\n env: options.env ?? process.env,\n stdio: ['ignore', 'pipe', 'pipe'],\n windowsHide: true,\n };\n\n const child =\n command.kind === 'shell'\n ? spawn(command.line, { ...spawnOptions, shell: true })\n : spawn(command.file, command.args, { ...spawnOptions, shell: needsShell(command.file) });\n\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf8');\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n stderr += chunk.toString('utf8');\n });\n\n const timer = options.timeoutMs\n ? setTimeout(() => {\n child.kill('SIGKILL');\n }, options.timeoutMs)\n : undefined;\n timer?.unref?.();\n\n child.once('error', (error) => {\n if (timer) clearTimeout(timer);\n reject(error);\n });\n child.once('close', (code) => {\n if (timer) clearTimeout(timer);\n resolve({ code, stdout, stderr });\n });\n });\n","import type { EventListener, LaracrewEvent } from './types.js';\n\n/**\n * Deliberately not an EventEmitter: subscribers get *every* event, which keeps the\n * renderers dumb and makes the daemon's IPC stream a straight passthrough.\n */\nexport class EventBus {\n #listeners = new Set<EventListener>();\n\n subscribe(listener: EventListener): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n emit(event: LaracrewEvent): void {\n for (const listener of this.#listeners) {\n try {\n listener(event);\n } catch (error) {\n // A broken renderer must never take the supervisor down with it.\n process.emitWarning(\n `laracrew: event listener threw: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n /** Resolves on the first event matching `predicate`, or rejects on timeout. */\n next(predicate: (event: LaracrewEvent) => boolean, timeoutMs = 10_000): Promise<LaracrewEvent> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n unsubscribe();\n reject(new Error('timed out waiting for event'));\n }, timeoutMs);\n timer.unref?.();\n\n const unsubscribe = this.subscribe((event) => {\n if (!predicate(event)) return;\n clearTimeout(timer);\n unsubscribe();\n resolve(event);\n });\n });\n }\n\n get size(): number {\n return this.#listeners.size;\n }\n}\n","import path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { readProjectEnv } from '../laravel/env.js';\nimport { ConfigError, didYouMean } from './errors.js';\nimport { interpolateDeep, type InterpolationContext } from './interpolate.js';\nimport type { LoadedStack } from './load.js';\nimport {\n backoffSchema,\n stopPolicySchema,\n type Backoff,\n type MetricsConfig,\n type ProjectConfig,\n type ReadyProbe,\n type RestartPolicy,\n type ServiceConfig,\n type StopPolicy,\n type WatchConfig,\n} from './schema.js';\n\nexport type Command =\n | { kind: 'shell'; line: string }\n | { kind: 'argv'; file: string; args: string[] };\n\nexport interface ResolvedProject {\n key: string;\n path: string;\n php: string;\n envFile: string;\n env: Record<string, string>;\n color: string;\n}\n\n/** Step 1 of the stop ladder, already resolved to something runnable. */\nexport interface GracefulStop {\n command: Command;\n cwd: string;\n}\n\nexport interface ResolvedService {\n name: string;\n project?: ResolvedProject;\n command?: Command;\n /** From `stop.exec`, or from `stop.artisan` on a project. Absent = go straight to the signal. */\n graceful?: GracefulStop;\n cwd: string;\n env: Record<string, string>;\n groups: string[];\n needs: string[];\n ready?: ReadyProbe;\n restart: RestartPolicy;\n backoff: Backoff;\n stop: StopPolicy;\n watch?: WatchConfig;\n metrics?: MetricsConfig;\n url?: string;\n external: boolean;\n /** false = created but not launched by `up`; the user starts it on demand. */\n autostart: boolean;\n color: string;\n}\n\nexport interface ResolvedStack {\n name: string;\n description?: string;\n dir: string;\n file: string;\n services: ResolvedService[];\n /** Topologically sorted groups; everything in a level can start in parallel. */\n levels: string[][];\n projects: Record<string, ResolvedProject>;\n ports: number[];\n logs: { maxLines: number; toFile: boolean; maxFileBytes: number; keepFiles: number };\n}\n\nexport interface ResolveOptions {\n profile?: string;\n only?: string[];\n except?: string[];\n env?: NodeJS.ProcessEnv;\n sharedProjects?: Record<string, ProjectConfig>;\n}\n\nconst PALETTE = ['cyan', 'magenta', 'green', 'yellow', 'blue', 'red'] as const;\n\nconst toCommand = (cmd: string | string[]): Command =>\n Array.isArray(cmd)\n ? { kind: 'argv', file: cmd[0]!, args: cmd.slice(1) }\n : { kind: 'shell', line: cmd };\n\n/** Matches a service against a selector: its exact name, or one of its groups. */\nconst matches = (service: ResolvedService, selectors: string[]): boolean =>\n selectors.some((selector) => service.name === selector || service.groups.includes(selector));\n\nconst resolveProjects = (\n stack: LoadedStack,\n shared: Record<string, ProjectConfig>,\n): Record<string, ResolvedProject> => {\n const wanted = new Map<string, ProjectConfig>();\n\n for (const key of stack.config.use) {\n const project = shared[key];\n if (!project) {\n const suggestion = didYouMean(key, Object.keys(shared));\n throw new ConfigError(\n `\\`use:\\` refers to project \"${key}\", which is not in projects.yaml` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n wanted.set(key, project);\n }\n // Inline definitions win over shared ones with the same key.\n for (const [key, project] of Object.entries(stack.config.projects)) wanted.set(key, project);\n\n const out: Record<string, ResolvedProject> = {};\n let index = 0;\n for (const [key, project] of wanted) {\n const root = path.resolve(project.path);\n out[key] = {\n key,\n path: root,\n php: project.php,\n envFile: project.envFile,\n env: readProjectEnv(root, project.envFile),\n color: project.color ?? PALETTE[index % PALETTE.length]!,\n };\n index += 1;\n }\n return out;\n};\n\nconst mergeService = (\n raw: ServiceConfig,\n stack: LoadedStack,\n projects: Record<string, ResolvedProject>,\n ports: Set<number>,\n processEnv: NodeJS.ProcessEnv,\n colorIndex: number,\n): ResolvedService => {\n const defaults = stack.config.defaults;\n\n let project: ResolvedProject | undefined;\n if (raw.project) {\n project = projects[raw.project];\n if (!project) {\n const suggestion = didYouMean(raw.project, Object.keys(projects));\n throw new ConfigError(\n `service \"${raw.name}\" refers to project \"${raw.project}\", which this stack does not define` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n }\n\n const ctx: InterpolationContext = {\n env: processEnv,\n stackDir: stack.dir,\n ports,\n ...(project ? { project: { path: project.path, env: project.env } } : {}),\n };\n\n let service: ServiceConfig;\n try {\n service = interpolateDeep(raw, ctx);\n } catch (error) {\n if (error instanceof ConfigError) {\n throw new ConfigError(`service \"${raw.name}\": ${error.message}`, { file: stack.file, cause: error });\n }\n throw error;\n }\n\n const cwd = service.cwd\n ? path.resolve(project?.path ?? stack.dir, service.cwd)\n : (project?.path ?? stack.dir);\n\n // A service declaring its own graceful step replaces the inherited one, whichever kind it is.\n const inheritedStop = { ...defaults.stop };\n const ownStop = service.stop ?? {};\n if (ownStop.exec !== undefined) delete inheritedStop.artisan;\n if (ownStop.artisan !== undefined) delete inheritedStop.exec;\n const stop = stopPolicySchema.parse({ ...inheritedStop, ...ownStop });\n\n if (stop.exec !== undefined && stop.artisan !== undefined) {\n throw new ConfigError(\n `service \"${service.name}\" declares both \\`stop.exec\\` and \\`stop.artisan\\``,\n { file: stack.file, details: ['keep one — `artisan` is only shorthand for an `exec` that runs artisan'] },\n );\n }\n if (stop.artisan !== undefined && !project) {\n throw new ConfigError(\n `service \"${service.name}\" declares \\`stop.artisan\\` but belongs to no project`,\n {\n file: stack.file,\n details: ['`artisan` runs `<project php> artisan ...`, so it needs a project', 'for any other command use `stop.exec`'],\n },\n );\n }\n\n const graceful: GracefulStop | undefined = stop.exec\n ? { command: toCommand(stop.exec), cwd }\n : stop.artisan && project\n ? // artisan must run from the Laravel root even when the service sets its own cwd.\n { command: { kind: 'argv', file: project.php, args: ['artisan', ...stop.artisan.split(/\\s+/)] }, cwd: project.path }\n : undefined;\n\n return {\n name: service.name,\n ...(project ? { project } : {}),\n ...(service.cmd ? { command: toCommand(service.cmd) } : {}),\n ...(graceful ? { graceful } : {}),\n cwd,\n env: { ...service.env },\n groups: service.groups,\n needs: service.needs,\n ...(service.ready ? { ready: service.ready } : {}),\n restart: service.restart ?? defaults.restart,\n backoff: backoffSchema.parse({ ...defaults.backoff, ...(service.backoff ?? {}) }),\n stop,\n ...(service.watch ? { watch: service.watch } : {}),\n ...(service.metrics ? { metrics: service.metrics } : {}),\n ...(service.url ? { url: service.url } : {}),\n external: service.external,\n autostart: service.autostart,\n color: service.color ?? project?.color ?? PALETTE[colorIndex % PALETTE.length]!,\n };\n};\n\n/**\n * Kahn's algorithm, but it keeps each \"level\" so the supervisor can start independent\n * services in parallel instead of one at a time. Throws with the actual cycle members.\n */\nexport const topoLevels = (services: ResolvedService[], file?: string): string[][] => {\n const names = new Set(services.map((s) => s.name));\n const remaining = new Map<string, Set<string>>();\n\n for (const service of services) {\n for (const need of service.needs) {\n if (!names.has(need)) {\n const suggestion = didYouMean(need, [...names]);\n throw new ConfigError(\n `service \"${service.name}\" needs \"${need}\", which is not in this stack` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n file ? { file } : {},\n );\n }\n }\n remaining.set(service.name, new Set(service.needs));\n }\n\n const levels: string[][] = [];\n const done = new Set<string>();\n\n while (done.size < services.length) {\n const level = [...remaining.entries()]\n .filter(([name, needs]) => !done.has(name) && [...needs].every((need) => done.has(need)))\n .map(([name]) => name);\n\n if (level.length === 0) {\n const stuck = services.filter((s) => !done.has(s.name)).map((s) => s.name);\n throw new ConfigError(\n `dependency cycle between: ${stuck.join(' -> ')}`,\n file ? { file } : {},\n );\n }\n\n for (const name of level) done.add(name);\n levels.push(level);\n }\n\n return levels;\n};\n\nexport const resolveStack = (stack: LoadedStack, options: ResolveOptions = {}): ResolvedStack => {\n const processEnv = options.env ?? process.env;\n const projects = resolveProjects(stack, options.sharedProjects ?? {});\n const ports = new Set<number>();\n\n const seen = new Set<string>();\n for (const service of stack.config.services) {\n if (seen.has(service.name)) {\n throw new ConfigError(`two services are both named \"${service.name}\"`, { file: stack.file });\n }\n seen.add(service.name);\n }\n\n let services = stack.config.services\n .filter((service) => service.enabled)\n .map((service, index) => mergeService(service, stack, projects, ports, processEnv, index));\n\n // Profile first, then explicit CLI flags, so --only can override a profile.\n const profile = options.profile ? stack.config.profiles[options.profile] : undefined;\n if (options.profile && !profile) {\n const suggestion = didYouMean(options.profile, Object.keys(stack.config.profiles));\n throw new ConfigError(\n `no profile \"${options.profile}\" in this stack` + (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { file: stack.file },\n );\n }\n\n const only = options.only?.length ? options.only : profile?.only;\n const except = options.except?.length ? options.except : profile?.except;\n\n if (only?.length) services = services.filter((service) => matches(service, only));\n if (except?.length) services = services.filter((service) => !matches(service, except));\n\n if (services.length === 0) {\n throw new ConfigError('the selection matched no services', { file: stack.file });\n }\n\n // A filtered-out dependency must not block the survivors.\n const kept = new Set(services.map((service) => service.name));\n services = services.map((service) => ({\n ...service,\n needs: service.needs.filter((need) => kept.has(need)),\n }));\n\n // An auto-started service cannot depend on one the user has to start by hand — that would\n // leave it waiting on a gate nobody opened.\n const manual = new Set(\n services.filter((service) => !service.autostart && !service.external).map((service) => service.name),\n );\n for (const service of services) {\n if (!service.autostart) continue;\n const blocked = service.needs.filter((need) => manual.has(need));\n if (blocked.length > 0) {\n throw new ConfigError(\n `service \"${service.name}\" starts at launch but needs \"${blocked.join('\", \"')}\", which ${\n blocked.length === 1 ? 'does' : 'do'\n } not`,\n { file: stack.file, details: ['give it `autostart: false` too, or start the dependency at launch'] },\n );\n }\n }\n\n for (const service of services) {\n if (!service.external && !existsSync(service.cwd)) {\n throw new ConfigError(\n `service \"${service.name}\" has cwd \"${service.cwd}\", which does not exist`,\n { file: stack.file },\n );\n }\n }\n\n return {\n name: stack.config.name,\n ...(stack.config.description ? { description: stack.config.description } : {}),\n dir: stack.dir,\n file: stack.file,\n services,\n levels: topoLevels(services, stack.file),\n projects,\n ports: [...ports].sort((a, b) => a - b),\n logs: stack.config.defaults.logs,\n };\n};\n","import { readFileSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * A .env reader with no side effects — it never touches process.env, because laracrew\n * reads several projects' files in one run and they routinely disagree.\n */\nexport const parseEnv = (content: string): Record<string, string> => {\n const out: Record<string, string> = {};\n\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === '' || line.startsWith('#')) continue;\n\n const withoutExport = line.startsWith('export ') ? line.slice('export '.length).trim() : line;\n const eq = withoutExport.indexOf('=');\n if (eq === -1) continue;\n\n const key = withoutExport.slice(0, eq).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_.]*$/.test(key)) continue;\n\n let value = withoutExport.slice(eq + 1).trim();\n\n if (\n (value.startsWith('\"') && value.endsWith('\"') && value.length >= 2) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\") && value.length >= 2)\n ) {\n const quote = value[0];\n value = value.slice(1, -1);\n // Only double quotes carry escapes, matching Laravel/phpdotenv behaviour.\n if (quote === '\"') value = value.replace(/\\\\n/g, '\\n').replace(/\\\\r/g, '\\r').replace(/\\\\\"/g, '\"');\n } else {\n const hash = value.indexOf(' #');\n if (hash !== -1) value = value.slice(0, hash).trim();\n }\n\n out[key] = value;\n }\n\n return out;\n};\n\n/** Reads `<projectPath>/<envFile>`; a missing file is not an error, just an empty environment. */\nexport const readProjectEnv = (projectPath: string, envFile = '.env'): Record<string, string> => {\n try {\n return parseEnv(readFileSync(path.join(projectPath, envFile), 'utf8'));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return {};\n throw error;\n }\n};\n","import { ConfigError } from './errors.js';\n\nexport interface InterpolationContext {\n /** process env of laracrew itself */\n env: NodeJS.ProcessEnv;\n /** the current service's project, when it has one */\n project?: { path: string; env: Record<string, string> };\n /** the stack's own folder, for hooks and fragments */\n stackDir?: string;\n /** collected by ${port:N} so `doctor` can report clashes */\n ports?: Set<number>;\n}\n\nconst TOKEN = /\\$\\{([^}]*)\\}/g;\n\nconst splitOnce = (input: string, separator: string): [string, string | undefined] => {\n const index = input.indexOf(separator);\n return index === -1 ? [input, undefined] : [input.slice(0, index), input.slice(index + separator.length)];\n};\n\n/**\n * Supported tokens:\n * ${env:FOO} laracrew's own environment\n * ${env:FOO:fallback} with a default when unset\n * ${project.path} the service's project root\n * ${project.env:REDIS_PORT} a value from that project's .env\n * ${stack.dir} the stack folder\n * ${port:8000} a port, recorded for collision checks\n */\nexport const interpolate = (input: string, ctx: InterpolationContext): string =>\n input.replace(TOKEN, (match, body: string) => {\n const [scheme, rest] = splitOnce(body.trim(), ':');\n\n switch (scheme) {\n case 'env': {\n if (!rest) throw new ConfigError(`\\${env:...} needs a variable name, got \"${match}\"`);\n const [key, fallback] = splitOnce(rest, ':');\n const value = ctx.env[key];\n if (value !== undefined) return value;\n if (fallback !== undefined) return fallback;\n throw new ConfigError(`environment variable \"${key}\" is not set (used in \"${match}\")`);\n }\n\n case 'project.path': {\n if (!ctx.project) throw new ConfigError(`\"${match}\" used on a service that has no \\`project\\``);\n return ctx.project.path;\n }\n\n case 'project.env': {\n if (!ctx.project) throw new ConfigError(`\"${match}\" used on a service that has no \\`project\\``);\n if (!rest) throw new ConfigError(`\\${project.env:...} needs a variable name, got \"${match}\"`);\n const [key, fallback] = splitOnce(rest, ':');\n const value = ctx.project.env[key];\n if (value !== undefined) return value;\n if (fallback !== undefined) return fallback;\n throw new ConfigError(`\"${key}\" is not in the project's .env (used in \"${match}\")`);\n }\n\n case 'stack.dir': {\n if (!ctx.stackDir) throw new ConfigError(`\"${match}\" used outside a stack folder`);\n return ctx.stackDir;\n }\n\n case 'port': {\n const port = Number(rest);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`\"${match}\" is not a valid port number`);\n }\n ctx.ports?.add(port);\n return String(port);\n }\n\n default:\n throw new ConfigError(\n `unknown token \"${match}\" — supported: \\${env:VAR}, \\${project.path}, \\${project.env:VAR}, \\${stack.dir}, \\${port:N}`,\n );\n }\n });\n\n/** Walks any parsed-YAML value and interpolates every string in it. */\nexport const interpolateDeep = <T>(value: T, ctx: InterpolationContext): T => {\n if (typeof value === 'string') return interpolate(value, ctx) as unknown as T;\n if (Array.isArray(value)) return value.map((item) => interpolateDeep(item, ctx)) as unknown as T;\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n // Guard against prototype pollution from a hand-written YAML file.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n out[key] = interpolateDeep(item, ctx);\n }\n return out as unknown as T;\n }\n return value;\n};\n","import path from 'node:path';\nimport type { ResolvedStack } from '../config/resolve.js';\nimport type { EventBus } from '../events/bus.js';\nimport { isLive, type ServiceState } from '../events/types.js';\nimport { LogWriter } from '../logs/file-sink.js';\nimport { paths } from '../config/paths.js';\nimport { ManagedProcess } from './managed-process.js';\n\nexport interface SupervisorOptions {\n env?: NodeJS.ProcessEnv;\n /** Override where log files land. Defaults to ~/.laracrew/logs/<stack>. */\n logDir?: string;\n}\n\nexport interface ServiceSnapshot {\n name: string;\n state: ServiceState;\n pid?: number;\n uptimeMs?: number;\n restarts: number;\n autostart: boolean;\n groups: string[];\n project?: string;\n url?: string;\n command?: string;\n external: boolean;\n color: string;\n}\n\n/**\n * Owns the whole fleet: starts it in dependency order, stops it in reverse, and never\n * leaves a half-started stack behind when a readiness gate fails.\n */\nexport class Supervisor {\n readonly stack: ResolvedStack;\n\n #bus: EventBus;\n #processes = new Map<string, ManagedProcess>();\n #startedOrder: string[] = [];\n #shuttingDown = false;\n #logWriter?: LogWriter;\n\n constructor(stack: ResolvedStack, bus: EventBus, options: SupervisorOptions = {}) {\n this.stack = stack;\n this.#bus = bus;\n\n for (const service of stack.services) {\n this.#processes.set(\n service.name,\n new ManagedProcess(service, bus, {\n logCapacity: stack.logs.maxLines,\n ...(options.env ? { env: options.env } : {}),\n }),\n );\n }\n\n if (stack.logs.toFile) {\n this.#logWriter = new LogWriter({\n dir: options.logDir ?? path.join(paths(options.env ?? process.env).logsDir, stack.name),\n services: stack.services.map((service) => service.name),\n maxBytes: stack.logs.maxFileBytes,\n keep: stack.logs.keepFiles,\n });\n this.#logWriter.attach(bus);\n }\n }\n\n /** Where a service's output is being written, if anywhere. */\n logFileFor(service: string): string | undefined {\n return this.#logWriter?.fileFor(service);\n }\n\n get(name: string): ManagedProcess | undefined {\n return this.#processes.get(name);\n }\n\n get processes(): ManagedProcess[] {\n return [...this.#processes.values()];\n }\n\n snapshot(): ServiceSnapshot[] {\n return this.processes.map((process) => ({\n name: process.service.name,\n state: process.state,\n ...(process.pid !== undefined ? { pid: process.pid } : {}),\n ...(process.uptimeMs !== undefined && isLive(process.state) ? { uptimeMs: process.uptimeMs } : {}),\n restarts: process.restarts,\n autostart: process.service.autostart,\n groups: process.service.groups,\n ...(process.service.project ? { project: process.service.project.key } : {}),\n ...(process.service.url ? { url: process.service.url } : {}),\n external: process.service.external,\n color: process.service.color,\n }));\n }\n\n /**\n * Starts every level in order; everything inside a level goes in parallel.\n * A failure rolls back what already started, so Ctrl-C is never needed to clean up.\n */\n async up(): Promise<void> {\n const startedAt = Date.now();\n this.#bus.emit({\n type: 'stack:starting',\n stack: this.stack.name,\n services: this.stack.services.map((service) => service.name),\n at: startedAt,\n });\n\n for (const level of this.stack.levels) {\n // `autostart: false` services stay in `queued` — defined, visible, startable on demand.\n const toStart = level.filter((name) => this.#processes.get(name)?.service.autostart !== false);\n\n const results = await Promise.allSettled(\n toStart.map(async (name) => {\n const process = this.#processes.get(name)!;\n await process.start();\n this.#startedOrder.push(name);\n }),\n );\n\n const failures = results\n .map((result, index) => ({ result, name: toStart[index]! }))\n .filter((entry): entry is { result: PromiseRejectedResult; name: string } => entry.result.status === 'rejected');\n\n if (failures.length > 0) {\n const reasons = failures.map((failure) => {\n const error: unknown = failure.result.reason;\n return error instanceof Error ? error.message : String(error);\n });\n for (const reason of reasons) {\n this.#bus.emit({ type: 'notice', level: 'error', message: reason, at: Date.now() });\n }\n await this.down('boot failed');\n throw new Error(`could not boot \"${this.stack.name}\":\\n ${reasons.join('\\n ')}`);\n }\n }\n\n this.#bus.emit({\n type: 'stack:ready',\n stack: this.stack.name,\n durationMs: Date.now() - startedAt,\n at: Date.now(),\n });\n }\n\n /** Reverse topological order, parallel within a level. */\n async down(reason?: string): Promise<void> {\n if (this.#shuttingDown) return;\n this.#shuttingDown = true;\n\n this.#bus.emit({ type: 'stack:stopping', stack: this.stack.name, at: Date.now() });\n if (reason) {\n this.#bus.emit({ type: 'notice', level: 'info', message: `stopping: ${reason}`, at: Date.now() });\n }\n\n for (const level of [...this.stack.levels].reverse()) {\n await Promise.all(\n level.map(async (name) => {\n const process = this.#processes.get(name);\n if (!process) return;\n try {\n await process.dispose();\n } catch (error) {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: name,\n message: `stop failed: ${error instanceof Error ? error.message : String(error)}`,\n at: Date.now(),\n });\n }\n }),\n );\n }\n\n this.#bus.emit({ type: 'stack:stopped', stack: this.stack.name, at: Date.now() });\n // Flush and close the log files last, so the shutdown itself is recorded.\n await this.#logWriter?.close();\n this.#shuttingDown = false;\n }\n\n async restart(name: string): Promise<void> {\n const process = this.#requireProcess(name);\n await process.restart();\n }\n\n /**\n * Restarts every service that is `running` right now and nothing else: a stopped or idle\n * service stays where it is, a failed one is not resurrected, one still starting is left to\n * finish. Dependency order, parallel within a level, so a dependency is back and ready\n * before the services that need it are bounced. Returns the names restarted, in that order.\n */\n async restartRunning(): Promise<string[]> {\n const isTarget = (process: ManagedProcess): boolean => !process.service.external && process.state === 'running';\n const wanted = new Set(this.processes.filter(isTarget).map((process) => process.service.name));\n if (wanted.size === 0) return [];\n\n this.#bus.emit({\n type: 'notice',\n level: 'info',\n message: `restarting ${wanted.size} running service${wanted.size === 1 ? '' : 's'}: ${[...wanted].join(', ')}`,\n at: Date.now(),\n });\n\n const restarted = new Set<string>();\n for (const level of this.stack.levels) {\n await Promise.all(\n level\n .filter((name) => wanted.has(name))\n .map(async (name) => {\n const process = this.#processes.get(name)!;\n // It was running when the key was pressed; if it died or was stopped since, leave it.\n if (!isTarget(process)) return;\n try {\n await process.restart();\n restarted.add(name);\n } catch (error) {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: name,\n message: `restart failed: ${error instanceof Error ? error.message : String(error)}`,\n at: Date.now(),\n });\n }\n }),\n );\n }\n\n return this.stack.levels.flat().filter((name) => restarted.has(name));\n }\n\n async stopService(name: string): Promise<void> {\n await this.#requireProcess(name).stop();\n }\n\n async startService(name: string): Promise<void> {\n await this.#requireProcess(name).start();\n }\n\n /** Every service carrying `group`, in dependency order. */\n servicesInGroup(group: string): string[] {\n return this.stack.services.filter((service) => service.groups.includes(group)).map((service) => service.name);\n }\n\n #requireProcess(name: string): ManagedProcess {\n const process = this.#processes.get(name);\n if (!process) {\n const available = [...this.#processes.keys()].join(', ');\n throw new Error(`no service \"${name}\" in stack \"${this.stack.name}\". Available: ${available}`);\n }\n return process;\n }\n}\n","/**\n * The single vocabulary every renderer speaks. `core/` emits these; the TUI, the plain\n * printer, the JSON printer and the daemon's IPC stream are all just subscribers.\n * Nothing in core may import a renderer.\n */\n\nexport type ServiceState =\n | 'queued'\n | 'starting'\n | 'ready'\n | 'running'\n | 'stopping'\n | 'stopped'\n | 'crashed'\n | 'backoff'\n | 'failed';\n\n/** States from which the service is not going to produce more output on its own. */\nexport const TERMINAL_STATES: ReadonlySet<ServiceState> = new Set(['stopped', 'failed']);\n\nexport const isLive = (state: ServiceState): boolean =>\n state === 'starting' || state === 'ready' || state === 'running';\n\nexport interface LogLine {\n service: string;\n stream: 'stdout' | 'stderr' | 'system';\n line: string;\n at: number;\n}\n\nexport type LaracrewEvent =\n | { type: 'stack:starting'; stack: string; services: string[]; at: number }\n | { type: 'stack:ready'; stack: string; durationMs: number; at: number }\n | { type: 'stack:stopping'; stack: string; at: number }\n | { type: 'stack:stopped'; stack: string; at: number }\n | {\n type: 'service:state';\n service: string;\n from: ServiceState;\n to: ServiceState;\n detail?: string;\n at: number;\n }\n | { type: 'service:spawned'; service: string; pid: number; command: string; cwd: string; at: number }\n | { type: 'service:ready'; service: string; durationMs: number; probe: string; at: number }\n | {\n type: 'service:exit';\n service: string;\n code: number | null;\n signal: NodeJS.Signals | null;\n intentional: boolean;\n at: number;\n }\n | { type: 'service:restart'; service: string; attempt: number; maxAttempts: number; delayMs: number; at: number }\n | { type: 'service:log'; log: LogLine }\n | { type: 'notice'; level: 'info' | 'warn' | 'error'; message: string; service?: string; at: number };\n\nexport type EventListener = (event: LaracrewEvent) => void;\n","import { closeSync, existsSync, mkdirSync, openSync, renameSync, rmSync, statSync, writeSync } from 'node:fs';\nimport path from 'node:path';\nimport { stripAnsi } from './sanitize.js';\nimport type { EventBus } from '../events/bus.js';\nimport type { LogLine } from '../events/types.js';\n\n/**\n * In-memory ring buffers hold three minutes of a busy stack. \"I saw an exception scroll past\n * and now it's gone\" is the single fastest way to stop trusting a process manager, so every\n * line also goes to disk.\n *\n * Files are plain text with a sortable local timestamp and no ANSI, so `grep` and `--since`\n * both work on them.\n */\n\nexport interface FileSinkOptions {\n maxBytes: number;\n /** How many rotated files to keep beside the current one. */\n keep: number;\n}\n\n/** `2026-09-19 11:23:45.123` — local time, because you think in local time. */\nexport const stamp = (at: number): string => {\n const date = new Date(at);\n const pad = (value: number, width = 2): string => String(value).padStart(width, '0');\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`\n );\n};\n\n/** Parses a line written by this sink back into its parts. */\nexport const parseLine = (raw: string): { at: number; stream: string; line: string } | undefined => {\n const match = /^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}) (stdout|stderr|system) (.*)$/s.exec(raw);\n if (!match) return undefined;\n const at = new Date(match[1]!.replace(' ', 'T')).getTime();\n return { at: Number.isNaN(at) ? 0 : at, stream: match[2]!, line: match[3]! };\n};\n\n/** `api:queue` is not a legal Windows filename. */\nexport const safeFileName = (service: string): string =>\n service.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'service';\n\n/**\n * Builds one filename per service, disambiguating the rare case where two service names\n * sanitise to the same thing (`api:queue` and `api-queue`).\n */\nexport const fileNamesFor = (services: readonly string[]): Map<string, string> => {\n const used = new Set<string>();\n const out = new Map<string, string>();\n\n for (const service of services) {\n const base = safeFileName(service);\n let candidate = base;\n let index = 2;\n while (used.has(candidate)) candidate = `${base}-${index++}`;\n used.add(candidate);\n out.set(service, `${candidate}.log`);\n }\n\n return out;\n};\n\n/**\n * One append-only file, rotated by size.\n *\n * Writes go through a held file descriptor with `writeSync` rather than a WriteStream. A\n * stream's `end()` is asynchronous, so rotation would rename the file while the handle was\n * still open — which Windows refuses outright, silently costing you the rotation. A\n * descriptor closes deterministically, and a synchronous write also means a line is on disk\n * before the process that logged it can crash.\n */\nexport class FileSink {\n readonly file: string;\n #fd?: number;\n #bytes = 0;\n #closed = false;\n readonly #options: FileSinkOptions;\n\n constructor(file: string, options: FileSinkOptions) {\n this.file = file;\n this.#options = options;\n }\n\n #open(): number | undefined {\n if (this.#fd !== undefined) return this.#fd;\n\n try {\n mkdirSync(path.dirname(this.file), { recursive: true });\n this.#bytes = existsSync(this.file) ? statSync(this.file).size : 0;\n this.#fd = openSync(this.file, 'a');\n return this.#fd;\n } catch {\n // A disk problem must never take the supervisor down with it.\n this.#closed = true;\n return undefined;\n }\n }\n\n write(entry: LogLine): void {\n if (this.#closed) return;\n\n const fd = this.#open();\n if (fd === undefined) return;\n\n const text = `${stamp(entry.at)} ${entry.stream} ${stripAnsi(entry.line)}\\n`;\n try {\n writeSync(fd, text);\n } catch {\n this.#closeHandle();\n this.#closed = true;\n return;\n }\n\n this.#bytes += Buffer.byteLength(text);\n if (this.#bytes >= this.#options.maxBytes) this.#rotate();\n }\n\n #closeHandle(): void {\n if (this.#fd === undefined) return;\n try {\n closeSync(this.#fd);\n } catch {\n /* already gone */\n }\n this.#fd = undefined;\n }\n\n #rotate(): void {\n // The handle must be closed before the rename, or Windows rejects it outright.\n this.#closeHandle();\n this.#bytes = 0;\n\n try {\n if (this.#options.keep <= 0) {\n rmSync(this.file, { force: true });\n return;\n }\n\n // Drop the oldest, shift the rest along, then move the current file to .1\n const oldest = `${this.file}.${this.#options.keep}`;\n if (existsSync(oldest)) rmSync(oldest, { force: true });\n\n for (let index = this.#options.keep - 1; index >= 1; index -= 1) {\n const from = `${this.file}.${index}`;\n if (existsSync(from)) renameSync(from, `${this.file}.${index + 1}`);\n }\n\n if (existsSync(this.file)) renameSync(this.file, `${this.file}.1`);\n } catch {\n // Losing a rotation is survivable; losing the process is not.\n }\n }\n\n close(): Promise<void> {\n this.#closed = true;\n this.#closeHandle();\n return Promise.resolve();\n }\n}\n\nexport interface LogWriterOptions {\n dir: string;\n services: readonly string[];\n maxBytes?: number;\n keep?: number;\n}\n\n/**\n * Routes every `service:log` event to the right file. Lives in core and subscribes to the\n * bus like any other renderer, so it works identically under the TUI, `--plain` and `--json`.\n */\nexport class LogWriter {\n readonly dir: string;\n readonly #sinks = new Map<string, FileSink>();\n readonly #names: Map<string, string>;\n #unsubscribe?: () => void;\n\n constructor(options: LogWriterOptions) {\n this.dir = options.dir;\n this.#names = fileNamesFor(options.services);\n\n const sinkOptions: FileSinkOptions = {\n maxBytes: options.maxBytes ?? 5_000_000,\n keep: options.keep ?? 1,\n };\n for (const [service, fileName] of this.#names) {\n this.#sinks.set(service, new FileSink(path.join(this.dir, fileName), sinkOptions));\n }\n }\n\n /** The file a given service writes to — used by `laracrew logs`. */\n fileFor(service: string): string | undefined {\n const name = this.#names.get(service);\n return name ? path.join(this.dir, name) : undefined;\n }\n\n attach(bus: EventBus): () => void {\n this.#unsubscribe = bus.subscribe((event) => {\n if (event.type !== 'service:log') return;\n this.#sinks.get(event.log.service)?.write(event.log);\n });\n return this.#unsubscribe;\n }\n\n async close(): Promise<void> {\n this.#unsubscribe?.();\n this.#unsubscribe = undefined;\n await Promise.all([...this.#sinks.values()].map((sink) => sink.close()));\n }\n}\n","import type { LogLine } from '../events/types.js';\n\n/**\n * Bounded per-service history. A chatty worker must not grow the heap forever, and the\n * TUI only ever renders a window of this anyway.\n */\nexport class RingBuffer<T = LogLine> {\n #items: (T | undefined)[];\n #next = 0;\n #count = 0;\n #dropped = 0;\n\n constructor(readonly capacity: number) {\n if (!Number.isInteger(capacity) || capacity < 1) {\n throw new RangeError(`RingBuffer capacity must be a positive integer, got ${capacity}`);\n }\n this.#items = Array.from({ length: capacity });\n }\n\n push(item: T): void {\n if (this.#count === this.capacity) this.#dropped += 1;\n this.#items[this.#next] = item;\n this.#next = (this.#next + 1) % this.capacity;\n this.#count = Math.min(this.#count + 1, this.capacity);\n }\n\n /** Oldest to newest. */\n toArray(): T[] {\n const out: T[] = [];\n const start = this.#count === this.capacity ? this.#next : 0;\n for (let i = 0; i < this.#count; i += 1) {\n out.push(this.#items[(start + i) % this.capacity]!);\n }\n return out;\n }\n\n /** The last `n` items, oldest to newest — what a log pane actually needs. */\n tail(n: number): T[] {\n if (n >= this.#count) return this.toArray();\n const out: T[] = [];\n for (let i = this.#count - n; i < this.#count; i += 1) {\n const start = this.#count === this.capacity ? this.#next : 0;\n out.push(this.#items[(start + i) % this.capacity]!);\n }\n return out;\n }\n\n clear(): void {\n this.#items = Array.from({ length: this.capacity });\n this.#next = 0;\n this.#count = 0;\n this.#dropped = 0;\n }\n\n get size(): number {\n return this.#count;\n }\n\n /** How many items fell off the back — worth showing in the UI. */\n get dropped(): number {\n return this.#dropped;\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\nexport const isAlive = (pid: number): boolean => {\n try {\n // Signal 0 performs the permission/existence check without delivering anything.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\n/**\n * `php artisan serve` spawns a child PHP server and `npm run dev` spawns Vite. Killing only\n * the parent orphans those and leaves the port bound — the single most common way a dev\n * process manager ruins your afternoon. So every kill is a tree kill.\n */\nexport const killTree = async (pid: number, signal: NodeJS.Signals = 'SIGKILL'): Promise<void> => {\n if (IS_WINDOWS) {\n await new Promise<void>((resolve) => {\n const killer = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n killer.once('error', () => resolve());\n killer.once('close', () => resolve());\n });\n return;\n }\n\n try {\n // Negative pid = the whole process group created by `detached: true`.\n process.kill(-pid, signal);\n } catch {\n try {\n process.kill(pid, signal);\n } catch {\n /* already gone */\n }\n }\n};\n\nexport const waitForExit = (child: ChildProcess, timeoutMs: number): Promise<boolean> =>\n new Promise((resolve) => {\n if (child.exitCode !== null || child.signalCode !== null) {\n resolve(true);\n return;\n }\n const timer = setTimeout(() => {\n child.removeListener('close', onClose);\n resolve(false);\n }, timeoutMs);\n timer.unref?.();\n\n const onClose = () => {\n clearTimeout(timer);\n resolve(true);\n };\n child.once('close', onClose);\n });\n\nexport interface StopLadderOptions {\n child: ChildProcess;\n /** Step 1: the service's own graceful shutdown, e.g. `php artisan queue:restart`. */\n graceful?: () => Promise<void>;\n signal: NodeJS.Signals;\n graceMs: number;\n onStep?: (step: string) => void;\n}\n\nexport type StopOutcome = 'graceful' | 'signal' | 'tree-kill' | 'already-gone' | 'survived';\n\n/**\n * Ordered stop, each step only attempted if the previous one timed out:\n * 1. Graceful command (the process finishes what it holds, then exits by itself)\n * 2. Signal (POSIX only — Windows has no real SIGTERM)\n * 3. Tree kill (taskkill /T /F, or kill the process group)\n */\nexport const stopLadder = async (options: StopLadderOptions): Promise<StopOutcome> => {\n const { child, graceful, signal, graceMs, onStep } = options;\n const pid = child.pid;\n\n if (pid === undefined || child.exitCode !== null || child.signalCode !== null) return 'already-gone';\n\n if (graceful) {\n onStep?.('graceful');\n try {\n await graceful();\n if (await waitForExit(child, graceMs)) return 'graceful';\n } catch {\n // A failed graceful hook is not fatal; fall through to the harder steps.\n }\n }\n\n if (!IS_WINDOWS) {\n onStep?.('signal');\n try {\n process.kill(-pid, signal);\n } catch {\n try {\n child.kill(signal);\n } catch {\n return 'already-gone';\n }\n }\n if (await waitForExit(child, Math.min(graceMs, 5_000))) return 'signal';\n }\n\n onStep?.('tree-kill');\n await killTree(pid);\n if (await waitForExit(child, 5_000)) return 'tree-kill';\n\n return isAlive(pid) ? 'survived' : 'tree-kill';\n};\n","import type { ChildProcess } from 'node:child_process';\nimport type { ResolvedService } from '../config/resolve.js';\nimport type { EventBus } from '../events/bus.js';\nimport type { LogLine, ServiceState } from '../events/types.js';\nimport { RingBuffer } from '../logs/ring-buffer.js';\nimport { LineSplitter } from '../logs/sanitize.js';\nimport { describeProbe, httpProbe, sleep, tcpProbe, waitFor, type ProbeResult } from '../health/probes.js';\nimport { describeCommand, runOnce, spawnService } from './spawn.js';\nimport { stopLadder } from './stop.js';\n\nexport interface ManagedProcessOptions {\n logCapacity?: number;\n env?: NodeJS.ProcessEnv;\n}\n\n/** One supervised child: its state machine, its logs, and its restart policy. */\nexport class ManagedProcess {\n readonly service: ResolvedService;\n readonly logs: RingBuffer<LogLine>;\n\n #bus: EventBus;\n #env: NodeJS.ProcessEnv;\n #child?: ChildProcess;\n #state: ServiceState = 'queued';\n #intentionalStop = false;\n #restarts = 0;\n #attempt = 0;\n #startedAt?: number;\n #readyAt?: number;\n #backoffTimer?: NodeJS.Timeout;\n #logWatchers = new Set<(line: string) => void>();\n #disposed = false;\n\n constructor(service: ResolvedService, bus: EventBus, options: ManagedProcessOptions = {}) {\n this.service = service;\n this.#bus = bus;\n this.#env = options.env ?? process.env;\n this.logs = new RingBuffer<LogLine>(options.logCapacity ?? 5_000);\n }\n\n get state(): ServiceState {\n return this.#state;\n }\n get pid(): number | undefined {\n return this.#child?.pid;\n }\n get restarts(): number {\n return this.#restarts;\n }\n get startedAt(): number | undefined {\n return this.#startedAt;\n }\n get uptimeMs(): number | undefined {\n return this.#startedAt === undefined ? undefined : Date.now() - this.#startedAt;\n }\n get readyDurationMs(): number | undefined {\n return this.#readyAt !== undefined && this.#startedAt !== undefined ? this.#readyAt - this.#startedAt : undefined;\n }\n\n #setState(to: ServiceState, detail?: string): void {\n if (this.#state === to) return;\n const from = this.#state;\n this.#state = to;\n this.#bus.emit({\n type: 'service:state',\n service: this.service.name,\n from,\n to,\n ...(detail ? { detail } : {}),\n at: Date.now(),\n });\n }\n\n #log(line: string, stream: LogLine['stream'] = 'system'): void {\n const entry: LogLine = { service: this.service.name, stream, line, at: Date.now() };\n this.logs.push(entry);\n this.#bus.emit({ type: 'service:log', log: entry });\n for (const watcher of this.#logWatchers) watcher(line);\n }\n\n /**\n * Spawns (unless external) and resolves once the readiness probe passes.\n * Rejects when the gate fails, which is what aborts a boot.\n */\n async start(): Promise<void> {\n if (this.#disposed) throw new Error(`service \"${this.service.name}\" has been disposed`);\n this.#intentionalStop = false;\n this.#setState('starting');\n this.#startedAt = Date.now();\n this.#readyAt = undefined;\n\n if (this.service.external) {\n await this.#awaitReady();\n return;\n }\n\n const { child, description } = spawnService(this.service, this.#env);\n this.#child = child;\n\n child.once('error', (error) => {\n this.#log(`failed to spawn: ${error.message}`, 'stderr');\n this.#setState('failed', error.message);\n });\n\n this.#pipe(child, 'stdout');\n this.#pipe(child, 'stderr');\n child.once('close', (code, signal) => this.#onExit(code, signal));\n\n if (child.pid !== undefined) {\n this.#bus.emit({\n type: 'service:spawned',\n service: this.service.name,\n pid: child.pid,\n command: description,\n cwd: this.service.cwd,\n at: Date.now(),\n });\n }\n\n await this.#awaitReady();\n }\n\n #pipe(child: ChildProcess, stream: 'stdout' | 'stderr'): void {\n const source = child[stream];\n if (!source) return;\n const splitter = new LineSplitter();\n source.setEncoding('utf8');\n source.on('data', (chunk: string) => {\n for (const line of splitter.push(chunk)) this.#log(line, stream);\n });\n source.once('end', () => {\n for (const line of splitter.flush()) this.#log(line, stream);\n });\n }\n\n async #awaitReady(): Promise<void> {\n const probe = this.service.ready;\n\n if (!probe) {\n this.#readyAt = Date.now();\n this.#setState('running');\n return;\n }\n\n const label = describeProbe(probe);\n const result = await this.#runProbe(probe);\n\n if (!result.ok) {\n this.#setState('failed', `readiness gate failed: ${label}${result.detail ? ` (${result.detail})` : ''}`);\n throw new Error(\n `service \"${this.service.name}\" never became ready: ${label}${result.detail ? ` — ${result.detail}` : ''}`,\n );\n }\n\n this.#readyAt = Date.now();\n this.#bus.emit({\n type: 'service:ready',\n service: this.service.name,\n durationMs: this.readyDurationMs ?? 0,\n probe: label,\n at: Date.now(),\n });\n this.#setState(this.service.external ? 'ready' : 'running');\n }\n\n async #runProbe(probe: NonNullable<ResolvedService['ready']>): Promise<ProbeResult> {\n if (probe.delayMs !== undefined && !probe.tcp && !probe.http && !probe.logMatch) {\n await sleep(probe.delayMs);\n return { ok: true };\n }\n if (probe.logMatch) return this.#waitForLogMatch(probe.logMatch, probe.timeoutMs);\n if (probe.http) {\n const url = probe.http;\n return waitFor(() => httpProbe(url, probe.intervalMs * 4), {\n timeoutMs: probe.timeoutMs,\n intervalMs: probe.intervalMs,\n });\n }\n const target = probe.tcp!;\n return waitFor(() => tcpProbe(target, probe.intervalMs * 4), {\n timeoutMs: probe.timeoutMs,\n intervalMs: probe.intervalMs,\n });\n }\n\n /** Readiness by output, for tools that announce themselves (Vite, Reverb). */\n #waitForLogMatch(source: string, timeoutMs: number): Promise<ProbeResult> {\n let pattern: RegExp;\n try {\n pattern = new RegExp(source);\n } catch (error) {\n return Promise.resolve({ ok: false, detail: `invalid logMatch regex: ${String(error)}` });\n }\n\n // Lines that already arrived count — the child may be faster than this gate.\n for (const entry of this.logs.toArray()) {\n if (pattern.test(entry.line)) return Promise.resolve({ ok: true, detail: 'matched buffered output' });\n }\n\n return new Promise((resolve) => {\n const done = (result: ProbeResult) => {\n clearTimeout(timer);\n this.#logWatchers.delete(watcher);\n resolve(result);\n };\n const watcher = (line: string) => {\n if (pattern.test(line)) done({ ok: true });\n };\n const timer = setTimeout(() => done({ ok: false, detail: 'no matching output' }), timeoutMs);\n timer.unref?.();\n this.#logWatchers.add(watcher);\n });\n }\n\n #onExit(code: number | null, signal: NodeJS.Signals | null): void {\n const wasIntentional = this.#intentionalStop;\n const uptime = this.uptimeMs ?? 0;\n this.#child = undefined;\n\n this.#bus.emit({\n type: 'service:exit',\n service: this.service.name,\n code,\n signal,\n intentional: wasIntentional,\n at: Date.now(),\n });\n\n if (wasIntentional || this.#disposed) {\n this.#setState('stopped');\n return;\n }\n\n // A long, healthy run means the earlier failures are ancient history.\n if (uptime >= this.service.backoff.resetAfterMs) this.#attempt = 0;\n\n const clean = code === 0 && signal === null;\n const policy = this.service.restart;\n const shouldRestart = policy === 'always' || (policy === 'on-failure' && !clean);\n\n this.#setState('crashed', signal ? `killed by ${signal}` : `exit code ${code}`);\n\n if (!shouldRestart) {\n this.#setState(clean ? 'stopped' : 'failed', clean ? undefined : `exited with code ${code}`);\n return;\n }\n\n if (this.#attempt >= this.service.backoff.maxRestarts) {\n this.#setState('failed', `gave up after ${this.#attempt} restarts`);\n return;\n }\n\n this.#attempt += 1;\n this.#restarts += 1;\n const { initialMs, factor, maxMs } = this.service.backoff;\n const delayMs = Math.min(Math.round(initialMs * factor ** (this.#attempt - 1)), maxMs);\n\n this.#setState('backoff', `restarting in ${delayMs}ms`);\n this.#bus.emit({\n type: 'service:restart',\n service: this.service.name,\n attempt: this.#attempt,\n maxAttempts: this.service.backoff.maxRestarts,\n delayMs,\n at: Date.now(),\n });\n\n this.#backoffTimer = setTimeout(() => {\n this.#backoffTimer = undefined;\n if (this.#disposed || this.#intentionalStop) return;\n void this.start().catch((error: unknown) => {\n this.#log(`restart failed: ${error instanceof Error ? error.message : String(error)}`, 'stderr');\n });\n }, delayMs);\n this.#backoffTimer.unref?.();\n }\n\n /**\n * Step 1 of the stop ladder: ask the process to finish what it is holding and exit by\n * itself. What that command is — `queue:restart`, `celery control shutdown`, a drain\n * script — was decided in `resolve.ts`; this only runs it.\n */\n #graceful(): (() => Promise<void>) | undefined {\n const graceful = this.service.graceful;\n if (!graceful) return undefined;\n\n return async () => {\n this.#log(`stop: ${describeCommand(graceful.command)}`);\n await runOnce(graceful.command, { cwd: graceful.cwd, env: this.#env, timeoutMs: 15_000 });\n };\n }\n\n async stop(): Promise<void> {\n this.#intentionalStop = true;\n\n if (this.#backoffTimer) {\n clearTimeout(this.#backoffTimer);\n this.#backoffTimer = undefined;\n }\n\n if (this.service.external) {\n this.#setState('stopped');\n return;\n }\n\n const child = this.#child;\n if (!child) {\n this.#setState('stopped');\n return;\n }\n\n this.#setState('stopping');\n\n const graceful = this.#graceful();\n const outcome = await stopLadder({\n child,\n ...(graceful ? { graceful } : {}),\n signal: this.service.stop.signal as NodeJS.Signals,\n graceMs: this.service.stop.graceMs,\n onStep: (step) => this.#log(`stop: ${step}`),\n });\n\n if (outcome === 'survived') {\n this.#bus.emit({\n type: 'notice',\n level: 'error',\n service: this.service.name,\n message: `process ${child.pid} survived the stop ladder — kill it manually`,\n at: Date.now(),\n });\n }\n\n this.#setState('stopped');\n }\n\n async restart(): Promise<void> {\n await this.stop();\n this.#attempt = 0;\n this.#restarts += 1;\n await this.start();\n }\n\n async dispose(): Promise<void> {\n this.#disposed = true;\n await this.stop();\n this.#logWatchers.clear();\n }\n}\n","import { EventEmitter } from 'node:events';\n\n/**\n * `laracrew up --json | head` closes the pipe under us. Without this, Node turns the EPIPE\n * into an unhandled 'error' event and kills the process — which skips the shutdown path and\n * orphans every child. So a broken pipe is treated as \"the reader left\": stop writing, then\n * shut the stack down cleanly.\n */\n\nexport interface WritableLike extends EventEmitter {\n write(chunk: string): boolean;\n}\n\nlet closed = false;\nconst handlers = new Set<() => void>();\n\nexport const outputClosed = (): boolean => closed;\n\n/** Registers a callback for when stdout goes away. Returns an unsubscribe function. */\nexport const onOutputClosed = (handler: () => void): (() => void) => {\n handlers.add(handler);\n if (closed) handler();\n return () => {\n handlers.delete(handler);\n };\n};\n\nconst markClosed = (): void => {\n if (closed) return;\n closed = true;\n for (const handler of handlers) {\n try {\n handler();\n } catch {\n // Nothing useful left to do — stdout is already gone.\n }\n }\n};\n\nconst isPipeError = (error: NodeJS.ErrnoException): boolean =>\n error.code === 'EPIPE' || error.code === 'ERR_STREAM_DESTROYED' || error.code === 'ERR_STREAM_WRITE_AFTER_END';\n\nexport const installPipeGuards = (streams: WritableLike[] = [process.stdout, process.stderr]): void => {\n for (const stream of streams) {\n stream.on('error', (error: NodeJS.ErrnoException) => {\n if (isPipeError(error)) {\n markClosed();\n return;\n }\n throw error;\n });\n }\n};\n\n/** The write every renderer should use: a no-op once the reader has gone. */\nexport const write = (text: string, stream: WritableLike = process.stdout): void => {\n if (closed) return;\n try {\n stream.write(text);\n } catch (error) {\n if (isPipeError(error as NodeJS.ErrnoException)) markClosed();\n else throw error;\n }\n};\n\n/** Test seam — the module-level flag would otherwise leak between cases. */\nexport const resetOutputState = (): void => {\n closed = false;\n handlers.clear();\n};\n","import type { EventBus } from '../../core/events/bus.js';\nimport type { LaracrewEvent } from '../../core/events/types.js';\nimport type { ResolvedStack } from '../../core/config/resolve.js';\nimport { glyphs, type Glyphs } from '../../tui/theme.js';\nimport { asColorName, padEnd, paint as defaultPaint, type Painter } from './colors.js';\nimport { write as safeWrite } from './output.js';\n\nexport interface PlainRendererOptions {\n stack: ResolvedStack;\n write?: (text: string) => void;\n painter?: Painter;\n glyph?: Glyphs;\n timestamps?: boolean;\n now?: () => Date;\n}\n\ntype Tone = 'info' | 'ok' | 'warn' | 'error';\n\nconst time = (date: Date): string =>\n `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(\n date.getSeconds(),\n ).padStart(2, '0')}`;\n\n/**\n * `concurrently`-style interleaved output: one fixed-width, coloured prefix per service.\n * This is what runs when stdout is not a TTY, and what CI sees.\n */\nexport const attachPlainRenderer = (bus: EventBus, options: PlainRendererOptions): (() => void) => {\n const write = options.write ?? ((text: string) => safeWrite(text));\n const painter = options.painter ?? defaultPaint;\n const glyph = options.glyph ?? glyphs();\n const showTime = options.timestamps ?? true;\n const now = options.now ?? (() => new Date());\n\n const colorOf = new Map(options.stack.services.map((service) => [service.name, asColorName(service.color)]));\n const width = Math.max(8, ...options.stack.services.map((service) => service.name.length), 'laracrew'.length);\n\n const line = (service: string, text: string, colorName = colorOf.get(service) ?? 'cyan') => {\n const stamp = showTime ? painter('gray', `${time(now())} `) : '';\n const prefix = painter(colorName, padEnd(service, width));\n write(`${stamp}${prefix} ${painter('gray', '|')} ${text}\\n`);\n };\n\n // Lifecycle notes carry a mark and a colour so they stand apart from the log lines around them.\n const note = (tone: Tone, text: string): string => {\n switch (tone) {\n case 'ok':\n return `${painter('green', glyph.tick)} ${painter('green', text)}`;\n case 'warn':\n return `${painter('yellow', glyph.warn)} ${painter('yellow', text)}`;\n case 'error':\n return `${painter('red', glyph.failed)} ${painter('red', text)}`;\n default:\n return painter('gray', text);\n }\n };\n\n const system = (text: string, tone: Tone = 'info') => line('laracrew', note(tone, text), 'bold');\n\n const handle = (event: LaracrewEvent): void => {\n switch (event.type) {\n case 'service:log':\n line(event.log.service, event.log.line);\n break;\n\n case 'stack:starting': {\n system(`starting ${event.stack} (${event.services.length} services)`);\n const manual = options.stack.services.filter((service) => !service.autostart && !service.external);\n if (manual.length > 0) {\n system(`not launched (autostart: false): ${manual.map((service) => service.name).join(', ')}`);\n }\n break;\n }\n\n case 'stack:ready':\n system(`${event.stack} ready in ${(event.durationMs / 1000).toFixed(1)}s`, 'ok');\n break;\n\n case 'stack:stopping':\n system(`stopping ${event.stack}…`);\n break;\n\n case 'stack:stopped':\n system(`${event.stack} stopped`);\n break;\n\n case 'service:spawned':\n line(event.service, painter('gray', `$ ${event.command}`));\n break;\n\n case 'service:ready':\n line(event.service, note('ok', `ready (${event.probe}) in ${event.durationMs}ms`));\n break;\n\n case 'service:exit':\n if (!event.intentional) {\n // A clean exit is worth a look; a crash is a failure.\n const clean = event.code === 0 && !event.signal;\n const why = event.signal ? `signal ${event.signal}` : `code ${event.code}`;\n line(event.service, note(clean ? 'warn' : 'error', `exited (${why})`));\n }\n break;\n\n case 'service:restart':\n line(\n event.service,\n `${painter('yellow', glyph.restart)} ${painter(\n 'yellow',\n `restarting in ${event.delayMs}ms (attempt ${event.attempt}/${event.maxAttempts})`,\n )}`,\n );\n break;\n\n case 'service:state':\n if (event.to === 'failed') {\n line(event.service, note('error', `failed${event.detail ? `: ${event.detail}` : ''}`));\n }\n break;\n\n case 'notice':\n if (event.service) {\n line(event.service, note(event.level, event.message));\n } else {\n system(event.message, event.level);\n }\n break;\n\n default:\n break;\n }\n };\n\n return bus.subscribe(handle);\n};\n","import type { Supervisor } from '../core/process/supervisor.js';\nimport type { LogLine, ServiceState } from '../core/events/types.js';\nimport { describeProbe } from '../core/health/probes.js';\n\n/**\n * What the views render. Built by polling the supervisor rather than by streaming events:\n * the ring buffers already hold everything, so a poll is cheaper than a re-render per line\n * and a chatty worker cannot stall the UI.\n */\n\nexport interface ProcessRow {\n index: number;\n name: string;\n state: ServiceState;\n pid: number | undefined;\n uptimeMs: number | undefined;\n restarts: number;\n external: boolean;\n autostart: boolean;\n /** What laracrew waits on, e.g. \"tcp 127.0.0.1:6379\". Shown for dependencies. */\n probe: string | undefined;\n project: string | undefined;\n command: string | undefined;\n cwd: string;\n url: string | undefined;\n groups: string[];\n logLines: number;\n}\n\nexport interface StackView {\n name: string;\n /** Processes laracrew starts and stops. Indices here are what the digit keys select. */\n rows: ProcessRow[];\n /** `external: true` services — health-checked, never managed. Not selectable. */\n dependencies: ProcessRow[];\n running: number;\n total: number;\n restarts: number;\n failed: number;\n dependenciesDown: number;\n}\n\nconst commandOf = (supervisor: Supervisor, name: string): string | undefined => {\n const service = supervisor.stack.services.find((entry) => entry.name === name);\n if (!service?.command) return undefined;\n return service.command.kind === 'shell'\n ? service.command.line\n : [service.command.file, ...service.command.args].join(' ');\n};\n\nexport const buildStackView = (supervisor: Supervisor): StackView => {\n const all: ProcessRow[] = supervisor.processes.map((managed) => ({\n index: -1, // assigned below, once externals are out of the way\n name: managed.service.name,\n state: managed.state,\n pid: managed.pid,\n uptimeMs: managed.uptimeMs,\n restarts: managed.restarts,\n external: managed.service.external,\n autostart: managed.service.autostart,\n probe: managed.service.ready ? describeProbe(managed.service.ready) : undefined,\n project: managed.service.project?.key,\n command: commandOf(supervisor, managed.service.name),\n cwd: managed.service.cwd,\n url: managed.service.url,\n groups: managed.service.groups,\n logLines: managed.logs.size,\n }));\n\n // Externals are checked, not run. Keeping them out of the numbered list means a digit key\n // always selects something laracrew can actually start and stop.\n const dependencies = all.filter((row) => row.external);\n const rows = all.filter((row) => !row.external).map((row, index) => ({ ...row, index }));\n\n return {\n name: supervisor.stack.name,\n rows,\n dependencies,\n running: rows.filter((row) => row.state === 'running' || row.state === 'ready').length,\n total: rows.length,\n restarts: rows.reduce((sum, row) => sum + row.restarts, 0),\n failed: rows.filter((row) => row.state === 'failed' || row.state === 'crashed').length,\n dependenciesDown: dependencies.filter((row) => row.state !== 'ready' && row.state !== 'running').length,\n };\n};\n\nexport const logsFor = (supervisor: Supervisor, name: string, limit: number): LogLine[] =>\n supervisor.get(name)?.logs.tail(limit) ?? [];\n\n/** Merged view: the newest `limit` lines across every service, oldest first. */\nexport const mergedLogs = (supervisor: Supervisor, limit: number): LogLine[] => {\n const perService = Math.max(20, Math.ceil(limit / Math.max(1, supervisor.processes.length)) * 4);\n const all: LogLine[] = [];\n for (const managed of supervisor.processes) all.push(...managed.logs.tail(perService));\n all.sort((a, b) => a.at - b.at);\n return all.slice(-limit);\n};\n","import type { UiState } from './screen.js';\n\n/**\n * Key handling as a pure function: state and keypress in, new state plus an optional command\n * out. The app performs the commands; this file stays trivially testable.\n */\n\nexport interface Key {\n name: string;\n ctrl?: boolean;\n shift?: boolean;\n}\n\nexport type Command =\n | { type: 'none' }\n | { type: 'quit' }\n | { type: 'force-quit' }\n | { type: 'restart'; index: number }\n | { type: 'restart-running' }\n | { type: 'toggle'; index: number };\n\nexport interface KeyResult {\n ui: UiState;\n command: Command;\n}\n\nconst none = (ui: UiState): KeyResult => ({ ui, command: { type: 'none' } });\n\nexport const handleKey = (ui: UiState, key: Key, rowCount: number): KeyResult => {\n // Ctrl-C always means stop, wherever you are.\n if (key.ctrl && key.name === 'c') {\n return { ui: { ...ui, confirmQuit: false }, command: { type: ui.phase === 'stopping' ? 'force-quit' : 'quit' } };\n }\n\n if (ui.confirmQuit) {\n if (key.name === 'y' || key.name === 'return') {\n return { ui: { ...ui, confirmQuit: false }, command: { type: 'quit' } };\n }\n return none({ ...ui, confirmQuit: false, note: 'Ready for commands.' });\n }\n\n if (ui.view === 'help') {\n return none({ ...ui, view: 'overview' });\n }\n\n const clamp = (index: number): number => Math.min(Math.max(0, index), Math.max(0, rowCount - 1));\n const inLogView = ui.view === 'log' || ui.view === 'merged';\n\n switch (key.name) {\n case 'q':\n return none({ ...ui, confirmQuit: true });\n\n case '?':\n\n return none({ ...ui, view: 'help' });\n\n case 'escape':\n return none({ ...ui, view: 'overview', scrollBack: 0, follow: true });\n\n case 's':\n if (inLogView) return none({ ...ui, view: 'overview', scrollBack: 0, follow: true });\n return { ui, command: { type: 'toggle', index: ui.selected } };\n\n case 't':\n return { ui, command: { type: 'toggle', index: ui.selected } };\n\n case 'r':\n // Shift-R bounces every running process; plain r only the selected one.\n if (key.shift) return { ui, command: { type: 'restart-running' } };\n return { ui, command: { type: 'restart', index: ui.selected } };\n\n case 'a':\n return none({ ...ui, view: ui.view === 'merged' ? 'overview' : 'merged', scrollBack: 0, follow: true });\n\n case 'return':\n case 'v':\n if (ui.view === 'overview') return none({ ...ui, view: 'log', scrollBack: 0, follow: true });\n return none(ui);\n\n case 'up':\n case 'k':\n if (inLogView) return none({ ...ui, scrollBack: ui.scrollBack + 1, follow: false });\n return none({ ...ui, selected: clamp(ui.selected - 1) });\n\n case 'down':\n case 'j':\n if (inLogView) {\n const scrollBack = Math.max(0, ui.scrollBack - 1);\n return none({ ...ui, scrollBack, follow: scrollBack === 0 });\n }\n return none({ ...ui, selected: clamp(ui.selected + 1) });\n\n case 'pageup':\n if (inLogView) return none({ ...ui, scrollBack: ui.scrollBack + 10, follow: false });\n return none({ ...ui, selected: clamp(ui.selected - 5) });\n\n case 'pagedown':\n if (inLogView) {\n const scrollBack = Math.max(0, ui.scrollBack - 10);\n return none({ ...ui, scrollBack, follow: scrollBack === 0 });\n }\n return none({ ...ui, selected: clamp(ui.selected + 5) });\n\n case 'g':\n if (inLogView) {\n // Shift-G is \"bottom\", plain g is \"top\".\n return key.shift\n ? none({ ...ui, scrollBack: 0, follow: true })\n : none({ ...ui, scrollBack: Number.MAX_SAFE_INTEGER, follow: false });\n }\n return none({ ...ui, selected: key.shift ? clamp(rowCount - 1) : 0 });\n\n case 'f':\n if (inLogView) return none({ ...ui, follow: !ui.follow, scrollBack: ui.follow ? ui.scrollBack : 0 });\n return none(ui);\n\n case 'home':\n return inLogView ? none({ ...ui, scrollBack: Number.MAX_SAFE_INTEGER, follow: false }) : none({ ...ui, selected: 0 });\n\n case 'end':\n return inLogView ? none({ ...ui, scrollBack: 0, follow: true }) : none({ ...ui, selected: clamp(rowCount - 1) });\n\n default: {\n // A digit jumps straight to that process and opens its log — the fast path.\n if (/^[0-9]$/.test(key.name)) {\n const index = Number(key.name);\n if (index < rowCount) {\n return none({ ...ui, selected: index, view: 'log', scrollBack: 0, follow: true });\n }\n }\n return none(ui);\n }\n }\n};\n","import type { LogLine } from '../core/events/types.js';\nimport { stripAnsi } from '../cli/render/colors.js';\nimport type { ProcessRow, StackView } from './model.js';\nimport { STATE_STYLE, formatClock, formatDuration, formatUptime, type Glyphs } from './theme.js';\n\n/**\n * Pure rendering: state in, lines of text out. No terminal, no timers, no framework — which\n * makes every screen directly unit-testable and keeps a repaint to one string write.\n */\n\nexport type ViewName = 'overview' | 'log' | 'merged' | 'help';\n\nexport interface UiState {\n view: ViewName;\n selected: number;\n /** Log views stick to the bottom until you scroll up. */\n follow: boolean;\n scrollBack: number;\n confirmQuit: boolean;\n phase: 'booting' | 'running' | 'stopping';\n note: string;\n}\n\nexport const initialUiState = (): UiState => ({\n view: 'overview',\n selected: 0,\n follow: true,\n scrollBack: 0,\n confirmQuit: false,\n phase: 'booting',\n note: 'Booting…',\n});\n\nexport interface Size {\n columns: number;\n rows: number;\n}\n\nexport interface Painter {\n (color: string, text: string): string;\n enabled: boolean;\n}\n\nexport interface RenderInput {\n stack: StackView;\n ui: UiState;\n size: Size;\n glyph: Glyphs;\n paint: Painter;\n /** Lines for the log views; ignored by the overview. */\n logs: LogLine[];\n uptimeMs: number;\n}\n\nconst pad = (text: string, width: number): string => {\n const visible = stripAnsi(text).length;\n return visible >= width ? text : text + ' '.repeat(width - visible);\n};\n\nconst truncate = (text: string, width: number): string => {\n if (width <= 1) return '';\n return stripAnsi(text).length <= width ? text : `${text.slice(0, Math.max(0, width - 1))}…`;\n};\n\nconst rule = (width: number, glyph: Glyphs): string => glyph.rule.repeat(Math.max(0, width));\n\n// ---------------------------------------------------------------- header\n\nconst header = ({ stack, ui, size, paint, glyph, uptimeMs }: RenderInput): string[] => {\n const title = `laracrew ${glyph.dot} ${stack.name}`;\n const health =\n stack.failed > 0\n ? paint('red', `${stack.failed} failed`)\n : stack.dependenciesDown > 0\n ? paint('red', `${stack.dependenciesDown} dependency down`)\n : ui.phase === 'booting'\n ? paint('yellow', 'booting')\n : paint('green', 'all healthy');\n\n const idle = stack.rows.filter((entry) => !entry.autostart && entry.state === 'queued').length;\n const right = [\n `up ${formatUptime(uptimeMs)}`,\n `${stack.running}/${stack.total} running`,\n idle > 0 ? `${idle} idle` : '',\n stack.restarts > 0 ? `${glyph.restart}${stack.restarts}` : '',\n ]\n .filter(Boolean)\n .join(` ${glyph.dot} `);\n\n const left = ` ${paint('bold', title)}`;\n const gap = Math.max(1, size.columns - stripAnsi(left).length - stripAnsi(right).length - stripAnsi(health).length - 5);\n\n return [\n '',\n `${left}${' '.repeat(gap)}${paint('gray', right)} ${health}`,\n paint('gray', ` ${rule(Math.max(0, size.columns - 4), glyph)}`),\n ];\n};\n\n// ---------------------------------------------------------------- key legend\n\nconst KEYS: Record<ViewName, [string, string][]> = {\n overview: [\n ['up/down', 'select'],\n ['enter', 'inspect log'],\n ['0-9', 'jump'],\n ['r', 'restart'],\n ['R', 'restart all running'],\n ['s', 'stop/start'],\n ['a', 'all logs'],\n ['?', 'help'],\n ['q', 'quit'],\n ],\n log: [\n ['esc', 'back to stack'],\n ['up/down', 'scroll'],\n ['g/G', 'top/bottom'],\n ['f', 'follow'],\n ['r', 'restart'],\n ['R', 'restart all running'],\n ['q', 'quit'],\n ],\n merged: [\n ['esc', 'back to stack'],\n ['up/down', 'scroll'],\n ['g/G', 'top/bottom'],\n ['f', 'follow'],\n ['R', 'restart all running'],\n ['q', 'quit'],\n ],\n help: [['any key', 'back']],\n};\n\nconst legend = ({ ui, paint, size }: RenderInput): string[] => {\n const pairs = KEYS[ui.view].map(([key, label]) => `${paint('cyan', key)} ${paint('gray', label)}`);\n\n const lines: string[] = [];\n let current = ' ';\n let currentWidth = 2;\n for (const pair of pairs) {\n const width = stripAnsi(pair).length + 3;\n if (currentWidth + width > size.columns - 2 && currentWidth > 2) {\n lines.push(current);\n current = ' ';\n currentWidth = 2;\n }\n current += `${pair} `;\n currentWidth += width;\n }\n if (currentWidth > 2) lines.push(current);\n return lines;\n};\n\n// ---------------------------------------------------------------- overview\n\nconst processLine = (\n row: ProcessRow,\n isSelected: boolean,\n isLast: boolean,\n nameWidth: number,\n { paint, glyph, size }: RenderInput,\n): string => {\n const style = STATE_STYLE[row.state];\n const branch = isLast ? glyph.lastBranch : glyph.branch;\n const pointer = isSelected ? paint('cyan', glyph.pointer) : ' ';\n const name = isSelected ? paint('cyan', pad(row.name, nameWidth)) : pad(row.name, nameWidth);\n\n // A service that was never meant to launch reads as \"idle\", not \"queued\" — it is not\n // waiting for anything, it is waiting for you.\n const manual = !row.autostart && row.state === 'queued';\n const label = manual ? 'idle' : style.label.toLowerCase();\n const labelColor = manual ? 'gray' : style.color;\n\n const detail = row.external\n ? paint('gray', 'external')\n : manual\n ? paint('cyan', 'press s')\n : row.state === 'running' || row.state === 'ready'\n ? paint('gray', formatDuration(row.uptimeMs))\n : '';\n\n const restarts = row.restarts > 0 ? paint('yellow', ` ${glyph.restart}${row.restarts}`) : '';\n\n const line =\n ` ${paint('gray', branch)} ${pointer} ${paint('gray', `[${row.index}]`)} ` +\n `${paint(labelColor, glyph[style.glyph])} ${name}` +\n `${paint(labelColor, pad(label, 11))}${pad(detail, 9)}${restarts}`;\n\n return truncate(line, size.columns + (line.length - stripAnsi(line).length));\n};\n\n/** Health-checked, never managed — so no index and no branch glyph. */\nconst dependencyLine = (row: ProcessRow, nameWidth: number, { paint, glyph, size }: RenderInput): string => {\n const style = STATE_STYLE[row.state];\n const label = row.state === 'ready' || row.state === 'running' ? 'ready' : style.label.toLowerCase();\n const color = row.state === 'ready' || row.state === 'running' ? 'green' : style.color;\n\n const line =\n ` ${paint(color, glyph[style.glyph])} ${pad(row.name, nameWidth)}` +\n `${paint(color, pad(label, 11))}${paint('gray', row.probe ?? '')}`;\n\n return truncate(line, size.columns + (line.length - stripAnsi(line).length));\n};\n\nconst dependencies = (input: RenderInput, nameWidth: number): string[] => {\n const { stack, paint } = input;\n if (stack.dependencies.length === 0) return [];\n\n return [\n ` ${paint('bold', 'DEPENDENT SERVICES')} ${paint('gray', '(checked, not managed)')}`,\n ...stack.dependencies.map((row) => dependencyLine(row, nameWidth, input)),\n '',\n ];\n};\n\nconst overview = (input: RenderInput, bodyRows: number): string[] => {\n const { stack, ui, paint, glyph } = input;\n const nameWidth =\n Math.max(12, ...[...stack.rows, ...stack.dependencies].map((row) => row.name.length)) + 2;\n\n const dependencyLines = dependencies(input, nameWidth);\n\n const lines: string[] = [\n ` ${paint('bold', 'STACK DETAILS')} ${paint('gray', '(process tree)')}`,\n '',\n ...dependencyLines,\n ` ${paint('gray', `processes (${stack.rows.length} managed)`)}`,\n paint('gray', ` ${glyph.pipe}`),\n ];\n\n if (stack.rows.length === 0) {\n lines.push(` ${paint('gray', `${glyph.lastBranch} nothing to manage in this stack`)}`);\n return lines;\n }\n\n // Keep the selection visible when the list is taller than the terminal.\n const capacity = Math.max(3, bodyRows - 5 - dependencyLines.length);\n let start = 0;\n if (stack.rows.length > capacity) {\n start = Math.min(Math.max(0, ui.selected - Math.floor(capacity / 2)), stack.rows.length - capacity);\n }\n const visible = stack.rows.slice(start, start + capacity);\n\n if (start > 0) lines.push(paint('gray', ` ${glyph.pipe} ${start} more above`));\n\n for (const [offset, row] of visible.entries()) {\n const index = start + offset;\n lines.push(processLine(row, index === ui.selected, index === stack.rows.length - 1, nameWidth, input));\n }\n\n const hiddenBelow = stack.rows.length - (start + visible.length);\n if (hiddenBelow > 0) lines.push(paint('gray', ` ${glyph.pipe} ${hiddenBelow} more below`));\n\n lines.push(paint('gray', ` ${glyph.pipe}`));\n lines.push(` ${paint('gray', `${glyph.lastBranch} ${input.ui.note}`)}`);\n\n return lines;\n};\n\n// ---------------------------------------------------------------- log views\n\nconst logHeader = (row: ProcessRow | undefined, input: RenderInput): string[] => {\n const { paint, glyph, size } = input;\n if (!row) return [` ${paint('gray', 'no process selected')}`];\n\n const style = STATE_STYLE[row.state];\n const meta = [\n paint(style.color, style.label.toLowerCase()),\n row.pid !== undefined ? paint('gray', `pid ${row.pid}`) : '',\n row.state === 'running' ? paint('gray', `up ${formatDuration(row.uptimeMs)}`) : '',\n row.restarts > 0 ? paint('yellow', `${glyph.restart}${row.restarts}`) : '',\n ]\n .filter(Boolean)\n .join(paint('gray', ` ${glyph.dot} `));\n\n const lines = [` ${paint('bold', row.name)} ${meta}`];\n if (row.command) lines.push(` ${paint('gray', truncate(`$ ${row.command}`, size.columns - 4))}`);\n lines.push(` ${paint('gray', truncate(row.cwd, size.columns - 4))}`);\n lines.push(paint('gray', ` ${rule(Math.max(0, size.columns - 4), glyph)}`));\n return lines;\n};\n\nconst logBody = (input: RenderInput, bodyRows: number, withServiceName: boolean): string[] => {\n const { logs, ui, paint, size } = input;\n const capacity = Math.max(1, bodyRows);\n\n if (logs.length === 0) {\n return [` ${paint('gray', 'no output yet')}`];\n }\n\n const end = Math.max(capacity, logs.length - ui.scrollBack);\n const window = logs.slice(Math.max(0, end - capacity), end);\n\n const nameWidth = withServiceName\n ? Math.max(...logs.map((line) => line.service.length))\n : 0;\n\n return window.map((line) => {\n const stamp = paint('gray', formatClock(line.at));\n const who = withServiceName ? ` ${paint('cyan', pad(line.service, nameWidth))}` : '';\n const body = line.stream === 'stderr' ? paint('red', line.line) : line.line;\n const rendered = ` ${stamp}${who} ${paint('gray', '|')} ${body}`;\n return truncate(rendered, size.columns + (rendered.length - stripAnsi(rendered).length));\n });\n};\n\n// ---------------------------------------------------------------- help\n\nconst help = ({ paint, glyph }: RenderInput): string[] => [\n ` ${paint('bold', 'KEYS')}`,\n '',\n ...[\n ['up / down, j / k', 'move the selection'],\n ['0 - 9', 'jump straight to that process and open its log'],\n ['enter, v', 'inspect the selected process log'],\n ['esc, s', 'back to the stack overview'],\n ['a', 'merged log across every service'],\n ['r', 'restart the selected process (graceful)'],\n ['R', 'restart every running process, in dependency order; stopped and idle stay put'],\n ['t', 'toggle the selected process: stop if running, start if stopped'],\n ['f', 'follow / pause tailing in a log view'],\n ['g / G', 'jump to the top / bottom of a log'],\n ['?', 'this help'],\n ['q, ctrl-c', 'quit — stops every process first'],\n ].map(([key, label]) => ` ${paint('cyan', pad(key!, 20))}${paint('gray', label!)}`),\n '',\n ` ${paint('gray', `The overview never streams logs — that is deliberate. Open one ${glyph.dot} read it ${glyph.dot} go back.`)}`,\n];\n\n// ---------------------------------------------------------------- shutdown\n\nexport const renderShutdown = (input: RenderInput): string[] => {\n const { stack, paint, glyph } = input;\n const lines = ['', ` ${paint('bold', `Stopping ${stack.name}…`)}`, ''];\n\n for (const row of stack.rows) {\n const done = row.state === 'stopped' || row.state === 'failed';\n const mark = done ? paint('green', glyph.tick) : paint('yellow', glyph.starting);\n const label = done ? paint('gray', 'stopped') : paint('yellow', 'stopping…');\n lines.push(` ${mark} ${pad(row.name, 22)}${label}`);\n }\n\n lines.push('', ` ${paint('gray', 'ctrl-c again to force')}`);\n return lines;\n};\n\n// ---------------------------------------------------------------- frame\n\n/** The whole screen, as lines. Callers just write this. */\nexport const renderFrame = (input: RenderInput): string[] => {\n if (input.ui.phase === 'stopping') return renderShutdown(input);\n\n const top = header(input);\n const keys = legend(input);\n const chrome = top.length + keys.length + 3;\n const bodyRows = Math.max(3, input.size.rows - chrome);\n\n let body: string[];\n switch (input.ui.view) {\n case 'help':\n body = help(input);\n break;\n case 'log': {\n const row = input.stack.rows[input.ui.selected];\n const head = logHeader(row, input);\n body = [...head, ...logBody(input, bodyRows - head.length, false)];\n break;\n }\n case 'merged':\n body = [\n ` ${input.paint('bold', 'ALL SERVICES')}`,\n input.paint('gray', ` ${rule(Math.max(0, input.size.columns - 4), input.glyph)}`),\n ...logBody(input, bodyRows - 2, true),\n ];\n break;\n default:\n body = overview(input, bodyRows);\n }\n\n const status = input.ui.confirmQuit\n ? ` ${input.paint('yellow', 'Quit and stop every process? (y/n)')}`\n : input.ui.view !== 'overview'\n ? ` ${input.paint('gray', input.ui.note)}`\n : '';\n\n return [...top, '', ...keys, ...body, '', ...(status ? [status] : [])];\n};\n","import readline from 'node:readline';\nimport { stripAnsi } from '../cli/render/colors.js';\nimport type { Key } from './keys.js';\nimport type { Size } from './screen.js';\n\nconst ESC = String.fromCharCode(27);\nconst CSI = `${ESC}[`;\n\n/** The escape codes a full-screen CLI actually needs. */\nexport const codes = {\n altScreenOn: `${CSI}?1049h`,\n altScreenOff: `${CSI}?1049l`,\n hideCursor: `${CSI}?25l`,\n showCursor: `${CSI}?25h`,\n home: `${CSI}H`,\n clearLine: `${CSI}K`,\n clearBelow: `${CSI}J`,\n};\n\nexport interface TerminalOptions {\n stdout?: NodeJS.WriteStream;\n stdin?: NodeJS.ReadStream;\n}\n\n/**\n * Drives a full-screen view over plain ANSI: enter the alternate screen buffer (so the user's\n * scrollback survives), then repaint by homing the cursor and clearing to end-of-line per row.\n * No clear-then-draw, so there is no flicker, and no framework.\n */\nexport class Terminal {\n readonly #stdout: NodeJS.WriteStream;\n readonly #stdin: NodeJS.ReadStream;\n #lastFrame: string[] = [];\n #active = false;\n #onKey?: (key: Key) => void;\n #onResize?: () => void;\n #keyListener?: (str: string | undefined, key: readline.Key) => void;\n #resizeListener?: () => void;\n\n constructor(options: TerminalOptions = {}) {\n this.#stdout = options.stdout ?? process.stdout;\n this.#stdin = options.stdin ?? process.stdin;\n }\n\n get size(): Size {\n return {\n columns: Math.max(40, this.#stdout.columns ?? 80),\n rows: Math.max(10, this.#stdout.rows ?? 24),\n };\n }\n\n start(handlers: { onKey: (key: Key) => void; onResize?: () => void }): void {\n if (this.#active) return;\n this.#active = true;\n this.#onKey = handlers.onKey;\n if (handlers.onResize) this.#onResize = handlers.onResize;\n\n this.#stdout.write(codes.altScreenOn + codes.hideCursor);\n\n readline.emitKeypressEvents(this.#stdin);\n if (this.#stdin.isTTY) this.#stdin.setRawMode(true);\n this.#stdin.resume();\n\n this.#keyListener = (_str, key) => {\n if (!key) return;\n this.#onKey?.({\n name: key.name ?? key.sequence ?? '',\n ...(key.ctrl ? { ctrl: true } : {}),\n ...(key.shift ? { shift: true } : {}),\n });\n };\n this.#stdin.on('keypress', this.#keyListener);\n\n this.#resizeListener = () => {\n this.#lastFrame = []; // force a full repaint at the new width\n this.#onResize?.();\n };\n this.#stdout.on('resize', this.#resizeListener);\n }\n\n /** Repaints only the lines that changed. */\n paint(lines: string[]): void {\n if (!this.#active) return;\n const { rows, columns } = this.size;\n const frame = lines.slice(0, rows - 1).map((line) => clip(line, columns));\n\n let output = codes.home;\n const height = Math.max(frame.length, this.#lastFrame.length);\n\n for (let index = 0; index < height; index += 1) {\n const line = frame[index] ?? '';\n if (this.#lastFrame[index] === line) {\n output += `${CSI}${index + 2};1H`; // nothing changed: skip to the next row\n continue;\n }\n output += `${CSI}${index + 1};1H${line}${codes.clearLine}`;\n }\n\n output += codes.clearBelow;\n this.#stdout.write(output);\n this.#lastFrame = frame;\n }\n\n stop(): void {\n if (!this.#active) return;\n this.#active = false;\n\n if (this.#keyListener) this.#stdin.off('keypress', this.#keyListener);\n if (this.#resizeListener) this.#stdout.off('resize', this.#resizeListener);\n if (this.#stdin.isTTY) this.#stdin.setRawMode(false);\n this.#stdin.pause();\n\n this.#stdout.write(codes.showCursor + codes.altScreenOff);\n this.#lastFrame = [];\n }\n}\n\n/** Trims a line to the terminal width without counting the invisible colour codes. */\nexport const clip = (line: string, columns: number): string => {\n const visible = stripAnsi(line).length;\n if (visible <= columns) return line;\n\n let out = '';\n let width = 0;\n let index = 0;\n while (index < line.length && width < columns) {\n if (line[index] === ESC) {\n const end = line.indexOf('m', index);\n if (end === -1) break;\n out += line.slice(index, end + 1);\n index = end + 1;\n continue;\n }\n out += line[index];\n width += 1;\n index += 1;\n }\n return out;\n};\n","import type { EventBus } from '../core/events/bus.js';\nimport type { Supervisor } from '../core/process/supervisor.js';\nimport { createPainter, supportsColor, type ColorName } from '../cli/render/colors.js';\nimport { buildStackView, logsFor, mergedLogs } from './model.js';\nimport { handleKey, type Command } from './keys.js';\nimport { initialUiState, renderFrame, type Painter, type UiState } from './screen.js';\nimport { Terminal } from './terminal.js';\nimport { glyphs } from './theme.js';\n\nexport interface TuiOptions {\n stdout?: NodeJS.WriteStream;\n stdin?: NodeJS.ReadStream;\n env?: NodeJS.ProcessEnv;\n /** Repaint interval. 250ms keeps uptime ticking without burning CPU. */\n frameMs?: number;\n}\n\nconst MAX_LOG_LINES = 400;\n\n/**\n * The whole UI: poll the supervisor, render a frame, handle keys. Deliberately a loop and not\n * an event stream — a worker emitting 500 lines/s must not cause 500 repaints.\n */\nexport const runTui = async (\n supervisor: Supervisor,\n bus: EventBus,\n options: TuiOptions = {},\n): Promise<number> => {\n const env = options.env ?? process.env;\n const stdout = options.stdout ?? process.stdout;\n const terminal = new Terminal({\n stdout,\n ...(options.stdin ? { stdin: options.stdin } : {}),\n });\n\n const basePainter = createPainter(supportsColor(stdout, env));\n const paint: Painter = Object.assign(\n (color: string, text: string) => basePainter(color as ColorName, text),\n { enabled: basePainter.enabled },\n );\n\n const glyph = glyphs(env);\n const startedAt = Date.now();\n\n let ui: UiState = initialUiState();\n let exitCode = 0;\n let stopping = false;\n let finished = false;\n\n const setNote = (note: string): void => {\n ui = { ...ui, note };\n };\n\n // Lifecycle events become the one-line status note; log events are ignored here on purpose.\n const unsubscribe = bus.subscribe((event) => {\n switch (event.type) {\n case 'stack:ready':\n ui = { ...ui, phase: 'running' };\n setNote(`Ready in ${(event.durationMs / 1000).toFixed(1)}s. Awaiting keyboard input…`);\n break;\n case 'service:restart':\n setNote(`${event.service} restarting in ${event.delayMs}ms (attempt ${event.attempt}/${event.maxAttempts})`);\n break;\n case 'service:exit':\n if (!event.intentional) {\n setNote(`${event.service} exited with ${event.signal ? `signal ${event.signal}` : `code ${event.code}`}`);\n }\n break;\n case 'notice':\n if (event.level !== 'info') setNote(`${event.service ? `${event.service}: ` : ''}${event.message}`);\n break;\n default:\n break;\n }\n });\n\n const draw = (): void => {\n const stack = buildStackView(supervisor);\n const selectedRow = stack.rows[ui.selected];\n\n const logs =\n ui.view === 'log' && selectedRow\n ? logsFor(supervisor, selectedRow.name, MAX_LOG_LINES)\n : ui.view === 'merged'\n ? mergedLogs(supervisor, MAX_LOG_LINES)\n : [];\n\n terminal.paint(\n renderFrame({\n stack,\n ui,\n size: terminal.size,\n glyph,\n paint,\n logs,\n uptimeMs: Date.now() - startedAt,\n }),\n );\n };\n\n const shutdown = async (reason: string): Promise<void> => {\n if (stopping) return;\n stopping = true;\n ui = { ...ui, phase: 'stopping' };\n draw();\n await supervisor.down(reason);\n finished = true;\n };\n\n const perform = (command: Command): void => {\n const stack = buildStackView(supervisor);\n const row = stack.rows['index' in command ? command.index : ui.selected];\n\n switch (command.type) {\n case 'quit':\n void shutdown('user quit');\n break;\n\n case 'force-quit':\n // Second ctrl-c during shutdown: stop waiting.\n terminal.stop();\n process.exit(130);\n break;\n\n case 'restart':\n if (!row) break;\n setNote(`restarting ${row.name}…`);\n void supervisor\n .restart(row.name)\n .then(() => setNote(`${row.name} restarted`))\n .catch((error: unknown) => setNote(`restart failed: ${error instanceof Error ? error.message : String(error)}`));\n break;\n\n case 'restart-running':\n setNote('restarting every running process…');\n void supervisor\n .restartRunning()\n .then((names) =>\n setNote(\n names.length === 0\n ? 'nothing is running — nothing to restart'\n : `restarted ${names.length} process${names.length === 1 ? '' : 'es'}: ${names.join(', ')}`,\n ),\n )\n .catch((error: unknown) => setNote(`restart failed: ${error instanceof Error ? error.message : String(error)}`));\n break;\n\n case 'toggle': {\n if (!row) break;\n if (row.external) {\n setNote(`${row.name} is external — laracrew does not start or stop it`);\n break;\n }\n const live = row.state === 'running' || row.state === 'ready' || row.state === 'starting';\n setNote(`${live ? 'stopping' : 'starting'} ${row.name}…`);\n const action = live ? supervisor.stopService(row.name) : supervisor.startService(row.name);\n void action\n .then(() => setNote(`${row.name} ${live ? 'stopped' : 'started'}`))\n .catch((error: unknown) => setNote(error instanceof Error ? error.message : String(error)));\n break;\n }\n\n default:\n break;\n }\n };\n\n terminal.start({\n onKey: (key) => {\n // Externals are not in the selectable list, so bound by managed rows only.\n const rowCount = buildStackView(supervisor).rows.length;\n const result = handleKey(ui, key, rowCount);\n ui = result.ui;\n perform(result.command);\n draw();\n },\n onResize: draw,\n });\n\n const timer = setInterval(draw, options.frameMs ?? 250);\n timer.unref?.();\n\n const onSignal = (): void => {\n void shutdown('received signal');\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n draw();\n\n try {\n await supervisor.up();\n } catch (error) {\n ui = { ...ui, phase: 'running' };\n setNote(error instanceof Error ? error.message : String(error));\n exitCode = 1;\n draw();\n }\n\n // Idle until the user quits or every service has finished on its own.\n await new Promise<void>((resolve) => {\n const check = setInterval(() => {\n if (finished) {\n clearInterval(check);\n resolve();\n return;\n }\n if (stopping) return;\n const anyLive = supervisor.processes.some(\n (managed) => managed.state !== 'stopped' && managed.state !== 'failed',\n );\n if (!anyLive) {\n clearInterval(check);\n void shutdown('all services finished').then(resolve);\n }\n }, 200);\n check.unref?.();\n });\n\n clearInterval(timer);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n unsubscribe();\n terminal.stop();\n\n return exitCode;\n};\n","import { EventBus } from '../../core/events/bus.js';\nimport { loadSharedProjects, loadStack } from '../../core/config/load.js';\nimport { resolveStack, type ResolvedStack } from '../../core/config/resolve.js';\nimport { Supervisor } from '../../core/process/supervisor.js';\nimport { attachPlainRenderer } from '../render/plain.js';\nimport { color } from '../render/colors.js';\nimport { marks } from '../render/marks.js';\nimport { onOutputClosed, write as safeWrite } from '../render/output.js';\nimport { runTui } from '../../tui/app.js';\n\nexport interface UpOptions {\n only?: string[];\n except?: string[];\n profile?: string;\n plain?: boolean;\n json?: boolean;\n env?: NodeJS.ProcessEnv;\n}\n\nconst splitList = (values: string[] | undefined): string[] =>\n (values ?? []).flatMap((value) => value.split(',')).map((value) => value.trim()).filter(Boolean);\n\nexport const prepareStack = (name: string, options: UpOptions = {}): ResolvedStack => {\n const env = options.env ?? process.env;\n const loaded = loadStack(name, env);\n return resolveStack(loaded, {\n sharedProjects: loadSharedProjects(env),\n env,\n ...(options.profile ? { profile: options.profile } : {}),\n only: splitList(options.only),\n except: splitList(options.except),\n });\n};\n\nconst attachJsonRenderer = (bus: EventBus): (() => void) =>\n bus.subscribe((event) => process.stdout.write(`${JSON.stringify(event)}\\n`));\n\n/**\n * Boots a stack and keeps running until the fleet stops or the user interrupts.\n * The TUI lands in M2; until then every run uses the plain renderer.\n */\n/** The TUI is the default, but only when there is a real terminal to draw on. */\nexport const shouldUseTui = (options: UpOptions, stdout: { isTTY?: boolean } = process.stdout): boolean =>\n !options.plain && !options.json && Boolean(stdout.isTTY);\n\nexport const upCommand = async (name: string, options: UpOptions = {}): Promise<number> => {\n const stack = prepareStack(name, options);\n const bus = new EventBus();\n const mark = marks(options.env);\n\n if (shouldUseTui(options)) {\n const supervisor = new Supervisor(stack, bus, options.env ? { env: options.env } : {});\n return runTui(supervisor, bus, options.env ? { env: options.env } : {});\n }\n\n const detach = options.json ? attachJsonRenderer(bus) : attachPlainRenderer(bus, { stack });\n\n const supervisor = new Supervisor(stack, bus, options.env ? { env: options.env } : {});\n\n let exitCode = 0;\n let stopping = false;\n\n const shutdown = async (reason: string): Promise<void> => {\n if (stopping) return;\n stopping = true;\n await supervisor.down(reason);\n };\n\n const onSignal = (signal: NodeJS.Signals) => {\n if (stopping) {\n // Second interrupt: the user is done being patient.\n console.error(`\\n${mark.fail} ${color.red.bold('forced exit — some children may survive')}`);\n process.exit(130);\n }\n void shutdown(`received ${signal}`);\n };\n\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n // `laracrew up --json | head` closes the pipe; that is a request to stop, not a crash.\n const releaseOutputHook = onOutputClosed(() => {\n void shutdown('output closed');\n });\n\n try {\n await supervisor.up();\n await waitUntilIdle(supervisor, () => stopping);\n } catch (error) {\n console.error(`${mark.fail} ${color.red(error instanceof Error ? error.message : String(error))}`);\n exitCode = 1;\n } finally {\n await shutdown('done');\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n releaseOutputHook();\n detach();\n }\n\n return exitCode;\n};\n\n/** Resolves when every service has reached a terminal state, or a stop was requested. */\nconst waitUntilIdle = (supervisor: Supervisor, stopRequested: () => boolean): Promise<void> =>\n new Promise((resolve) => {\n const check = () => {\n if (stopRequested()) {\n clearInterval(timer);\n resolve();\n return;\n }\n const anyLive = supervisor.processes.some(\n (process) => process.state !== 'stopped' && process.state !== 'failed',\n );\n if (!anyLive) {\n clearInterval(timer);\n resolve();\n }\n };\n const timer = setInterval(check, 250);\n timer.unref?.();\n });\n","import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { isMap, isSeq, parseDocument, type Document, type YAMLMap, type YAMLSeq } from 'yaml';\nimport { ConfigError } from '../../core/config/errors.js';\nimport { parseYaml, validateStack } from '../../core/config/load.js';\nimport { stackDir, stackFile } from '../../core/config/paths.js';\nimport type { StackConfig } from '../../core/config/schema.js';\nimport { color, padEnd } from '../render/colors.js';\nimport { marks, nextSteps } from '../render/marks.js';\nimport { linkCommand } from './link.js';\n\n/**\n * A stack built one command at a time in the folder you are standing in, then published into\n * ~/.laracrew. The draft is an ordinary stack.yaml — same schema, same validation — so it can\n * be edited by hand, kept next to the code and committed.\n */\n\nconst SUFFIX = '.laracrew.yaml';\nconst DRAFT_FILE = /^(.+)\\.laracrew\\.ya?ml$/i;\nconst NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;\nconst SERVICE_NAME = /^[A-Za-z0-9][A-Za-z0-9_.:-]*$/;\n\n/** Commands that say how something runs, not what it is — skipped when deriving a name. */\nconst RUNNERS = new Set(['node', 'npm', 'npx', 'yarn', 'pnpm', 'bun', 'deno', 'python', 'python3', 'php', 'run', 'exec', 'poetry']);\n\nconst forward = (value: string): string => value.replace(/\\\\/g, '/');\n\n// realpath so a Windows 8.3 short name and its long form count as the same folder.\nconst canonical = (value: string): string => {\n try {\n return realpathSync.native(value);\n } catch {\n return path.resolve(value);\n }\n};\n\nconst samePath = (a: string, b: string): boolean => {\n const [x, y] = [canonical(a), canonical(b)];\n return process.platform === 'win32' ? x.toLowerCase() === y.toLowerCase() : x === y;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nexport const draftFile = (name: string, cwd: string = process.cwd()): string => path.join(cwd, `${name}${SUFFIX}`);\n\nexport interface DraftRef {\n name: string;\n file: string;\n}\n\n/** Every draft in a folder, by stack name. */\nexport const listDrafts = (cwd: string = process.cwd()): DraftRef[] =>\n readdirSync(cwd)\n .map((entry) => ({ entry, match: DRAFT_FILE.exec(entry) }))\n .filter((item): item is { entry: string; match: RegExpExecArray } => item.match !== null)\n .map(({ entry, match }) => ({ name: match[1]!, file: path.join(cwd, entry) }))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n/**\n * The draft a command works on: the one named, else the only one in the folder. `pick` is how\n * the caller's command names a draft, for the message when there are several.\n */\nexport const resolveDraft = (cwd: string = process.cwd(), name?: string, pick = '--draft <name>'): DraftRef => {\n if (name) {\n const file = draftFile(name, cwd);\n if (!existsSync(file)) {\n throw new ConfigError(`no draft named \"${name}\" in ${cwd}`, { details: ['start one with `laracrew draft <name>`'] });\n }\n return { name, file };\n }\n const drafts = listDrafts(cwd);\n if (drafts.length === 1) return drafts[0]!;\n if (drafts.length === 0) {\n throw new ConfigError(`no draft in ${cwd}`, { details: ['start one with `laracrew draft <name>`'] });\n }\n throw new ConfigError(`several drafts here: ${drafts.map((draft) => draft.name).join(', ')} — pick one with ${pick}`);\n};\n\n// Reads sensibly both as a draft and after publish copies it into ~/.laracrew verbatim.\nconst template = (name: string): string => `# Built with \\`laracrew draft\\`. Add services with \\`laracrew draft add\\`, install the stack with\n# \\`laracrew draft publish\\`, or edit by hand — this is an ordinary stack.yaml.\n#\n# laracrew draft add --project api --path C:/work/api --command \"php artisan queue:work\"\n# laracrew draft add --project api --command \"php artisan schedule:work\"\n# laracrew draft add --command \"npm run dev\" --default-state stopped\nname: ${name}\ncommand: ${name} # \\`laracrew link ${name}\\` installs this as a global command\nprojects: {}\nservices: []\n`;\n\nexport const createDraft = (name: string, options: { cwd?: string; force?: boolean } = {}): string => {\n const cwd = options.cwd ?? process.cwd();\n if (!NAME.test(name)) {\n throw new ConfigError(`\"${name}\" is not a usable stack name — letters, digits, dot, dash and underscore only`);\n }\n if (name === 'add' || name === 'publish') {\n throw new ConfigError(`\"${name}\" would clash with \\`laracrew draft ${name}\\` — pick another name`);\n }\n const file = draftFile(name, cwd);\n if (existsSync(file) && !options.force) {\n throw new ConfigError(`${path.basename(file)} already exists here`, {\n details: ['add to it with `laracrew draft add`, or pass --force to start over'],\n });\n }\n writeFileSync(file, template(name), 'utf8');\n return file;\n};\n\n// ---------------------------------------------------------------- add\n\nconst readDraft = (file: string): Document => {\n const doc = parseDocument(readFileSync(file, 'utf8'), { prettyErrors: true });\n const [problem] = doc.errors;\n if (problem) throw new ConfigError(`invalid YAML: ${problem.message}`, { file });\n if (!isMap(doc.contents)) throw new ConfigError('the draft should be a YAML mapping (name:, services: …)', { file });\n return doc;\n};\n\nconst mapAt = (doc: Document, key: string, file: string): YAMLMap => {\n let node: unknown = doc.get(key);\n if (node === undefined || node === null) {\n node = doc.createNode({});\n doc.set(key, node);\n }\n if (!isMap(node)) throw new ConfigError(`\\`${key}:\\` should be a map`, { file });\n return node;\n};\n\nconst seqAt = (doc: Document, key: string, file: string): YAMLSeq => {\n let node: unknown = doc.get(key);\n if (node === undefined || node === null) {\n node = doc.createNode([]);\n doc.set(key, node);\n }\n if (!isSeq(node)) throw new ConfigError(`\\`${key}:\\` should be a list`, { file });\n return node;\n};\n\n/**\n * `php artisan queue:work …` → `queue:work`; otherwise the first word that is not a runner\n * (`npm run dev` → `dev`, `node server.js` → `server`). Prefixed with the project key.\n */\nexport const deriveServiceName = (command: string, project?: string): string => {\n const artisan = /\\bartisan\\s+([A-Za-z0-9:_.-]+)/.exec(command);\n let verb = artisan?.[1];\n if (!verb) {\n const words = command\n .trim()\n .split(/\\s+/)\n .filter((word) => word && !word.startsWith('-'))\n .map((word) => word.split(/[\\\\/]/).pop() ?? word);\n const word = words.find((candidate) => !RUNNERS.has(candidate.toLowerCase())) ?? words[0] ?? 'service';\n verb = word.replace(/\\.[A-Za-z0-9]+$/, '');\n }\n const clean =\n verb\n .toLowerCase()\n .replace(/[^a-z0-9:_.-]+/g, '-')\n .replace(/^[-.:]+|[-.:]+$/g, '') || 'service';\n return project ? `${project}:${clean}` : clean;\n};\n\nconst uniqueName = (base: string, taken: Set<string>): string => {\n if (!taken.has(base)) return base;\n for (let n = 2; ; n += 1) {\n const candidate = `${base}-${n}`;\n if (!taken.has(candidate)) return candidate;\n }\n};\n\nconst parseState = (value: string | undefined): boolean => {\n if (value === undefined || value === 'running') return true;\n if (value === 'stopped') return false;\n throw new ConfigError(`--default-state is \"running\" or \"stopped\", not \"${value}\"`);\n};\n\nexport interface AddOptions {\n command: string;\n project?: string;\n path?: string;\n name?: string;\n /** \"running\" (the default) or \"stopped\" — a stopped service is defined but idle until started. */\n state?: string;\n draft?: string;\n cwd?: string;\n}\n\nexport interface AddResult {\n draft: string;\n file: string;\n service: { name: string; cmd: string; autostart: boolean; cwd?: string };\n project?: { key: string; path: string; created: boolean };\n /** How many services the draft holds now. */\n services: number;\n}\n\nexport const addToDraft = (options: AddOptions): AddResult => {\n const cwd = options.cwd ?? process.cwd();\n const command = options.command.trim();\n if (!command) throw new ConfigError('--command needs something to run, e.g. \"php artisan queue:work\"');\n const autostart = parseState(options.state);\n if (options.project !== undefined && !NAME.test(options.project)) {\n throw new ConfigError(`\"${options.project}\" is not a usable project key — letters, digits, dot, dash and underscore only`);\n }\n\n const { name: draftName, file } = resolveDraft(cwd, options.draft);\n const doc = readDraft(file);\n\n let project: AddResult['project'];\n if (options.project) {\n const projects = mapAt(doc, 'projects', file);\n const wanted = options.path ? forward(path.resolve(cwd, options.path)) : undefined;\n const existing: unknown = projects.get(options.project);\n if (existing !== undefined && existing !== null) {\n const current = isMap(existing) ? String(existing.get('path') ?? '') : '';\n if (wanted && !samePath(current, wanted)) {\n throw new ConfigError(`project \"${options.project}\" already points at ${current}`, {\n file,\n details: ['a draft keeps one path per project — leave --path off to reuse it, or pick another key'],\n });\n }\n project = { key: options.project, path: current, created: false };\n } else {\n const dir = wanted ?? forward(cwd);\n projects.set(options.project, doc.createNode({ path: dir }));\n projects.flow = false;\n project = { key: options.project, path: dir, created: true };\n }\n }\n\n const services = seqAt(doc, 'services', file);\n const taken = new Set(services.items.map((item) => (isMap(item) ? String(item.get('name') ?? '') : '')));\n let name: string;\n if (options.name) {\n if (!SERVICE_NAME.test(options.name)) {\n throw new ConfigError(`\"${options.name}\" is not a usable service name — letters, digits, colon, dot, dash and underscore only`);\n }\n if (taken.has(options.name)) throw new ConfigError(`a service named \"${options.name}\" is already in the draft`, { file });\n name = options.name;\n } else {\n name = uniqueName(deriveServiceName(command, options.project), taken);\n }\n\n // Key order is what a reader sees first, so: what it is, where, what it runs, then the extras.\n const service: Record<string, unknown> = { name };\n if (options.project) service.project = options.project;\n service.cmd = command;\n // Without a project there is nothing to inherit a folder from, and a linked command runs from\n // anywhere — so the folder is pinned now, while we know it.\n const serviceCwd = options.project ? undefined : forward(path.resolve(cwd, options.path ?? '.'));\n if (serviceCwd) service.cwd = serviceCwd;\n if (!autostart) service.autostart = false;\n services.add(doc.createNode(service));\n services.flow = false;\n\n writeFileSync(file, doc.toString(), 'utf8');\n\n return {\n draft: draftName,\n file,\n service: { name, cmd: command, autostart, ...(serviceCwd ? { cwd: serviceCwd } : {}) },\n ...(project ? { project } : {}),\n services: services.items.length,\n };\n};\n\n// ---------------------------------------------------------------- show\n\nexport interface DraftSummary {\n name: string;\n file: string;\n stackName: string;\n command: string;\n projects: { key: string; path: string }[];\n services: { name: string; cmd: string; project?: string; autostart: boolean }[];\n}\n\n/** What the draft holds, read leniently — this is for looking, publish is what validates. */\nexport const describeDraft = (cwd: string = process.cwd(), name?: string): DraftSummary => {\n const ref = resolveDraft(cwd, name, 'laracrew draft <name>');\n const raw = parseYaml(readFileSync(ref.file, 'utf8'), ref.file);\n const record = isRecord(raw) ? raw : {};\n const stackName = typeof record.name === 'string' ? record.name : ref.name;\n\n const projects = isRecord(record.projects)\n ? Object.entries(record.projects).map(([key, value]) => ({\n key,\n path: isRecord(value) && typeof value.path === 'string' ? value.path : '',\n }))\n : [];\n\n const services = Array.isArray(record.services)\n ? record.services.filter(isRecord).map((entry) => ({\n name: typeof entry.name === 'string' ? entry.name : '?',\n cmd: Array.isArray(entry.cmd) ? entry.cmd.map(String).join(' ') : typeof entry.cmd === 'string' ? entry.cmd : '',\n ...(typeof entry.project === 'string' ? { project: entry.project } : {}),\n autostart: entry.autostart !== false,\n }))\n : [];\n\n return {\n name: ref.name,\n file: ref.file,\n stackName,\n command: typeof record.command === 'string' ? record.command : stackName,\n projects,\n services,\n };\n};\n\n// ---------------------------------------------------------------- publish\n\nexport interface PublishOptions {\n cwd?: string;\n draft?: string;\n force?: boolean;\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface PublishResult {\n name: string;\n draft: string;\n file: string;\n target: string;\n replaced: boolean;\n config: StackConfig;\n}\n\n/** Validates the draft with the real schema and copies it, comments and all, into the home. */\nexport const publishDraft = (options: PublishOptions = {}): PublishResult => {\n const cwd = options.cwd ?? process.cwd();\n const env = options.env ?? process.env;\n const { name: draftName, file } = resolveDraft(cwd, options.draft);\n\n const source = readFileSync(file, 'utf8');\n const raw = parseYaml(source, file);\n if (isRecord(raw) && Array.isArray(raw.services) && raw.services.length === 0) {\n throw new ConfigError('the draft has no services yet', {\n file,\n details: ['add one with `laracrew draft add --command \"…\"`'],\n });\n }\n const config = validateStack(raw, file);\n\n const target = stackFile(config.name, env);\n const replaced = existsSync(target);\n if (replaced && !options.force) {\n throw new ConfigError(`a stack named \"${config.name}\" already exists`, {\n file: target,\n details: ['pass --force to replace it, or change `name:` in the draft'],\n });\n }\n mkdirSync(stackDir(config.name, env), { recursive: true });\n writeFileSync(target, source, 'utf8');\n\n return { name: config.name, draft: draftName, file, target, replaced, config };\n};\n\n// ---------------------------------------------------------------- console\n\nconst plural = (count: number, noun: string): string => `${count} ${noun}${count === 1 ? '' : 's'}`;\n\nexport const draftCommand = (\n name: string | undefined,\n options: { force?: boolean } = {},\n cwd: string = process.cwd(),\n env: NodeJS.ProcessEnv = process.env,\n): number => {\n const mark = marks(env);\n\n // `draft <name>` starts a draft, and shows it when it already exists — one verb for both.\n if (name && (options.force || !existsSync(draftFile(name, cwd)))) {\n const file = createDraft(name, { cwd, ...(options.force ? { force: true } : {}) });\n console.log(`${mark.ok} started draft ${color.bold(name)} ${mark.arrow} ${color.gray(path.basename(file))}`);\n console.log(\n `\\n${nextSteps(\n [\n ['laracrew draft add', `--project api --path C:/work/api --command ${color.green('\"php artisan queue:work\"')}`],\n ['', `--project api --command ${color.green('\"php artisan schedule:work\"')} ${color.gray('the path is remembered')}`],\n ['', `--command ${color.green('\"npm run dev\"')} --default-state stopped ${color.gray('idle until you press s')}`],\n ['laracrew draft', 'show what the draft holds so far'],\n ['laracrew draft publish', `install it as the ${color.cyan(name)} stack in ~/.laracrew`],\n ],\n env,\n )}\\n`,\n );\n return 0;\n }\n\n const draft = describeDraft(cwd, name);\n console.log(`${color.bold('draft')} ${color.gray('·')} ${color.cyan.bold(draft.stackName)} ${color.gray(path.basename(draft.file))}`);\n if (draft.command !== draft.stackName) console.log(` ${color.gray(`command: ${draft.command}`)}`);\n\n console.log(`\\n${color.bold('PROJECTS')} ${color.gray(`(${draft.projects.length})`)}`);\n if (draft.projects.length === 0) console.log(color.gray(' none — `--project <key> --path <dir>` on the next add'));\n const keyWidth = Math.max(4, ...draft.projects.map((project) => project.key.length));\n for (const project of draft.projects) {\n console.log(` ${color.magenta.bold(padEnd(project.key, keyWidth))} ${project.path}`);\n }\n\n console.log(`\\n${color.bold('SERVICES')} ${color.gray(`(${draft.services.length})`)}`);\n if (draft.services.length === 0) console.log(color.gray(' none yet — `laracrew draft add --command \"…\"`'));\n const nameWidth = Math.max(4, ...draft.services.map((service) => service.name.length));\n for (const service of draft.services) {\n const idle = service.autostart ? '' : ` ${color.yellow('idle until started')}`;\n console.log(` ${color.cyan.bold(padEnd(service.name, nameWidth))} ${service.cmd}${idle}`);\n }\n\n console.log(\n `\\n${nextSteps(\n [\n ['laracrew draft add', `--command ${color.green('\"…\"')} to add another`],\n ['laracrew draft publish', `install it as the ${color.cyan(draft.stackName)} stack`],\n ],\n env,\n )}\\n`,\n );\n return 0;\n};\n\nexport const draftAddCommand = (\n options: Omit<AddOptions, 'cwd'>,\n cwd: string = process.cwd(),\n env: NodeJS.ProcessEnv = process.env,\n): number => {\n const result = addToDraft({ ...options, cwd });\n const mark = marks(env);\n\n const idle = result.service.autostart ? '' : ` ${color.yellow('idle until started')}`;\n console.log(`${mark.ok} added ${color.bold(result.service.name)} ${mark.arrow} ${color.gray(result.service.cmd)}${idle}`);\n if (result.project?.created) {\n const guessed = options.path ? '' : ` ${color.yellow('this folder — pass --path if that is wrong')}`;\n console.log(` ${mark.ok} project ${color.magenta.bold(result.project.key)} ${mark.arrow} ${color.gray(result.project.path)}${guessed}`);\n }\n if (result.service.cwd) console.log(` ${color.gray(`runs in ${result.service.cwd}`)}`);\n console.log(\n ` ${color.gray(`${plural(result.services, 'service')} in ${path.basename(result.file)} — \\`laracrew draft publish\\` when done`)}`,\n );\n return 0;\n};\n\nexport const draftPublishCommand = (\n options: { force?: boolean; link?: boolean; draft?: string } = {},\n cwd: string = process.cwd(),\n env: NodeJS.ProcessEnv = process.env,\n): number => {\n const result = publishDraft({\n cwd,\n env,\n ...(options.draft ? { draft: options.draft } : {}),\n ...(options.force ? { force: true } : {}),\n });\n const mark = marks(env);\n const command = result.config.command ?? result.name;\n\n console.log(\n `${mark.ok} ${color.green(result.replaced ? 'replaced' : 'published')} ${color.bold(result.name)} ${mark.arrow} ${color.gray(result.target)}`,\n );\n console.log(\n ` ${color.gray(\n `${plural(Object.keys(result.config.projects).length, 'project')}, ${plural(result.config.services.length, 'service')}; the draft stays at ${path.basename(result.file)}`,\n )}`,\n );\n\n if (options.link) {\n console.log('');\n const code = linkCommand(result.name, {}, env);\n if (code !== 0) return code;\n }\n\n const steps: [string, string][] = [\n [`laracrew doctor ${result.name}`, 'check paths, ports and PHP before the first boot'],\n [`laracrew up ${result.name}`, 'boot it'],\n ];\n if (!options.link) steps.push([`laracrew link ${result.name}`, `type ${color.cyan(command)} from anywhere to boot it`]);\n console.log(`\\n${nextSteps(steps, env)}\\n`);\n return 0;\n};\n","import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { ConfigError } from '../../core/config/errors.js';\nimport { listStacks, loadStack } from '../../core/config/load.js';\nimport { paths } from '../../core/config/paths.js';\nimport { color } from '../render/colors.js';\nimport { marks } from '../render/marks.js';\n\nconst IS_WINDOWS = process.platform === 'win32';\n\n/** Stamped into every generated file so we never overwrite something we did not write. */\nexport const MARKER = 'laracrew-generated';\n\nconst RESERVED = new Set(['laracrew', 'node', 'npm', 'npx', 'php', 'git', 'cd', 'ls', 'rm', 'sh', 'bash']);\nconst VALID_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;\n\nexport interface ShimTarget {\n /** Absolute path to the node binary that should run laracrew. */\n node: string;\n /** Absolute path to laracrew's entry script. */\n entry: string;\n stack: string;\n}\n\n/**\n * The script the shim must hand to node. This is `process.argv[1]` — the entry Node was\n * actually given — not a path derived from this module's own location: tsup bundles the\n * whole program into one file, so any relative walk from here is wrong in a build.\n */\nexport const entryScript = (argv: string[] = process.argv): string => {\n const main = argv[1];\n if (!main) return fileURLToPath(import.meta.url);\n\n const resolved = path.resolve(main);\n if (!resolved.endsWith('.ts')) return resolved;\n\n // Running from TypeScript source (`npm run dev`): a shim cannot invoke .ts with plain\n // node, so point it at the built bundle instead.\n const dist = path.join(path.dirname(path.dirname(resolved)), 'dist', 'index.js');\n if (existsSync(dist)) return dist;\n\n throw new ConfigError('run `npm run build` first — a generated command has to point at dist/index.js');\n};\n\n/** Where laracrew is running from — embedded in the shim so PATH changes can't break it. */\nexport const currentTarget = (stack: string): ShimTarget => ({\n node: process.execPath,\n entry: entryScript(),\n stack,\n});\n\nconst forward = (value: string): string => value.replace(/\\\\/g, '/');\n\nexport const shShim = ({ node, entry, stack }: ShimTarget): string =>\n `#!/bin/sh\n# ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\nexec \"${forward(node)}\" \"${forward(entry)}\" up ${stack} \"$@\"\n`;\n\nexport const cmdShim = ({ node, entry, stack }: ShimTarget): string =>\n `@ECHO OFF\\r\nREM ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\\r\n\"${node}\" \"${entry}\" up ${stack} %*\\r\n`;\n\nexport const ps1Shim = ({ node, entry, stack }: ShimTarget): string =>\n `#!/usr/bin/env pwsh\n# ${MARKER}: boots the \"${stack}\" stack. Regenerate with \\`laracrew link ${stack}\\`.\n& \"${node}\" \"${entry}\" up ${stack} @args\nexit $LASTEXITCODE\n`;\n\n/** The files one command needs: three on Windows (sh, cmd, PowerShell), one elsewhere. */\nexport const shimFiles = (name: string, target: ShimTarget): { file: string; contents: string; exec: boolean }[] => {\n const posix = { file: name, contents: shShim(target), exec: true };\n if (!IS_WINDOWS) return [posix];\n return [\n posix, // Git Bash reads the extensionless file\n { file: `${name}.cmd`, contents: cmdShim(target), exec: false },\n { file: `${name}.ps1`, contents: ps1Shim(target), exec: true },\n ];\n};\n\nconst pathDirs = (env: NodeJS.ProcessEnv): string[] =>\n (env.PATH ?? env.Path ?? '').split(path.delimiter).filter(Boolean);\n\nconst samePath = (a: string, b: string): boolean =>\n IS_WINDOWS ? a.toLowerCase() === b.toLowerCase() : a === b;\n\n/** The directory on PATH that holds the `laracrew` command itself. */\nconst ownBinDir = (env: NodeJS.ProcessEnv): string | undefined => {\n for (const dir of pathDirs(env)) {\n for (const candidate of IS_WINDOWS ? ['laracrew.cmd', 'laracrew'] : ['laracrew']) {\n try {\n if (existsSync(path.join(dir, candidate))) return dir;\n } catch {\n // An unreadable PATH entry is not our problem.\n }\n }\n }\n return undefined;\n};\n\n/**\n * Wherever `laracrew` itself lives is by definition on PATH and writable by whoever\n * installed it, so sibling commands belong there. Asking npm for its prefix would mean\n * spawning npm on every call — slower, and it trips Node's shell-argument deprecation.\n */\nexport const resolveBinDir = (env: NodeJS.ProcessEnv = process.env): { dir: string; onPath: boolean } => {\n if (env.LARACREW_BIN) return { dir: path.resolve(env.LARACREW_BIN), onPath: true };\n\n const own = ownBinDir(env);\n if (own) return { dir: own, onPath: true };\n\n // Not installed globally (running from source): try npm's default prefix.\n const conventional = IS_WINDOWS\n ? env.APPDATA\n ? path.join(env.APPDATA, 'npm')\n : undefined\n : path.dirname(process.execPath);\n\n if (conventional && existsSync(conventional) && pathDirs(env).some((dir) => samePath(dir, conventional))) {\n return { dir: conventional, onPath: true };\n }\n\n return { dir: path.join(paths(env).root, 'bin'), onPath: false };\n};\n\nconst isOurs = (file: string): boolean => {\n try {\n return readFileSync(file, 'utf8').includes(MARKER);\n } catch {\n return false;\n }\n};\n\nexport interface LinkResult {\n name: string;\n stack: string;\n dir: string;\n onPath: boolean;\n files: string[];\n replaced: boolean;\n}\n\nexport const linkStack = (\n stackName: string,\n options: { as?: string; dir?: string; force?: boolean; env?: NodeJS.ProcessEnv } = {},\n): LinkResult => {\n const env = options.env ?? process.env;\n const { config } = loadStack(stackName, env); // validates before we create anything\n\n const name = options.as ?? config.command ?? stackName;\n\n if (!VALID_NAME.test(name)) {\n throw new ConfigError(\n `\"${name}\" is not a usable command name — letters, digits, dot, dash and underscore only`,\n );\n }\n if (RESERVED.has(name.toLowerCase()) && !options.force) {\n throw new ConfigError(`\"${name}\" would shadow an important command`, {\n details: ['pick another with `--as <name>`, or pass --force if you really mean it'],\n });\n }\n\n const resolved = options.dir ? { dir: path.resolve(options.dir), onPath: true } : resolveBinDir(env);\n mkdirSync(resolved.dir, { recursive: true });\n\n const target = currentTarget(stackName);\n const planned = shimFiles(name, target);\n\n let replaced = false;\n for (const { file } of planned) {\n const full = path.join(resolved.dir, file);\n if (!existsSync(full)) continue;\n if (isOurs(full)) {\n replaced = true;\n continue;\n }\n if (!options.force) {\n throw new ConfigError(`\"${full}\" already exists and was not created by laracrew`, {\n details: ['choose another name with `--as <name>`, or pass --force to overwrite'],\n });\n }\n replaced = true;\n }\n\n const written: string[] = [];\n for (const { file, contents, exec } of planned) {\n const full = path.join(resolved.dir, file);\n writeFileSync(full, contents, 'utf8');\n if (exec && !IS_WINDOWS) chmodSync(full, 0o755);\n else if (exec) {\n try {\n chmodSync(full, 0o755);\n } catch {\n // Windows ignores the mode; Git Bash still honours the shebang.\n }\n }\n written.push(full);\n }\n\n return { name, stack: stackName, dir: resolved.dir, onPath: resolved.onPath, files: written, replaced };\n};\n\nexport const unlinkCommandName = (\n name: string,\n options: { dir?: string; env?: NodeJS.ProcessEnv } = {},\n): string[] => {\n const env = options.env ?? process.env;\n const dir = options.dir ? path.resolve(options.dir) : resolveBinDir(env).dir;\n\n const removed: string[] = [];\n for (const candidate of [name, `${name}.cmd`, `${name}.ps1`]) {\n const full = path.join(dir, candidate);\n if (!existsSync(full)) continue;\n if (!isOurs(full)) {\n throw new ConfigError(`\"${full}\" was not created by laracrew — leaving it alone`);\n }\n unlinkSync(full);\n removed.push(full);\n }\n\n if (removed.length === 0) throw new ConfigError(`no laracrew command named \"${name}\" in ${dir}`);\n return removed;\n};\n\nexport interface InstalledLink {\n name: string;\n stack: string;\n file: string;\n}\n\n/** Every command in the bin directory that laracrew generated. */\nexport const listLinks = (options: { dir?: string; env?: NodeJS.ProcessEnv } = {}): InstalledLink[] => {\n const env = options.env ?? process.env;\n const dir = options.dir ? path.resolve(options.dir) : resolveBinDir(env).dir;\n if (!existsSync(dir)) return [];\n\n const found: InstalledLink[] = [];\n for (const entry of readdirSync(dir).sort()) {\n if (entry.endsWith('.cmd') || entry.endsWith('.ps1')) continue;\n const full = path.join(dir, entry);\n let contents: string;\n try {\n contents = readFileSync(full, 'utf8');\n } catch {\n continue;\n }\n if (!contents.includes(MARKER)) continue;\n const stack = /\\bup ([^\\s\"]+)/.exec(contents)?.[1];\n if (stack) found.push({ name: entry, stack, file: full });\n }\n return found;\n};\n\nexport const linkCommand = (\n stackName: string | undefined,\n options: { as?: string; dir?: string; force?: boolean; all?: boolean },\n env: NodeJS.ProcessEnv = process.env,\n): number => {\n const stacks = options.all ? listStacks(env) : stackName ? [stackName] : [];\n if (stacks.length === 0) {\n throw new ConfigError('name a stack to link, or pass --all');\n }\n\n const results: LinkResult[] = [];\n for (const stack of stacks) {\n // With --all, a stack that opts out by having no `command:` is skipped rather than\n // silently claiming a global name derived from its folder.\n if (options.all) {\n const { config } = loadStack(stack, env);\n if (!config.command) continue;\n }\n results.push(\n linkStack(stack, {\n ...(options.as ? { as: options.as } : {}),\n ...(options.dir ? { dir: options.dir } : {}),\n ...(options.force ? { force: options.force } : {}),\n env,\n }),\n );\n }\n\n const mark = marks(env);\n\n if (results.length === 0) {\n console.log(\n `${mark.warn} ${color.yellow('nothing to link — add `command: <name>` to the stacks you want a command for')}`,\n );\n return 0;\n }\n\n for (const result of results) {\n const verb = result.replaced ? 'updated' : 'created';\n console.log(\n `${mark.ok} ${color.green(verb)} ${color.bold(result.name)} ${mark.arrow} ${color.gray(`laracrew up ${result.stack}`)}`,\n );\n }\n\n const first = results[0]!;\n console.log(`\\n${color.gray(`in ${first.dir}`)}`);\n\n if (!first.onPath) {\n console.log(\n `\\n${mark.warn} ${color.yellow('that directory is not on your PATH.')} Add it once:\\n` +\n (IS_WINDOWS\n ? ` ${color.cyan(`setx PATH \"%PATH%;${first.dir}\"`)} ${color.gray('(then reopen the terminal)')}`\n : ` ${color.cyan(`echo 'export PATH=\"$PATH:${first.dir}\"' >> ~/.bashrc`)}`),\n );\n } else {\n console.log(`\\nRun it from anywhere: ${color.cyan.bold(first.name)}`);\n console.log(color.gray(`Flags pass straight through: ${first.name} --only workers`));\n }\n\n return 0;\n};\n\nexport const unlinkCommandAction = (name: string, env: NodeJS.ProcessEnv = process.env): number => {\n const removed = unlinkCommandName(name, { env });\n const mark = marks(env);\n for (const file of removed) console.log(`${mark.ok} removed ${color.gray(file)}`);\n return 0;\n};\n","import { mkdirSync, writeFileSync, existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { paths } from '../../core/config/paths.js';\nimport { color } from '../render/colors.js';\nimport { marks, nextSteps } from '../render/marks.js';\nimport {\n CONFIG_YAML,\n EXAMPLE_STACK_YAML,\n HOME_README,\n PROJECTS_YAML,\n REAL_STACK_TEMPLATE,\n RESET_TASK_YAML,\n} from './templates.js';\n\nexport interface InitOptions {\n /** Also write the demo stack, the two-project template and the sample task. */\n examples?: boolean;\n}\n\nexport interface InitResult {\n root: string;\n created: string[];\n skipped: string[];\n examples: boolean;\n}\n\n/** Idempotent: re-running never overwrites something you edited. */\nexport const runInit = (env: NodeJS.ProcessEnv = process.env, options: InitOptions = {}): InitResult => {\n const home = paths(env);\n const created: string[] = [];\n const skipped: string[] = [];\n\n for (const dir of [home.root, home.stacksDir, home.tasksDir, home.fragmentsDir, home.logsDir, home.runDir]) {\n mkdirSync(dir, { recursive: true });\n }\n\n const files: [string, string][] = [\n [home.configFile, CONFIG_YAML],\n [home.projectsFile, PROJECTS_YAML],\n [path.join(home.root, 'README.md'), HOME_README],\n ];\n\n if (options.examples) {\n mkdirSync(path.join(home.stacksDir, 'example'), { recursive: true });\n mkdirSync(path.join(home.stacksDir, 'dual'), { recursive: true });\n files.push(\n [path.join(home.stacksDir, 'example', 'stack.yaml'), EXAMPLE_STACK_YAML],\n [path.join(home.stacksDir, 'dual', 'stack.yaml'), REAL_STACK_TEMPLATE],\n [path.join(home.tasksDir, 'reset.yaml'), RESET_TASK_YAML],\n );\n }\n\n for (const [file, contents] of files) {\n if (existsSync(file)) {\n skipped.push(file);\n continue;\n }\n writeFileSync(file, contents, 'utf8');\n created.push(file);\n }\n\n return { root: home.root, created, skipped, examples: options.examples ?? false };\n};\n\nexport const initCommand = (options: InitOptions = {}, env: NodeJS.ProcessEnv = process.env): void => {\n const result = runInit(env, options);\n const mark = marks(env);\n\n console.log(`${color.bold('laracrew home')} ${color.gray(result.root)}`);\n for (const file of result.created) console.log(` ${mark.ok} ${path.relative(result.root, file)}`);\n for (const file of result.skipped) {\n console.log(` ${mark.skip} ${color.gray(`${path.relative(result.root, file)} (kept)`)}`);\n }\n\n const steps: [string, string][] = result.examples\n ? [\n ['laracrew up example', 'run the demo stack — proves it works, no Laravel needed'],\n ['laracrew link example', 'install it as a global command you can type from anywhere'],\n ['laracrew doctor dual', `check the real stack once ${color.gray(path.join(result.root, 'projects.yaml'))}`],\n ['', `has your project paths, then ${color.cyan('laracrew up dual')}`],\n ]\n : [\n ['laracrew init --examples', 'add a runnable demo stack and a two-project template,'],\n ['', `or write your own at ${color.gray(path.join(result.root, 'stacks', '<name>', 'stack.yaml'))}`],\n ['laracrew draft <name>', 'or build one in a project folder, one command at a time'],\n ['laracrew up <name>', `boot it — ${color.cyan('laracrew ls')} shows what is defined`],\n ];\n console.log(`\\n${nextSteps(steps, env)}\\n`);\n};\n","/**\n * Kept as string constants rather than shipped files: no path resolution to get wrong\n * between `tsx src/index.ts` and the bundled `dist/index.js`, and nothing to forget in\n * package.json#files.\n */\n\nexport const CONFIG_YAML = `# laracrew global preferences\n# theme: auto | dark | light | mono | high-contrast\ntheme: auto\n\n# Polling interval for queue depth and stream lag, in milliseconds.\nmetricsIntervalMs: 2000\n\n# The stack \\`laracrew up\\` boots when you don't name one.\n# defaultStack: dual\n`;\n\nexport const PROJECTS_YAML = `# Your projects, referenced by key from any stack. A project is just a root directory\n# plus the defaults its services inherit — cwd, .env and colour. Any language.\n# Paths may use forward slashes on Windows.\n#\n# Declaring projects here is optional: a service can carry its own \\`cwd\\` instead.\nprojects: {}\n\n# Example — delete the \\`{}\\` above and uncomment:\n#\n# projects:\n# api:\n# path: D:/work/api\n# php: php # only used by \\`stop: { artisan: ... }\\`; ignore it for non-PHP projects\n# envFile: .env # read for \\${project.env:KEY} tokens, and by \\`doctor\\`\n# color: cyan\n# web:\n# path: D:/work/web\n# envFile: .env\n# color: magenta\n`;\n\n/** A stack that actually runs on a fresh install, so `laracrew up example` works immediately. */\nexport const EXAMPLE_STACK_YAML = `# A runnable demo stack — no Laravel project required.\n# Try: laracrew up example\n# Then: laracrew up example --only workers\nname: example\ndescription: Three fake services that prove laracrew works on this machine\n\n# \\`laracrew link example\\` installs this as a global command you can run from anywhere.\ncommand: demo\n\ndefaults:\n restart: on-failure\n backoff: { initialMs: 500, maxMs: 5000, factor: 2, maxRestarts: 5 }\n stop: { graceMs: 5000 }\n\nservices:\n - name: demo:heartbeat\n cmd: [\"node\", \"-e\", \"let n=0; setInterval(() => console.log('heartbeat ' + (++n)), 1000)\"]\n groups: [workers]\n color: cyan\n\n - name: demo:worker\n cmd: [\"node\", \"-e\", \"let n=0; setInterval(() => console.log('processed job #' + (++n)), 1700)\"]\n groups: [workers]\n needs: [demo:heartbeat]\n color: magenta\n\n - name: demo:slow-starter\n cmd: [\"node\", \"-e\", \"setTimeout(() => console.log('listening on 9'), 1200); setInterval(() => {}, 1000)\"]\n groups: [http]\n ready: { logMatch: \"listening on\", timeoutMs: 10000 }\n color: green\n\nprofiles:\n quiet:\n except: [http]\n`;\n\nexport const REAL_STACK_TEMPLATE = `# Two interconnected Laravel projects: queues, Redis stream listeners, schedulers.\n# Fill in the project paths in ~/.laracrew/projects.yaml first, then: laracrew up dual\nname: dual\ndescription: API + Portal with queues, streams and schedulers\n\n# Run \\`laracrew link dual\\` and this whole set boots by typing \\`dual\\` from anywhere.\ncommand: dual\n\nuse: [api, portal]\n\ndefaults:\n restart: on-failure\n backoff: { initialMs: 1000, maxMs: 30000, factor: 2, maxRestarts: 10 }\n stop: { graceMs: 10000 }\n logs: { maxLines: 5000, toFile: false }\n\nservices:\n - name: redis\n external: true # laracrew checks it, never starts it\n ready: { tcp: \"127.0.0.1:6379\" }\n\n - name: api:serve\n project: api\n cmd: php artisan serve --port=\\${port:8000}\n groups: [http]\n needs: [redis]\n ready: { http: \"http://127.0.0.1:8000/up\", timeoutMs: 20000 }\n url: http://127.0.0.1:8000\n\n - name: api:queue\n project: api\n cmd: php artisan queue:work redis --queue=high,default --tries=3 --timeout=90\n groups: [workers]\n needs: [redis]\n stop: { artisan: \"queue:restart\", graceMs: 15000 }\n watch:\n paths: [app, config, routes, database]\n strategy: artisan-queue-restart\n debounceMs: 800\n metrics:\n queues: [high, default]\n\n - name: api:streams\n project: api\n cmd: php artisan streams:listen orders\n groups: [workers, streams]\n needs: [redis]\n metrics:\n streams:\n - { key: orders, group: api-consumers }\n\n - name: api:schedule\n project: api\n cmd: php artisan schedule:work\n groups: [workers]\n needs: [redis]\n\n - name: portal:serve\n project: portal\n cmd: php artisan serve --port=\\${port:8001}\n groups: [http]\n needs: [redis, api:serve] # don't boot until the API answers\n ready: { http: \"http://127.0.0.1:8001/up\", timeoutMs: 20000 }\n url: http://127.0.0.1:8001\n\n - name: portal:queue\n project: portal\n cmd: php artisan queue:work redis --queue=default --tries=3\n groups: [workers]\n needs: [redis, api:serve]\n stop: { artisan: \"queue:restart\" }\n watch: { paths: [app, config], strategy: artisan-queue-restart }\n metrics: { queues: [default] }\n\n - name: portal:streams\n project: portal\n cmd: php artisan streams:listen inventory\n groups: [workers, streams]\n needs: [redis]\n metrics:\n streams:\n - { key: inventory, group: portal-consumers }\n\nprofiles:\n light:\n except: [assets]\n workers-only:\n only: [workers]\n`;\n\nexport const RESET_TASK_YAML = `# laracrew run reset\nname: reset\ndescription: Wipe and reseed both databases in the right order\npauseServices: [workers] # stopped before the steps, restarted after\nsteps:\n - { project: api, cmd: php artisan migrate:fresh --seed }\n - { project: portal, cmd: php artisan migrate:fresh --seed }\n - parallel:\n - { project: api, cmd: php artisan cache:clear }\n - { project: portal, cmd: php artisan cache:clear }\n`;\n\nexport const HOME_README = `# ~/.laracrew\n\nYour laracrew configuration. Safe to keep in git — nothing here is secret unless you put\nsecrets in it.\n\n config.yaml global preferences\n projects.yaml your Laravel projects, referenced by key\n stacks/<name>/ one folder per stack; stack.yaml is the definition\n tasks/<name>.yaml one-shot sequences (laracrew run <name>)\n fragments/ shared YAML any stack can reuse\n logs/ per-run log files, when defaults.logs.toFile is on\n\nStart here:\n\n laracrew init --examples # add a demo stack and a two-project template\n laracrew draft <name> # build a stack in a project folder, one command at a time\n laracrew ls # what is defined\n laracrew doctor <stack> # check a stack before booting it\n laracrew link <stack> # give a stack its own global command\n`;\n","import { existsSync, readdirSync } from 'node:fs';\nimport path from 'node:path';\nimport { ConfigError, didYouMean } from '../../core/config/errors.js';\nimport { paths } from '../../core/config/paths.js';\nimport { fileNamesFor } from '../../core/logs/file-sink.js';\nimport { followFile, parseSince, tailFile, toEntries } from '../../core/logs/read.js';\nimport type { LogLine } from '../../core/events/types.js';\nimport { color, padEnd } from '../render/colors.js';\nimport { marks } from '../render/marks.js';\nimport { glyphs } from '../../tui/theme.js';\nimport { write as safeWrite } from '../render/output.js';\nimport { prepareStack } from './up.js';\n\nexport interface LogsOptions {\n stack?: string;\n lines?: number;\n follow?: boolean;\n since?: string;\n all?: boolean;\n list?: boolean;\n env?: NodeJS.ProcessEnv;\n}\n\nexport const logDirFor = (stackName: string, env: NodeJS.ProcessEnv = process.env): string =>\n path.join(paths(env).logsDir, stackName);\n\ninterface Target {\n service: string;\n file: string;\n color: string;\n}\n\n/** Every service of a stack that has a log file on disk. */\nexport const targetsFor = (stackName: string, env: NodeJS.ProcessEnv = process.env): Target[] => {\n const stack = prepareStack(stackName, { env });\n const dir = logDirFor(stackName, env);\n const names = fileNamesFor(stack.services.map((service) => service.name));\n\n return stack.services\n .map((service) => ({\n service: service.name,\n file: path.join(dir, names.get(service.name)!),\n color: service.color,\n }))\n .filter((target) => existsSync(target.file));\n};\n\nconst formatEntry = (entry: LogLine, width: number, withName: boolean): string => {\n const time = new Date(entry.at || Date.now());\n const clock = [time.getHours(), time.getMinutes(), time.getSeconds()]\n .map((part) => String(part).padStart(2, '0'))\n .join(':');\n\n const who = withName ? `${color.cyan(padEnd(entry.service, width))} ` : '';\n const body = entry.stream === 'stderr' ? color.red(entry.line) : entry.line;\n return `${color.gray(clock)} ${who}${color.gray('|')} ${body}\\n`;\n};\n\nexport const logsCommand = async (service: string | undefined, options: LogsOptions = {}): Promise<number> => {\n const env = options.env ?? process.env;\n const stackName = options.stack;\n if (!stackName) throw new ConfigError('name a stack with --stack, or run `laracrew logs` from a known stack');\n\n const dir = logDirFor(stackName, env);\n const available = targetsFor(stackName, env);\n\n const mark = marks(env);\n\n if (options.list) {\n if (available.length === 0) {\n console.log(`${mark.warn} ${color.yellow(`no log files yet in ${dir}`)}`);\n console.log(` ${color.gray('they appear once the stack has run at least once')}`);\n return 0;\n }\n console.log(`${color.bold('logs')} ${color.gray(glyphs(env).dot)} ${color.cyan.bold(stackName)}`);\n console.log(` ${color.gray(dir)}`);\n for (const target of available) {\n console.log(` ${color.cyan(target.service)} ${color.gray(path.basename(target.file))}`);\n }\n return 0;\n }\n\n if (available.length === 0) {\n console.error(`${mark.warn} ${color.yellow(`no log files in ${dir}`)}`);\n console.error(\n ` ${color.gray('run the stack at least once, and check `defaults.logs.toFile` is not set to false')}`,\n );\n return 1;\n }\n\n let selected: Target[];\n if (options.all || !service) {\n selected = available;\n } else {\n const match = available.find((target) => target.service === service);\n if (!match) {\n const suggestion = didYouMean(\n service,\n available.map((target) => target.service),\n );\n throw new ConfigError(\n `no log for service \"${service}\" in stack \"${stackName}\"` +\n (suggestion ? ` — did you mean \"${suggestion}\"?` : ''),\n { details: [`available: ${available.map((target) => target.service).join(', ')}`] },\n );\n }\n selected = [match];\n }\n\n const withName = selected.length > 1;\n const width = Math.max(...selected.map((target) => target.service.length));\n const limit = options.lines ?? 200;\n const since = options.since ? parseSince(options.since) : undefined;\n\n if (options.since && since === undefined) {\n throw new ConfigError(`could not read --since \"${options.since}\"`, {\n details: ['try a relative window like 10m, 2h, 1d, or an absolute date'],\n });\n }\n\n // History first, merged across services and ordered by time.\n const history: LogLine[] = [];\n for (const target of selected) {\n // When filtering by time we need a wider net than `limit`, since the matching lines\n // may be spread across a much longer file.\n history.push(...toEntries(target.service, tailFile(target.file, since ? Math.max(limit, 5_000) : limit)));\n }\n\n history.sort((a, b) => a.at - b.at);\n const filtered = since ? history.filter((entry) => entry.at >= since) : history;\n for (const entry of filtered.slice(-limit)) safeWrite(formatEntry(entry, width, withName));\n\n if (!options.follow) return 0;\n\n // Then tail.\n const controller = new AbortController();\n const stops = selected.map((target) =>\n followFile(target.file, {\n signal: controller.signal,\n onLines: (lines) => {\n for (const entry of toEntries(target.service, lines)) {\n safeWrite(formatEntry(entry, width, withName));\n }\n },\n }),\n );\n\n await new Promise<void>((resolve) => {\n const finish = (): void => {\n controller.abort();\n for (const stop of stops) stop();\n resolve();\n };\n process.once('SIGINT', finish);\n process.once('SIGTERM', finish);\n });\n\n return 0;\n};\n\n/** Stacks that have a log directory, for a helpful error when none is named. */\nexport const stacksWithLogs = (env: NodeJS.ProcessEnv = process.env): string[] => {\n const root = paths(env).logsDir;\n if (!existsSync(root)) return [];\n return readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort();\n};\n","import { openSync, readSync, closeSync, statSync, existsSync } from 'node:fs';\nimport type { LogLine } from '../events/types.js';\nimport { parseLine } from './file-sink.js';\n\n/**\n * Reading back what the sink wrote. Tailing reads from the end of the file rather than\n * loading it, so a rotated-but-still-large log does not cost a heap allocation.\n */\n\nconst CHUNK = 64 * 1024;\n\n/** The last `limit` lines of a file, oldest first, without reading the whole thing. */\nexport const tailFile = (file: string, limit: number): string[] => {\n if (!existsSync(file) || limit <= 0) return [];\n\n const size = statSync(file).size;\n if (size === 0) return [];\n\n const handle = openSync(file, 'r');\n try {\n let position = size;\n let text = '';\n let newlines = 0;\n\n while (position > 0 && newlines <= limit) {\n const length = Math.min(CHUNK, position);\n position -= length;\n\n const buffer = Buffer.alloc(length);\n readSync(handle, buffer, 0, length, position);\n const chunk = buffer.toString('utf8');\n\n text = chunk + text;\n newlines = 0;\n for (const character of text) if (character === '\\n') newlines += 1;\n }\n\n const lines = text.split('\\n');\n if (lines.at(-1) === '') lines.pop();\n return lines.slice(-limit);\n } finally {\n closeSync(handle);\n }\n};\n\n/** Turns raw file lines into log entries, keeping unparseable lines rather than dropping them. */\nexport const toEntries = (service: string, lines: readonly string[]): LogLine[] =>\n lines.map((raw) => {\n const parsed = parseLine(raw);\n if (!parsed) return { service, stream: 'stdout' as const, line: raw, at: 0 };\n return {\n service,\n stream: (parsed.stream === 'stderr' ? 'stderr' : parsed.stream === 'system' ? 'system' : 'stdout') as\n | 'stdout'\n | 'stderr'\n | 'system',\n line: parsed.line,\n at: parsed.at,\n };\n });\n\n/**\n * `10m`, `2h`, `90s`, `1d`, or anything `Date` understands. Returns a timestamp in ms.\n */\nexport const parseSince = (input: string): number | undefined => {\n const relative = /^(\\d+)\\s*(s|m|h|d)$/i.exec(input.trim());\n if (relative) {\n const amount = Number(relative[1]);\n const unit = relative[2]!.toLowerCase();\n const ms = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 }[unit] ?? 0;\n return Date.now() - amount * ms;\n }\n\n const absolute = new Date(input).getTime();\n return Number.isNaN(absolute) ? undefined : absolute;\n};\n\nexport interface FollowOptions {\n /** How often to check for new bytes. Polling is steadier than fs.watch across platforms. */\n intervalMs?: number;\n signal?: AbortSignal;\n onLines: (lines: string[]) => void;\n}\n\n/**\n * Watches a file for appended lines. Handles the file being rotated out from under us by\n * noticing the size shrank and starting again from the top.\n */\nexport const followFile = (file: string, options: FollowOptions): (() => void) => {\n let position = existsSync(file) ? statSync(file).size : 0;\n let carry = '';\n\n const read = (): void => {\n if (!existsSync(file)) return;\n\n const size = statSync(file).size;\n if (size === position) return;\n\n // Rotation: the file we were reading was renamed and a fresh one took its place.\n if (size < position) {\n position = 0;\n carry = '';\n }\n\n const length = size - position;\n const handle = openSync(file, 'r');\n try {\n const buffer = Buffer.alloc(length);\n readSync(handle, buffer, 0, length, position);\n position = size;\n\n const text = carry + buffer.toString('utf8');\n const lines = text.split('\\n');\n carry = lines.pop() ?? '';\n if (lines.length > 0) options.onLines(lines);\n } finally {\n closeSync(handle);\n }\n };\n\n const timer = setInterval(read, options.intervalMs ?? 300);\n timer.unref?.();\n\n const stop = (): void => clearInterval(timer);\n options.signal?.addEventListener('abort', stop, { once: true });\n return stop;\n};\n","import { existsSync } from 'node:fs';\nimport { listStacks, listTasks, loadSharedProjects, loadStack } from '../../core/config/load.js';\nimport { paths } from '../../core/config/paths.js';\nimport { ConfigError } from '../../core/config/errors.js';\nimport { listLinks } from './link.js';\nimport { color, padEnd } from '../render/colors.js';\nimport { marks } from '../render/marks.js';\n\nexport const lsCommand = (env: NodeJS.ProcessEnv = process.env, json = false): number => {\n const home = paths(env);\n const mark = marks(env);\n\n if (!existsSync(home.root)) {\n console.error(`${mark.warn} ${color.yellow('no laracrew home yet')} — run ${color.cyan('laracrew init')}`);\n return 1;\n }\n\n const stackNames = listStacks(env);\n const taskNames = listTasks(env);\n const projects = loadSharedProjects(env);\n\n const linkedByStack = new Map(listLinks({ env }).map((link) => [link.stack, link.name] as const));\n\n const stacks = stackNames.map((name) => {\n try {\n const { config } = loadStack(name, env);\n return {\n name,\n description: config.description ?? '',\n services: config.services.length,\n profiles: Object.keys(config.profiles),\n command: linkedByStack.get(name) ?? null,\n valid: true,\n };\n } catch (error) {\n return {\n name,\n description: error instanceof ConfigError ? error.message : 'invalid',\n services: 0,\n profiles: [],\n command: linkedByStack.get(name) ?? null,\n valid: false,\n };\n }\n });\n\n if (json) {\n console.log(JSON.stringify({ root: home.root, stacks, tasks: taskNames, projects }, null, 2));\n return 0;\n }\n\n const heading = (label: string, count: number): string => `\\n${color.bold(label)} ${color.gray(`(${count})`)}`;\n\n console.log(`${color.bold('laracrew')} ${color.gray(home.root)}`);\n\n console.log(heading('STACKS', stacks.length));\n if (stacks.length === 0) {\n console.log(color.gray(' none — run `laracrew init --examples`, or write stacks/<name>/stack.yaml'));\n }\n const width = Math.max(4, ...stacks.map((stack) => stack.name.length));\n const indent = ' '.repeat(width + 4);\n for (const stack of stacks) {\n if (stack.valid) {\n const meta = padEnd(`${stack.services} service${stack.services === 1 ? '' : 's'}`, 11);\n console.log(` ${color.cyan.bold(padEnd(stack.name, width))} ${color.gray(meta)} ${stack.description}`.trimEnd());\n } else {\n console.log(\n `${mark.fail} ${color.red.bold(padEnd(stack.name, width))} ${color.red(padEnd('invalid', 11))} ${color.red(stack.description)}`,\n );\n }\n if (stack.command) console.log(`${indent}${color.green(`$ ${stack.command}`)} ${color.gray('global command')}`);\n if (stack.profiles.length > 0) console.log(`${indent}${color.gray(`profiles: ${stack.profiles.join(', ')}`)}`);\n }\n\n const projectKeys = Object.keys(projects);\n console.log(heading('PROJECTS', projectKeys.length));\n if (projectKeys.length === 0) console.log(color.gray(' none — add them to projects.yaml'));\n const projectWidth = Math.max(4, ...projectKeys.map((key) => key.length));\n for (const [key, project] of Object.entries(projects)) {\n const exists = existsSync(project.path);\n const lead = exists ? ' ' : `${mark.fail} `;\n const where = exists ? project.path : color.red(`${project.path} (missing)`);\n console.log(`${lead}${color.magenta.bold(padEnd(key, projectWidth))} ${where}`);\n }\n\n console.log(heading('TASKS', taskNames.length));\n if (taskNames.length === 0) console.log(color.gray(' none'));\n for (const task of taskNames) console.log(` ${color.green(task)}`);\n\n console.log('');\n return 0;\n};\n","import { run } from './cli/program.js';\nimport { color } from './cli/render/colors.js';\nimport { marks } from './cli/render/marks.js';\nimport { installPipeGuards } from './cli/render/output.js';\n\ninstallPipeGuards();\n\nrun().catch((error: unknown) => {\n // Set exitCode rather than calling process.exit(), which truncates pending stdout writes.\n const [head, ...trace] = (error instanceof Error ? (error.stack ?? error.message) : String(error)).split('\\n');\n console.error(`${marks().fail} ${color.red.bold(head ?? 'unexpected error')}`);\n if (trace.length > 0) console.error(color.gray(trace.join('\\n')));\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["readFileSync","path","fileURLToPath","path","path","existsSync","path","path","existsSync","readFileSync","path","path","existsSync","path","existsSync","statSync","path","pad","path","existsSync","statSync","spawn","IS_WINDOWS","path","process","write","stamp","dependencies","paint","color","stamp","ESC","CSI","handlers","paint","color","supervisor","process","existsSync","path","existsSync","mkdirSync","readFileSync","readdirSync","writeFileSync","path","existsSync","mkdirSync","readFileSync","readdirSync","path","IS_WINDOWS","path","existsSync","readFileSync","mkdirSync","readdirSync","forward","path","samePath","isRecord","readdirSync","existsSync","writeFileSync","readFileSync","word","mkdirSync","mkdirSync","writeFileSync","existsSync","path","home","mkdirSync","path","existsSync","writeFileSync","existsSync","readdirSync","path","openSync","closeSync","statSync","existsSync","existsSync","statSync","openSync","closeSync","path","existsSync","time","existsSync","home","existsSync","write"]}