@nmakarov/cli-toolkit 0.27.0 → 0.32.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/README.md +38 -0
- package/dist/aws.cjs +210 -0
- package/dist/aws.cjs.map +1 -0
- package/dist/aws.js +201 -0
- package/dist/aws.js.map +1 -0
- package/dist/cli-runner.cjs +43 -11
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +43 -11
- package/dist/cli-runner.js.map +1 -1
- package/dist/deploy.cjs +1166 -0
- package/dist/deploy.cjs.map +1 -0
- package/dist/deploy.js +1096 -0
- package/dist/deploy.js.map +1 -0
- package/dist/index.cjs +1405 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1354 -29
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +19 -6
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +19 -6
- package/dist/init.js.map +1 -1
- package/dist/params.cjs +8 -4
- package/dist/params.cjs.map +1 -1
- package/dist/params.js +8 -4
- package/dist/params.js.map +1 -1
- package/dist/s3.cjs +1 -0
- package/dist/s3.cjs.map +1 -1
- package/dist/s3.js +1 -0
- package/dist/s3.js.map +1 -1
- package/dist/tasks.cjs +25 -7
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +25 -7
- package/dist/tasks.js.map +1 -1
- package/package.json +15 -2
- package/scripts/deploy/cli.js +181 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/deploy/service.js","../src/deploy/paths.js","../src/deploy/run.js","../src/deploy/log.js","../src/deploy/git.js","../src/deploy/release.js","../src/deploy/activate.js","../src/deploy/deps.js","../src/deploy/test.js","../src/deploy/prune.js","../src/deploy/pm2.js","../src/deploy/nginx.js","../src/deploy/sync-env.js","../src/deploy/build-info.js","../src/deploy/init-structure.js","../src/deploy/bootstrap-host.js","../src/deploy/deploy-service.js","../src/deploy/provision-service.js","../src/deploy/rollback-service.js","../src/deploy/ssh-remote.js","../src/deploy/manifests.js"],"sourcesContent":["/**\n * A \"service\" is a plain manifest object describing how to deploy one app onto a\n * host. Projects define these; the engine is otherwise project-agnostic.\n *\n * Required:\n * name unique id, also the default pm2 app + nginx site name\n * appsRoot base dir on the host, e.g. /apps/<name>\n * repoUrl git url to clone (ssh git@… or https://…)\n * pm2.script entry script (relative to the release/cwd)\n *\n * Optional (sensible defaults applied by defineService):\n * repoDirName default: repo name derived from repoUrl\n * repoSubdir default: \"\" (release = repo root). Set \"v2\" for a monorepo subdir.\n * keepReleases default: 3\n * testCommand default: null (shell run in the release before activating; null = skip)\n * envScrubPatterns default: [] (regex source strings; matching .env lines are dropped)\n * legacyRepoEnv default: null (fallback .env path on a pre-migration host)\n * buildInfoPath default: \"build-info.json\" (written into each release, relative to release root)\n * deployKey default: null (path to a git deploy key; only needed for ssh repoUrl)\n * requireEnv default: false (true = fail if no .env found; false = continue with empty)\n * pm2: { appName=name, script, args=\"\", port }\n * nginx: { siteName=name, fqdn } (omit nginx entirely to skip the nginx step)\n */\nexport function deriveRepoDirName(repoUrl) {\n const tail = String(repoUrl ?? \"\").split(\"/\").pop() ?? \"repo\";\n return tail.replace(/\\.git$/, \"\") || \"repo\";\n}\n\nexport function defineService(service) {\n if (!service?.name) throw new Error(\"service manifest needs a `name`\");\n if (!service.appsRoot) throw new Error(`service \"${service.name}\" needs an appsRoot`);\n if (!service.repoUrl) throw new Error(`service \"${service.name}\" needs a repoUrl`);\n if (!service.pm2?.script) throw new Error(`service \"${service.name}\" needs pm2.script`);\n\n const pm2 = {\n appName: service.name,\n args: \"\",\n ...service.pm2,\n };\n const nginx = service.nginx\n ? { siteName: service.name, ...service.nginx }\n : null;\n\n return {\n repoDirName: deriveRepoDirName(service.repoUrl),\n repoSubdir: \"\",\n keepReleases: 3,\n testCommand: null,\n envScrubPatterns: [],\n legacyRepoEnv: null,\n buildInfoPath: \"build-info.json\",\n deployKey: null,\n requireEnv: false,\n ...service,\n pm2,\n nginx,\n };\n}\n","import { join } from \"node:path\";\n\n/**\n * Resolve on-disk paths for a service under <appsRoot>/.\n *\n * <appsRoot>/\n * <repoDirName>/[<repoSubdir>/] git checkout (build source only)\n * releases/<stamp>/ one release = contents of the run dir\n * shared/.env, ecosystem.config.cjs\n * logs/deploy.log\n * current -> releases/<stamp>\n */\nexport function servicePaths(service) {\n const root = service.appsRoot;\n const repoDirName = service.repoDirName ?? \"repo\";\n const repoSubdir = service.repoSubdir ?? \"\";\n\n const repo = join(root, repoDirName);\n const repoRun = repoSubdir ? join(repo, repoSubdir) : repo;\n\n return {\n root,\n repo,\n repoRun,\n repoEnv: join(repoRun, \".env\"),\n releases: join(root, \"releases\"),\n shared: join(root, \"shared\"),\n logs: join(root, \"logs\"),\n current: join(root, \"current\"),\n sharedEnv: join(root, \"shared\", \".env\"),\n ecosystem: join(root, \"shared\", \"ecosystem.config.cjs\"),\n deployLog: join(root, \"logs\", \"deploy.log\"),\n lockHashFile: join(root, \"shared\", \".package-lock.sha256\"),\n };\n}\n\n/** ISO-8601 release stamp with `:` (safe on Linux ext4). */\nexport function releaseStamp(date = new Date()) {\n return date.toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\nexport function releaseDir(releasesRoot, stamp) {\n return join(releasesRoot, stamp);\n}\n","import { spawn } from \"node:child_process\";\n\n/** npm omits devDependencies when NODE_ENV=production — unset it for ci + tests. */\nexport function npmEnv(baseEnv = process.env) {\n const env = { ...baseEnv };\n delete env.NODE_ENV;\n return env;\n}\n\n/** Env for npm ci/install so devDependencies are always installed. */\nexport function npmInstallEnv(baseEnv = process.env) {\n return {\n ...npmEnv(baseEnv),\n NPM_CONFIG_PRODUCTION: \"false\",\n npm_config_production: \"false\",\n };\n}\n\n/** Run a command with inherited stdio. Rejects on non-zero exit. */\nexport function run(cmd, args, options = {}) {\n const { cwd, env, logger } = options;\n\n return new Promise((resolve, reject) => {\n logger?.info?.(`$ ${cmd} ${args.join(\" \")}${cwd ? ` (cwd=${cwd})` : \"\"}`);\n const child = spawn(cmd, args, {\n cwd,\n env: env ?? process.env,\n stdio: \"inherit\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else reject(new Error(`${cmd} exited with code ${code}`));\n });\n });\n}\n\n/** Run a shell one-liner via bash -lc. */\nexport function runShell(command, options = {}) {\n return run(\"bash\", [\"-lc\", command], options);\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\n\nexport async function appendDeployLog(deployLogPath, message) {\n await mkdir(deployLogPath.replace(/\\/[^/]+$/, \"\"), { recursive: true });\n const line = `[${new Date().toISOString()}] ${message}\\n`;\n await appendFile(deployLogPath, line);\n}\n","import { access } from \"node:fs/promises\";\n\nimport { servicePaths } from \"./paths.js\";\nimport { run } from \"./run.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function cloneRepo(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n\n if (await pathExists(paths.repo)) {\n throw new Error(`Repo already exists at ${paths.repo} — use git pull instead`);\n }\n if (dryRun) {\n logger.info(`[dryRun] would git clone ${service.repoUrl} ${paths.repo}`);\n return;\n }\n\n await run(\"git\", [\"clone\", service.repoUrl, paths.repo], { logger });\n logger.info(`cloned ${service.repoUrl} → ${paths.repo}`);\n}\n\nexport async function pullRepo(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n\n if (!(await pathExists(paths.repo))) {\n throw new Error(`Repo missing at ${paths.repo} — run provision first`);\n }\n if (dryRun) {\n logger.info(`[dryRun] would git -C ${paths.repo} pull --ff-only`);\n return;\n }\n\n await run(\"git\", [\"-C\", paths.repo, \"pull\", \"--ff-only\"], { logger });\n logger.info(`pulled ${paths.repo}`);\n}\n","import { cp, mkdir, readlink, readdir, stat } from \"node:fs/promises\";\nimport { join, dirname as pathDirname, sep } from \"node:path\";\n\nimport { releaseDir, releaseStamp, servicePaths } from \"./paths.js\";\n\nconst SKIP_TOP = new Set([\"node_modules\", \".git\"]);\n\nfunction shouldCopyEntry(srcPath) {\n const parts = srcPath.split(sep);\n if (parts.some((p) => p === \"node_modules\" || p === \".git\")) return false;\n const top = parts.at(-1);\n if (parts.length === 1 && SKIP_TOP.has(top)) return false;\n return true;\n}\n\n/** Copy the run dir into releases/<stamp>/ (excluding node_modules and .git). */\nexport async function createRelease(service, options = {}) {\n const { stamp = releaseStamp(), dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n const dest = releaseDir(paths.releases, stamp);\n\n if (dryRun) {\n logger.info(`[dryRun] would copy ${paths.repoRun} → ${dest}`);\n return { stamp, path: dest };\n }\n\n await mkdir(paths.releases, { recursive: true });\n await cp(paths.repoRun, dest, {\n recursive: true,\n filter: (src) => shouldCopyEntry(src),\n });\n\n logger.info(`release ${stamp} created at ${dest}`);\n return { stamp, path: dest };\n}\n\n/** Resolve current release path if symlink exists. */\nexport async function readCurrentRelease(paths) {\n try {\n const target = await readlink(paths.current);\n return target.startsWith(\"/\") ? target : join(pathDirname(paths.current), target);\n } catch {\n return null;\n }\n}\n\nexport async function listReleases(paths) {\n let names;\n try {\n names = await readdir(paths.releases);\n } catch {\n return [];\n }\n\n const entries = [];\n for (const name of names) {\n const full = releaseDir(paths.releases, name);\n const s = await stat(full);\n if (s.isDirectory()) entries.push({ name, path: full, mtime: s.mtime });\n }\n\n entries.sort((a, b) => b.name.localeCompare(a.name));\n return entries;\n}\n","import { symlink, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n/** Point current → release and link shared/.env inside the release. */\nexport async function activateRelease(releasePath, paths, options = {}) {\n const { dryRun = false, logger = console } = options;\n\n if (dryRun) {\n logger.info(`[dryRun] would activate ${releasePath} → ${paths.current}`);\n return;\n }\n\n try {\n await unlink(paths.current);\n } catch {\n // first deploy\n }\n await symlink(releasePath, paths.current);\n\n const envLink = join(releasePath, \".env\");\n try {\n await unlink(envLink);\n } catch {\n // ok\n }\n await symlink(paths.sharedEnv, envLink);\n\n logger.info(`active release: ${releasePath}`);\n}\n","import { createHash } from \"node:crypto\";\nimport { access, cp, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { readCurrentRelease } from \"./release.js\";\nimport { npmInstallEnv, run } from \"./run.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function lockfileHash(releasePath) {\n const lockPath = join(releasePath, \"package-lock.json\");\n try {\n const buf = await readFile(lockPath);\n return createHash(\"sha256\").update(buf).digest(\"hex\");\n } catch {\n return null; // no lockfile → can't fingerprint; always (re)install\n }\n}\n\nasync function readHashFile(path) {\n try {\n return (await readFile(path, \"utf8\")).trim();\n } catch {\n return null;\n }\n}\n\nasync function npmInstall(releasePath, hasLock, logger) {\n await rm(join(releasePath, \"node_modules\"), { recursive: true, force: true });\n const cmd = hasLock ? [\"ci\", \"--include=dev\"] : [\"install\", \"--include=dev\", \"--no-audit\", \"--no-fund\"];\n logger.info(`running npm ${cmd.join(\" \")} in ${releasePath}`);\n await run(\"npm\", cmd, { cwd: releasePath, logger, env: npmInstallEnv() });\n}\n\n/**\n * Install deps in the release. If the lockfile is unchanged from the active\n * release and its node_modules exists, copy it (fast path); otherwise npm ci.\n */\nexport async function installDeps(service, releasePath, paths, options = {}) {\n const { dryRun = false, logger = console } = options;\n\n if (dryRun) {\n logger.info(`[dryRun] would install deps in ${releasePath}`);\n return { hash: null, copied: false };\n }\n\n const hash = await lockfileHash(releasePath);\n const hasLock = hash !== null;\n const hashMarker = join(releasePath, \".deploy-package-lock.sha256\");\n\n const currentPath = await readCurrentRelease(paths);\n let copied = false;\n\n if (hasLock && currentPath && (await pathExists(join(currentPath, \"node_modules\")))) {\n const currentHash = await readHashFile(join(currentPath, \".deploy-package-lock.sha256\"));\n if (currentHash === hash) {\n logger.info(\"lockfile unchanged — copying node_modules from current release\");\n await cp(join(currentPath, \"node_modules\"), join(releasePath, \"node_modules\"), {\n recursive: true,\n force: true,\n });\n copied = true;\n }\n }\n\n if (!copied) {\n await npmInstall(releasePath, hasLock, logger);\n }\n\n if (hasLock) {\n await writeFile(hashMarker, `${hash}\\n`, \"utf8\");\n await mkdir(paths.shared, { recursive: true });\n await writeFile(paths.lockHashFile, `${hash}\\n`, \"utf8\");\n }\n\n return { hash, copied };\n}\n","import { symlink, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { npmInstallEnv, runShell } from \"./run.js\";\n\n/**\n * Symlink shared/.env into the release and run the service's testCommand (a shell\n * one-liner, e.g. \"npm run test:ci\"). No-op when the service defines no command.\n */\nexport async function runReleaseTests(service, releasePath, paths, options = {}) {\n const { dryRun = false, logger = console } = options;\n\n if (!service.testCommand) {\n logger.info(\"no testCommand configured — skipping tests\");\n return;\n }\n\n if (dryRun) {\n logger.info(`[dryRun] would run \"${service.testCommand}\" in ${releasePath}`);\n return;\n }\n\n const envLink = join(releasePath, \".env\");\n try {\n await unlink(envLink);\n } catch {\n // no existing link\n }\n await symlink(paths.sharedEnv, envLink);\n\n logger.info(`running \"${service.testCommand}\" in ${releasePath}`);\n await runShell(service.testCommand, { cwd: releasePath, logger, env: npmInstallEnv() });\n}\n","import { rm, readlink } from \"node:fs/promises\";\n\nimport { listReleases } from \"./release.js\";\n\n/** Remove old releases, keeping the newest N (always keeps the active one). */\nexport async function pruneReleases(service, paths, options = {}) {\n const { dryRun = false, logger = console } = options;\n const keep = service.keepReleases ?? 3;\n const releases = await listReleases(paths);\n\n let activeName = null;\n try {\n const target = await readlink(paths.current);\n activeName = target.split(\"/\").pop();\n } catch {\n // no current\n }\n\n const keepSet = new Set();\n for (const rel of releases) {\n if (keepSet.size < keep) keepSet.add(rel.name);\n }\n if (activeName) keepSet.add(activeName);\n\n const toRemove = releases.filter((rel) => !keepSet.has(rel.name));\n for (const rel of toRemove) {\n if (dryRun) {\n logger.info(`[dryRun] would rm -rf ${rel.path}`);\n } else {\n await rm(rel.path, { recursive: true, force: true });\n logger.info(`pruned ${rel.path}`);\n }\n }\n\n return { removed: toRemove.map((r) => r.name) };\n}\n","import { runShell } from \"./run.js\";\n\nexport async function reloadPm2(paths, options = {}) {\n const { dryRun = false, logger = console } = options;\n\n if (dryRun) {\n logger.info(`[dryRun] would pm2 startOrReload ${paths.ecosystem} --update-env`);\n return;\n }\n\n await runShell(`pm2 startOrReload \"${paths.ecosystem}\" --update-env`, { logger });\n logger.info(\"pm2 reloaded\");\n}\n","import { writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { runShell } from \"./run.js\";\n\nasync function hasTlsCert(certPath) {\n try {\n await runShell(`sudo test -f '${certPath}'`, {});\n return true;\n } catch {\n return false;\n }\n}\n\nfunction proxyBlock(port) {\n return ` location / {\n proxy_pass http://127.0.0.1:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_read_timeout 120s;\n }`;\n}\n\nfunction buildNginxConfig(service) {\n const { nginx, pm2 } = service;\n const certDir = `/etc/letsencrypt/live/${nginx.fqdn}`;\n\n return `# ${nginx.siteName} — managed by cli-toolkit deploy (proxy mode)\n# ${nginx.fqdn} → 127.0.0.1:${pm2.port}\n\nserver {\n listen 80;\n listen [::]:80;\n server_name ${nginx.fqdn};\n location / { return 301 https://$host$request_uri; }\n}\n\nserver {\n listen 443 ssl;\n listen [::]:443 ssl;\n server_name ${nginx.fqdn};\n\n ssl_certificate ${certDir}/fullchain.pem;\n ssl_certificate_key ${certDir}/privkey.pem;\n include /etc/letsencrypt/options-ssl-nginx.conf;\n ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;\n\n client_max_body_size 25m;\n\n${proxyBlock(pm2.port)}\n}\n`;\n}\n\nfunction buildNginxConfigHttpOnly(service) {\n const { nginx, pm2 } = service;\n return `# ${nginx.siteName} — managed by cli-toolkit deploy (HTTP proxy, no TLS cert yet)\n\nserver {\n listen 80;\n listen [::]:80;\n server_name ${nginx.fqdn};\n\n client_max_body_size 25m;\n\n${proxyBlock(pm2.port)}\n}\n`;\n}\n\n/** Replace the stub nginx site with a reverse-proxy to the app. */\nexport async function enableNginxUpstream(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const { nginx } = service;\n if (!nginx) {\n logger.info(\"no nginx config on service — skipping nginx step\");\n return { skipped: true };\n }\n\n const siteAvailable = `/etc/nginx/sites-available/${nginx.siteName}`;\n const siteEnabled = `/etc/nginx/sites-enabled/${nginx.siteName}`;\n const cert = `/etc/letsencrypt/live/${nginx.fqdn}/fullchain.pem`;\n\n if (dryRun) {\n logger.info(`[dryRun] would write ${siteAvailable} (proxy → 127.0.0.1:${service.pm2.port}) and reload nginx`);\n return { hasCert: null };\n }\n\n const hasCert = await hasTlsCert(cert);\n const config = hasCert ? buildNginxConfig(service) : buildNginxConfigHttpOnly(service);\n\n const tmp = join(tmpdir(), `${service.name}-nginx.conf`);\n await writeFile(tmp, config);\n await runShell(\n `sudo cp '${tmp}' '${siteAvailable}' && sudo ln -sf '${siteAvailable}' '${siteEnabled}' && sudo nginx -t && sudo systemctl reload nginx`,\n { logger },\n );\n\n logger.info(`nginx upstream enabled for ${nginx.fqdn} → 127.0.0.1:${service.pm2.port} (tls=${hasCert})`);\n return { hasCert };\n}\n","import { access, mkdir, readFile, writeFile } from \"node:fs/promises\";\n\nimport { servicePaths } from \"./paths.js\";\n\n/**\n * Drop .env lines matching any of the service's envScrubPatterns (regex source\n * strings). Useful to strip empty keys that would crash strict param validation.\n */\nexport function scrubEnvContent(content, patterns = []) {\n const regexes = patterns.map((p) => (p instanceof RegExp ? p : new RegExp(p)));\n if (regexes.length === 0) return content;\n return content\n .split(\"\\n\")\n .filter((line) => !regexes.some((re) => re.test(line.trim())))\n .join(\"\\n\");\n}\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Copy <repoRun>/.env → shared/.env (with optional legacy fallback + scrubbing). */\nexport async function syncEnv(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n const patterns = service.envScrubPatterns ?? [];\n\n if (dryRun) {\n logger.info(`[dryRun] would sync ${paths.repoEnv} → ${paths.sharedEnv}`);\n return { source: paths.repoEnv, dest: paths.sharedEnv };\n }\n\n let source = paths.repoEnv;\n if (!(await pathExists(source)) && service.legacyRepoEnv && (await pathExists(service.legacyRepoEnv))) {\n logger.info(`using legacy env: ${service.legacyRepoEnv}`);\n source = service.legacyRepoEnv;\n }\n\n await mkdir(paths.shared, { recursive: true });\n\n if (!(await pathExists(source))) {\n if (service.requireEnv) {\n throw new Error(\n `No .env found at ${paths.repoEnv}` +\n (service.legacyRepoEnv ? ` or ${service.legacyRepoEnv}` : \"\") +\n \" — place .env on the host or run the remote deploy from a laptop with a local .env (auto-scp)\",\n );\n }\n // Optional env: ensure shared/.env exists so the per-release symlink is valid.\n if (!(await pathExists(paths.sharedEnv))) {\n await writeFile(paths.sharedEnv, \"\", { mode: 0o600 });\n }\n logger.warn(`no .env found (source ${source}) — using empty ${paths.sharedEnv}`);\n return { source: null, dest: paths.sharedEnv };\n }\n\n const raw = await readFile(source, \"utf8\");\n await writeFile(paths.sharedEnv, scrubEnvContent(raw, patterns), { mode: 0o600 });\n logger.info(`synced ${source} → ${paths.sharedEnv}`);\n return { source, dest: paths.sharedEnv };\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport { readCurrentRelease } from \"./release.js\";\nimport { servicePaths } from \"./paths.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** Bump semver patch (0.1.0 → 0.1.1). */\nexport function bumpPatchVersion(version) {\n const parts = String(version).trim().split(\".\");\n const major = Number.parseInt(parts[0], 10) || 0;\n const minor = Number.parseInt(parts[1], 10) || 0;\n const patch = Number.parseInt(parts[2], 10) || 0;\n return `${major}.${minor}.${patch + 1}`;\n}\n\nasync function readJson(path) {\n try {\n return JSON.parse(await readFile(path, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nasync function gitShortCommit(repoPath) {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", repoPath, \"rev-parse\", \"--short\", \"HEAD\"], {\n encoding: \"utf8\",\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Next semver: bump patch from the **currently active** release's build-info,\n * else seed from package.json. Each release carries its own build-info.json so a\n * rollback restores that release's label.\n */\nexport async function resolveNextVersion(service, paths, pkgPath) {\n const pkg = (await readJson(pkgPath)) ?? {};\n const baseVersion = pkg.version || \"0.1.0\";\n\n const currentPath = await readCurrentRelease(paths);\n if (currentPath) {\n const active = await readJson(join(currentPath, service.buildInfoPath));\n if (active?.version) return bumpPatchVersion(active.version);\n }\n return baseVersion;\n}\n\n/** Read build-info from a release directory (for rollback logs / status). */\nexport async function readReleaseBuildInfo(service, releasePath) {\n return readJson(join(releasePath, service.buildInfoPath));\n}\n\n/** Write build-info.json into the new release directory. */\nexport async function writeReleaseBuildInfo(service, releasePath, { stamp, dryRun = false, logger = console }) {\n const paths = servicePaths(service);\n const pkgPath = join(paths.repoRun, \"package.json\");\n\n const version = await resolveNextVersion(service, paths, pkgPath);\n const gitCommit = await gitShortCommit(paths.repo);\n\n const buildInfo = {\n version,\n release: stamp,\n deployedAt: new Date().toISOString(),\n gitCommit,\n service: service.name,\n };\n\n const dest = join(releasePath, service.buildInfoPath);\n\n if (dryRun) {\n logger.info(`[dryRun] would write ${dest} (${JSON.stringify(buildInfo)})`);\n return buildInfo;\n }\n\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, `${JSON.stringify(buildInfo, null, 2)}\\n`, { mode: 0o644 });\n\n const gitSuffix = gitCommit ? ` git=${gitCommit}` : \"\";\n logger.info(`build info: v${version} release=${stamp}${gitSuffix}`);\n return buildInfo;\n}\n","import { access, appendFile, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\nimport { servicePaths } from \"./paths.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Fail fast with a useful message when not on a provisioned host. */\nasync function requireDeployRoot(parentDir, serviceRoot) {\n if (await pathExists(parentDir)) return;\n throw new Error(\n `Cannot create ${serviceRoot}: parent directory ${parentDir} does not exist.\\n` +\n `This is meant to run on the target host (where ${parentDir} exists). ` +\n `For a local dry run use --appsRoot=/tmp/<service>.`,\n );\n}\n\nfunction buildEcosystemConfig(service, paths) {\n const { pm2 } = service;\n const outLog = join(paths.logs, `${pm2.appName}.out.log`);\n const errLog = join(paths.logs, `${pm2.appName}.err.log`);\n\n return `/**\n * pm2 ecosystem for ${service.name} — seeded by cli-toolkit deploy (init).\n *\n * cwd points at the \\`current\\` symlink (created on first deploy).\n * Tweak \\`args\\` here, then: pm2 reload ${paths.ecosystem} --update-env\n */\nmodule.exports = {\n apps: [\n {\n name: \"${pm2.appName}\",\n script: \"${pm2.script}\",\n cwd: \"${paths.current}\",\n args: \"${pm2.args}\",\n instances: 1,\n exec_mode: \"fork\",\n autorestart: true,\n min_uptime: \"10s\",\n max_restarts: 10,\n restart_delay: 2000,\n max_memory_restart: \"1500M\",\n out_file: \"${outLog}\",\n error_file: \"${errLog}\",\n merge_logs: true,\n time: true,\n env: {\n NODE_ENV: \"production\",\n },\n },\n ],\n};\n`;\n}\n\n/** Create <appsRoot>/{releases,shared,logs} and seed shared/ecosystem.config.cjs. */\nexport async function initServiceStructure(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n const dirs = [paths.releases, paths.shared, paths.logs];\n const created = [];\n const skipped = [];\n\n if (!dryRun) {\n await requireDeployRoot(dirname(paths.root), paths.root);\n }\n\n for (const dir of dirs) {\n if (await pathExists(dir)) {\n skipped.push(dir);\n continue;\n }\n if (!dryRun) await mkdir(dir, { recursive: true });\n created.push(dir);\n }\n\n let ecosystemCreated = false;\n if (await pathExists(paths.ecosystem)) {\n skipped.push(paths.ecosystem);\n } else {\n if (!dryRun) {\n await writeFile(paths.ecosystem, buildEcosystemConfig(service, paths), { mode: 0o644 });\n }\n ecosystemCreated = true;\n created.push(paths.ecosystem);\n }\n\n const line = `[${new Date().toISOString()}] init-structure service=${service.name} dryRun=${dryRun} created=${created.length} skipped=${skipped.length}\\n`;\n if (!dryRun) {\n await mkdir(paths.logs, { recursive: true });\n await appendFile(paths.deployLog, line);\n }\n\n logger.info(`service=${service.name} appsRoot=${paths.root}`);\n logger.info(`created: ${created.length ? created.join(\", \") : \"(none)\"}`);\n logger.info(`already present: ${skipped.length ? skipped.join(\", \") : \"(none)\"}`);\n if (ecosystemCreated) logger.info(`seeded ${paths.ecosystem}`);\n\n return { paths, created, skipped, ecosystemCreated };\n}\n","import { execSync } from \"node:child_process\";\nimport { access, chmod, copyFile, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\n\nimport { runShell } from \"./run.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction expandHome(path) {\n return path.startsWith(\"~/\") ? join(homedir(), path.slice(2)) : path;\n}\n\nasync function ensurePm2Startup(options = {}) {\n const { user = \"ubuntu\", dryRun = false, logger = console } = options;\n\n if (dryRun) {\n logger.info(\"[dryRun] would configure pm2 startup systemd\");\n return;\n }\n\n try {\n execSync(\"pm2 ping\", { stdio: \"ignore\" });\n } catch {\n // pm2 daemon may not be up yet\n }\n\n try {\n const out = execSync(`pm2 startup systemd -u ${user} --hp /home/${user}`, { encoding: \"utf8\" });\n const sudoLine = out.split(\"\\n\").find((l) => l.trim().startsWith(\"sudo\"));\n if (sudoLine) {\n execSync(sudoLine.trim(), { stdio: \"inherit\" });\n logger.info(\"pm2 startup systemd configured\");\n }\n } catch (err) {\n logger.warn(`pm2 startup skipped or already configured: ${err.message}`);\n }\n}\n\nasync function installDeployKey(deployKeyPath, options = {}) {\n const { dryRun = false, logger = console } = options;\n const keyPath = expandHome(deployKeyPath);\n\n if (!(await pathExists(keyPath))) {\n logger.warn(`deploy key not found at ${keyPath} — skipping git ssh setup`);\n return;\n }\n\n const keyBase = basename(keyPath);\n const sshDir = join(homedir(), \".ssh\");\n const destKey = join(sshDir, keyBase);\n const configPath = join(sshDir, \"config\");\n const block = `\nHost github.com\n HostName github.com\n User git\n IdentityFile ${destKey}\n IdentitiesOnly yes\n`;\n\n if (dryRun) {\n logger.info(`[dryRun] would install deploy key ${keyPath} → ${destKey}`);\n return;\n }\n\n await mkdir(sshDir, { recursive: true, mode: 0o700 });\n await copyFile(keyPath, destKey);\n await chmod(destKey, 0o600);\n\n let config = \"\";\n if (await pathExists(configPath)) config = await readFile(configPath, \"utf8\");\n if (!config.includes(\"Host github.com\")) {\n await writeFile(configPath, `${config.trimEnd()}\\n${block}\\n`, { mode: 0o600 });\n logger.info(\"updated ~/.ssh/config for github.com\");\n }\n logger.info(`deploy key installed at ${destKey}`);\n}\n\nasync function installLogrotate(service, options = {}) {\n const { dryRun = false, logger = console } = options;\n const conf = `/etc/logrotate.d/${service.name}`;\n const body = `${service.appsRoot}/logs/*.log {\n daily\n rotate 14\n compress\n delaycompress\n missingok\n notifempty\n copytruncate\n}\n`;\n\n if (dryRun) {\n logger.info(`[dryRun] would write ${conf}`);\n return;\n }\n\n const tmp = join(\"/tmp\", `${service.name}-logrotate.conf`);\n await writeFile(tmp, body);\n await runShell(`sudo cp '${tmp}' '${conf}'`, { logger });\n logger.info(`logrotate config written: ${conf}`);\n}\n\n/** One-time host prep: pm2 systemd, optional git deploy key, logrotate. */\nexport async function bootstrapHost(service, options = {}) {\n const { deployKey = service.deployKey, user = \"ubuntu\", dryRun = false, logger = console } = options;\n\n await ensurePm2Startup({ user, dryRun, logger });\n if (deployKey) await installDeployKey(deployKey, { dryRun, logger });\n await installLogrotate(service, { dryRun, logger });\n logger.info(\"bootstrap-host complete\");\n}\n","import { initServiceStructure } from \"./init-structure.js\";\nimport { appendDeployLog } from \"./log.js\";\nimport { pullRepo } from \"./git.js\";\nimport { createRelease } from \"./release.js\";\nimport { installDeps } from \"./deps.js\";\nimport { runReleaseTests } from \"./test.js\";\nimport { activateRelease } from \"./activate.js\";\nimport { pruneReleases } from \"./prune.js\";\nimport { reloadPm2 } from \"./pm2.js\";\nimport { enableNginxUpstream } from \"./nginx.js\";\nimport { syncEnv } from \"./sync-env.js\";\nimport { writeReleaseBuildInfo } from \"./build-info.js\";\nimport { servicePaths } from \"./paths.js\";\n\n/** Full deploy: pull → env → release → deps → test → activate → prune → pm2 → nginx. */\nexport async function deployService(service, options = {}) {\n const {\n dryRun = false,\n skipPull = false,\n skipTests = false,\n skipNginx = false,\n logger = console,\n } = options;\n\n const paths = servicePaths(service);\n\n await initServiceStructure(service, { dryRun, logger });\n\n if (!skipPull) await pullRepo(service, { dryRun, logger });\n\n await syncEnv(service, { dryRun, logger });\n\n const { stamp, path: releasePath } = await createRelease(service, { dryRun, logger });\n await writeReleaseBuildInfo(service, releasePath, { stamp, dryRun, logger });\n await installDeps(service, releasePath, paths, { dryRun, logger });\n\n if (!skipTests) await runReleaseTests(service, releasePath, paths, { dryRun, logger });\n\n await activateRelease(releasePath, paths, { dryRun, logger });\n await pruneReleases(service, paths, { dryRun, logger });\n await reloadPm2(paths, { dryRun, logger });\n\n if (!skipNginx) await enableNginxUpstream(service, { dryRun, logger });\n\n const summary = `deploy complete stamp=${stamp} dryRun=${dryRun}`;\n logger.info(summary);\n if (!dryRun) await appendDeployLog(paths.deployLog, summary);\n\n return { stamp, releasePath };\n}\n","import { access } from \"node:fs/promises\";\n\nimport { bootstrapHost } from \"./bootstrap-host.js\";\nimport { initServiceStructure } from \"./init-structure.js\";\nimport { cloneRepo, pullRepo } from \"./git.js\";\nimport { deployService } from \"./deploy-service.js\";\nimport { syncEnv } from \"./sync-env.js\";\nimport { servicePaths } from \"./paths.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** First-time setup: optional bootstrap, init dirs, clone/pull, sync .env, first deploy. */\nexport async function provisionService(service, options = {}) {\n const {\n dryRun = false,\n deploy = true,\n skipBootstrap = true,\n deployKey,\n logger = console,\n } = options;\n\n if (!skipBootstrap) {\n await bootstrapHost(service, { deployKey, dryRun, logger });\n }\n\n await initServiceStructure(service, { dryRun, logger });\n const paths = servicePaths(service);\n\n if (await pathExists(paths.repo)) {\n logger.info(`repo exists at ${paths.repo} — pulling`);\n await pullRepo(service, { dryRun, logger });\n } else {\n await cloneRepo(service, { dryRun, logger });\n }\n\n await syncEnv(service, { dryRun, logger });\n\n if (deploy) {\n await deployService(service, { dryRun, logger, skipPull: true });\n } else {\n logger.info(\"provision complete (deploy skipped)\");\n }\n}\n","import { readlink } from \"node:fs/promises\";\n\nimport { activateRelease } from \"./activate.js\";\nimport { readReleaseBuildInfo } from \"./build-info.js\";\nimport { appendDeployLog } from \"./log.js\";\nimport { listReleases } from \"./release.js\";\nimport { reloadPm2 } from \"./pm2.js\";\nimport { servicePaths } from \"./paths.js\";\n\n/** Flip current to a named release or the previous one. */\nexport async function rollbackService(service, options = {}) {\n const { release: targetName, dryRun = false, logger = console } = options;\n const paths = servicePaths(service);\n const releases = await listReleases(paths);\n\n if (releases.length === 0) throw new Error(\"No releases to roll back to\");\n\n let activeName = null;\n try {\n const target = await readlink(paths.current);\n activeName = target.split(\"/\").pop();\n } catch {\n throw new Error(\"No active release (current symlink missing)\");\n }\n\n let rollbackTarget;\n if (targetName) {\n rollbackTarget = releases.find((r) => r.name === targetName);\n if (!rollbackTarget) throw new Error(`Release not found: ${targetName}`);\n } else {\n rollbackTarget = releases.find((r) => r.name !== activeName);\n if (!rollbackTarget) throw new Error(\"No previous release to roll back to\");\n }\n\n if (rollbackTarget.name === activeName) throw new Error(`Already on release ${activeName}`);\n\n logger.info(`rollback ${activeName} → ${rollbackTarget.name}`);\n const buildInfo = await readReleaseBuildInfo(service, rollbackTarget.path);\n if (buildInfo?.version) {\n logger.info(`rollback target: v${buildInfo.version} release=${buildInfo.release ?? rollbackTarget.name}`);\n }\n await activateRelease(rollbackTarget.path, paths, { dryRun, logger });\n await reloadPm2(paths, { dryRun, logger });\n\n const summary = `rollback ${activeName} → ${rollbackTarget.name} dryRun=${dryRun}`;\n if (!dryRun) await appendDeployLog(paths.deployLog, summary);\n\n return { from: activeName, to: rollbackTarget.name, path: rollbackTarget.path };\n}\n","import { access, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { spawn } from \"node:child_process\";\n\nimport { scrubEnvContent } from \"./sync-env.js\";\nimport { servicePaths } from \"./paths.js\";\n\n/** Path (relative to the run dir on the server) of the toolkit deploy CLI. */\nexport const REMOTE_CLI_REL = \"node_modules/@nmakarov/cli-toolkit/scripts/deploy/cli.js\";\n\nasync function pathExists(path) {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction expandHome(path) {\n return path.startsWith(\"~/\") ? join(homedir(), path.slice(2)) : path;\n}\n\nfunction resolveLocalEnvPath(envFile) {\n if (envFile) {\n const expanded = expandHome(envFile);\n return expanded.startsWith(\"/\") ? expanded : join(process.cwd(), expanded);\n }\n return join(process.cwd(), \".env\");\n}\n\n/** Parse the ssh host out of a git url (git@host:..., ssh://git@host/...). null for https. */\nexport function parseGitHost(repoUrl) {\n const u = String(repoUrl ?? \"\");\n let m = u.match(/^[^@]+@([^:]+):/); // git@github.com:org/repo.git\n if (m) return m[1];\n m = u.match(/^ssh:\\/\\/[^@]+@([^/:]+)/); // ssh://git@github.com/org/repo.git\n if (m) return m[1];\n return null;\n}\n\nexport function shellQuote(value) {\n return `'${String(value).replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport function sshRun(host, remoteCommand, options = {}) {\n const { logger } = options;\n return new Promise((resolve, reject) => {\n logger?.info?.(`ssh ${host} ${remoteCommand.slice(0, 120)}${remoteCommand.length > 120 ? \"…\" : \"\"}`);\n const child = spawn(\"ssh\", [host, remoteCommand], { stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => (code === 0 ? resolve() : reject(new Error(`ssh ${host} exited with code ${code}`))));\n });\n}\n\nfunction scp(localPath, remoteSpec) {\n return new Promise((resolve, reject) => {\n const child = spawn(\"scp\", [localPath, remoteSpec], { stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => (code === 0 ? resolve() : reject(new Error(`scp exited with code ${code}`))));\n });\n}\n\n/** Copy a git deploy key from the laptop to the server (no-op if not present locally). */\nexport async function ensureDeployKeyOnRemote(host, deployKeyPath, options = {}) {\n const { logger = console } = options;\n if (!deployKeyPath) return false;\n const localPath = expandHome(deployKeyPath);\n if (!(await pathExists(localPath))) return false;\n\n const keyBase = basename(localPath);\n logger.info(`copying deploy key ${localPath} → ${host}:~/.ssh/${keyBase}`);\n await sshRun(host, \"mkdir -p ~/.ssh && chmod 700 ~/.ssh\", { logger });\n await scp(localPath, `${host}:.ssh/${keyBase}`, { logger });\n await sshRun(host, `chmod 600 ~/.ssh/${keyBase}`, { logger });\n return true;\n}\n\n/** known_hosts for the git host + (optional) ~/.ssh/config IdentityFile for the deploy key. */\nexport async function prepareGitHost(host, options = {}) {\n const { logger = console, gitHost, keyBasename } = options;\n if (!gitHost) return;\n\n const configBlock = keyBasename\n ? `if ! grep -q 'Host ${gitHost}' ~/.ssh/config 2>/dev/null; then\n printf '%s\\\\n' '' 'Host ${gitHost}' ' HostName ${gitHost}' ' User git' ' IdentityFile ~/.ssh/${keyBasename}' ' IdentitiesOnly yes' >> ~/.ssh/config\n chmod 600 ~/.ssh/config\n echo \"configured ~/.ssh/config for ${gitHost}\"\nfi`\n : `:`;\n\n const script = `\nset -euo pipefail\nmkdir -p ~/.ssh\nchmod 700 ~/.ssh\nif ! grep -q '^${gitHost}' ~/.ssh/known_hosts 2>/dev/null; then\n ssh-keyscan -t ed25519,rsa ${gitHost} >> ~/.ssh/known_hosts 2>/dev/null\n echo \"added ${gitHost} to known_hosts\"\nfi\n${configBlock}\n`.trim();\n\n await sshRun(host, script, { logger });\n}\n\n/** Install the run-dir workspace deps so the toolkit CLI is available on the server. */\nexport async function ensureRepoDependencies(host, service, options = {}) {\n const { logger = console } = options;\n const paths = servicePaths(service);\n const run = shellQuote(paths.repoRun);\n await sshRun(\n host,\n `cd ${run} && if [ ! -d node_modules/@nmakarov/cli-toolkit ] || [ package-lock.json -nt node_modules/.package-lock.json ]; then npm ci; fi`,\n { logger },\n );\n}\n\n/** Copy laptop .env → server run-dir .env (scrubbed). sync-env then copies it to shared/. */\nexport async function ensureEnvOnRemote(host, service, options = {}) {\n const { logger = console, envFile } = options;\n const paths = servicePaths(service);\n const localPath = resolveLocalEnvPath(envFile);\n if (!(await pathExists(localPath))) return false;\n\n logger.info(`copying .env ${localPath} → ${host}:${paths.repoEnv}`);\n await sshRun(host, `mkdir -p ${shellQuote(dirname(paths.repoEnv))}`, { logger });\n\n const scrubbed = scrubEnvContent(await readFile(localPath, \"utf8\"), service.envScrubPatterns ?? []);\n const tmp = join(tmpdir(), `deploy-env-${Date.now()}`);\n await writeFile(tmp, scrubbed, { mode: 0o600 });\n await scp(tmp, `${host}:${paths.repoEnv}`, { logger });\n await sshRun(host, `chmod 600 ${shellQuote(paths.repoEnv)}`, { logger });\n return true;\n}\n\n/** Ensure a checkout exists on the server, then pull latest + deps + env. */\nexport async function ensureRemoteRepo(host, service, options = {}) {\n const { logger = console, deployKey = service.deployKey, envFile } = options;\n const paths = servicePaths(service);\n const repo = shellQuote(paths.repo);\n const repoUrl = shellQuote(service.repoUrl);\n const root = shellQuote(paths.root);\n\n const localKeyBase = deployKey ? basename(expandHome(deployKey)) : null;\n await ensureDeployKeyOnRemote(host, deployKey, { logger });\n await prepareGitHost(host, { logger, gitHost: parseGitHost(service.repoUrl), keyBasename: localKeyBase });\n\n await sshRun(\n host,\n `mkdir -p ${root} && if [ -d ${repo}/.git ]; then git -C ${repo} pull --ff-only; else git clone ${repoUrl} ${repo}; fi`,\n { logger },\n );\n\n await ensureRepoDependencies(host, service, { logger });\n await ensureEnvOnRemote(host, service, { logger, envFile });\n}\n\n/**\n * Invoke the toolkit deploy CLI on the server in local mode (no --host), passing\n * the same --service/--manifests + extra flags. Run after ensureRemoteRepo.\n */\nexport async function runRemoteCli(host, service, command, args = [], options = {}) {\n const { logger = console, manifests, skipPull = false, deployKey = service.deployKey, envFile } = options;\n const paths = servicePaths(service);\n const run = shellQuote(paths.repoRun);\n const cli = shellQuote(REMOTE_CLI_REL);\n\n if (!skipPull) {\n await ensureRemoteRepo(host, service, { logger, deployKey, envFile });\n } else {\n await ensureRepoDependencies(host, service, { logger });\n await ensureEnvOnRemote(host, service, { logger, envFile });\n }\n\n const passthrough = [\n `--service=${service.name}`,\n ...(manifests ? [`--manifests=${manifests}`] : []),\n ...args,\n ].map(shellQuote).join(\" \");\n\n await sshRun(host, `cd ${run} && node ${cli} ${shellQuote(command)} ${passthrough}`.trim(), { logger });\n}\n\nexport async function runRemoteStatus(host, service, options = {}) {\n const { logger = console } = options;\n const paths = servicePaths(service);\n const port = service.pm2.port;\n const app = service.pm2.appName;\n\n const script = `\necho \"=== apps root ===\"\nls -la ${shellQuote(paths.root)} 2>/dev/null || echo \"(missing)\"\necho \"\"\necho \"=== current ===\"\nreadlink ${shellQuote(paths.current)} 2>/dev/null || echo \"(not set)\"\necho \"\"\necho \"=== releases ===\"\nls -1 ${shellQuote(paths.releases)} 2>/dev/null || echo \"(none)\"\necho \"\"\necho \"=== pm2 ===\"\npm2 describe ${app} 2>/dev/null | head -20 || pm2 status ${app} 2>/dev/null || echo \"(not running)\"\n${port ? `echo \"\"\necho \"=== app health (localhost) ===\"\ncurl -sf http://127.0.0.1:${port}/healthz 2>/dev/null || echo \"(no /healthz on :${port})\"` : \"\"}\n`.trim();\n\n await sshRun(host, script, { logger });\n}\n","import { isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { defineService } from \"./service.js\";\n\n/**\n * Load a project's service manifests module. The module may export:\n * export const services = { \"my-svc\": { … }, … } // map\n * export default { \"my-svc\": { … } } // map as default\n * export const services = [ { name: \"my-svc\", … } ] // array\n * Every entry is normalized through defineService().\n *\n * @param {{ manifests?: string, cwd?: string }} opts manifests = path to the module\n * @returns {Promise<Record<string, object>>} name → normalized service\n */\nexport async function loadServices({ manifests = \"deploy/services.js\", cwd = process.cwd() } = {}) {\n const abs = isAbsolute(manifests) ? manifests : resolve(cwd, manifests);\n let mod;\n try {\n mod = await import(pathToFileURL(abs).href);\n } catch (err) {\n throw new Error(`Could not load deploy manifests from ${abs}: ${err.message}`);\n }\n\n const raw = mod.services ?? mod.default;\n if (!raw) {\n throw new Error(`Manifests module ${abs} must export \\`services\\` (or default): a map or array of service manifests`);\n }\n\n const list = Array.isArray(raw) ? raw : Object.values(raw);\n const out = {};\n for (const entry of list) {\n const svc = defineService(entry);\n out[svc.name] = svc;\n }\n return out;\n}\n\n/** Resolve one normalized service by name (optionally overriding appsRoot). */\nexport function resolveServiceFrom(serviceMap, name, { appsRoot } = {}) {\n const svc = serviceMap[name];\n if (!svc) {\n throw new Error(`Unknown service \"${name}\". Known: ${Object.keys(serviceMap).join(\", \") || \"(none)\"}`);\n }\n return appsRoot ? { ...svc, appsRoot } : svc;\n}\n"],"mappings":"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","names":["resolve","mkdir","join","mkdir","join","join","access","cp","mkdir","join","pathExists","access","join","cp","mkdir","symlink","unlink","join","join","unlink","symlink","rm","readlink","readlink","rm","writeFile","join","join","writeFile","access","mkdir","readFile","writeFile","pathExists","access","mkdir","writeFile","readFile","readFile","writeFile","mkdir","join","readFile","join","mkdir","writeFile","access","appendFile","mkdir","writeFile","dirname","join","pathExists","access","join","dirname","mkdir","writeFile","appendFile","access","mkdir","readFile","writeFile","join","pathExists","access","join","mkdir","readFile","writeFile","access","pathExists","access","readlink","readlink","access","readFile","writeFile","homedir","tmpdir","basename","dirname","join","spawn","pathExists","access","expandHome","join","homedir","resolve","spawn","basename","run","dirname","readFile","tmpdir","writeFile"]}
|