@precisa-saude/worktree-cli 1.4.0 → 1.5.1

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/bin.js CHANGED
@@ -353,7 +353,7 @@ function spawnService(svc, entry, cwd, branch, detach) {
353
353
  return out;
354
354
  };
355
355
  const rawArgs = devArgs(svc);
356
- const args = ["--filter", svc.pnpmFilter, "dev", "--", ...rawArgs.map(interpolate)];
356
+ const args = ["--filter", svc.pnpmFilter, "dev", ...rawArgs.map(interpolate)];
357
357
  const env = { ...process.env };
358
358
  for (const [k, v] of Object.entries(svc.env ?? {})) {
359
359
  env[k] = interpolate(v);
@@ -448,7 +448,7 @@ async function logs({ branch, cfg, service }) {
448
448
  }
449
449
 
450
450
  // src/commands/setup.ts
451
- import { execFileSync } from "child_process";
451
+ import { execFileSync, spawnSync as spawnSync2 } from "child_process";
452
452
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync } from "fs";
453
453
  import { dirname as dirname2, resolve as resolve3 } from "path";
454
454
  import chalk3 from "chalk";
@@ -461,9 +461,9 @@ async function setup({ branch, cfg, repoRoot }) {
461
461
  }
462
462
  console.log(chalk3.bold(`==> Creating worktree for '${branch}' at ${wtPath}...`));
463
463
  execFileSync("git", ["-C", repoRoot, "fetch", "origin", "main"], { stdio: "inherit" });
464
- execFileSync("git", ["-C", repoRoot, "worktree", "add", "-b", branch, wtPath, "origin/main"], {
465
- stdio: "inherit"
466
- });
464
+ const reuseExisting = branchExists(repoRoot, branch);
465
+ const addArgs = reuseExisting ? ["-C", repoRoot, "worktree", "add", wtPath, branch] : ["-C", repoRoot, "worktree", "add", "-b", branch, wtPath, "origin/main"];
466
+ execFileSync("git", addArgs, { stdio: "inherit" });
467
467
  const entry = await allocate(cfg, branch);
468
468
  if (cfg.install !== false) {
469
469
  console.log(chalk3.bold("==> Installing dependencies (pnpm install)..."));
@@ -499,6 +499,20 @@ async function setup({ branch, cfg, repoRoot }) {
499
499
  console.log("To start the dev server(s):");
500
500
  console.log(` cd ${wtPath} && precisa-worktree dev ${branch}`);
501
501
  }
502
+ function branchExists(repoRoot, branch) {
503
+ const local = spawnSync2(
504
+ "git",
505
+ ["-C", repoRoot, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`],
506
+ { stdio: "ignore" }
507
+ );
508
+ if (local.status === 0) return true;
509
+ const remote = spawnSync2(
510
+ "git",
511
+ ["-C", repoRoot, "show-ref", "--verify", "--quiet", `refs/remotes/origin/${branch}`],
512
+ { stdio: "ignore" }
513
+ );
514
+ return remote.status === 0;
515
+ }
502
516
 
503
517
  // src/commands/stop.ts
504
518
  import chalk4 from "chalk";
@@ -552,8 +566,8 @@ async function teardown({
552
566
  if (keepBranch) {
553
567
  console.log(`Preserving local branch: ${branch}`);
554
568
  } else {
555
- const branchExists = branchRefExists(repoRoot, branch);
556
- if (branchExists) {
569
+ const branchExists2 = branchRefExists(repoRoot, branch);
570
+ if (branchExists2) {
557
571
  console.log(chalk5.bold(`Deleting local branch: ${branch}`));
558
572
  try {
559
573
  execFileSync2("git", ["-C", repoRoot, "branch", "-d", branch], {
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/commands/dev.ts","../src/config.ts","../src/paths.ts","../src/ports.ts","../src/registry.ts","../src/commands/list.ts","../src/commands/logs.ts","../src/commands/setup.ts","../src/commands/stop.ts","../src/commands/teardown.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { rmdirSync } from 'node:fs';\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nimport { dev } from './commands/dev.js';\nimport { list } from './commands/list.js';\nimport { logs } from './commands/logs.js';\nimport { setup } from './commands/setup.js';\nimport { stop } from './commands/stop.js';\nimport { teardown } from './commands/teardown.js';\nimport { loadConfig, lockDir, type WorktreeConfig } from './config.js';\nimport { detectBranch, findRepoRoot, mainWorktreeRoot } from './paths.js';\n\nasync function main(): Promise<void> {\n const program = new Command();\n program\n .name('precisa-worktree')\n .description('Git-worktree lifecycle CLI for Precisa Saúde repositories')\n .version('1.0.4');\n\n program\n .command('setup <branch>')\n .description('Create a worktree, install deps, allocate ports')\n .action(async (branch: string) => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await setup({ branch, cfg, repoRoot: mainRoot });\n });\n\n program\n .command('dev [branch]')\n .description('Start dev server(s) on the allocated ports')\n .option('-d, --detach', 'Run detached (nohup-style); write to log files', false)\n .option('-f, --force', 'Kill any process already on the port', false)\n .action(async (branchArg: string | undefined, opts: { detach: boolean; force: boolean }) => {\n const { branch, cfg, wtRoot } = await resolveContext({ allowDetect: true, branchArg });\n await dev({ branch, cfg, detach: opts.detach, force: opts.force, repoRoot: wtRoot });\n });\n\n program\n .command('stop [branch]')\n .description('Kill dev server(s) for a worktree')\n .action(async (branchArg?: string) => {\n const { branch, cfg } = await resolveContext({ allowDetect: true, branchArg });\n await stop({ branch, cfg });\n });\n\n program\n .command('teardown <branch>')\n .description('Stop dev servers, remove worktree, delete branch, free ports')\n .option('--keep-branch', 'Preserve the local branch', false)\n .action(async (branch: string, opts: { keepBranch: boolean }) => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await teardown({ branch, cfg, keepBranch: opts.keepBranch, repoRoot: mainRoot });\n });\n\n program\n .command('list')\n .description('List all worktrees with ports and status')\n .action(async () => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await list({ cfg, repoRoot: mainRoot });\n });\n\n program\n .command('logs [branch]')\n .description('Tail the log for a worktree dev server')\n .option('-s, --service <name>', 'Service name (defaults to the first configured)')\n .action(async (branchArg: string | undefined, opts: { service?: string }) => {\n const { branch, cfg } = await resolveContext({ allowDetect: true, branchArg });\n await logs({ branch, cfg, service: opts.service });\n });\n\n // Global EXIT handler — release the lock if we died mid-operation.\n // Safe because `rmdir` only succeeds on an empty directory we created.\n process.on('exit', () => {\n try {\n // Best-effort; we don't know the config if we failed before loading it.\n // This handler is installed after config load via resolveContext.\n } catch {\n // ignore\n }\n });\n\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n}\n\ninterface ResolveOpts {\n /** Allow `detectBranch()` when inside a linked worktree. */\n allowDetect?: boolean;\n branchArg?: string | undefined;\n /** Require the repo root to be the main worktree (setup/teardown/list). */\n requireMain?: boolean;\n}\n\nasync function resolveContext(opts: ResolveOpts): Promise<{\n cfg: WorktreeConfig;\n wtRoot: string;\n mainRoot: string;\n branch: string;\n}> {\n const wtRoot = findRepoRoot();\n const mainRoot = mainWorktreeRoot();\n const cfg = await loadConfig(mainRoot);\n\n // Install an exit handler now that we know the lock path.\n const lockPath = lockDir(cfg);\n process.on('exit', () => {\n try {\n rmdirSync(lockPath);\n } catch {\n // already released or never held\n }\n });\n\n let branch = opts.branchArg ?? '';\n if (!branch && opts.allowDetect) {\n branch = detectBranch(cfg) ?? '';\n }\n\n if (!branch && !opts.requireMain) {\n console.error(\n chalk.red(\n \"Couldn't detect branch. Run from inside a linked worktree or pass the branch name.\",\n ),\n );\n process.exit(1);\n }\n\n return { branch, cfg, mainRoot, wtRoot };\n}\n\nvoid main();\n","import { spawn } from 'node:child_process';\nimport { createWriteStream, existsSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { devArgs, type ServiceConfig, type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { getBranchEntry, portFor } from '../registry.js';\n\nexport interface DevOptions {\n branch: string;\n cfg: WorktreeConfig;\n /** Run detached from the terminal; write stdout/stderr to log files. */\n detach?: boolean;\n /** If a port is already in use, kill the process instead of aborting. */\n force?: boolean;\n repoRoot: string;\n}\n\nexport async function dev({\n branch,\n cfg,\n detach = false,\n force = false,\n repoRoot,\n}: DevOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n if (!entry) {\n console.error(chalk.red(`No ports allocated for '${branch}'. Run setup first.`));\n process.exit(1);\n }\n\n const wtPath = worktreePath(cfg, repoRoot, branch);\n if (!existsSync(wtPath)) {\n console.error(chalk.red(`Worktree not found at ${wtPath}`));\n process.exit(1);\n }\n\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n if (force) {\n console.log(chalk.yellow(`Port ${port} in use — killing (--force)`));\n await killPort(port);\n } else {\n console.error(\n chalk.red(`Port ${port} (${svc.name}) already in use. Pass --force to kill.`),\n );\n process.exit(1);\n }\n }\n }\n\n console.log(chalk.bold(`Starting dev servers for '${branch}'...`));\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n console.log(` ${svc.name}: http://localhost:${port} (logs: ${logFile(svc, branch)})`);\n }\n console.log('');\n\n const procs = cfg.services.map((svc) => spawnService(svc, entry, wtPath, branch, detach));\n\n if (detach) {\n for (const p of procs) p.unref();\n console.log(chalk.green('Started detached. Use `precisa-worktree stop` to kill.'));\n return;\n }\n\n // Foreground: forward signals, wait for first exit.\n const cleanup = (signal: NodeJS.Signals): void => {\n for (const p of procs) {\n try {\n if (!p.killed) p.kill(signal);\n } catch {\n // already dead\n }\n }\n };\n process.on('SIGINT', () => cleanup('SIGINT'));\n process.on('SIGTERM', () => cleanup('SIGTERM'));\n\n const exitCode = await new Promise<number>((resolvePromise) => {\n let resolved = false;\n for (const p of procs) {\n p.on('exit', (code) => {\n if (resolved) return;\n resolved = true;\n cleanup('SIGTERM');\n resolvePromise(code ?? 1);\n });\n }\n });\n process.exit(exitCode);\n}\n\nfunction spawnService(\n svc: ServiceConfig,\n entry: { ports: Record<string, number> },\n cwd: string,\n branch: string,\n detach: boolean,\n): ReturnType<typeof spawn> {\n const port = portFor(entry, svc);\n const interpolate = (s: string): string => {\n let out = s.replace('{port}', String(port));\n // Allow cross-service refs like `{api_port}` so one service's env\n // can embed another service's allocated port.\n for (const [otherName, otherPort] of Object.entries(entry.ports)) {\n out = out.replaceAll(`{${otherName}_port}`, String(otherPort));\n }\n return out;\n };\n\n const rawArgs = devArgs(svc);\n const args = ['--filter', svc.pnpmFilter, 'dev', '--', ...rawArgs.map(interpolate)];\n\n const env = { ...process.env };\n for (const [k, v] of Object.entries(svc.env ?? {})) {\n env[k] = interpolate(v);\n }\n\n if (detach) {\n const logPath = logFile(svc, branch);\n const out = createWriteStream(logPath, { flags: 'a' });\n const proc = spawn('pnpm', args, {\n cwd,\n detached: true,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n proc.stdout?.pipe(out);\n proc.stderr?.pipe(out);\n return proc;\n }\n\n return spawn('pnpm', args, { cwd, env, stdio: 'inherit' });\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\n\nexport interface ServiceConfig {\n /**\n * Extra args passed to the dev script. `{port}` is replaced with the\n * allocated port. Defaults to `['--port', '{port}']` (works with vite).\n */\n devArgs?: string[];\n /**\n * Optional: additional env vars to set for the dev process. The literal\n * `{port}` is substituted. Example: `{ VITE_API_URL: 'http://localhost:{port}/api' }`.\n */\n env?: Record<string, string>;\n /**\n * First port for feature worktrees. Slot 1 uses this port; slot 2 uses\n * `featureBase + increment`, slot 3 uses `featureBase + 2*increment`, etc.\n */\n featureBase: number;\n /** Increment between slots. Defaults to 10. */\n increment?: number;\n /**\n * Prefix for the log file path: `/tmp/<logPrefix>-<branch>.log`. Required\n * so that sibling services in a repo don't overwrite each other's logs.\n */\n logPrefix: string;\n /** Port used by the default (main) worktree. */\n mainPort: number;\n /** Service name used in CLI output, column headers, and log file naming. */\n name: string;\n /** pnpm filter pattern for `worktree dev`. Example: `@medbench-brasil/site`. */\n pnpmFilter: string;\n}\n\nexport interface WorktreeConfig {\n /**\n * Optional extra build command run during `setup`, after `pnpm install`.\n * Example: `pnpm turbo run build --filter=./packages/*`.\n */\n buildCommand?: string;\n /**\n * Prefix used for worktree directory names: `<prefix>-<branch>`.\n * Example: `medbench-brasil` → worktrees land at\n * `../medbench-brasil-feat-foo`.\n */\n directoryPrefix: string;\n /**\n * Whether to run `pnpm install` during setup. Defaults to true. Set to\n * false for repos where install should be manual or where the script\n * is invoked inside a container.\n */\n install?: boolean;\n /** Absolute path to the lock directory. Defaults to `<portRegistry>.lock.d`. */\n portLockDir?: string;\n /** Absolute path to the port registry JSON file. */\n portRegistry: string;\n /** Services managed by this repo. At least one required. */\n services: ServiceConfig[];\n /**\n * Extra per-service file writes performed during `setup`, after\n * install + build. Intended for repos that need `.env.local`-style\n * files seeded with the allocated ports so that running `dev` without\n * explicit env vars picks up the right values.\n *\n * Each entry is `{ path, contents }` where `contents` supports the\n * same `{port}` and `{<service>_port}` substitutions available in\n * `service.env` / `service.devArgs`.\n *\n * Example (platform):\n * writeFiles: [\n * { path: 'apps/web/.env.local',\n * contents: 'VITE_DEV_PORT={web_port}\\nVITE_API_URL=http://localhost:{api_port}/api\\n' },\n * { path: 'apps/api/.env.local',\n * contents: 'PORT={api_port}\\n' },\n * ]\n */\n writeFiles?: Array<{ path: string; contents: string }>;\n}\n\ninterface PackageJson {\n name?: string;\n worktree?: WorktreeConfig;\n}\n\nexport async function loadConfig(repoRoot: string): Promise<WorktreeConfig> {\n const pkgPath = resolve(repoRoot, 'package.json');\n let pkg: PackageJson;\n try {\n pkg = JSON.parse(await readFile(pkgPath, 'utf-8')) as PackageJson;\n } catch (err) {\n throw new Error(`Failed to read ${pkgPath}: ${(err as Error).message}. Is this the repo root?`);\n }\n\n const cfg = pkg.worktree;\n if (!cfg) {\n throw new Error(\n `No \"worktree\" field in ${pkgPath}. Add a worktree config — see ` +\n `https://github.com/Precisa-Saude/tooling/tree/main/packages/worktree-cli#configuration`,\n );\n }\n\n if (!cfg.directoryPrefix) {\n throw new Error('worktree.directoryPrefix is required');\n }\n if (!cfg.portRegistry) {\n throw new Error('worktree.portRegistry is required');\n }\n if (!cfg.services?.length) {\n throw new Error('worktree.services must contain at least one entry');\n }\n for (const svc of cfg.services) {\n if (!svc.name) throw new Error('service.name is required');\n if (!svc.pnpmFilter) throw new Error(`service.${svc.name}.pnpmFilter is required`);\n if (!svc.logPrefix) throw new Error(`service.${svc.name}.logPrefix is required`);\n if (typeof svc.mainPort !== 'number') {\n throw new Error(`service.${svc.name}.mainPort must be a number`);\n }\n if (typeof svc.featureBase !== 'number') {\n throw new Error(`service.${svc.name}.featureBase must be a number`);\n }\n }\n\n return cfg;\n}\n\nexport function lockDir(cfg: WorktreeConfig): string {\n return cfg.portLockDir ?? `${cfg.portRegistry}.lock.d`;\n}\n\nexport function increment(svc: ServiceConfig): number {\n return svc.increment ?? 10;\n}\n\nexport function devArgs(svc: ServiceConfig): string[] {\n return svc.devArgs ?? ['--port', '{port}'];\n}\n","import { execSync } from 'node:child_process';\nimport { basename, dirname, resolve } from 'node:path';\n\nimport type { ServiceConfig, WorktreeConfig } from './config.js';\n\n/** Convert a branch name to a safe directory-suffix: `feat/foo` → `feat-foo`. */\nexport function branchToSuffix(branch: string): string {\n return branch.replace(/\\//g, '-');\n}\n\nexport function worktreeDirectoryName(cfg: WorktreeConfig, branch: string): string {\n return `${cfg.directoryPrefix}-${branchToSuffix(branch)}`;\n}\n\nexport function worktreePath(cfg: WorktreeConfig, repoRoot: string, branch: string): string {\n const parentDir = dirname(repoRoot);\n return resolve(parentDir, worktreeDirectoryName(cfg, branch));\n}\n\nexport function logFile(svc: ServiceConfig, branch: string): string {\n return `/tmp/${svc.logPrefix}-${branchToSuffix(branch)}.log`;\n}\n\n/**\n * Detect the current branch when invoked from inside a linked worktree.\n * Returns null from the main worktree — refusing auto-detect there avoids\n * accidentally acting on `main` when the user forgot to pass a branch.\n */\nexport function detectBranch(cfg: WorktreeConfig): string | null {\n const cwdBase = basename(process.cwd());\n if (!cwdBase.startsWith(`${cfg.directoryPrefix}-`)) return null;\n try {\n const out = execSync('git branch --show-current', { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n return out || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the repo root by walking up from cwd looking for a `package.json`\n * with a `worktree` field. If invoked from inside a linked worktree, falls\n * back to the main worktree (identified by the directory NOT having the\n * `<prefix>-<branch>` suffix).\n */\nexport function findRepoRoot(): string {\n // `git rev-parse --show-toplevel` gives the worktree root (linked or main).\n try {\n return execSync('git rev-parse --show-toplevel', { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n } catch {\n return process.cwd();\n }\n}\n\n/**\n * From a linked worktree, walk back to the main worktree using\n * `git worktree list --porcelain`. The first entry is always the main.\n */\nexport function mainWorktreeRoot(): string {\n try {\n const out = execSync('git worktree list --porcelain', {\n stdio: ['ignore', 'pipe', 'ignore'],\n }).toString();\n const firstLine = out.split('\\n')[0] ?? '';\n const match = firstLine.match(/^worktree (.+)$/);\n if (match) return match[1]!;\n } catch {\n // fall through\n }\n return findRepoRoot();\n}\n","import { execSync } from 'node:child_process';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\n/**\n * Return PIDs listening on `port` using the first available tool.\n * Prefers lsof (macOS default), falls back to ss then fuser (Linux).\n * Returns empty array if none can inspect ports or nothing is listening.\n */\nfunction listenersOnPort(port: number): number[] {\n for (const [cmd, parse] of probers) {\n if (!hasCommand(cmd)) continue;\n try {\n const out = execSync(probeCommand(cmd, port), { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n return parse(out);\n } catch {\n // non-zero exit — no listeners found\n return [];\n }\n }\n console.error(`Warning: lsof/ss/fuser not available — can't inspect port ${port}`);\n return [];\n}\n\ntype Prober = [cmd: string, parse: (output: string) => number[]];\n\nconst probers: Prober[] = [\n [\n 'lsof',\n (out) =>\n out\n .split('\\n')\n .map((s) => parseInt(s.trim(), 10))\n .filter((n) => !isNaN(n)),\n ],\n [\n 'ss',\n (out) => {\n const pids: number[] = [];\n for (const line of out.split('\\n')) {\n const matches = line.match(/pid=(\\d+)/g) ?? [];\n for (const m of matches) pids.push(parseInt(m.slice(4), 10));\n }\n return pids;\n },\n ],\n [\n 'fuser',\n (out) =>\n out\n .split(/\\s+/)\n .map((s) => parseInt(s, 10))\n .filter((n) => !isNaN(n)),\n ],\n];\n\nfunction probeCommand(cmd: string, port: number): string {\n switch (cmd) {\n case 'lsof':\n return `lsof -iTCP:${port} -sTCP:LISTEN -t`;\n case 'ss':\n return `ss -tlnp | awk '$4 ~ /:${port}$/ {print}'`;\n case 'fuser':\n return `fuser -n tcp ${port} 2>/dev/null`;\n default:\n throw new Error(`Unsupported prober: ${cmd}`);\n }\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execSync(`command -v ${cmd}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isPortInUse(port: number): boolean {\n return listenersOnPort(port).length > 0;\n}\n\n/** Kill processes listening on `port`. SIGTERM first, then SIGKILL if any survive. */\nexport async function killPort(port: number): Promise<void> {\n const pids = listenersOnPort(port);\n if (pids.length === 0) return;\n\n for (const pid of pids) {\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n // process may have exited between listing and kill — ignore\n }\n }\n\n await sleep(1000);\n\n const stillAlive = listenersOnPort(port);\n for (const pid of stillAlive) {\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n // ignore\n }\n }\n}\n","import { existsSync, mkdirSync, rmdirSync } from 'node:fs';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\nimport { increment, lockDir, type ServiceConfig, type WorktreeConfig } from './config.js';\n\nexport type Registry = Record<string, { slot: number; ports: Record<string, number> }>;\n\nasync function ensureRegistry(cfg: WorktreeConfig): Promise<void> {\n if (!existsSync(cfg.portRegistry)) {\n await writeFile(cfg.portRegistry, '{}');\n }\n}\n\n/**\n * Acquire an exclusive lock via `mkdir` — POSIX-atomic, portable across\n * macOS/Linux, no dependency on `flock` (which isn't on macOS by default).\n * Used to serialize registry read-modify-write across concurrent sessions.\n */\nasync function acquireLock(cfg: WorktreeConfig): Promise<void> {\n const dir = lockDir(cfg);\n const maxTries = 100;\n for (let i = 0; i < maxTries; i++) {\n try {\n mkdirSync(dir);\n return;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n }\n await sleep(100);\n }\n throw new Error(\n `Timeout (~10s) waiting for lock at ${dir}. If no other session is ` +\n `running, remove it manually: rmdir ${dir}`,\n );\n}\n\nfunction releaseLock(cfg: WorktreeConfig): void {\n try {\n rmdirSync(lockDir(cfg));\n } catch {\n // ignore — already released or never held\n }\n}\n\n/**\n * Run `fn` while holding the registry lock. Always releases, even on throw.\n * The release is also safe against signal interruption because the lock\n * directory will be removed at process exit via the handler in bin.ts.\n */\nexport async function withLock<T>(cfg: WorktreeConfig, fn: () => Promise<T> | T): Promise<T> {\n await ensureRegistry(cfg);\n await acquireLock(cfg);\n try {\n return await fn();\n } finally {\n releaseLock(cfg);\n }\n}\n\nexport async function readRegistry(cfg: WorktreeConfig): Promise<Registry> {\n await ensureRegistry(cfg);\n const text = await readFile(cfg.portRegistry, 'utf-8');\n try {\n return JSON.parse(text) as Registry;\n } catch {\n return {};\n }\n}\n\nasync function writeRegistry(cfg: WorktreeConfig, reg: Registry): Promise<void> {\n await writeFile(cfg.portRegistry, `${JSON.stringify(reg, null, 2)}\\n`);\n}\n\n/**\n * Allocate a slot+ports for `branch`. Idempotent: returns the existing\n * entry if the branch already has one. Reuses freed slots so slot numbers\n * don't grow unbounded over many create/teardown cycles.\n */\nexport async function allocate(\n cfg: WorktreeConfig,\n branch: string,\n): Promise<{ slot: number; ports: Record<string, number> }> {\n return withLock(cfg, async () => {\n const reg = await readRegistry(cfg);\n if (reg[branch]) return reg[branch];\n\n const usedSlots = new Set(Object.values(reg).map((e) => e.slot));\n let slot = 1;\n while (usedSlots.has(slot)) slot++;\n\n const ports: Record<string, number> = {};\n for (const svc of cfg.services) {\n ports[svc.name] = svc.featureBase + (slot - 1) * increment(svc);\n }\n\n reg[branch] = { ports, slot };\n await writeRegistry(cfg, reg);\n return reg[branch];\n });\n}\n\nexport async function free(cfg: WorktreeConfig, branch: string): Promise<void> {\n return withLock(cfg, async () => {\n const reg = await readRegistry(cfg);\n if (reg[branch]) {\n delete reg[branch];\n await writeRegistry(cfg, reg);\n }\n });\n}\n\nexport async function getBranchEntry(\n cfg: WorktreeConfig,\n branch: string,\n): Promise<{ slot: number; ports: Record<string, number> } | null> {\n const reg = await readRegistry(cfg);\n return reg[branch] ?? null;\n}\n\nexport function portFor(entry: { ports: Record<string, number> }, svc: ServiceConfig): number {\n const port = entry.ports[svc.name];\n if (typeof port !== 'number') {\n throw new Error(\n `No port allocated for service \"${svc.name}\" on this branch. ` +\n `Registry entry may be from an older config version — run teardown + setup again.`,\n );\n }\n return port;\n}\n","import { existsSync } from 'node:fs';\n\nimport { type ServiceConfig, type WorktreeConfig } from '../config.js';\nimport { worktreePath } from '../paths.js';\nimport { isPortInUse } from '../ports.js';\nimport { readRegistry } from '../registry.js';\n\nexport interface ListOptions {\n cfg: WorktreeConfig;\n repoRoot: string;\n}\n\nexport async function list({ cfg, repoRoot }: ListOptions): Promise<void> {\n const reg = await readRegistry(cfg);\n\n console.log(`Worktrees for ${cfg.directoryPrefix}:`);\n console.log('');\n\n const headers = ['BRANCH', ...cfg.services.map((s) => s.name.toUpperCase()), 'STATUS'];\n const widths = [40, ...cfg.services.map(() => 10), 10];\n printRow(headers, widths);\n printRow(\n headers.map((h) => '-'.repeat(Math.min(h.length, 6))),\n widths,\n );\n\n // Main worktree row\n printRow(\n [\n 'main (default)',\n ...cfg.services.map((s) => String(s.mainPort)),\n statusOf(cfg.services, (s) => s.mainPort, /* dirExists */ true),\n ],\n widths,\n );\n\n // Feature worktree rows\n for (const [branch, entry] of Object.entries(reg)) {\n const wtPath = worktreePath(cfg, repoRoot, branch);\n const dirExists = existsSync(wtPath);\n const ports = cfg.services.map((s) => entry.ports[s.name]!);\n printRow(\n [\n branch,\n ...ports.map((p) => String(p)),\n dirExists ? statusOf(cfg.services, (s) => entry.ports[s.name]!, true) : 'missing',\n ],\n widths,\n );\n }\n\n console.log('');\n console.log(`Registry: ${cfg.portRegistry}`);\n}\n\nfunction statusOf(\n services: ServiceConfig[],\n portOf: (s: ServiceConfig) => number,\n dirExists: boolean,\n): string {\n if (!dirExists) return 'missing';\n const anyRunning = services.some((s) => isPortInUse(portOf(s)));\n return anyRunning ? 'running' : 'stopped';\n}\n\nfunction printRow(cells: string[], widths: number[]): void {\n const line = cells.map((c, i) => c.padEnd(widths[i] ?? 10)).join(' ');\n console.log(` ${line}`);\n}\n","import { spawnSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile } from '../paths.js';\n\nexport interface LogsOptions {\n branch: string;\n cfg: WorktreeConfig;\n service?: string;\n}\n\nexport async function logs({ branch, cfg, service }: LogsOptions): Promise<void> {\n const svc = service ? cfg.services.find((s) => s.name === service) : cfg.services[0];\n\n if (!svc) {\n const names = cfg.services.map((s) => s.name).join(', ');\n console.error(chalk.red(`Unknown service \"${service}\". Valid services: ${names}`));\n process.exit(1);\n }\n\n const path = logFile(svc, branch);\n if (!existsSync(path)) {\n console.error(chalk.red(`Log file not found: ${path}`));\n console.error(`Start the dev server first: precisa-worktree dev ${branch}`);\n process.exit(1);\n }\n\n // Delegate to tail -f so Ctrl-C works and rotation is handled.\n const result = spawnSync('tail', ['-f', path], { stdio: 'inherit' });\n process.exit(result.status ?? 0);\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { allocate } from '../registry.js';\n\nexport interface SetupOptions {\n branch: string;\n cfg: WorktreeConfig;\n repoRoot: string;\n}\n\nexport async function setup({ branch, cfg, repoRoot }: SetupOptions): Promise<void> {\n const wtPath = worktreePath(cfg, repoRoot, branch);\n\n if (existsSync(wtPath)) {\n console.error(chalk.red(`Worktree already exists: ${wtPath}`));\n console.error(`To start dev servers: precisa-worktree dev ${branch}`);\n process.exit(1);\n }\n\n console.log(chalk.bold(`==> Creating worktree for '${branch}' at ${wtPath}...`));\n\n // Fetch origin/main from the main worktree; the new worktree branches from it.\n execFileSync('git', ['-C', repoRoot, 'fetch', 'origin', 'main'], { stdio: 'inherit' });\n execFileSync('git', ['-C', repoRoot, 'worktree', 'add', '-b', branch, wtPath, 'origin/main'], {\n stdio: 'inherit',\n });\n\n const entry = await allocate(cfg, branch);\n\n if (cfg.install !== false) {\n console.log(chalk.bold('==> Installing dependencies (pnpm install)...'));\n execFileSync('pnpm', ['install'], { cwd: wtPath, stdio: 'inherit' });\n }\n\n if (cfg.buildCommand) {\n console.log(chalk.bold(`==> Running build: ${cfg.buildCommand}`));\n execFileSync('sh', ['-c', cfg.buildCommand], { cwd: wtPath, stdio: 'inherit' });\n }\n\n // Write per-repo files with the allocated ports substituted in. Used\n // by platform to seed apps/*/.env.local so the running dev server\n // picks up the right ports without extra env-var plumbing.\n if (cfg.writeFiles?.length) {\n console.log(chalk.bold('==> Writing worktree-scoped files'));\n for (const { contents, path } of cfg.writeFiles) {\n let interpolated = contents;\n for (const [svcName, port] of Object.entries(entry.ports)) {\n interpolated = interpolated\n .replaceAll(`{${svcName}_port}`, String(port))\n .replaceAll('{port}', String(port));\n }\n const fullPath = resolve(wtPath, path);\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, interpolated);\n console.log(` wrote ${path}`);\n }\n }\n\n console.log('');\n console.log(chalk.green(`Worktree ready: ${wtPath}`));\n console.log(` Branch: ${branch}`);\n for (const svc of cfg.services) {\n const port = entry.ports[svc.name]!;\n console.log(\n ` ${svc.name.padEnd(8)}: http://localhost:${port} (logs: ${logFile(svc, branch)})`,\n );\n }\n console.log('');\n console.log('To start the dev server(s):');\n console.log(` cd ${wtPath} && precisa-worktree dev ${branch}`);\n}\n","import chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { getBranchEntry, portFor } from '../registry.js';\n\nexport interface StopOptions {\n branch: string;\n cfg: WorktreeConfig;\n}\n\nexport async function stop({ branch, cfg }: StopOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n if (!entry) {\n console.error(`No ports registered for '${branch}'.`);\n process.exit(1);\n }\n\n let anyRunning = false;\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n console.log(chalk.bold(`Killing ${svc.name} dev server on port ${port}...`));\n await killPort(port);\n anyRunning = true;\n }\n }\n\n if (!anyRunning) {\n console.log(`No dev servers running for '${branch}'.`);\n }\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, rmSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { free, getBranchEntry, portFor } from '../registry.js';\n\nexport interface TeardownOptions {\n branch: string;\n cfg: WorktreeConfig;\n keepBranch?: boolean;\n repoRoot: string;\n}\n\nexport async function teardown({\n branch,\n cfg,\n keepBranch = false,\n repoRoot,\n}: TeardownOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n const wtPath = worktreePath(cfg, repoRoot, branch);\n\n if (entry) {\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n console.log(chalk.bold(`Stopping ${svc.name} dev server on port ${port}...`));\n await killPort(port);\n }\n }\n }\n\n if (existsSync(wtPath)) {\n console.log(chalk.bold(`Removing worktree: ${wtPath}`));\n execFileSync('git', ['-C', repoRoot, 'worktree', 'remove', wtPath, '--force'], {\n stdio: 'inherit',\n });\n }\n\n if (keepBranch) {\n console.log(`Preserving local branch: ${branch}`);\n } else {\n const branchExists = branchRefExists(repoRoot, branch);\n if (branchExists) {\n console.log(chalk.bold(`Deleting local branch: ${branch}`));\n try {\n execFileSync('git', ['-C', repoRoot, 'branch', '-d', branch], {\n stdio: 'ignore',\n });\n } catch {\n // Not fully merged — force-delete since worktree was already removed.\n execFileSync('git', ['-C', repoRoot, 'branch', '-D', branch], {\n stdio: 'inherit',\n });\n }\n }\n }\n\n await free(cfg, branch);\n\n for (const svc of cfg.services) {\n const path = logFile(svc, branch);\n if (existsSync(path)) rmSync(path);\n }\n\n console.log(chalk.green(`Teardown complete for '${branch}'.`));\n}\n\nfunction branchRefExists(repoRoot: string, branch: string): boolean {\n try {\n execFileSync(\n 'git',\n ['-C', repoRoot, 'show-ref', '--verify', '--quiet', `refs/heads/${branch}`],\n {\n stdio: 'ignore',\n },\n );\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["rmdirSync","chalk","existsSync","resolve","execSync","readFile","sleep","sleep","readFile","existsSync","existsSync","existsSync","existsSync","chalk","chalk","existsSync","existsSync","mkdirSync","dirname","resolve","chalk","existsSync","chalk","resolve","mkdirSync","dirname","chalk","chalk","execFileSync","existsSync","chalk","chalk","existsSync","execFileSync","chalk","rmdirSync"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/commands/dev.ts","../src/config.ts","../src/paths.ts","../src/ports.ts","../src/registry.ts","../src/commands/list.ts","../src/commands/logs.ts","../src/commands/setup.ts","../src/commands/stop.ts","../src/commands/teardown.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { rmdirSync } from 'node:fs';\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nimport { dev } from './commands/dev.js';\nimport { list } from './commands/list.js';\nimport { logs } from './commands/logs.js';\nimport { setup } from './commands/setup.js';\nimport { stop } from './commands/stop.js';\nimport { teardown } from './commands/teardown.js';\nimport { loadConfig, lockDir, type WorktreeConfig } from './config.js';\nimport { detectBranch, findRepoRoot, mainWorktreeRoot } from './paths.js';\n\nasync function main(): Promise<void> {\n const program = new Command();\n program\n .name('precisa-worktree')\n .description('Git-worktree lifecycle CLI for Precisa Saúde repositories')\n .version('1.0.4');\n\n program\n .command('setup <branch>')\n .description('Create a worktree, install deps, allocate ports')\n .action(async (branch: string) => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await setup({ branch, cfg, repoRoot: mainRoot });\n });\n\n program\n .command('dev [branch]')\n .description('Start dev server(s) on the allocated ports')\n .option('-d, --detach', 'Run detached (nohup-style); write to log files', false)\n .option('-f, --force', 'Kill any process already on the port', false)\n .action(async (branchArg: string | undefined, opts: { detach: boolean; force: boolean }) => {\n const { branch, cfg, wtRoot } = await resolveContext({ allowDetect: true, branchArg });\n await dev({ branch, cfg, detach: opts.detach, force: opts.force, repoRoot: wtRoot });\n });\n\n program\n .command('stop [branch]')\n .description('Kill dev server(s) for a worktree')\n .action(async (branchArg?: string) => {\n const { branch, cfg } = await resolveContext({ allowDetect: true, branchArg });\n await stop({ branch, cfg });\n });\n\n program\n .command('teardown <branch>')\n .description('Stop dev servers, remove worktree, delete branch, free ports')\n .option('--keep-branch', 'Preserve the local branch', false)\n .action(async (branch: string, opts: { keepBranch: boolean }) => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await teardown({ branch, cfg, keepBranch: opts.keepBranch, repoRoot: mainRoot });\n });\n\n program\n .command('list')\n .description('List all worktrees with ports and status')\n .action(async () => {\n const { cfg, mainRoot } = await resolveContext({ requireMain: true });\n await list({ cfg, repoRoot: mainRoot });\n });\n\n program\n .command('logs [branch]')\n .description('Tail the log for a worktree dev server')\n .option('-s, --service <name>', 'Service name (defaults to the first configured)')\n .action(async (branchArg: string | undefined, opts: { service?: string }) => {\n const { branch, cfg } = await resolveContext({ allowDetect: true, branchArg });\n await logs({ branch, cfg, service: opts.service });\n });\n\n // Global EXIT handler — release the lock if we died mid-operation.\n // Safe because `rmdir` only succeeds on an empty directory we created.\n process.on('exit', () => {\n try {\n // Best-effort; we don't know the config if we failed before loading it.\n // This handler is installed after config load via resolveContext.\n } catch {\n // ignore\n }\n });\n\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n console.error(chalk.red((err as Error).message));\n process.exit(1);\n }\n}\n\ninterface ResolveOpts {\n /** Allow `detectBranch()` when inside a linked worktree. */\n allowDetect?: boolean;\n branchArg?: string | undefined;\n /** Require the repo root to be the main worktree (setup/teardown/list). */\n requireMain?: boolean;\n}\n\nasync function resolveContext(opts: ResolveOpts): Promise<{\n cfg: WorktreeConfig;\n wtRoot: string;\n mainRoot: string;\n branch: string;\n}> {\n const wtRoot = findRepoRoot();\n const mainRoot = mainWorktreeRoot();\n const cfg = await loadConfig(mainRoot);\n\n // Install an exit handler now that we know the lock path.\n const lockPath = lockDir(cfg);\n process.on('exit', () => {\n try {\n rmdirSync(lockPath);\n } catch {\n // already released or never held\n }\n });\n\n let branch = opts.branchArg ?? '';\n if (!branch && opts.allowDetect) {\n branch = detectBranch(cfg) ?? '';\n }\n\n if (!branch && !opts.requireMain) {\n console.error(\n chalk.red(\n \"Couldn't detect branch. Run from inside a linked worktree or pass the branch name.\",\n ),\n );\n process.exit(1);\n }\n\n return { branch, cfg, mainRoot, wtRoot };\n}\n\nvoid main();\n","import { spawn } from 'node:child_process';\nimport { createWriteStream, existsSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { devArgs, type ServiceConfig, type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { getBranchEntry, portFor } from '../registry.js';\n\nexport interface DevOptions {\n branch: string;\n cfg: WorktreeConfig;\n /** Run detached from the terminal; write stdout/stderr to log files. */\n detach?: boolean;\n /** If a port is already in use, kill the process instead of aborting. */\n force?: boolean;\n repoRoot: string;\n}\n\nexport async function dev({\n branch,\n cfg,\n detach = false,\n force = false,\n repoRoot,\n}: DevOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n if (!entry) {\n console.error(chalk.red(`No ports allocated for '${branch}'. Run setup first.`));\n process.exit(1);\n }\n\n const wtPath = worktreePath(cfg, repoRoot, branch);\n if (!existsSync(wtPath)) {\n console.error(chalk.red(`Worktree not found at ${wtPath}`));\n process.exit(1);\n }\n\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n if (force) {\n console.log(chalk.yellow(`Port ${port} in use — killing (--force)`));\n await killPort(port);\n } else {\n console.error(\n chalk.red(`Port ${port} (${svc.name}) already in use. Pass --force to kill.`),\n );\n process.exit(1);\n }\n }\n }\n\n console.log(chalk.bold(`Starting dev servers for '${branch}'...`));\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n console.log(` ${svc.name}: http://localhost:${port} (logs: ${logFile(svc, branch)})`);\n }\n console.log('');\n\n const procs = cfg.services.map((svc) => spawnService(svc, entry, wtPath, branch, detach));\n\n if (detach) {\n for (const p of procs) p.unref();\n console.log(chalk.green('Started detached. Use `precisa-worktree stop` to kill.'));\n return;\n }\n\n // Foreground: forward signals, wait for first exit.\n const cleanup = (signal: NodeJS.Signals): void => {\n for (const p of procs) {\n try {\n if (!p.killed) p.kill(signal);\n } catch {\n // already dead\n }\n }\n };\n process.on('SIGINT', () => cleanup('SIGINT'));\n process.on('SIGTERM', () => cleanup('SIGTERM'));\n\n const exitCode = await new Promise<number>((resolvePromise) => {\n let resolved = false;\n for (const p of procs) {\n p.on('exit', (code) => {\n if (resolved) return;\n resolved = true;\n cleanup('SIGTERM');\n resolvePromise(code ?? 1);\n });\n }\n });\n process.exit(exitCode);\n}\n\nfunction spawnService(\n svc: ServiceConfig,\n entry: { ports: Record<string, number> },\n cwd: string,\n branch: string,\n detach: boolean,\n): ReturnType<typeof spawn> {\n const port = portFor(entry, svc);\n const interpolate = (s: string): string => {\n let out = s.replace('{port}', String(port));\n // Allow cross-service refs like `{api_port}` so one service's env\n // can embed another service's allocated port.\n for (const [otherName, otherPort] of Object.entries(entry.ports)) {\n out = out.replaceAll(`{${otherName}_port}`, String(otherPort));\n }\n return out;\n };\n\n const rawArgs = devArgs(svc);\n // No `--` separator: with pnpm 9 + `\"dev\": \"vite\"`, inserting `--`\n // causes vite to receive it as a literal argv entry (`vite -- --port NNN`)\n // and silently ignore the port flag, falling back to its default.\n const args = ['--filter', svc.pnpmFilter, 'dev', ...rawArgs.map(interpolate)];\n\n const env = { ...process.env };\n for (const [k, v] of Object.entries(svc.env ?? {})) {\n env[k] = interpolate(v);\n }\n\n if (detach) {\n const logPath = logFile(svc, branch);\n const out = createWriteStream(logPath, { flags: 'a' });\n const proc = spawn('pnpm', args, {\n cwd,\n detached: true,\n env,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n proc.stdout?.pipe(out);\n proc.stderr?.pipe(out);\n return proc;\n }\n\n return spawn('pnpm', args, { cwd, env, stdio: 'inherit' });\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\n\nexport interface ServiceConfig {\n /**\n * Extra args passed to the dev script. `{port}` is replaced with the\n * allocated port. Defaults to `['--port', '{port}']` (works with vite).\n */\n devArgs?: string[];\n /**\n * Optional: additional env vars to set for the dev process. The literal\n * `{port}` is substituted. Example: `{ VITE_API_URL: 'http://localhost:{port}/api' }`.\n */\n env?: Record<string, string>;\n /**\n * First port for feature worktrees. Slot 1 uses this port; slot 2 uses\n * `featureBase + increment`, slot 3 uses `featureBase + 2*increment`, etc.\n */\n featureBase: number;\n /** Increment between slots. Defaults to 10. */\n increment?: number;\n /**\n * Prefix for the log file path: `/tmp/<logPrefix>-<branch>.log`. Required\n * so that sibling services in a repo don't overwrite each other's logs.\n */\n logPrefix: string;\n /** Port used by the default (main) worktree. */\n mainPort: number;\n /** Service name used in CLI output, column headers, and log file naming. */\n name: string;\n /** pnpm filter pattern for `worktree dev`. Example: `@medbench-brasil/site`. */\n pnpmFilter: string;\n}\n\nexport interface WorktreeConfig {\n /**\n * Optional extra build command run during `setup`, after `pnpm install`.\n * Example: `pnpm turbo run build --filter=./packages/*`.\n */\n buildCommand?: string;\n /**\n * Prefix used for worktree directory names: `<prefix>-<branch>`.\n * Example: `medbench-brasil` → worktrees land at\n * `../medbench-brasil-feat-foo`.\n */\n directoryPrefix: string;\n /**\n * Whether to run `pnpm install` during setup. Defaults to true. Set to\n * false for repos where install should be manual or where the script\n * is invoked inside a container.\n */\n install?: boolean;\n /** Absolute path to the lock directory. Defaults to `<portRegistry>.lock.d`. */\n portLockDir?: string;\n /** Absolute path to the port registry JSON file. */\n portRegistry: string;\n /** Services managed by this repo. At least one required. */\n services: ServiceConfig[];\n /**\n * Extra per-service file writes performed during `setup`, after\n * install + build. Intended for repos that need `.env.local`-style\n * files seeded with the allocated ports so that running `dev` without\n * explicit env vars picks up the right values.\n *\n * Each entry is `{ path, contents }` where `contents` supports the\n * same `{port}` and `{<service>_port}` substitutions available in\n * `service.env` / `service.devArgs`.\n *\n * Example (platform):\n * writeFiles: [\n * { path: 'apps/web/.env.local',\n * contents: 'VITE_DEV_PORT={web_port}\\nVITE_API_URL=http://localhost:{api_port}/api\\n' },\n * { path: 'apps/api/.env.local',\n * contents: 'PORT={api_port}\\n' },\n * ]\n */\n writeFiles?: Array<{ path: string; contents: string }>;\n}\n\ninterface PackageJson {\n name?: string;\n worktree?: WorktreeConfig;\n}\n\nexport async function loadConfig(repoRoot: string): Promise<WorktreeConfig> {\n const pkgPath = resolve(repoRoot, 'package.json');\n let pkg: PackageJson;\n try {\n pkg = JSON.parse(await readFile(pkgPath, 'utf-8')) as PackageJson;\n } catch (err) {\n throw new Error(`Failed to read ${pkgPath}: ${(err as Error).message}. Is this the repo root?`);\n }\n\n const cfg = pkg.worktree;\n if (!cfg) {\n throw new Error(\n `No \"worktree\" field in ${pkgPath}. Add a worktree config — see ` +\n `https://github.com/Precisa-Saude/tooling/tree/main/packages/worktree-cli#configuration`,\n );\n }\n\n if (!cfg.directoryPrefix) {\n throw new Error('worktree.directoryPrefix is required');\n }\n if (!cfg.portRegistry) {\n throw new Error('worktree.portRegistry is required');\n }\n if (!cfg.services?.length) {\n throw new Error('worktree.services must contain at least one entry');\n }\n for (const svc of cfg.services) {\n if (!svc.name) throw new Error('service.name is required');\n if (!svc.pnpmFilter) throw new Error(`service.${svc.name}.pnpmFilter is required`);\n if (!svc.logPrefix) throw new Error(`service.${svc.name}.logPrefix is required`);\n if (typeof svc.mainPort !== 'number') {\n throw new Error(`service.${svc.name}.mainPort must be a number`);\n }\n if (typeof svc.featureBase !== 'number') {\n throw new Error(`service.${svc.name}.featureBase must be a number`);\n }\n }\n\n return cfg;\n}\n\nexport function lockDir(cfg: WorktreeConfig): string {\n return cfg.portLockDir ?? `${cfg.portRegistry}.lock.d`;\n}\n\nexport function increment(svc: ServiceConfig): number {\n return svc.increment ?? 10;\n}\n\nexport function devArgs(svc: ServiceConfig): string[] {\n return svc.devArgs ?? ['--port', '{port}'];\n}\n","import { execSync } from 'node:child_process';\nimport { basename, dirname, resolve } from 'node:path';\n\nimport type { ServiceConfig, WorktreeConfig } from './config.js';\n\n/** Convert a branch name to a safe directory-suffix: `feat/foo` → `feat-foo`. */\nexport function branchToSuffix(branch: string): string {\n return branch.replace(/\\//g, '-');\n}\n\nexport function worktreeDirectoryName(cfg: WorktreeConfig, branch: string): string {\n return `${cfg.directoryPrefix}-${branchToSuffix(branch)}`;\n}\n\nexport function worktreePath(cfg: WorktreeConfig, repoRoot: string, branch: string): string {\n const parentDir = dirname(repoRoot);\n return resolve(parentDir, worktreeDirectoryName(cfg, branch));\n}\n\nexport function logFile(svc: ServiceConfig, branch: string): string {\n return `/tmp/${svc.logPrefix}-${branchToSuffix(branch)}.log`;\n}\n\n/**\n * Detect the current branch when invoked from inside a linked worktree.\n * Returns null from the main worktree — refusing auto-detect there avoids\n * accidentally acting on `main` when the user forgot to pass a branch.\n */\nexport function detectBranch(cfg: WorktreeConfig): string | null {\n const cwdBase = basename(process.cwd());\n if (!cwdBase.startsWith(`${cfg.directoryPrefix}-`)) return null;\n try {\n const out = execSync('git branch --show-current', { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n return out || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the repo root by walking up from cwd looking for a `package.json`\n * with a `worktree` field. If invoked from inside a linked worktree, falls\n * back to the main worktree (identified by the directory NOT having the\n * `<prefix>-<branch>` suffix).\n */\nexport function findRepoRoot(): string {\n // `git rev-parse --show-toplevel` gives the worktree root (linked or main).\n try {\n return execSync('git rev-parse --show-toplevel', { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n } catch {\n return process.cwd();\n }\n}\n\n/**\n * From a linked worktree, walk back to the main worktree using\n * `git worktree list --porcelain`. The first entry is always the main.\n */\nexport function mainWorktreeRoot(): string {\n try {\n const out = execSync('git worktree list --porcelain', {\n stdio: ['ignore', 'pipe', 'ignore'],\n }).toString();\n const firstLine = out.split('\\n')[0] ?? '';\n const match = firstLine.match(/^worktree (.+)$/);\n if (match) return match[1]!;\n } catch {\n // fall through\n }\n return findRepoRoot();\n}\n","import { execSync } from 'node:child_process';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\n/**\n * Return PIDs listening on `port` using the first available tool.\n * Prefers lsof (macOS default), falls back to ss then fuser (Linux).\n * Returns empty array if none can inspect ports or nothing is listening.\n */\nfunction listenersOnPort(port: number): number[] {\n for (const [cmd, parse] of probers) {\n if (!hasCommand(cmd)) continue;\n try {\n const out = execSync(probeCommand(cmd, port), { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim();\n return parse(out);\n } catch {\n // non-zero exit — no listeners found\n return [];\n }\n }\n console.error(`Warning: lsof/ss/fuser not available — can't inspect port ${port}`);\n return [];\n}\n\ntype Prober = [cmd: string, parse: (output: string) => number[]];\n\nconst probers: Prober[] = [\n [\n 'lsof',\n (out) =>\n out\n .split('\\n')\n .map((s) => parseInt(s.trim(), 10))\n .filter((n) => !isNaN(n)),\n ],\n [\n 'ss',\n (out) => {\n const pids: number[] = [];\n for (const line of out.split('\\n')) {\n const matches = line.match(/pid=(\\d+)/g) ?? [];\n for (const m of matches) pids.push(parseInt(m.slice(4), 10));\n }\n return pids;\n },\n ],\n [\n 'fuser',\n (out) =>\n out\n .split(/\\s+/)\n .map((s) => parseInt(s, 10))\n .filter((n) => !isNaN(n)),\n ],\n];\n\nfunction probeCommand(cmd: string, port: number): string {\n switch (cmd) {\n case 'lsof':\n return `lsof -iTCP:${port} -sTCP:LISTEN -t`;\n case 'ss':\n return `ss -tlnp | awk '$4 ~ /:${port}$/ {print}'`;\n case 'fuser':\n return `fuser -n tcp ${port} 2>/dev/null`;\n default:\n throw new Error(`Unsupported prober: ${cmd}`);\n }\n}\n\nfunction hasCommand(cmd: string): boolean {\n try {\n execSync(`command -v ${cmd}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isPortInUse(port: number): boolean {\n return listenersOnPort(port).length > 0;\n}\n\n/** Kill processes listening on `port`. SIGTERM first, then SIGKILL if any survive. */\nexport async function killPort(port: number): Promise<void> {\n const pids = listenersOnPort(port);\n if (pids.length === 0) return;\n\n for (const pid of pids) {\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n // process may have exited between listing and kill — ignore\n }\n }\n\n await sleep(1000);\n\n const stillAlive = listenersOnPort(port);\n for (const pid of stillAlive) {\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n // ignore\n }\n }\n}\n","import { existsSync, mkdirSync, rmdirSync } from 'node:fs';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { setTimeout as sleep } from 'node:timers/promises';\n\nimport { increment, lockDir, type ServiceConfig, type WorktreeConfig } from './config.js';\n\nexport type Registry = Record<string, { slot: number; ports: Record<string, number> }>;\n\nasync function ensureRegistry(cfg: WorktreeConfig): Promise<void> {\n if (!existsSync(cfg.portRegistry)) {\n await writeFile(cfg.portRegistry, '{}');\n }\n}\n\n/**\n * Acquire an exclusive lock via `mkdir` — POSIX-atomic, portable across\n * macOS/Linux, no dependency on `flock` (which isn't on macOS by default).\n * Used to serialize registry read-modify-write across concurrent sessions.\n */\nasync function acquireLock(cfg: WorktreeConfig): Promise<void> {\n const dir = lockDir(cfg);\n const maxTries = 100;\n for (let i = 0; i < maxTries; i++) {\n try {\n mkdirSync(dir);\n return;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n }\n await sleep(100);\n }\n throw new Error(\n `Timeout (~10s) waiting for lock at ${dir}. If no other session is ` +\n `running, remove it manually: rmdir ${dir}`,\n );\n}\n\nfunction releaseLock(cfg: WorktreeConfig): void {\n try {\n rmdirSync(lockDir(cfg));\n } catch {\n // ignore — already released or never held\n }\n}\n\n/**\n * Run `fn` while holding the registry lock. Always releases, even on throw.\n * The release is also safe against signal interruption because the lock\n * directory will be removed at process exit via the handler in bin.ts.\n */\nexport async function withLock<T>(cfg: WorktreeConfig, fn: () => Promise<T> | T): Promise<T> {\n await ensureRegistry(cfg);\n await acquireLock(cfg);\n try {\n return await fn();\n } finally {\n releaseLock(cfg);\n }\n}\n\nexport async function readRegistry(cfg: WorktreeConfig): Promise<Registry> {\n await ensureRegistry(cfg);\n const text = await readFile(cfg.portRegistry, 'utf-8');\n try {\n return JSON.parse(text) as Registry;\n } catch {\n return {};\n }\n}\n\nasync function writeRegistry(cfg: WorktreeConfig, reg: Registry): Promise<void> {\n await writeFile(cfg.portRegistry, `${JSON.stringify(reg, null, 2)}\\n`);\n}\n\n/**\n * Allocate a slot+ports for `branch`. Idempotent: returns the existing\n * entry if the branch already has one. Reuses freed slots so slot numbers\n * don't grow unbounded over many create/teardown cycles.\n */\nexport async function allocate(\n cfg: WorktreeConfig,\n branch: string,\n): Promise<{ slot: number; ports: Record<string, number> }> {\n return withLock(cfg, async () => {\n const reg = await readRegistry(cfg);\n if (reg[branch]) return reg[branch];\n\n const usedSlots = new Set(Object.values(reg).map((e) => e.slot));\n let slot = 1;\n while (usedSlots.has(slot)) slot++;\n\n const ports: Record<string, number> = {};\n for (const svc of cfg.services) {\n ports[svc.name] = svc.featureBase + (slot - 1) * increment(svc);\n }\n\n reg[branch] = { ports, slot };\n await writeRegistry(cfg, reg);\n return reg[branch];\n });\n}\n\nexport async function free(cfg: WorktreeConfig, branch: string): Promise<void> {\n return withLock(cfg, async () => {\n const reg = await readRegistry(cfg);\n if (reg[branch]) {\n delete reg[branch];\n await writeRegistry(cfg, reg);\n }\n });\n}\n\nexport async function getBranchEntry(\n cfg: WorktreeConfig,\n branch: string,\n): Promise<{ slot: number; ports: Record<string, number> } | null> {\n const reg = await readRegistry(cfg);\n return reg[branch] ?? null;\n}\n\nexport function portFor(entry: { ports: Record<string, number> }, svc: ServiceConfig): number {\n const port = entry.ports[svc.name];\n if (typeof port !== 'number') {\n throw new Error(\n `No port allocated for service \"${svc.name}\" on this branch. ` +\n `Registry entry may be from an older config version — run teardown + setup again.`,\n );\n }\n return port;\n}\n","import { existsSync } from 'node:fs';\n\nimport { type ServiceConfig, type WorktreeConfig } from '../config.js';\nimport { worktreePath } from '../paths.js';\nimport { isPortInUse } from '../ports.js';\nimport { readRegistry } from '../registry.js';\n\nexport interface ListOptions {\n cfg: WorktreeConfig;\n repoRoot: string;\n}\n\nexport async function list({ cfg, repoRoot }: ListOptions): Promise<void> {\n const reg = await readRegistry(cfg);\n\n console.log(`Worktrees for ${cfg.directoryPrefix}:`);\n console.log('');\n\n const headers = ['BRANCH', ...cfg.services.map((s) => s.name.toUpperCase()), 'STATUS'];\n const widths = [40, ...cfg.services.map(() => 10), 10];\n printRow(headers, widths);\n printRow(\n headers.map((h) => '-'.repeat(Math.min(h.length, 6))),\n widths,\n );\n\n // Main worktree row\n printRow(\n [\n 'main (default)',\n ...cfg.services.map((s) => String(s.mainPort)),\n statusOf(cfg.services, (s) => s.mainPort, /* dirExists */ true),\n ],\n widths,\n );\n\n // Feature worktree rows\n for (const [branch, entry] of Object.entries(reg)) {\n const wtPath = worktreePath(cfg, repoRoot, branch);\n const dirExists = existsSync(wtPath);\n const ports = cfg.services.map((s) => entry.ports[s.name]!);\n printRow(\n [\n branch,\n ...ports.map((p) => String(p)),\n dirExists ? statusOf(cfg.services, (s) => entry.ports[s.name]!, true) : 'missing',\n ],\n widths,\n );\n }\n\n console.log('');\n console.log(`Registry: ${cfg.portRegistry}`);\n}\n\nfunction statusOf(\n services: ServiceConfig[],\n portOf: (s: ServiceConfig) => number,\n dirExists: boolean,\n): string {\n if (!dirExists) return 'missing';\n const anyRunning = services.some((s) => isPortInUse(portOf(s)));\n return anyRunning ? 'running' : 'stopped';\n}\n\nfunction printRow(cells: string[], widths: number[]): void {\n const line = cells.map((c, i) => c.padEnd(widths[i] ?? 10)).join(' ');\n console.log(` ${line}`);\n}\n","import { spawnSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile } from '../paths.js';\n\nexport interface LogsOptions {\n branch: string;\n cfg: WorktreeConfig;\n service?: string;\n}\n\nexport async function logs({ branch, cfg, service }: LogsOptions): Promise<void> {\n const svc = service ? cfg.services.find((s) => s.name === service) : cfg.services[0];\n\n if (!svc) {\n const names = cfg.services.map((s) => s.name).join(', ');\n console.error(chalk.red(`Unknown service \"${service}\". Valid services: ${names}`));\n process.exit(1);\n }\n\n const path = logFile(svc, branch);\n if (!existsSync(path)) {\n console.error(chalk.red(`Log file not found: ${path}`));\n console.error(`Start the dev server first: precisa-worktree dev ${branch}`);\n process.exit(1);\n }\n\n // Delegate to tail -f so Ctrl-C works and rotation is handled.\n const result = spawnSync('tail', ['-f', path], { stdio: 'inherit' });\n process.exit(result.status ?? 0);\n}\n","import { execFileSync, spawnSync } from 'node:child_process';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { allocate } from '../registry.js';\n\nexport interface SetupOptions {\n branch: string;\n cfg: WorktreeConfig;\n repoRoot: string;\n}\n\nexport async function setup({ branch, cfg, repoRoot }: SetupOptions): Promise<void> {\n const wtPath = worktreePath(cfg, repoRoot, branch);\n\n if (existsSync(wtPath)) {\n console.error(chalk.red(`Worktree already exists: ${wtPath}`));\n console.error(`To start dev servers: precisa-worktree dev ${branch}`);\n process.exit(1);\n }\n\n console.log(chalk.bold(`==> Creating worktree for '${branch}' at ${wtPath}...`));\n\n // Fetch origin/main from the main worktree; a fresh worktree branches from it.\n execFileSync('git', ['-C', repoRoot, 'fetch', 'origin', 'main'], { stdio: 'inherit' });\n\n // If the branch already exists (local or remote-tracking), check it out\n // into the new worktree instead of creating a fresh branch — otherwise\n // `git worktree add -b` errors out on the duplicate.\n const reuseExisting = branchExists(repoRoot, branch);\n const addArgs = reuseExisting\n ? ['-C', repoRoot, 'worktree', 'add', wtPath, branch]\n : ['-C', repoRoot, 'worktree', 'add', '-b', branch, wtPath, 'origin/main'];\n execFileSync('git', addArgs, { stdio: 'inherit' });\n\n const entry = await allocate(cfg, branch);\n\n if (cfg.install !== false) {\n console.log(chalk.bold('==> Installing dependencies (pnpm install)...'));\n execFileSync('pnpm', ['install'], { cwd: wtPath, stdio: 'inherit' });\n }\n\n if (cfg.buildCommand) {\n console.log(chalk.bold(`==> Running build: ${cfg.buildCommand}`));\n execFileSync('sh', ['-c', cfg.buildCommand], { cwd: wtPath, stdio: 'inherit' });\n }\n\n // Write per-repo files with the allocated ports substituted in. Used\n // by platform to seed apps/*/.env.local so the running dev server\n // picks up the right ports without extra env-var plumbing.\n if (cfg.writeFiles?.length) {\n console.log(chalk.bold('==> Writing worktree-scoped files'));\n for (const { contents, path } of cfg.writeFiles) {\n let interpolated = contents;\n for (const [svcName, port] of Object.entries(entry.ports)) {\n interpolated = interpolated\n .replaceAll(`{${svcName}_port}`, String(port))\n .replaceAll('{port}', String(port));\n }\n const fullPath = resolve(wtPath, path);\n mkdirSync(dirname(fullPath), { recursive: true });\n writeFileSync(fullPath, interpolated);\n console.log(` wrote ${path}`);\n }\n }\n\n console.log('');\n console.log(chalk.green(`Worktree ready: ${wtPath}`));\n console.log(` Branch: ${branch}`);\n for (const svc of cfg.services) {\n const port = entry.ports[svc.name]!;\n console.log(\n ` ${svc.name.padEnd(8)}: http://localhost:${port} (logs: ${logFile(svc, branch)})`,\n );\n }\n console.log('');\n console.log('To start the dev server(s):');\n console.log(` cd ${wtPath} && precisa-worktree dev ${branch}`);\n}\n\nfunction branchExists(repoRoot: string, branch: string): boolean {\n const local = spawnSync(\n 'git',\n ['-C', repoRoot, 'show-ref', '--verify', '--quiet', `refs/heads/${branch}`],\n { stdio: 'ignore' },\n );\n if (local.status === 0) return true;\n const remote = spawnSync(\n 'git',\n ['-C', repoRoot, 'show-ref', '--verify', '--quiet', `refs/remotes/origin/${branch}`],\n { stdio: 'ignore' },\n );\n return remote.status === 0;\n}\n","import chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { getBranchEntry, portFor } from '../registry.js';\n\nexport interface StopOptions {\n branch: string;\n cfg: WorktreeConfig;\n}\n\nexport async function stop({ branch, cfg }: StopOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n if (!entry) {\n console.error(`No ports registered for '${branch}'.`);\n process.exit(1);\n }\n\n let anyRunning = false;\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n console.log(chalk.bold(`Killing ${svc.name} dev server on port ${port}...`));\n await killPort(port);\n anyRunning = true;\n }\n }\n\n if (!anyRunning) {\n console.log(`No dev servers running for '${branch}'.`);\n }\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, rmSync } from 'node:fs';\n\nimport chalk from 'chalk';\n\nimport { type WorktreeConfig } from '../config.js';\nimport { logFile, worktreePath } from '../paths.js';\nimport { isPortInUse, killPort } from '../ports.js';\nimport { free, getBranchEntry, portFor } from '../registry.js';\n\nexport interface TeardownOptions {\n branch: string;\n cfg: WorktreeConfig;\n keepBranch?: boolean;\n repoRoot: string;\n}\n\nexport async function teardown({\n branch,\n cfg,\n keepBranch = false,\n repoRoot,\n}: TeardownOptions): Promise<void> {\n const entry = await getBranchEntry(cfg, branch);\n const wtPath = worktreePath(cfg, repoRoot, branch);\n\n if (entry) {\n for (const svc of cfg.services) {\n const port = portFor(entry, svc);\n if (isPortInUse(port)) {\n console.log(chalk.bold(`Stopping ${svc.name} dev server on port ${port}...`));\n await killPort(port);\n }\n }\n }\n\n if (existsSync(wtPath)) {\n console.log(chalk.bold(`Removing worktree: ${wtPath}`));\n execFileSync('git', ['-C', repoRoot, 'worktree', 'remove', wtPath, '--force'], {\n stdio: 'inherit',\n });\n }\n\n if (keepBranch) {\n console.log(`Preserving local branch: ${branch}`);\n } else {\n const branchExists = branchRefExists(repoRoot, branch);\n if (branchExists) {\n console.log(chalk.bold(`Deleting local branch: ${branch}`));\n try {\n execFileSync('git', ['-C', repoRoot, 'branch', '-d', branch], {\n stdio: 'ignore',\n });\n } catch {\n // Not fully merged — force-delete since worktree was already removed.\n execFileSync('git', ['-C', repoRoot, 'branch', '-D', branch], {\n stdio: 'inherit',\n });\n }\n }\n }\n\n await free(cfg, branch);\n\n for (const svc of cfg.services) {\n const path = logFile(svc, branch);\n if (existsSync(path)) rmSync(path);\n }\n\n console.log(chalk.green(`Teardown complete for '${branch}'.`));\n}\n\nfunction branchRefExists(repoRoot: string, branch: string): boolean {\n try {\n execFileSync(\n 'git',\n ['-C', repoRoot, 'show-ref', '--verify', '--quiet', `refs/heads/${branch}`],\n {\n stdio: 'ignore',\n },\n );\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["rmdirSync","chalk","existsSync","resolve","execSync","readFile","sleep","sleep","readFile","existsSync","existsSync","existsSync","existsSync","chalk","chalk","existsSync","spawnSync","existsSync","mkdirSync","dirname","resolve","chalk","existsSync","chalk","resolve","mkdirSync","dirname","spawnSync","chalk","chalk","execFileSync","existsSync","chalk","chalk","existsSync","execFileSync","branchExists","chalk","rmdirSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@precisa-saude/worktree-cli",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "Shared git-worktree lifecycle CLI for Precisa Saúde repositories — creates/dev-runs/tears-down feature worktrees with per-repo port allocation. Drop-in replacement for each repo's `scripts/worktree.sh`.",
5
5
  "keywords": [
6
6
  "git-worktree",
@@ -39,7 +39,7 @@
39
39
  "@types/node": "^22.10.0",
40
40
  "tsup": "^8.3.5",
41
41
  "typescript": "~5.7.3",
42
- "@precisa-saude/tsconfig": "1.4.0"
42
+ "@precisa-saude/tsconfig": "1.5.1"
43
43
  },
44
44
  "engines": {
45
45
  "node": ">=22.0.0"