@rawdash/cli 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.js.map +1 -1
  2. package/package.json +1 -1
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/commands/deploy.ts","../src/lib/cloud-config.ts","../src/lib/env.ts","../src/lib/api-client.ts","../src/lib/config-loader.ts","../src/lib/output.ts","../src/commands/secrets.ts","../src/commands/validate.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { deployCommand } from './commands/deploy';\nimport { secretsCommand } from './commands/secrets';\nimport { validateCommand } from './commands/validate';\n\nconst pkg = JSON.parse(\n readFileSync(\n join(dirname(fileURLToPath(import.meta.url)), '../package.json'),\n 'utf8',\n ),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('rawdash')\n .description('Rawdash CLI — deploy and manage your dashboard config')\n .version(pkg.version);\n\nprogram.addCommand(deployCommand);\nprogram.addCommand(secretsCommand);\nprogram.addCommand(validateCommand);\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n","import { confirm, isCancel, spinner } from '@clack/prompts';\nimport { Command } from 'commander';\n\nimport { postConfig } from '../lib/api-client';\nimport { findConfigFile, loadConfig } from '../lib/config-loader';\nimport { requireApiKey } from '../lib/env';\nimport { printDiff, printError, printSuccess } from '../lib/output';\n\nexport const deployCommand = new Command('deploy')\n .description('Deploy rawdash.config.ts to the server')\n .option('--config <path>', 'path to rawdash.config.ts')\n .option('--dry-run', 'validate and diff without persisting')\n .option('--yes', 'skip confirmation prompt (useful in CI)')\n .action(\n async (opts: { config?: string; dryRun?: boolean; yes?: boolean }) => {\n requireApiKey();\n\n const configPath = await findConfigFile(opts.config).catch(\n (err: unknown) => {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n },\n );\n\n const s = spinner();\n s.start('Loading config...');\n\n const config = await loadConfig(configPath).catch((err: unknown) => {\n s.stop('Failed to load config');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n });\n s.stop('Config loaded');\n\n s.start('Fetching diff...');\n const previewResult = await postConfig(config, true);\n s.stop('');\n\n if (!previewResult.ok) {\n printError(previewResult.error);\n process.exit(exitCodeForStatus(previewResult.status));\n }\n\n printDiff(previewResult.diff);\n\n if (opts.dryRun) {\n printSuccess('Dry run complete — no changes applied');\n return;\n }\n\n if (!opts.yes) {\n const confirmed = await confirm({ message: 'Apply this diff?' });\n if (isCancel(confirmed) || !confirmed) {\n console.log('Aborted.');\n process.exit(0);\n }\n }\n\n s.start('Deploying...');\n const deployResult = await postConfig(config, false);\n s.stop('');\n\n if (!deployResult.ok) {\n printError(deployResult.error);\n process.exit(exitCodeForStatus(deployResult.status));\n }\n\n printSuccess('Deployed');\n },\n );\n\nfunction exitCodeForStatus(status: number): number {\n if (status === 401 || status === 403) {\n return 3;\n }\n if (status === 409) {\n return 4;\n }\n if (status === 422) {\n return 2;\n }\n return 1;\n}\n","import type { DashboardConfig } from '@rawdash/core';\n\nexport interface CloudConnector {\n name: string;\n connectorId: string;\n displayName?: string;\n config: Record<string, unknown>;\n syncIntervalSeconds?: number;\n enabled?: boolean;\n}\n\nexport interface CloudDashboard {\n id?: string;\n name: string;\n slug: string;\n config: Record<string, unknown>;\n}\n\nexport interface CloudConfigBody {\n connectors?: CloudConnector[];\n dashboards?: CloudDashboard[];\n}\n\nexport function toCloudConfig(ossConfig: DashboardConfig): CloudConfigBody {\n return {\n connectors: ossConfig.connectors.map(({ connector }) => ({\n name: connector.id,\n connectorId: connector.id,\n displayName: connector.id,\n config: connector.serializeConfig(),\n syncIntervalSeconds: 300,\n enabled: true,\n })),\n dashboards: Object.entries(ossConfig.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n","export function getEnv(): { url: string; apiKey: string | undefined } {\n return {\n url: process.env['RAWDASH_URL'] ?? 'https://api.rawdash.dev',\n apiKey: process.env['RAWDASH_API_KEY'],\n };\n}\n\nexport function requireApiKey(): string {\n const { apiKey } = getEnv();\n if (!apiKey) {\n console.error('RAWDASH_API_KEY is not set. Set it in your environment.');\n process.exit(3);\n }\n return apiKey;\n}\n","import type { DashboardConfig } from '@rawdash/core';\n\nimport { toCloudConfig } from './cloud-config';\nimport { getEnv } from './env';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface DiffSet<T> {\n added: T[];\n removed: T[];\n modified: T[];\n}\n\nexport interface CloudConnectorEntry {\n name: string;\n connectorId: string;\n displayName?: string | null;\n config: Record<string, unknown>;\n syncIntervalSeconds?: number;\n enabled?: boolean;\n}\n\nexport interface CloudDashboardEntry {\n id: string;\n name: string;\n slug: string;\n config: Record<string, unknown>;\n}\n\nexport interface ConfigDiff {\n connectors: DiffSet<CloudConnectorEntry>;\n dashboards: DiffSet<CloudDashboardEntry>;\n}\n\nexport interface DeploySuccess {\n ok: true;\n diff: ConfigDiff;\n}\n\nexport interface DeployFailure {\n ok: false;\n error: string;\n status: number;\n conflicts?: string[];\n}\n\nexport type DeployResult = DeploySuccess | DeployFailure;\n\nexport interface SecretEntry {\n name: string;\n lastRotatedAt: string | null;\n}\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function postConfig(\n config: DashboardConfig,\n dryRun: boolean,\n): Promise<DeployResult> {\n const { url, apiKey } = getEnv();\n const endpoint = `${url}/config${dryRun ? '?dryRun=true' : ''}`;\n\n let res: Response;\n try {\n res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey ?? ''}`,\n },\n body: JSON.stringify(toCloudConfig(config)),\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error &&\n (err.name === 'AbortError' || err.name === 'TimeoutError');\n return {\n ok: false,\n error: isTimeout\n ? 'Request timed out'\n : `Network error: ${err instanceof Error ? err.message : String(err)}`,\n status: 0,\n };\n }\n\n if (res.ok) {\n const diff = (await res.json()) as ConfigDiff;\n return { ok: true, diff };\n }\n\n return buildDeployFailure(res);\n}\n\nasync function buildDeployFailure(res: Response): Promise<DeployFailure> {\n const { body, text } = await readErrorBody(res);\n const rawMessage = body.error ?? body.message ?? (text || res.statusText);\n\n let error: string;\n if (res.status === 401) {\n error = `API key invalid or revoked. Check RAWDASH_API_KEY. (${rawMessage})`;\n } else if (res.status === 403) {\n error = `Key lacks config:write scope. Get a new key with broader scope. (${rawMessage})`;\n } else if (res.status === 409) {\n error = `Org is in ui source-of-truth mode. Switch to git mode in cloud settings, or push UI changes back into your config first.`;\n } else if (res.status === 422) {\n error = `Validation failed: ${rawMessage}`;\n } else {\n error = `Request failed (${res.status}): ${rawMessage}`;\n }\n\n return { ok: false, error, status: res.status, conflicts: body.conflicts };\n}\n\nexport async function setSecret(name: string, value: string): Promise<void> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey ?? ''}`,\n },\n body: JSON.stringify({ name, value }),\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n}\n\nexport async function listSecrets(): Promise<SecretEntry[]> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets`, {\n headers: { Authorization: `Bearer ${apiKey ?? ''}` },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n const body = (await res.json()) as { secrets: SecretEntry[] };\n return body.secrets;\n}\n\nexport async function removeSecret(name: string): Promise<void> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets/${encodeURIComponent(name)}`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${apiKey ?? ''}` },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n}\n\nfunction wrapFetchError(err: unknown): string {\n if (\n err instanceof Error &&\n (err.name === 'AbortError' || err.name === 'TimeoutError')\n ) {\n return 'Request timed out';\n }\n return `Network error: ${err instanceof Error ? err.message : String(err)}`;\n}\n\nasync function throwApiError(res: Response): Promise<never> {\n const { body, text } = await readErrorBody(res);\n const message = body.error ?? body.message ?? (text || res.statusText);\n throw new ApiError(`API error (${res.status}): ${message}`, res.status);\n}\n\nasync function readErrorBody(res: Response): Promise<{\n body: { error?: string; message?: string; conflicts?: string[] };\n text: string;\n}> {\n const text = await res.text();\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n try {\n return {\n body: JSON.parse(text) as {\n error?: string;\n message?: string;\n conflicts?: string[];\n },\n text,\n };\n } catch {\n // body claimed JSON but wasn't — fall through to text\n }\n }\n return { body: {}, text };\n}\n","import { type DashboardConfig, defineConfig } from '@rawdash/core';\nimport { existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { tsImport } from 'tsx/esm/api';\n\nexport async function findConfigFile(explicitPath?: string): Promise<string> {\n if (explicitPath) {\n const abs = resolve(explicitPath);\n if (!existsSync(abs)) {\n throw new Error(`Config file not found: ${abs}`);\n }\n return abs;\n }\n\n let dir = process.cwd();\n for (;;) {\n const candidate = join(dir, 'rawdash.config.ts');\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n break;\n }\n dir = parent;\n }\n\n throw new Error(\n 'Could not find rawdash.config.ts. Pass --config <path> to specify it explicitly.',\n );\n}\n\nexport async function loadConfig(configPath: string): Promise<DashboardConfig> {\n const mod = await tsImport(configPath, import.meta.url);\n const config: unknown =\n (mod as { default?: unknown; config?: unknown }).default ??\n (mod as { config?: unknown }).config;\n if (!config || typeof config !== 'object') {\n throw new Error(\n `${configPath} must export a default config (result of defineConfig())`,\n );\n }\n return defineConfig(config as Parameters<typeof defineConfig>[0]);\n}\n","import pc from 'picocolors';\n\nimport type {\n CloudConnectorEntry,\n CloudDashboardEntry,\n ConfigDiff,\n DiffSet,\n} from './api-client';\n\nexport function printDiff(diff: ConfigDiff): void {\n printDiffSection('Connectors', diff.connectors, (c) => c.name);\n printDiffSection('Dashboards', diff.dashboards, (d) => d.slug);\n}\n\nfunction printDiffSection<T extends CloudConnectorEntry | CloudDashboardEntry>(\n label: string,\n diff: DiffSet<T>,\n getName: (t: T) => string,\n): void {\n if (\n diff.added.length === 0 &&\n diff.modified.length === 0 &&\n diff.removed.length === 0\n ) {\n console.log(pc.dim(` ${label}: no changes`));\n return;\n }\n console.log(pc.bold(` ${label}:`));\n for (const item of diff.added) {\n console.log(pc.green(` + ${getName(item)}`));\n }\n for (const item of diff.modified) {\n console.log(pc.yellow(` ~ ${getName(item)}`));\n }\n for (const item of diff.removed) {\n console.log(pc.red(` - ${getName(item)}`));\n }\n}\n\nexport function printError(message: string): void {\n console.error(pc.red(`✗ ${message}`));\n}\n\nexport function printSuccess(message: string): void {\n console.log(pc.green(`✓ ${message}`));\n}\n","import { spinner } from '@clack/prompts';\nimport { Command } from 'commander';\n\nimport {\n ApiError,\n listSecrets,\n removeSecret,\n setSecret,\n} from '../lib/api-client';\nimport { requireApiKey } from '../lib/env';\nimport { printError, printSuccess } from '../lib/output';\n\nexport const secretsCommand = new Command('secrets').description(\n 'Manage secrets',\n);\n\nsecretsCommand\n .command('set <name> [value]')\n .description('Set a secret (reads value from stdin if not provided)')\n .action(async (name: string, value?: string) => {\n requireApiKey();\n\n let secretValue = value;\n if (secretValue === undefined) {\n secretValue = await readStdin();\n if (!secretValue) {\n printError('No value provided. Pass as argument or via stdin.');\n process.exit(1);\n }\n }\n\n const s = spinner();\n s.start(`Setting secret ${name}...`);\n try {\n await setSecret(name, secretValue);\n s.stop('');\n printSuccess(`Secret ${name} set`);\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nsecretsCommand\n .command('list')\n .description('List all secrets (names and last-rotated timestamps)')\n .action(async () => {\n requireApiKey();\n\n const s = spinner();\n s.start('Fetching secrets...');\n try {\n const secrets = await listSecrets();\n s.stop('');\n if (secrets.length === 0) {\n console.log('No secrets configured.');\n return;\n }\n for (const { name, lastRotatedAt } of secrets) {\n const ts = lastRotatedAt\n ? new Date(lastRotatedAt).toLocaleString()\n : 'never';\n console.log(` ${name} (last rotated: ${ts})`);\n }\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nsecretsCommand\n .command('remove <name>')\n .description('Remove a secret')\n .action(async (name: string) => {\n requireApiKey();\n\n const s = spinner();\n s.start(`Removing secret ${name}...`);\n try {\n await removeSecret(name);\n s.stop('');\n printSuccess(`Secret ${name} removed`);\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n process.stdin.on('data', (chunk: Buffer) => chunks.push(chunk));\n process.stdin.on('end', () =>\n resolve(Buffer.concat(chunks).toString('utf8')),\n );\n process.stdin.on('error', reject);\n });\n}\n\nfunction authExitCode(err: unknown): number {\n if (err instanceof ApiError && (err.status === 401 || err.status === 403)) {\n return 3;\n }\n return 1;\n}\n","import { Command } from 'commander';\n\nimport { findConfigFile, loadConfig } from '../lib/config-loader';\nimport { printError, printSuccess } from '../lib/output';\n\nexport const validateCommand = new Command('validate')\n .description('Validate rawdash.config.ts locally without network access')\n .option('--config <path>', 'path to rawdash.config.ts')\n .action(async (opts: { config?: string }) => {\n const configPath = await findConfigFile(opts.config).catch(\n (err: unknown) => {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n },\n );\n\n try {\n const config = await loadConfig(configPath);\n console.log(JSON.stringify(config, null, 2));\n printSuccess('Config is valid');\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n }\n });\n"],"mappings":"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","names":["Command","dirname","join","spinner","Command","Command","spinner","resolve","Command","Command","join","dirname","Command"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/commands/deploy.ts","../src/lib/cloud-config.ts","../src/lib/env.ts","../src/lib/api-client.ts","../src/lib/config-loader.ts","../src/lib/output.ts","../src/commands/secrets.ts","../src/commands/validate.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { deployCommand } from './commands/deploy';\nimport { secretsCommand } from './commands/secrets';\nimport { validateCommand } from './commands/validate';\n\nconst pkg = JSON.parse(\n readFileSync(\n join(dirname(fileURLToPath(import.meta.url)), '../package.json'),\n 'utf8',\n ),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name('rawdash')\n .description('Rawdash CLI — deploy and manage your dashboard config')\n .version(pkg.version);\n\nprogram.addCommand(deployCommand);\nprogram.addCommand(secretsCommand);\nprogram.addCommand(validateCommand);\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n","import { confirm, isCancel, spinner } from '@clack/prompts';\nimport { Command } from 'commander';\n\nimport { postConfig } from '../lib/api-client';\nimport { findConfigFile, loadConfig } from '../lib/config-loader';\nimport { requireApiKey } from '../lib/env';\nimport { printDiff, printError, printSuccess } from '../lib/output';\n\nexport const deployCommand = new Command('deploy')\n .description('Deploy rawdash.config.ts to the server')\n .option('--config <path>', 'path to rawdash.config.ts')\n .option('--dry-run', 'validate and diff without persisting')\n .option('--yes', 'skip confirmation prompt (useful in CI)')\n .action(\n async (opts: { config?: string; dryRun?: boolean; yes?: boolean }) => {\n requireApiKey();\n\n const configPath = await findConfigFile(opts.config).catch(\n (err: unknown) => {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n },\n );\n\n const s = spinner();\n s.start('Loading config...');\n\n const config = await loadConfig(configPath).catch((err: unknown) => {\n s.stop('Failed to load config');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n });\n s.stop('Config loaded');\n\n s.start('Fetching diff...');\n const previewResult = await postConfig(config, true);\n s.stop('');\n\n if (!previewResult.ok) {\n printError(previewResult.error);\n process.exit(exitCodeForStatus(previewResult.status));\n }\n\n printDiff(previewResult.diff);\n\n if (opts.dryRun) {\n printSuccess('Dry run complete — no changes applied');\n return;\n }\n\n if (!opts.yes) {\n const confirmed = await confirm({ message: 'Apply this diff?' });\n if (isCancel(confirmed) || !confirmed) {\n console.log('Aborted.');\n process.exit(0);\n }\n }\n\n s.start('Deploying...');\n const deployResult = await postConfig(config, false);\n s.stop('');\n\n if (!deployResult.ok) {\n printError(deployResult.error);\n process.exit(exitCodeForStatus(deployResult.status));\n }\n\n printSuccess('Deployed');\n },\n );\n\nfunction exitCodeForStatus(status: number): number {\n if (status === 401 || status === 403) {\n return 3;\n }\n if (status === 409) {\n return 4;\n }\n if (status === 422) {\n return 2;\n }\n return 1;\n}\n","import type { DashboardConfig } from '@rawdash/core';\n\nexport interface CloudConnector {\n name: string;\n connectorId: string;\n displayName?: string;\n config: Record<string, unknown>;\n syncIntervalSeconds?: number;\n enabled?: boolean;\n}\n\nexport interface CloudDashboard {\n id?: string;\n name: string;\n slug: string;\n config: Record<string, unknown>;\n}\n\nexport interface CloudConfig {\n connectors?: CloudConnector[];\n dashboards?: CloudDashboard[];\n}\n\nexport function toCloudConfig(ossConfig: DashboardConfig): CloudConfig {\n return {\n connectors: ossConfig.connectors.map(({ connector }) => ({\n name: connector.id,\n connectorId: connector.id,\n displayName: connector.id,\n config: connector.serializeConfig(),\n syncIntervalSeconds: 300,\n enabled: true,\n })),\n dashboards: Object.entries(ossConfig.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n","export function getEnv(): { url: string; apiKey: string | undefined } {\n return {\n url: process.env['RAWDASH_URL'] ?? 'https://api.rawdash.dev',\n apiKey: process.env['RAWDASH_API_KEY'],\n };\n}\n\nexport function requireApiKey(): string {\n const { apiKey } = getEnv();\n if (!apiKey) {\n console.error('RAWDASH_API_KEY is not set. Set it in your environment.');\n process.exit(3);\n }\n return apiKey;\n}\n","import type { DashboardConfig } from '@rawdash/core';\n\nimport { toCloudConfig } from './cloud-config';\nimport { getEnv } from './env';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface Diff<T> {\n added: T[];\n removed: T[];\n modified: T[];\n}\n\nexport interface CloudConnectorRecord {\n name: string;\n connectorId: string;\n displayName?: string | null;\n config: Record<string, unknown>;\n syncIntervalSeconds?: number;\n enabled?: boolean;\n}\n\nexport interface CloudDashboardRecord {\n id: string;\n name: string;\n slug: string;\n config: Record<string, unknown>;\n}\n\nexport interface ConfigDiff {\n connectors: Diff<CloudConnectorRecord>;\n dashboards: Diff<CloudDashboardRecord>;\n}\n\nexport interface DeploySuccess {\n ok: true;\n diff: ConfigDiff;\n}\n\nexport interface DeployFailure {\n ok: false;\n error: string;\n status: number;\n conflicts?: string[];\n}\n\nexport type DeployResult = DeploySuccess | DeployFailure;\n\nexport interface CloudSecret {\n name: string;\n lastRotatedAt: string | null;\n}\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function postConfig(\n config: DashboardConfig,\n dryRun: boolean,\n): Promise<DeployResult> {\n const { url, apiKey } = getEnv();\n const endpoint = `${url}/config${dryRun ? '?dryRun=true' : ''}`;\n\n let res: Response;\n try {\n res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey ?? ''}`,\n },\n body: JSON.stringify(toCloudConfig(config)),\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error &&\n (err.name === 'AbortError' || err.name === 'TimeoutError');\n return {\n ok: false,\n error: isTimeout\n ? 'Request timed out'\n : `Network error: ${err instanceof Error ? err.message : String(err)}`,\n status: 0,\n };\n }\n\n if (res.ok) {\n const diff = (await res.json()) as ConfigDiff;\n return { ok: true, diff };\n }\n\n return buildDeployFailure(res);\n}\n\nasync function buildDeployFailure(res: Response): Promise<DeployFailure> {\n const { body, text } = await readErrorBody(res);\n const rawMessage = body.error ?? body.message ?? (text || res.statusText);\n\n let error: string;\n if (res.status === 401) {\n error = `API key invalid or revoked. Check RAWDASH_API_KEY. (${rawMessage})`;\n } else if (res.status === 403) {\n error = `Key lacks config:write scope. Get a new key with broader scope. (${rawMessage})`;\n } else if (res.status === 409) {\n error = `Org is in ui source-of-truth mode. Switch to git mode in cloud settings, or push UI changes back into your config first.`;\n } else if (res.status === 422) {\n error = `Validation failed: ${rawMessage}`;\n } else {\n error = `Request failed (${res.status}): ${rawMessage}`;\n }\n\n return { ok: false, error, status: res.status, conflicts: body.conflicts };\n}\n\nexport async function setSecret(name: string, value: string): Promise<void> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey ?? ''}`,\n },\n body: JSON.stringify({ name, value }),\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n}\n\nexport async function listSecrets(): Promise<CloudSecret[]> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets`, {\n headers: { Authorization: `Bearer ${apiKey ?? ''}` },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n const body = (await res.json()) as { secrets: CloudSecret[] };\n return body.secrets;\n}\n\nexport async function removeSecret(name: string): Promise<void> {\n const { url, apiKey } = getEnv();\n\n let res: Response;\n try {\n res = await fetch(`${url}/secrets/${encodeURIComponent(name)}`, {\n method: 'DELETE',\n headers: { Authorization: `Bearer ${apiKey ?? ''}` },\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n } catch (err) {\n throw new ApiError(wrapFetchError(err), 0);\n }\n\n if (!res.ok) {\n await throwApiError(res);\n }\n}\n\nfunction wrapFetchError(err: unknown): string {\n if (\n err instanceof Error &&\n (err.name === 'AbortError' || err.name === 'TimeoutError')\n ) {\n return 'Request timed out';\n }\n return `Network error: ${err instanceof Error ? err.message : String(err)}`;\n}\n\nasync function throwApiError(res: Response): Promise<never> {\n const { body, text } = await readErrorBody(res);\n const message = body.error ?? body.message ?? (text || res.statusText);\n throw new ApiError(`API error (${res.status}): ${message}`, res.status);\n}\n\nasync function readErrorBody(res: Response): Promise<{\n body: { error?: string; message?: string; conflicts?: string[] };\n text: string;\n}> {\n const text = await res.text();\n const contentType = res.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n try {\n return {\n body: JSON.parse(text) as {\n error?: string;\n message?: string;\n conflicts?: string[];\n },\n text,\n };\n } catch {\n // body claimed JSON but wasn't — fall through to text\n }\n }\n return { body: {}, text };\n}\n","import { type DashboardConfig, defineConfig } from '@rawdash/core';\nimport { existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { tsImport } from 'tsx/esm/api';\n\nexport async function findConfigFile(explicitPath?: string): Promise<string> {\n if (explicitPath) {\n const abs = resolve(explicitPath);\n if (!existsSync(abs)) {\n throw new Error(`Config file not found: ${abs}`);\n }\n return abs;\n }\n\n let dir = process.cwd();\n for (;;) {\n const candidate = join(dir, 'rawdash.config.ts');\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n break;\n }\n dir = parent;\n }\n\n throw new Error(\n 'Could not find rawdash.config.ts. Pass --config <path> to specify it explicitly.',\n );\n}\n\nexport async function loadConfig(configPath: string): Promise<DashboardConfig> {\n const mod = await tsImport(configPath, import.meta.url);\n const config: unknown =\n (mod as { default?: unknown; config?: unknown }).default ??\n (mod as { config?: unknown }).config;\n if (!config || typeof config !== 'object') {\n throw new Error(\n `${configPath} must export a default config (result of defineConfig())`,\n );\n }\n return defineConfig(config as Parameters<typeof defineConfig>[0]);\n}\n","import pc from 'picocolors';\n\nimport type {\n CloudConnectorRecord,\n CloudDashboardRecord,\n ConfigDiff,\n Diff,\n} from './api-client';\n\nexport function printDiff(diff: ConfigDiff): void {\n printDiffSection('Connectors', diff.connectors, (c) => c.name);\n printDiffSection('Dashboards', diff.dashboards, (d) => d.slug);\n}\n\nfunction printDiffSection<\n T extends CloudConnectorRecord | CloudDashboardRecord,\n>(label: string, diff: Diff<T>, getName: (t: T) => string): void {\n if (\n diff.added.length === 0 &&\n diff.modified.length === 0 &&\n diff.removed.length === 0\n ) {\n console.log(pc.dim(` ${label}: no changes`));\n return;\n }\n console.log(pc.bold(` ${label}:`));\n for (const item of diff.added) {\n console.log(pc.green(` + ${getName(item)}`));\n }\n for (const item of diff.modified) {\n console.log(pc.yellow(` ~ ${getName(item)}`));\n }\n for (const item of diff.removed) {\n console.log(pc.red(` - ${getName(item)}`));\n }\n}\n\nexport function printError(message: string): void {\n console.error(pc.red(`✗ ${message}`));\n}\n\nexport function printSuccess(message: string): void {\n console.log(pc.green(`✓ ${message}`));\n}\n","import { spinner } from '@clack/prompts';\nimport { Command } from 'commander';\n\nimport {\n ApiError,\n listSecrets,\n removeSecret,\n setSecret,\n} from '../lib/api-client';\nimport { requireApiKey } from '../lib/env';\nimport { printError, printSuccess } from '../lib/output';\n\nexport const secretsCommand = new Command('secrets').description(\n 'Manage secrets',\n);\n\nsecretsCommand\n .command('set <name> [value]')\n .description('Set a secret (reads value from stdin if not provided)')\n .action(async (name: string, value?: string) => {\n requireApiKey();\n\n let secretValue = value;\n if (secretValue === undefined) {\n secretValue = await readStdin();\n if (!secretValue) {\n printError('No value provided. Pass as argument or via stdin.');\n process.exit(1);\n }\n }\n\n const s = spinner();\n s.start(`Setting secret ${name}...`);\n try {\n await setSecret(name, secretValue);\n s.stop('');\n printSuccess(`Secret ${name} set`);\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nsecretsCommand\n .command('list')\n .description('List all secrets (names and last-rotated timestamps)')\n .action(async () => {\n requireApiKey();\n\n const s = spinner();\n s.start('Fetching secrets...');\n try {\n const secrets = await listSecrets();\n s.stop('');\n if (secrets.length === 0) {\n console.log('No secrets configured.');\n return;\n }\n for (const { name, lastRotatedAt } of secrets) {\n const ts = lastRotatedAt\n ? new Date(lastRotatedAt).toLocaleString()\n : 'never';\n console.log(` ${name} (last rotated: ${ts})`);\n }\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nsecretsCommand\n .command('remove <name>')\n .description('Remove a secret')\n .action(async (name: string) => {\n requireApiKey();\n\n const s = spinner();\n s.start(`Removing secret ${name}...`);\n try {\n await removeSecret(name);\n s.stop('');\n printSuccess(`Secret ${name} removed`);\n } catch (err) {\n s.stop('');\n printError(err instanceof Error ? err.message : String(err));\n process.exit(authExitCode(err));\n }\n });\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n process.stdin.on('data', (chunk: Buffer) => chunks.push(chunk));\n process.stdin.on('end', () =>\n resolve(Buffer.concat(chunks).toString('utf8')),\n );\n process.stdin.on('error', reject);\n });\n}\n\nfunction authExitCode(err: unknown): number {\n if (err instanceof ApiError && (err.status === 401 || err.status === 403)) {\n return 3;\n }\n return 1;\n}\n","import { Command } from 'commander';\n\nimport { findConfigFile, loadConfig } from '../lib/config-loader';\nimport { printError, printSuccess } from '../lib/output';\n\nexport const validateCommand = new Command('validate')\n .description('Validate rawdash.config.ts locally without network access')\n .option('--config <path>', 'path to rawdash.config.ts')\n .action(async (opts: { config?: string }) => {\n const configPath = await findConfigFile(opts.config).catch(\n (err: unknown) => {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n },\n );\n\n try {\n const config = await loadConfig(configPath);\n console.log(JSON.stringify(config, null, 2));\n printSuccess('Config is valid');\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n process.exit(2);\n }\n });\n"],"mappings":"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","names":["Command","dirname","join","spinner","Command","Command","spinner","resolve","Command","Command","join","dirname","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawdash/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Rawdash CLI — deploy and manage your dashboard config",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",