datavessel-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * `config` and `sync` commands.
3
+ *
4
+ * `config` manages non-secret per-profile settings (base URL, default
5
+ * profile). `sync` force-refreshes the local tool catalog cache.
6
+ */
7
+ import { buildContext, globalOpts } from '../context.js';
8
+ import { refreshCatalog } from '../catalog.js';
9
+ import { DEFAULT_BASE_URL, configDir, listProfiles, resolveConfig, resolveProfileName, setAppUrl, setBaseUrl, setDefaultProfile, } from '../config.js';
10
+ import { CliError, ExitCode } from '../errors.js';
11
+ import { printJson, success, info, table, c } from '../output.js';
12
+ export function registerConfigCommands(program) {
13
+ const config = program.command('config').description('Manage CLI configuration');
14
+ config
15
+ .command('show')
16
+ .description('Show the resolved configuration for the active profile')
17
+ .action((_opts, cmd) => {
18
+ const global = globalOpts(cmd);
19
+ const resolved = resolveConfig(global.profile);
20
+ const data = {
21
+ profile: resolved.profile,
22
+ baseUrl: resolved.baseUrl,
23
+ appUrl: resolved.appUrl,
24
+ authenticated: Boolean(resolved.credential),
25
+ authType: resolved.credential?.type ?? null,
26
+ configDir: configDir(),
27
+ profiles: listProfiles(),
28
+ };
29
+ if (global.json) {
30
+ printJson(data);
31
+ return;
32
+ }
33
+ info(table(['FIELD', 'VALUE'], [
34
+ ['profile', data.profile],
35
+ ['base-url', data.baseUrl],
36
+ ['app-url', data.appUrl],
37
+ ['authenticated', String(data.authenticated)],
38
+ ['auth-type', String(data.authType ?? '-')],
39
+ ['config-dir', data.configDir],
40
+ ['profiles', data.profiles.join(', ')],
41
+ ]));
42
+ });
43
+ config
44
+ .command('get <key>')
45
+ .description('Get a config value. Keys: base-url, app-url, default-profile')
46
+ .action((key, _opts, cmd) => {
47
+ const global = globalOpts(cmd);
48
+ const resolved = resolveConfig(global.profile);
49
+ switch (key) {
50
+ case 'base-url':
51
+ info(resolved.baseUrl);
52
+ break;
53
+ case 'app-url':
54
+ info(resolved.appUrl);
55
+ break;
56
+ case 'default-profile':
57
+ info(resolveProfileName());
58
+ break;
59
+ default:
60
+ throw new CliError(`Unknown config key: ${key}`, ExitCode.USAGE, 'Keys: base-url, app-url, default-profile');
61
+ }
62
+ });
63
+ config
64
+ .command('set <key> <value>')
65
+ .description('Set a config value. Keys: base-url, app-url, default-profile')
66
+ .action((key, value, _opts, cmd) => {
67
+ const global = globalOpts(cmd);
68
+ const profile = resolveProfileName(global.profile);
69
+ switch (key) {
70
+ case 'base-url':
71
+ setBaseUrl(profile, value);
72
+ success(`Set base-url for profile ${c.cyan(profile)} to ${value}`);
73
+ break;
74
+ case 'app-url':
75
+ setAppUrl(profile, value);
76
+ success(`Set app-url for profile ${c.cyan(profile)} to ${value}`);
77
+ break;
78
+ case 'default-profile':
79
+ setDefaultProfile(value);
80
+ success(`Default profile set to ${c.cyan(value)}`);
81
+ break;
82
+ default:
83
+ throw new CliError(`Unknown config key: ${key}`, ExitCode.USAGE, 'Keys: base-url, app-url, default-profile');
84
+ }
85
+ });
86
+ config
87
+ .command('reset-base-url')
88
+ .description(`Reset base-url to the default (${DEFAULT_BASE_URL})`)
89
+ .action((_opts, cmd) => {
90
+ const global = globalOpts(cmd);
91
+ const profile = resolveProfileName(global.profile);
92
+ setBaseUrl(profile, DEFAULT_BASE_URL);
93
+ success(`Reset base-url for profile ${c.cyan(profile)} to ${DEFAULT_BASE_URL}`);
94
+ });
95
+ program
96
+ .command('sync')
97
+ .description('Force-refresh the local tool catalog from the backend')
98
+ .action(async (_opts, cmd) => {
99
+ const ctx = buildContext(cmd);
100
+ const tools = await refreshCatalog(ctx.client);
101
+ if (ctx.global.json) {
102
+ printJson({ tools: tools.length, baseUrl: ctx.client.baseUrl });
103
+ return;
104
+ }
105
+ success(`Synced ${tools.length} tools from ${ctx.client.baseUrl}`);
106
+ });
107
+ }
108
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * `datavessel run <tool> [--flags…]` — execute any catalog tool.
3
+ *
4
+ * Flags are validated against the tool's `inputSchema` from the catalog. Two
5
+ * escape hatches always work for power users / odd schemas:
6
+ * --param key=value (repeatable) set one parameter as a raw string
7
+ * --params-json '<json>' merge a full JSON object of parameters
8
+ *
9
+ * Write tools prompt for confirmation unless `--yes` (global) is set.
10
+ * Global options (e.g. `--json`) must precede `run`: `datavessel --json run …`.
11
+ */
12
+ import { buildContext } from '../context.js';
13
+ import { getCatalog, findTool } from '../catalog.js';
14
+ import { schemaToParams, collectParams, describeSchema, } from '../schema.js';
15
+ import { CliError, ExitCode } from '../errors.js';
16
+ import { printJson, info, success, warn, c } from '../output.js';
17
+ import { confirm, isInteractive } from '../prompt.js';
18
+ /** Parse the raw token stream after `<tool>` into flags + escape-hatch params. */
19
+ export function parseRawFlags(tokens) {
20
+ const flags = {};
21
+ const params = {};
22
+ let wantsHelp = false;
23
+ const addFlag = (name, value) => {
24
+ const prev = flags[name];
25
+ if (Array.isArray(prev))
26
+ prev.push(value);
27
+ else
28
+ flags[name] = [value];
29
+ };
30
+ for (let i = 0; i < tokens.length; i++) {
31
+ const tok = tokens[i];
32
+ if (tok === '--help' || tok === '-h') {
33
+ wantsHelp = true;
34
+ continue;
35
+ }
36
+ if (!tok.startsWith('--')) {
37
+ throw new CliError(`Unexpected argument: ${tok}`, ExitCode.USAGE);
38
+ }
39
+ let name = tok.slice(2);
40
+ let inlineValue;
41
+ const eq = name.indexOf('=');
42
+ if (eq !== -1) {
43
+ inlineValue = name.slice(eq + 1);
44
+ name = name.slice(0, eq);
45
+ }
46
+ // Escape hatches.
47
+ if (name === 'params-json') {
48
+ const raw = inlineValue ?? tokens[++i];
49
+ if (raw === undefined)
50
+ throw new CliError('--params-json requires a value', ExitCode.USAGE);
51
+ let obj;
52
+ try {
53
+ obj = JSON.parse(raw);
54
+ }
55
+ catch {
56
+ throw new CliError('--params-json must be valid JSON', ExitCode.USAGE);
57
+ }
58
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
59
+ throw new CliError('--params-json must be a JSON object', ExitCode.USAGE);
60
+ }
61
+ Object.assign(params, obj);
62
+ continue;
63
+ }
64
+ if (name === 'param') {
65
+ const raw = inlineValue ?? tokens[++i];
66
+ if (raw === undefined)
67
+ throw new CliError('--param requires key=value', ExitCode.USAGE);
68
+ const kv = raw.indexOf('=');
69
+ if (kv === -1)
70
+ throw new CliError(`--param expects key=value, got "${raw}"`, ExitCode.USAGE);
71
+ params[raw.slice(0, kv)] = raw.slice(kv + 1);
72
+ continue;
73
+ }
74
+ // Boolean negation: --no-foo
75
+ if (name.startsWith('no-')) {
76
+ flags[name.slice(3)] = false;
77
+ continue;
78
+ }
79
+ if (inlineValue !== undefined) {
80
+ addFlag(name, inlineValue);
81
+ continue;
82
+ }
83
+ // Look ahead: a following non-flag token is this flag's value; otherwise
84
+ // it's a boolean switch.
85
+ const next = tokens[i + 1];
86
+ if (next !== undefined && !next.startsWith('--')) {
87
+ addFlag(name, next);
88
+ i++;
89
+ }
90
+ else {
91
+ flags[name] = true;
92
+ }
93
+ }
94
+ return { flags, params, wantsHelp };
95
+ }
96
+ /** Map parsed kebab-flags onto the commander-style opts object keyed by attr. */
97
+ function flagsToOpts(parsed, params) {
98
+ const byFlag = new Map(params.map((p) => [p.flag, p]));
99
+ const opts = {};
100
+ const unknown = [];
101
+ for (const [flag, value] of Object.entries(parsed.flags)) {
102
+ const desc = byFlag.get(flag);
103
+ if (!desc) {
104
+ // Unknown flag: keep as a raw string param so schemaless tools still work.
105
+ if (!(flag in parsed.params)) {
106
+ parsed.params[flag] = Array.isArray(value) ? value[value.length - 1] : value;
107
+ }
108
+ unknown.push(flag);
109
+ continue;
110
+ }
111
+ if (desc.type === 'array') {
112
+ opts[desc.attr] = Array.isArray(value) ? value : [value];
113
+ }
114
+ else if (Array.isArray(value)) {
115
+ opts[desc.attr] = value[value.length - 1]; // last wins for scalars
116
+ }
117
+ else {
118
+ opts[desc.attr] = value;
119
+ }
120
+ }
121
+ return { opts, unknown };
122
+ }
123
+ export function registerRunCommand(program) {
124
+ program
125
+ .command('run')
126
+ .description('Execute a tool by name (flags are derived from its schema)')
127
+ .argument('<tool>', 'Tool name, e.g. get_account_summaries')
128
+ .argument('[params...]', 'Tool parameters as --flag value (see `tools show <tool>`)')
129
+ .passThroughOptions()
130
+ .allowUnknownOption()
131
+ .addHelpText('after', '\nExamples:\n' +
132
+ ' datavessel run get_account_summaries\n' +
133
+ ' datavessel run run_report --property-id 123 --metrics sessions --metrics users\n' +
134
+ " datavessel run some_tool --params-json '{\"a\":1}'\n" +
135
+ ' datavessel --json run list_sites\n')
136
+ .action(async (toolName, rawParams, _opts, cmd) => {
137
+ const ctx = buildContext(cmd);
138
+ const catalog = await getCatalog(ctx.client);
139
+ const tool = findTool(catalog, toolName);
140
+ if (!tool) {
141
+ throw new CliError(`Unknown tool: ${toolName}`, ExitCode.USAGE, 'Run `datavessel tools list` to see available tools.');
142
+ }
143
+ const descriptors = schemaToParams(tool.inputSchema);
144
+ const parsed = parseRawFlags(rawParams);
145
+ if (parsed.wantsHelp) {
146
+ info(`${c.bold(tool.toolName)} ${c.dim(`(${tool.provider}, ${tool.access})`)}`);
147
+ if (tool.description)
148
+ info(`\n${tool.description}`);
149
+ info(`\n${c.bold('Parameters:')}`);
150
+ info(describeSchema(descriptors));
151
+ return;
152
+ }
153
+ const { opts, unknown } = flagsToOpts(parsed, descriptors);
154
+ if (unknown.length > 0 && descriptors.length > 0) {
155
+ warn(`Unknown flag(s) sent as raw string params: ${unknown
156
+ .map((f) => '--' + f)
157
+ .join(', ')}. See \`datavessel tools show ${toolName}\`.`);
158
+ }
159
+ const params = collectParams(descriptors, opts, parsed.params);
160
+ // Guard destructive/write tools behind a confirmation.
161
+ if (tool.access === 'write' && !ctx.global.yes) {
162
+ if (!isInteractive()) {
163
+ throw new CliError(`'${toolName}' is a write tool; refusing to run non-interactively without --yes.`, ExitCode.USAGE);
164
+ }
165
+ const ok = await confirm(`${c.yellow('!')} '${toolName}' modifies data. Continue?`, false);
166
+ if (!ok) {
167
+ info('Aborted.');
168
+ process.exitCode = ExitCode.OK;
169
+ return;
170
+ }
171
+ }
172
+ const result = await ctx.client.execute(toolName, params);
173
+ if (ctx.global.json) {
174
+ printJson(result);
175
+ }
176
+ else if (typeof result === 'string') {
177
+ process.stdout.write(result + '\n');
178
+ }
179
+ else {
180
+ printJson(result);
181
+ }
182
+ success(`Executed ${toolName}`);
183
+ });
184
+ }
185
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Tool catalog commands: `tools list` and `tools show <name>`.
3
+ *
4
+ * Both read the catalog from the local cache (refreshing from the backend when
5
+ * stale). `tools show` renders the dynamically-derived flags for a tool — the
6
+ * same flags `datavessel run <tool>` accepts.
7
+ */
8
+ import { buildContext } from '../context.js';
9
+ import { getCatalog, findTool } from '../catalog.js';
10
+ import { schemaToParams, describeSchema } from '../schema.js';
11
+ import { CliError, ExitCode } from '../errors.js';
12
+ import { printJson, table, info, c } from '../output.js';
13
+ export function registerToolsCommands(program) {
14
+ const tools = program.command('tools').description('Browse the available tool catalog');
15
+ tools
16
+ .command('list')
17
+ .description('List all available tools')
18
+ .option('-p, --provider <name>', 'Filter by provider (e.g. google_analytics)')
19
+ .option('-a, --access <type>', "Filter by access: 'read' or 'write'")
20
+ .option('-s, --search <text>', 'Filter by substring in name or description')
21
+ .option('--refresh', 'Force-refresh the catalog from the backend')
22
+ .action(async (opts, cmd) => {
23
+ const ctx = buildContext(cmd);
24
+ let catalog = await getCatalog(ctx.client, { forceRefresh: Boolean(opts.refresh) });
25
+ if (opts.provider)
26
+ catalog = catalog.filter((t) => t.provider === opts.provider);
27
+ if (opts.access)
28
+ catalog = catalog.filter((t) => t.access === opts.access);
29
+ if (opts.search) {
30
+ const q = String(opts.search).toLowerCase();
31
+ catalog = catalog.filter((t) => t.toolName.toLowerCase().includes(q) ||
32
+ (t.description ?? '').toLowerCase().includes(q));
33
+ }
34
+ catalog = [...catalog].sort((a, b) => a.provider.localeCompare(b.provider) || a.toolName.localeCompare(b.toolName));
35
+ if (ctx.global.json) {
36
+ printJson(catalog);
37
+ return;
38
+ }
39
+ if (catalog.length === 0) {
40
+ info('No matching tools.');
41
+ return;
42
+ }
43
+ const rows = catalog.map((t) => [
44
+ t.access === 'write' ? c.yellow(t.toolName) : t.toolName,
45
+ t.provider,
46
+ t.access,
47
+ truncate(t.description ?? '', 60),
48
+ ]);
49
+ info(table(['TOOL', 'PROVIDER', 'ACCESS', 'DESCRIPTION'], rows));
50
+ info('');
51
+ info(c.dim(`${catalog.length} tool(s). Run \`datavessel tools show <name>\` for details.`));
52
+ });
53
+ tools
54
+ .command('show <name>')
55
+ .description('Show a tool description and its parameters')
56
+ .option('--refresh', 'Force-refresh the catalog from the backend')
57
+ .action(async (name, opts, cmd) => {
58
+ const ctx = buildContext(cmd);
59
+ const catalog = await getCatalog(ctx.client, { forceRefresh: Boolean(opts.refresh) });
60
+ const tool = findTool(catalog, name);
61
+ if (!tool) {
62
+ throw new CliError(`Unknown tool: ${name}`, ExitCode.USAGE, 'Run `datavessel tools list` to see available tools.');
63
+ }
64
+ if (ctx.global.json) {
65
+ printJson(tool);
66
+ return;
67
+ }
68
+ const params = schemaToParams(tool.inputSchema);
69
+ info(`${c.bold(tool.toolName)} ${c.dim(`(${tool.provider}, ${tool.access})`)}`);
70
+ if (tool.description)
71
+ info(`\n${tool.description}`);
72
+ info(`\n${c.bold('Parameters:')}`);
73
+ info(describeSchema(params));
74
+ info(`\n${c.dim('Run with:')} datavessel run ${tool.toolName} ${params
75
+ .filter((p) => p.required)
76
+ .map((p) => `--${p.flag} <…>`)
77
+ .join(' ')}`);
78
+ });
79
+ }
80
+ function truncate(s, n) {
81
+ const clean = s.replace(/\s+/g, ' ').trim();
82
+ return clean.length > n ? clean.slice(0, n - 1) + '…' : clean;
83
+ }
84
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/commands/tools.ts"],"names":[],"mappings":"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"}
package/dist/config.js ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Configuration and credential storage.
3
+ *
4
+ * Two files live under the datavessel config dir (default
5
+ * `~/.config/datavessel`, override with `DATAVESSEL_CONFIG_DIR`):
6
+ *
7
+ * - config.json non-secret settings (base URL, default profile, …)
8
+ * - credentials.json auth tokens, written with 0600 perms
9
+ *
10
+ * Both support named profiles so a user can keep separate prod / staging /
11
+ * personal credentials. The active profile is chosen by (in order):
12
+ * `--profile` flag → `DATAVESSEL_PROFILE` env → config `defaultProfile` →
13
+ * "default".
14
+ */
15
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'node:fs';
16
+ import { homedir } from 'node:os';
17
+ import { join } from 'node:path';
18
+ /** Production backend API base. Override per-profile or with DATAVESSEL_API_URL. */
19
+ export const DEFAULT_BASE_URL = 'https://api.datavessel.io';
20
+ /** Web app base, used for the browser login handoff. Override with DATAVESSEL_APP_URL. */
21
+ export const DEFAULT_APP_URL = 'https://app.datavessel.io';
22
+ export function configDir() {
23
+ if (process.env.DATAVESSEL_CONFIG_DIR)
24
+ return process.env.DATAVESSEL_CONFIG_DIR;
25
+ const base = process.env.XDG_CONFIG_HOME && process.env.XDG_CONFIG_HOME.length > 0
26
+ ? process.env.XDG_CONFIG_HOME
27
+ : join(homedir(), '.config');
28
+ return join(base, 'datavessel');
29
+ }
30
+ const configPath = () => join(configDir(), 'config.json');
31
+ const credentialsPath = () => join(configDir(), 'credentials.json');
32
+ const catalogPath = () => join(configDir(), 'catalog.json');
33
+ export function ensureDir() {
34
+ const dir = configDir();
35
+ if (!existsSync(dir))
36
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
37
+ }
38
+ function readJson(path, fallback) {
39
+ if (!existsSync(path))
40
+ return fallback;
41
+ try {
42
+ return JSON.parse(readFileSync(path, 'utf8'));
43
+ }
44
+ catch {
45
+ return fallback;
46
+ }
47
+ }
48
+ function readConfig() {
49
+ return readJson(configPath(), {});
50
+ }
51
+ function readCredentials() {
52
+ return readJson(credentialsPath(), {});
53
+ }
54
+ function writeConfig(cfg) {
55
+ ensureDir();
56
+ writeFileSync(configPath(), JSON.stringify(cfg, null, 2) + '\n', { mode: 0o600 });
57
+ }
58
+ function writeCredentials(creds) {
59
+ ensureDir();
60
+ writeFileSync(credentialsPath(), JSON.stringify(creds, null, 2) + '\n', { mode: 0o600 });
61
+ // Defensive: re-assert perms in case the file pre-existed with looser bits.
62
+ try {
63
+ chmodSync(credentialsPath(), 0o600);
64
+ }
65
+ catch {
66
+ /* best effort */
67
+ }
68
+ }
69
+ /** The profile name in effect, honouring flag → env → config default. */
70
+ export function resolveProfileName(flagProfile) {
71
+ return (flagProfile ||
72
+ process.env.DATAVESSEL_PROFILE ||
73
+ readConfig().defaultProfile ||
74
+ 'default');
75
+ }
76
+ /**
77
+ * Resolve the full active config: base URL and credential for the chosen
78
+ * profile, with env-var overrides applied. The base URL precedence is
79
+ * `DATAVESSEL_API_URL` → per-profile config → built-in default.
80
+ */
81
+ export function resolveConfig(flagProfile) {
82
+ const profile = resolveProfileName(flagProfile);
83
+ const cfg = readConfig();
84
+ const baseUrl = process.env.DATAVESSEL_API_URL ||
85
+ cfg.profiles?.[profile]?.baseUrl ||
86
+ DEFAULT_BASE_URL;
87
+ const appUrl = process.env.DATAVESSEL_APP_URL ||
88
+ cfg.profiles?.[profile]?.appUrl ||
89
+ DEFAULT_APP_URL;
90
+ let credential = readCredentials()[profile];
91
+ // Env tokens win so CI can inject auth without touching disk.
92
+ if (process.env.DATAVESSEL_TOKEN) {
93
+ credential = { type: 'bearer', token: process.env.DATAVESSEL_TOKEN };
94
+ }
95
+ else if (process.env.DATAVESSEL_API_KEY) {
96
+ credential = { type: 'api-key', token: process.env.DATAVESSEL_API_KEY };
97
+ }
98
+ return { profile, baseUrl, appUrl, credential };
99
+ }
100
+ export function setBaseUrl(profile, baseUrl) {
101
+ const cfg = readConfig();
102
+ cfg.profiles ??= {};
103
+ cfg.profiles[profile] ??= {};
104
+ cfg.profiles[profile].baseUrl = baseUrl;
105
+ writeConfig(cfg);
106
+ }
107
+ export function setAppUrl(profile, appUrl) {
108
+ const cfg = readConfig();
109
+ cfg.profiles ??= {};
110
+ cfg.profiles[profile] ??= {};
111
+ cfg.profiles[profile].appUrl = appUrl;
112
+ writeConfig(cfg);
113
+ }
114
+ export function setDefaultProfile(profile) {
115
+ const cfg = readConfig();
116
+ cfg.defaultProfile = profile;
117
+ writeConfig(cfg);
118
+ }
119
+ export function saveCredential(profile, credential) {
120
+ const creds = readCredentials();
121
+ creds[profile] = credential;
122
+ writeCredentials(creds);
123
+ }
124
+ export function clearCredential(profile) {
125
+ const creds = readCredentials();
126
+ if (!(profile in creds))
127
+ return false;
128
+ delete creds[profile];
129
+ writeCredentials(creds);
130
+ return true;
131
+ }
132
+ export function listProfiles() {
133
+ const fromConfig = Object.keys(readConfig().profiles ?? {});
134
+ const fromCreds = Object.keys(readCredentials());
135
+ return [...new Set(['default', ...fromConfig, ...fromCreds])].sort();
136
+ }
137
+ export const _paths = { configPath, credentialsPath, catalogPath };
138
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Builds the per-invocation context (resolved config + API client) from the
3
+ * program's global options, applying flag overrides on top of stored config.
4
+ */
5
+ import { ApiClient } from './api.js';
6
+ import { resolveConfig, saveCredential } from './config.js';
7
+ /** Read the root program's global options regardless of nesting depth. */
8
+ export function globalOpts(cmd) {
9
+ let root = cmd;
10
+ while (root.parent)
11
+ root = root.parent;
12
+ return root.opts();
13
+ }
14
+ export function buildContext(cmd) {
15
+ const global = globalOpts(cmd);
16
+ const config = resolveConfig(global.profile);
17
+ // Flag overrides take precedence over stored/env config.
18
+ if (global.baseUrl)
19
+ config.baseUrl = global.baseUrl;
20
+ let credential = config.credential;
21
+ let fromStore = true;
22
+ if (global.token) {
23
+ credential = { type: 'bearer', token: global.token };
24
+ fromStore = false;
25
+ }
26
+ else if (global.apiKey) {
27
+ credential = { type: 'api-key', token: global.apiKey };
28
+ fromStore = false;
29
+ }
30
+ config.credential = credential;
31
+ // Persist rotated OAuth tokens only when the credential came from disk (not
32
+ // from an ephemeral --token / env override).
33
+ const onRefresh = fromStore && credential?.type === 'oauth'
34
+ ? (c) => saveCredential(config.profile, c)
35
+ : undefined;
36
+ const client = new ApiClient({ baseUrl: config.baseUrl, credential, onRefresh });
37
+ return { global, config, client };
38
+ }
39
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAwC,MAAM,aAAa,CAAC;AAkBlG,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,IAAI,IAAI,GAAY,GAAG,CAAC;IACxB,OAAO,IAAI,CAAC,MAAM;QAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,OAAO,IAAI,CAAC,IAAI,EAAiB,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE7C,yDAAyD;IACzD,IAAI,MAAM,CAAC,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IACpD,IAAI,UAAU,GAA2B,MAAM,CAAC,UAAU,CAAC;IAC3D,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,UAAU,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACrD,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,UAAU,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACvD,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC;IACD,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IAE/B,4EAA4E;IAC5E,6CAA6C;IAC7C,MAAM,SAAS,GACb,SAAS,IAAI,UAAU,EAAE,IAAI,KAAK,OAAO;QACvC,CAAC,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;IACjF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACpC,CAAC"}