@deessejs/cli 2.1.0-canary.20260901220925.84058f1 → 2.2.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/LICENSE +21 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +22 -22
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Deessejs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { RPCLink } from '@orpc/client/fetch';
|
|
|
15
15
|
import { spawn as spawn$1 } from 'child_process';
|
|
16
16
|
|
|
17
17
|
// src/api/self-version.ts
|
|
18
|
-
var readPackageVersion = () => "2.
|
|
18
|
+
var readPackageVersion = () => "2.2.0";
|
|
19
19
|
|
|
20
20
|
// src/constants/exit.ts
|
|
21
21
|
var EXIT_ERROR = 1;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/self-version.ts","../src/constants/exit.ts","../src/errors/network.ts","../src/errors/not-found.ts","../src/errors/device-denied.ts","../src/errors/device-expired.ts","../src/errors/index.ts","../src/utils/sleep.ts","../../../packages/api/dist/constants/base-path.js","../src/lib/auth/store/better-auth-client.ts","../src/lib/auth/store/bearer-fetch.ts","../src/lib/auth/flow/polling-errors.ts","../src/lib/auth/flow/device-flow.ts","../src/lib/auth/flow/open-verification-url.ts","../src/cache/location.ts","../src/lib/auth/store/store.ts","../src/output/table.ts","../src/output/index.ts","../src/commands/auth/login.ts","../src/commands/auth/status.ts","../src/commands/auth/logout.ts","../src/version/check.ts","../src/api/client.ts","../src/api/index.ts","../src/utils/spawn.ts","../src/utils/git.ts","../src/utils/detect-pm.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/info.ts","../src/index.ts"],"names":["nodeSetTimeout","existsSync","mkdirSync","pc","Command","ora","DEFAULT_API_URL","resolveBaseURL","resolve","nodeSpawn","join","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["// Local declaration: tsup `define` (see apps/cli/tsup.config.ts) replaces\n// `process.env.CLI_PACKAGE_VERSION` with a string literal at build time.\n// The field is not present on Node's actual `process.env` shape, so we\n// declare it here for typechecking. The declaration is scoped to this\n// file; nothing else in the CLI sees it.\ndeclare const process: {\n env: {\n CLI_PACKAGE_VERSION: string\n }\n}\n\n/**\n * The CLI's own version, injected at build time from\n * apps/cli/package.json via tsup `define`. The bundler inlines the\n * literal string; there is no runtime lookup and no fragile\n * `import.meta.url` resolution back to package.json.\n *\n * Single source of truth: apps/cli/package.json. Changesets owns\n * the field; tsup reads it; the bundle carries it.\n *\n * See ADR-019.\n */\nexport const readPackageVersion = (): string => process.env.CLI_PACKAGE_VERSION\n","export const EXIT_SUCCESS = 0\nexport const EXIT_ERROR = 1\n","import { CliError } from \"./index.js\"\n\nexport const networkError = (detail: string): CliError =>\n new CliError(\n \"network_error\",\n `could not reach the templates endpoint`,\n detail,\n )\n","import { CliError } from \"./index.js\"\n\nexport const notFound = (slug: string, available: string[]): CliError =>\n new CliError(\n \"not_found\",\n `template \"${slug}\" not found`,\n `available templates: ${available.join(\", \")}`,\n )\n","import { CliError } from \"./index.js\"\n\n/**\n * The user denied the device-flow authorization in the\n * browser (ADR-020 mapping table: Better Auth\n * `access_denied` -> cli_device_denied).\n */\nexport const cliDeviceDenied = (): CliError =>\n\tnew CliError(\n\t\t\"cli_device_denied\",\n\t\t\"authorization was denied in the browser\",\n\t\t\"run `deesse auth login` again if this was a mistake\",\n\t)\n","import { CliError } from \"./index.js\"\n\n/**\n * The device code expired before the user approved it\n * (ADR-020 mapping table: Better Auth `expired_token` /\n * `invalid_grant` / `invalid_client` -> cli_device_expired).\n *\n * Also returned for the explicit 30-minute timeout when the\n * poll loop exhausts the device-code TTL without seeing an\n * approval.\n */\nexport const cliDeviceExpired = (reason?: string): CliError =>\n\tnew CliError(\n\t\t\"cli_device_expired\",\n\t\treason ??\n\t\t\t\"the device code expired before it was approved\",\n\t\t\"run `deesse auth login` again to obtain a fresh device code\",\n\t)\n","import { EXIT_ERROR } from \"../constants/exit.js\"\n\n// Public surface (per ADR-010 §2): the closed list of error codes\n// that downstream tooling may pattern-match against. Adding a code\n// here is a breaking change.\n//\n// The two device-flow codes (cli_device_denied,\n// cli_device_expired) are an amendment to the closed list, added\n// in lockstep with ADR-020 (device authorization). They are not\n// a precedent for further openings; see ADR-010 §2 \"What this\n// rule forbids\".\nexport type CliErrorCode =\n | \"not_found\"\n | \"network_error\"\n | \"parse_error\"\n | \"cli_outdated\"\n | \"cli_device_denied\"\n | \"cli_device_expired\"\n\n// Internal codes, used only inside the CLI. Not surfaced as a public\n// pattern-match surface. Adding a code here is non-breaking.\nexport type InternalCliErrorCode =\n | \"git_not_installed\"\n | \"target_exists\"\n | \"install_failed\"\n | \"internal\"\n\nexport type AnyCliErrorCode = CliErrorCode | InternalCliErrorCode\n\nexport class CliError extends Error {\n public readonly code: AnyCliErrorCode\n public readonly hint: string | undefined\n\n constructor(code: AnyCliErrorCode, message: string, hint?: string) {\n super(message)\n this.name = \"CliError\"\n this.code = code\n this.hint = hint\n }\n\n public exitCode = (): number => EXIT_ERROR\n}\n\n// Public factories (re-export the per-code files).\nexport { networkError } from \"./network.js\"\nexport { parseError } from \"./parse.js\"\nexport { notFound } from \"./not-found.js\"\nexport { cliOutdated } from \"./outdated.js\"\nexport { cliDeviceDenied } from \"./device-denied.js\"\nexport { cliDeviceExpired } from \"./device-expired.js\"\n\n// Internal factories, kept in this file because they are not part of\n// the public surface (ADR-010 §2 \"What this rule allows\": internal\n// error codes are not surfaced to the user).\nexport const gitNotInstalled = (): CliError =>\n new CliError(\n \"git_not_installed\",\n \"`git` is not installed or not on PATH\",\n \"install git from https://git-scm.com and try again\",\n )\n\nexport const targetExists = (dir: string): CliError =>\n new CliError(\n \"target_exists\",\n `target directory \"${dir}\" already exists`,\n \"remove the directory or pass --force to overwrite\",\n )\n\nexport const installFailed = (\n pm: string,\n code: number | null,\n): CliError =>\n new CliError(\n \"install_failed\",\n `${pm} install exited with code ${code ?? \"unknown\"}`,\n \"check the output above, then run the install command manually inside the cloned directory\",\n )\n\nexport const internal = (detail: string): CliError =>\n new CliError(\"internal\", \"unexpected internal error\", detail)\n","/**\n * Promisified setTimeout (ADR-020).\n *\n * Used by the deesse auth login polling loop to wait between\n * polls of /device/token. The loop's total timeout (1800 seconds\n * for a device-code TTL, hard-stopped via the mapPollingError\n * table) also uses this helper — there is no second timing\n * mechanism.\n *\n * Implemented with `node:timers/promises` so we do not pull in\n * a third-party timing lib for one helper. The Node API has\n * been stable since Node 15.\n *\n * Per ADR-002 Rule 2, helpers like this live in their own file\n * (no shared utils/ catch-all). One file, one function.\n */\nimport { setTimeout as nodeSetTimeout } from \"node:timers/promises\"\n\nexport const sleep = (ms: number): Promise<void> => nodeSetTimeout(ms)\n","/**\n * Single source of truth for the API path.\n *\n * The Next.js catch-all at `apps/app/app/api/[[...route]]/route.ts` exposes\n * every route under the active base path. Hono is mounted with\n * `basePath(API_BASE_PATH)`, and the oRPC client targets `API_RPC_PATH` to\n * reach the procedures endpoint.\n *\n * Versioning strategy (locked in docs/engineering/plans/robust-shared-backend.md):\n * - Each contract version lives under `packages/contracts/src/vN/`.\n * - The HTTP URL prefix mirrors that: `API_BASE_PATH_V1 = \"/api/v1\"`.\n * - `API_BASE_PATH` aliases the *active* version. When a V2 is introduced,\n * define `API_BASE_PATH_V2`, point `API_BASE_PATH` at it, and keep V1\n * served as a deprecated alias for installed CLI V1.x clients.\n *\n * Renaming the API prefix means:\n * 1. Edit `API_BASE_PATH_V*` below.\n * 2. Move (or alias) the Next.js catch-all to match.\n * 3. If you later introduce a `NEXT_PUBLIC_API_BASE_PATH` env override,\n * read it here and have `API_BASE_PATH` default to it.\n *\n * Do NOT introduce a parallel \"API path\" hardcoded in any app or package —\n * always import from this module.\n *\n * Note: Hono routes are kept *relative* to `basePath`, so the Hono-side\n * patterns (`/health`, `/rpc/*`) are NOT exposed here — only the full\n * client-facing paths.\n */\nexport const API_BASE_PATH_V1 = \"/api/v1\";\n/** Active version. Alias of the latest released base path. */\nexport const API_BASE_PATH = API_BASE_PATH_V1;\nexport const API_RPC_PATH = `${API_BASE_PATH}/rpc`;\nexport const API_AUTH_PATH = `${API_BASE_PATH}/auth`;\nexport const API_HEALTH_PATH = `${API_BASE_PATH}/health`;\nexport const API_READY_PATH = `${API_BASE_PATH}/ready`;\n","import { createAuthClient } from \"better-auth/client\"\nimport { deviceAuthorizationClient } from \"better-auth/client/plugins\"\nimport { API_AUTH_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../../../api/self-version.js\"\n\n/**\n * Production default for the CLI's `baseURL`.\n *\n * The CLI ships to npm as `@deessejs/cli`. When an end user\n * runs `npx @deessejs/cli@latest <cmd>` they have no\n * control over `process.env.DEESSEJS_API_URL` (it is the\n * shell environment of the user's machine, not the CLI's).\n * Baked-in defaults are the only mechanism that works\n * out of the box.\n *\n * The host `app.deessejs.com` is the production API host\n * per ADR-015 and ADR-016 (which both reproduce / test\n * against `app.deessejs.com/api/v1/...`). The `basePath` of\n * `/api/v1/auth` is appended by the Better Auth client, so\n * the device-flow endpoints live at\n * `${baseURL}${API_AUTH_PATH}/device/*` =\n * `https://app.deessejs.com/api/v1/auth/device/*`.\n *\n * (Note: an earlier draft of this comment cited\n * `deessejs.com` from ADR-014, which is the marketing\n * apex. ADR-014 was wrong about which host serves the\n * API. The canonical prod API host is `app.deessejs.com`,\n * confirmed by ADR-015 §\"Root cause\" and ADR-016\n * §\"API CI\". ADR-014 should be updated to match.)\n *\n * Three sources, in priority order:\n * 1. `DEESSEJS_API_URL` env var (CI / dev override;\n * never set by end users in practice).\n * 2. The baked-in default below (production).\n * 3. A thrown validation error when source 1 is set but\n * malformed (per ADR-014 §\"Malformed values fail\n * loudly\").\n */\nexport const DEFAULT_API_URL = \"https://app.deessejs.com\"\n\nexport function resolveBaseURL(): string {\n\tconst raw = process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL\n\ttry {\n\t\tconst parsed = new URL(raw)\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\t\tthrow new Error(\n\t\t\t\t`DEESSEJS_API_URL must use http or https (got ${parsed.protocol ?? \"no protocol\"})`,\n\t\t\t)\n\t\t}\n\t\treturn parsed.toString().replace(/\\/$/, \"\")\n\t} catch (e) {\n\t\tconst detail = e instanceof Error ? e.message : String(e)\n\t\tthrow new Error(\n\t\t\t`DEESSEJS_API_URL is malformed: ${detail}. ` +\n\t\t\t\t`Expected a full URL like https://api.example.com.`,\n\t\t)\n\t}\n}\n\n/**\n * Better Auth client factory for the CLI (ADR-020).\n *\n * The factory is the public surface (not a singleton).\n * Two reasons:\n * 1. Tests need to override `DEESSEJS_API_URL` before the\n * client is built; a module-level singleton would\n * capture the env var at import time and freeze it.\n * 2. Each command that touches the server runs at a\n * different point in the process lifetime; a fresh\n * client per call is fine because createAuthClient is\n * cheap (a Proxy + a few plugins).\n *\n * The framework-agnostic core (`better-auth/client`) is used\n * rather than `better-auth/react`. The react subpath only\n * adds hooks like `useSession` that the CLI does not consume.\n *\n * `disableDefaultFetchPlugins: true` is set for Node: the\n * default plugins include a redirect handler that intercepts\n * `window.location`-style redirects, which is meaningless in\n * Node.\n *\n * `fetchOptions.headers` injects the CLI User-Agent on every\n * request (ADR-020 limitation 1 mitigation).\n */\nexport function createCliAuthClient() {\n\treturn createAuthClient({\n\t\tbaseURL: resolveBaseURL(),\n\t\tbasePath: API_AUTH_PATH,\n\t\tplugins: [deviceAuthorizationClient()],\n\t\tdisableDefaultFetchPlugins: true,\n\t\tfetchOptions: {\n\t\t\theaders: {\n\t\t\t\t\"user-agent\": `DeesseJS CLI/${readPackageVersion()}`,\n\t\t\t},\n\t\t},\n\t})\n}\n","import { API_AUTH_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../../../api/self-version.js\"\n\nimport { resolveBaseURL } from \"./better-auth-client.js\"\n\n/**\n * Minimal bearer-token fetch for the CLI (ADR-020).\n *\n * Used only by auth status and auth logout, both of which\n * need to call Better Auth endpoints with a bearer token\n * read from ~/.deessejs/auth.json. The typed client\n * (apps/cli/src/lib/auth/store/better-auth-client.ts) does\n * not support this case: it sends the bearer via its\n * cookie-based session, not a caller-supplied token.\n *\n * The helper injects two headers:\n * - User-Agent: DeesseJS CLI/<version> (per ADR-020\n * limitation 1 mitigation, the V1 label for the\n * /settings/sessions view of CLI sessions)\n * - Authorization: Bearer <access_token> (caller-supplied)\n *\n * Path is appended to (baseURL + API_AUTH_PATH) so the\n * request is absolute. baseURL is resolved by the same\n * helper the typed client uses (`resolveBaseURL` from\n * better-auth-client.ts) so production and tests share\n * the same resolution. No hardcoded localhost default\n * here: end users who install the CLI do not control\n * their shell env, and pointing to localhost would be a\n * silent failure.\n */\nfunction authUrl(path: string): string {\n\tconst normalised = path.startsWith(\"/\") ? path.slice(1) : path\n\treturn `${resolveBaseURL()}${API_AUTH_PATH}/${normalised}`\n}\n\nexport function bearerFetch(\n\tpath: string,\n\taccessToken: string,\n\tinit?: RequestInit,\n): Promise<Response> {\n\tconst headers = new Headers(init?.headers)\n\theaders.set(\"user-agent\", `DeesseJS CLI/${readPackageVersion()}`)\n\theaders.set(\"authorization\", `Bearer ${accessToken}`)\n\treturn fetch(authUrl(path), {\n\t\t...init,\n\t\theaders,\n\t})\n}\n","import { cliDeviceExpired, cliDeviceDenied, CliError } from \"../../../errors/index.js\"\n\n/**\n * Polling-protocol error mapper (ADR-020).\n *\n * Translates Better Auth device-flow error codes (per the\n * plugin's `error-codes.mjs`) into the CLI's closed list of\n * public error codes (ADR-010 §2). The CLI surfaces the cause\n * instead of masking it with `not_found`.\n *\n * Mapping (per ADR-020):\n *\n * authorization_pending — not an error; the polling loop\n * continues and ignores the return value\n * slow_down — caller is expected to bump the local\n * interval by 5s and continue (the mapper returns\n * null to signal 'no error, keep polling')\n * expired_token — cli_device_expired\n * access_denied — cli_device_denied\n * invalid_grant — cli_device_expired (code is invalid or\n * already used; the user's only recourse is to retry)\n * invalid_client — cli_device_expired (CLI is not a\n * registered device client; same recovery: retry)\n *\n * The function returns either `null` (continue polling) or\n * a `CliError` to surface. The caller decides whether the\n * CliError is a hard exit or just a log line; per ADR-010\n * §2 the closed-list codes are user-visible.\n */\nexport type BetterAuthDeviceErrorCode =\n | \"authorization_pending\"\n | \"slow_down\"\n | \"expired_token\"\n | \"access_denied\"\n | \"invalid_grant\"\n | \"invalid_client\"\n\nexport const mapPollingError = (\n code: BetterAuthDeviceErrorCode | string,\n): CliError | null => {\n switch (code) {\n case \"authorization_pending\":\n case \"slow_down\":\n // Not errors. Caller treats null as \"continue polling\";\n // for `slow_down`, the caller is also expected to bump\n // its local interval by 5 seconds.\n return null\n case \"access_denied\":\n return cliDeviceDenied()\n case \"expired_token\":\n case \"invalid_grant\":\n case \"invalid_client\":\n return cliDeviceExpired()\n default:\n // Unknown Better Auth code: treat as expired for the\n // purposes of recovery. The user retries the flow.\n return cliDeviceExpired()\n }\n}\n","import { cliDeviceExpired } from \"../../../errors/index.js\"\nimport { sleep } from \"../../../utils/sleep.js\"\n\nimport { bearerFetch } from \"../store/bearer-fetch.js\"\nimport { createCliAuthClient } from \"../store/better-auth-client.js\"\n\nimport { mapPollingError } from \"./polling-errors.js\"\n\n/**\n * Device-flow orchestration (ADR-020, ADR-022).\n *\n * Three pure functions that the `login` command composes:\n *\n * - requestDeviceCode: hits /device/code, returns the\n * issued code + the URL to open + an absolute deadline\n * matching the device-code TTL (30 minutes, per\n * Better Auth's plugin default).\n *\n * - pollForToken: hits /device/token until the Better\n * Auth error codes say \"approved\" (returns the token)\n * or one of the closed-list terminal codes says \"no\".\n * Honors slow_down by bumping the local interval by 5\n * seconds. Per ADR-020, silent on authorization_pending\n * and slow_down; surfaces cli_device_expired /\n * cli_device_denied per the polling-errors mapper.\n *\n * - fetchUserIdentity (ADR-022): resolves the user tied\n * to the device-flow access token by calling\n * /get-session with `Authorization: Bearer <token>`.\n * Uses `bearerFetch` (raw fetch) instead of the typed\n * Better Auth client because the typed client is\n * cookie-based and the CLI has no cookie jar. Throws\n * `cliDeviceExpired` (not a soft null) when the server\n * rejects the token or returns no user — a token\n * without a resolvable identity is a server-side or\n * wire-protocol regression, not a normal state. See\n * ADR-022 §\"Decision / 1. CLI side\".\n *\n * Polling interval constants live here, not in login.ts,\n * because they are part of the device-flow protocol, not\n * the commander wrapper around it.\n */\n\nconst POLL_INTERVAL_MS = 5_000\nconst POLL_INTERVAL_WITH_BACKOFF_MS = 10_000\nconst TOTAL_TIMEOUT_MS = 30 * 60 * 1_000 // 30 minutes per device-code TTL\n\nexport type IssuedDeviceCode = {\n\turl: string\n\tdeviceCode: string\n\texpiresBy: number\n}\n\nexport type ResolvedToken = {\n\taccessToken: string\n}\n\nexport type UserIdentity = {\n\tid: string\n\temail?: string\n\tname?: string\n}\n\nexport const requestDeviceCode = async (): Promise<IssuedDeviceCode> => {\n\tconst authClient = createCliAuthClient()\n\tconst { data, error } = await authClient.device.code({\n\t\tclient_id: \"deessejs-cli\",\n\t})\n\tif (error || !data) {\n\t\tconst description =\n\t\t\t(error as { error_description?: string } | null)?.error_description ??\n\t\t\t\"unknown error\"\n\t\tthrow cliDeviceExpired(`could not obtain a device code: ${description}`)\n\t}\n\treturn {\n\t\turl: data.verification_uri_complete,\n\t\tdeviceCode: data.device_code,\n\t\texpiresBy: Date.now() + TOTAL_TIMEOUT_MS,\n\t}\n}\n\nexport const pollForToken = async (\n\tdeviceCode: string,\n\texpiresBy: number,\n): Promise<ResolvedToken> => {\n\tlet interval = POLL_INTERVAL_MS\n\tfor (;;) {\n\t\tif (Date.now() >= expiresBy) {\n\t\t\tthrow cliDeviceExpired(\"device flow timed out after 30 minutes\")\n\t\t}\n\t\tawait sleep(interval)\n\t\tconst authClient = createCliAuthClient()\n\t\tconst { data, error } = await authClient.device.token({\n\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\tdevice_code: deviceCode,\n\t\t\tclient_id: \"deessejs-cli\",\n\t\t})\n\t\tif (data) {\n\t\t\t// The plugin types `data` as `unknown` in some\n\t\t\t// Better Auth 1.6.x minor versions; the access\n\t\t\t// token field is stable across versions.\n\t\t\tconst token = (data as { access_token: string }).access_token\n\t\t\treturn { accessToken: token }\n\t\t}\n\t\t// The plugin's error envelope is\n\t\t// { error: \"access_denied\", error_description: \"...\" }\n\t\t// (per better-auth/dist/plugins/device-authorization/\n\t\t// routes.mjs deviceTokenErrorSchema). The field name is\n\t\t// `error`, not `code`. Reading `code` here silently\n\t\t// yields undefined and the polling loop falls through\n\t\t// to the \"no error code\" guard below, which throws\n\t\t// cliDeviceExpired instead of the actual reason.\n\t\tconst code = (error as { error?: string } | null)?.error\n\t\tif (!code) {\n\t\t\tthrow cliDeviceExpired(\n\t\t\t\t\"token endpoint returned no data and no error code\",\n\t\t\t)\n\t\t}\n\t\tconst mapped = mapPollingError(code)\n\t\tif (mapped !== null) {\n\t\t\tthrow mapped\n\t\t}\n\t\t// slow_down: bump the local interval for the next poll.\n\t\t// Per ADR-020, slow_down and pending are silent.\n\t\tinterval = POLL_INTERVAL_WITH_BACKOFF_MS\n\t}\n}\n\nexport const fetchUserIdentity = async (\n\taccessToken: string,\n): Promise<UserIdentity> => {\n\tconst response = await bearerFetch(\"get-session\", accessToken, { method: \"GET\" })\n\tif (!response.ok) {\n\t\tthrow cliDeviceExpired(\n\t\t\t`server issued a session token but /get-session rejected it (HTTP ${response.status})`,\n\t\t)\n\t}\n\tconst body = (await response.json()) as { user?: UserIdentity }\n\tif (!body.user) {\n\t\tthrow cliDeviceExpired(\n\t\t\t\"server issued a session token but no user identity was attached\",\n\t\t)\n\t}\n\treturn body.user\n}\n","import open from \"open\"\n\n/**\n * Open the device-flow verification URL in the OS-default\n * browser (ADR-020). The `open` package handles per-OS\n * dispatch (`open` on macOS, `xdg-open` on Linux,\n * `start` on Windows) plus WSL detection in one line.\n *\n * `wait: false` returns once the child process is spawned\n * (not when the browser closes). The caller does not await\n * the user-facing flow: the user clicks Approve in the\n * browser, the poll loop in the caller resolves.\n */\nexport const openVerificationUrl = async (url: string): Promise<void> => {\n\tawait open(url, { wait: false })\n}\n","import { existsSync, mkdirSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\n/**\n * On-disk response cache for the CLI.\n *\n * Layout: one file per endpoint under ~/.deessejs/. Each file holds the\n * raw response body plus the ETag the server returned, so we can reissue\n * If-None-Match on the next call and serve the cached body on a 304.\n *\n * No TTL: the server is the source of truth for freshness. A cache entry\n * is \"valid\" if either (a) we can revalidate it against the server and\n * the server says 304, or (b) we're in --offline mode and any prior\n * response is better than nothing.\n *\n * Corruption policy: a malformed file is treated as cache-miss. We do\n * not auto-overwrite it — if the user manually edited a cache file, we\n * surface that as a warning and let them decide. The next successful\n * network call will overwrite the file normally.\n *\n * The home directory is read lazily on each call to `cacheDir` so that\n * tests can override `HOME` / `USERPROFILE` between calls and pick up\n * the new value. Computing CACHE_DIR at module load time would freeze\n * the path on whatever os.homedir() returns when this file is first\n * imported, which makes integration testing impossible.\n */\n\n/**\n * Return the cache directory, computed at call time so the\n * process.env.HOME / USERPROFILE override pattern works\n * in tests.\n */\nexport const cacheDir = (): string => join(homedir(), \".deessejs\")\n\nexport const ensureCacheDir = (): void => {\n const dir = cacheDir()\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Absolute path to a file under the cache directory.\n * Computed at call time (no module-level capture) so tests\n * can override HOME / USERPROFILE and have the path\n * recomputed on the next invocation.\n */\nexport const cachePath = (name: string): string => join(cacheDir(), name)\n","import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\"\nimport { dirname } from \"node:path\"\n\nimport { cachePath } from \"../../../cache/location.js\"\n\n/**\n * CLI session-token store (ADR-020).\n *\n * Holds the Better Auth session token returned by\n * /device/token after the user approves the device flow in\n * the browser. The file lives at `~/.deessejs/auth.json`,\n * the same directory as the templates cache.\n *\n * File format (ADR-020 opaque-cache rule, ADR-010 §4):\n * {\n * \"access_token\": \"<session.token>\",\n * \"user\": { \"id\": \"...\", \"email\": \"...\", \"name\": \"...\" },\n * \"fetchedAt\": \"2026-08-17T...\"\n * }\n *\n * The shape may change between CLI minor versions without\n * bumping the major. Tooling that reads auth.json directly\n * reads the cache at its own risk.\n */\n\n/**\n * Absolute path to the auth.json file. Computed at call\n * time (no module-level capture) so tests can override\n * HOME / USERPROFILE and have the path recomputed on\n * the next invocation. Stable for the lifetime of a\n * single process invocation under a given HOME.\n */\nexport const AUTH_PATH = (): string => cachePath(\"auth.json\")\n\n// Convenience alias: readAuth / writeAuth / clearAuth all\n// resolve AUTH_PATH() once per call so they see the same\n// value for the duration of a single operation.\nconst resolveAuthPath = (): string => AUTH_PATH()\n\n/** Stored session shape. JSON-serialisable. */\nexport interface StoredAuth {\n\taccess_token: string\n\tuser: { id: string; email?: string; name?: string }\n\tfetchedAt: string\n}\n\nconst ensureDir = (path: string): void => {\n\tif (!existsSync(dirname(path))) {\n\t\tmkdirSync(dirname(path), { recursive: true })\n\t}\n}\n\nconst chmodOwnerOnly = (path: string): void => {\n\t// fs.writeFile's `mode` is masked by the process umask, so\n\t// the explicit chmod after the write is the authoritative\n\t// step. Without it, a default umask of 022 leaves the file\n\t// world-readable on Linux/macOS. The mode 0o600 means\n\t// read/write for the owner only.\n\ttry {\n\t\tchmodSync(path, 0o600)\n\t} catch {\n\t\t// chmod may fail on Windows in tests; the writeAuth\n\t\t// caller treats chmod failure as a write failure (the\n\t\t// CLI exits through CliError). Silent here means we\n\t\t// only fall through if chmod itself is unsupported on\n\t\t// the platform, which is rare on Node targets.\n\t}\n}\n\n/**\n * Read the stored auth.json. Returns null when the file does\n * not exist or is malformed. A malformed file is treated as\n * \"no session\" rather than a hard error: the next command\n * either re-runs the login flow or surfaces the parse error\n * explicitly via the CLI error path.\n */\nexport const readAuth = (): StoredAuth | null => {\n\tconst path = resolveAuthPath()\n\tif (!existsSync(path)) return null\n\ttry {\n\t\tconst text = readFileSync(path, \"utf8\")\n\t\tconst parsed = JSON.parse(text) as StoredAuth\n\t\tif (typeof parsed.access_token !== \"string\") return null\n\t\treturn parsed\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Write the auth.json file with mode 0o600. The function\n * throws on filesystem failure (caller decides how to surface).\n */\nexport const writeAuth = (auth: StoredAuth): void => {\n\tconst path = resolveAuthPath()\n\tensureDir(path)\n\tconst text = JSON.stringify(auth, null, 2)\n\twriteFileSync(path, text, { mode: 0o600 })\n\tchmodOwnerOnly(path)\n}\n\n/**\n * Delete the auth.json file. No-op when the file does not\n * exist. Used by `deesse auth logout` and on explicit\n * server-side session invalidation.\n */\nexport const clearAuth = (): void => {\n\tconst path = resolveAuthPath()\n\tif (!existsSync(path)) return\n\tunlinkSync(path)\n}\n\n// Exposed for the rare caller that needs the resolved path\n// without importing auth.json by name (test fixtures).\nexport const authPath = AUTH_PATH\n","import pc from \"picocolors\"\n\nimport type { Template } from \"../api/index.js\"\n\nexport const printTemplatesTable = (templates: Template[]): void => {\n if (templates.length === 0) {\n process.stdout.write(pc.dim(\"No templates available.\\n\"))\n return\n }\n const headers = [\"slug\", \"name\", \"category\", \"license\"]\n const rows = templates.map((t) => [\n t.slug,\n t.name,\n t.category,\n t.license,\n ])\n printAlignedTable([headers, ...rows])\n}\n\nexport const printTemplateInfo = (t: Template): void => {\n const lines: Array<[string, string]> = [\n [\"slug\", t.slug],\n [\"name\", t.name],\n [\"description\", t.description],\n [\"category\", t.category],\n [\"license\", t.license],\n [\"repo\", `${t.owner}/${t.repo}`],\n [\"labels\", t.labels.join(\", \") || pc.dim(\"(none)\")],\n ]\n if (t.image) lines.push([\"image\", t.image])\n\n const labelWidth = Math.max(...lines.map(([l]) => l.length))\n for (const [label, value] of lines) {\n process.stdout.write(\n `${pc.dim(label.padEnd(labelWidth))} ${value}\\n`,\n )\n }\n}\n\nconst printAlignedTable = (rows: string[][]): void => {\n const firstRow = rows[0]\n if (!firstRow) return\n const widths = firstRow.map((_, col) =>\n Math.max(...rows.map((row) => row[col]?.length ?? 0)),\n )\n for (const row of rows) {\n process.stdout.write(\n row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(\" \") + \"\\n\",\n )\n }\n}\n","import pc from \"picocolors\"\n\nimport type { CliError } from \"../errors/index.js\"\n\nexport const printJson = (value: unknown): void => {\n process.stdout.write(JSON.stringify(value, null, 2) + \"\\n\")\n}\n\nexport const printError = (err: CliError): void => {\n process.stderr.write(\n `${pc.red(\"Error\")}: ${err.message}\\n` +\n (err.hint ? `${pc.dim(\"Hint\")}: ${err.hint}\\n` : \"\") +\n `${pc.dim(\"Code\")}: ${err.code}\\n`,\n )\n}\n\nexport { printTemplatesTable, printTemplateInfo } from \"./table.js\"\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport {\n\tfetchUserIdentity,\n\topenVerificationUrl,\n\tpollForToken,\n\trequestDeviceCode,\n} from \"../../lib/auth/flow/index.js\"\nimport { writeAuth } from \"../../lib/auth/store/store.js\"\nimport { type CliError } from \"../../errors/index.js\"\nimport { printError, printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth login (ADR-020, ADR-022).\n *\n * Commander wrapper around the device-flow orchestration in\n * apps/cli/src/lib/auth/flow/. This file owns the command\n * surface: option parsing, spinners, output formatting, and\n * exit-code mapping. The flow itself (request / poll /\n * open-browser) lives in the auth-flow module and is\n * reusable from other commands (e.g. a future `auth\n * reauth`) without duplicating orchestration.\n *\n * Flow summary (full detail in apps/cli/src/lib/auth/flow/):\n * 1. requestDeviceCode: POST /device/code\n * 2. openVerificationUrl: spawn the OS browser\n * 3. pollForToken: poll /device/token until approved\n * 4. fetchUserIdentity (ADR-022): GET /get-session with\n * `Authorization: Bearer <access_token>` to resolve\n * the user. Throws cli_device_expired if the server\n * rejects the token or returns no user — a soft\n * `?? { id: \"\" }` fallback would write a fake user to\n * ~/.deessejs/auth.json and surface as \"logged in as\n * unknown user\" downstream (Bug A).\n * 5. writeAuth: persist ~/.deessejs/auth.json with mode 0600\n */\nexport const loginCommand = new Command(\"login\")\n\t.description(\"Authorize this machine against the DeesseJS server\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst spinner = opts.json\n\t\t\t? null\n\t\t\t: ora(\"Requesting device code...\").start()\n\t\ttry {\n\t\t\tconst issued = await requestDeviceCode()\n\t\t\tspinner?.stop()\n\n\t\t\tif (!opts.json) {\n\t\t\t\tconsole.log()\n\t\t\t\tconsole.log(\n\t\t\t\t\tpc.cyan(\n\t\t\t\t\t\t`Open the following URL in your browser if it doesn't open automatically:`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\tconsole.log(pc.bold(issued.url))\n\t\t\t\tconsole.log()\n\t\t\t}\n\n\t\t\tawait openVerificationUrl(issued.url)\n\n\t\t\tconst pollSpinner = opts.json\n\t\t\t\t? null\n\t\t\t\t: ora(\"Waiting for browser approval...\").start()\n\t\t\ttry {\n\t\t\t\tconst token = await pollForToken(issued.deviceCode, issued.expiresBy)\n\t\t\t\tconst user = await fetchUserIdentity(token.accessToken)\n\t\t\t\twriteAuth({\n\t\t\t\t\taccess_token: token.accessToken,\n\t\t\t\t\tuser,\n\t\t\t\t\tfetchedAt: new Date().toISOString(),\n\t\t\t\t})\n\t\t\t\tpollSpinner?.stop()\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({ ok: true, user })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.green(\"✓ logged in as \") +\n\t\t\t\t\t\t\tpc.bold(user.email ?? user.name ?? user.id),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpollSpinner?.stop()\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tif (e instanceof Error && \"code\" in e && \"exitCode\" in e) {\n\t\t\t\tconst err = e as CliError\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({ ok: false, code: err.code, message: err.message })\n\t\t\t\t} else {\n\t\t\t\t\tprintError(err)\n\t\t\t\t}\n\t\t\t\t// Rethrow so the index.ts last-resort handler\n\t\t\t\t// calls process.exit(err.exitCode()). This is\n\t\t\t\t// also what makes the command testable: vitest\n\t\t\t\t// catches the throw, asserts on the error shape,\n\t\t\t\t// and the production path still exits with the\n\t\t\t\t// right code (via the central handler).\n\t\t\t\tthrow err\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t})\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport { bearerFetch } from \"../../lib/auth/store/bearer-fetch.js\"\nimport { readAuth, type StoredAuth } from \"../../lib/auth/store/store.js\"\nimport { internal } from \"../../errors/index.js\"\nimport { printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth status (ADR-020).\n *\n * Read-only command. Validates the stored session token\n * against the server's /get-session endpoint. The typed\n * better-auth client cannot drive this case (it sends the\n * session cookie, not a caller-supplied bearer token),\n * so this command uses the bearer-fetch helper directly.\n *\n * Terminal states:\n * - No auth.json: yellow notice, exit 0. No session is the\n * normal pre-login state.\n * - Token still valid server-side: green ✓, identity\n * echoed back, fetchedAt shown.\n * - Token revoked or expired server-side: yellow notice,\n * stale identity shown for context, exit 0. The user\n * reruns auth login.\n *\n * The token itself is never echoed.\n */\n\ntype StoredUser = StoredAuth[\"user\"]\n\nconst formatStored = (stored: StoredAuth): string => {\n\tconst userBits: string[] = []\n\tif (stored.user.email) userBits.push(stored.user.email)\n\tif (stored.user.name) userBits.push(stored.user.name)\n\tif (stored.user.id) userBits.push(`(${stored.user.id})`)\n\tconst who = userBits.length > 0 ? userBits.join(\" \") : \"unknown user\"\n\tconst when = new Date(stored.fetchedAt).toLocaleString()\n\treturn `${who} — token fetched ${when}`\n}\n\nconst validateSession = async (\n\taccessToken: string,\n): Promise<StoredUser | null> => {\n\tconst res = await bearerFetch(\"get-session\", accessToken, { method: \"GET\" })\n\tif (res.status !== 200) return null\n\tconst body = (await res.json()) as { user?: StoredUser } | null\n\treturn body?.user ?? null\n}\n\nexport const statusCommand = new Command(\"status\")\n\t.description(\"Show the current CLI auth session\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst stored = readAuth()\n\t\tif (!stored) {\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: false, reason: \"no_session\" })\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\"no active session. Run `deesse auth login` to authorise this machine.\",\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst spinner = opts.json ? null : ora(\"Checking session...\").start()\n\t\ttry {\n\t\t\tconst user = await validateSession(stored.access_token)\n\t\t\tif (!user) {\n\t\t\t\tspinner?.stop()\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\treason: \"session_invalid\",\n\t\t\t\t\t\tstored: {\n\t\t\t\t\t\t\tuser: stored.user,\n\t\t\t\t\t\t\tfetchedAt: stored.fetchedAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\t\"The stored token no longer matches an active session on the server. Run `deesse auth login` again.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\tconsole.log(pc.dim(formatStored(stored)))\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tspinner?.stop()\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true, user, fetchedAt: stored.fetchedAt })\n\t\t\t} else {\n\t\t\t\tconsole.log()\n\t\t\t\tconsole.log(pc.green(\"✓ active session\"))\n\t\t\t\tconsole.log(pc.dim(formatStored({ ...stored, user })))\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tthrow internal(e instanceof Error ? e.message : String(e))\n\t\t}\n\t})\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport { bearerFetch } from \"../../lib/auth/store/bearer-fetch.js\"\nimport { clearAuth, readAuth } from \"../../lib/auth/store/store.js\"\nimport { internal } from \"../../errors/index.js\"\nimport { printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth logout (ADR-020).\n *\n * Sequence:\n * 1. POST /api/v1/auth/sign-out with the stored token to\n * invalidate the session server-side.\n * 2. Delete ~/.deessejs/auth.json regardless of the\n * sign-out outcome: a stale file is worse than a\n * missing one (every subsequent command would silently\n * use a dead token).\n *\n * Uses bearerFetch (not the typed client) because the\n * client sends the session cookie, not a caller-supplied\n * bearer token. The two helper files (better-auth-client.ts\n * and bearer-fetch.ts) are deliberately complementary: the\n * typed client owns the device-flow HTTP shape; the bearer\n * helper owns the two read-only endpoints that need a\n * caller-supplied token.\n *\n * If the file does not exist, the command exits 0 silently:\n * there is no session to revoke.\n */\n\nexport const logoutCommand = new Command(\"logout\")\n\t.description(\"Sign out this machine and remove the stored token\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst stored = readAuth()\n\t\tif (!stored) {\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true, reason: \"no_session\" })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst spinner = opts.json\n\t\t\t? null\n\t\t\t: ora(\"Signing out...\").start()\n\t\ttry {\n\t\t\tconst res = await bearerFetch(\"sign-out\", stored.access_token, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\t})\n\t\t\t// We deliberately do NOT throw on a non-2xx here:\n\t\t\t// the local cache cleanup is the user-facing\n\t\t\t// outcome. A server-side failure (e.g. token\n\t\t\t// already revoked) is logged but the local file\n\t\t\t// is cleared regardless. The user's machine is\n\t\t\t// now in a \"no session\" state either way.\n\t\t\tif (res.status !== 200 && res.status !== 204) {\n\t\t\t\tspinner?.stop()\n\t\t\t\tif (!opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\t`Server returned HTTP ${res.status} on sign-out; clearing the local token file anyway.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tspinner?.stop()\n\t\t\t}\n\t\t\tclearAuth()\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true })\n\t\t\t} else {\n\t\t\t\tconsole.log(pc.green(\"✓ signed out\"))\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tclearAuth()\n\t\t\tthrow internal(e instanceof Error ? e.message : String(e))\n\t\t}\n\t})\n","import { API_BASE_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../api/self-version.js\"\n\nexport type CliVersionResponse = {\n version: string\n minSupported: string\n}\n\nconst SEMVER_RE = /^\\d+\\.\\d+\\.\\d+$/\n\nconst parseSemver = (v: string): [number, number, number] | null => {\n if (!SEMVER_RE.test(v)) return null\n const [major, minor, patch] = v.split(\".\").map(Number)\n return [major ?? 0, minor ?? 0, patch ?? 0]\n}\n\nconst compareSemver = (a: string, b: string): number => {\n const pa = parseSemver(a)\n const pb = parseSemver(b)\n if (!pa || !pb) return 0 // unknown: don't warn\n if (pa[0] !== pb[0]) return pa[0] - pb[0]\n if (pa[1] !== pb[1]) return pa[1] - pb[1]\n return pa[2] - pb[2]\n}\n\n/**\n * Non-blocking version probe.\n *\n * Calls `${API_BASE_PATH}/version` (a system route per ADR-011, served\n * by Hono direct, not through oRPC). If the local CLI version is\n * strictly below minSupported, prints a warning to stderr. The caller\n * does NOT abort; the user might have a workflow that depends on the\n * old version. The warning is loud but not authoritative.\n *\n * Failures (network, parse, server error) are swallowed silently: the\n * version check is best-effort, never the reason a command fails.\n *\n * Per ADR-021: the URL is composed via `new URL(path, base)`. The\n * host is read from `DEESSEJS_API_URL` (the canonical CLI override)\n * with fallback to `DEFAULT_API_URL = \"https://app.deessejs.com\"`.\n * The shared `resolveBaseURL()` lives in `apps/cli/src/api/client.ts`;\n * this file duplicates the resolution (a one-line `new URL(raw)`)\n * because the version probe runs at startup before the oRPC link is\n * constructed and importing the oRPC module would drag `node:fs`\n * transitively (the CLI's tsup bundle is intentionally slim).\n */\nexport const maybeWarnAboutOutdatedCli = async (): Promise<void> => {\n let bodyText: string\n try {\n const raw =\n process.env.DEESSEJS_API_URL ?? \"https://app.deessejs.com\"\n const versionUrl = new URL(`${API_BASE_PATH}/version`, raw).toString()\n const res = await fetch(versionUrl)\n if (res.status !== 200) return\n bodyText = await res.text()\n } catch {\n return\n }\n\n let parsed: CliVersionResponse\n try {\n parsed = JSON.parse(bodyText) as CliVersionResponse\n } catch {\n return\n }\n if (\n typeof parsed.version !== \"string\" ||\n typeof parsed.minSupported !== \"string\"\n ) {\n return\n }\n\n const localVersion = readPackageVersion()\n if (compareSemver(localVersion, parsed.minSupported) < 0) {\n process.stderr.write(\n `\\n⚠ deessejs-cli ${localVersion} is below the minimum supported version (${parsed.minSupported}).\\n` +\n ` Upgrade: pnpm dlx @deessejs/cli@latest\\n\\n`,\n )\n }\n}\n","import {\n ClientRetryPlugin,\n RetryAfterPlugin,\n} from \"@orpc/client/plugins\"\nimport { RPCLink } from \"@orpc/client/fetch\"\nimport { createORPCClient } from \"@orpc/client\"\nimport type { RouterClient } from \"@orpc/server\"\n\nimport { appRouter } from \"@workspace/api/router\"\nimport { API_RPC_PATH } from \"@workspace/api/base-path\"\n\n/**\n * Typed oRPC link for the CLI.\n *\n * Internal to the CLI. The public surface (`fetchTemplates`) lives in\n * ../api/index.ts. Tests that target the typed client (Server-Side Client\n * pattern) import `appRouter` directly from `@workspace/api/router` and\n * bypass this module entirely.\n *\n * Resilience is delegated to the official oRPC plugins\n * (`ClientRetryPlugin`, `RetryAfterPlugin`); the HTTP fetch itself is\n * `globalThis.fetch` (the oRPC default). The plugins cover retry on\n * transient network errors and on 429 / 503 honouring `Retry-After`.\n *\n * See `apps/internal-documentation/content/docs/knowledge-base/orpc/client-plugins.mdx`\n * for the full coverage analysis.\n *\n * The previous custom `orpcFetch` hook (which injected the User-Agent\n * header and did bespoke retries) was removed in favour of the plugins.\n * The User-Agent header is no longer sent from the typed client. The\n * system-level version probe (`apps/cli/src/version/check.ts`) still\n * sends a User-Agent because it hits a Hono-direct endpoint, not an\n * oRPC procedure.\n *\n * Per ADR-021: the URL is composed via `new URL(path, base)` rather\n * than string concatenation; the leading-slash rule of `new URL`\n * collapses any trailing slash on the base. The trailing-slash guard\n * for the CLI is `resolveBaseURL()` below.\n */\n/**\n * Production default for the CLI's `baseURL`. Mirrors\n * `apps/cli/src/lib/auth/store/better-auth-client.ts` so production\n * and tests share the same resolution (per ADR-015/016: canonical\n * prod API host is `app.deessejs.com`, NOT `deessejs.com` which is\n * the marketing apex).\n */\nexport const DEFAULT_API_URL = \"https://app.deessejs.com\"\n\n/**\n * Resolve the API base URL.\n *\n * Three sources, in priority order:\n * 1. `DEESSEJS_API_URL` env var (CI / dev override; never set by\n * end users in practice).\n * 2. The baked-in default above (production).\n * 3. A thrown validation error when source 1 is set but malformed.\n *\n * Per ADR-021: this is the CLI's analogue of the\n * `apps/web/src/lib/orpc.ts` URL composition. The CLI cannot import\n * `@workspace/env/server` because the env package is private to the\n * monorepo (`packages/env/package.json: private: true`) and the CLI\n * is published on npm. The naming divergence (`DEESSEJS_API_URL`\n * here vs. `API_BASE_URL` in apps/web and apps/app) is intentional —\n * the env loader on the web side owns the canonical name; the CLI\n * uses a different namespace because its published tarball carries a\n * single env var and there is no loader to alias it through.\n */\nexport function resolveBaseURL(): string {\n\tconst raw = process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL\n\ttry {\n\t\tconst parsed = new URL(raw)\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\t\tthrow new Error(\n\t\t\t\t`DEESSEJS_API_URL must use http or https (got ${parsed.protocol ?? \"no protocol\"})`,\n\t\t\t)\n\t\t}\n\t\treturn parsed.toString().replace(/\\/$/, \"\")\n\t} catch (e) {\n\t\tconst detail = e instanceof Error ? e.message : String(e)\n\t\tthrow new Error(\n\t\t\t`DEESSEJS_API_URL is malformed: ${detail}. ` +\n\t\t\t\t`Expected a full URL like https://api.example.com.`,\n\t\t)\n\t}\n}\n\n/**\n * Whether an error thrown from the wire layer is a transient network\n * error (DNS failure, TCP reset, timeout). These are worth retrying;\n * typed ORPCError and other application errors are not.\n */\nconst isTransientNetworkError = (e: unknown): boolean =>\n e instanceof TypeError\n\n/**\n * RPCLink URL must be absolute in a Node CLI context.\n *\n * The oRPC `RPCLink` resolves a relative `url` against the host page's\n * origin via `new URL(...)`, which is meaningless in a Node binary (no\n * `window.location`). Passing `API_RPC_PATH` (= `\"/api/v1/rpc\"`) as-is\n * raised `TypeError: Invalid URL` on every command, surfaced to users\n * as `network_error` with hint `Invalid URL` despite the network being\n * fine.\n *\n * Fix: join `resolveBaseURL()` and `API_RPC_PATH` to an absolute URL\n * via `new URL(path, base)` so the leading-slash rule collapses any\n * trailing slash on the base. `resolveBaseURL()` already strips a\n * trailing slash as a first line of defence; `new URL` is the second.\n */\nconst link = new RPCLink({\n url: new URL(API_RPC_PATH, resolveBaseURL()).toString(),\n plugins: [\n new RetryAfterPlugin(),\n new ClientRetryPlugin({\n default: {\n retry: 3,\n shouldRetry: ({ error }) => isTransientNetworkError(error),\n },\n }),\n ],\n})\n\nexport type ORPCClient = RouterClient<typeof appRouter>\n\nexport const orpc: ORPCClient = createORPCClient(link)\n","import { toORPCError } from \"@orpc/client\"\nimport { TemplatesListResponseV1 } from \"@workspace/contracts/v1\"\n\nimport { networkError } from \"../errors/index.js\"\nimport { maybeWarnAboutOutdatedCli } from \"../version/check.js\"\nimport { orpc } from \"./client.js\"\n\nexport type Template = TemplatesListResponseV1[\"templates\"][number]\n\nexport type FetchOptions = {\n /** Skip the version probe. Used by tests and by the version probe itself. */\n skipVersionCheck?: boolean\n}\n\n/**\n * Normalise an error thrown from the typed oRPC client.\n *\n * Uses `toORPCError` from `@orpc/client` to do the shape matching. This is\n * the canonical entry point: the lib does the matching internally and\n * exposes `[Symbol.hasInstance]` for the Next.js multi-context case.\n *\n * In V1 the only mapping is `TypeError -> networkError`, because that\n * is the only error the global `fetch` throws for an unreachable network.\n * `ORPCError` instances are propagated as-is: the calling command knows\n * the procedure semantics and decides how to surface them.\n */\nexport const normaliseError = (e: unknown): Error => {\n // The global fetch throws a TypeError for unreachable networks.\n // `toORPCError` from @orpc/client wraps anything into an ORPCError\n // (replacing the original cause), so we must check TypeError BEFORE\n // calling it.\n if (e instanceof TypeError) {\n return networkError(e.message)\n }\n // For anything that is already (or can be normalised to) an\n // ORPCError, propagate as-is. The calling command knows the\n // procedure semantics and decides how to surface them.\n return toORPCError(e) as Error\n}\n\n/**\n * Fetch the templates registry.\n *\n * Flow:\n * 1. (If not skipVersionCheck) probe /version and warn if outdated.\n * Failure here is silent — version check is best-effort.\n * 2. Call templates.list on the shared typed client. Retry on\n * 5xx and 429 is handled by the official oRPC plugins configured\n * in ./client.ts.\n * 3. Surface typed errors via `normaliseError`.\n *\n * The URL is fixed at `API_RPC_PATH` (imported from\n * `@workspace/api/base-path`). A per-command override is intentionally\n * not part of the public surface in V1.\n *\n * Testing:\n * - The procedure contract is tested via the Server-Side Client\n * pattern in `test/contract/orpc-to-cli-error.test.ts`. Call\n * `appRouter.templates.list()` directly, no HTTP.\n */\nexport const fetchTemplates = async (\n options: FetchOptions = {},\n): Promise<Template[]> => {\n if (!options.skipVersionCheck) {\n await maybeWarnAboutOutdatedCli()\n }\n\n try {\n const result = await orpc.templates.list()\n return result.templates\n } catch (e) {\n throw normaliseError(e)\n }\n}\n","import { spawn as nodeSpawn } from \"node:child_process\"\n\n// Dummy comment added to exercise the CI workflows on a no-op change.\n// No runtime behavior change; tests and bundle are unaffected.\n\nexport type SpawnOptions = {\n cwd?: string\n env?: NodeJS.ProcessEnv\n stdio?: \"inherit\" | \"pipe\" | \"ignore\"\n /** If true, do not throw on non-zero exit codes. Default is `true` (no throw). */\n reject?: boolean\n}\n\n/**\n * Run a command and resolve with its exit code. Never throws on non-zero by\n * default; pass `reject: true` to opt into throwing.\n */\nexport const spawn = (\n command: string,\n args: string[],\n options: SpawnOptions = {},\n): Promise<number> => {\n const { cwd, env, stdio = \"inherit\", reject = false } = options\n return new Promise((resolve, rejectFn) => {\n const child = nodeSpawn(command, args, {\n cwd,\n env: env ?? process.env,\n stdio,\n shell: false,\n })\n child.on(\"error\", (err) => rejectFn(err))\n child.on(\"exit\", (code) => {\n const exit = code ?? 1\n if (reject && exit !== 0) {\n rejectFn(new Error(`${command} exited with code ${exit}`))\n } else {\n resolve(exit)\n }\n })\n })\n}","import { spawn } from \"./spawn.js\"\nimport { gitNotInstalled } from \"../errors/index.js\"\n\nexport type CloneResult = {\n ref: string\n attempts: string[]\n}\n\n/**\n * Clone a git repo to `dir`. Tries `main` first, then falls back to `master`.\n * Caller can pass an explicit `--ref` to override.\n */\nexport const cloneRepo = async (\n url: string,\n dir: string,\n requestedRef?: string,\n): Promise<CloneResult> => {\n const refs = requestedRef ? [requestedRef] : [\"main\", \"master\"]\n const attempts: string[] = []\n\n for (const ref of refs) {\n attempts.push(ref)\n const code = await spawn(\n \"git\",\n [\"clone\", \"--depth\", \"1\", \"--branch\", ref, url, dir],\n { stdio: \"inherit\", reject: false },\n )\n if (code === 0) {\n return { ref, attempts }\n }\n }\n\n // All attempts failed. Probe whether git is even installed.\n const probe = await spawn(\"git\", [\"--version\"], {\n stdio: \"ignore\",\n reject: false,\n })\n if (probe !== 0) {\n throw gitNotInstalled()\n }\n\n // Git works but neither ref matched. Re-throw with attempts context.\n throw new Error(\n `git clone failed for refs: ${refs.join(\", \")}. Tried: ${attempts.join(\", \")}.`,\n )\n}","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\"\n\nexport type PackageManagerInfo = {\n pm: PackageManager\n /** Raw value from packageManager field, e.g. \"pnpm@9.0.0\". May include version. */\n raw?: string\n}\n\n/**\n * Detect the package manager for a directory, in priority order:\n * 1. `packageManager` field in package.json (Corepack convention)\n * 2. Lockfile presence\n * 3. Returns null if nothing matches (caller decides whether to fail)\n */\nexport const detectPackageManager = (\n cwd: string,\n): PackageManagerInfo | null => {\n const pkg = readPackageJson(cwd)\n if (pkg?.packageManager) {\n const pm = parsePackageManagerField(pkg.packageManager)\n if (pm) return pm\n }\n\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return { pm: \"pnpm\" }\n if (existsSync(join(cwd, \"bun.lockb\"))) return { pm: \"bun\" }\n if (existsSync(join(cwd, \"yarn.lock\"))) return { pm: \"yarn\" }\n if (existsSync(join(cwd, \"package-lock.json\"))) return { pm: \"npm\" }\n\n return null\n}\n\nexport const getInstallCommand = (info: PackageManagerInfo): string => {\n switch (info.pm) {\n case \"pnpm\":\n return \"pnpm install\"\n case \"npm\":\n return \"npm install\"\n case \"yarn\":\n return \"yarn install\"\n case \"bun\":\n return \"bun install\"\n }\n}\n\nconst readPackageJson = (\n cwd: string,\n): { packageManager?: string } | null => {\n const path = join(cwd, \"package.json\")\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as {\n packageManager?: string\n }\n } catch {\n return null\n }\n}\n\nexport const parsePackageManagerField = (\n raw: string,\n): PackageManagerInfo | null => {\n // Format: \"<name>@<version>\" or just \"<name>\". Common names: pnpm, npm, yarn, bun.\n const name = raw.split(\"@\")[0]?.trim().toLowerCase()\n if (name === \"pnpm\" || name === \"npm\" || name === \"yarn\" || name === \"bun\") {\n return { pm: name, raw }\n }\n return null\n}","import { existsSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport {\n installFailed,\n internal,\n notFound,\n targetExists,\n} from \"../errors/index.js\"\nimport { printError, printJson } from \"../output/index.js\"\nimport { cloneRepo } from \"../utils/git.js\"\nimport {\n detectPackageManager,\n getInstallCommand,\n type PackageManagerInfo,\n} from \"../utils/detect-pm.js\"\nimport { spawn } from \"../utils/spawn.js\"\n\nexport const initCommand = new Command(\"init\")\n .description(\"Clone a template repo + install dependencies\")\n .argument(\"<slug>\", \"template slug (use `deessejs list` to see options)\")\n .option(\"--pm <name>\", \"override detected package manager (pnpm|npm|yarn|bun)\")\n .option(\"--dir <path>\", \"target directory (default: ./<slug>)\")\n .option(\"--ref <branch>\", \"git ref to clone (default: tries main, falls back to master)\")\n .option(\"--no-install\", \"skip the install step\")\n .option(\"--force\", \"overwrite target directory if it exists\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (\n slug: string,\n opts: {\n pm?: string\n dir?: string\n ref?: string\n install: boolean\n force?: boolean\n json?: boolean\n },\n ) => {\n try {\n const templates = await fetchTemplates()\n const template = templates.find((t) => t.slug === slug)\n if (!template) {\n throw notFound(\n slug,\n templates.map((t) => t.slug),\n )\n }\n\n const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`)\n if (existsSync(dir) && !opts.force) {\n throw targetExists(dir)\n }\n\n const repoUrl =\n template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`\n\n const cloneSpinner = ora(`Cloning ${pc.cyan(template.owner + \"/\" + template.repo)}...`).start()\n let cloneResult\n try {\n cloneResult = await cloneRepo(repoUrl, dir, opts.ref)\n cloneSpinner.succeed(`Cloned into ${pc.cyan(dir)} (ref: ${cloneResult.ref})`)\n } catch (err) {\n cloneSpinner.fail(\"Clone failed\")\n throw err\n }\n\n if (!opts.install) {\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: false,\n })\n } else {\n console.log(pc.dim(`\\nNext: cd ${dir} && <your package manager> install\\n`))\n }\n return\n }\n\n const VALID_PMS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const\n type ValidPm = (typeof VALID_PMS)[number]\n const pmInfo: PackageManagerInfo | null =\n opts.pm && (VALID_PMS as readonly string[]).includes(opts.pm)\n ? { pm: opts.pm as ValidPm }\n : detectPackageManager(dir)\n\n if (!pmInfo) {\n console.log(\n pc.yellow(\n \"\\nNo package manager detected (no packageManager field, no lockfile).\",\n ),\n )\n console.log(\n pc.dim(\"Skipping install. Run your install command manually inside the directory.\\n\"),\n )\n } else {\n const installSpinner = ora(\n `Installing dependencies via ${pc.cyan(pmInfo.pm)}...`,\n ).start()\n const cmd = getInstallCommand(pmInfo)\n const cmdParts = cmd.split(\" \")\n const bin = cmdParts[0] ?? \"npm\"\n const args = cmdParts.slice(1)\n const code = await spawn(bin, args, { cwd: dir, stdio: \"inherit\", reject: false })\n if (code !== 0) {\n installSpinner.fail(`${pmInfo.pm} install failed`)\n throw installFailed(pmInfo.pm, code)\n }\n installSpinner.succeed(\"Dependencies installed\")\n }\n\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: pmInfo !== null,\n packageManager: pmInfo?.pm ?? null,\n })\n } else {\n console.log()\n console.log(pc.green(\"✓ Template ready\"))\n console.log(pc.dim(` cd ${dir}`))\n console.log(\n pc.dim(\n pmInfo\n ? ` ${getInstallCommand(pmInfo).split(\" \")[0]} dev`\n : ` install deps, then start`,\n ),\n )\n console.log()\n }\n } catch (err) {\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit((err as { exitCode?: () => number }).exitCode?.() ?? 1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal } from \"../errors/index.js\"\nimport { printError, printJson, printTemplatesTable } from \"../output/index.js\"\n\nexport const listCommand = new Command(\"list\")\n .description(\"List available templates\")\n .option(\"--category <name>\", \"filter to a single category\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (opts: { category?: string; json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching templates...\").start()\n\n try {\n const all = await fetchTemplates()\n const filtered = opts.category\n ? all.filter((t) => t.category === opts.category)\n : all\n\n spinner?.stop()\n\n if (opts.json) {\n printJson({ templates: filtered })\n } else {\n if (opts.category) {\n console.log(pc.dim(`Category: ${opts.category}`))\n }\n printTemplatesTable(filtered)\n console.log()\n console.log(\n pc.dim(\n `${filtered.length} template${filtered.length === 1 ? \"\" : \"s\"}.` +\n (opts.category\n ? \"\"\n : \" Use --category <name> to filter, --json for scripting.\"),\n ),\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch templates\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal, notFound } from \"../errors/index.js\"\nimport { printError, printJson, printTemplateInfo } from \"../output/index.js\"\n\nexport const infoCommand = new Command(\"info\")\n .description(\"Show details for one template\")\n .argument(\"<slug>\", \"template slug\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(async (slug: string, opts: { json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching template...\").start()\n\n try {\n const all = await fetchTemplates()\n const template = all.find((t) => t.slug === slug)\n spinner?.stop()\n\n if (!template) {\n throw notFound(slug, all.map((t) => t.slug))\n }\n\n if (opts.json) {\n printJson({ template })\n } else {\n printTemplateInfo(template)\n console.log()\n console.log(\n `Install: ${`deessejs init ${template.slug}`}`,\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch template\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n })\n","import { Command } from \"commander\"\nimport pc from \"picocolors\"\nimport { readPackageVersion } from \"./api/self-version.js\"\nimport {\n\tloginCommand,\n\tlogoutCommand,\n\tstatusCommand,\n} from \"./commands/auth/index.js\"\nimport { initCommand } from \"./commands/init.js\"\nimport { listCommand } from \"./commands/list.js\"\nimport { infoCommand } from \"./commands/info.js\"\n\nconst program = new Command()\n\nprogram\n .name(\"deessejs\")\n .description(\"CLI for the DeesseJS template registry\")\n .version(readPackageVersion())\n\nprogram.addCommand(listCommand)\nprogram.addCommand(infoCommand)\nprogram.addCommand(initCommand)\n\n// auth subcommand (ADR-020). Three children: login (request\n// device code, open browser, poll), status (print stored\n// user identity), logout (sign out + clear local token).\nconst authCommand = new Command(\"auth\").description(\n\t\"Authenticate this machine against the DeesseJS server\",\n)\nauthCommand.addCommand(loginCommand)\nauthCommand.addCommand(statusCommand)\nauthCommand.addCommand(logoutCommand)\nprogram.addCommand(authCommand)\n\nprogram.parseAsync(process.argv).catch((err) => {\n // Last-resort error handler. Per-command handlers catch CliError and exit\n // cleanly with the right code. Anything that lands here is an uncaught bug.\n process.stderr.write(\n `${pc.red(\"Internal error\")}: ${err instanceof Error ? err.message : String(err)}\\n`,\n )\n if (process.env.DEESSEJS_DEBUG) {\n process.stderr.write(`\\n${err instanceof Error && err.stack ? err.stack : \"\"}\\n`)\n }\n process.exit(1)\n})\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/api/self-version.ts","../src/constants/exit.ts","../src/errors/network.ts","../src/errors/not-found.ts","../src/errors/device-denied.ts","../src/errors/device-expired.ts","../src/errors/index.ts","../src/utils/sleep.ts","../../../packages/api/dist/constants/base-path.js","../src/lib/auth/store/better-auth-client.ts","../src/lib/auth/store/bearer-fetch.ts","../src/lib/auth/flow/polling-errors.ts","../src/lib/auth/flow/device-flow.ts","../src/lib/auth/flow/open-verification-url.ts","../src/cache/location.ts","../src/lib/auth/store/store.ts","../src/output/table.ts","../src/output/index.ts","../src/commands/auth/login.ts","../src/commands/auth/status.ts","../src/commands/auth/logout.ts","../src/version/check.ts","../src/api/client.ts","../src/api/index.ts","../src/utils/spawn.ts","../src/utils/git.ts","../src/utils/detect-pm.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/info.ts","../src/index.ts"],"names":["nodeSetTimeout","existsSync","mkdirSync","pc","Command","ora","DEFAULT_API_URL","resolveBaseURL","resolve","nodeSpawn","join","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["// Local declaration: tsup `define` (see apps/cli/tsup.config.ts) replaces\n// `process.env.CLI_PACKAGE_VERSION` with a string literal at build time.\n// The field is not present on Node's actual `process.env` shape, so we\n// declare it here for typechecking. The declaration is scoped to this\n// file; nothing else in the CLI sees it.\ndeclare const process: {\n env: {\n CLI_PACKAGE_VERSION: string\n }\n}\n\n/**\n * The CLI's own version, injected at build time from\n * apps/cli/package.json via tsup `define`. The bundler inlines the\n * literal string; there is no runtime lookup and no fragile\n * `import.meta.url` resolution back to package.json.\n *\n * Single source of truth: apps/cli/package.json. Changesets owns\n * the field; tsup reads it; the bundle carries it.\n *\n * See ADR-019.\n */\nexport const readPackageVersion = (): string => process.env.CLI_PACKAGE_VERSION\n","export const EXIT_SUCCESS = 0\nexport const EXIT_ERROR = 1\n","import { CliError } from \"./index.js\"\n\nexport const networkError = (detail: string): CliError =>\n new CliError(\n \"network_error\",\n `could not reach the templates endpoint`,\n detail,\n )\n","import { CliError } from \"./index.js\"\n\nexport const notFound = (slug: string, available: string[]): CliError =>\n new CliError(\n \"not_found\",\n `template \"${slug}\" not found`,\n `available templates: ${available.join(\", \")}`,\n )\n","import { CliError } from \"./index.js\"\n\n/**\n * The user denied the device-flow authorization in the\n * browser (ADR-020 mapping table: Better Auth\n * `access_denied` -> cli_device_denied).\n */\nexport const cliDeviceDenied = (): CliError =>\n\tnew CliError(\n\t\t\"cli_device_denied\",\n\t\t\"authorization was denied in the browser\",\n\t\t\"run `deesse auth login` again if this was a mistake\",\n\t)\n","import { CliError } from \"./index.js\"\n\n/**\n * The device code expired before the user approved it\n * (ADR-020 mapping table: Better Auth `expired_token` /\n * `invalid_grant` / `invalid_client` -> cli_device_expired).\n *\n * Also returned for the explicit 30-minute timeout when the\n * poll loop exhausts the device-code TTL without seeing an\n * approval.\n */\nexport const cliDeviceExpired = (reason?: string): CliError =>\n\tnew CliError(\n\t\t\"cli_device_expired\",\n\t\treason ??\n\t\t\t\"the device code expired before it was approved\",\n\t\t\"run `deesse auth login` again to obtain a fresh device code\",\n\t)\n","import { EXIT_ERROR } from \"../constants/exit.js\"\n\n// Public surface (per ADR-010 §2): the closed list of error codes\n// that downstream tooling may pattern-match against. Adding a code\n// here is a breaking change.\n//\n// The two device-flow codes (cli_device_denied,\n// cli_device_expired) are an amendment to the closed list, added\n// in lockstep with ADR-020 (device authorization). They are not\n// a precedent for further openings; see ADR-010 §2 \"What this\n// rule forbids\".\nexport type CliErrorCode =\n | \"not_found\"\n | \"network_error\"\n | \"parse_error\"\n | \"cli_outdated\"\n | \"cli_device_denied\"\n | \"cli_device_expired\"\n\n// Internal codes, used only inside the CLI. Not surfaced as a public\n// pattern-match surface. Adding a code here is non-breaking.\nexport type InternalCliErrorCode =\n | \"git_not_installed\"\n | \"target_exists\"\n | \"install_failed\"\n | \"internal\"\n\nexport type AnyCliErrorCode = CliErrorCode | InternalCliErrorCode\n\nexport class CliError extends Error {\n public readonly code: AnyCliErrorCode\n public readonly hint: string | undefined\n\n constructor(code: AnyCliErrorCode, message: string, hint?: string) {\n super(message)\n this.name = \"CliError\"\n this.code = code\n this.hint = hint\n }\n\n public exitCode = (): number => EXIT_ERROR\n}\n\n// Public factories (re-export the per-code files).\nexport { networkError } from \"./network.js\"\nexport { parseError } from \"./parse.js\"\nexport { notFound } from \"./not-found.js\"\nexport { cliOutdated } from \"./outdated.js\"\nexport { cliDeviceDenied } from \"./device-denied.js\"\nexport { cliDeviceExpired } from \"./device-expired.js\"\n\n// Internal factories, kept in this file because they are not part of\n// the public surface (ADR-010 §2 \"What this rule allows\": internal\n// error codes are not surfaced to the user).\nexport const gitNotInstalled = (): CliError =>\n new CliError(\n \"git_not_installed\",\n \"`git` is not installed or not on PATH\",\n \"install git from https://git-scm.com and try again\",\n )\n\nexport const targetExists = (dir: string): CliError =>\n new CliError(\n \"target_exists\",\n `target directory \"${dir}\" already exists`,\n \"remove the directory or pass --force to overwrite\",\n )\n\nexport const installFailed = (\n pm: string,\n code: number | null,\n): CliError =>\n new CliError(\n \"install_failed\",\n `${pm} install exited with code ${code ?? \"unknown\"}`,\n \"check the output above, then run the install command manually inside the cloned directory\",\n )\n\nexport const internal = (detail: string): CliError =>\n new CliError(\"internal\", \"unexpected internal error\", detail)\n","/**\n * Promisified setTimeout (ADR-020).\n *\n * Used by the deesse auth login polling loop to wait between\n * polls of /device/token. The loop's total timeout (1800 seconds\n * for a device-code TTL, hard-stopped via the mapPollingError\n * table) also uses this helper — there is no second timing\n * mechanism.\n *\n * Implemented with `node:timers/promises` so we do not pull in\n * a third-party timing lib for one helper. The Node API has\n * been stable since Node 15.\n *\n * Per ADR-002 Rule 2, helpers like this live in their own file\n * (no shared utils/ catch-all). One file, one function.\n */\nimport { setTimeout as nodeSetTimeout } from \"node:timers/promises\"\n\nexport const sleep = (ms: number): Promise<void> => nodeSetTimeout(ms)\n","/**\n * Single source of truth for the API path.\n *\n * The Next.js catch-all at `apps/app/app/api/[[...route]]/route.ts` exposes\n * every route under the active base path. Hono is mounted with\n * `basePath(API_BASE_PATH)`, and the oRPC client targets `API_RPC_PATH` to\n * reach the procedures endpoint.\n *\n * Versioning strategy (locked in docs/engineering/plans/robust-shared-backend.md):\n * - Each contract version lives under `packages/contracts/src/vN/`.\n * - The HTTP URL prefix mirrors that: `API_BASE_PATH_V1 = \"/api/v1\"`.\n * - `API_BASE_PATH` aliases the *active* version. When a V2 is introduced,\n * define `API_BASE_PATH_V2`, point `API_BASE_PATH` at it, and keep V1\n * served as a deprecated alias for installed CLI V1.x clients.\n *\n * Renaming the API prefix means:\n * 1. Edit `API_BASE_PATH_V*` below.\n * 2. Move (or alias) the Next.js catch-all to match.\n * 3. If you later introduce a `NEXT_PUBLIC_API_BASE_PATH` env override,\n * read it here and have `API_BASE_PATH` default to it.\n *\n * Do NOT introduce a parallel \"API path\" hardcoded in any app or package —\n * always import from this module.\n *\n * Note: Hono routes are kept *relative* to `basePath`, so the Hono-side\n * patterns (`/health`, `/rpc/*`) are NOT exposed here — only the full\n * client-facing paths.\n */\nexport const API_BASE_PATH_V1 = \"/api/v1\";\n/** Active version. Alias of the latest released base path. */\nexport const API_BASE_PATH = API_BASE_PATH_V1;\nexport const API_RPC_PATH = `${API_BASE_PATH}/rpc`;\nexport const API_AUTH_PATH = `${API_BASE_PATH}/auth`;\nexport const API_HEALTH_PATH = `${API_BASE_PATH}/health`;\nexport const API_READY_PATH = `${API_BASE_PATH}/ready`;\n","import { createAuthClient } from \"better-auth/client\"\nimport { deviceAuthorizationClient } from \"better-auth/client/plugins\"\nimport { API_AUTH_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../../../api/self-version.js\"\n\n/**\n * Production default for the CLI's `baseURL`.\n *\n * The CLI ships to npm as `@deessejs/cli`. When an end user\n * runs `npx @deessejs/cli@latest <cmd>` they have no\n * control over `process.env.DEESSEJS_API_URL` (it is the\n * shell environment of the user's machine, not the CLI's).\n * Baked-in defaults are the only mechanism that works\n * out of the box.\n *\n * The host `app.deessejs.com` is the production API host\n * per ADR-015 and ADR-016 (which both reproduce / test\n * against `app.deessejs.com/api/v1/...`). The `basePath` of\n * `/api/v1/auth` is appended by the Better Auth client, so\n * the device-flow endpoints live at\n * `${baseURL}${API_AUTH_PATH}/device/*` =\n * `https://app.deessejs.com/api/v1/auth/device/*`.\n *\n * (Note: an earlier draft of this comment cited\n * `deessejs.com` from ADR-014, which is the marketing\n * apex. ADR-014 was wrong about which host serves the\n * API. The canonical prod API host is `app.deessejs.com`,\n * confirmed by ADR-015 §\"Root cause\" and ADR-016\n * §\"API CI\". ADR-014 should be updated to match.)\n *\n * Three sources, in priority order:\n * 1. `DEESSEJS_API_URL` env var (CI / dev override;\n * never set by end users in practice).\n * 2. The baked-in default below (production).\n * 3. A thrown validation error when source 1 is set but\n * malformed (per ADR-014 §\"Malformed values fail\n * loudly\").\n */\nexport const DEFAULT_API_URL = \"https://app.deessejs.com\"\n\nexport function resolveBaseURL(): string {\n\tconst raw = process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL\n\ttry {\n\t\tconst parsed = new URL(raw)\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\t\tthrow new Error(\n\t\t\t\t`DEESSEJS_API_URL must use http or https (got ${parsed.protocol ?? \"no protocol\"})`,\n\t\t\t)\n\t\t}\n\t\treturn parsed.toString().replace(/\\/$/, \"\")\n\t} catch (e) {\n\t\tconst detail = e instanceof Error ? e.message : String(e)\n\t\tthrow new Error(\n\t\t\t`DEESSEJS_API_URL is malformed: ${detail}. ` +\n\t\t\t\t`Expected a full URL like https://api.example.com.`,\n\t\t)\n\t}\n}\n\n/**\n * Better Auth client factory for the CLI (ADR-020).\n *\n * The factory is the public surface (not a singleton).\n * Two reasons:\n * 1. Tests need to override `DEESSEJS_API_URL` before the\n * client is built; a module-level singleton would\n * capture the env var at import time and freeze it.\n * 2. Each command that touches the server runs at a\n * different point in the process lifetime; a fresh\n * client per call is fine because createAuthClient is\n * cheap (a Proxy + a few plugins).\n *\n * The framework-agnostic core (`better-auth/client`) is used\n * rather than `better-auth/react`. The react subpath only\n * adds hooks like `useSession` that the CLI does not consume.\n *\n * `disableDefaultFetchPlugins: true` is set for Node: the\n * default plugins include a redirect handler that intercepts\n * `window.location`-style redirects, which is meaningless in\n * Node.\n *\n * `fetchOptions.headers` injects the CLI User-Agent on every\n * request (ADR-020 limitation 1 mitigation).\n */\nexport function createCliAuthClient() {\n\treturn createAuthClient({\n\t\tbaseURL: resolveBaseURL(),\n\t\tbasePath: API_AUTH_PATH,\n\t\tplugins: [deviceAuthorizationClient()],\n\t\tdisableDefaultFetchPlugins: true,\n\t\tfetchOptions: {\n\t\t\theaders: {\n\t\t\t\t\"user-agent\": `DeesseJS CLI/${readPackageVersion()}`,\n\t\t\t},\n\t\t},\n\t})\n}\n","import { API_AUTH_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../../../api/self-version.js\"\n\nimport { resolveBaseURL } from \"./better-auth-client.js\"\n\n/**\n * Minimal bearer-token fetch for the CLI (ADR-020).\n *\n * Used only by auth status and auth logout, both of which\n * need to call Better Auth endpoints with a bearer token\n * read from ~/.deessejs/auth.json. The typed client\n * (apps/cli/src/lib/auth/store/better-auth-client.ts) does\n * not support this case: it sends the bearer via its\n * cookie-based session, not a caller-supplied token.\n *\n * The helper injects two headers:\n * - User-Agent: DeesseJS CLI/<version> (per ADR-020\n * limitation 1 mitigation, the V1 label for the\n * /settings/sessions view of CLI sessions)\n * - Authorization: Bearer <access_token> (caller-supplied)\n *\n * Path is appended to (baseURL + API_AUTH_PATH) so the\n * request is absolute. baseURL is resolved by the same\n * helper the typed client uses (`resolveBaseURL` from\n * better-auth-client.ts) so production and tests share\n * the same resolution. No hardcoded localhost default\n * here: end users who install the CLI do not control\n * their shell env, and pointing to localhost would be a\n * silent failure.\n */\nfunction authUrl(path: string): string {\n\tconst normalised = path.startsWith(\"/\") ? path.slice(1) : path\n\treturn `${resolveBaseURL()}${API_AUTH_PATH}/${normalised}`\n}\n\nexport function bearerFetch(\n\tpath: string,\n\taccessToken: string,\n\tinit?: RequestInit,\n): Promise<Response> {\n\tconst headers = new Headers(init?.headers)\n\theaders.set(\"user-agent\", `DeesseJS CLI/${readPackageVersion()}`)\n\theaders.set(\"authorization\", `Bearer ${accessToken}`)\n\treturn fetch(authUrl(path), {\n\t\t...init,\n\t\theaders,\n\t})\n}\n","import { cliDeviceExpired, cliDeviceDenied, CliError } from \"../../../errors/index.js\"\n\n/**\n * Polling-protocol error mapper (ADR-020).\n *\n * Translates Better Auth device-flow error codes (per the\n * plugin's `error-codes.mjs`) into the CLI's closed list of\n * public error codes (ADR-010 §2). The CLI surfaces the cause\n * instead of masking it with `not_found`.\n *\n * Mapping (per ADR-020):\n *\n * authorization_pending — not an error; the polling loop\n * continues and ignores the return value\n * slow_down — caller is expected to bump the local\n * interval by 5s and continue (the mapper returns\n * null to signal 'no error, keep polling')\n * expired_token — cli_device_expired\n * access_denied — cli_device_denied\n * invalid_grant — cli_device_expired (code is invalid or\n * already used; the user's only recourse is to retry)\n * invalid_client — cli_device_expired (CLI is not a\n * registered device client; same recovery: retry)\n *\n * The function returns either `null` (continue polling) or\n * a `CliError` to surface. The caller decides whether the\n * CliError is a hard exit or just a log line; per ADR-010\n * §2 the closed-list codes are user-visible.\n */\nexport type BetterAuthDeviceErrorCode =\n | \"authorization_pending\"\n | \"slow_down\"\n | \"expired_token\"\n | \"access_denied\"\n | \"invalid_grant\"\n | \"invalid_client\"\n\nexport const mapPollingError = (\n code: BetterAuthDeviceErrorCode | string,\n): CliError | null => {\n switch (code) {\n case \"authorization_pending\":\n case \"slow_down\":\n // Not errors. Caller treats null as \"continue polling\";\n // for `slow_down`, the caller is also expected to bump\n // its local interval by 5 seconds.\n return null\n case \"access_denied\":\n return cliDeviceDenied()\n case \"expired_token\":\n case \"invalid_grant\":\n case \"invalid_client\":\n return cliDeviceExpired()\n default:\n // Unknown Better Auth code: treat as expired for the\n // purposes of recovery. The user retries the flow.\n return cliDeviceExpired()\n }\n}\n","import { cliDeviceExpired } from \"../../../errors/index.js\"\nimport { sleep } from \"../../../utils/sleep.js\"\n\nimport { bearerFetch } from \"../store/bearer-fetch.js\"\nimport { createCliAuthClient } from \"../store/better-auth-client.js\"\n\nimport { mapPollingError } from \"./polling-errors.js\"\n\n/**\n * Device-flow orchestration (ADR-020, ADR-022).\n *\n * Three pure functions that the `login` command composes:\n *\n * - requestDeviceCode: hits /device/code, returns the\n * issued code + the URL to open + an absolute deadline\n * matching the device-code TTL (30 minutes, per\n * Better Auth's plugin default).\n *\n * - pollForToken: hits /device/token until the Better\n * Auth error codes say \"approved\" (returns the token)\n * or one of the closed-list terminal codes says \"no\".\n * Honors slow_down by bumping the local interval by 5\n * seconds. Per ADR-020, silent on authorization_pending\n * and slow_down; surfaces cli_device_expired /\n * cli_device_denied per the polling-errors mapper.\n *\n * - fetchUserIdentity (ADR-022): resolves the user tied\n * to the device-flow access token by calling\n * /get-session with `Authorization: Bearer <token>`.\n * Uses `bearerFetch` (raw fetch) instead of the typed\n * Better Auth client because the typed client is\n * cookie-based and the CLI has no cookie jar. Throws\n * `cliDeviceExpired` (not a soft null) when the server\n * rejects the token or returns no user — a token\n * without a resolvable identity is a server-side or\n * wire-protocol regression, not a normal state. See\n * ADR-022 §\"Decision / 1. CLI side\".\n *\n * Polling interval constants live here, not in login.ts,\n * because they are part of the device-flow protocol, not\n * the commander wrapper around it.\n */\n\nconst POLL_INTERVAL_MS = 5_000\nconst POLL_INTERVAL_WITH_BACKOFF_MS = 10_000\nconst TOTAL_TIMEOUT_MS = 30 * 60 * 1_000 // 30 minutes per device-code TTL\n\nexport type IssuedDeviceCode = {\n\turl: string\n\tdeviceCode: string\n\texpiresBy: number\n}\n\nexport type ResolvedToken = {\n\taccessToken: string\n}\n\nexport type UserIdentity = {\n\tid: string\n\temail?: string\n\tname?: string\n}\n\nexport const requestDeviceCode = async (): Promise<IssuedDeviceCode> => {\n\tconst authClient = createCliAuthClient()\n\tconst { data, error } = await authClient.device.code({\n\t\tclient_id: \"deessejs-cli\",\n\t})\n\tif (error || !data) {\n\t\tconst description =\n\t\t\t(error as { error_description?: string } | null)?.error_description ??\n\t\t\t\"unknown error\"\n\t\tthrow cliDeviceExpired(`could not obtain a device code: ${description}`)\n\t}\n\treturn {\n\t\turl: data.verification_uri_complete,\n\t\tdeviceCode: data.device_code,\n\t\texpiresBy: Date.now() + TOTAL_TIMEOUT_MS,\n\t}\n}\n\nexport const pollForToken = async (\n\tdeviceCode: string,\n\texpiresBy: number,\n): Promise<ResolvedToken> => {\n\tlet interval = POLL_INTERVAL_MS\n\tfor (;;) {\n\t\tif (Date.now() >= expiresBy) {\n\t\t\tthrow cliDeviceExpired(\"device flow timed out after 30 minutes\")\n\t\t}\n\t\tawait sleep(interval)\n\t\tconst authClient = createCliAuthClient()\n\t\tconst { data, error } = await authClient.device.token({\n\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\tdevice_code: deviceCode,\n\t\t\tclient_id: \"deessejs-cli\",\n\t\t})\n\t\tif (data) {\n\t\t\t// The plugin types `data` as `unknown` in some\n\t\t\t// Better Auth 1.6.x minor versions; the access\n\t\t\t// token field is stable across versions.\n\t\t\tconst token = (data as { access_token: string }).access_token\n\t\t\treturn { accessToken: token }\n\t\t}\n\t\t// The plugin's error envelope is\n\t\t// { error: \"access_denied\", error_description: \"...\" }\n\t\t// (per better-auth/dist/plugins/device-authorization/\n\t\t// routes.mjs deviceTokenErrorSchema). The field name is\n\t\t// `error`, not `code`. Reading `code` here silently\n\t\t// yields undefined and the polling loop falls through\n\t\t// to the \"no error code\" guard below, which throws\n\t\t// cliDeviceExpired instead of the actual reason.\n\t\tconst code = (error as { error?: string } | null)?.error\n\t\tif (!code) {\n\t\t\tthrow cliDeviceExpired(\n\t\t\t\t\"token endpoint returned no data and no error code\",\n\t\t\t)\n\t\t}\n\t\tconst mapped = mapPollingError(code)\n\t\tif (mapped !== null) {\n\t\t\tthrow mapped\n\t\t}\n\t\t// slow_down: bump the local interval for the next poll.\n\t\t// Per ADR-020, slow_down and pending are silent.\n\t\tinterval = POLL_INTERVAL_WITH_BACKOFF_MS\n\t}\n}\n\nexport const fetchUserIdentity = async (\n\taccessToken: string,\n): Promise<UserIdentity> => {\n\tconst response = await bearerFetch(\"get-session\", accessToken, { method: \"GET\" })\n\tif (!response.ok) {\n\t\tthrow cliDeviceExpired(\n\t\t\t`server issued a session token but /get-session rejected it (HTTP ${response.status})`,\n\t\t)\n\t}\n\tconst body = (await response.json()) as { user?: UserIdentity }\n\tif (!body.user) {\n\t\tthrow cliDeviceExpired(\n\t\t\t\"server issued a session token but no user identity was attached\",\n\t\t)\n\t}\n\treturn body.user\n}\n","import open from \"open\"\n\n/**\n * Open the device-flow verification URL in the OS-default\n * browser (ADR-020). The `open` package handles per-OS\n * dispatch (`open` on macOS, `xdg-open` on Linux,\n * `start` on Windows) plus WSL detection in one line.\n *\n * `wait: false` returns once the child process is spawned\n * (not when the browser closes). The caller does not await\n * the user-facing flow: the user clicks Approve in the\n * browser, the poll loop in the caller resolves.\n */\nexport const openVerificationUrl = async (url: string): Promise<void> => {\n\tawait open(url, { wait: false })\n}\n","import { existsSync, mkdirSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\n\n/**\n * On-disk response cache for the CLI.\n *\n * Layout: one file per endpoint under ~/.deessejs/. Each file holds the\n * raw response body plus the ETag the server returned, so we can reissue\n * If-None-Match on the next call and serve the cached body on a 304.\n *\n * No TTL: the server is the source of truth for freshness. A cache entry\n * is \"valid\" if either (a) we can revalidate it against the server and\n * the server says 304, or (b) we're in --offline mode and any prior\n * response is better than nothing.\n *\n * Corruption policy: a malformed file is treated as cache-miss. We do\n * not auto-overwrite it — if the user manually edited a cache file, we\n * surface that as a warning and let them decide. The next successful\n * network call will overwrite the file normally.\n *\n * The home directory is read lazily on each call to `cacheDir` so that\n * tests can override `HOME` / `USERPROFILE` between calls and pick up\n * the new value. Computing CACHE_DIR at module load time would freeze\n * the path on whatever os.homedir() returns when this file is first\n * imported, which makes integration testing impossible.\n */\n\n/**\n * Return the cache directory, computed at call time so the\n * process.env.HOME / USERPROFILE override pattern works\n * in tests.\n */\nexport const cacheDir = (): string => join(homedir(), \".deessejs\")\n\nexport const ensureCacheDir = (): void => {\n const dir = cacheDir()\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Absolute path to a file under the cache directory.\n * Computed at call time (no module-level capture) so tests\n * can override HOME / USERPROFILE and have the path\n * recomputed on the next invocation.\n */\nexport const cachePath = (name: string): string => join(cacheDir(), name)\n","import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\"\nimport { dirname } from \"node:path\"\n\nimport { cachePath } from \"../../../cache/location.js\"\n\n/**\n * CLI session-token store (ADR-020).\n *\n * Holds the Better Auth session token returned by\n * /device/token after the user approves the device flow in\n * the browser. The file lives at `~/.deessejs/auth.json`,\n * the same directory as the templates cache.\n *\n * File format (ADR-020 opaque-cache rule, ADR-010 §4):\n * {\n * \"access_token\": \"<session.token>\",\n * \"user\": { \"id\": \"...\", \"email\": \"...\", \"name\": \"...\" },\n * \"fetchedAt\": \"2026-08-17T...\"\n * }\n *\n * The shape may change between CLI minor versions without\n * bumping the major. Tooling that reads auth.json directly\n * reads the cache at its own risk.\n */\n\n/**\n * Absolute path to the auth.json file. Computed at call\n * time (no module-level capture) so tests can override\n * HOME / USERPROFILE and have the path recomputed on\n * the next invocation. Stable for the lifetime of a\n * single process invocation under a given HOME.\n */\nexport const AUTH_PATH = (): string => cachePath(\"auth.json\")\n\n// Convenience alias: readAuth / writeAuth / clearAuth all\n// resolve AUTH_PATH() once per call so they see the same\n// value for the duration of a single operation.\nconst resolveAuthPath = (): string => AUTH_PATH()\n\n/** Stored session shape. JSON-serialisable. */\nexport interface StoredAuth {\n\taccess_token: string\n\tuser: { id: string; email?: string; name?: string }\n\tfetchedAt: string\n}\n\nconst ensureDir = (path: string): void => {\n\tif (!existsSync(dirname(path))) {\n\t\tmkdirSync(dirname(path), { recursive: true })\n\t}\n}\n\nconst chmodOwnerOnly = (path: string): void => {\n\t// fs.writeFile's `mode` is masked by the process umask, so\n\t// the explicit chmod after the write is the authoritative\n\t// step. Without it, a default umask of 022 leaves the file\n\t// world-readable on Linux/macOS. The mode 0o600 means\n\t// read/write for the owner only.\n\ttry {\n\t\tchmodSync(path, 0o600)\n\t} catch {\n\t\t// chmod may fail on Windows in tests; the writeAuth\n\t\t// caller treats chmod failure as a write failure (the\n\t\t// CLI exits through CliError). Silent here means we\n\t\t// only fall through if chmod itself is unsupported on\n\t\t// the platform, which is rare on Node targets.\n\t}\n}\n\n/**\n * Read the stored auth.json. Returns null when the file does\n * not exist or is malformed. A malformed file is treated as\n * \"no session\" rather than a hard error: the next command\n * either re-runs the login flow or surfaces the parse error\n * explicitly via the CLI error path.\n */\nexport const readAuth = (): StoredAuth | null => {\n\tconst path = resolveAuthPath()\n\tif (!existsSync(path)) return null\n\ttry {\n\t\tconst text = readFileSync(path, \"utf8\")\n\t\tconst parsed = JSON.parse(text) as StoredAuth\n\t\tif (typeof parsed.access_token !== \"string\") return null\n\t\treturn parsed\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Write the auth.json file with mode 0o600. The function\n * throws on filesystem failure (caller decides how to surface).\n */\nexport const writeAuth = (auth: StoredAuth): void => {\n\tconst path = resolveAuthPath()\n\tensureDir(path)\n\tconst text = JSON.stringify(auth, null, 2)\n\twriteFileSync(path, text, { mode: 0o600 })\n\tchmodOwnerOnly(path)\n}\n\n/**\n * Delete the auth.json file. No-op when the file does not\n * exist. Used by `deesse auth logout` and on explicit\n * server-side session invalidation.\n */\nexport const clearAuth = (): void => {\n\tconst path = resolveAuthPath()\n\tif (!existsSync(path)) return\n\tunlinkSync(path)\n}\n\n// Exposed for the rare caller that needs the resolved path\n// without importing auth.json by name (test fixtures).\nexport const authPath = AUTH_PATH\n","import pc from \"picocolors\"\n\nimport type { Template } from \"../api/index.js\"\n\nexport const printTemplatesTable = (templates: Template[]): void => {\n if (templates.length === 0) {\n process.stdout.write(pc.dim(\"No templates available.\\n\"))\n return\n }\n const headers = [\"slug\", \"name\", \"category\", \"license\"]\n const rows = templates.map((t) => [\n t.slug,\n t.name,\n t.category,\n t.license,\n ])\n printAlignedTable([headers, ...rows])\n}\n\nexport const printTemplateInfo = (t: Template): void => {\n const lines: Array<[string, string]> = [\n [\"slug\", t.slug],\n [\"name\", t.name],\n [\"description\", t.description],\n [\"category\", t.category],\n [\"license\", t.license],\n [\"repo\", `${t.owner}/${t.repo}`],\n [\"labels\", t.labels.join(\", \") || pc.dim(\"(none)\")],\n ]\n if (t.image) lines.push([\"image\", t.image])\n\n const labelWidth = Math.max(...lines.map(([l]) => l.length))\n for (const [label, value] of lines) {\n process.stdout.write(\n `${pc.dim(label.padEnd(labelWidth))} ${value}\\n`,\n )\n }\n}\n\nconst printAlignedTable = (rows: string[][]): void => {\n const firstRow = rows[0]\n if (!firstRow) return\n const widths = firstRow.map((_, col) =>\n Math.max(...rows.map((row) => row[col]?.length ?? 0)),\n )\n for (const row of rows) {\n process.stdout.write(\n row.map((cell, i) => cell.padEnd(widths[i] ?? 0)).join(\" \") + \"\\n\",\n )\n }\n}\n","import pc from \"picocolors\"\n\nimport type { CliError } from \"../errors/index.js\"\n\nexport const printJson = (value: unknown): void => {\n process.stdout.write(JSON.stringify(value, null, 2) + \"\\n\")\n}\n\nexport const printError = (err: CliError): void => {\n process.stderr.write(\n `${pc.red(\"Error\")}: ${err.message}\\n` +\n (err.hint ? `${pc.dim(\"Hint\")}: ${err.hint}\\n` : \"\") +\n `${pc.dim(\"Code\")}: ${err.code}\\n`,\n )\n}\n\nexport { printTemplatesTable, printTemplateInfo } from \"./table.js\"\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport {\n\tfetchUserIdentity,\n\topenVerificationUrl,\n\tpollForToken,\n\trequestDeviceCode,\n} from \"../../lib/auth/flow/index.js\"\nimport { writeAuth } from \"../../lib/auth/store/store.js\"\nimport { type CliError } from \"../../errors/index.js\"\nimport { printError, printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth login (ADR-020, ADR-022).\n *\n * Commander wrapper around the device-flow orchestration in\n * apps/cli/src/lib/auth/flow/. This file owns the command\n * surface: option parsing, spinners, output formatting, and\n * exit-code mapping. The flow itself (request / poll /\n * open-browser) lives in the auth-flow module and is\n * reusable from other commands (e.g. a future `auth\n * reauth`) without duplicating orchestration.\n *\n * Flow summary (full detail in apps/cli/src/lib/auth/flow/):\n * 1. requestDeviceCode: POST /device/code\n * 2. openVerificationUrl: spawn the OS browser\n * 3. pollForToken: poll /device/token until approved\n * 4. fetchUserIdentity (ADR-022): GET /get-session with\n * `Authorization: Bearer <access_token>` to resolve\n * the user. Throws cli_device_expired if the server\n * rejects the token or returns no user — a soft\n * `?? { id: \"\" }` fallback would write a fake user to\n * ~/.deessejs/auth.json and surface as \"logged in as\n * unknown user\" downstream (Bug A).\n * 5. writeAuth: persist ~/.deessejs/auth.json with mode 0600\n */\nexport const loginCommand = new Command(\"login\")\n\t.description(\"Authorize this machine against the DeesseJS server\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst spinner = opts.json\n\t\t\t? null\n\t\t\t: ora(\"Requesting device code...\").start()\n\t\ttry {\n\t\t\tconst issued = await requestDeviceCode()\n\t\t\tspinner?.stop()\n\n\t\t\tif (!opts.json) {\n\t\t\t\tconsole.log()\n\t\t\t\tconsole.log(\n\t\t\t\t\tpc.cyan(\n\t\t\t\t\t\t`Open the following URL in your browser if it doesn't open automatically:`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\tconsole.log(pc.bold(issued.url))\n\t\t\t\tconsole.log()\n\t\t\t}\n\n\t\t\tawait openVerificationUrl(issued.url)\n\n\t\t\tconst pollSpinner = opts.json\n\t\t\t\t? null\n\t\t\t\t: ora(\"Waiting for browser approval...\").start()\n\t\t\ttry {\n\t\t\t\tconst token = await pollForToken(issued.deviceCode, issued.expiresBy)\n\t\t\t\tconst user = await fetchUserIdentity(token.accessToken)\n\t\t\t\twriteAuth({\n\t\t\t\t\taccess_token: token.accessToken,\n\t\t\t\t\tuser,\n\t\t\t\t\tfetchedAt: new Date().toISOString(),\n\t\t\t\t})\n\t\t\t\tpollSpinner?.stop()\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({ ok: true, user })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.green(\"✓ logged in as \") +\n\t\t\t\t\t\t\tpc.bold(user.email ?? user.name ?? user.id),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tpollSpinner?.stop()\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tif (e instanceof Error && \"code\" in e && \"exitCode\" in e) {\n\t\t\t\tconst err = e as CliError\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({ ok: false, code: err.code, message: err.message })\n\t\t\t\t} else {\n\t\t\t\t\tprintError(err)\n\t\t\t\t}\n\t\t\t\t// Rethrow so the index.ts last-resort handler\n\t\t\t\t// calls process.exit(err.exitCode()). This is\n\t\t\t\t// also what makes the command testable: vitest\n\t\t\t\t// catches the throw, asserts on the error shape,\n\t\t\t\t// and the production path still exits with the\n\t\t\t\t// right code (via the central handler).\n\t\t\t\tthrow err\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t})\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport { bearerFetch } from \"../../lib/auth/store/bearer-fetch.js\"\nimport { readAuth, type StoredAuth } from \"../../lib/auth/store/store.js\"\nimport { internal } from \"../../errors/index.js\"\nimport { printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth status (ADR-020).\n *\n * Read-only command. Validates the stored session token\n * against the server's /get-session endpoint. The typed\n * better-auth client cannot drive this case (it sends the\n * session cookie, not a caller-supplied bearer token),\n * so this command uses the bearer-fetch helper directly.\n *\n * Terminal states:\n * - No auth.json: yellow notice, exit 0. No session is the\n * normal pre-login state.\n * - Token still valid server-side: green ✓, identity\n * echoed back, fetchedAt shown.\n * - Token revoked or expired server-side: yellow notice,\n * stale identity shown for context, exit 0. The user\n * reruns auth login.\n *\n * The token itself is never echoed.\n */\n\ntype StoredUser = StoredAuth[\"user\"]\n\nconst formatStored = (stored: StoredAuth): string => {\n\tconst userBits: string[] = []\n\tif (stored.user.email) userBits.push(stored.user.email)\n\tif (stored.user.name) userBits.push(stored.user.name)\n\tif (stored.user.id) userBits.push(`(${stored.user.id})`)\n\tconst who = userBits.length > 0 ? userBits.join(\" \") : \"unknown user\"\n\tconst when = new Date(stored.fetchedAt).toLocaleString()\n\treturn `${who} — token fetched ${when}`\n}\n\nconst validateSession = async (\n\taccessToken: string,\n): Promise<StoredUser | null> => {\n\tconst res = await bearerFetch(\"get-session\", accessToken, { method: \"GET\" })\n\tif (res.status !== 200) return null\n\tconst body = (await res.json()) as { user?: StoredUser } | null\n\treturn body?.user ?? null\n}\n\nexport const statusCommand = new Command(\"status\")\n\t.description(\"Show the current CLI auth session\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst stored = readAuth()\n\t\tif (!stored) {\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: false, reason: \"no_session\" })\n\t\t\t} else {\n\t\t\t\tconsole.error(\n\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\"no active session. Run `deesse auth login` to authorise this machine.\",\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst spinner = opts.json ? null : ora(\"Checking session...\").start()\n\t\ttry {\n\t\t\tconst user = await validateSession(stored.access_token)\n\t\t\tif (!user) {\n\t\t\t\tspinner?.stop()\n\t\t\t\tif (opts.json) {\n\t\t\t\t\tprintJson({\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\treason: \"session_invalid\",\n\t\t\t\t\t\tstored: {\n\t\t\t\t\t\t\tuser: stored.user,\n\t\t\t\t\t\t\tfetchedAt: stored.fetchedAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\t\"The stored token no longer matches an active session on the server. Run `deesse auth login` again.\",\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\tconsole.log(pc.dim(formatStored(stored)))\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tspinner?.stop()\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true, user, fetchedAt: stored.fetchedAt })\n\t\t\t} else {\n\t\t\t\tconsole.log()\n\t\t\t\tconsole.log(pc.green(\"✓ active session\"))\n\t\t\t\tconsole.log(pc.dim(formatStored({ ...stored, user })))\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tthrow internal(e instanceof Error ? e.message : String(e))\n\t\t}\n\t})\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\n\nimport { bearerFetch } from \"../../lib/auth/store/bearer-fetch.js\"\nimport { clearAuth, readAuth } from \"../../lib/auth/store/store.js\"\nimport { internal } from \"../../errors/index.js\"\nimport { printJson } from \"../../output/index.js\"\n\n/**\n * deesse auth logout (ADR-020).\n *\n * Sequence:\n * 1. POST /api/v1/auth/sign-out with the stored token to\n * invalidate the session server-side.\n * 2. Delete ~/.deessejs/auth.json regardless of the\n * sign-out outcome: a stale file is worse than a\n * missing one (every subsequent command would silently\n * use a dead token).\n *\n * Uses bearerFetch (not the typed client) because the\n * client sends the session cookie, not a caller-supplied\n * bearer token. The two helper files (better-auth-client.ts\n * and bearer-fetch.ts) are deliberately complementary: the\n * typed client owns the device-flow HTTP shape; the bearer\n * helper owns the two read-only endpoints that need a\n * caller-supplied token.\n *\n * If the file does not exist, the command exits 0 silently:\n * there is no session to revoke.\n */\n\nexport const logoutCommand = new Command(\"logout\")\n\t.description(\"Sign out this machine and remove the stored token\")\n\t.option(\"--json\", \"JSON output for scripting\")\n\t.action(async (opts: { json?: boolean }) => {\n\t\tconst stored = readAuth()\n\t\tif (!stored) {\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true, reason: \"no_session\" })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst spinner = opts.json\n\t\t\t? null\n\t\t\t: ora(\"Signing out...\").start()\n\t\ttry {\n\t\t\tconst res = await bearerFetch(\"sign-out\", stored.access_token, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\t})\n\t\t\t// We deliberately do NOT throw on a non-2xx here:\n\t\t\t// the local cache cleanup is the user-facing\n\t\t\t// outcome. A server-side failure (e.g. token\n\t\t\t// already revoked) is logged but the local file\n\t\t\t// is cleared regardless. The user's machine is\n\t\t\t// now in a \"no session\" state either way.\n\t\t\tif (res.status !== 200 && res.status !== 204) {\n\t\t\t\tspinner?.stop()\n\t\t\t\tif (!opts.json) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\tpc.yellow(\n\t\t\t\t\t\t\t`Server returned HTTP ${res.status} on sign-out; clearing the local token file anyway.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tspinner?.stop()\n\t\t\t}\n\t\t\tclearAuth()\n\t\t\tif (opts.json) {\n\t\t\t\tprintJson({ ok: true })\n\t\t\t} else {\n\t\t\t\tconsole.log(pc.green(\"✓ signed out\"))\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tspinner?.stop()\n\t\t\tclearAuth()\n\t\t\tthrow internal(e instanceof Error ? e.message : String(e))\n\t\t}\n\t})\n","import { API_BASE_PATH } from \"@workspace/api/base-path\"\n\nimport { readPackageVersion } from \"../api/self-version.js\"\n\nexport type CliVersionResponse = {\n version: string\n minSupported: string\n}\n\nconst SEMVER_RE = /^\\d+\\.\\d+\\.\\d+$/\n\nconst parseSemver = (v: string): [number, number, number] | null => {\n if (!SEMVER_RE.test(v)) return null\n const [major, minor, patch] = v.split(\".\").map(Number)\n return [major ?? 0, minor ?? 0, patch ?? 0]\n}\n\nconst compareSemver = (a: string, b: string): number => {\n const pa = parseSemver(a)\n const pb = parseSemver(b)\n if (!pa || !pb) return 0 // unknown: don't warn\n if (pa[0] !== pb[0]) return pa[0] - pb[0]\n if (pa[1] !== pb[1]) return pa[1] - pb[1]\n return pa[2] - pb[2]\n}\n\n/**\n * Non-blocking version probe.\n *\n * Calls `${API_BASE_PATH}/version` (a system route per ADR-011, served\n * by Hono direct, not through oRPC). If the local CLI version is\n * strictly below minSupported, prints a warning to stderr. The caller\n * does NOT abort; the user might have a workflow that depends on the\n * old version. The warning is loud but not authoritative.\n *\n * Failures (network, parse, server error) are swallowed silently: the\n * version check is best-effort, never the reason a command fails.\n *\n * Per ADR-021: the URL is composed via `new URL(path, base)`. The\n * host is read from `DEESSEJS_API_URL` (the canonical CLI override)\n * with fallback to `DEFAULT_API_URL = \"https://app.deessejs.com\"`.\n * The shared `resolveBaseURL()` lives in `apps/cli/src/api/client.ts`;\n * this file duplicates the resolution (a one-line `new URL(raw)`)\n * because the version probe runs at startup before the oRPC link is\n * constructed and importing the oRPC module would drag `node:fs`\n * transitively (the CLI's tsup bundle is intentionally slim).\n */\nexport const maybeWarnAboutOutdatedCli = async (): Promise<void> => {\n let bodyText: string\n try {\n const raw =\n process.env.DEESSEJS_API_URL ?? \"https://app.deessejs.com\"\n const versionUrl = new URL(`${API_BASE_PATH}/version`, raw).toString()\n const res = await fetch(versionUrl)\n if (res.status !== 200) return\n bodyText = await res.text()\n } catch {\n return\n }\n\n let parsed: CliVersionResponse\n try {\n parsed = JSON.parse(bodyText) as CliVersionResponse\n } catch {\n return\n }\n if (\n typeof parsed.version !== \"string\" ||\n typeof parsed.minSupported !== \"string\"\n ) {\n return\n }\n\n const localVersion = readPackageVersion()\n if (compareSemver(localVersion, parsed.minSupported) < 0) {\n process.stderr.write(\n `\\n⚠ deessejs-cli ${localVersion} is below the minimum supported version (${parsed.minSupported}).\\n` +\n ` Upgrade: pnpm dlx @deessejs/cli@latest\\n\\n`,\n )\n }\n}\n","import {\n ClientRetryPlugin,\n RetryAfterPlugin,\n} from \"@orpc/client/plugins\"\nimport { RPCLink } from \"@orpc/client/fetch\"\nimport { createORPCClient } from \"@orpc/client\"\nimport type { RouterClient } from \"@orpc/server\"\n\nimport { appRouter } from \"@workspace/api/router\"\nimport { API_RPC_PATH } from \"@workspace/api/base-path\"\n\n/**\n * Typed oRPC link for the CLI.\n *\n * Internal to the CLI. The public surface (`fetchTemplates`) lives in\n * ../api/index.ts. Tests that target the typed client (Server-Side Client\n * pattern) import `appRouter` directly from `@workspace/api/router` and\n * bypass this module entirely.\n *\n * Resilience is delegated to the official oRPC plugins\n * (`ClientRetryPlugin`, `RetryAfterPlugin`); the HTTP fetch itself is\n * `globalThis.fetch` (the oRPC default). The plugins cover retry on\n * transient network errors and on 429 / 503 honouring `Retry-After`.\n *\n * See `apps/internal-documentation/content/docs/knowledge-base/orpc/client-plugins.mdx`\n * for the full coverage analysis.\n *\n * The previous custom `orpcFetch` hook (which injected the User-Agent\n * header and did bespoke retries) was removed in favour of the plugins.\n * The User-Agent header is no longer sent from the typed client. The\n * system-level version probe (`apps/cli/src/version/check.ts`) still\n * sends a User-Agent because it hits a Hono-direct endpoint, not an\n * oRPC procedure.\n *\n * Per ADR-021: the URL is composed via `new URL(path, base)` rather\n * than string concatenation; the leading-slash rule of `new URL`\n * collapses any trailing slash on the base. The trailing-slash guard\n * for the CLI is `resolveBaseURL()` below.\n */\n/**\n * Production default for the CLI's `baseURL`. Mirrors\n * `apps/cli/src/lib/auth/store/better-auth-client.ts` so production\n * and tests share the same resolution (per ADR-015/016: canonical\n * prod API host is `app.deessejs.com`, NOT `deessejs.com` which is\n * the marketing apex).\n */\nexport const DEFAULT_API_URL = \"https://app.deessejs.com\"\n\n/**\n * Resolve the API base URL.\n *\n * Three sources, in priority order:\n * 1. `DEESSEJS_API_URL` env var (CI / dev override; never set by\n * end users in practice).\n * 2. The baked-in default above (production).\n * 3. A thrown validation error when source 1 is set but malformed.\n *\n * Per ADR-021: this is the CLI's analogue of the\n * `apps/web/src/lib/orpc.ts` URL composition. The CLI cannot import\n * `@workspace/env/server` because the env package is private to the\n * monorepo (`packages/env/package.json: private: true`) and the CLI\n * is published on npm. The naming divergence (`DEESSEJS_API_URL`\n * here vs. `API_BASE_URL` in apps/web and apps/app) is intentional —\n * the env loader on the web side owns the canonical name; the CLI\n * uses a different namespace because its published tarball carries a\n * single env var and there is no loader to alias it through.\n */\nexport function resolveBaseURL(): string {\n\tconst raw = process.env.DEESSEJS_API_URL ?? DEFAULT_API_URL\n\ttry {\n\t\tconst parsed = new URL(raw)\n\t\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n\t\t\tthrow new Error(\n\t\t\t\t`DEESSEJS_API_URL must use http or https (got ${parsed.protocol ?? \"no protocol\"})`,\n\t\t\t)\n\t\t}\n\t\treturn parsed.toString().replace(/\\/$/, \"\")\n\t} catch (e) {\n\t\tconst detail = e instanceof Error ? e.message : String(e)\n\t\tthrow new Error(\n\t\t\t`DEESSEJS_API_URL is malformed: ${detail}. ` +\n\t\t\t\t`Expected a full URL like https://api.example.com.`,\n\t\t)\n\t}\n}\n\n/**\n * Whether an error thrown from the wire layer is a transient network\n * error (DNS failure, TCP reset, timeout). These are worth retrying;\n * typed ORPCError and other application errors are not.\n */\nconst isTransientNetworkError = (e: unknown): boolean =>\n e instanceof TypeError\n\n/**\n * RPCLink URL must be absolute in a Node CLI context.\n *\n * The oRPC `RPCLink` resolves a relative `url` against the host page's\n * origin via `new URL(...)`, which is meaningless in a Node binary (no\n * `window.location`). Passing `API_RPC_PATH` (= `\"/api/v1/rpc\"`) as-is\n * raised `TypeError: Invalid URL` on every command, surfaced to users\n * as `network_error` with hint `Invalid URL` despite the network being\n * fine.\n *\n * Fix: join `resolveBaseURL()` and `API_RPC_PATH` to an absolute URL\n * via `new URL(path, base)` so the leading-slash rule collapses any\n * trailing slash on the base. `resolveBaseURL()` already strips a\n * trailing slash as a first line of defence; `new URL` is the second.\n */\nconst link = new RPCLink({\n url: new URL(API_RPC_PATH, resolveBaseURL()).toString(),\n plugins: [\n new RetryAfterPlugin(),\n new ClientRetryPlugin({\n default: {\n retry: 3,\n shouldRetry: ({ error }) => isTransientNetworkError(error),\n },\n }),\n ],\n})\n\nexport type ORPCClient = RouterClient<typeof appRouter>\n\nexport const orpc: ORPCClient = createORPCClient(link)\n","import { toORPCError } from \"@orpc/client\"\nimport { TemplatesListResponseV1 } from \"@workspace/contracts/v1\"\n\nimport { networkError } from \"../errors/index.js\"\nimport { maybeWarnAboutOutdatedCli } from \"../version/check.js\"\nimport { orpc } from \"./client.js\"\n\nexport type Template = TemplatesListResponseV1[\"templates\"][number]\n\nexport type FetchOptions = {\n /** Skip the version probe. Used by tests and by the version probe itself. */\n skipVersionCheck?: boolean\n}\n\n/**\n * Normalise an error thrown from the typed oRPC client.\n *\n * Uses `toORPCError` from `@orpc/client` to do the shape matching. This is\n * the canonical entry point: the lib does the matching internally and\n * exposes `[Symbol.hasInstance]` for the Next.js multi-context case.\n *\n * In V1 the only mapping is `TypeError -> networkError`, because that\n * is the only error the global `fetch` throws for an unreachable network.\n * `ORPCError` instances are propagated as-is: the calling command knows\n * the procedure semantics and decides how to surface them.\n */\nexport const normaliseError = (e: unknown): Error => {\n // The global fetch throws a TypeError for unreachable networks.\n // `toORPCError` from @orpc/client wraps anything into an ORPCError\n // (replacing the original cause), so we must check TypeError BEFORE\n // calling it.\n if (e instanceof TypeError) {\n return networkError(e.message)\n }\n // For anything that is already (or can be normalised to) an\n // ORPCError, propagate as-is. The calling command knows the\n // procedure semantics and decides how to surface them.\n return toORPCError(e) as Error\n}\n\n/**\n * Fetch the templates registry.\n *\n * Flow:\n * 1. (If not skipVersionCheck) probe /version and warn if outdated.\n * Failure here is silent — version check is best-effort.\n * 2. Call templates.list on the shared typed client. Retry on\n * 5xx and 429 is handled by the official oRPC plugins configured\n * in ./client.ts.\n * 3. Surface typed errors via `normaliseError`.\n *\n * The URL is fixed at `API_RPC_PATH` (imported from\n * `@workspace/api/base-path`). A per-command override is intentionally\n * not part of the public surface in V1.\n *\n * Testing:\n * - The procedure contract is tested via the Server-Side Client\n * pattern in `test/contract/orpc-to-cli-error.test.ts`. Call\n * `appRouter.templates.list()` directly, no HTTP.\n */\nexport const fetchTemplates = async (\n options: FetchOptions = {},\n): Promise<Template[]> => {\n if (!options.skipVersionCheck) {\n await maybeWarnAboutOutdatedCli()\n }\n\n try {\n const result = await orpc.templates.list()\n return result.templates\n } catch (e) {\n throw normaliseError(e)\n }\n}\n","import { spawn as nodeSpawn } from \"node:child_process\"\n\n// Dummy comment added to exercise the CI workflows on a no-op change.\n// No runtime behavior change; tests and bundle are unaffected.\n\nexport type SpawnOptions = {\n cwd?: string\n env?: NodeJS.ProcessEnv\n stdio?: \"inherit\" | \"pipe\" | \"ignore\"\n /** If true, do not throw on non-zero exit codes. Default is `true` (no throw). */\n reject?: boolean\n}\n\n/**\n * Run a command and resolve with its exit code. Never throws on non-zero by\n * default; pass `reject: true` to opt into throwing.\n */\nexport const spawn = (\n command: string,\n args: string[],\n options: SpawnOptions = {},\n): Promise<number> => {\n const { cwd, env, stdio = \"inherit\", reject = false } = options\n return new Promise((resolve, rejectFn) => {\n const child = nodeSpawn(command, args, {\n cwd,\n env: env ?? process.env,\n stdio,\n shell: false,\n })\n child.on(\"error\", (err) => rejectFn(err))\n child.on(\"exit\", (code) => {\n const exit = code ?? 1\n if (reject && exit !== 0) {\n rejectFn(new Error(`${command} exited with code ${exit}`))\n } else {\n resolve(exit)\n }\n })\n })\n}","import { spawn } from \"./spawn.js\"\nimport { gitNotInstalled } from \"../errors/index.js\"\n\nexport type CloneResult = {\n ref: string\n attempts: string[]\n}\n\n/**\n * Clone a git repo to `dir`. Tries `main` first, then falls back to `master`.\n * Caller can pass an explicit `--ref` to override.\n */\nexport const cloneRepo = async (\n url: string,\n dir: string,\n requestedRef?: string,\n): Promise<CloneResult> => {\n const refs = requestedRef ? [requestedRef] : [\"main\", \"master\"]\n const attempts: string[] = []\n\n for (const ref of refs) {\n attempts.push(ref)\n const code = await spawn(\n \"git\",\n [\"clone\", \"--depth\", \"1\", \"--branch\", ref, url, dir],\n { stdio: \"inherit\", reject: false },\n )\n if (code === 0) {\n return { ref, attempts }\n }\n }\n\n // All attempts failed. Probe whether git is even installed.\n const probe = await spawn(\"git\", [\"--version\"], {\n stdio: \"ignore\",\n reject: false,\n })\n if (probe !== 0) {\n throw gitNotInstalled()\n }\n\n // Git works but neither ref matched. Re-throw with attempts context.\n throw new Error(\n `git clone failed for refs: ${refs.join(\", \")}. Tried: ${attempts.join(\", \")}.`,\n )\n}","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\"\n\nexport type PackageManagerInfo = {\n pm: PackageManager\n /** Raw value from packageManager field, e.g. \"pnpm@9.0.0\". May include version. */\n raw?: string\n}\n\n/**\n * Detect the package manager for a directory, in priority order:\n * 1. `packageManager` field in package.json (Corepack convention)\n * 2. Lockfile presence\n * 3. Returns null if nothing matches (caller decides whether to fail)\n */\nexport const detectPackageManager = (\n cwd: string,\n): PackageManagerInfo | null => {\n const pkg = readPackageJson(cwd)\n if (pkg?.packageManager) {\n const pm = parsePackageManagerField(pkg.packageManager)\n if (pm) return pm\n }\n\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return { pm: \"pnpm\" }\n if (existsSync(join(cwd, \"bun.lockb\"))) return { pm: \"bun\" }\n if (existsSync(join(cwd, \"yarn.lock\"))) return { pm: \"yarn\" }\n if (existsSync(join(cwd, \"package-lock.json\"))) return { pm: \"npm\" }\n\n return null\n}\n\nexport const getInstallCommand = (info: PackageManagerInfo): string => {\n switch (info.pm) {\n case \"pnpm\":\n return \"pnpm install\"\n case \"npm\":\n return \"npm install\"\n case \"yarn\":\n return \"yarn install\"\n case \"bun\":\n return \"bun install\"\n }\n}\n\nconst readPackageJson = (\n cwd: string,\n): { packageManager?: string } | null => {\n const path = join(cwd, \"package.json\")\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as {\n packageManager?: string\n }\n } catch {\n return null\n }\n}\n\nexport const parsePackageManagerField = (\n raw: string,\n): PackageManagerInfo | null => {\n // Format: \"<name>@<version>\" or just \"<name>\". Common names: pnpm, npm, yarn, bun.\n const name = raw.split(\"@\")[0]?.trim().toLowerCase()\n if (name === \"pnpm\" || name === \"npm\" || name === \"yarn\" || name === \"bun\") {\n return { pm: name, raw }\n }\n return null\n}","import { existsSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport {\n installFailed,\n internal,\n notFound,\n targetExists,\n} from \"../errors/index.js\"\nimport { printError, printJson } from \"../output/index.js\"\nimport { cloneRepo } from \"../utils/git.js\"\nimport {\n detectPackageManager,\n getInstallCommand,\n type PackageManagerInfo,\n} from \"../utils/detect-pm.js\"\nimport { spawn } from \"../utils/spawn.js\"\n\nexport const initCommand = new Command(\"init\")\n .description(\"Clone a template repo + install dependencies\")\n .argument(\"<slug>\", \"template slug (use `deessejs list` to see options)\")\n .option(\"--pm <name>\", \"override detected package manager (pnpm|npm|yarn|bun)\")\n .option(\"--dir <path>\", \"target directory (default: ./<slug>)\")\n .option(\"--ref <branch>\", \"git ref to clone (default: tries main, falls back to master)\")\n .option(\"--no-install\", \"skip the install step\")\n .option(\"--force\", \"overwrite target directory if it exists\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (\n slug: string,\n opts: {\n pm?: string\n dir?: string\n ref?: string\n install: boolean\n force?: boolean\n json?: boolean\n },\n ) => {\n try {\n const templates = await fetchTemplates()\n const template = templates.find((t) => t.slug === slug)\n if (!template) {\n throw notFound(\n slug,\n templates.map((t) => t.slug),\n )\n }\n\n const dir = resolve(process.cwd(), opts.dir ?? `./${slug}`)\n if (existsSync(dir) && !opts.force) {\n throw targetExists(dir)\n }\n\n const repoUrl =\n template.cloneUrl ?? `https://github.com/${template.owner}/${template.repo}`\n\n const cloneSpinner = ora(`Cloning ${pc.cyan(template.owner + \"/\" + template.repo)}...`).start()\n let cloneResult\n try {\n cloneResult = await cloneRepo(repoUrl, dir, opts.ref)\n cloneSpinner.succeed(`Cloned into ${pc.cyan(dir)} (ref: ${cloneResult.ref})`)\n } catch (err) {\n cloneSpinner.fail(\"Clone failed\")\n throw err\n }\n\n if (!opts.install) {\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: false,\n })\n } else {\n console.log(pc.dim(`\\nNext: cd ${dir} && <your package manager> install\\n`))\n }\n return\n }\n\n const VALID_PMS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const\n type ValidPm = (typeof VALID_PMS)[number]\n const pmInfo: PackageManagerInfo | null =\n opts.pm && (VALID_PMS as readonly string[]).includes(opts.pm)\n ? { pm: opts.pm as ValidPm }\n : detectPackageManager(dir)\n\n if (!pmInfo) {\n console.log(\n pc.yellow(\n \"\\nNo package manager detected (no packageManager field, no lockfile).\",\n ),\n )\n console.log(\n pc.dim(\"Skipping install. Run your install command manually inside the directory.\\n\"),\n )\n } else {\n const installSpinner = ora(\n `Installing dependencies via ${pc.cyan(pmInfo.pm)}...`,\n ).start()\n const cmd = getInstallCommand(pmInfo)\n const cmdParts = cmd.split(\" \")\n const bin = cmdParts[0] ?? \"npm\"\n const args = cmdParts.slice(1)\n const code = await spawn(bin, args, { cwd: dir, stdio: \"inherit\", reject: false })\n if (code !== 0) {\n installSpinner.fail(`${pmInfo.pm} install failed`)\n throw installFailed(pmInfo.pm, code)\n }\n installSpinner.succeed(\"Dependencies installed\")\n }\n\n if (opts.json) {\n printJson({\n ok: true,\n slug: template.slug,\n dir,\n ref: cloneResult.ref,\n installed: pmInfo !== null,\n packageManager: pmInfo?.pm ?? null,\n })\n } else {\n console.log()\n console.log(pc.green(\"✓ Template ready\"))\n console.log(pc.dim(` cd ${dir}`))\n console.log(\n pc.dim(\n pmInfo\n ? ` ${getInstallCommand(pmInfo).split(\" \")[0]} dev`\n : ` install deps, then start`,\n ),\n )\n console.log()\n }\n } catch (err) {\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit((err as { exitCode?: () => number }).exitCode?.() ?? 1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal } from \"../errors/index.js\"\nimport { printError, printJson, printTemplatesTable } from \"../output/index.js\"\n\nexport const listCommand = new Command(\"list\")\n .description(\"List available templates\")\n .option(\"--category <name>\", \"filter to a single category\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(\n async (opts: { category?: string; json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching templates...\").start()\n\n try {\n const all = await fetchTemplates()\n const filtered = opts.category\n ? all.filter((t) => t.category === opts.category)\n : all\n\n spinner?.stop()\n\n if (opts.json) {\n printJson({ templates: filtered })\n } else {\n if (opts.category) {\n console.log(pc.dim(`Category: ${opts.category}`))\n }\n printTemplatesTable(filtered)\n console.log()\n console.log(\n pc.dim(\n `${filtered.length} template${filtered.length === 1 ? \"\" : \"s\"}.` +\n (opts.category\n ? \"\"\n : \" Use --category <name> to filter, --json for scripting.\"),\n ),\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch templates\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n },\n )\n","import { Command } from \"commander\"\nimport ora from \"ora\"\nimport { fetchTemplates } from \"../api/index.js\"\nimport { internal, notFound } from \"../errors/index.js\"\nimport { printError, printJson, printTemplateInfo } from \"../output/index.js\"\n\nexport const infoCommand = new Command(\"info\")\n .description(\"Show details for one template\")\n .argument(\"<slug>\", \"template slug\")\n .option(\"--json\", \"JSON output for scripting\")\n .action(async (slug: string, opts: { json?: boolean }) => {\n const spinner = opts.json ? null : ora(\"Fetching template...\").start()\n\n try {\n const all = await fetchTemplates()\n const template = all.find((t) => t.slug === slug)\n spinner?.stop()\n\n if (!template) {\n throw notFound(slug, all.map((t) => t.slug))\n }\n\n if (opts.json) {\n printJson({ template })\n } else {\n printTemplateInfo(template)\n console.log()\n console.log(\n `Install: ${`deessejs init ${template.slug}`}`,\n )\n }\n } catch (err) {\n spinner?.fail(\"Failed to fetch template\")\n if (err instanceof Error && err.name === \"CliError\") {\n if (opts.json) {\n printJson({\n ok: false,\n code: (err as { code?: string }).code,\n message: err.message,\n hint: (err as { hint?: string }).hint,\n })\n } else {\n printError(err as Parameters<typeof printError>[0])\n }\n process.exit(1)\n }\n throw internal(err instanceof Error ? err.message : String(err))\n }\n })\n","import { Command } from \"commander\"\nimport pc from \"picocolors\"\nimport { readPackageVersion } from \"./api/self-version.js\"\nimport {\n\tloginCommand,\n\tlogoutCommand,\n\tstatusCommand,\n} from \"./commands/auth/index.js\"\nimport { initCommand } from \"./commands/init.js\"\nimport { listCommand } from \"./commands/list.js\"\nimport { infoCommand } from \"./commands/info.js\"\n\nconst program = new Command()\n\nprogram\n .name(\"deessejs\")\n .description(\"CLI for the DeesseJS template registry\")\n .version(readPackageVersion())\n\nprogram.addCommand(listCommand)\nprogram.addCommand(infoCommand)\nprogram.addCommand(initCommand)\n\n// auth subcommand (ADR-020). Three children: login (request\n// device code, open browser, poll), status (print stored\n// user identity), logout (sign out + clear local token).\nconst authCommand = new Command(\"auth\").description(\n\t\"Authenticate this machine against the DeesseJS server\",\n)\nauthCommand.addCommand(loginCommand)\nauthCommand.addCommand(statusCommand)\nauthCommand.addCommand(logoutCommand)\nprogram.addCommand(authCommand)\n\nprogram.parseAsync(process.argv).catch((err) => {\n // Last-resort error handler. Per-command handlers catch CliError and exit\n // cleanly with the right code. Anything that lands here is an uncaught bug.\n process.stderr.write(\n `${pc.red(\"Internal error\")}: ${err instanceof Error ? err.message : String(err)}\\n`,\n )\n if (process.env.DEESSEJS_DEBUG) {\n process.stderr.write(`\\n${err instanceof Error && err.stack ? err.stack : \"\"}\\n`)\n }\n process.exit(1)\n})\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deessejs/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "CLI for the DeesseJS template registry.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,19 +26,6 @@
|
|
|
26
26
|
"README.md",
|
|
27
27
|
"../../LICENSE"
|
|
28
28
|
],
|
|
29
|
-
"scripts": {
|
|
30
|
-
"prebuild": "pnpm --filter @workspace/contracts build",
|
|
31
|
-
"build": "tsup",
|
|
32
|
-
"predev": "pnpm --filter @workspace/contracts build",
|
|
33
|
-
"dev": "tsup --watch",
|
|
34
|
-
"lint": "eslint",
|
|
35
|
-
"format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
|
|
36
|
-
"typecheck": "tsc --noEmit",
|
|
37
|
-
"pretest": "pnpm turbo build --filter=@deessejs/cli && tsup",
|
|
38
|
-
"test": "vitest run",
|
|
39
|
-
"test:watch": "vitest",
|
|
40
|
-
"start": "node ./dist/index.js"
|
|
41
|
-
},
|
|
42
29
|
"dependencies": {
|
|
43
30
|
"@deessejs/errors": "^1.1.1",
|
|
44
31
|
"@deessejs/fp": "^1.0.0",
|
|
@@ -51,17 +38,17 @@
|
|
|
51
38
|
"picocolors": "^1.1.1"
|
|
52
39
|
},
|
|
53
40
|
"devDependencies": {
|
|
54
|
-
"@types/node": "
|
|
55
|
-
"@workspace/api": "workspace:*",
|
|
56
|
-
"@workspace/contracts": "workspace:*",
|
|
57
|
-
"@workspace/eslint-config": "workspace:*",
|
|
58
|
-
"@workspace/typescript-config": "workspace:*",
|
|
41
|
+
"@types/node": "^24",
|
|
59
42
|
"eslint": "^9",
|
|
60
43
|
"prettier": "^3.9.4",
|
|
61
44
|
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
62
45
|
"tsup": "^8.3.5",
|
|
63
|
-
"typescript": "
|
|
64
|
-
"vitest": "^2.1.5"
|
|
46
|
+
"typescript": "^6.0.3",
|
|
47
|
+
"vitest": "^2.1.5",
|
|
48
|
+
"@workspace/api": "0.0.3",
|
|
49
|
+
"@workspace/eslint-config": "0.0.0",
|
|
50
|
+
"@workspace/typescript-config": "0.0.0",
|
|
51
|
+
"@workspace/contracts": "0.0.1"
|
|
65
52
|
},
|
|
66
53
|
"engines": {
|
|
67
54
|
"node": ">=20.0.0"
|
|
@@ -69,5 +56,18 @@
|
|
|
69
56
|
"publishConfig": {
|
|
70
57
|
"access": "public",
|
|
71
58
|
"provenance": true
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"prebuild": "pnpm --filter @workspace/contracts build",
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"predev": "pnpm --filter @workspace/contracts build",
|
|
64
|
+
"dev": "tsup --watch",
|
|
65
|
+
"lint": "eslint",
|
|
66
|
+
"format": "prettier --write \"**/*.{ts,tsx,json,md}\"",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"pretest": "pnpm turbo build --filter=@deessejs/cli && tsup",
|
|
69
|
+
"test": "vitest run",
|
|
70
|
+
"test:watch": "vitest",
|
|
71
|
+
"start": "node ./dist/index.js"
|
|
72
72
|
}
|
|
73
|
-
}
|
|
73
|
+
}
|