infra-kit 0.5.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-63VNUKUS.js +8 -0
- package/dist/chunk-63VNUKUS.js.map +7 -0
- package/dist/chunk-7YE5QKKB.js +444 -0
- package/dist/chunk-7YE5QKKB.js.map +7 -0
- package/dist/chunk-GYPVEWUV.js +2 -0
- package/dist/chunk-GYPVEWUV.js.map +7 -0
- package/dist/chunk-KXQQUBGV.js +10 -0
- package/dist/{chunk-744Y674Y.js.map → chunk-KXQQUBGV.js.map} +4 -4
- package/dist/chunk-MFLYORUJ.js +2 -0
- package/dist/chunk-MFLYORUJ.js.map +7 -0
- package/dist/chunk-NFIFWIO6.js +4 -0
- package/dist/chunk-NFIFWIO6.js.map +7 -0
- package/dist/chunk-QS4JZKF2.js +2 -0
- package/dist/{chunk-YYEUJYC7.js.map → chunk-QS4JZKF2.js.map} +1 -1
- package/dist/chunk-UI2MUEVR.js +2 -0
- package/dist/chunk-UI2MUEVR.js.map +7 -0
- package/dist/{chunk-QUXDC3A3.js → chunk-YKCY657C.js} +4 -4
- package/dist/cli.js +11 -10
- package/dist/cli.js.map +3 -3
- package/dist/dev-server.js +22 -22
- package/dist/dev-server.js.map +3 -3
- package/dist/{dev-wizard-run-DWDA5R3A.js → dev-wizard-run-MCUYV6IN.js} +2 -2
- package/dist/mcp-proxy.js +9 -9
- package/dist/mcp-proxy.js.map +3 -3
- package/dist/mcp.js +2 -2
- package/dist/mcp.js.map +4 -4
- package/dist/update-check.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-744Y674Y.js +0 -10
- package/dist/chunk-LCNORKDV.js +0 -8
- package/dist/chunk-LCNORKDV.js.map +0 -7
- package/dist/chunk-PQG63EIV.js +0 -4
- package/dist/chunk-PQG63EIV.js.map +0 -7
- package/dist/chunk-XJOY7J3G.js +0 -2
- package/dist/chunk-XJOY7J3G.js.map +0 -7
- package/dist/chunk-XN7VHD7P.js +0 -445
- package/dist/chunk-XN7VHD7P.js.map +0 -7
- package/dist/chunk-Y5TLBGZT.js +0 -2
- package/dist/chunk-Y5TLBGZT.js.map +0 -7
- package/dist/chunk-YYEUJYC7.js +0 -2
- /package/dist/{chunk-QUXDC3A3.js.map → chunk-YKCY657C.js.map} +0 -0
- /package/dist/{dev-wizard-run-DWDA5R3A.js.map → dev-wizard-run-MCUYV6IN.js.map} +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import a from"node:path";var i="infra-kit",l=`${i}@latest`,_=(n,t)=>t===void 0?n:n.map(e=>e===l?`${i}@${t}`:e),g=(n,t,e)=>{let r=a.relative(e(a.resolve(n)),a.resolve(t));return r!==""&&!r.startsWith("..")&&!a.isAbsolute(r)},o=(n,t)=>a.resolve(n).split(a.sep).includes(t),h=(n,t)=>{let e=a.resolve(n).split(a.sep),r=e.indexOf("Cellar");return r!==-1&&e[r+1]===t},x=(n,t)=>{let e=a.resolve(n).split(a.sep),r=e.lastIndexOf("node_modules");return r<2||e[r-1]!=="lib"||e[r+1]!==t?null:e.slice(0,r-1).join(a.sep)||a.sep},w=n=>x(n,i),C=n=>["npm","install","-g","--prefix",n,l],N=n=>n.map(t=>t.includes(" ")?`'${t}'`:t).join(" "),m=(n,t,e,r)=>{let s=n[t];return s!=null&&s!==""&&g(s,e,r)},R=[{manager:"volta",test:({selfRealPath:n,env:t,realpath:e})=>m(t,"VOLTA_HOME",n,e)||o(n,".volta")||o(n,"volta"),updateCommand:["volta","install",i],canSelfSpawn:!0},{manager:"homebrew",test:({selfRealPath:n})=>h(n,i),updateCommand:["brew","upgrade",i],canSelfSpawn:!1}],O=[{manager:"pnpm",test:({selfRealPath:n,env:t,realpath:e})=>m(t,"PNPM_HOME",n,e)||o(n,"pnpm")&&o(n,"global"),updateCommand:["pnpm","add","-g",l],canSelfSpawn:!0},{manager:"bun",test:({selfRealPath:n,env:t,realpath:e})=>m(t,"BUN_INSTALL",n,e)||o(n,".bun"),updateCommand:["bun","add","-g",l],canSelfSpawn:!0},{manager:"yarn",test:({selfRealPath:n})=>o(n,".yarn")||o(n,"yarn")&&o(n,"global"),updateCommand:["yarn","global","add",l],canSelfSpawn:!0},{manager:"npm",test:({selfRealPath:n,env:t,realpath:e})=>m(t,"npm_config_prefix",n,e),updateCommand:["npm","install","-g",l],canSelfSpawn:!0}],M=["npm","install","-g",l],b=n=>{let{selfRealPath:t,env:e,realpath:r,lazyNpmRoot:s,version:p}=n,c=y({selfRealPath:t,env:e,realpath:r,lazyNpmRoot:s});return{...c,updateCommand:_(c.updateCommand,p)}},y=n=>{let{selfRealPath:t,env:e,realpath:r,lazyNpmRoot:s}=n,p=u=>({manager:u.manager,updateCommand:u.updateCommand,canSelfSpawn:u.canSelfSpawn}),c=({test:u})=>u({selfRealPath:t,env:e,realpath:r}),f=R.find(c);if(f)return p(f);let I=w(t);if(I!==null)return{manager:"npm",updateCommand:C(I),canSelfSpawn:!0};let S=O.find(c);if(S)return p(S);let d=s?.();return d!=null&&d!==""&&g(d,t,r)?{manager:"npm",updateCommand:M,canSelfSpawn:!0}:{manager:"unknown",updateCommand:M,canSelfSpawn:!1}},v=(n,t,e)=>o(n,"node_modules")&&g(t,n,e),A=32,T=n=>{let t=a.resolve(n).split(a.sep),e=t.indexOf("node_modules");return e===-1?a.dirname(n):t.slice(0,e).join(a.sep)||a.sep},F=(n,t)=>{let e=[],r=n;for(;r!==t&&e.length<A;){e.push(r);let s=a.dirname(r);if(s===r)break;r=s}return e},G=(n,t,e)=>F(n,t).some(r=>e(a.join(r,".git"))),E=n=>{try{let{selfRealPath:t,env:e,realpath:r,home:s,exists:p}=n;return b({selfRealPath:t,env:e,realpath:r}).manager==="unknown"?!1:!G(T(t),r(a.resolve(s)),p)}catch{return!1}},L=n=>{let{selfRealPath:t,cwd:e,realpath:r}=n;return!E(n)&&v(t,e,r)};import{realpathSync as k}from"node:fs";import D from"node:path";var W=n=>{try{return k(n)}catch{return D.resolve(n)}};import{execFileSync as j}from"node:child_process";import J from"node:process";var H=3e3,U=()=>{try{let t=j("npm",["root","-g"],{encoding:"utf-8",timeout:H,stdio:["ignore","pipe","ignore"],shell:J.platform==="win32"}).trim();return t===""?void 0:t}catch{return}};var P=n=>Object.fromEntries(Object.entries(n).filter(([t])=>!t.startsWith("npm_")&&t!=="PNPM_SCRIPT_SRC_DIR")),z=/^npm_config_(?:prefix|registry)$/i,K=n=>{let t=P(n);for(let[e,r]of Object.entries(n))z.test(e)&&(t[e]=r);return t};export{i as a,g as b,o as c,h as d,x as e,N as f,b as g,v as h,E as i,L as j,U as k,W as l,P as m,K as n};
|
|
2
|
+
//# sourceMappingURL=chunk-GYPVEWUV.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lib/install-manager/install-manager.ts", "../src/lib/install-manager/safe-realpath.ts", "../src/lib/install-manager/npm-root.ts", "../src/lib/pm-env/pm-env.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Pure detection of *how* this CLI was installed, so the background updater knows whether it may act at\n * all, and the advisory it prints can name the one command that will actually work. No fs, no spawn, no `process.env` read \u2014 every input is injected, which is\n * what lets the whole matrix be table-tested.\n *\n * Detection is env-first and LAZY: the only signal that costs a subprocess (`npm root -g`) is passed in\n * as `lazyNpmRoot` and consulted solely when every cheaper matcher has missed.\n */\nimport path from 'node:path'\n\n/** The published package this CLI updates itself to. Single source for every suggested argv. */\nexport const PACKAGE_NAME = 'infra-kit'\n\nconst LATEST = `${PACKAGE_NAME}@latest`\n\nexport type InstallManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'volta' | 'homebrew' | 'unknown'\n\nexport interface InstallManagerInfo {\n manager: InstallManager\n /** The command to run. Only safe to spawn ourselves when `canSelfSpawn`; otherwise print it. */\n updateCommand: string[]\n /** False when we must not run the command for the user \u2014 either it needs sudo/a tap, or we guessed. */\n canSelfSpawn: boolean\n}\n\n/**\n * Canonicalises a candidate *root* directory. Required, not optional: `selfRealPath` has already had its\n * symlinks followed, so comparing it against a raw `PNPM_HOME`/`npm root -g`/`cwd` compares a resolved\n * path to an unresolved one and silently never matches. macOS is the everyday proof \u2014 `/var` is a symlink\n * to `/private/var`, so a global install under `/var/...` reports `unknown` unless both sides are resolved.\n * Callers inject the real thing; tests inject a stub.\n */\nexport type RealpathFn = (dir: string) => string\n\nexport interface DetectInstallManagerInput {\n /** Fully-resolved (symlinks followed) path to this CLI's entry file. */\n selfRealPath: string\n env: NodeJS.ProcessEnv\n /** Canonicalises each candidate root before comparison. See {@link RealpathFn}. */\n realpath: RealpathFn\n /** `npm root -g`, deferred: invoked at most once, and only when no cheaper matcher hit. */\n lazyNpmRoot?: () => string | undefined\n /**\n * The exact version to install, when the caller has already resolved it. Omitted, the command targets\n * the `latest` dist-tag \u2014 fine to PRINT, unsafe to RUN: see {@link pinSpec}.\n */\n version?: string\n}\n\n/**\n * Swap the `@latest` token for `@<version>`.\n *\n * `pnpm add -g infra-kit@latest` resolves the tag from pnpm's on-disk metadata cache and does not\n * revalidate it when a cached version already satisfies the tag (pnpm 12.3.4, measured: two runs 90+\n * minutes after a publish both reinstalled the stale `latest` while `pnpm view` already reported the new\n * one). The updater had fetched the real latest itself moments earlier, ran the tag command, got exit 0\n * \u2014 nothing was reinstalled \u2014 and recorded `installed`, so the stale binary looked up to date until the\n * next cycle repeated the same no-op. A concrete version the cache has never seen forces the fetch.\n */\nconst pinSpec = (command: string[], version: string | undefined): string[] => {\n if (version === undefined) return command\n\n return command.map((token) => {\n return token === LATEST ? `${PACKAGE_NAME}@${version}` : token\n })\n}\n\n/**\n * Is `child` inside the `parent` subtree? Boundary-aware: a naive `startsWith` would call\n * `/Users/x/pnpm-ish` a child of `/Users/x/pnpm`. `parent` is canonicalised first because it arrives raw\n * from the environment while `child` is already a realpath.\n */\nexport const isWithin = (parent: string, child: string, realpath: RealpathFn): boolean => {\n const rel = path.relative(realpath(path.resolve(parent)), path.resolve(child))\n\n return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel)\n}\n\n/** Does `p` contain `name` as a whole path SEGMENT? `/a/node_modules_backup/b` must not match `node_modules`. */\nexport const hasSegment = (p: string, name: string): boolean => {\n return path.resolve(p).split(path.sep).includes(name)\n}\n\n/**\n * Is `p` inside a Homebrew keg belonging to the `name` FORMULA \u2014 i.e. `.../Cellar/<name>/<version>/...`?\n *\n * The formula name is what makes this sound. A bare `Cellar` segment says only \"somewhere under a keg\",\n * and the keg it lands in is routinely someone else's: when npm's global prefix is a node keg\n * (`npm config set prefix \"$(brew --prefix node)\"`, or any keg-only `node@X`), an `npm i -g` package\n * installs to `Cellar/node/<v>/lib/node_modules/<pkg>/...` \u2014 brew has never heard of it, yet the segment\n * is right there. Requiring `<name>` to sit directly after `Cellar` is what separates \"brew installed\n * THIS\" from \"brew installed the runtime that installed this\".\n *\n * Works for both keg layouts, since each is rooted at the formula: a plain formula\n * (`Cellar/infra-kit/1.2.3/bin/infra-kit`) and brew's node-CLI layout\n * (`Cellar/infra-kit/1.2.3/libexec/lib/node_modules/infra-kit/dist/cli.js`). Do NOT try to tell them\n * apart by excluding `node_modules` \u2014 the second one contains it.\n */\nexport const isBrewKegOf = (p: string, name: string): boolean => {\n const segments = path.resolve(p).split(path.sep)\n const cellar = segments.indexOf('Cellar')\n\n return cellar !== -1 && segments[cellar + 1] === name\n}\n\n/**\n * The npm global prefix that owns `binRealPath`, derived from the path ITSELF, or null when the\n * layout is not an npm global one.\n *\n * Matches `<prefix>/lib/node_modules/<packageName>` \u2014 npm's global layout and no other manager's\n * \u2014 requiring BOTH the `lib` parent and our package as the immediate child. Windows global npm has\n * no `lib` segment (`%APPDATA%\\npm\\node_modules`), so this returns null there and detection falls\n * through to `npm root -g`, which is correct on Windows, where there is normally one npm.\n */\n// This is the one signal that cannot point at the wrong tree. Everything else in this module\n// answers \"is this file somewhere inside tool X's directory?\", and containment is not ownership:\n// - `npm root -g` answers for whichever `npm` is first on PATH, which is routinely a DIFFERENT\n// node than the one that installed us (a pnpm/nvm/fnm-managed node, or a node that has since\n// been removed). It then reports a root that does not contain us, every matcher misses, and\n// detection degrades to `unknown` \u2014 a notice printed forever, on the single most common install\n// method. That is the bug this exists to close.\n// - `PNPM_HOME` containment is satisfied by `<PNPM_HOME>/nodejs/<v>/lib/node_modules/<pkg>` (a\n// plain `npm i -g` under a pnpm-managed node), yet `pnpm add -g` installs to\n// `<PNPM_HOME>/global/<v>/...` \u2014 a different directory. That one is worse than a missed update:\n// the install \"succeeds\" while the binary on PATH stays old, silently, with no notice to show\n// for it.\n//\n// Requiring both segments is what makes the match proof rather than a hint. The `lib` requirement\n// is also what keeps a project-local `<repo>/node_modules/<pkg>` out (it has no `lib`), and nesting\n// cannot spoof it: `.../node_modules/foo/node_modules/<pkg>` fails the `lib` test.\nexport const npmPrefixOfPackage = (binRealPath: string, packageName: string): string | null => {\n const segments = path.resolve(binRealPath).split(path.sep)\n const nodeModules = segments.lastIndexOf('node_modules')\n\n if (nodeModules < 2) return null\n if (segments[nodeModules - 1] !== 'lib') return null\n if (segments[nodeModules + 1] !== packageName) return null\n\n // Drop `lib/node_modules/...`; the empty result of a root-level prefix (`/lib/node_modules/...`) is `/`.\n return segments.slice(0, nodeModules - 1).join(path.sep) || path.sep\n}\n\n// The self-scoped reading, kept as the name every call site below already uses. `dependency-registry`\n// asks the same question about OTHER packages (`portless`), which is why the body moved up one level\n// rather than gaining a defaulted parameter \u2014 a default is how the wrong package silently gets probed.\nconst npmPrefixFromSelfPath = (selfRealPath: string): string | null => {\n return npmPrefixOfPackage(selfRealPath, PACKAGE_NAME)\n}\n\n/**\n * `--prefix` is passed EXPLICITLY rather than trusting the ambient one: the whole point of deriving it is\n * that the `npm` we are about to run may default to a different prefix than the one we are installed in.\n * A command-line flag outranks both `npm_config_prefix` and any `.npmrc`, so this targets the tree we\n * actually run from. With `-g`, npm writes `<prefix>/lib/node_modules` and links bins into `<prefix>/bin`.\n */\nconst npmPrefixInstallCommand = (prefix: string): string[] => {\n return ['npm', 'install', '-g', '--prefix', prefix, LATEST]\n}\n\n/**\n * Render argv as a line the user can paste into a shell.\n *\n * A plain `join(' ')` was fine while every token came from a static table; `--prefix <path>` puts a\n * filesystem path in argv, and `/Users/Ada Lovelace/.nvm/...` pasted unquoted is two arguments and a\n * failed install. Single quotes are sound here without escaping because the callers' validation rejects a\n * token containing a quote \u2014 see `SAFE_COMMAND_TOKEN` in src/lib/update-check/auto-update.ts.\n *\n * @example\n * formatUpdateCommand(['npm', 'install', '-g', '--prefix', '/opt/x y', 'infra-kit@latest'])\n * // => \"npm install -g --prefix '/opt/x y' infra-kit@latest\"\n */\nexport const formatUpdateCommand = (command: string[]): string => {\n return command\n .map((token) => {\n return token.includes(' ') ? `'${token}'` : token\n })\n .join(' ')\n}\n\n/** `env[key]` names a directory that contains `selfRealPath`. Absent/empty env var \u2192 no match. */\nconst underEnvDir = (env: NodeJS.ProcessEnv, key: string, selfRealPath: string, realpath: RealpathFn): boolean => {\n const dir = env[key]\n\n return dir != null && dir !== '' && isWithin(dir, selfRealPath, realpath)\n}\n\ninterface Matcher extends Omit<InstallManagerInfo, 'manager'> {\n manager: InstallManager\n test: (input: Required<Pick<DetectInstallManagerInput, 'selfRealPath' | 'env' | 'realpath'>>) => boolean\n}\n\n/**\n * Consulted FIRST, before {@link npmPrefixFromSelfPath}. Both of these legitimately wrap an npm-shaped\n * `lib/node_modules` tree \u2014 volta at `~/.volta/tools/image/node/<v>/lib/node_modules`, brew at\n * `Cellar/<pkg>/<v>/libexec/lib/node_modules` \u2014 so deriving an npm prefix from the path would hijack\n * installs that a wrapper owns and must keep owning.\n */\nconst WRAPPER_MATCHERS: Matcher[] = [\n {\n manager: 'volta',\n // volta owns the shim; `volta install` is the correct tool, not a workaround \u2014 so we may run it.\n test: ({ selfRealPath, env, realpath }) => {\n return (\n underEnvDir(env, 'VOLTA_HOME', selfRealPath, realpath) ||\n hasSegment(selfRealPath, '.volta') ||\n hasSegment(selfRealPath, 'volta')\n )\n },\n updateCommand: ['volta', 'install', PACKAGE_NAME],\n canSelfSpawn: true,\n },\n {\n manager: 'homebrew',\n // `brew upgrade` can touch the prefix, relink, and prompt \u2014 never ours to run unattended.\n //\n // Our own keg is the ONLY sound signal \u2014 see `isBrewKegOf`. Two broader tests look plausible\n // and are both wrong, because each answers \"did brew put something here?\" when the question is \"does\n // brew own THIS package?\":\n // - `HOMEBREW_PREFIX` containment: when node comes from brew, npm's global prefix IS\n // $HOMEBREW_PREFIX, so EVERY `npm i -g` package lands under it, unknown to brew.\n // - a bare `Cellar` segment: an npm prefix pointed at a node keg puts packages inside that keg.\n // Either misfire tells macOS users to run `brew upgrade infra-kit` \u2014 a formula that does not exist \u2014\n // and, far worse, makes the background auto-updater bail with `cannot-self-spawn` forever, so the\n // very fix for it can never reach them. Detection runs on the realpath, and a linked brew bin always\n // resolves into its own keg, so the narrow test has no false negatives to trade for this.\n test: ({ selfRealPath }) => {\n return isBrewKegOf(selfRealPath, PACKAGE_NAME)\n },\n updateCommand: ['brew', 'upgrade', PACKAGE_NAME],\n canSelfSpawn: false,\n },\n]\n\n/**\n * Consulted LAST, after {@link npmPrefixFromSelfPath} has had its say. Each of these proves only that we\n * live somewhere inside a tool's directory tree, which is weaker than knowing the layout npm itself\n * created \u2014 see the `PNPM_HOME`/`nodejs` case in that helper's doc for a containment hit whose install\n * command targets the wrong directory.\n */\nconst TREE_MATCHERS: Matcher[] = [\n {\n manager: 'pnpm',\n test: ({ selfRealPath, env, realpath }) => {\n return (\n underEnvDir(env, 'PNPM_HOME', selfRealPath, realpath) ||\n (hasSegment(selfRealPath, 'pnpm') && hasSegment(selfRealPath, 'global'))\n )\n },\n updateCommand: ['pnpm', 'add', '-g', LATEST],\n canSelfSpawn: true,\n },\n {\n manager: 'bun',\n test: ({ selfRealPath, env, realpath }) => {\n return underEnvDir(env, 'BUN_INSTALL', selfRealPath, realpath) || hasSegment(selfRealPath, '.bun')\n },\n updateCommand: ['bun', 'add', '-g', LATEST],\n canSelfSpawn: true,\n },\n {\n manager: 'yarn',\n test: ({ selfRealPath }) => {\n return (\n hasSegment(selfRealPath, '.yarn') || (hasSegment(selfRealPath, 'yarn') && hasSegment(selfRealPath, 'global'))\n )\n },\n updateCommand: ['yarn', 'global', 'add', LATEST],\n canSelfSpawn: true,\n },\n {\n manager: 'npm',\n test: ({ selfRealPath, env, realpath }) => {\n return underEnvDir(env, 'npm_config_prefix', selfRealPath, realpath)\n },\n updateCommand: ['npm', 'install', '-g', LATEST],\n canSelfSpawn: true,\n },\n]\n\nconst NPM_UPDATE_COMMAND = ['npm', 'install', '-g', LATEST]\n\n/**\n * Identify the package manager that owns `selfRealPath`.\n *\n * Order, and why it is this one: wrappers that own an npm-shaped tree (volta, brew) first, then the npm\n * prefix DERIVED from our own path, then the env/path containment matchers, then the `npm root -g` probe.\n * The derived prefix sits above containment because it is the only signal that cannot name a directory we\n * do not live in \u2014 see {@link npmPrefixFromSelfPath}.\n *\n * `lazyNpmRoot` is the last resort and is invoked at most once, only after every matcher has missed \u2014 a\n * pnpm or volta install never pays for the subprocess, and neither does any npm global install in the\n * standard layout, which the derived prefix now settles for free. When nothing matches we report `unknown`\n * with an npm command that is a *suggestion only* (`canSelfSpawn: false`): running a guessed global\n * install is worse than printing one.\n *\n * @example\n * detectInstallManager({ selfRealPath: '/Users/x/Library/pnpm/global/5/node_modules/infra-kit/dist/cli.js', env: {} })\n * // => { manager: 'pnpm', updateCommand: ['pnpm', 'add', '-g', 'infra-kit@latest'], canSelfSpawn: true }\n * detectInstallManager({ selfRealPath: '/Users/x/Library/pnpm/global/5/node_modules/infra-kit/dist/cli.js', env: {}, version: '0.5.5' })\n * // => { manager: 'pnpm', updateCommand: ['pnpm', 'add', '-g', 'infra-kit@0.5.5'], canSelfSpawn: true }\n */\nexport const detectInstallManager = (input: DetectInstallManagerInput): InstallManagerInfo => {\n const { selfRealPath, env, realpath, lazyNpmRoot, version } = input\n const detected = detectUnpinned({ selfRealPath, env, realpath, lazyNpmRoot })\n\n return { ...detected, updateCommand: pinSpec(detected.updateCommand, version) }\n}\n\nconst detectUnpinned = (input: DetectInstallManagerInput): InstallManagerInfo => {\n const { selfRealPath, env, realpath, lazyNpmRoot } = input\n const toInfo = (hit: Matcher): InstallManagerInfo => {\n return { manager: hit.manager, updateCommand: hit.updateCommand, canSelfSpawn: hit.canSelfSpawn }\n }\n const matches = ({ test }: Matcher): boolean => {\n return test({ selfRealPath, env, realpath })\n }\n\n const wrapper = WRAPPER_MATCHERS.find(matches)\n\n if (wrapper) return toInfo(wrapper)\n\n const derivedPrefix = npmPrefixFromSelfPath(selfRealPath)\n\n if (derivedPrefix !== null) {\n return { manager: 'npm', updateCommand: npmPrefixInstallCommand(derivedPrefix), canSelfSpawn: true }\n }\n\n const tree = TREE_MATCHERS.find(matches)\n\n if (tree) return toInfo(tree)\n\n const npmRoot = lazyNpmRoot?.()\n\n if (npmRoot != null && npmRoot !== '' && isWithin(npmRoot, selfRealPath, realpath)) {\n return { manager: 'npm', updateCommand: NPM_UPDATE_COMMAND, canSelfSpawn: true }\n }\n\n return { manager: 'unknown', updateCommand: NPM_UPDATE_COMMAND, canSelfSpawn: false }\n}\n\n/**\n * Is this CLI running from a *project-local* `node_modules` (as opposed to a global root)?\n *\n * The cwd clause is what does the distinguishing \u2014 BOTH a project install and a global root contain a\n * `/node_modules/` segment (`pnpm root -g` is `~/Library/pnpm/global/5/node_modules`). Without it we\n * would nag every global pnpm user to stop using a local install they do not have.\n *\n * Accepted false-negative: invoked from a subdirectory (cwd `project/apps/x`, deps at\n * `project/node_modules`) this returns false and the advisory stays silent. Under-warning is the safe\n * direction for a best-effort, never-throwing advisory \u2014 do not \"fix\" it by dropping the cwd clause.\n *\n * `cwd` is canonicalised before comparison for the same reason `detectInstallManager` canonicalises its\n * roots: `selfRealPath` is a realpath, and comparing it to an unresolved cwd never matches.\n *\n * @example\n * isLocalNodeModulesInstall('/repo/node_modules/infra-kit/dist/cli.js', '/repo', (p) => p) // => true\n */\nexport const isLocalNodeModulesInstall = (selfRealPath: string, cwd: string, realpath: RealpathFn): boolean => {\n return hasSegment(selfRealPath, 'node_modules') && isWithin(cwd, selfRealPath, realpath)\n}\n\n/** Does this path exist at all \u2014 directory, file, or symlink? Injected so the walk never touches the real disk in tests. */\nexport type ExistsFn = (p: string) => boolean\n\nexport interface IsGlobalInstallInput {\n /** Fully-resolved (symlinks followed) path to this CLI's entry file. */\n selfRealPath: string\n env: NodeJS.ProcessEnv\n /** Canonicalises `home` and every root {@link detectInstallManager} compares against. */\n realpath: RealpathFn\n /** The user's home directory (`os.homedir()`), raw \u2014 canonicalised here before the walk compares it. */\n home: string\n exists: ExistsFn\n}\n\n/** Upper bound on the `.git` walk: deeper than any real install layout, so it only ever guards against a pathological path. */\nconst GIT_WALK_MAX_HOPS = 32\n\n/**\n * Where the `.git` walk starts: the parent of the OUTERMOST `node_modules` segment (`indexOf`, not\n * `lastIndexOf` \u2014 pnpm's `.pnpm/<pkg>@<v>/node_modules/<pkg>` nests two, and the checkout that owns the\n * tree sits above the first). A self path with no `node_modules` at all (a plain brew keg's `bin/`) starts\n * at its own directory, so the walk still inspects every ancestor.\n */\nconst gitWalkStart = (selfRealPath: string): string => {\n const segments = path.resolve(selfRealPath).split(path.sep)\n const outermost = segments.indexOf('node_modules')\n\n if (outermost === -1) return path.dirname(selfRealPath)\n\n return segments.slice(0, outermost).join(path.sep) || path.sep\n}\n\n/** `start` and its ancestors up to but EXCLUDING `homeReal`, bounded \u2014 the directories the `.git` walk may inspect. */\nconst ancestorsBelowHome = (start: string, homeReal: string): string[] => {\n const dirs: string[] = []\n let dir = start\n\n while (dir !== homeReal && dirs.length < GIT_WALK_MAX_HOPS) {\n dirs.push(dir)\n\n const parent = path.dirname(dir)\n\n if (parent === dir) break\n\n dir = parent\n }\n\n return dirs\n}\n\nconst hasGitAncestor = (start: string, homeReal: string, exists: ExistsFn): boolean => {\n return ancestorsBelowHome(start, homeReal).some((dir) => {\n return exists(path.join(dir, '.git'))\n })\n}\n\n/**\n * Is this CLI the machine's *global* install \u2014 the one a root-owned daemon or a system-wide link may be\n * aimed at \u2014 as opposed to a checkout or a project-local dependency? Probe-free: fs + env only, never a\n * subprocess, because it runs on every boot.\n *\n * True iff {@link detectInstallManager} names a manager AND no `.git` entry (directory or file \u2014 a\n * worktree's is a file) exists above the outermost `node_modules`, walking up to but EXCLUDING\n * `realpath(home)`. Never throws: any seam failure reports false, the safe direction for every caller.\n *\n * @example\n * isGlobalInstall({\n * selfRealPath: '/Users/x/Library/pnpm/global/v11/8a83-1/node_modules/.pnpm/infra-kit@0.5.6/node_modules/infra-kit/dist/cli.js',\n * env: { PNPM_HOME: '/Users/x/Library/pnpm' },\n * realpath: (p) => p,\n * home: '/Users/x',\n * exists: (p) => p === '/Users/x/.git',\n * }) // => true \u2014 the only `.git` is $HOME's own, which the walk never inspects\n */\n// Why these two predicates and not the obvious candidates:\n// - Not `canSelfSpawn`: that flag encodes \"may I run an unattended `npm i -g`\", and homebrew is\n// `canSelfSpawn: false` while being unmistakably global \u2014 gating on it would leave a brew install\n// unconverged forever. A global install whose manager cannot be identified in a stripped env (no\n// `PNPM_HOME`, no derivable prefix) reports false: fail-safe, since a skipped write is never wrong and\n// the next shell-run command converges it.\n// - Not `isLocalNodeModulesInstall`: its cwd clause calls every global layout under `$HOME` \"local\" the\n// moment cwd is `$HOME` \u2014 which is exactly the cwd the background updater spawns with, and a plain\n// `cd ~ && infra-kit version` reproduces it. This predicate reads the tree, not the cwd.\n// - Why the `.git` walk at all: the cheap matchers are segment heuristics that also fire on\n// project-local shapes \u2014 a repo with a `volta` path segment, Yarn Berry's `.yarn/unplugged/\u2026`, a\n// checkout cloned under `$PNPM_HOME`, a workspace package literally named `lib` \u2014 and every one of\n// those is a checkout; every checkout has a `.git`, no global root does.\n// - Why `$HOME` is excluded: dotfiles users `git init ~`, and a `~/.git` would refuse the pnpm-global\n// install permanently. Every checkout under `$HOME` (`~/repo/.git`) is still strictly below it.\n// - Why `.git` ONLY, not `pnpm-workspace.yaml`: pnpm 12 writes one INSIDE the global install dir, so\n// that marker would refuse the very install this is for.\nexport const isGlobalInstall = (input: IsGlobalInstallInput): boolean => {\n try {\n const { selfRealPath, env, realpath, home, exists } = input\n\n if (detectInstallManager({ selfRealPath, env, realpath }).manager === 'unknown') return false\n\n return !hasGitAncestor(gitWalkStart(selfRealPath), realpath(path.resolve(home)), exists)\n } catch {\n return false\n }\n}\n\n/**\n * The advisory gate for `warnIfLocalInstall`, pulled out so it is testable without spawning the CLI.\n * Warn only when the install is provably NOT global AND looks project-local: the second clause alone\n * fires on a global pnpm root whenever cwd is `$HOME` (see {@link isGlobalInstall}).\n */\nexport const shouldWarnLocalInstall = (input: IsGlobalInstallInput & { cwd: string }): boolean => {\n const { selfRealPath, cwd, realpath } = input\n\n return !isGlobalInstall(input) && isLocalNodeModulesInstall(selfRealPath, cwd, realpath)\n}\n", "import { realpathSync } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * The impure companion to the pure detection module: canonicalise a directory that may not exist.\n *\n * `realpathSync` throws on a missing path, and candidate roots routinely miss \u2014 `PNPM_HOME` can point at a\n * directory the user never created, `npm root -g` can name a prefix that was removed. A throw there would\n * turn \"we could not identify your install\" into a crash, so an unresolvable path falls back to\n * `path.resolve`, which still normalises `.`/`..` and yields a usable, non-matching absolute path.\n */\nexport const safeRealpath = (dir: string): string => {\n try {\n return realpathSync(dir)\n } catch {\n return path.resolve(dir)\n }\n}\n", "/* eslint-disable sonarjs/no-os-command-from-path */\n/**\n * `npm root -g`, the LAZY fallback for {@link detectInstallManager}.\n *\n * Why it is indispensable: the `npm` matcher keys off `npm_config_prefix`, which npm sets only while npm\n * itself is running. A user who ran `npm i -g infra-kit` months ago and now types `ik` has no such var,\n * so every cheap matcher misses and detection reports `unknown` / `canSelfSpawn: false`. Without this\n * probe the single most common install method can never update itself.\n *\n * Read by the background update worker, and by the `doctor` advisory that names the command a human\n * would run by hand \u2014 one probe so the two can never disagree about who owns the install.\n */\nimport { execFileSync } from 'node:child_process'\nimport process from 'node:process'\n\nconst NPM_ROOT_TIMEOUT_MS = 3_000\n\n/**\n * The global npm root, or undefined when npm is absent, slow, or errors. Costs a subprocess, so\n * `detectInstallManager` invokes it at most once and only after every env/path matcher has missed \u2014 a\n * pnpm or volta install never pays for it.\n *\n * Resolving the user's `npm` from PATH is inherent here: we must ask the very package manager that owns\n * this install where its global root is. Pinning an absolute path would defeat the detection.\n *\n * @example\n * defaultLazyNpmRoot() // => '/usr/local/lib/node_modules' | undefined\n */\nexport const defaultLazyNpmRoot = (): string | undefined => {\n try {\n const out = execFileSync('npm', ['root', '-g'], {\n encoding: 'utf-8',\n timeout: NPM_ROOT_TIMEOUT_MS,\n stdio: ['ignore', 'pipe', 'ignore'],\n shell: process.platform === 'win32',\n })\n const trimmed = out.trim()\n\n return trimmed === '' ? undefined : trimmed\n } catch {\n return undefined\n }\n}\n", "/**\n * `env` minus every package-manager marker a spawned child could mistake for a throwaway install:\n * the whole `npm_*` block plus `PNPM_SCRIPT_SRC_DIR`. The result makes the child look exactly like\n * a direct `node <pkg>/dist/cli.js` run \u2014 which it is.\n */\n// Any child we launch through `node <bin>` (the portless driver, the update worker, the mcp launcher)\n// inherits our env, and a tool that sniffs those markers will conclude it was run via `npx`/`pnpm\n// dlx` and refuse to work. portless is the motivating case; its guard (cli.js `main()`) is:\n//\n// isNpx = npm_command === 'exec' && !npm_lifecycle_event\n// isPnpmDlx = !!PNPM_SCRIPT_SRC_DIR && !npm_lifecycle_event\n// if ((isNpx || isPnpmDlx) && !isLocallyInstalled()) -> abort\n//\n// `isLocallyInstalled()` walks up from the CHILD's cwd, so in a consumer repo (where portless is a\n// transitive dep of infra-kit, absent from the root `node_modules`) it is false and the guard is\n// live. `pnpm exec infra-kit dev` exports `npm_command=exec` with no lifecycle event, so `isNpx`\n// holds, every portless call exits 1, `isAvailable()` is false, and `ensureProxy` aborts the whole\n// dev boot with \"portless is not installed\", on a machine where it plainly is.\n//\n// `PNPM_SCRIPT_SRC_DIR` must be dropped ALONGSIDE the `npm_*` block, not left behind: it is set by\n// `pnpm run <script>`, where `npm_lifecycle_event` is what suppresses `isPnpmDlx`. Stripping only\n// `npm_*` removes that suppressor and creates an abort for the script-style invocation that\n// previously worked. Both markers go, or neither is safe.\nexport const withoutPackageManagerEnv = (env: NodeJS.ProcessEnv): NodeJS.ProcessEnv => {\n return Object.fromEntries(\n Object.entries(env).filter(([key]) => {\n return !key.startsWith('npm_') && key !== 'PNPM_SCRIPT_SRC_DIR'\n }),\n )\n}\n\n/**\n * npm's own configuration \u2014 as opposed to the npx/dlx *markers* above. Case-insensitive because npm reads\n * `npm_config_*` case-insensitively (its parser matches `/^npm_config_/i`) and real environments export\n * both forms: shells write the lowercase name, Dockerfiles and CI images overwhelmingly write the\n * uppercase one.\n */\nconst NPM_CONFIG_TO_PRESERVE = /^npm_config_(?:prefix|registry)$/i\n\n/**\n * The env for spawning a package-manager INSTALL: npx/dlx markers stripped, but npm's own config\n * kept \u2014 specifically `npm_config_prefix` and `npm_config_registry`.\n *\n * @example\n * packageManagerInstallEnv({ npm_command: 'exec', npm_config_prefix: '/p', PATH: '/bin' })\n * // => { npm_config_prefix: '/p', PATH: '/bin' }\n */\n// `withoutPackageManagerEnv` is deliberately a blunt `npm_*` prefix filter, and it is the\n// right tool for the portless driver \u2014 but it is the WRONG tool for spawning an install, because it\n// also drops the two variables that tell the package manager where, and from where, to install:\n//\n// - `npm_config_prefix` is the npm matcher's ONLY signal (see `install-manager.ts`). Strip it and\n// we detect a global install rooted at prefix P, then run the install with P erased \u2014 so it\n// lands in the DEFAULT prefix instead. That is either a permanent EACCES, or a second global\n// copy that is not the one on PATH. Nothing notices: the install exits 0, we report\n// `installed`, the version on PATH never moves, and the whole cycle repeats every window\n// forever. `export npm_config_prefix=~/.npm-global` is npm's own documented EACCES workaround,\n// so this is a mainstream layout, not an exotic one.\n// - `npm_config_registry` is what the update CHECK already used to pick a registry. Dropping it\n// here means we decide against a corporate mirror and then install from somewhere else.\n//\n// Preserving these cannot re-arm the dlx guard: that guard reads `npm_command`,\n// `npm_lifecycle_event` and `PNPM_SCRIPT_SRC_DIR` \u2014 none of which are npm config, and all of which\n// remain stripped.\nexport const packageManagerInstallEnv = (env: NodeJS.ProcessEnv): NodeJS.ProcessEnv => {\n const sanitised = withoutPackageManagerEnv(env)\n\n for (const [key, value] of Object.entries(env)) {\n if (NPM_CONFIG_TO_PRESERVE.test(key)) sanitised[key] = value\n }\n\n return sanitised\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path", "PACKAGE_NAME", "LATEST", "pinSpec", "command", "version", "token", "isWithin", "parent", "child", "realpath", "rel", "hasSegment", "p", "name", "isBrewKegOf", "segments", "cellar", "npmPrefixOfPackage", "binRealPath", "packageName", "nodeModules", "npmPrefixFromSelfPath", "selfRealPath", "npmPrefixInstallCommand", "prefix", "formatUpdateCommand", "underEnvDir", "env", "key", "dir", "WRAPPER_MATCHERS", "TREE_MATCHERS", "NPM_UPDATE_COMMAND", "detectInstallManager", "input", "lazyNpmRoot", "detected", "detectUnpinned", "toInfo", "hit", "matches", "test", "wrapper", "derivedPrefix", "tree", "npmRoot", "isLocalNodeModulesInstall", "cwd", "GIT_WALK_MAX_HOPS", "gitWalkStart", "outermost", "ancestorsBelowHome", "start", "homeReal", "dirs", "hasGitAncestor", "exists", "isGlobalInstall", "home", "shouldWarnLocalInstall", "realpathSync", "path", "safeRealpath", "dir", "execFileSync", "process", "NPM_ROOT_TIMEOUT_MS", "defaultLazyNpmRoot", "trimmed", "withoutPackageManagerEnv", "env", "key", "NPM_CONFIG_TO_PRESERVE", "packageManagerInstallEnv", "sanitised", "value"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{K as l,P as W,R as I,da as O,g as D,m as M}from"./chunk-63VNUKUS.js";import{execFile as rr,execFileSync as er}from"node:child_process";import d from"node:process";var tr=5e3,or=100,J=2e3,F="/bin/ps",nr=1e3,j=["-eo","pid=,ppid=,pgid=,lstart="],U=8<<20,q=r=>r.split(`
|
|
2
|
+
`).flatMap(e=>{let[t,o,n,...i]=e.trim().split(/\s+/);if(t==null||o==null||n==null)return[];let s=Number(t),c=Number(o),u=Number(n);return!Number.isInteger(s)||!Number.isInteger(c)||!Number.isInteger(u)?[]:[{pid:s,ppid:c,pgid:u,lstart:i.join(" ")}]}),K=r=>{let e=new Map;for(let t of r)t.pid===t.pgid&&e.set(t.pgid,t.lstart);return e},sr=(r,e,t)=>{let o=K(e);return X(r,e,t).flatMap(n=>{let i=o.get(n);return i==null||i===""?[]:[{pgid:n,leaderStart:i}]})},H=(r,e)=>{let t=K(e);return r.flatMap(({pgid:o,leaderStart:n})=>t.get(o)===n?[o]:[])},B=(r,e)=>H(r,e).flatMap(t=>{try{d.kill(-t,"SIGKILL")}catch{return[]}return[t]}),X=(r,e,t)=>{let o=new Map;for(let c of e){let u=o.get(c.ppid);u?u.push(c):o.set(c.ppid,[c])}let n=new Set([r]),i=new Set([r]),s=[r];for(let c=0;c<s.length;c+=1)for(let u of o.get(s[c]??-1)??[])i.has(u.pid)||(i.add(u.pid),n.add(u.pgid),s.push(u.pid));return[...n].filter(c=>c>1&&c!==t)},R=()=>{try{return q(er(F,[...j],{encoding:"utf8",maxBuffer:U}))}catch{return[]}},ir=async()=>new Promise(r=>{rr(F,[...j],{encoding:"utf8",maxBuffer:U},(e,t)=>{r(e?[]:q(t))})}),ar=(r,e,t)=>t.some(o=>o.pid===r&&o.ppid===e),E=(r,e)=>{let t=e.find(o=>o.pid===d.pid)?.pgid;return X(r,e,t)},Q=r=>{try{return d.kill(-r,0),!0}catch{return!1}},N=(r,e)=>{for(let t of r)try{d.kill(-t,e)}catch{}},x=new Set,cr=(r,e,t)=>{let o=E(r,e),n=t.flatMap(i=>H(i,e));return[...new Set([...o,...n])]},V=()=>{let r=R(),e=[...x].map(t=>t());N(cr(d.pid,r,e),"SIGKILL")},ur=async r=>new Promise(e=>{setTimeout(e,r)}),C=async(r,e)=>{let t=Date.now()+e,o=r;for(;o.length>0&&Date.now()<t&&(o=o.filter(Q),o.length!==0);)await ur(or);return o};function Jr(r,e=tr,t,o=R){r.unref();let n=!1,i=!1,s=[],c=null,u=()=>s;x.add(u);let m=()=>{c&&clearInterval(c),c=null},g=async()=>{await C(s.map(a=>a.pgid),J),x.delete(u)},f=a=>{let p=r.pid;if(p==null||i||n||a.length===0)return;let P=a.find(v=>v.pid===d.pid)?.pgid,k=sr(p,a,P);k.length>0&&(s=k)},w=async()=>{r.pid==null||i||n||f(await ir())};f(R()),c=setInterval(()=>{w()},nr),c.unref();let S=a=>{n||t?.(a)};return r.on("exit",(a,p)=>{i=!0,m(),n||(B(s,o()),g()),S(`exited unexpectedly (code=${a??"null"}, signal=${p??"null"})`)}),r.on("error",a=>{S(`failed to spawn: ${a.message}`)}),{kill:async()=>{n=!0,m();let a=r.pid;if(a==null){x.delete(u);return}if(r.exitCode!==null||r.signalCode!==null){B(s,o()),await g();return}let p=o();if(p.length>0&&!ar(a,d.pid,p))return;let P=E(a,p);N(P,"SIGTERM");let k=await C(P,e);if(k.length===0){x.delete(u);return}let v=E(a,o()),_=[...new Set([...k,...v])].filter(Q);N(_,"SIGKILL"),await C(_,J),x.delete(u)}}}import{constants as pr}from"node:os";import h from"node:process";var lr=["SIGINT","SIGTERM","SIGHUP"],dr=pr.signals,mr=2,L=r=>128+(dr[r]??mr),gr=2e4,fr=r=>{h.exit(r)},wr=(r,e)=>{h.on(r,e)},xr=(r,e)=>{h.off(r,e)},yr=(r,e)=>{let t=setTimeout(r,e);return t.unref(),()=>{clearTimeout(t)}},G=r=>{try{h.stderr.write(r)}catch{}},kr=(r,e)=>{let t=e instanceof Error?`${e.message}
|
|
3
|
+
${e.stack??"(no stack)"}`:String(e);G(`
|
|
4
|
+
\u2717 Teardown failed while handling ${r}: ${t}
|
|
5
|
+
`)},qr=({onSignal:r,exit:e=fr,register:t=wr,unregister:o=xr,forceReap:n=V,teardownDeadlineMs:i=gr,setTimer:s=yr,describeStall:c=()=>"unknown",fileReport:u=()=>{}})=>{let m=null,g=null,f=new Map,w=()=>{for(let[a,p]of f)o(a,p);f.clear()},S=a=>{if(m!==null){if(a!==m)return;G(`
|
|
6
|
+
\u26A0 Received ${a} again \u2014 force-quitting.
|
|
7
|
+
`),g?.(),n(),w(),e(L(a));return}m=a,g=s(()=>{let p=`
|
|
8
|
+
\u26A0 Teardown deadline exceeded at stage=${c()} after ${i}ms \u2014 force-quitting.
|
|
9
|
+
`;G(p),u(p),n(),w(),e(L(a))},i),(async()=>{try{await r(a)}catch(p){kr(a,p)}finally{g?.(),w(),e(L(a))}})()};for(let a of lr){let p=()=>S(a);f.set(a,p),t(a,p)}return w};import Sr from"node:process";import{$}from"zx";var Pr=async()=>{try{return await $`cmux --version`.quiet(),!0}catch{return!1}},hr=async r=>{let{cwd:e,title:t,layout:o}=r,n=JSON.stringify(o),s=(await $({env:{...Sr.env,CMUX_QUIET:"1"}})`cmux new-workspace --name ${t} --cwd ${e} --focus false --layout ${n}`).stdout;return vr(s)},br=async r=>{try{await $`cmux close-workspace --workspace ${r}`.quiet()}catch(e){l.debug({error:e,ref:r},"cmux: skipped closing dev workspace")}},vr=r=>{let e=r.match(/workspace:\d+/);if(!e)throw new Error("cmux: could not locate workspace ref in new-workspace output");return e[0]};import{$ as Rr}from"zx";import{realpath as Cr}from"node:fs/promises";import{$ as z}from"zx";var b=async r=>{try{return await Cr(r)}catch{return r}},A=async()=>{try{let[r,e]=await Promise.all([z`cmux workspace list --json`.quiet(),z`cmux workspace-group list --json`.quiet()]),t=JSON.parse(r.stdout).workspaces??[],o=JSON.parse(e.stdout).groups??[],n=new Set(o.map(s=>s.anchor_workspace_ref).filter(s=>typeof s=="string")),i=new Map;for(let s of t)!s.current_directory||n.has(s.ref)||i.set(await b(s.current_directory),s.ref);return i}catch(r){return l.debug({error:r},"cmux: skipped listing workspaces by cwd"),new Map}};var Er=async r=>{try{let t=(await A()).get(await b(r));if(!t)return;await Rr`cmux workspace close ${t}`.quiet()}catch(e){l.debug({error:e,cwd:r},"cmux: skipped closing workspace by cwd")}};import{$ as T}from"zx";var Y=async r=>{try{let e=(await T`cmux workspace-group list --json`.quiet()).stdout;return(JSON.parse(e).groups??[]).find(n=>n.name===r)?.ref??null}catch(e){return l.debug({error:e,name:r},"cmux: skipped group lookup"),null}},Nr=async(r,e)=>{try{let o=(await T`cmux workspace-group create --name ${r} --from ${e.join(",")}`).stdout.match(/workspace_group:\d+/)?.[0]??await Y(r);return o&&await T`cmux workspace-group pin ${o}`.quiet(),o??null}catch(t){return l.warn({error:t,name:r},"\u26A0\uFE0F cmux: failed to create workspace group"),null}};import{$ as y}from"zx";var Lr=async r=>{let{cwd:e,title:t,group:o}=r,n=W(await I()),i=o?(await y`cmux workspace create --cwd ${e} --group ${o} --group-placement end`).stdout:(await y`cmux workspace create --cwd ${e}`).stdout,s=$r(i),c=(await y`cmux list-pane-surfaces --workspace ${s}`).stdout,u=Gr(c);return await y`cmux new-split right --workspace ${s} --surface ${u}`,n==="three-pane"&&await y`cmux new-split down --workspace ${s} --surface ${u}`,t&&await y`cmux workspace rename --workspace ${s} --title ${t}`,s},Gr=r=>{let e=r.match(/surface:\d+/);if(!e)throw new Error("cmux: could not locate initial surface in list-pane-surfaces output");return e[0]},$r=r=>{let e=r.match(/workspace:\d+/);if(!e)throw new Error("cmux: could not locate workspace ref in workspace create output");return e[0]};var Ar=r=>{let{branch:e}=r,t=D(e);return t?M(t):e};var Tr=new Set(["ExitPromptError","AbortPromptError","PromptCancelledError"]),Z=r=>r instanceof Error&&Tr.has(r.name),Se=r=>{if(Z(r))return!0;let e=r?.cause;return Z(e)};import{loadDev as _r}from"@slip-stream-kit/config/internal";import Dr from"node:path";var Mr=(r,e)=>{let t=new Set;for(let o of Object.values(r))for(let n of Object.keys(O(o,e).proxy))t.add(n);return[...t]},Wr=async(r,e)=>{let t={},o=[];return await Promise.all(e.map(async n=>{try{let s=(await _r(Dr.join(r,"apps",n,"ui")))?.proxy?.routes;if(!s)return;t[n]=Object.fromEntries(Object.entries(s).map(([c,u])=>[c,u.packageName]))}catch(i){o.push({app:n,message:i instanceof Error?i.message:String(i)})}})),{routePkg:(n,i)=>t[n]?.[i],loadErrors:o}},Ce=async(r,e,t,o)=>{let{routePkg:n,loadErrors:i}=await Wr(r,Mr(e,t));return{ctx:{discovered:t,apiPkgByApp:Object.fromEntries(o.map(s=>[s.name,s.packageName])),routePkg:n},loadErrors:i}};export{Ce as a,V as b,Jr as c,L as d,qr as e,b as f,A as g,Er as h,Y as i,Nr as j,Pr as k,hr as l,br as m,Lr as n,Ar as o,Se as p};
|
|
10
|
+
//# sourceMappingURL=chunk-KXQQUBGV.js.map
|