@cat-factory/cli 0.2.2 → 0.4.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/args.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { type ContainerRuntime } from './templates.js';
2
2
  import { type VcsProvider } from './vcs.js';
3
+ /** The Kubernetes distribution `cat-factory k3s` can provision/target. */
4
+ export declare const K3S_RUNTIMES: readonly ['k3d', 'kind', 'k3s'];
5
+ export type K3sRuntime = (typeof K3S_RUNTIMES)[number];
3
6
  /** Parsed, validated CLI options. Unset optionals are resolved later (defaults / prompts). */
4
7
  export interface CliOptions {
5
- /** The subcommand. Only `init` exists today; the default when omitted. */
6
- command: 'init' | 'help' | 'version';
8
+ /** The subcommand. `init` (the default when omitted) or `k3s` (guided local-cluster setup). */
9
+ command: 'init' | 'k3s' | 'help' | 'version';
7
10
  dir?: string;
8
11
  projectName?: string;
9
12
  appTitle?: string;
@@ -15,6 +18,10 @@ export interface CliOptions {
15
18
  harnessImage?: string;
16
19
  /** Container runtime that spawns agent jobs (`LOCAL_CONTAINER_RUNTIME`). */
17
20
  containerRuntime?: ContainerRuntime;
21
+ /** `k3s` command: name for a provisioned local cluster. */
22
+ clusterName?: string;
23
+ /** `k3s` command: the Kubernetes distribution to provision/target. */
24
+ k3sRuntime?: K3sRuntime;
18
25
  /** Skip opening the browser at the token-creation URL (still prints it). */
19
26
  noOpen: boolean;
20
27
  /** Non-interactive: never prompt; use defaults/flags. Fails if a required value is missing. */
@@ -35,6 +42,8 @@ export declare const OPTION_DEFAULTS: {
35
42
  readonly port: 8787;
36
43
  readonly harnessImage: "ghcr.io/kibertoad/cat-factory-executor:latest";
37
44
  readonly containerRuntime: ContainerRuntime;
45
+ readonly k3sClusterName: 'cat-factory';
46
+ readonly k3sRuntime: K3sRuntime;
38
47
  };
39
- export declare const HELP_TEXT = "cat-factory \u2014 bootstrap a local cat-factory deployment\n\nUsage:\n cat-factory [init] [options]\n\nScaffolds a local-mode backend (local/) and frontend SPA (frontend/), generates the\ncrypto secrets, mints a GitHub/GitLab personal access token (opens your browser), and\nwrites gitignored .env files.\n\nOptions:\n -d, --dir <path> Target directory (default: ./<name>)\n --name <name> Project name slug (default: cat-factory)\n --title <title> Frontend app title (default: Agent Architecture Board)\n --provider <p> Source control: github | gitlab (default: github)\n --token <token> PAT value (skips the browser/paste flow)\n --db-url <url> Postgres DATABASE_URL\n --api-base <url> Backend API base for the SPA (default: http://localhost:<port>)\n --port <n> Backend HTTP port (default: 8787; also sets the SPA's api-base)\n --harness-image <ref> Executor-harness image (default: ghcr.io ...:latest)\n --container-runtime <r> Agent container runtime: docker | podman | orbstack | colima | apple\n --no-open Don't open the browser (just print the token URL)\n -y, --yes Non-interactive: use defaults/flags, never prompt\n -f, --force Overwrite existing files\n -h, --help Show this help\n -v, --version Show the CLI version\n";
48
+ export declare const HELP_TEXT = "cat-factory \u2014 bootstrap a local cat-factory deployment\n\nUsage:\n cat-factory [init] [options]\n cat-factory k3s [options]\n\nCommands:\n init Scaffold a local-mode backend (local/) + frontend SPA (frontend/): generate the\n crypto secrets, mint a GitHub/GitLab PAT (opens your browser), write gitignored .env.\n k3s Guided local Kubernetes setup: probe the host for a usable cluster, then create (or\n reuse) one + a least-privilege ServiceAccount and print the values to wire the\n Local k3s environment handler. A k3s install needs sudo, so it is only ever printed.\n\nOptions (init):\n -d, --dir <path> Target directory (default: ./<name>)\n --name <name> Project name slug (default: cat-factory)\n --title <title> Frontend app title (default: Agent Architecture Board)\n --provider <p> Source control: github | gitlab (default: github)\n --token <token> PAT value (skips the browser/paste flow)\n --db-url <url> Postgres DATABASE_URL\n --api-base <url> Backend API base for the SPA (default: http://localhost:<port>)\n --port <n> Backend HTTP port (default: 8787; also sets the SPA's api-base)\n --harness-image <ref> Executor-harness image (default: ghcr.io ...:latest)\n --container-runtime <r> Agent container runtime: docker | podman | orbstack | colima | apple\n --no-open Don't open the browser (just print the token URL)\n -y, --yes Non-interactive: use defaults/flags, never prompt\n -f, --force Overwrite existing files\n -h, --help Show this help\n -v, --version Show the CLI version\n\nOptions (k3s):\n --cluster-name <n> Name for a provisioned local cluster (default: cat-factory)\n --runtime <r> Kubernetes distribution: k3d | kind | k3s (default: k3d)\n -y, --yes Non-interactive: pick the recommended path + skip confirms\n";
40
49
  //# sourceMappingURL=args.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,gBAAgB,EAAyB,MAAM,gBAAgB,CAAA;AACjG,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AAE1D,8FAA8F;AAC9F,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACpC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;IACf,+FAA+F;IAC/F,GAAG,EAAE,OAAO,CAAA;IACZ,oDAAoD;IACpD,KAAK,EAAE,OAAO,CAAA;CACf;AAQD,qBAAa,QAAS,SAAQ,KAAK;CAAG;AAEtC,mGAAmG;AACnG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoFpD;AAwBD,qEAAqE;AACrE,eAAO,MAAM,eAAe;aAC1B,WAAW,EAAE,aAAa;aAC1B,QAAQ,EAAE,0BAA0B;aACpC,QAAQ,EAAc,WAAW;aACjC,WAAW,EAAE,8CAA8C;aAI3D,IAAI,EAAE,IAAI;aACV,YAAY;aACZ,gBAAgB,EAAc,gBAAgB;CACtC,CAAA;AAEV,eAAO,MAAM,SAAS,k3CAyBrB,CAAA"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,gBAAgB,EAAyB,MAAM,gBAAgB,CAAA;AACjG,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AAE1D,0EAA0E;AAC1E,eAAO,MAAM,YAAY,YAAI,KAAK,EAAE,MAAM,EAAE,KAAK,CAAU,CAAA;AAC3D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD,8FAA8F;AAC9F,MAAM,WAAW,UAAU;IACzB,+FAA+F;IAC/F,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;IACf,+FAA+F;IAC/F,GAAG,EAAE,OAAO,CAAA;IACZ,oDAAoD;IACpD,KAAK,EAAE,OAAO,CAAA;CACf;AAQD,qBAAa,QAAS,SAAQ,KAAK;CAAG;AAEtC,mGAAmG;AACnG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAgGpD;AA8BD,qEAAqE;AACrE,eAAO,MAAM,eAAe;aAC1B,WAAW,EAAE,aAAa;aAC1B,QAAQ,EAAE,0BAA0B;aACpC,QAAQ,EAAc,WAAW;aACjC,WAAW,EAAE,8CAA8C;aAI3D,IAAI,EAAE,IAAI;aACV,YAAY;aACZ,gBAAgB,EAAc,gBAAgB;aAE9C,cAAc,EAAE,aAAa;aAC7B,UAAU,EAAW,UAAU;CACvB,CAAA;AAEV,eAAO,MAAM,SAAS,y7DAkCrB,CAAA"}
package/dist/args.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { CONTAINER_RUNTIMES, DEFAULT_HARNESS_IMAGE } from './templates.js';
2
2
  import { VCS_PROVIDERS } from './vcs.js';
3
+ /** The Kubernetes distribution `cat-factory k3s` can provision/target. */
4
+ export const K3S_RUNTIMES = ['k3d', 'kind', 'k3s'];
3
5
  const DEFAULTS = {
4
6
  noOpen: false,
5
7
  yes: false,
@@ -32,6 +34,12 @@ export function parseArgs(argv) {
32
34
  commandSet = true;
33
35
  }
34
36
  break;
37
+ case 'k3s':
38
+ if (!commandSet) {
39
+ opts.command = 'k3s';
40
+ commandSet = true;
41
+ }
42
+ break;
35
43
  case 'help':
36
44
  case '--help':
37
45
  case '-h':
@@ -75,6 +83,12 @@ export function parseArgs(argv) {
75
83
  case '--container-runtime':
76
84
  opts.containerRuntime = parseContainerRuntime(takeValue(flag, inline, queue));
77
85
  break;
86
+ case '--cluster-name':
87
+ opts.clusterName = takeValue(flag, inline, queue);
88
+ break;
89
+ case '--runtime':
90
+ opts.k3sRuntime = parseK3sRuntime(takeValue(flag, inline, queue));
91
+ break;
78
92
  case '--no-open':
79
93
  opts.noOpen = true;
80
94
  break;
@@ -104,6 +118,12 @@ function parseContainerRuntime(value) {
104
118
  return v;
105
119
  throw new ArgError(`Invalid --container-runtime "${value}" (expected: ${CONTAINER_RUNTIMES.join(' | ')})`);
106
120
  }
121
+ function parseK3sRuntime(value) {
122
+ const v = value.toLowerCase();
123
+ if (K3S_RUNTIMES.includes(v))
124
+ return v;
125
+ throw new ArgError(`Invalid --runtime "${value}" (expected: ${K3S_RUNTIMES.join(' | ')})`);
126
+ }
107
127
  function parsePort(value) {
108
128
  const n = Number(value);
109
129
  if (!Number.isInteger(n) || n < 1 || n > 65535) {
@@ -123,17 +143,24 @@ export const OPTION_DEFAULTS = {
123
143
  port: 8787,
124
144
  harnessImage: DEFAULT_HARNESS_IMAGE,
125
145
  containerRuntime: 'docker',
146
+ // `k3s` command defaults.
147
+ k3sClusterName: 'cat-factory',
148
+ k3sRuntime: 'k3d',
126
149
  };
127
150
  export const HELP_TEXT = `cat-factory — bootstrap a local cat-factory deployment
128
151
 
129
152
  Usage:
130
153
  cat-factory [init] [options]
154
+ cat-factory k3s [options]
131
155
 
132
- Scaffolds a local-mode backend (local/) and frontend SPA (frontend/), generates the
133
- crypto secrets, mints a GitHub/GitLab personal access token (opens your browser), and
134
- writes gitignored .env files.
156
+ Commands:
157
+ init Scaffold a local-mode backend (local/) + frontend SPA (frontend/): generate the
158
+ crypto secrets, mint a GitHub/GitLab PAT (opens your browser), write gitignored .env.
159
+ k3s Guided local Kubernetes setup: probe the host for a usable cluster, then create (or
160
+ reuse) one + a least-privilege ServiceAccount and print the values to wire the
161
+ Local k3s environment handler. A k3s install needs sudo, so it is only ever printed.
135
162
 
136
- Options:
163
+ Options (init):
137
164
  -d, --dir <path> Target directory (default: ./<name>)
138
165
  --name <name> Project name slug (default: cat-factory)
139
166
  --title <title> Frontend app title (default: Agent Architecture Board)
@@ -149,5 +176,10 @@ Options:
149
176
  -f, --force Overwrite existing files
150
177
  -h, --help Show this help
151
178
  -v, --version Show the CLI version
179
+
180
+ Options (k3s):
181
+ --cluster-name <n> Name for a provisioned local cluster (default: cat-factory)
182
+ --runtime <r> Kubernetes distribution: k3d | kind | k3s (default: k3d)
183
+ -y, --yes Non-interactive: pick the recommended path + skip confirms
152
184
  `;
153
185
  //# sourceMappingURL=args.js.map
package/dist/args.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
package/dist/bin.js CHANGED
@@ -3,6 +3,7 @@ import { readFileSync } from 'node:fs';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { ArgError, HELP_TEXT, parseArgs } from './args.js';
5
5
  import { bootstrap } from './bootstrap.js';
6
+ import { setupK3s } from './k3s.js';
6
7
  function readVersion() {
7
8
  try {
8
9
  const pkgUrl = new URL('../package.json', import.meta.url);
@@ -33,6 +34,10 @@ async function main() {
33
34
  process.stdout.write(`${readVersion()}\n`);
34
35
  return;
35
36
  }
37
+ if (options.command === 'k3s') {
38
+ await setupK3s(options);
39
+ return;
40
+ }
36
41
  await bootstrap(options);
37
42
  }
38
43
  main().catch((err) => {
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAA;QAC3F,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAA;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,OAAO,SAAS,EAAE,CAAC,CAAA;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC/B,OAAM;IACR,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,CAAA;QAC1C,OAAM;IACR,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;AAC1B,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAA;QAC3F,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAA;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,OAAO,SAAS,EAAE,CAAC,CAAA;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAC/B,OAAM;IACR,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,CAAA;QAC1C,OAAM;IACR,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC9B,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAA;QACvB,OAAM;IACR,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;AAC1B,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The result of running a host command. `code` is the process exit code; the special value
3
+ * {@link COMMAND_NOT_FOUND} (127) is used when the binary itself is missing (spawn `ENOENT`),
4
+ * so callers can distinguish "not installed" from "ran but failed".
5
+ */
6
+ export interface ShellResult {
7
+ code: number;
8
+ stdout: string;
9
+ stderr: string;
10
+ }
11
+ /** Conventional exit code for a missing binary — returned by {@link HostShell.run} on `ENOENT`. */
12
+ export declare const COMMAND_NOT_FOUND = 127;
13
+ /** Conventional exit code for a command killed by the watchdog timeout (mirrors `timeout(1)`). */
14
+ export declare const COMMAND_TIMED_OUT = 124;
15
+ /**
16
+ * Default per-command watchdog (ms). A probe must stay responsive, but some detections shell out to
17
+ * `kubectl`, which contacts the apiserver — a kubeconfig pointing at a down/unroutable cluster would
18
+ * otherwise block on the TCP/HTTP timeout. The watchdog kills such a child and reports
19
+ * {@link COMMAND_TIMED_OUT} so the probe treats it as "ran but failed" (not reachable), never hangs.
20
+ */
21
+ export declare const DEFAULT_COMMAND_TIMEOUT_MS = 10000;
22
+ /**
23
+ * Host shell-out seam. The k3s flow depends on this interface (never on `node:child_process`
24
+ * directly), so probing/provisioning can be driven by a fake in tests. The real implementation
25
+ * ({@link createNodeShell}) spawns real processes; tests inject their own. Mirrors the `Io` /
26
+ * `FileSystem` seams used by the `init` command.
27
+ */
28
+ export interface HostShell {
29
+ /**
30
+ * Run `cmd` with `args`, capturing stdout/stderr. Resolves with the exit code — it NEVER
31
+ * rejects: a missing binary resolves to `{ code: COMMAND_NOT_FOUND }` so the probe can treat
32
+ * "not installed" uniformly, and a command that overruns `timeoutMs` is killed and resolves to
33
+ * `{ code: COMMAND_TIMED_OUT }`. Output is returned to the caller, never logged here.
34
+ *
35
+ * `opts.input`, when set, is written to the child's stdin and the stream is closed — used to
36
+ * feed a manifest to `kubectl apply -f -` WITHOUT writing it (or the token Secret it creates)
37
+ * to a temp file on disk.
38
+ */
39
+ run(cmd: string, args: string[], opts?: {
40
+ timeoutMs?: number;
41
+ input?: string;
42
+ }): Promise<ShellResult>;
43
+ }
44
+ /** The real, process-backed {@link HostShell}. */
45
+ export declare function createNodeShell(): HostShell;
46
+ //# sourceMappingURL=host-shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-shell.d.ts","sourceRoot":"","sources":["../src/host-shell.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,mGAAmG;AACnG,eAAO,MAAM,iBAAiB,MAAM,CAAA;AAEpC,kGAAkG;AAClG,eAAO,MAAM,iBAAiB,MAAM,CAAA;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAS,CAAA;AAEhD;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;;OASG;IACH,GAAG,CACD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,OAAO,CAAC,WAAW,CAAC,CAAA;CACxB;AAED,kDAAkD;AAClD,wBAAgB,eAAe,IAAI,SAAS,CA2D3C"}
@@ -0,0 +1,73 @@
1
+ import { spawn } from 'node:child_process';
2
+ /** Conventional exit code for a missing binary — returned by {@link HostShell.run} on `ENOENT`. */
3
+ export const COMMAND_NOT_FOUND = 127;
4
+ /** Conventional exit code for a command killed by the watchdog timeout (mirrors `timeout(1)`). */
5
+ export const COMMAND_TIMED_OUT = 124;
6
+ /**
7
+ * Default per-command watchdog (ms). A probe must stay responsive, but some detections shell out to
8
+ * `kubectl`, which contacts the apiserver — a kubeconfig pointing at a down/unroutable cluster would
9
+ * otherwise block on the TCP/HTTP timeout. The watchdog kills such a child and reports
10
+ * {@link COMMAND_TIMED_OUT} so the probe treats it as "ran but failed" (not reachable), never hangs.
11
+ */
12
+ export const DEFAULT_COMMAND_TIMEOUT_MS = 10_000;
13
+ /** The real, process-backed {@link HostShell}. */
14
+ export function createNodeShell() {
15
+ return {
16
+ run(cmd, args, opts) {
17
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
18
+ return new Promise((resolve) => {
19
+ let stdout = '';
20
+ let stderr = '';
21
+ let settled = false;
22
+ let timer;
23
+ const finish = (result) => {
24
+ if (settled)
25
+ return;
26
+ settled = true;
27
+ if (timer)
28
+ clearTimeout(timer);
29
+ resolve(result);
30
+ };
31
+ // Feed stdin only when there's input; otherwise leave it closed (`ignore`).
32
+ const stdin = opts?.input !== undefined ? 'pipe' : 'ignore';
33
+ let child;
34
+ try {
35
+ child = spawn(cmd, args, { stdio: [stdin, 'pipe', 'pipe'] });
36
+ }
37
+ catch {
38
+ finish({ code: COMMAND_NOT_FOUND, stdout: '', stderr: `${cmd}: not found` });
39
+ return;
40
+ }
41
+ if (opts?.input !== undefined && child.stdin) {
42
+ // A child that exits before draining stdin raises EPIPE on the write; swallow it so a
43
+ // fast-failing command surfaces as its exit code, not an unhandled stream error.
44
+ child.stdin.on('error', () => { });
45
+ child.stdin.end(opts.input);
46
+ }
47
+ // Watchdog: kill a child that runs past the deadline (e.g. `kubectl` stuck dialing an
48
+ // unreachable apiserver) and report it as timed-out rather than blocking the probe forever.
49
+ timer = setTimeout(() => {
50
+ child.kill('SIGKILL');
51
+ finish({ code: COMMAND_TIMED_OUT, stdout, stderr: stderr || `${cmd}: timed out` });
52
+ }, timeoutMs);
53
+ timer.unref?.();
54
+ child.stdout?.on('data', (chunk) => {
55
+ stdout += chunk.toString();
56
+ });
57
+ child.stderr?.on('data', (chunk) => {
58
+ stderr += chunk.toString();
59
+ });
60
+ child.on('error', (err) => {
61
+ // ENOENT ⇒ the binary is missing; anything else ⇒ a genuine spawn failure. Both are
62
+ // surfaced as a non-zero result rather than a throw so the caller stays branch-free.
63
+ const code = err.code === 'ENOENT' ? COMMAND_NOT_FOUND : 1;
64
+ finish({ code, stdout, stderr: stderr || err.message });
65
+ });
66
+ child.on('close', (code) => {
67
+ finish({ code: code ?? 1, stdout, stderr });
68
+ });
69
+ });
70
+ },
71
+ };
72
+ }
73
+ //# sourceMappingURL=host-shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-shell.js","sourceRoot":"","sources":["../src/host-shell.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
- export { type CliOptions, HELP_TEXT, OPTION_DEFAULTS, parseArgs, ArgError } from './args.js';
1
+ export { type CliOptions, HELP_TEXT, K3S_RUNTIMES, type K3sRuntime, OPTION_DEFAULTS, parseArgs, ArgError, } from './args.js';
2
2
  export { bootstrap, type BootstrapDeps, type FileSystem, BootstrapError } from './bootstrap.js';
3
+ export { COMMAND_NOT_FOUND, COMMAND_TIMED_OUT, createNodeShell, DEFAULT_COMMAND_TIMEOUT_MS, type HostShell, type ShellResult, } from './host-shell.js';
4
+ export { K3S_INSTALL_COMMAND, type K3sDeps, type K3sResult, setupK3s } from './k3s.js';
5
+ export { classifyHost, hasServerVersion, type HostDetections, type HostState, type Offer, type OfferId, parseK3dClusters, parseKindClusters, probeHost, type ToolDetection, } from './k3s-probe.js';
3
6
  export { buildFrontendEnv, buildLocalEnv, type EnvEntry, type FrontendEnvInput, type LocalEnvInput, renderEnvFile, } from './env.js';
4
7
  export { buildGitignore, mergeGitignore, REQUIRED_GITIGNORE_RULES } from './gitignore.js';
5
8
  export { type Io, createConsoleIo } from './io.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC5F,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACjG,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EACf,SAAS,EACT,YAAY,EACZ,KAAK,UAAU,EACf,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,KAAK,cAAc,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACjG,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  // Public, programmatic API of @cat-factory/cli. The `cat-factory` command (bin.ts) is a thin
2
2
  // shell over these; they are also exported so the bootstrap can be embedded in other tooling.
3
- export { HELP_TEXT, OPTION_DEFAULTS, parseArgs, ArgError } from './args.js';
3
+ export { HELP_TEXT, K3S_RUNTIMES, OPTION_DEFAULTS, parseArgs, ArgError, } from './args.js';
4
4
  export { bootstrap, BootstrapError } from './bootstrap.js';
5
+ export { COMMAND_NOT_FOUND, COMMAND_TIMED_OUT, createNodeShell, DEFAULT_COMMAND_TIMEOUT_MS, } from './host-shell.js';
6
+ export { K3S_INSTALL_COMMAND, setupK3s } from './k3s.js';
7
+ export { classifyHost, hasServerVersion, parseK3dClusters, parseKindClusters, probeHost, } from './k3s-probe.js';
5
8
  export { buildFrontendEnv, buildLocalEnv, renderEnvFile, } from './env.js';
6
9
  export { buildGitignore, mergeGitignore, REQUIRED_GITIGNORE_RULES } from './gitignore.js';
7
10
  export { createConsoleIo } from './io.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,8FAA8F;AAC9F,OAAO,EAAmB,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC5F,OAAO,EAAE,SAAS,EAAuC,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EACL,gBAAgB,EAChB,aAAa,EAIb,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAW,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAuB,SAAS,EAAoB,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAA2C,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAyB,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACjG,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,GAEd,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,8FAA8F;AAC9F,OAAO,EAEL,SAAS,EACT,YAAY,EAEZ,eAAe,EACf,SAAS,EACT,QAAQ,GACT,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAuC,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,GAG3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAgC,QAAQ,EAAE,MAAM,UAAU,CAAA;AACtF,OAAO,EACL,YAAY,EACZ,gBAAgB,EAKhB,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,GAEV,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,gBAAgB,EAChB,aAAa,EAIb,aAAa,GACd,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AACzF,OAAO,EAAW,eAAe,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAuB,SAAS,EAAoB,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,eAAe,EAA2C,MAAM,cAAc,CAAA;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,kBAAkB,EAAyB,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACjG,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,aAAa,EACb,aAAa,GAEd,MAAM,UAAU,CAAA"}
@@ -0,0 +1,69 @@
1
+ import { type K3sRuntime } from './args.js';
2
+ import { type HostShell } from './host-shell.js';
3
+ /** Whether a host CLI is installed, and its reported version string when detectable. */
4
+ export interface ToolDetection {
5
+ installed: boolean;
6
+ version?: string;
7
+ }
8
+ /**
9
+ * The raw facts detected about the host, produced by {@link probeHost} and consumed by the pure
10
+ * {@link classifyHost}. Kept as plain data so classification is unit-testable with no shell.
11
+ */
12
+ export interface HostDetections {
13
+ kubectl: ToolDetection;
14
+ k3d: ToolDetection;
15
+ kind: ToolDetection;
16
+ k3s: ToolDetection;
17
+ docker: {
18
+ installed: boolean;
19
+ running: boolean;
20
+ };
21
+ /** A cluster is reachable via the current kubeconfig (apiserver answered a version request). */
22
+ reachableCluster: boolean;
23
+ /** The current kubeconfig context name, when one is set. */
24
+ clusterContext?: string;
25
+ /** Names of existing k3d-managed clusters (Docker). */
26
+ k3dClusters: string[];
27
+ /** Names of existing kind-managed clusters (Docker). */
28
+ kindClusters: string[];
29
+ }
30
+ /** The setup paths the probe can offer. */
31
+ export type OfferId = 'use-existing' | 'create-k3d' | 'create-kind' | 'install-k3s';
32
+ /** One offered setup path, with whether it's currently possible + why not. */
33
+ export interface Offer {
34
+ id: OfferId;
35
+ label: string;
36
+ available: boolean;
37
+ recommended: boolean;
38
+ /** When `available` is false, a short reason the UI can show. */
39
+ reason?: string;
40
+ }
41
+ /** The classified host state: the raw detections plus the offered paths and the recommendation. */
42
+ export interface HostState {
43
+ detections: HostDetections;
44
+ offers: Offer[];
45
+ recommended: OfferId;
46
+ }
47
+ /**
48
+ * Classify the host from its detected facts into the offered setup paths. Pure — no IO — so it's
49
+ * the primary unit-test target. `recommended` is the highest-priority AVAILABLE offer for the
50
+ * `preferred` runtime (default `k3d`, the no-root Docker path).
51
+ */
52
+ export declare function classifyHost(d: HostDetections, preferred?: K3sRuntime): HostState;
53
+ /** Parse `k3d cluster list --output json` (an array of `{ name }`) into cluster names. */
54
+ export declare function parseK3dClusters(stdout: string): string[];
55
+ /** Parse `kind get clusters` (newline-separated names; a "No kind clusters" note ⇒ empty). */
56
+ export declare function parseKindClusters(stdout: string): string[];
57
+ /** Detect whether a `kubectl version --output=json` payload reports a reachable apiserver. */
58
+ export declare function hasServerVersion(stdout: string): boolean;
59
+ /**
60
+ * Probe the host over the {@link HostShell} seam and classify it for the `preferred` runtime. Runs
61
+ * each tool's detection command, treats {@link COMMAND_NOT_FOUND} as "not installed", and folds the
62
+ * results through the pure {@link classifyHost}. Tested with a scripted fake shell.
63
+ *
64
+ * `kubectl version` / `config current-context` contact the apiserver, so they carry an explicit
65
+ * `--request-timeout` — a kubeconfig pointing at a down cluster then fails fast instead of hanging
66
+ * the probe (the {@link HostShell} watchdog is the outer backstop).
67
+ */
68
+ export declare function probeHost(shell: HostShell, preferred?: K3sRuntime): Promise<HostState>;
69
+ //# sourceMappingURL=k3s-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k3s-probe.d.ts","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEnE,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAA;IACtB,GAAG,EAAE,aAAa,CAAA;IAClB,IAAI,EAAE,aAAa,CAAA;IACnB,GAAG,EAAE,aAAa,CAAA;IAClB,MAAM,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;IAChD,gGAAgG;IAChG,gBAAgB,EAAE,OAAO,CAAA;IACzB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uDAAuD;IACvD,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,wDAAwD;IACxD,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,2CAA2C;AAC3C,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,aAAa,CAAA;AAEnF,8EAA8E;AAC9E,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IACpB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,mGAAmG;AACnG,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,cAAc,CAAA;IAC1B,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,WAAW,EAAE,OAAO,CAAA;CACrB;AAmBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,GAAE,UAAkB,GAAG,SAAS,CAsDxF;AAgBD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAYzD;AAED,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1D;AAED,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAOxD;AAED;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,SAAS,EAChB,SAAS,GAAE,UAAkB,GAC5B,OAAO,CAAC,SAAS,CAAC,CA0CpB"}
@@ -0,0 +1,154 @@
1
+ import {} from './args.js';
2
+ import { COMMAND_NOT_FOUND } from './host-shell.js';
3
+ /**
4
+ * Priority order for picking the recommendation, given the user's preferred runtime. A live cluster
5
+ * always wins; otherwise the preferred distribution's create/install path is tried first, then the
6
+ * others as fallbacks. Every list ends with `install-k3s`, which is always available.
7
+ */
8
+ function offerPriority(preferred) {
9
+ switch (preferred) {
10
+ case 'kind':
11
+ return ['use-existing', 'create-kind', 'create-k3d', 'install-k3s'];
12
+ case 'k3s':
13
+ // An explicit k3s preference favours the guided single-node install over the Docker paths.
14
+ return ['use-existing', 'install-k3s', 'create-k3d', 'create-kind'];
15
+ default:
16
+ return ['use-existing', 'create-k3d', 'create-kind', 'install-k3s'];
17
+ }
18
+ }
19
+ /**
20
+ * Classify the host from its detected facts into the offered setup paths. Pure — no IO — so it's
21
+ * the primary unit-test target. `recommended` is the highest-priority AVAILABLE offer for the
22
+ * `preferred` runtime (default `k3d`, the no-root Docker path).
23
+ */
24
+ export function classifyHost(d, preferred = 'k3d') {
25
+ const useExisting = {
26
+ id: 'use-existing',
27
+ label: d.clusterContext
28
+ ? `Use the existing cluster (context: ${d.clusterContext})`
29
+ : 'Use the existing reachable cluster',
30
+ available: d.reachableCluster,
31
+ recommended: false,
32
+ reason: d.reachableCluster ? undefined : 'No cluster is reachable via your kubeconfig',
33
+ };
34
+ const dockerReason = !d.docker.installed
35
+ ? 'Docker is not installed'
36
+ : !d.docker.running
37
+ ? 'Docker is not running'
38
+ : undefined;
39
+ const createK3d = {
40
+ id: 'create-k3d',
41
+ label: 'Create a local k3d cluster (Docker, no root)',
42
+ available: d.docker.running && d.k3d.installed,
43
+ recommended: false,
44
+ reason: dockerReason ?? (!d.k3d.installed ? 'k3d is not installed (https://k3d.io)' : undefined),
45
+ };
46
+ const createKind = {
47
+ id: 'create-kind',
48
+ label: 'Create a local kind cluster (Docker, no root)',
49
+ available: d.docker.running && d.kind.installed,
50
+ recommended: false,
51
+ reason: dockerReason ??
52
+ (!d.kind.installed ? 'kind is not installed (https://kind.sigs.k8s.io)' : undefined),
53
+ };
54
+ // The guided k3s path is always available: when k3s is already installed it only points the user
55
+ // at starting the service; otherwise it PRINTS the install command (needs sudo). Never auto-runs.
56
+ const installK3s = {
57
+ id: 'install-k3s',
58
+ label: d.k3s.installed
59
+ ? 'Start your already-installed k3s (needs sudo — not run for you)'
60
+ : 'Show the k3s install command (needs sudo — not run for you)',
61
+ available: true,
62
+ recommended: false,
63
+ };
64
+ const offers = [useExisting, createK3d, createKind, installK3s];
65
+ const recommended = offerPriority(preferred).find((id) => offers.find((o) => o.id === id)?.available) ??
66
+ 'install-k3s';
67
+ for (const o of offers)
68
+ o.recommended = o.id === recommended;
69
+ return { detections: d, offers, recommended };
70
+ }
71
+ /** True when a `run` result indicates the binary exists (it ran, even if the subcommand failed). */
72
+ function isInstalled(code) {
73
+ return code !== COMMAND_NOT_FOUND;
74
+ }
75
+ /** First non-empty trimmed line of a command's stdout (used for `--version` style output). */
76
+ function firstLine(stdout) {
77
+ const line = stdout
78
+ .split('\n')
79
+ .map((l) => l.trim())
80
+ .find((l) => l.length > 0);
81
+ return line && line.length > 0 ? line : undefined;
82
+ }
83
+ /** Parse `k3d cluster list --output json` (an array of `{ name }`) into cluster names. */
84
+ export function parseK3dClusters(stdout) {
85
+ try {
86
+ const parsed = JSON.parse(stdout);
87
+ if (!Array.isArray(parsed))
88
+ return [];
89
+ return parsed
90
+ .map((c) => typeof c === 'object' && c !== null ? c.name : undefined)
91
+ .filter((n) => typeof n === 'string' && n.length > 0);
92
+ }
93
+ catch {
94
+ return [];
95
+ }
96
+ }
97
+ /** Parse `kind get clusters` (newline-separated names; a "No kind clusters" note ⇒ empty). */
98
+ export function parseKindClusters(stdout) {
99
+ return stdout
100
+ .split('\n')
101
+ .map((l) => l.trim())
102
+ .filter((l) => l.length > 0 && !l.toLowerCase().startsWith('no kind clusters'));
103
+ }
104
+ /** Detect whether a `kubectl version --output=json` payload reports a reachable apiserver. */
105
+ export function hasServerVersion(stdout) {
106
+ try {
107
+ const parsed = JSON.parse(stdout);
108
+ return typeof parsed.serverVersion === 'object' && parsed.serverVersion !== null;
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ /**
115
+ * Probe the host over the {@link HostShell} seam and classify it for the `preferred` runtime. Runs
116
+ * each tool's detection command, treats {@link COMMAND_NOT_FOUND} as "not installed", and folds the
117
+ * results through the pure {@link classifyHost}. Tested with a scripted fake shell.
118
+ *
119
+ * `kubectl version` / `config current-context` contact the apiserver, so they carry an explicit
120
+ * `--request-timeout` — a kubeconfig pointing at a down cluster then fails fast instead of hanging
121
+ * the probe (the {@link HostShell} watchdog is the outer backstop).
122
+ */
123
+ export async function probeHost(shell, preferred = 'k3d') {
124
+ const [kubectlVersion, kubectlContext, k3dVersion, k3dList, kindVersion, kindList, k3sVersion, dockerVersion,] = await Promise.all([
125
+ shell.run('kubectl', ['version', '--output=json', '--request-timeout=3s']),
126
+ shell.run('kubectl', ['config', 'current-context']),
127
+ shell.run('k3d', ['version']),
128
+ shell.run('k3d', ['cluster', 'list', '--output', 'json']),
129
+ shell.run('kind', ['version']),
130
+ shell.run('kind', ['get', 'clusters']),
131
+ shell.run('k3s', ['--version']),
132
+ shell.run('docker', ['version', '--format', '{{.Server.Version}}']),
133
+ ]);
134
+ const context = kubectlContext.code === 0 ? firstLine(kubectlContext.stdout) : undefined;
135
+ const detections = {
136
+ kubectl: {
137
+ installed: isInstalled(kubectlVersion.code),
138
+ version: firstLine(kubectlVersion.stdout),
139
+ },
140
+ k3d: { installed: isInstalled(k3dVersion.code), version: firstLine(k3dVersion.stdout) },
141
+ kind: { installed: isInstalled(kindVersion.code), version: firstLine(kindVersion.stdout) },
142
+ k3s: { installed: isInstalled(k3sVersion.code), version: firstLine(k3sVersion.stdout) },
143
+ docker: {
144
+ installed: isInstalled(dockerVersion.code),
145
+ running: dockerVersion.code === 0 && firstLine(dockerVersion.stdout) !== undefined,
146
+ },
147
+ reachableCluster: kubectlVersion.code === 0 && hasServerVersion(kubectlVersion.stdout),
148
+ clusterContext: context,
149
+ k3dClusters: k3dList.code === 0 ? parseK3dClusters(k3dList.stdout) : [],
150
+ kindClusters: kindList.code === 0 ? parseKindClusters(kindList.stdout) : [],
151
+ };
152
+ return classifyHost(detections, preferred);
153
+ }
154
+ //# sourceMappingURL=k3s-probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k3s-probe.js","sourceRoot":"","sources":["../src/k3s-probe.ts"],"names":[],"mappings":"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"}