@glassanalytics/cli 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -296,18 +296,18 @@ function detectPackageManager() {
296
296
  function snippetFor(framework, project) {
297
297
  if (framework === "node") {
298
298
  return {
299
- pkg: "@glass/node",
299
+ pkg: "@glassanalytics/node",
300
300
  file: "glass.ts",
301
- code: `import { GlassNode } from '@glass/node';
301
+ code: `import { GlassNode } from '@glassanalytics/node';
302
302
 
303
303
  export const glass = new GlassNode({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });
304
304
  `
305
305
  };
306
306
  }
307
307
  return {
308
- pkg: "@glass/browser",
308
+ pkg: "@glassanalytics/browser",
309
309
  file: "glass.ts",
310
- code: `import glass from '@glass/browser';
310
+ code: `import glass from '@glassanalytics/browser';
311
311
 
312
312
  glass.init({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });
313
313
 
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands.ts","../src/output.ts","../src/api.ts","../src/config.ts"],"sourcesContent":["import { parseArgs } from 'node:util';\nimport * as cmd from './commands.js';\nimport { ExitCode, fail, setFormat, setJsonMode } from './output.js';\n\n/**\n * `glass` — the agent-friendly terminal surface (`CLI.md`). Setup in one command\n * (`glass init`, no signup), then the same typed query primitives the dashboard\n * uses. `--json` + stable exit codes make it scriptable by humans and agents.\n */\n\nconst HELP = `glass <command> [options]\n\nSetup\n init [--force] Provision a project with no signup (writes glass.json)\n install [--framework F] [--no-install] Install + wire the SDK\n status Show whether events are being received\n doctor Diagnose setup problems\n claim Get the claim URL to keep your data\n login [--token T] Store a Clerk session for human-scoped access\n logout Clear the stored session\n whoami Show the current principal (GET /v1/me)\n link --project ID Point glass.json at another project you can access\n\nQuery (all accept --last 7d, --json, --confirm, --max-scan <MB>)\n trend --event E [--bucket day] [--breakdown B] [--aggregate count|unique_users|sum]\n funnel --steps a,b,c | --id <def> [--window 1d]\n retention --id <def> --return E [--periods 8]\n segment --group-by a,b [--event E]\n errors\n replays [--limit 50]\n query --query '<json>' | -f <file> | (piped stdin)\n\nManage\n define --file spec.json | --kind funnel --steps a,b | --list\n tokens list | create [--budget-r2sql 1GB/day] | revoke <id>\n link <project-id>\n\nGlobal: --json --csv --ndjson --api-host --ingest-host\n --max-scan <500MB|1GB> --yes/--no-input (auth: --token | GLASS_TOKEN)\nEnv: GLASS_TOKEN GLASS_PROJECT GLASS_INGEST_KEY GLASS_API_HOST`;\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n const command = argv[0];\n const sub = argv[1] && !argv[1].startsWith('-') ? argv[1] : undefined;\n\n const { values, positionals } = parseArgs({\n args: argv.slice(1),\n allowPositionals: true,\n options: {\n json: { type: 'boolean' },\n csv: { type: 'boolean' },\n ndjson: { type: 'boolean' },\n confirm: { type: 'boolean' },\n reissue: { type: 'boolean' },\n force: { type: 'boolean' },\n 'no-install': { type: 'boolean' },\n yes: { type: 'boolean' },\n 'no-input': { type: 'boolean' },\n list: { type: 'boolean' },\n 'max-scan': { type: 'string' },\n last: { type: 'string' },\n event: { type: 'string' },\n bucket: { type: 'string' },\n breakdown: { type: 'string' },\n aggregate: { type: 'string' },\n steps: { type: 'string' },\n window: { type: 'string' },\n scope: { type: 'string' },\n kind: { type: 'string' },\n id: { type: 'string' },\n return: { type: 'string' },\n periods: { type: 'string' },\n 'group-by': { type: 'string' },\n group: { type: 'string' },\n status: { type: 'string' },\n limit: { type: 'string' },\n user: { type: 'string' },\n query: { type: 'string' },\n file: { type: 'string', short: 'f' },\n name: { type: 'string' },\n role: { type: 'string' },\n framework: { type: 'string' },\n project: { type: 'string' },\n 'budget-r2sql': { type: 'string' },\n token: { type: 'string' },\n 'api-host': { type: 'string' },\n 'ingest-host': { type: 'string' },\n },\n });\n\n const flags = values as Record<string, string | boolean>;\n if (flags.json) setJsonMode(true);\n else if (flags.ndjson) setFormat('ndjson');\n else if (flags.csv) setFormat('csv');\n\n switch (command) {\n case 'init':\n return void (await cmd.init(flags));\n case 'install':\n return void cmd.install(flags);\n case 'status':\n return void (await cmd.status(flags));\n case 'doctor':\n return void (await cmd.doctor(flags));\n case 'claim':\n return void (await cmd.claim(flags));\n case 'login':\n return void (await cmd.login(flags));\n case 'logout':\n return void cmd.logout(flags);\n case 'whoami':\n return void (await cmd.whoami(flags));\n case 'link':\n return void (await cmd.link(flags, positionals));\n case 'trend':\n return void (await cmd.trend(flags));\n case 'funnel':\n return void (await cmd.funnel(flags));\n case 'retention':\n return void (await cmd.retention(flags));\n case 'segment':\n return void (await cmd.segment(flags));\n case 'errors':\n return void (await cmd.errors(flags));\n case 'replays':\n return void (await cmd.replays(flags));\n case 'query':\n return void (await cmd.query(flags));\n case 'define':\n return void (await cmd.define(flags));\n case 'tokens':\n // positionals[0] is the sub-action; pass the remainder (e.g. token id).\n return void (await cmd.tokens(sub ?? 'list', flags, positionals.slice(1)));\n case 'help':\n case undefined:\n case '--help':\n case '-h':\n process.stdout.write(`${HELP}\\n`);\n process.exit(ExitCode.OK);\n break;\n default:\n fail(ExitCode.USAGE, `unknown command: ${command}\\n\\n${HELP}`);\n }\n}\n\nmain().catch((e) => fail(ExitCode.ERROR, String(e?.message ?? e)));\n","import { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, relative } from 'node:path';\nimport type { GlassQuery } from '@glassanalytics/core';\nimport { Api } from './api.js';\nimport { readCredentials, readProject, tokenFor, writeCredentials, writeProject } from './config.js';\nimport { ExitCode, fail, ok, parseBytes } from './output.js';\n\ntype Flags = Record<string, string | boolean>;\n\nfunction requireProject() {\n const project = readProject();\n if (!project) fail(ExitCode.USAGE, 'no glass.json found — run `glass init` first');\n return project;\n}\n\n/**\n * Token precedence (`CLI.md` §2): explicit --token > GLASS_TOKEN env > stored\n * per-project token > stored Clerk session. Lets CI inject a token without\n * touching the filesystem.\n */\nfunction resolveToken(flags: Flags, projectId?: string): string | undefined {\n if (typeof flags.token === 'string' && flags.token) return flags.token;\n if (process.env.GLASS_TOKEN) return process.env.GLASS_TOKEN;\n if (projectId) {\n const t = tokenFor(projectId);\n if (t) return t;\n }\n return readCredentials().session;\n}\n\nfunction authedApi(flags: Flags = {}) {\n const project = requireProject();\n const token = resolveToken(flags, project.project_id);\n if (!token) fail(ExitCode.AUTH, 'no credentials — run `glass init`, `glass login`, or set GLASS_TOKEN');\n return { api: new Api(project.api_host, token, project.project_id), project };\n}\n\n// --- glass init (zero-auth provisioning) -------------------------------------\n\nexport async function init(flags: Flags): Promise<never> {\n // Idempotent: don't re-provision if a project is already linked here.\n const existing = readProject();\n if (existing && flags.force !== true) {\n return ok({ project_id: existing.project_id, linked: true }, () => {\n process.stdout.write(`Already linked to ${existing.project_id} (glass.json present).\\n`);\n process.stdout.write('Use `glass init --force` to provision a new project, or `glass install` to wire the SDK.\\n');\n });\n }\n\n const apiHost = (flags['api-host'] as string) ?? 'https://api.glass.dev';\n const api = new Api(apiHost);\n const res = await api.request<{\n project_id: string;\n ingest_key: string;\n provisioning_token: string;\n claim_url: string;\n }>('POST', '/v1/projects/provision', { name: (flags.name as string) ?? undefined });\n\n writeProject({\n project_id: res.project_id,\n ingest_key: res.ingest_key,\n ingest_host: (flags['ingest-host'] as string) ?? 'https://in.glass.dev',\n api_host: apiHost,\n claim_url: res.claim_url,\n });\n const creds = readCredentials();\n creds.tokens[res.project_id] = res.provisioning_token;\n writeCredentials(creds);\n\n return ok(res, () => {\n process.stdout.write(`Created project ${res.project_id}\\n`);\n process.stdout.write('Wrote glass.json and ~/.glass/credentials.json (0600)\\n');\n process.stdout.write(`\\nClaim it to keep your data:\\n ${res.claim_url}\\n`);\n process.stdout.write('\\nNext: `glass install` to wire up the SDK.\\n');\n });\n}\n\n// --- glass install (framework detection) -------------------------------------\n\ntype Framework = 'next' | 'react' | 'vite' | 'node' | 'browser';\n\nfunction detectFramework(): Framework {\n try {\n const pkg = JSON.parse(readFileSync('package.json', 'utf8')) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.next) return 'next';\n if (deps.express || deps.fastify || deps.hono) return 'node';\n if (deps.react) return 'react';\n if (deps.vite) return 'vite';\n } catch {\n /* no package.json — assume browser */\n }\n return 'browser';\n}\n\n/** Pick the package manager from the lockfile present in cwd. */\nfunction detectPackageManager(): { cmd: string; args: string[] } {\n if (existsSync('pnpm-lock.yaml')) return { cmd: 'pnpm', args: ['add'] };\n if (existsSync('yarn.lock')) return { cmd: 'yarn', args: ['add'] };\n if (existsSync('bun.lockb')) return { cmd: 'bun', args: ['add'] };\n return { cmd: 'npm', args: ['install'] };\n}\n\nfunction snippetFor(framework: Framework, project: { ingest_key: string; ingest_host: string }): { file: string; code: string; pkg: string } {\n if (framework === 'node') {\n return {\n pkg: '@glass/node',\n file: 'glass.ts',\n code: `import { GlassNode } from '@glass/node';\\n\\nexport const glass = new GlassNode({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });\\n`,\n };\n }\n return {\n pkg: '@glass/browser',\n file: 'glass.ts',\n code: `import glass from '@glass/browser';\\n\\nglass.init({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });\\n\\nexport default glass;\\n`,\n };\n}\n\n/** Candidate entry-point files per framework, in preference order. */\nfunction entryCandidates(framework: Framework): string[] {\n switch (framework) {\n case 'next':\n return ['app/layout.tsx', 'app/layout.jsx', 'src/app/layout.tsx', 'src/app/layout.jsx'];\n case 'react':\n case 'vite':\n return ['src/main.tsx', 'src/main.jsx', 'src/index.tsx', 'src/index.jsx', 'src/main.ts', 'src/index.ts'];\n case 'node':\n return ['src/index.ts', 'src/server.ts', 'index.ts', 'server.ts', 'src/main.ts'];\n default:\n return [];\n }\n}\n\n/**\n * Inject `import '<glass>'` into the app's entry point so the SDK actually\n * initialises (`CLI.md` §3.1) — writing `glass.ts` alone wires nothing. We only\n * touch a file that exists and doesn't already import it, and we never reorder\n * existing code (the import is prepended, after a leading \"use client\" if present).\n */\nfunction injectEntryPoint(framework: Framework, glassFile: string): { entry: string | null; injected: boolean } {\n for (const entry of entryCandidates(framework)) {\n if (!existsSync(entry)) continue;\n const src = readFileSync(entry, 'utf8');\n let spec = relative(dirname(entry), glassFile).replace(/\\.(ts|tsx|js|jsx)$/, '');\n if (!spec.startsWith('.')) spec = `./${spec}`;\n if (src.includes(`'${spec}'`) || src.includes(`\"${spec}\"`)) return { entry, injected: false };\n const importLine = `import '${spec}';\\n`;\n // Preserve a leading directive (\"use client\"/\"use server\") as the first line.\n const directive = /^\\s*(['\"])use (client|server)\\1;?\\s*\\n/.exec(src);\n const next = directive\n ? src.slice(0, directive[0].length) + importLine + src.slice(directive[0].length)\n : importLine + src;\n writeFileSync(entry, next);\n return { entry, injected: true };\n }\n return { entry: null, injected: false };\n}\n\nexport function install(flags: Flags): never {\n const project = requireProject();\n const framework = ((flags.framework as Framework) ?? detectFramework()) as Framework;\n const { pkg, file, code } = snippetFor(framework, project);\n\n // 1. Install the SDK dependency (fixed argv — never a shell string).\n let installed = false;\n if (flags['no-install'] !== true) {\n const pm = detectPackageManager();\n const r = spawnSync(pm.cmd, [...pm.args, pkg], { stdio: 'inherit' });\n installed = r.status === 0;\n if (!installed && r.error) {\n return fail(ExitCode.ERROR, `failed to run ${pm.cmd}: ${String(r.error.message)} — install ${pkg} manually`);\n }\n }\n\n // 2. Write the wiring file if absent (never clobber existing app code).\n let wrote = false;\n if (!existsSync(file)) {\n writeFileSync(file, code);\n wrote = true;\n }\n\n // 3. Inject the import into the framework entry point so init actually runs.\n const { entry, injected } = injectEntryPoint(framework, file);\n\n return ok({ framework, package: pkg, installed, file, wrote_file: wrote, entry, injected, snippet: code }, () => {\n process.stdout.write(`Detected: ${framework}\\n`);\n process.stdout.write(installed ? `Installed ${pkg}.\\n` : `Skipped install — add ${pkg} yourself.\\n`);\n process.stdout.write(wrote ? `Wrote ${file}.\\n` : `${file} already exists; left untouched.\\n`);\n if (injected && entry) process.stdout.write(`Wired ${file} into ${entry}.\\n`);\n else if (entry) process.stdout.write(`${entry} already imports ${file}.\\n`);\n else process.stdout.write(`No entry point found — import \"./${file.replace(/\\.(ts|tsx)$/, '')}\" yourself.\\n`);\n });\n}\n\n// --- status / doctor ----------------------------------------------------------\n\nexport async function status(flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n const res = await api.request('GET', '/v1/ingest/status');\n return ok(res);\n}\n\nexport async function doctor(flags: Flags): Promise<never> {\n const project = readProject();\n const checks: { name: string; ok: boolean; detail?: string }[] = [];\n checks.push({ name: 'glass.json present', ok: !!project });\n if (project) {\n const tok = resolveToken(flags, project.project_id);\n checks.push({ name: 'credentials present', ok: !!tok });\n try {\n const api = new Api(project.api_host, tok, project.project_id);\n const s = await api.request<{ receiving: boolean }>('GET', '/v1/ingest/status');\n checks.push({ name: 'events received', ok: s.receiving, detail: s.receiving ? undefined : 'no events in last 24h' });\n } catch {\n checks.push({ name: 'control plane reachable', ok: false });\n }\n }\n const allOk = checks.every((c) => c.ok);\n return allOk ? ok({ checks }) : fail(ExitCode.ERROR, 'doctor found problems', { checks });\n}\n\n// --- claim / login ------------------------------------------------------------\n\nexport async function claim(flags: Flags): Promise<never> {\n const project = requireProject();\n\n // Default: show the claim URL stored at `glass init` WITHOUT contacting the\n // control plane (so we never invalidate a link the user may already be using).\n if (flags.reissue !== true && project.claim_url) {\n return ok({ claim_url: project.claim_url, reissued: false }, () =>\n process.stdout.write(`Claim URL:\\n ${project.claim_url}\\n\\n(Use \\`glass claim --reissue\\` to mint a fresh single-use link.)\\n`),\n );\n }\n\n // `--reissue` (or no stored URL): mint a fresh single-use claim link.\n const token = tokenFor(project.project_id);\n if (!token) fail(ExitCode.AUTH, 'no provisioning token for this project');\n const api = new Api(project.api_host, token);\n const res = await api.request<{ claim_url: string }>('POST', `/v1/projects/${project.project_id}/claim-url`);\n // Persist the new link so subsequent `glass claim` shows it without reissuing.\n writeProject({ ...project, claim_url: res.claim_url });\n return ok({ ...res, reissued: true }, () => process.stdout.write(`Claim URL (reissued):\\n ${res.claim_url}\\n`));\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n/**\n * `glass login` (`CLI.md` §2). `--token <session>` stores a session directly\n * (CI/non-interactive); otherwise runs the OAuth-style device flow: start a\n * grant, print the verification URL + short user-code, then poll until a\n * signed-in human approves it in the dashboard.\n */\nexport async function login(flags: Flags): Promise<never> {\n const apiHost = (flags['api-host'] as string) ?? readProject()?.api_host ?? 'https://api.glass.dev';\n\n // Non-interactive path: store an explicitly-provided session.\n const provided = flags.token as string | undefined;\n if (provided) {\n const creds = readCredentials();\n creds.session = provided;\n writeCredentials(creds);\n return ok({ message: 'Logged in. Session stored in ~/.glass/credentials.json' }, () =>\n process.stdout.write('Logged in. Session stored in ~/.glass/credentials.json\\n'),\n );\n }\n\n // The device flow needs a human to approve in a browser; in non-interactive\n // mode (`--no-input`/`--yes`, or CI) fail fast and ask for a token instead.\n if (flags['no-input'] === true || flags.yes === true || (!process.stdin.isTTY && !process.stdout.isTTY)) {\n return fail(ExitCode.AUTH, 'login is interactive — pass `--token <session>` or set GLASS_TOKEN for non-interactive use');\n }\n\n // Device flow.\n const api = new Api(apiHost);\n const grant = await api.request<{\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n interval: number;\n expires_in: number;\n }>('POST', '/v1/cli/device/start');\n\n if (!flags.json) {\n process.stdout.write('\\nTo sign in, open:\\n');\n process.stdout.write(` ${grant.verification_uri_complete ?? grant.verification_uri}\\n\\n`);\n process.stdout.write(`and enter the code: ${grant.user_code}\\n\\n`);\n process.stdout.write('Waiting for approval…\\n');\n }\n\n const deadline = Date.now() + grant.expires_in * 1000;\n const intervalMs = Math.max(1, grant.interval) * 1000;\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n let resp: { session?: string; status?: string } | null = null;\n try {\n resp = await api.request<{ session?: string; status?: string }>('POST', '/v1/cli/device/token', {\n device_code: grant.device_code,\n });\n } catch {\n // 202 (pending) / 410 (expired) surface as request errors depending on the\n // client; treat transient failures as \"keep polling\" until the deadline.\n continue;\n }\n if (resp?.session) {\n const creds = readCredentials();\n creds.session = resp.session;\n writeCredentials(creds);\n return ok({ message: 'Logged in. Session stored in ~/.glass/credentials.json' }, () =>\n process.stdout.write('\\nLogged in. Session stored in ~/.glass/credentials.json\\n'),\n );\n }\n }\n return fail(ExitCode.AUTH, 'device authorization timed out — run `glass login` again');\n}\n\nexport function logout(_flags: Flags): never {\n const creds = readCredentials();\n creds.session = undefined;\n writeCredentials(creds);\n return ok({ message: 'Logged out. Cleared stored session.' }, () => process.stdout.write('Logged out.\\n'));\n}\n\nexport async function whoami(flags: Flags): Promise<never> {\n const project = readProject();\n const token = resolveToken(flags, project?.project_id);\n if (!token) fail(ExitCode.AUTH, 'not logged in — run `glass login` or set GLASS_TOKEN');\n const api = new Api(project?.api_host ?? (flags['api-host'] as string) ?? 'https://api.glass.dev', token, project?.project_id);\n return ok(await api.request('GET', '/v1/me'));\n}\n\n/** Switch the active project in glass.json after verifying access. */\nexport async function link(flags: Flags, positionals: string[] = []): Promise<never> {\n // Accept both `glass link <id>` and `glass link --project <id>`.\n const projectId = (flags.project as string | undefined) ?? positionals[0];\n if (!projectId) fail(ExitCode.USAGE, 'link needs a project id: `glass link <id>`');\n const existing = readProject();\n const apiHost = (flags['api-host'] as string) ?? existing?.api_host ?? 'https://api.glass.dev';\n const token = resolveToken(flags, projectId);\n if (!token) fail(ExitCode.AUTH, 'no credentials — run `glass login` or set GLASS_TOKEN');\n const api = new Api(apiHost, token, projectId);\n const proj = await api.request<{ id: string; publishableKey?: string; ingestHost?: string }>('GET', '/v1/project');\n writeProject({\n project_id: projectId,\n ingest_key: proj.publishableKey ?? existing?.ingest_key ?? '',\n ingest_host: proj.ingestHost ?? existing?.ingest_host ?? 'https://in.glass.dev',\n api_host: apiHost,\n });\n return ok({ linked: projectId }, () => process.stdout.write(`Linked glass.json to ${projectId}.\\n`));\n}\n\n// --- query + sugar ------------------------------------------------------------\n\n/**\n * `glass query` source resolution (`CLI.md` §4): a GlassQuery can come from\n * `--query '<json>'`, `--file/-f <path>`, or stdin (so it composes in a pipe:\n * `cat q.json | glass query --json`). Exactly one source is used, in that order.\n */\nexport async function query(flags: Flags): Promise<never> {\n let raw: string | undefined;\n if (typeof flags.query === 'string' && flags.query) raw = flags.query;\n else if (typeof flags.file === 'string' && flags.file) raw = readFileSync(flags.file, 'utf8');\n else if (!process.stdin.isTTY) raw = readFileSync(0, 'utf8').trim() || undefined;\n\n if (!raw) fail(ExitCode.USAGE, \"query needs --query '<json>', --file <path>, or piped stdin\");\n let parsed: GlassQuery;\n try {\n parsed = JSON.parse(raw) as GlassQuery;\n } catch (e) {\n return fail(ExitCode.USAGE, `query is not valid JSON: ${String((e as Error).message)}`);\n }\n return runQuery(parsed, flags);\n}\n\nexport async function runQuery(query: GlassQuery, flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n const body: Record<string, unknown> = { query, confirm: flags.confirm === true };\n if (flags['max-scan']) {\n // Accept a bare number (legacy: MB) or a unit string (`500MB`, `1GB`).\n const raw = String(flags['max-scan']);\n const bytes = /^[0-9]*\\.?[0-9]+$/.test(raw.trim())\n ? Number(raw) * 1024 * 1024\n : parseBytes(raw);\n if (bytes == null) fail(ExitCode.USAGE, `invalid --max-scan: ${raw} (try 500MB or 1GB)`);\n body.max_scan_bytes = bytes;\n }\n const res = await api.request('POST', '/v1/query', body);\n return ok(res);\n}\n\nfunction parseTime(flags: Flags) {\n return { last: (flags.last as string) ?? '7d' };\n}\n\nexport async function trend(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'trend',\n time: parseTime(flags),\n measure: { aggregate: (flags.aggregate as 'count' | 'unique_users' | 'sum') ?? 'count', ...(flags.event ? { event: flags.event as string } : {}) },\n bucket: (flags.bucket as 'hour' | 'day' | 'week' | 'month') ?? 'day',\n ...(flags.breakdown ? { breakdown: flags.breakdown as string } : {}),\n },\n flags,\n );\n}\n\nexport async function funnel(flags: Flags): Promise<never> {\n const steps = String(flags.steps ?? '').split(',').map((e) => ({ event: e.trim() })).filter((s) => s.event);\n if (flags.id) return runQuery({ v: 1, kind: 'funnel', time: parseTime(flags), definition_id: flags.id as string }, flags);\n if (steps.length < 2) fail(ExitCode.USAGE, 'funnel needs --steps a,b,c (>=2) or --id <definition>');\n return runQuery({ v: 1, kind: 'funnel', time: parseTime(flags), steps, ...(flags.window ? { window: flags.window as string } : {}) }, flags);\n}\n\nexport async function retention(flags: Flags): Promise<never> {\n if (!flags.id) fail(ExitCode.USAGE, 'retention needs --id <definition>');\n return runQuery({ v: 1, kind: 'retention', time: parseTime(flags), definition_id: flags.id as string, return_event: (flags.return as string) ?? '$pageview', periods: Number(flags.periods ?? 8) }, flags);\n}\n\nexport async function segment(flags: Flags): Promise<never> {\n const groupBy = String(flags['group-by'] ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n if (groupBy.length === 0) fail(ExitCode.USAGE, 'segment needs --group-by a,b');\n return runQuery({ v: 1, kind: 'segmentation', time: parseTime(flags), group_by: groupBy, ...(flags.event ? { event: flags.event as string } : {}) }, flags);\n}\n\nexport async function errors(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'errors',\n time: parseTime(flags),\n limit: Number(flags.limit ?? 50),\n ...(flags.group ? { group: flags.group as string } : {}),\n ...(flags.status ? { status: flags.status as 'unresolved' | 'resolved' | 'ignored' } : {}),\n },\n flags,\n );\n}\n\nexport async function replays(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'replays',\n time: parseTime(flags),\n limit: Number(flags.limit ?? 50),\n ...(flags.user ? { session_filters: [{ property: 'user_id', op: 'eq' as const, value: flags.user as string }] } : {}),\n },\n flags,\n );\n}\n\n// --- define / tokens ----------------------------------------------------------\n\nexport async function define(flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n\n // `define --list` — show existing definitions.\n if (flags.list) return ok(await api.request('GET', '/v1/definitions'));\n\n // Flag-based sugar: build a spec from flags without writing JSON.\n let spec: unknown;\n if (flags.kind === 'funnel') {\n const steps = String(flags.steps ?? '').split(',').map((e) => ({ event: e.trim() })).filter((s) => s.event);\n if (steps.length < 2) fail(ExitCode.USAGE, 'define --kind funnel needs --steps a,b,c (>=2)');\n spec = { v: 1, kind: 'funnel', name: (flags.name as string) ?? 'funnel', steps, scope: (flags.scope as string) ?? 'within-session', ...(flags.window ? { window: flags.window as string } : {}) };\n } else if (flags.kind === 'metric') {\n spec = { v: 1, kind: 'metric', name: (flags.name as string) ?? 'metric', aggregate: (flags.aggregate as string) ?? 'count', bucket: (flags.bucket as string) ?? 'day', ...(flags.event ? { event: flags.event as string } : {}) };\n } else {\n const raw = flags.file ? readFileSync(flags.file as string, 'utf8') : readFileSync(0, 'utf8');\n spec = JSON.parse(raw);\n }\n const res = await api.request('POST', '/v1/definitions', { spec });\n return ok(res);\n}\n\nexport async function tokens(action: string, flags: Flags, positionals: string[] = []): Promise<never> {\n const { api } = authedApi(flags);\n if (action === 'list') return ok(await api.request('GET', '/v1/tokens'));\n if (action === 'create') {\n let budget: number | undefined;\n if (flags['budget-r2sql']) {\n // Accept human units + an optional `/day` rate suffix (`1GB/day`).\n const parsed = parseBytes(String(flags['budget-r2sql']));\n if (parsed == null) fail(ExitCode.USAGE, `invalid --budget-r2sql: ${flags['budget-r2sql']} (try 1GB/day)`);\n budget = parsed;\n }\n const res = await api.request<{ id: string; token: string; prefix: string }>('POST', '/v1/tokens', {\n name: (flags.name as string) ?? 'agent',\n role: (flags.role as string) ?? 'read',\n ...(budget != null ? { budget_r2sql_bytes_per_day: budget } : {}),\n });\n // The secret is shown ONCE — print it verbatim (not through the redactor).\n return ok(res, () => {\n process.stdout.write(`Created token ${res.id}\\n\\n ${res.token}\\n\\nThis is shown once. Store it now (e.g. as GLASS_TOKEN).\\n`);\n });\n }\n if (action === 'revoke') {\n // Accept both `glass tokens revoke <id>` and `--id <id>`.\n const id = (flags.id as string | undefined) ?? positionals[0];\n if (!id) fail(ExitCode.USAGE, 'tokens revoke needs a token id: `glass tokens revoke <id>`');\n return ok(await api.request('DELETE', `/v1/tokens/${id}`));\n }\n return fail(ExitCode.USAGE, 'tokens <list|create|revoke>');\n}\n","/**\n * Stable, scriptable output (`CLI.md` §5). The CLI is built for agents as much\n * as humans: `--json` emits a uniform envelope and EXIT CODES are stable so a\n * caller can branch on them without parsing prose.\n */\n\nexport const ExitCode = {\n OK: 0,\n ERROR: 1,\n USAGE: 2,\n AUTH: 3,\n COST_GATE: 4,\n BUDGET: 5,\n} as const;\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];\n\ntype OutputFormat = 'human' | 'json' | 'csv' | 'ndjson';\nlet format: OutputFormat = 'human';\nexport function setFormat(f: OutputFormat): void {\n format = f;\n}\n/** Back-compat shim for `--json`. */\nexport function setJsonMode(on: boolean): void {\n if (on) format = 'json';\n}\n\n/** Mask token-like secrets in human output so they're never accidentally logged. */\nconst SECRET_RE =\n /\\b(glass_(?:sk|pt)_[A-Za-z0-9]+)\\b|\\b(eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})\\b/g;\nexport function redact(text: string): string {\n return text.replace(SECRET_RE, (m) => `${m.slice(0, 12)}…<redacted>`);\n}\n\n/** Flatten an array of flat records to CSV; falls back to JSON for non-tabular data. */\nexport function toCsv(data: unknown): string | null {\n const rows = Array.isArray(data) ? data : extractRows(data);\n if (!rows || rows.length === 0) return null;\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n const esc = (v: unknown) => {\n const s = v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n return /[\",\\n]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n return [\n cols.join(','),\n ...rows.map((r) => cols.map((c) => esc((r as Record<string, unknown>)[c])).join(',')),\n ].join('\\n');\n}\n\n/**\n * Parse a human byte budget into bytes (`CLI.md` §4): accepts plain numbers and\n * unit suffixes (`500MB`, `1GB`, `2 TiB`), with an optional `/day` rate suffix\n * that we strip (the API stores per-day budgets). Returns null on garbage.\n */\nconst BYTE_UNITS: Record<string, number> = {\n b: 1,\n kb: 1e3,\n mb: 1e6,\n gb: 1e9,\n tb: 1e12,\n kib: 1024,\n mib: 1024 ** 2,\n gib: 1024 ** 3,\n tib: 1024 ** 4,\n};\nexport function parseBytes(input: string): number | null {\n const s = input.trim().toLowerCase().replace(/\\/(day|d|hr|hour|h)$/, '');\n const m = /^([0-9]*\\.?[0-9]+)\\s*([a-z]+)?$/.exec(s);\n if (!m) return null;\n const value = Number(m[1]);\n if (!Number.isFinite(value)) return null;\n if (!m[2]) return value; // bare number = bytes\n const unit = BYTE_UNITS[m[2]];\n if (!unit) return null;\n return Math.round(value * unit);\n}\n\n/** Find the first array-of-objects field (e.g. {rows:[...]}, {issues:[...]}). */\nexport function extractRows(data: unknown): Record<string, unknown>[] | null {\n if (Array.isArray(data)) return data as Record<string, unknown>[];\n if (data && typeof data === 'object') {\n for (const v of Object.values(data)) {\n if (Array.isArray(v) && v.every((x) => x && typeof x === 'object'))\n return v as Record<string, unknown>[];\n }\n }\n return null;\n}\n\n/**\n * Render an array of flat records as an aligned ASCII table for human output.\n * Returns null when the data isn't tabular so callers can fall back to JSON.\n */\nexport function humanTable(data: unknown): string | null {\n const rows = extractRows(data);\n if (!rows || rows.length === 0) return null;\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n if (cols.length === 0) return null;\n const cell = (v: unknown) => {\n const s = v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n return redact(s).replace(/\\n/g, ' ');\n };\n const widths = cols.map((c) =>\n Math.max(c.length, ...rows.map((r) => cell((r as Record<string, unknown>)[c]).length)),\n );\n const line = (cells: string[]) => cells.map((s, i) => s.padEnd(widths[i] ?? 0)).join(' ').trimEnd();\n const header = line(cols);\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const body = rows.map((r) => line(cols.map((c) => cell((r as Record<string, unknown>)[c]))));\n return [header, sep, ...body].join('\\n');\n}\n\n/**\n * One-line provenance badge for a query result (`UI.md` ResultBadge parity):\n * surfaces whether a number is exact or sampled, and its source, so an agent\n * reading stdout knows how much to trust it. Returns null when not applicable.\n */\nexport function resultBadge(data: unknown): string | null {\n if (!data || typeof data !== 'object') return null;\n const d = data as Record<string, unknown>;\n if (typeof d.exact !== 'boolean' && !d.source && !d.sampled) return null;\n const parts: string[] = [];\n parts.push(d.exact === false ? 'sampled' : 'exact');\n if (d.source) parts.push(String(d.source));\n const sampled = d.sampled as { interval?: number } | undefined;\n if (sampled?.interval && sampled.interval > 1) parts.push(`1/${sampled.interval}`);\n return `[${parts.join(' · ')}]`;\n}\n\nexport function ok(data: unknown, human?: () => void): never {\n if (format === 'json') {\n process.stdout.write(`${JSON.stringify({ ok: true, data }, null, 2)}\\n`);\n } else if (format === 'ndjson') {\n const rows = extractRows(data) ?? [data];\n for (const r of rows) process.stdout.write(`${JSON.stringify(r)}\\n`);\n } else if (format === 'csv') {\n const csv = toCsv(data);\n process.stdout.write(csv ? `${csv}\\n` : `${JSON.stringify(data, null, 2)}\\n`);\n } else if (human) {\n human();\n } else {\n const table = humanTable(data);\n if (table) {\n const badge = resultBadge(data);\n process.stdout.write(`${table}\\n`);\n if (badge) process.stdout.write(`${badge}\\n`);\n } else {\n process.stdout.write(`${redact(JSON.stringify(data, null, 2))}\\n`);\n }\n }\n process.exit(ExitCode.OK);\n}\n\nexport function fail(code: ExitCodeValue, message: string, extra?: unknown): never {\n if (format === 'json' || format === 'ndjson') {\n process.stdout.write(\n `${JSON.stringify({ ok: false, error: { code, message, ...(extra ? { extra } : {}) } }, null, 2)}\\n`,\n );\n } else {\n process.stderr.write(`glass: ${message}\\n`);\n if (extra) process.stderr.write(`${redact(JSON.stringify(extra, null, 2))}\\n`);\n }\n process.exit(code);\n}\n","import { ExitCode, fail } from './output.js';\n\n/**\n * Thin control-plane client. Maps HTTP status to the CLI's stable exit codes so\n * `--json` callers (agents) can branch deterministically (`CLI.md` §5):\n * 401/403 → AUTH(3), 402 → COST_GATE(4), 429 → BUDGET(5).\n */\nexport class Api {\n constructor(\n private apiHost: string,\n private token?: string,\n private projectId?: string,\n ) {}\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.token) headers.Authorization = `Bearer ${this.token}`;\n if (this.projectId) headers['X-Glass-Project'] = this.projectId;\n\n const res = await fetch(`${this.apiHost}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n }).catch((e) => fail(ExitCode.ERROR, `network error: ${String(e)}`));\n\n const text = await res.text();\n const json = text ? (JSON.parse(text) as T) : ({} as T);\n\n if (res.status === 401 || res.status === 403) fail(ExitCode.AUTH, 'unauthorized', json);\n if (res.status === 402) fail(ExitCode.COST_GATE, 'cost gate: re-run with --confirm', json);\n if (res.status === 429) fail(ExitCode.BUDGET, 'budget or rate limit exceeded', json);\n if (!res.ok) fail(ExitCode.ERROR, `request failed (${res.status})`, json);\n return json;\n }\n}\n","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\n/**\n * Local config (`CLI.md` §2/§3). Project pointer in `glass.json` (committable,\n * contains only the write-only publishable key); SECRETS in\n * `~/.glass/credentials.json` with `0600` perms, never in the repo.\n */\n\nexport interface ProjectFile {\n project_id: string;\n ingest_key: string;\n ingest_host: string;\n api_host: string;\n /** The claim URL minted at provisioning (single-use); shown by `glass claim`. */\n claim_url?: string;\n}\n\nexport interface Credentials {\n /** provisioning/agent tokens keyed by project_id. */\n tokens: Record<string, string>;\n /** Clerk session from `glass login` (device flow). */\n session?: string;\n}\n\nconst PROJECT_FILE = join(process.cwd(), 'glass.json');\nconst CRED_FILE = join(homedir(), '.glass', 'credentials.json');\n\n/**\n * Read the project pointer, with environment overrides layered on top\n * (`CLI.md` §2): `GLASS_PROJECT` selects/overrides the project id and\n * `GLASS_INGEST_KEY` the publishable key — so CI can run without a committed\n * `glass.json`. If neither the file nor `GLASS_PROJECT` is present, returns null.\n */\nexport function readProject(): ProjectFile | null {\n let file: ProjectFile | null = null;\n try {\n file = JSON.parse(readFileSync(PROJECT_FILE, 'utf8')) as ProjectFile;\n } catch {\n file = null;\n }\n\n const envProject = process.env.GLASS_PROJECT;\n const envIngest = process.env.GLASS_INGEST_KEY;\n if (!file && !envProject) return null;\n\n return {\n project_id: envProject ?? file?.project_id ?? '',\n ingest_key: envIngest ?? file?.ingest_key ?? '',\n ingest_host: process.env.GLASS_INGEST_HOST ?? file?.ingest_host ?? 'https://in.glass.dev',\n api_host: process.env.GLASS_API_HOST ?? file?.api_host ?? 'https://api.glass.dev',\n ...(file?.claim_url ? { claim_url: file.claim_url } : {}),\n };\n}\n\nexport function writeProject(p: ProjectFile): void {\n writeFileSync(PROJECT_FILE, `${JSON.stringify(p, null, 2)}\\n`);\n}\n\nexport function readCredentials(): Credentials {\n try {\n return JSON.parse(readFileSync(CRED_FILE, 'utf8')) as Credentials;\n } catch {\n return { tokens: {} };\n }\n}\n\nexport function writeCredentials(c: Credentials): void {\n mkdirSync(dirname(CRED_FILE), { recursive: true, mode: 0o700 });\n writeFileSync(CRED_FILE, `${JSON.stringify(c, null, 2)}\\n`, { mode: 0o600 });\n chmodSync(CRED_FILE, 0o600); // enforce even if the file pre-existed\n}\n\nexport function tokenFor(projectId: string): string | undefined {\n return readCredentials().tokens[projectId];\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","dirname","readFileSync","dirname","writeFileSync","query"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands.ts","../src/output.ts","../src/api.ts","../src/config.ts"],"sourcesContent":["import { parseArgs } from 'node:util';\nimport * as cmd from './commands.js';\nimport { ExitCode, fail, setFormat, setJsonMode } from './output.js';\n\n/**\n * `glass` — the agent-friendly terminal surface (`CLI.md`). Setup in one command\n * (`glass init`, no signup), then the same typed query primitives the dashboard\n * uses. `--json` + stable exit codes make it scriptable by humans and agents.\n */\n\nconst HELP = `glass <command> [options]\n\nSetup\n init [--force] Provision a project with no signup (writes glass.json)\n install [--framework F] [--no-install] Install + wire the SDK\n status Show whether events are being received\n doctor Diagnose setup problems\n claim Get the claim URL to keep your data\n login [--token T] Store a Clerk session for human-scoped access\n logout Clear the stored session\n whoami Show the current principal (GET /v1/me)\n link --project ID Point glass.json at another project you can access\n\nQuery (all accept --last 7d, --json, --confirm, --max-scan <MB>)\n trend --event E [--bucket day] [--breakdown B] [--aggregate count|unique_users|sum]\n funnel --steps a,b,c | --id <def> [--window 1d]\n retention --id <def> --return E [--periods 8]\n segment --group-by a,b [--event E]\n errors\n replays [--limit 50]\n query --query '<json>' | -f <file> | (piped stdin)\n\nManage\n define --file spec.json | --kind funnel --steps a,b | --list\n tokens list | create [--budget-r2sql 1GB/day] | revoke <id>\n link <project-id>\n\nGlobal: --json --csv --ndjson --api-host --ingest-host\n --max-scan <500MB|1GB> --yes/--no-input (auth: --token | GLASS_TOKEN)\nEnv: GLASS_TOKEN GLASS_PROJECT GLASS_INGEST_KEY GLASS_API_HOST`;\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n const command = argv[0];\n const sub = argv[1] && !argv[1].startsWith('-') ? argv[1] : undefined;\n\n const { values, positionals } = parseArgs({\n args: argv.slice(1),\n allowPositionals: true,\n options: {\n json: { type: 'boolean' },\n csv: { type: 'boolean' },\n ndjson: { type: 'boolean' },\n confirm: { type: 'boolean' },\n reissue: { type: 'boolean' },\n force: { type: 'boolean' },\n 'no-install': { type: 'boolean' },\n yes: { type: 'boolean' },\n 'no-input': { type: 'boolean' },\n list: { type: 'boolean' },\n 'max-scan': { type: 'string' },\n last: { type: 'string' },\n event: { type: 'string' },\n bucket: { type: 'string' },\n breakdown: { type: 'string' },\n aggregate: { type: 'string' },\n steps: { type: 'string' },\n window: { type: 'string' },\n scope: { type: 'string' },\n kind: { type: 'string' },\n id: { type: 'string' },\n return: { type: 'string' },\n periods: { type: 'string' },\n 'group-by': { type: 'string' },\n group: { type: 'string' },\n status: { type: 'string' },\n limit: { type: 'string' },\n user: { type: 'string' },\n query: { type: 'string' },\n file: { type: 'string', short: 'f' },\n name: { type: 'string' },\n role: { type: 'string' },\n framework: { type: 'string' },\n project: { type: 'string' },\n 'budget-r2sql': { type: 'string' },\n token: { type: 'string' },\n 'api-host': { type: 'string' },\n 'ingest-host': { type: 'string' },\n },\n });\n\n const flags = values as Record<string, string | boolean>;\n if (flags.json) setJsonMode(true);\n else if (flags.ndjson) setFormat('ndjson');\n else if (flags.csv) setFormat('csv');\n\n switch (command) {\n case 'init':\n return void (await cmd.init(flags));\n case 'install':\n return void cmd.install(flags);\n case 'status':\n return void (await cmd.status(flags));\n case 'doctor':\n return void (await cmd.doctor(flags));\n case 'claim':\n return void (await cmd.claim(flags));\n case 'login':\n return void (await cmd.login(flags));\n case 'logout':\n return void cmd.logout(flags);\n case 'whoami':\n return void (await cmd.whoami(flags));\n case 'link':\n return void (await cmd.link(flags, positionals));\n case 'trend':\n return void (await cmd.trend(flags));\n case 'funnel':\n return void (await cmd.funnel(flags));\n case 'retention':\n return void (await cmd.retention(flags));\n case 'segment':\n return void (await cmd.segment(flags));\n case 'errors':\n return void (await cmd.errors(flags));\n case 'replays':\n return void (await cmd.replays(flags));\n case 'query':\n return void (await cmd.query(flags));\n case 'define':\n return void (await cmd.define(flags));\n case 'tokens':\n // positionals[0] is the sub-action; pass the remainder (e.g. token id).\n return void (await cmd.tokens(sub ?? 'list', flags, positionals.slice(1)));\n case 'help':\n case undefined:\n case '--help':\n case '-h':\n process.stdout.write(`${HELP}\\n`);\n process.exit(ExitCode.OK);\n break;\n default:\n fail(ExitCode.USAGE, `unknown command: ${command}\\n\\n${HELP}`);\n }\n}\n\nmain().catch((e) => fail(ExitCode.ERROR, String(e?.message ?? e)));\n","import { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, relative } from 'node:path';\nimport type { GlassQuery } from '@glassanalytics/core';\nimport { Api } from './api.js';\nimport { readCredentials, readProject, tokenFor, writeCredentials, writeProject } from './config.js';\nimport { ExitCode, fail, ok, parseBytes } from './output.js';\n\ntype Flags = Record<string, string | boolean>;\n\nfunction requireProject() {\n const project = readProject();\n if (!project) fail(ExitCode.USAGE, 'no glass.json found — run `glass init` first');\n return project;\n}\n\n/**\n * Token precedence (`CLI.md` §2): explicit --token > GLASS_TOKEN env > stored\n * per-project token > stored Clerk session. Lets CI inject a token without\n * touching the filesystem.\n */\nfunction resolveToken(flags: Flags, projectId?: string): string | undefined {\n if (typeof flags.token === 'string' && flags.token) return flags.token;\n if (process.env.GLASS_TOKEN) return process.env.GLASS_TOKEN;\n if (projectId) {\n const t = tokenFor(projectId);\n if (t) return t;\n }\n return readCredentials().session;\n}\n\nfunction authedApi(flags: Flags = {}) {\n const project = requireProject();\n const token = resolveToken(flags, project.project_id);\n if (!token) fail(ExitCode.AUTH, 'no credentials — run `glass init`, `glass login`, or set GLASS_TOKEN');\n return { api: new Api(project.api_host, token, project.project_id), project };\n}\n\n// --- glass init (zero-auth provisioning) -------------------------------------\n\nexport async function init(flags: Flags): Promise<never> {\n // Idempotent: don't re-provision if a project is already linked here.\n const existing = readProject();\n if (existing && flags.force !== true) {\n return ok({ project_id: existing.project_id, linked: true }, () => {\n process.stdout.write(`Already linked to ${existing.project_id} (glass.json present).\\n`);\n process.stdout.write('Use `glass init --force` to provision a new project, or `glass install` to wire the SDK.\\n');\n });\n }\n\n const apiHost = (flags['api-host'] as string) ?? 'https://api.glass.dev';\n const api = new Api(apiHost);\n const res = await api.request<{\n project_id: string;\n ingest_key: string;\n provisioning_token: string;\n claim_url: string;\n }>('POST', '/v1/projects/provision', { name: (flags.name as string) ?? undefined });\n\n writeProject({\n project_id: res.project_id,\n ingest_key: res.ingest_key,\n ingest_host: (flags['ingest-host'] as string) ?? 'https://in.glass.dev',\n api_host: apiHost,\n claim_url: res.claim_url,\n });\n const creds = readCredentials();\n creds.tokens[res.project_id] = res.provisioning_token;\n writeCredentials(creds);\n\n return ok(res, () => {\n process.stdout.write(`Created project ${res.project_id}\\n`);\n process.stdout.write('Wrote glass.json and ~/.glass/credentials.json (0600)\\n');\n process.stdout.write(`\\nClaim it to keep your data:\\n ${res.claim_url}\\n`);\n process.stdout.write('\\nNext: `glass install` to wire up the SDK.\\n');\n });\n}\n\n// --- glass install (framework detection) -------------------------------------\n\ntype Framework = 'next' | 'react' | 'vite' | 'node' | 'browser';\n\nfunction detectFramework(): Framework {\n try {\n const pkg = JSON.parse(readFileSync('package.json', 'utf8')) as { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.next) return 'next';\n if (deps.express || deps.fastify || deps.hono) return 'node';\n if (deps.react) return 'react';\n if (deps.vite) return 'vite';\n } catch {\n /* no package.json — assume browser */\n }\n return 'browser';\n}\n\n/** Pick the package manager from the lockfile present in cwd. */\nfunction detectPackageManager(): { cmd: string; args: string[] } {\n if (existsSync('pnpm-lock.yaml')) return { cmd: 'pnpm', args: ['add'] };\n if (existsSync('yarn.lock')) return { cmd: 'yarn', args: ['add'] };\n if (existsSync('bun.lockb')) return { cmd: 'bun', args: ['add'] };\n return { cmd: 'npm', args: ['install'] };\n}\n\nfunction snippetFor(framework: Framework, project: { ingest_key: string; ingest_host: string }): { file: string; code: string; pkg: string } {\n if (framework === 'node') {\n return {\n pkg: '@glassanalytics/node',\n file: 'glass.ts',\n code: `import { GlassNode } from '@glassanalytics/node';\\n\\nexport const glass = new GlassNode({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });\\n`,\n };\n }\n return {\n pkg: '@glassanalytics/browser',\n file: 'glass.ts',\n code: `import glass from '@glassanalytics/browser';\\n\\nglass.init({ projectKey: '${project.ingest_key}', ingestHost: '${project.ingest_host}' });\\n\\nexport default glass;\\n`,\n };\n}\n\n/** Candidate entry-point files per framework, in preference order. */\nfunction entryCandidates(framework: Framework): string[] {\n switch (framework) {\n case 'next':\n return ['app/layout.tsx', 'app/layout.jsx', 'src/app/layout.tsx', 'src/app/layout.jsx'];\n case 'react':\n case 'vite':\n return ['src/main.tsx', 'src/main.jsx', 'src/index.tsx', 'src/index.jsx', 'src/main.ts', 'src/index.ts'];\n case 'node':\n return ['src/index.ts', 'src/server.ts', 'index.ts', 'server.ts', 'src/main.ts'];\n default:\n return [];\n }\n}\n\n/**\n * Inject `import '<glass>'` into the app's entry point so the SDK actually\n * initialises (`CLI.md` §3.1) — writing `glass.ts` alone wires nothing. We only\n * touch a file that exists and doesn't already import it, and we never reorder\n * existing code (the import is prepended, after a leading \"use client\" if present).\n */\nfunction injectEntryPoint(framework: Framework, glassFile: string): { entry: string | null; injected: boolean } {\n for (const entry of entryCandidates(framework)) {\n if (!existsSync(entry)) continue;\n const src = readFileSync(entry, 'utf8');\n let spec = relative(dirname(entry), glassFile).replace(/\\.(ts|tsx|js|jsx)$/, '');\n if (!spec.startsWith('.')) spec = `./${spec}`;\n if (src.includes(`'${spec}'`) || src.includes(`\"${spec}\"`)) return { entry, injected: false };\n const importLine = `import '${spec}';\\n`;\n // Preserve a leading directive (\"use client\"/\"use server\") as the first line.\n const directive = /^\\s*(['\"])use (client|server)\\1;?\\s*\\n/.exec(src);\n const next = directive\n ? src.slice(0, directive[0].length) + importLine + src.slice(directive[0].length)\n : importLine + src;\n writeFileSync(entry, next);\n return { entry, injected: true };\n }\n return { entry: null, injected: false };\n}\n\nexport function install(flags: Flags): never {\n const project = requireProject();\n const framework = ((flags.framework as Framework) ?? detectFramework()) as Framework;\n const { pkg, file, code } = snippetFor(framework, project);\n\n // 1. Install the SDK dependency (fixed argv — never a shell string).\n let installed = false;\n if (flags['no-install'] !== true) {\n const pm = detectPackageManager();\n const r = spawnSync(pm.cmd, [...pm.args, pkg], { stdio: 'inherit' });\n installed = r.status === 0;\n if (!installed && r.error) {\n return fail(ExitCode.ERROR, `failed to run ${pm.cmd}: ${String(r.error.message)} — install ${pkg} manually`);\n }\n }\n\n // 2. Write the wiring file if absent (never clobber existing app code).\n let wrote = false;\n if (!existsSync(file)) {\n writeFileSync(file, code);\n wrote = true;\n }\n\n // 3. Inject the import into the framework entry point so init actually runs.\n const { entry, injected } = injectEntryPoint(framework, file);\n\n return ok({ framework, package: pkg, installed, file, wrote_file: wrote, entry, injected, snippet: code }, () => {\n process.stdout.write(`Detected: ${framework}\\n`);\n process.stdout.write(installed ? `Installed ${pkg}.\\n` : `Skipped install — add ${pkg} yourself.\\n`);\n process.stdout.write(wrote ? `Wrote ${file}.\\n` : `${file} already exists; left untouched.\\n`);\n if (injected && entry) process.stdout.write(`Wired ${file} into ${entry}.\\n`);\n else if (entry) process.stdout.write(`${entry} already imports ${file}.\\n`);\n else process.stdout.write(`No entry point found — import \"./${file.replace(/\\.(ts|tsx)$/, '')}\" yourself.\\n`);\n });\n}\n\n// --- status / doctor ----------------------------------------------------------\n\nexport async function status(flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n const res = await api.request('GET', '/v1/ingest/status');\n return ok(res);\n}\n\nexport async function doctor(flags: Flags): Promise<never> {\n const project = readProject();\n const checks: { name: string; ok: boolean; detail?: string }[] = [];\n checks.push({ name: 'glass.json present', ok: !!project });\n if (project) {\n const tok = resolveToken(flags, project.project_id);\n checks.push({ name: 'credentials present', ok: !!tok });\n try {\n const api = new Api(project.api_host, tok, project.project_id);\n const s = await api.request<{ receiving: boolean }>('GET', '/v1/ingest/status');\n checks.push({ name: 'events received', ok: s.receiving, detail: s.receiving ? undefined : 'no events in last 24h' });\n } catch {\n checks.push({ name: 'control plane reachable', ok: false });\n }\n }\n const allOk = checks.every((c) => c.ok);\n return allOk ? ok({ checks }) : fail(ExitCode.ERROR, 'doctor found problems', { checks });\n}\n\n// --- claim / login ------------------------------------------------------------\n\nexport async function claim(flags: Flags): Promise<never> {\n const project = requireProject();\n\n // Default: show the claim URL stored at `glass init` WITHOUT contacting the\n // control plane (so we never invalidate a link the user may already be using).\n if (flags.reissue !== true && project.claim_url) {\n return ok({ claim_url: project.claim_url, reissued: false }, () =>\n process.stdout.write(`Claim URL:\\n ${project.claim_url}\\n\\n(Use \\`glass claim --reissue\\` to mint a fresh single-use link.)\\n`),\n );\n }\n\n // `--reissue` (or no stored URL): mint a fresh single-use claim link.\n const token = tokenFor(project.project_id);\n if (!token) fail(ExitCode.AUTH, 'no provisioning token for this project');\n const api = new Api(project.api_host, token);\n const res = await api.request<{ claim_url: string }>('POST', `/v1/projects/${project.project_id}/claim-url`);\n // Persist the new link so subsequent `glass claim` shows it without reissuing.\n writeProject({ ...project, claim_url: res.claim_url });\n return ok({ ...res, reissued: true }, () => process.stdout.write(`Claim URL (reissued):\\n ${res.claim_url}\\n`));\n}\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));\n\n/**\n * `glass login` (`CLI.md` §2). `--token <session>` stores a session directly\n * (CI/non-interactive); otherwise runs the OAuth-style device flow: start a\n * grant, print the verification URL + short user-code, then poll until a\n * signed-in human approves it in the dashboard.\n */\nexport async function login(flags: Flags): Promise<never> {\n const apiHost = (flags['api-host'] as string) ?? readProject()?.api_host ?? 'https://api.glass.dev';\n\n // Non-interactive path: store an explicitly-provided session.\n const provided = flags.token as string | undefined;\n if (provided) {\n const creds = readCredentials();\n creds.session = provided;\n writeCredentials(creds);\n return ok({ message: 'Logged in. Session stored in ~/.glass/credentials.json' }, () =>\n process.stdout.write('Logged in. Session stored in ~/.glass/credentials.json\\n'),\n );\n }\n\n // The device flow needs a human to approve in a browser; in non-interactive\n // mode (`--no-input`/`--yes`, or CI) fail fast and ask for a token instead.\n if (flags['no-input'] === true || flags.yes === true || (!process.stdin.isTTY && !process.stdout.isTTY)) {\n return fail(ExitCode.AUTH, 'login is interactive — pass `--token <session>` or set GLASS_TOKEN for non-interactive use');\n }\n\n // Device flow.\n const api = new Api(apiHost);\n const grant = await api.request<{\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n interval: number;\n expires_in: number;\n }>('POST', '/v1/cli/device/start');\n\n if (!flags.json) {\n process.stdout.write('\\nTo sign in, open:\\n');\n process.stdout.write(` ${grant.verification_uri_complete ?? grant.verification_uri}\\n\\n`);\n process.stdout.write(`and enter the code: ${grant.user_code}\\n\\n`);\n process.stdout.write('Waiting for approval…\\n');\n }\n\n const deadline = Date.now() + grant.expires_in * 1000;\n const intervalMs = Math.max(1, grant.interval) * 1000;\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n let resp: { session?: string; status?: string } | null = null;\n try {\n resp = await api.request<{ session?: string; status?: string }>('POST', '/v1/cli/device/token', {\n device_code: grant.device_code,\n });\n } catch {\n // 202 (pending) / 410 (expired) surface as request errors depending on the\n // client; treat transient failures as \"keep polling\" until the deadline.\n continue;\n }\n if (resp?.session) {\n const creds = readCredentials();\n creds.session = resp.session;\n writeCredentials(creds);\n return ok({ message: 'Logged in. Session stored in ~/.glass/credentials.json' }, () =>\n process.stdout.write('\\nLogged in. Session stored in ~/.glass/credentials.json\\n'),\n );\n }\n }\n return fail(ExitCode.AUTH, 'device authorization timed out — run `glass login` again');\n}\n\nexport function logout(_flags: Flags): never {\n const creds = readCredentials();\n creds.session = undefined;\n writeCredentials(creds);\n return ok({ message: 'Logged out. Cleared stored session.' }, () => process.stdout.write('Logged out.\\n'));\n}\n\nexport async function whoami(flags: Flags): Promise<never> {\n const project = readProject();\n const token = resolveToken(flags, project?.project_id);\n if (!token) fail(ExitCode.AUTH, 'not logged in — run `glass login` or set GLASS_TOKEN');\n const api = new Api(project?.api_host ?? (flags['api-host'] as string) ?? 'https://api.glass.dev', token, project?.project_id);\n return ok(await api.request('GET', '/v1/me'));\n}\n\n/** Switch the active project in glass.json after verifying access. */\nexport async function link(flags: Flags, positionals: string[] = []): Promise<never> {\n // Accept both `glass link <id>` and `glass link --project <id>`.\n const projectId = (flags.project as string | undefined) ?? positionals[0];\n if (!projectId) fail(ExitCode.USAGE, 'link needs a project id: `glass link <id>`');\n const existing = readProject();\n const apiHost = (flags['api-host'] as string) ?? existing?.api_host ?? 'https://api.glass.dev';\n const token = resolveToken(flags, projectId);\n if (!token) fail(ExitCode.AUTH, 'no credentials — run `glass login` or set GLASS_TOKEN');\n const api = new Api(apiHost, token, projectId);\n const proj = await api.request<{ id: string; publishableKey?: string; ingestHost?: string }>('GET', '/v1/project');\n writeProject({\n project_id: projectId,\n ingest_key: proj.publishableKey ?? existing?.ingest_key ?? '',\n ingest_host: proj.ingestHost ?? existing?.ingest_host ?? 'https://in.glass.dev',\n api_host: apiHost,\n });\n return ok({ linked: projectId }, () => process.stdout.write(`Linked glass.json to ${projectId}.\\n`));\n}\n\n// --- query + sugar ------------------------------------------------------------\n\n/**\n * `glass query` source resolution (`CLI.md` §4): a GlassQuery can come from\n * `--query '<json>'`, `--file/-f <path>`, or stdin (so it composes in a pipe:\n * `cat q.json | glass query --json`). Exactly one source is used, in that order.\n */\nexport async function query(flags: Flags): Promise<never> {\n let raw: string | undefined;\n if (typeof flags.query === 'string' && flags.query) raw = flags.query;\n else if (typeof flags.file === 'string' && flags.file) raw = readFileSync(flags.file, 'utf8');\n else if (!process.stdin.isTTY) raw = readFileSync(0, 'utf8').trim() || undefined;\n\n if (!raw) fail(ExitCode.USAGE, \"query needs --query '<json>', --file <path>, or piped stdin\");\n let parsed: GlassQuery;\n try {\n parsed = JSON.parse(raw) as GlassQuery;\n } catch (e) {\n return fail(ExitCode.USAGE, `query is not valid JSON: ${String((e as Error).message)}`);\n }\n return runQuery(parsed, flags);\n}\n\nexport async function runQuery(query: GlassQuery, flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n const body: Record<string, unknown> = { query, confirm: flags.confirm === true };\n if (flags['max-scan']) {\n // Accept a bare number (legacy: MB) or a unit string (`500MB`, `1GB`).\n const raw = String(flags['max-scan']);\n const bytes = /^[0-9]*\\.?[0-9]+$/.test(raw.trim())\n ? Number(raw) * 1024 * 1024\n : parseBytes(raw);\n if (bytes == null) fail(ExitCode.USAGE, `invalid --max-scan: ${raw} (try 500MB or 1GB)`);\n body.max_scan_bytes = bytes;\n }\n const res = await api.request('POST', '/v1/query', body);\n return ok(res);\n}\n\nfunction parseTime(flags: Flags) {\n return { last: (flags.last as string) ?? '7d' };\n}\n\nexport async function trend(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'trend',\n time: parseTime(flags),\n measure: { aggregate: (flags.aggregate as 'count' | 'unique_users' | 'sum') ?? 'count', ...(flags.event ? { event: flags.event as string } : {}) },\n bucket: (flags.bucket as 'hour' | 'day' | 'week' | 'month') ?? 'day',\n ...(flags.breakdown ? { breakdown: flags.breakdown as string } : {}),\n },\n flags,\n );\n}\n\nexport async function funnel(flags: Flags): Promise<never> {\n const steps = String(flags.steps ?? '').split(',').map((e) => ({ event: e.trim() })).filter((s) => s.event);\n if (flags.id) return runQuery({ v: 1, kind: 'funnel', time: parseTime(flags), definition_id: flags.id as string }, flags);\n if (steps.length < 2) fail(ExitCode.USAGE, 'funnel needs --steps a,b,c (>=2) or --id <definition>');\n return runQuery({ v: 1, kind: 'funnel', time: parseTime(flags), steps, ...(flags.window ? { window: flags.window as string } : {}) }, flags);\n}\n\nexport async function retention(flags: Flags): Promise<never> {\n if (!flags.id) fail(ExitCode.USAGE, 'retention needs --id <definition>');\n return runQuery({ v: 1, kind: 'retention', time: parseTime(flags), definition_id: flags.id as string, return_event: (flags.return as string) ?? '$pageview', periods: Number(flags.periods ?? 8) }, flags);\n}\n\nexport async function segment(flags: Flags): Promise<never> {\n const groupBy = String(flags['group-by'] ?? '').split(',').map((s) => s.trim()).filter(Boolean);\n if (groupBy.length === 0) fail(ExitCode.USAGE, 'segment needs --group-by a,b');\n return runQuery({ v: 1, kind: 'segmentation', time: parseTime(flags), group_by: groupBy, ...(flags.event ? { event: flags.event as string } : {}) }, flags);\n}\n\nexport async function errors(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'errors',\n time: parseTime(flags),\n limit: Number(flags.limit ?? 50),\n ...(flags.group ? { group: flags.group as string } : {}),\n ...(flags.status ? { status: flags.status as 'unresolved' | 'resolved' | 'ignored' } : {}),\n },\n flags,\n );\n}\n\nexport async function replays(flags: Flags): Promise<never> {\n return runQuery(\n {\n v: 1,\n kind: 'replays',\n time: parseTime(flags),\n limit: Number(flags.limit ?? 50),\n ...(flags.user ? { session_filters: [{ property: 'user_id', op: 'eq' as const, value: flags.user as string }] } : {}),\n },\n flags,\n );\n}\n\n// --- define / tokens ----------------------------------------------------------\n\nexport async function define(flags: Flags): Promise<never> {\n const { api } = authedApi(flags);\n\n // `define --list` — show existing definitions.\n if (flags.list) return ok(await api.request('GET', '/v1/definitions'));\n\n // Flag-based sugar: build a spec from flags without writing JSON.\n let spec: unknown;\n if (flags.kind === 'funnel') {\n const steps = String(flags.steps ?? '').split(',').map((e) => ({ event: e.trim() })).filter((s) => s.event);\n if (steps.length < 2) fail(ExitCode.USAGE, 'define --kind funnel needs --steps a,b,c (>=2)');\n spec = { v: 1, kind: 'funnel', name: (flags.name as string) ?? 'funnel', steps, scope: (flags.scope as string) ?? 'within-session', ...(flags.window ? { window: flags.window as string } : {}) };\n } else if (flags.kind === 'metric') {\n spec = { v: 1, kind: 'metric', name: (flags.name as string) ?? 'metric', aggregate: (flags.aggregate as string) ?? 'count', bucket: (flags.bucket as string) ?? 'day', ...(flags.event ? { event: flags.event as string } : {}) };\n } else {\n const raw = flags.file ? readFileSync(flags.file as string, 'utf8') : readFileSync(0, 'utf8');\n spec = JSON.parse(raw);\n }\n const res = await api.request('POST', '/v1/definitions', { spec });\n return ok(res);\n}\n\nexport async function tokens(action: string, flags: Flags, positionals: string[] = []): Promise<never> {\n const { api } = authedApi(flags);\n if (action === 'list') return ok(await api.request('GET', '/v1/tokens'));\n if (action === 'create') {\n let budget: number | undefined;\n if (flags['budget-r2sql']) {\n // Accept human units + an optional `/day` rate suffix (`1GB/day`).\n const parsed = parseBytes(String(flags['budget-r2sql']));\n if (parsed == null) fail(ExitCode.USAGE, `invalid --budget-r2sql: ${flags['budget-r2sql']} (try 1GB/day)`);\n budget = parsed;\n }\n const res = await api.request<{ id: string; token: string; prefix: string }>('POST', '/v1/tokens', {\n name: (flags.name as string) ?? 'agent',\n role: (flags.role as string) ?? 'read',\n ...(budget != null ? { budget_r2sql_bytes_per_day: budget } : {}),\n });\n // The secret is shown ONCE — print it verbatim (not through the redactor).\n return ok(res, () => {\n process.stdout.write(`Created token ${res.id}\\n\\n ${res.token}\\n\\nThis is shown once. Store it now (e.g. as GLASS_TOKEN).\\n`);\n });\n }\n if (action === 'revoke') {\n // Accept both `glass tokens revoke <id>` and `--id <id>`.\n const id = (flags.id as string | undefined) ?? positionals[0];\n if (!id) fail(ExitCode.USAGE, 'tokens revoke needs a token id: `glass tokens revoke <id>`');\n return ok(await api.request('DELETE', `/v1/tokens/${id}`));\n }\n return fail(ExitCode.USAGE, 'tokens <list|create|revoke>');\n}\n","/**\n * Stable, scriptable output (`CLI.md` §5). The CLI is built for agents as much\n * as humans: `--json` emits a uniform envelope and EXIT CODES are stable so a\n * caller can branch on them without parsing prose.\n */\n\nexport const ExitCode = {\n OK: 0,\n ERROR: 1,\n USAGE: 2,\n AUTH: 3,\n COST_GATE: 4,\n BUDGET: 5,\n} as const;\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];\n\ntype OutputFormat = 'human' | 'json' | 'csv' | 'ndjson';\nlet format: OutputFormat = 'human';\nexport function setFormat(f: OutputFormat): void {\n format = f;\n}\n/** Back-compat shim for `--json`. */\nexport function setJsonMode(on: boolean): void {\n if (on) format = 'json';\n}\n\n/** Mask token-like secrets in human output so they're never accidentally logged. */\nconst SECRET_RE =\n /\\b(glass_(?:sk|pt)_[A-Za-z0-9]+)\\b|\\b(eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,})\\b/g;\nexport function redact(text: string): string {\n return text.replace(SECRET_RE, (m) => `${m.slice(0, 12)}…<redacted>`);\n}\n\n/** Flatten an array of flat records to CSV; falls back to JSON for non-tabular data. */\nexport function toCsv(data: unknown): string | null {\n const rows = Array.isArray(data) ? data : extractRows(data);\n if (!rows || rows.length === 0) return null;\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n const esc = (v: unknown) => {\n const s = v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n return /[\",\\n]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n return [\n cols.join(','),\n ...rows.map((r) => cols.map((c) => esc((r as Record<string, unknown>)[c])).join(',')),\n ].join('\\n');\n}\n\n/**\n * Parse a human byte budget into bytes (`CLI.md` §4): accepts plain numbers and\n * unit suffixes (`500MB`, `1GB`, `2 TiB`), with an optional `/day` rate suffix\n * that we strip (the API stores per-day budgets). Returns null on garbage.\n */\nconst BYTE_UNITS: Record<string, number> = {\n b: 1,\n kb: 1e3,\n mb: 1e6,\n gb: 1e9,\n tb: 1e12,\n kib: 1024,\n mib: 1024 ** 2,\n gib: 1024 ** 3,\n tib: 1024 ** 4,\n};\nexport function parseBytes(input: string): number | null {\n const s = input.trim().toLowerCase().replace(/\\/(day|d|hr|hour|h)$/, '');\n const m = /^([0-9]*\\.?[0-9]+)\\s*([a-z]+)?$/.exec(s);\n if (!m) return null;\n const value = Number(m[1]);\n if (!Number.isFinite(value)) return null;\n if (!m[2]) return value; // bare number = bytes\n const unit = BYTE_UNITS[m[2]];\n if (!unit) return null;\n return Math.round(value * unit);\n}\n\n/** Find the first array-of-objects field (e.g. {rows:[...]}, {issues:[...]}). */\nexport function extractRows(data: unknown): Record<string, unknown>[] | null {\n if (Array.isArray(data)) return data as Record<string, unknown>[];\n if (data && typeof data === 'object') {\n for (const v of Object.values(data)) {\n if (Array.isArray(v) && v.every((x) => x && typeof x === 'object'))\n return v as Record<string, unknown>[];\n }\n }\n return null;\n}\n\n/**\n * Render an array of flat records as an aligned ASCII table for human output.\n * Returns null when the data isn't tabular so callers can fall back to JSON.\n */\nexport function humanTable(data: unknown): string | null {\n const rows = extractRows(data);\n if (!rows || rows.length === 0) return null;\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n if (cols.length === 0) return null;\n const cell = (v: unknown) => {\n const s = v == null ? '' : typeof v === 'object' ? JSON.stringify(v) : String(v);\n return redact(s).replace(/\\n/g, ' ');\n };\n const widths = cols.map((c) =>\n Math.max(c.length, ...rows.map((r) => cell((r as Record<string, unknown>)[c]).length)),\n );\n const line = (cells: string[]) => cells.map((s, i) => s.padEnd(widths[i] ?? 0)).join(' ').trimEnd();\n const header = line(cols);\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const body = rows.map((r) => line(cols.map((c) => cell((r as Record<string, unknown>)[c]))));\n return [header, sep, ...body].join('\\n');\n}\n\n/**\n * One-line provenance badge for a query result (`UI.md` ResultBadge parity):\n * surfaces whether a number is exact or sampled, and its source, so an agent\n * reading stdout knows how much to trust it. Returns null when not applicable.\n */\nexport function resultBadge(data: unknown): string | null {\n if (!data || typeof data !== 'object') return null;\n const d = data as Record<string, unknown>;\n if (typeof d.exact !== 'boolean' && !d.source && !d.sampled) return null;\n const parts: string[] = [];\n parts.push(d.exact === false ? 'sampled' : 'exact');\n if (d.source) parts.push(String(d.source));\n const sampled = d.sampled as { interval?: number } | undefined;\n if (sampled?.interval && sampled.interval > 1) parts.push(`1/${sampled.interval}`);\n return `[${parts.join(' · ')}]`;\n}\n\nexport function ok(data: unknown, human?: () => void): never {\n if (format === 'json') {\n process.stdout.write(`${JSON.stringify({ ok: true, data }, null, 2)}\\n`);\n } else if (format === 'ndjson') {\n const rows = extractRows(data) ?? [data];\n for (const r of rows) process.stdout.write(`${JSON.stringify(r)}\\n`);\n } else if (format === 'csv') {\n const csv = toCsv(data);\n process.stdout.write(csv ? `${csv}\\n` : `${JSON.stringify(data, null, 2)}\\n`);\n } else if (human) {\n human();\n } else {\n const table = humanTable(data);\n if (table) {\n const badge = resultBadge(data);\n process.stdout.write(`${table}\\n`);\n if (badge) process.stdout.write(`${badge}\\n`);\n } else {\n process.stdout.write(`${redact(JSON.stringify(data, null, 2))}\\n`);\n }\n }\n process.exit(ExitCode.OK);\n}\n\nexport function fail(code: ExitCodeValue, message: string, extra?: unknown): never {\n if (format === 'json' || format === 'ndjson') {\n process.stdout.write(\n `${JSON.stringify({ ok: false, error: { code, message, ...(extra ? { extra } : {}) } }, null, 2)}\\n`,\n );\n } else {\n process.stderr.write(`glass: ${message}\\n`);\n if (extra) process.stderr.write(`${redact(JSON.stringify(extra, null, 2))}\\n`);\n }\n process.exit(code);\n}\n","import { ExitCode, fail } from './output.js';\n\n/**\n * Thin control-plane client. Maps HTTP status to the CLI's stable exit codes so\n * `--json` callers (agents) can branch deterministically (`CLI.md` §5):\n * 401/403 → AUTH(3), 402 → COST_GATE(4), 429 → BUDGET(5).\n */\nexport class Api {\n constructor(\n private apiHost: string,\n private token?: string,\n private projectId?: string,\n ) {}\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.token) headers.Authorization = `Bearer ${this.token}`;\n if (this.projectId) headers['X-Glass-Project'] = this.projectId;\n\n const res = await fetch(`${this.apiHost}${path}`, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n }).catch((e) => fail(ExitCode.ERROR, `network error: ${String(e)}`));\n\n const text = await res.text();\n const json = text ? (JSON.parse(text) as T) : ({} as T);\n\n if (res.status === 401 || res.status === 403) fail(ExitCode.AUTH, 'unauthorized', json);\n if (res.status === 402) fail(ExitCode.COST_GATE, 'cost gate: re-run with --confirm', json);\n if (res.status === 429) fail(ExitCode.BUDGET, 'budget or rate limit exceeded', json);\n if (!res.ok) fail(ExitCode.ERROR, `request failed (${res.status})`, json);\n return json;\n }\n}\n","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\n/**\n * Local config (`CLI.md` §2/§3). Project pointer in `glass.json` (committable,\n * contains only the write-only publishable key); SECRETS in\n * `~/.glass/credentials.json` with `0600` perms, never in the repo.\n */\n\nexport interface ProjectFile {\n project_id: string;\n ingest_key: string;\n ingest_host: string;\n api_host: string;\n /** The claim URL minted at provisioning (single-use); shown by `glass claim`. */\n claim_url?: string;\n}\n\nexport interface Credentials {\n /** provisioning/agent tokens keyed by project_id. */\n tokens: Record<string, string>;\n /** Clerk session from `glass login` (device flow). */\n session?: string;\n}\n\nconst PROJECT_FILE = join(process.cwd(), 'glass.json');\nconst CRED_FILE = join(homedir(), '.glass', 'credentials.json');\n\n/**\n * Read the project pointer, with environment overrides layered on top\n * (`CLI.md` §2): `GLASS_PROJECT` selects/overrides the project id and\n * `GLASS_INGEST_KEY` the publishable key — so CI can run without a committed\n * `glass.json`. If neither the file nor `GLASS_PROJECT` is present, returns null.\n */\nexport function readProject(): ProjectFile | null {\n let file: ProjectFile | null = null;\n try {\n file = JSON.parse(readFileSync(PROJECT_FILE, 'utf8')) as ProjectFile;\n } catch {\n file = null;\n }\n\n const envProject = process.env.GLASS_PROJECT;\n const envIngest = process.env.GLASS_INGEST_KEY;\n if (!file && !envProject) return null;\n\n return {\n project_id: envProject ?? file?.project_id ?? '',\n ingest_key: envIngest ?? file?.ingest_key ?? '',\n ingest_host: process.env.GLASS_INGEST_HOST ?? file?.ingest_host ?? 'https://in.glass.dev',\n api_host: process.env.GLASS_API_HOST ?? file?.api_host ?? 'https://api.glass.dev',\n ...(file?.claim_url ? { claim_url: file.claim_url } : {}),\n };\n}\n\nexport function writeProject(p: ProjectFile): void {\n writeFileSync(PROJECT_FILE, `${JSON.stringify(p, null, 2)}\\n`);\n}\n\nexport function readCredentials(): Credentials {\n try {\n return JSON.parse(readFileSync(CRED_FILE, 'utf8')) as Credentials;\n } catch {\n return { tokens: {} };\n }\n}\n\nexport function writeCredentials(c: Credentials): void {\n mkdirSync(dirname(CRED_FILE), { recursive: true, mode: 0o700 });\n writeFileSync(CRED_FILE, `${JSON.stringify(c, null, 2)}\\n`, { mode: 0o600 });\n chmodSync(CRED_FILE, 0o600); // enforce even if the file pre-existed\n}\n\nexport function tokenFor(projectId: string): string | undefined {\n return readCredentials().tokens[projectId];\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","dirname","readFileSync","dirname","writeFileSync","query"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassanalytics/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Glass CLI — zero-auth provisioning, SDK install, and typed querying from the terminal. Agent-friendly: --json + stable exit codes.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",