@quatronic/qore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/dist/cli.js +1084 -0
- package/dist/cli.js.map +1 -0
- package/package.json +58 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli/io.ts","../src/platform/browser.ts","../src/core/errors.ts","../src/cli/program.ts","../src/core/api/http.ts","../src/cli/render.ts","../src/core/api/meta.ts","../src/core/auth/oidc.ts","../src/core/auth/login.ts","../src/core/auth/tokenStore.ts","../src/core/profiles.ts","../src/core/api/client.ts","../src/core/auth/refresh.ts","../src/core/session.ts","../src/cli/commands/login.ts","../src/cli/commands/logout.ts","../src/cli/commands/tenant.ts","../src/cli/commands/version.ts","../src/cli/commands/whoami.ts","../src/cli/commands/index.ts","../src/cli/updateCheck.ts","../src/core/config.ts","../src/platform/keychain.ts","../src/platform/lock.ts","../src/platform/paths.ts","../src/version.ts"],"sourcesContent":["import { homedir } from \"node:os\"\nimport { EnvHttpProxyAgent, setGlobalDispatcher } from \"undici\"\nimport { isInteractive, processIo } from \"./cli/io.js\"\nimport { run } from \"./cli/program.js\"\nimport { COMMANDS } from \"./cli/commands/index.js\"\nimport { maybeNotifyUpdate } from \"./cli/updateCheck.js\"\nimport { abortableFetch } from \"./core/api/http.js\"\nimport { createOidc } from \"./core/auth/oidc.js\"\nimport { ConfigStore } from \"./core/config.js\"\nimport type { Deps } from \"./core/deps.js\"\nimport { OsKeychain } from \"./platform/keychain.js\"\nimport { fileLock } from \"./platform/lock.js\"\nimport { configDir } from \"./platform/paths.js\"\nimport { VERSION } from \"./version.js\"\n\nif (process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY) setGlobalDispatcher(new EnvHttpProxyAgent())\n\nconst dir = configDir(process.env, process.platform, homedir())\nconst argv = process.argv.slice(2)\nconst json = argv.includes(\"--json\")\n// Ctrl+C: the first one aborts every in-flight request and prompt through `ac.signal`\n// (→ CancelledError → exit 130); a second one exits at once, whatever is still running.\nconst ac = new AbortController()\nprocess.on(\"SIGINT\", () => {\n if (ac.signal.aborted) process.exit(130)\n ac.abort()\n})\nconst fetch = abortableFetch(globalThis.fetch, ac.signal)\nconst deps: Deps = {\n fetch,\n keychain: new OsKeychain(),\n config: new ConfigStore(dir),\n withLock: fileLock(dir),\n now: () => new Date(),\n oidcFor: (issuer) => createOidc({ issuer, clientId: \"qore-cli\", fetch }),\n env: process.env,\n platform: process.platform,\n version: VERSION,\n}\nconst io = processIo(isInteractive({ stdinTTY: Boolean(process.stdin.isTTY), stdoutTTY: Boolean(process.stdout.isTTY),\n json, noInput: argv.includes(\"--no-input\"), env: process.env }))\nprocess.exitCode = await run(argv, deps, io, ac.signal, COMMANDS)\nif (!ac.signal.aborted) {\n try {\n await maybeNotifyUpdate(deps, io, { json })\n } catch {\n // an update check must never change the exit code\n }\n}\n","import { select } from \"@inquirer/prompts\"\nimport { createInterface } from \"node:readline\"\nimport { openBrowser } from \"../platform/browser.js\"\nimport { CancelledError } from \"../core/errors.js\"\n\nexport interface Io {\n out(s: string): void\n err(s: string): void\n interactive: boolean\n select<T>(msg: string, choices: { name: string; value: T; description?: string }[]): Promise<T>\n waitForEnter(msg: string, signal: AbortSignal): Promise<void>\n openUrl(url: string): Promise<boolean>\n}\n\nexport function isInteractive(o: { stdinTTY: boolean; stdoutTTY: boolean; json: boolean; noInput: boolean; env: NodeJS.ProcessEnv }): boolean {\n return o.stdinTTY && o.stdoutTTY && !o.json && !o.noInput && !o.env.CI\n}\n\nexport function processIo(interactive: boolean): Io {\n return {\n out: (s) => { process.stdout.write(s + \"\\n\") },\n err: (s) => { process.stderr.write(s + \"\\n\") },\n interactive,\n async select(message, choices) {\n try { return await select({ message, choices }) } catch (e) {\n if ((e as Error).name === \"ExitPromptError\") throw new CancelledError()\n throw e\n }\n },\n waitForEnter: createWaitForEnter(process.stdin, process.stderr),\n openUrl: openBrowser,\n }\n}\n\n/** Builds a `waitForEnter` bound to the given streams, so tests can drive it without a\n * real TTY. Readline puts a TTY's stdin in raw mode, which turns Ctrl+C into the\n * interface's own 'SIGINT' event rather than a process-level SIGINT (R16) — that must be\n * turned into a CancelledError itself, since `process.once(\"SIGINT\", …)` in cli.ts never\n * fires for it. `terminal: true` makes readline parse Ctrl+C the same way on any stream. */\nexport function createWaitForEnter(\n input: NodeJS.ReadableStream, output: NodeJS.WritableStream,\n): (message: string, signal: AbortSignal) => Promise<void> {\n return (message, signal) => new Promise((resolve, reject) => {\n const rl = createInterface({ input, output, terminal: true })\n const onAbort = () => { rl.close(); reject(new CancelledError()) }\n const done = () => { signal.removeEventListener(\"abort\", onAbort); rl.close(); resolve() }\n signal.addEventListener(\"abort\", onAbort, { once: true })\n rl.on(\"SIGINT\", () => { signal.removeEventListener(\"abort\", onAbort); rl.close(); reject(new CancelledError()) })\n rl.question(message, done)\n })\n}\n","import open from \"open\"\n\n/** Opens the URL; false when there is no display (SSH, container) or it fails. */\nexport async function openBrowser(url: string): Promise<boolean> {\n if (process.platform === \"linux\" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) return false\n try { await open(url); return true } catch { return false }\n}\n","export const EXIT = {\n QORE_INTERNAL: 1,\n QORE_KEYCHAIN_UNAVAILABLE: 1,\n QORE_KEYCHAIN_DENIED: 1,\n QORE_CONTEXT_REQUIRED: 2,\n QORE_CONTEXT_INVALID: 2,\n QORE_NOT_LOGGED_IN: 4,\n QORE_SESSION_EXPIRED: 4,\n QORE_LOGIN_EXPIRED: 4,\n QORE_LOGIN_DENIED: 4,\n QORE_CLOCK_SKEW: 4,\n QORE_TENANT_ACCESS_LOST: 5,\n QORE_RESOURCE_NOT_FOUND: 5,\n QORE_ACCESS_DENIED: 5,\n QORE_NO_DEVELOPER_ACCESS: 5,\n QORE_AUTH_UNAVAILABLE: 6,\n QORE_AUTH_BUSY: 6,\n QORE_API_UNREACHABLE: 6,\n QORE_API_UNAVAILABLE: 6,\n QORE_INCOMPATIBLE_SERVER: 7,\n QORE_UNSUPPORTED_BY_SERVER: 7,\n QORE_UPGRADE_REQUIRED: 7,\n QORE_PORTAL_UNTRUSTED: 7,\n QORE_RATE_LIMITED: 8,\n} as const\n\nexport type QoreErrorCode = keyof typeof EXIT\n\ntype Opts = {\n hint?: string\n status?: number\n requestId?: string\n candidates?: unknown[]\n serverCode?: string\n details?: Record<string, unknown>\n cause?: unknown\n}\n\nexport class QoreError extends Error {\n readonly code: QoreErrorCode\n readonly hint?: string\n readonly status?: number\n readonly requestId?: string\n readonly candidates?: unknown[]\n readonly serverCode?: string\n readonly details?: Record<string, unknown>\n\n constructor(code: QoreErrorCode, message: string, opts: Opts = {}) {\n super(message, opts.cause === undefined ? undefined : { cause: opts.cause })\n this.name = \"QoreError\"\n this.code = code\n this.hint = opts.hint\n this.status = opts.status\n this.requestId = opts.requestId\n this.candidates = opts.candidates\n this.serverCode = opts.serverCode\n this.details = opts.details\n }\n}\n\nexport class CancelledError extends Error {\n constructor() {\n super(\"Cancelled\")\n this.name = \"CancelledError\"\n }\n}\n\nexport function exitCodeFor(err: unknown): number {\n if (err instanceof CancelledError || (err instanceof Error && err.name === \"CancelledError\")) return 130\n if (err instanceof QoreError) return EXIT[err.code]\n return 1\n}\n\nexport function toJsonError(err: unknown): Record<string, unknown> {\n if (!(err instanceof QoreError)) {\n return { code: \"QORE_INTERNAL\", message: err instanceof Error ? err.message : String(err) }\n }\n const out: Record<string, unknown> = { code: err.code, message: err.message }\n for (const k of [\"hint\", \"status\", \"requestId\", \"candidates\", \"serverCode\", \"details\"] as const) {\n if (err[k] !== undefined) out[k] = err[k]\n }\n return out\n}\n","import { Command, CommanderError } from \"commander\"\nimport type { Deps } from \"../core/deps.js\"\nimport { isAbortError } from \"../core/api/http.js\"\nimport { CancelledError, exitCodeFor } from \"../core/errors.js\"\nimport type { Io } from \"./io.js\"\nimport pc from \"picocolors\"\nimport { renderError } from \"./render.js\"\n\n/** Detects --json before commander has parsed anything, so a parse error (thrown before\n * global opts exist) can still be rendered as JSON, and commander's own stderr line\n * can be suppressed in that mode. See ruling R12. */\nfunction jsonFromArgv(argv: string[]): boolean {\n return argv.some((a) => a === \"--json\" || a.startsWith(\"--json=\"))\n}\n\nexport type GlobalOpts = { portal?: string; json?: boolean; input?: boolean; verbose?: boolean; color?: boolean }\n\nexport type CommandContext = { deps: Deps; io: Io; signal: AbortSignal; opts: () => GlobalOpts }\n\nexport type Register = (program: Command, ctx: CommandContext) => void\n\n/** `--verbose`: request lines (method, path, status, request id; never a token) on stderr. */\nexport function requestLog(ctx: CommandContext): ((line: string) => void) | undefined {\n return ctx.opts().verbose ? (line) => ctx.io.err(line) : undefined\n}\n\nexport function buildProgram(deps: Deps, io: Io, signal: AbortSignal, register: Register[]): Command {\n const program = new Command(\"qore\")\n .description(\"Qore developer CLI\")\n .option(\"--portal <name|url>\", \"prod, staging, or a portal URL (default: the portal you last logged in to, else prod)\")\n .option(\"--json\", \"print exactly one JSON document on stdout\")\n .option(\"--no-input\", \"never prompt\")\n .option(\"--verbose\", \"log request lines (never secrets)\")\n .option(\"--no-color\", \"disable colours\")\n .exitOverride()\n .configureOutput({ writeOut: (s) => io.out(s.trimEnd()), writeErr: (s) => io.err(s.trimEnd()) })\n const ctx: CommandContext = { deps, io, signal, opts: () => program.opts<GlobalOpts>() }\n for (const r of register) r(program, ctx)\n return program\n}\n\nexport async function run(argv: string[], deps: Deps, io: Io, signal: AbortSignal, register: Register[]): Promise<number> {\n const json = jsonFromArgv(argv)\n // Commander may throw before global opts exist (e.g. an unknown option), and by default\n // writes its own message to stderr on the way there. In --json mode that would land\n // alongside our single JSON document, so suppress it here and render the error ourselves.\n const parseIo: Io = json ? { ...io, err: () => {} } : io\n const program = buildProgram(deps, parseIo, signal, register)\n try {\n await program.parseAsync(argv, { from: \"user\" })\n return 0\n } catch (caught) {\n // Once Ctrl+C has fired, any AbortError that escaped a mapping is that cancel.\n const e = signal.aborted && isAbortError(caught) ? new CancelledError() : caught\n if (e instanceof CommanderError) {\n if (e.exitCode === 0) return 0\n if (json) io.out(JSON.stringify({ ok: false, error: { code: \"QORE_CONTEXT_INVALID\", message: e.message } }))\n return 2\n }\n const opts = program.opts<GlobalOpts>()\n renderError(io, e, Boolean(opts.json), pc.isColorSupported && opts.color !== false)\n return exitCodeFor(e)\n }\n}\n","import { CancelledError, QoreError, type QoreErrorCode } from \"../errors.js\"\n\nexport type Fetch = (input: string | URL, init?: RequestInit) => Promise<Response>\n\n/** Every request also carries `signal` (the process's Ctrl+C signal), next to any signal\n * of the caller's own, so a cancel aborts whatever is in flight (spec §4). */\nexport function abortableFetch(fetch: Fetch, signal: AbortSignal): Fetch {\n return (input, init) => fetch(input, { ...init, signal: init?.signal ? AbortSignal.any([init.signal, signal]) : signal })\n}\n\nconst TLS = new Set([\"SELF_SIGNED_CERT_IN_CHAIN\", \"UNABLE_TO_GET_ISSUER_CERT_LOCALLY\",\n \"DEPTH_ZERO_SELF_SIGNED_CERT\", \"UNABLE_TO_VERIFY_LEAF_SIGNATURE\", \"CERT_HAS_EXPIRED\"])\n\nfunction causeCode(e: unknown): string | undefined {\n const c = (e as { cause?: { code?: unknown } })?.cause\n const code = c?.code ?? (e as { code?: unknown })?.code\n // DOMException carries a numeric legacy `code`; only errno-style strings are meaningful here.\n return typeof code === \"string\" ? code : undefined\n}\n\nexport function isAbortError(e: unknown): boolean {\n return (e as { name?: unknown } | null)?.name === \"AbortError\"\n}\n\n/** A failed fetch: a cancel (Ctrl+C aborted the request) or a network failure. */\nexport function fetchError(e: unknown, host: string): Error {\n return isAbortError(e) ? new CancelledError() : networkError(e, host)\n}\n\nexport function networkError(e: unknown, host: string): QoreError {\n const code = causeCode(e) ?? \"\"\n let reason = \"connect\"\n let hint = \"Check your network or VPN.\"\n if (code === \"ENOTFOUND\" || code === \"EAI_AGAIN\") {\n reason = \"dns\"; hint = `${host} could not be resolved. Check your network or VPN.`\n } else if (TLS.has(code)) {\n reason = \"tls\"\n hint = \"A proxy is re-signing TLS. Point NODE_EXTRA_CA_CERTS at your organisation's CA certificate.\"\n } else if (code.includes(\"TIMEOUT\") || code === \"ETIMEDOUT\") {\n reason = \"timeout\"\n } else if (!process.env.HTTPS_PROXY && !process.env.https_proxy) {\n hint = \"Check your network. Behind a corporate proxy, set HTTPS_PROXY.\"\n }\n return new QoreError(\"QORE_API_UNREACHABLE\", `Could not reach ${host}`, { hint, details: { reason, host, errno: code || undefined }, cause: e })\n}\n\nconst BY_SERVER_CODE: Record<string, QoreErrorCode> = {\n \"app.access.denied\": \"QORE_ACCESS_DENIED\",\n \"auth.scope.insufficient\": \"QORE_ACCESS_DENIED\",\n \"cli.upgrade_required\": \"QORE_UPGRADE_REQUIRED\",\n \"rate_limited\": \"QORE_RATE_LIMITED\",\n}\n\nfunction byStatus(status: number): QoreErrorCode {\n if (status === 403) return \"QORE_ACCESS_DENIED\"\n if (status === 404) return \"QORE_RESOURCE_NOT_FOUND\"\n if (status === 426) return \"QORE_UPGRADE_REQUIRED\"\n if (status === 429) return \"QORE_RATE_LIMITED\"\n if (status === 502 || status === 503 || status === 504) return \"QORE_API_UNAVAILABLE\"\n return \"QORE_INTERNAL\"\n}\n\nexport async function problemToError(res: Response): Promise<QoreError> {\n let body: { code?: string; title?: string; detail?: unknown } = {}\n try { body = (await res.json()) as typeof body } catch { /* not JSON */ }\n const serverCode = body.code\n const code = (serverCode && BY_SERVER_CODE[serverCode]) || byStatus(res.status)\n const requestId = res.headers.get(\"x-request-id\") ?? undefined\n const details: Record<string, unknown> = {}\n if (body.detail && typeof body.detail === \"object\") Object.assign(details, body.detail)\n const detail = typeof body.detail === \"string\" && body.detail ? body.detail : undefined\n if (detail) details.detail = detail\n const retry = res.headers.get(\"retry-after\")\n if (retry && /^\\d+$/.test(retry)) details.retryAfter = Number(retry)\n const hint =\n code === \"QORE_UPGRADE_REQUIRED\" ? \"Run: npm i -g @quatronic/qore\"\n : code === \"QORE_RATE_LIMITED\" ? `Wait ${details.retryAfter ?? \"a moment\"} s and retry.`\n : code === \"QORE_API_UNAVAILABLE\" ? \"Qore is temporarily unavailable; retry in a minute.\"\n : undefined\n // portal-api falls back to the title \"HTTP error\"; a server code is no message either.\n // Then the string detail is the most useful message there is.\n const genericTitle = !body.title || body.title === \"HTTP error\" || body.title === serverCode\n const message = (genericTitle && detail) || body.title || `Request failed (${res.status})`\n return new QoreError(code, message, {\n status: res.status, requestId, serverCode, hint,\n details: Object.keys(details).length ? details : undefined,\n })\n}\n","import pc, { createColors } from \"picocolors\"\nimport { QoreError, toJsonError } from \"../core/errors.js\"\nimport type { Io } from \"./io.js\"\n\nexport function renderJson(io: Io, data: unknown): void {\n io.out(JSON.stringify({ ok: true, data }))\n}\n\nexport function renderError(io: Io, err: unknown, json: boolean, colorEnabled = pc.isColorSupported): void {\n if (json) { io.out(JSON.stringify({ ok: false, error: toJsonError(err) })); return }\n if (err instanceof Error && err.name === \"CancelledError\") { io.err(\"Cancelled\"); return }\n const c = createColors(colorEnabled)\n const e = err instanceof QoreError ? err : new QoreError(\"QORE_INTERNAL\", err instanceof Error ? err.message : String(err))\n io.err(c.red(`Error: ${e.message}`))\n if (e.hint) io.err(e.hint)\n io.err(c.dim(`Code: ${e.code}${e.requestId ? ` (request ${e.requestId})` : \"\"}`))\n}\n","import { QoreError } from \"../errors.js\"\nimport type { PortalRef } from \"../profiles.js\"\nimport { fetchError, problemToError, type Fetch } from \"./http.js\"\nimport type { CliMeta } from \"./types.js\"\n\nconst SUPPORTED = [\"v1\"] as const\nconst SEMVER = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?/\n\nexport function compareVersions(a: string, b: string): number {\n const pa = SEMVER.exec(a), pb = SEMVER.exec(b)\n if (!pa || !pb) return 0\n for (let i = 1; i <= 3; i++) {\n const d = Number(pa[i]) - Number(pb[i])\n if (d !== 0) return d\n }\n if (pa[4] && !pb[4]) return -1\n if (!pa[4] && pb[4]) return 1\n return 0\n}\n\nexport async function fetchMeta(fetch: Fetch, apiOrigin: string): Promise<CliMeta> {\n let res: Response\n try { res = await fetch(`${apiOrigin}/api/cli/meta`, { headers: { accept: \"application/json\" } }) }\n catch (e) { throw fetchError(e, new URL(apiOrigin).host) }\n if (res.status === 404) {\n // No CLI surface at all: a portal-api from before the CLI (or the wrong URL).\n throw new QoreError(\"QORE_INCOMPATIBLE_SERVER\", \"This portal does not support the Qore CLI yet\", {\n status: 404, requestId: res.headers.get(\"x-request-id\") ?? undefined,\n hint: `Check the portal URL (${apiOrigin}); if it is right, the portal must be upgraded before qore can use it.`,\n })\n }\n if (!res.ok) throw await problemToError(res)\n return (await res.json()) as CliMeta\n}\n\nexport function negotiate(meta: CliMeta, portal: PortalRef, cliVersion: string): { apiVersion: \"v1\" } {\n if (portal.pinnedIssuer && meta.auth.issuer !== portal.pinnedIssuer) {\n throw new QoreError(\"QORE_PORTAL_UNTRUSTED\", `${portal.apiOrigin} names an unexpected identity provider`, {\n details: { expected: portal.pinnedIssuer, got: meta.auth.issuer },\n hint: \"Refusing to log in. Check the portal URL and your network.\",\n })\n }\n const apiVersion = SUPPORTED.find((v) => meta.apiVersions.includes(v))\n if (!apiVersion) {\n throw new QoreError(\"QORE_INCOMPATIBLE_SERVER\", \"This portal speaks no API version this qore knows\", {\n details: { server: meta.apiVersions, client: [...SUPPORTED] }, hint: \"Run: npm i -g @quatronic/qore\",\n })\n }\n if (!cliVersion.endsWith(\"-dev\") && compareVersions(cliVersion, meta.minCliVersion) < 0) {\n throw new QoreError(\"QORE_UPGRADE_REQUIRED\", `qore ${cliVersion} is too old for this portal (needs ${meta.minCliVersion})`, {\n hint: \"Run: npm i -g @quatronic/qore\",\n })\n }\n return { apiVersion }\n}\n","import * as oc from \"openid-client\"\nimport { CancelledError, QoreError } from \"../errors.js\"\nimport type { Fetch } from \"../api/http.js\"\nimport { isAbortError, networkError } from \"../api/http.js\"\n\nexport type DeviceStart = { userCode: string; verificationUri: string; verificationUriComplete?: string; expiresIn: number; handle: unknown }\nexport type TokenSet = { accessToken: string; refreshToken: string; expiresIn: number; scope: string; sub: string; email?: string }\n\nexport interface Oidc {\n startDevice(scope: string): Promise<DeviceStart>\n pollDevice(start: DeviceStart, signal: AbortSignal): Promise<TokenSet>\n refresh(rt: string, scope?: string): Promise<TokenSet>\n revoke(rt: string): Promise<void>\n}\n\nexport const LOGIN_SCOPE = \"openid profile email offline_access qore:read qore:local-env\"\n\nfunction decodeSub(accessToken: string): { sub: string; email?: string } {\n const part = accessToken.split(\".\")[1] ?? \"\"\n const claims = JSON.parse(Buffer.from(part, \"base64url\").toString(\"utf8\")) as { sub: string; email?: string }\n return { sub: claims.sub, email: claims.email }\n}\n\nfunction toTokenSet(t: oc.TokenEndpointResponse, fallbackRt?: string): TokenSet {\n const rt = t.refresh_token ?? fallbackRt\n if (!rt) throw new QoreError(\"QORE_INTERNAL\", \"Keycloak returned no refresh token\")\n return { accessToken: t.access_token, refreshToken: rt, expiresIn: t.expires_in ?? 600,\n scope: t.scope ?? \"\", ...decodeSub(t.access_token) }\n}\n\n/** Keycloak unreachable is QORE_AUTH_UNAVAILABLE (spec §7, §14; R19), not the portal's\n * QORE_API_UNREACHABLE — with the same network diagnosis (hint, reason, host). */\nfunction unreachable(e: unknown, host: string): QoreError {\n const n = networkError(e, host)\n return new QoreError(\"QORE_AUTH_UNAVAILABLE\", n.message, { hint: n.hint, details: n.details, cause: e })\n}\n\nexport function mapOidcError(e: unknown, host: string): Error {\n if (e instanceof QoreError || e instanceof CancelledError) return e\n // Ctrl+C aborts the request's signal; openid-client wraps that DOMException as\n // ClientError { code: \"OAUTH_ABORT\", cause }.\n if (isAbortError(e) || (e as { code?: unknown })?.code === \"OAUTH_ABORT\" || isAbortError((e as { cause?: unknown })?.cause)) {\n return new CancelledError()\n }\n const err = (e as { error?: string }).error\n if (err === \"access_denied\") return new QoreError(\"QORE_LOGIN_DENIED\", \"The login was denied in the browser\")\n if (err === \"expired_token\") return new QoreError(\"QORE_LOGIN_EXPIRED\", \"The login code expired\", { hint: \"Run `qore login` again.\" })\n if (err === \"invalid_grant\") return new QoreError(\"QORE_SESSION_EXPIRED\", \"Your session has ended\", { hint: \"Run `qore login`.\" })\n const status = (e as { status?: number }).status\n if (status && status >= 500) return new QoreError(\"QORE_AUTH_UNAVAILABLE\", \"Keycloak is unavailable\", { cause: e })\n if (e instanceof TypeError) return unreachable(e, host)\n // openid-client sometimes wraps the raw fetch TypeError (DNS/TLS/connect/timeout) one\n // level deep, e.g. `new ClientError(\"something went wrong\", { cause: err })`.\n const cause = (e as { cause?: unknown })?.cause\n if (cause instanceof TypeError) return unreachable(cause, host)\n return new QoreError(\"QORE_AUTH_UNAVAILABLE\", \"Login failed\", { cause: e })\n}\n\nexport async function createOidc(opts: { issuer: string; clientId: string; fetch: Fetch }): Promise<Oidc> {\n const host = new URL(opts.issuer).host\n const execute = new URL(opts.issuer).protocol === \"http:\" ? [oc.allowInsecureRequests] : []\n let config: oc.Configuration\n try {\n config = await oc.discovery(new URL(opts.issuer), opts.clientId, undefined, oc.None(), {\n execute, [oc.customFetch]: opts.fetch as unknown as oc.CustomFetch,\n })\n } catch (e) { throw mapOidcError(e, host) }\n\n return {\n async startDevice(scope) {\n try {\n const r = await oc.initiateDeviceAuthorization(config, { scope })\n return { userCode: r.user_code, verificationUri: r.verification_uri,\n verificationUriComplete: r.verification_uri_complete, expiresIn: r.expires_in, handle: r }\n } catch (e) { throw mapOidcError(e, host) }\n },\n async pollDevice(start, signal) {\n try {\n const t = await oc.pollDeviceAuthorizationGrant(config, start.handle as oc.DeviceAuthorizationResponse, undefined, { signal })\n return toTokenSet(t)\n } catch (e) { throw mapOidcError(e, host) }\n },\n async refresh(rt, scope) {\n try {\n const t = await oc.refreshTokenGrant(config, rt, scope ? { scope } : undefined)\n return toTokenSet(t, rt)\n } catch (e) { throw mapOidcError(e, host) }\n },\n async revoke(rt) {\n try { await oc.tokenRevocation(config, rt, { token_type_hint: \"refresh_token\" }) }\n catch (e) { throw mapOidcError(e, host) }\n },\n }\n}\n","import type { WithLock } from \"../../platform/lock.js\"\nimport type { DeviceStart, Oidc, TokenSet } from \"./oidc.js\"\nimport { LOGIN_SCOPE } from \"./oidc.js\"\nimport type { TokenStore } from \"./tokenStore.js\"\n\nexport async function deviceLogin(opts: {\n oidc: Oidc\n store: TokenStore\n now: () => Date\n /** Shows the code. Polling already runs meanwhile; `settled` aborts once it succeeds or\n * fails, so a prompt waiting on the user (who may have opened the URL themselves) can end. */\n onCode: (s: DeviceStart, settled: AbortSignal) => void | Promise<void>\n signal: AbortSignal\n withLock?: WithLock\n lockName?: string\n}): Promise<TokenSet> {\n // Probe the keychain first: an unusable or denied keychain must fail before the user\n // approves anything in the browser (Review Focus #4), not after.\n await opts.store.getRefresh()\n const start = await opts.oidc.startDevice(LOGIN_SCOPE)\n const stopPoll = new AbortController()\n const settled = new AbortController()\n const poll = opts.oidc.pollDevice(start, AbortSignal.any([opts.signal, stopPoll.signal]))\n .finally(() => settled.abort())\n // Awaited below; this only keeps a poll that fails while onCode runs from counting as unhandled.\n poll.catch(() => {})\n try {\n await opts.onCode(start, settled.signal)\n } catch (e) {\n stopPoll.abort()\n // Approved just before onCode failed: that session is never stored, so end it server-side.\n const late = await poll.catch(() => null)\n if (late) await opts.oidc.revoke(late.refreshToken).catch(() => {})\n throw e\n }\n const t = await poll\n const at = opts.now()\n const write = async () => {\n // Refresh first: a crash between the two writes then leaves a usable session.\n await opts.store.setRefresh({ rt: t.refreshToken, sub: t.sub, scope: t.scope, obtainedAt: at.toISOString() })\n await opts.store.setAccess({ at: t.accessToken, expiresAt: new Date(at.getTime() + t.expiresIn * 1000).toISOString() })\n }\n try {\n if (opts.withLock && opts.lockName) await opts.withLock(opts.lockName, write)\n else await write()\n } catch (e) {\n // The new session cannot be kept: end it server-side and drop any half-written entry.\n // Both best-effort; the original (keychain) error is what the user needs to see.\n await opts.oidc.revoke(t.refreshToken).catch(() => {})\n await opts.store.clear().catch(() => {})\n throw e\n }\n return t\n}\n","import type { Keychain } from \"../../platform/keychain.js\"\n\nexport type StoredRefresh = { rt: string; sub: string; scope: string; obtainedAt: string }\nexport type StoredAccess = { at: string; expiresAt: string }\n\nexport class TokenStore {\n constructor(private readonly kc: Keychain, private readonly hash: string) {}\n\n private async read<T>(suffix: string): Promise<T | null> {\n const raw = await this.kc.get(`${this.hash}:${suffix}`)\n if (raw === null) return null\n try { return JSON.parse(raw) as T } catch { return null }\n }\n\n getRefresh() { return this.read<StoredRefresh>(\"refresh\") }\n getAccess() { return this.read<StoredAccess>(\"access\") }\n setRefresh(v: StoredRefresh) { return this.kc.set(`${this.hash}:refresh`, JSON.stringify(v)) }\n setAccess(v: StoredAccess) { return this.kc.set(`${this.hash}:access`, JSON.stringify(v)) }\n async clear() {\n await this.kc.delete(`${this.hash}:access`)\n await this.kc.delete(`${this.hash}:refresh`)\n }\n}\n","import { createHash } from \"node:crypto\"\nimport { QoreError } from \"./errors.js\"\n\nexport type PortalRef = { apiOrigin: string; pinnedIssuer: string | null; builtin: \"prod\" | \"staging\" | null }\n\nexport const BUILTIN_PORTALS = {\n prod: {\n apiOrigin: \"https://api.quatronic.app\",\n pinnedIssuer: \"https://auth.quatronic.app/realms/platform-prod\",\n },\n staging: {\n apiOrigin: \"https://p01--portal-api-staging--hcywmtb2vksv.code.run\",\n pinnedIssuer: \"https://auth-staging.quatronic.app/realms/platform-staging\",\n },\n} as const satisfies Record<string, { apiOrigin: string; pinnedIssuer: string | null }>\n\nfunction builtinFor(origin: string): PortalRef | null {\n for (const [name, p] of Object.entries(BUILTIN_PORTALS)) {\n if (p.apiOrigin === origin) return { ...p, builtin: name as \"prod\" | \"staging\" }\n }\n return null\n}\n\nfunction toOrigin(raw: string): string {\n let url: URL\n try { url = new URL(raw) } catch {\n throw new QoreError(\"QORE_CONTEXT_INVALID\", `Not a portal name or URL: ${raw}`, {\n hint: \"Use --portal prod, --portal staging or --portal https://…\",\n })\n }\n const loopback = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\"\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) {\n throw new QoreError(\"QORE_CONTEXT_INVALID\", \"A portal URL must use https (http only for localhost)\")\n }\n return url.origin.toLowerCase()\n}\n\nexport function resolvePortal(arg: string | undefined, defaultProfile: string | undefined): PortalRef {\n const chosen = arg ?? defaultProfile\n if (chosen === undefined || chosen === \"prod\") return { ...BUILTIN_PORTALS.prod, builtin: \"prod\" }\n if (chosen === \"staging\") return { ...BUILTIN_PORTALS.staging, builtin: \"staging\" }\n const origin = toOrigin(chosen)\n return builtinFor(origin) ?? { apiOrigin: origin, pinnedIssuer: null, builtin: null }\n}\n\nexport function profileHash(apiOrigin: string, issuer: string): string {\n return createHash(\"sha256\").update(`${apiOrigin}|${issuer}`).digest(\"hex\").slice(0, 16)\n}\n","import { QoreError } from \"../errors.js\"\nimport { fetchError, problemToError, type Fetch } from \"./http.js\"\n\nexport class QoreApiClient {\n constructor(private readonly o: {\n apiOrigin: string; fetch: Fetch; token: (force: boolean) => Promise<string>\n cliVersion: string; command: string; platform: string; onRequest?: (line: string) => void\n }) {}\n\n private async once(path: string, force: boolean): Promise<Response> {\n const token = await this.o.token(force)\n let res: Response\n try {\n res = await this.o.fetch(`${this.o.apiOrigin}${path}`, {\n headers: {\n authorization: `Bearer ${token}`,\n accept: \"application/json\",\n \"qore-cli-version\": this.o.cliVersion,\n \"qore-command\": this.o.command,\n \"user-agent\": `qore/${this.o.cliVersion} (${this.o.platform})`,\n },\n })\n } catch (e) { throw fetchError(e, new URL(this.o.apiOrigin).host) }\n this.o.onRequest?.(`GET ${path} → ${res.status}${res.headers.get(\"x-request-id\") ? ` (${res.headers.get(\"x-request-id\")})` : \"\"}`)\n return res\n }\n\n async get<T>(path: string): Promise<T> {\n let res = await this.once(path, false)\n if (res.status === 401) {\n res = await this.once(path, true)\n if (res.status === 401) {\n throw new QoreError(\"QORE_SESSION_EXPIRED\", \"The portal no longer accepts your session\", {\n hint: \"Run `qore login`.\", status: 401, requestId: res.headers.get(\"x-request-id\") ?? undefined,\n })\n }\n }\n if (!res.ok) throw await problemToError(res)\n return (await res.json()) as T\n }\n}\n","import { QoreError } from \"../errors.js\"\nimport type { WithLock } from \"../../platform/lock.js\"\nimport type { Oidc, TokenSet } from \"./oidc.js\"\nimport type { TokenStore } from \"./tokenStore.js\"\n\nconst SKEW_MS = 60_000\n\nexport class RefreshCoordinator {\n constructor(private readonly o: {\n store: TokenStore; oidc: () => Promise<Oidc>; withLock: WithLock; lockName: string; now: () => Date\n }) {}\n\n private fresh(expiresAt: string): boolean {\n return new Date(expiresAt).getTime() - this.o.now().getTime() > SKEW_MS\n }\n\n private async rotate(scope?: string): Promise<TokenSet> {\n let stored = await this.o.store.getRefresh()\n if (!stored) throw new QoreError(\"QORE_NOT_LOGGED_IN\", \"Not logged in\", { hint: \"Run `qore login`.\" })\n let t: TokenSet\n for (let attempt = 0; ; attempt++) {\n try {\n t = await (await this.o.oidc()).refresh(stored.rt, scope)\n break\n } catch (e) {\n if (!(e instanceof QoreError && e.code === \"QORE_SESSION_EXPIRED\")) throw e\n // Only the RT we presented was rejected. Another process may have rotated it\n // meanwhile (a stolen stale lock, a second config dir, a lost response): then the\n // stored RT is newer, so retry once with it instead of logging the user out.\n const now = await this.o.store.getRefresh()\n if (now && now.rt !== stored.rt) {\n if (attempt === 0) { stored = now; continue }\n throw e\n }\n await this.o.store.clear()\n throw e\n }\n }\n // Store the scope the token response reports: after a downscoped refresh the rotated RT\n // may carry only the narrowed scope, so never record the old full scope for it. An empty\n // response scope means \"as requested\" (RFC 6749 §5.1).\n await this.o.store.setRefresh({ rt: t.refreshToken, sub: t.sub, scope: t.scope || (scope ?? stored.scope), obtainedAt: this.o.now().toISOString() })\n return t\n }\n\n async accessToken(opts: { force?: boolean } = {}): Promise<string> {\n const seen = await this.o.store.getAccess()\n if (!opts.force && seen && this.fresh(seen.expiresAt)) return seen.at\n return this.o.withLock(this.o.lockName, async () => {\n const again = await this.o.store.getAccess()\n if (again && again.at !== seen?.at && this.fresh(again.expiresAt)) return again.at\n const t = await this.rotate()\n await this.o.store.setAccess({ at: t.accessToken, expiresAt: new Date(this.o.now().getTime() + t.expiresIn * 1000).toISOString() })\n return t.accessToken\n })\n }\n\n /** A token carrying only `scopes`, held in memory by the caller (qore mcp). */\n async downscoped(scopes: string[]): Promise<string> {\n return this.o.withLock(this.o.lockName, async () => (await this.rotate(scopes.join(\" \"))).accessToken)\n }\n}\n","import { QoreApiClient } from \"./api/client.js\"\nimport { RefreshCoordinator } from \"./auth/refresh.js\"\nimport { TokenStore } from \"./auth/tokenStore.js\"\nimport type { ProfileRecord } from \"./config.js\"\nimport type { Deps } from \"./deps.js\"\nimport { QoreError } from \"./errors.js\"\nimport { profileHash, type PortalRef } from \"./profiles.js\"\n\nexport function loginHint(portal: PortalRef): string {\n return portal.builtin === \"prod\" ? \"Run `qore login`.\" : `Run \\`qore login --portal ${portal.builtin ?? portal.apiOrigin}\\`.`\n}\n\nexport async function openSession(deps: Deps, portal: PortalRef, command: string, onRequest?: (l: string) => void) {\n const profile: ProfileRecord | undefined = (await deps.config.read()).profiles[portal.apiOrigin]\n if (!profile) throw new QoreError(\"QORE_NOT_LOGGED_IN\", `Not logged in to ${portal.apiOrigin}`, { hint: loginHint(portal) })\n const hash = profileHash(profile.apiOrigin, profile.issuer)\n const tokens = new TokenStore(deps.keychain, hash)\n if (!(await tokens.getRefresh())) throw new QoreError(\"QORE_NOT_LOGGED_IN\", `Not logged in to ${portal.apiOrigin}`, { hint: loginHint(portal) })\n const refresh = new RefreshCoordinator({ store: tokens, oidc: () => deps.oidcFor(profile.issuer), withLock: deps.withLock, lockName: hash, now: deps.now })\n const api = new QoreApiClient({\n apiOrigin: profile.apiOrigin, fetch: deps.fetch, token: (force) => refresh.accessToken({ force }),\n cliVersion: deps.version, command, platform: `${deps.platform} ${process.arch}; node ${process.versions.node}`, onRequest,\n })\n return { profile, api, tokens, refresh }\n}\n","import type { Command } from \"commander\"\nimport { fetchMeta, negotiate } from \"../../core/api/meta.js\"\nimport type { CliMe, CliMeta } from \"../../core/api/types.js\"\nimport { deviceLogin } from \"../../core/auth/login.js\"\nimport { TokenStore } from \"../../core/auth/tokenStore.js\"\nimport { profileHash, resolvePortal } from \"../../core/profiles.js\"\nimport { openSession } from \"../../core/session.js\"\nimport { requestLog, type CommandContext } from \"../program.js\"\nimport { renderJson } from \"../render.js\"\n\nexport function registerLogin(program: Command, ctx: CommandContext): void {\n program.command(\"login\").description(\"Log in with your Qore account\")\n .option(\"--no-browser\", \"only print the URL\")\n .action(async (cmd: { browser: boolean }) => {\n const { deps, io, signal } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const portal = resolvePortal(g.portal, cfg.defaultProfile)\n const meta: CliMeta = await fetchMeta(deps.fetch, portal.apiOrigin)\n const known = cfg.profiles[portal.apiOrigin]?.issuer\n const pinned = { ...portal, pinnedIssuer: portal.pinnedIssuer ?? known ?? null }\n if (!pinned.pinnedIssuer && portal.builtin === null) {\n io.err(`! Logging in to ${portal.apiOrigin}, identity provider ${meta.auth.issuer}`)\n }\n negotiate(meta, pinned, deps.version)\n const issuer = pinned.pinnedIssuer ?? meta.auth.issuer\n const hash = profileHash(portal.apiOrigin, issuer)\n const store = new TokenStore(deps.keychain, hash)\n const t = await deviceLogin({\n oidc: await deps.oidcFor(issuer), store, now: deps.now, signal,\n withLock: deps.withLock, lockName: hash,\n onCode: async (s, settled) => {\n const url = s.verificationUriComplete ?? s.verificationUri\n io.err(`! First copy your one-time code: ${s.userCode}`)\n if (io.interactive && cmd.browser) {\n try {\n await io.waitForEnter(` Press Enter to open ${url} (or open it yourself)`, AbortSignal.any([signal, settled]))\n } catch (e) {\n // Approved (or denied) in a browser the user opened themselves: nothing left to open.\n if (settled.aborted && !signal.aborted) return\n throw e\n }\n if (settled.aborted) return\n if (!(await io.openUrl(url))) io.err(` Open ${url} in a browser`)\n } else {\n io.err(` Open ${url} in a browser`)\n }\n },\n })\n await deps.config.update((c) => {\n c.profiles[portal.apiOrigin] = { ...c.profiles[portal.apiOrigin], apiOrigin: portal.apiOrigin, issuer,\n sub: t.sub, email: t.email, meta: { fetchedAt: deps.now().toISOString(), doc: meta } }\n if (g.portal || !c.defaultProfile) c.defaultProfile = portal.apiOrigin\n })\n const { api } = await openSession(deps, { ...portal, pinnedIssuer: issuer }, \"login\", requestLog(ctx))\n const me = await api.get<CliMe>(\"/api/cli/v1/me\")\n const prev = cfg.profiles[portal.apiOrigin]\n let active: { id: string; slug: string } | undefined =\n prev?.sub === t.sub && prev.activeTenant && me.tenants.some((x) => x.id === prev.activeTenant!.id)\n ? prev.activeTenant\n : undefined\n if (active) {\n // A previous session's active tenant is still valid for this sub: keep it, no re-selection.\n } else if (me.tenants.length === 0) {\n io.err(\"! Your account is not a developer in any organisation. Ask an admin to invite you as developer.\")\n } else if (me.tenants.length === 1) {\n active = { id: me.tenants[0]!.id, slug: me.tenants[0]!.slug }\n io.err(`✓ Using tenant ${me.tenants[0]!.name}`)\n } else if (io.interactive) {\n active = await io.select(\"Select a tenant\", me.tenants.map((x) => ({ name: `${x.name} ${x.role}`, value: { id: x.id, slug: x.slug } })))\n } else {\n io.err(`! You belong to ${me.tenants.length} tenants; choose one with \\`qore tenant use <slug>\\``)\n }\n await deps.config.update((c) => { c.profiles[portal.apiOrigin]!.activeTenant = active })\n const label = portal.builtin ?? portal.apiOrigin\n if (g.json) renderJson(io, { portal: label, email: me.email, activeTenant: active ?? null })\n else io.out(`✓ Logged in as ${me.email} (${label})`)\n })\n}\n","import type { Command } from \"commander\"\nimport { TokenStore } from \"../../core/auth/tokenStore.js\"\nimport { QoreError } from \"../../core/errors.js\"\nimport { profileHash, resolvePortal } from \"../../core/profiles.js\"\nimport type { CommandContext } from \"../program.js\"\nimport { renderJson } from \"../render.js\"\n\nexport function registerLogout(program: Command, ctx: CommandContext): void {\n program.command(\"logout\").description(\"End the CLI session\")\n .option(\"--all\", \"log out of every portal\")\n .action(async (cmd: { all?: boolean }) => {\n const { deps, io } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const targets = cmd.all ? Object.values(cfg.profiles)\n : [cfg.profiles[resolvePortal(g.portal, cfg.defaultProfile).apiOrigin]].filter((p) => p !== undefined)\n const done: string[] = []\n for (const p of targets) {\n const hash = profileHash(p.apiOrigin, p.issuer)\n const store = new TokenStore(deps.keychain, hash)\n const host = new URL(p.issuer).host\n // Read, revoke and clear under one lock, so a concurrent refresh cannot rotate the\n // RT between our read and the revoke (we would revoke a stale one) or resurrect it.\n await deps.withLock(hash, async () => {\n const rt = await store.getRefresh()\n if (rt) {\n try { await (await deps.oidcFor(p.issuer)).revoke(rt.rt) }\n catch (e) {\n const network = e instanceof QoreError && e.details?.reason !== undefined\n io.err(network\n ? `! Could not reach ${host}; the server session may persist until it expires.`\n : `! Could not revoke the session at ${host} (${e instanceof Error ? e.message : String(e)}); the server session may persist until it expires.`)\n }\n }\n await store.clear()\n })\n done.push(p.apiOrigin)\n }\n if (g.json) renderJson(io, { loggedOut: done })\n else if (done.length === 0) io.out(\"Not logged in\")\n else io.out(`✓ Logged out of ${done.map((o) => resolvePortal(o, undefined).builtin ?? o).join(\", \")}`)\n })\n}\n","import type { Command } from \"commander\"\nimport type { CliMe } from \"../../core/api/types.js\"\nimport { QoreError } from \"../../core/errors.js\"\nimport { resolvePortal } from \"../../core/profiles.js\"\nimport { openSession } from \"../../core/session.js\"\nimport { requestLog, type CommandContext } from \"../program.js\"\nimport { renderJson } from \"../render.js\"\n\nexport function registerTenant(program: Command, ctx: CommandContext): void {\n const tenant = program.command(\"tenant\").description(\"Manage the active tenant\")\n\n tenant.command(\"list\").description(\"List tenants you have access to\")\n .action(async () => {\n const { deps, io } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const portal = resolvePortal(g.portal, cfg.defaultProfile)\n const { profile, api } = await openSession(deps, portal, \"tenant list\", requestLog(ctx))\n const me = await api.get<CliMe>(\"/api/cli/v1/me\")\n const activeId = profile.activeTenant?.id\n if (g.json) {\n renderJson(io, { tenants: me.tenants.map((t) => ({ ...t, active: t.id === activeId })) })\n return\n }\n for (const t of me.tenants) {\n const mark = t.id === activeId ? \"*\" : \" \"\n io.out(`${mark} ${t.name} ${t.role}`)\n }\n })\n\n tenant.command(\"use\").description(\"Set the active tenant\").argument(\"[slug]\", \"tenant slug\")\n .action(async (slug: string | undefined) => {\n const { deps, io } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const portal = resolvePortal(g.portal, cfg.defaultProfile)\n const { api } = await openSession(deps, portal, \"tenant use\", requestLog(ctx))\n const me = await api.get<CliMe>(\"/api/cli/v1/me\")\n const candidates = me.tenants.map((t) => t.slug)\n let chosen: { id: string; slug: string }\n if (slug) {\n const found = me.tenants.find((t) => t.slug === slug)\n if (!found) throw new QoreError(\"QORE_RESOURCE_NOT_FOUND\", `No tenant \"${slug}\" for this account`, { candidates })\n chosen = { id: found.id, slug: found.slug }\n } else if (io.interactive) {\n chosen = await io.select(\"Select a tenant\", me.tenants.map((t) => ({ name: `${t.name} ${t.role}`, value: { id: t.id, slug: t.slug } })))\n } else {\n throw new QoreError(\"QORE_CONTEXT_REQUIRED\", \"Which tenant? Pass a slug or run interactively.\", { candidates })\n }\n await deps.config.update((c) => { c.profiles[portal.apiOrigin]!.activeTenant = chosen })\n if (g.json) renderJson(io, { activeTenant: chosen })\n else io.out(`✓ Using tenant ${chosen.slug}`)\n })\n}\n","import type { Command } from \"commander\"\nimport { fetchMeta } from \"../../core/api/meta.js\"\nimport { CancelledError } from \"../../core/errors.js\"\nimport { resolvePortal } from \"../../core/profiles.js\"\nimport type { CommandContext } from \"../program.js\"\nimport { renderJson } from \"../render.js\"\n\nexport function registerVersion(program: Command, ctx: CommandContext): void {\n program.command(\"version\").description(\"Show the CLI and portal version\")\n .action(async () => {\n const { deps, io } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const portal = resolvePortal(g.portal, cfg.defaultProfile)\n let portalInfo: { apiVersions: string[]; minCliVersion: string; latestCliVersion: string; capabilities: string[] } | null = null\n try {\n const meta = await fetchMeta(deps.fetch, portal.apiOrigin)\n portalInfo = { apiVersions: meta.apiVersions, minCliVersion: meta.minCliVersion, latestCliVersion: meta.latestCliVersion, capabilities: meta.capabilities }\n } catch (e) {\n // A cancel is not \"unreachable\": Ctrl+C still exits 130.\n if (e instanceof CancelledError) throw e\n /* portal unreachable; report null below */\n }\n if (g.json) {\n renderJson(io, { cli: deps.version, portal: portalInfo })\n return\n }\n io.out(`qore ${deps.version}`)\n const label = portal.builtin ?? portal.apiOrigin\n if (portalInfo) {\n io.out(`portal ${label}: api ${portalInfo.apiVersions.join(\",\")}, min ${portalInfo.minCliVersion}, latest ${portalInfo.latestCliVersion}`)\n } else {\n io.out(`portal ${label}: unreachable`)\n }\n })\n}\n","import type { Command } from \"commander\"\nimport type { CliMe } from \"../../core/api/types.js\"\nimport { resolvePortal } from \"../../core/profiles.js\"\nimport { openSession } from \"../../core/session.js\"\nimport { requestLog, type CommandContext } from \"../program.js\"\nimport { renderJson } from \"../render.js\"\n\nexport function registerWhoami(program: Command, ctx: CommandContext): void {\n program.command(\"whoami\").description(\"Show who you're logged in as\")\n .action(async () => {\n const { deps, io } = ctx\n const g = ctx.opts()\n const cfg = await deps.config.read()\n const portal = resolvePortal(g.portal, cfg.defaultProfile)\n const { profile, api } = await openSession(deps, portal, \"whoami\", requestLog(ctx))\n const me = await api.get<CliMe>(\"/api/cli/v1/me\")\n const activeTenant = profile.activeTenant\n if (activeTenant && !me.tenants.some((t) => t.id === activeTenant.id)) {\n io.err(`! You no longer have developer access to ${activeTenant.slug}`)\n }\n const label = portal.builtin ?? portal.apiOrigin\n if (g.json) {\n renderJson(io, { portal: label, activeTenant: activeTenant ?? null, me })\n return\n }\n io.out(`${me.email} (${label})`)\n for (const t of me.tenants) {\n const mark = activeTenant?.id === t.id ? \"*\" : \" \"\n io.out(`${mark} ${t.name} ${t.role}`)\n for (const a of t.apps) {\n io.out(` ${a.slug} ${a.access}`)\n for (const m of a.modules) {\n io.out(` ${m.slug} ${m.type} ${m.access}`)\n }\n }\n }\n })\n}\n","import type { Register } from \"../program.js\"\nimport { registerLogin } from \"./login.js\"\nimport { registerLogout } from \"./logout.js\"\nimport { registerTenant } from \"./tenant.js\"\nimport { registerVersion } from \"./version.js\"\nimport { registerWhoami } from \"./whoami.js\"\n\nexport const COMMANDS: Register[] = [registerLogin, registerLogout, registerWhoami, registerTenant, registerVersion]\n","import { compareVersions } from \"../core/api/meta.js\"\nimport type { Deps } from \"../core/deps.js\"\nimport type { Io } from \"./io.js\"\n\nconst REGISTRY_URL = \"https://registry.npmjs.org/@quatronic%2Fqore/latest\"\nconst DAY_MS = 24 * 60 * 60 * 1000\nconst DEFAULT_TIMEOUT_MS = 1500\n\nexport async function maybeNotifyUpdate(deps: Deps, io: Io, o: { json: boolean }, timeoutMs = DEFAULT_TIMEOUT_MS): Promise<void> {\n if (o.json || deps.env.CI || deps.env.QORE_NO_UPDATE_CHECK === \"1\" || !io.interactive) return\n const cfg = await deps.config.read()\n const last = cfg.updateCheck?.lastCheckedAt\n if (last && deps.now().getTime() - new Date(last).getTime() < DAY_MS) return\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n let latest: string | undefined\n try {\n const res = await deps.fetch(REGISTRY_URL, { signal: controller.signal })\n if (res.ok) latest = ((await res.json()) as { version?: string }).version\n } catch { /* silent: an update check never affects the run */ }\n finally { clearTimeout(timer) }\n try {\n // Recorded after a failed, non-OK or timed-out check too, so an offline user does not\n // pay the timeout on every command; the last known latest version is kept then.\n await deps.config.update((c) => {\n c.updateCheck = { lastCheckedAt: deps.now().toISOString(), latest: latest ?? c.updateCheck?.latest ?? deps.version }\n })\n } catch { return }\n if (latest && compareVersions(latest, deps.version) > 0) {\n io.err(`A new qore is available: ${deps.version} → ${latest} npm i -g @quatronic/qore`)\n }\n}\n","import { mkdir, readFile, rename, writeFile, chmod } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { randomBytes } from \"node:crypto\"\nimport { QoreError } from \"./errors.js\"\n\nexport type ProfileRecord = {\n apiOrigin: string\n issuer: string\n sub?: string\n email?: string\n activeTenant?: { id: string; slug: string }\n meta?: { fetchedAt: string; doc: unknown }\n}\n\nexport type QoreConfig = {\n schemaVersion: 1\n defaultProfile?: string\n profiles: Record<string, ProfileRecord>\n updateCheck?: { lastCheckedAt: string; latest: string }\n}\n\nconst empty = (): QoreConfig => ({ schemaVersion: 1, profiles: {} })\n\nexport class ConfigStore {\n constructor(readonly dir: string) {}\n\n private get file() { return join(this.dir, \"config.json\") }\n\n async read(): Promise<QoreConfig> {\n let raw: string\n try {\n raw = await readFile(this.file, \"utf8\")\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"ENOENT\") return empty()\n throw e\n }\n try {\n const parsed = JSON.parse(raw) as QoreConfig\n if (parsed.schemaVersion !== 1 || typeof parsed.profiles !== \"object\") throw new Error(\"shape\")\n return parsed\n } catch (cause) {\n throw new QoreError(\"QORE_CONTEXT_INVALID\", `Qore config is malformed: ${this.file}`, {\n hint: \"Fix or delete the file, then run `qore login` again\", cause,\n })\n }\n }\n\n async update(fn: (c: QoreConfig) => QoreConfig | void): Promise<QoreConfig> {\n const current = await this.read()\n const next = fn(current) ?? current\n await mkdir(this.dir, { recursive: true, mode: 0o700 })\n const tmp = join(this.dir, `.config.${randomBytes(6).toString(\"hex\")}.tmp`)\n await writeFile(tmp, JSON.stringify(next, null, 2) + \"\\n\", { mode: 0o600 })\n await chmod(tmp, 0o600)\n await rename(tmp, this.file)\n return next\n }\n}\n","import { Entry } from \"@napi-rs/keyring\"\nimport { QoreError } from \"../core/errors.js\"\n\nexport interface Keychain {\n get(account: string): Promise<string | null>\n set(account: string, value: string): Promise<void>\n delete(account: string): Promise<void>\n}\n\nconst SERVICE = \"qore\"\nconst HINTS: Partial<Record<NodeJS.Platform, string>> = {\n linux: \"Install and unlock a Secret Service provider (gnome-keyring or KWallet); headless machines and containers have none.\",\n darwin: \"Unlock your login keychain in Keychain Access.\",\n win32: \"Windows Credential Manager must be available for your user.\",\n}\n\nexport function classifyKeychainError(e: unknown, platform: NodeJS.Platform): QoreError {\n const msg = e instanceof Error ? e.message : String(e)\n // keyring-rs Error::TooLong (\"… is longer than the platform limit of N chars\"): Windows\n // Credential Manager caps a credential blob (R18). Still UNAVAILABLE, but say what it is.\n if (/TooLong|longer than the platform limit/i.test(msg)) {\n return new QoreError(\"QORE_KEYCHAIN_UNAVAILABLE\", \"The session token is too large for the OS keychain\", {\n hint: platform === \"win32\"\n ? \"The token exceeds the Windows Credential Manager size limit. Report this to the Qore team.\"\n : \"The token exceeds the keychain's size limit. Report this to the Qore team.\",\n cause: e,\n })\n }\n if (/cancel|denied|errSecAuthFailed|user interaction/i.test(msg)) {\n return new QoreError(\"QORE_KEYCHAIN_DENIED\", \"Access to the OS keychain was denied\", {\n hint: \"Allow qore to use the keychain when your OS asks, then retry.\", cause: e,\n })\n }\n return new QoreError(\"QORE_KEYCHAIN_UNAVAILABLE\", \"No usable OS keychain\", {\n hint: HINTS[platform] ?? \"qore stores tokens only in the OS keychain.\", cause: e,\n })\n}\n\nexport class OsKeychain implements Keychain {\n constructor(private readonly platform: NodeJS.Platform = process.platform) {}\n\n private wrap<T>(fn: () => T): Promise<T> {\n try { return Promise.resolve(fn()) } catch (e) { return Promise.reject(classifyKeychainError(e, this.platform)) }\n }\n\n get(account: string) { return this.wrap(() => new Entry(SERVICE, account).getPassword() ?? null) }\n set(account: string, value: string) { return this.wrap(() => { new Entry(SERVICE, account).setPassword(value) }) }\n delete(account: string) {\n // deletePassword() returns false (rather than throwing) when there is no entry.\n return this.wrap(() => { new Entry(SERVICE, account).deletePassword() })\n }\n}\n","import { mkdir, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport lockfile from \"proper-lockfile\"\nimport { QoreError } from \"../core/errors.js\"\n\nexport type WithLock = <T>(name: string, fn: () => Promise<T>) => Promise<T>\n\nexport function fileLock(dir: string): WithLock {\n return async (name, fn) => {\n const locks = join(dir, \"locks\")\n await mkdir(locks, { recursive: true, mode: 0o700 })\n const target = join(locks, `${name}.lock`)\n await writeFile(target, \"\", { flag: \"a\" })\n let release: () => Promise<void>\n // proper-lockfile's default onCompromised throws from a timer (an uncaught crash). A\n // compromised lock (mtime update failed, or another process took it as stale) is only\n // recorded: the keychain writes under it are idempotent, and refresh re-reads the RT.\n let compromised: Error | undefined\n try {\n release = await lockfile.lock(target, {\n stale: 30_000,\n retries: { retries: 30, minTimeout: 100, maxTimeout: 1000, randomize: true },\n onCompromised: (err) => { compromised = err },\n })\n } catch (cause) {\n throw new QoreError(\"QORE_AUTH_BUSY\", \"Another qore process is refreshing the session\", { hint: \"Retry in a moment.\", cause })\n }\n try { return await fn() } finally {\n // After a compromise release() rejects (ERELEASED); that must not replace fn's outcome.\n await release().catch((e: unknown) => { if (!compromised) throw e })\n }\n }\n}\n","import { posix, win32 } from \"node:path\"\n\nexport function configDir(env: NodeJS.ProcessEnv, platform: NodeJS.Platform, home: string): string {\n if (platform === \"win32\") return win32.join(env.APPDATA ?? win32.join(home, \"AppData\", \"Roaming\"), \"qore\")\n // posix.join, not the host's join: the result is for the target platform, whatever the host\n // (tests run on Windows CI too).\n if (platform === \"darwin\") return posix.join(home, \"Library\", \"Application Support\", \"qore\")\n // XDG Base Directory spec: a relative $XDG_CONFIG_HOME is invalid and must be ignored.\n const xdg = env.XDG_CONFIG_HOME && posix.isAbsolute(env.XDG_CONFIG_HOME) ? env.XDG_CONFIG_HOME : undefined\n return posix.join(xdg ?? posix.join(home, \".config\"), \"qore\")\n}\n","declare const __QORE_VERSION__: string | undefined\n// tsup replaces __QORE_VERSION__ at build time; tests run from source and see \"0.0.0-dev\".\nexport const VERSION: string = typeof __QORE_VERSION__ === \"string\" ? __QORE_VERSION__ : \"0.0.0-dev\"\n"],"mappings":"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","names":["fetch","pc","io","json","argv","deps","io","json","pc","fetch","deps","deps","io","deps","io","deps","io","deps","io","deps","io","deps","io","dir","mkdir","writeFile","join","dir","join","mkdir","writeFile"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quatronic/qore",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Qore developer CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"qore": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"schema",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22"
|
|
16
|
+
},
|
|
17
|
+
"packageManager": "pnpm@11.13.1",
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/Quatronic-IT/qore-cli.git"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"test:e2e": "pnpm build && vitest run --config vitest.e2e.config.ts",
|
|
31
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"lint": "eslint src tests",
|
|
34
|
+
"prepublishOnly": "pnpm build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@inquirer/prompts": "^7.8.0",
|
|
38
|
+
"@napi-rs/keyring": "^1.1.0",
|
|
39
|
+
"commander": "^14.0.0",
|
|
40
|
+
"open": "^10.2.0",
|
|
41
|
+
"openid-client": "^6.6.0",
|
|
42
|
+
"picocolors": "^1.1.1",
|
|
43
|
+
"proper-lockfile": "^4.1.2",
|
|
44
|
+
"undici": "^7.29.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@eslint/js": "^9.33.0",
|
|
48
|
+
"@types/node": "^22.17.0",
|
|
49
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
50
|
+
"eslint": "^9.33.0",
|
|
51
|
+
"execa": "^9.6.0",
|
|
52
|
+
"lefthook": "^1.12.0",
|
|
53
|
+
"tsup": "^8.5.0",
|
|
54
|
+
"typescript": "^5.9.2",
|
|
55
|
+
"typescript-eslint": "^8.40.0",
|
|
56
|
+
"vitest": "^3.2.4"
|
|
57
|
+
}
|
|
58
|
+
}
|