actionxm 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.
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerAuthCommands(program: Command): void;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0G3D"}
@@ -0,0 +1,94 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { readConfig, clearAuth, isAuthenticated, getConfigPath } from '../lib/config.js';
4
+ import { deviceAuthFlow, validateToken } from '../lib/auth.js';
5
+ import { exitWithError, printKeyValue, printSuccess } from '../utils/output.js';
6
+ export function registerAuthCommands(program) {
7
+ const auth = program.command('auth').description('Manage authentication');
8
+ auth
9
+ .command('login')
10
+ .description('Authenticate with ActionXM via device authorization')
11
+ .action(async () => {
12
+ if (isAuthenticated()) {
13
+ const config = readConfig();
14
+ const { valid } = await validateToken();
15
+ if (valid) {
16
+ console.log(`Already logged in as ${chalk.bold(config.user?.email)}.`);
17
+ console.log(`Use ${chalk.cyan('actionxm auth logout')} first to switch accounts.`);
18
+ return;
19
+ }
20
+ // Token expired — proceed with login
21
+ clearAuth();
22
+ }
23
+ const spinner = ora();
24
+ try {
25
+ const result = await deviceAuthFlow((userCode, verificationUri) => {
26
+ console.log();
27
+ console.log(`Open ${chalk.bold.cyan(verificationUri)} in your browser`);
28
+ console.log(`and enter code: ${chalk.bold.yellow(userCode)}`);
29
+ console.log();
30
+ // Try to open browser
31
+ import('open')
32
+ .then((mod) => mod.default(verificationUri))
33
+ .catch(() => {
34
+ /* browser open is best-effort */
35
+ });
36
+ }, () => {
37
+ spinner.start('Waiting for authorization...');
38
+ });
39
+ spinner.stop();
40
+ console.log();
41
+ printSuccess(`Logged in as ${chalk.bold(result.user.email)}`);
42
+ if (result.sites.length > 0) {
43
+ console.log(`Active site: ${chalk.cyan(result.sites[0].name)} (${result.sites[0].domain})`);
44
+ }
45
+ if (result.sites.length > 1) {
46
+ console.log(`${result.sites.length} sites available. Use ${chalk.cyan('actionxm sites list')} to see all.`);
47
+ }
48
+ }
49
+ catch (err) {
50
+ spinner.stop();
51
+ exitWithError(err instanceof Error ? err.message : String(err));
52
+ }
53
+ });
54
+ auth
55
+ .command('logout')
56
+ .description('Clear stored credentials')
57
+ .action(() => {
58
+ if (!isAuthenticated()) {
59
+ console.log('Not logged in.');
60
+ return;
61
+ }
62
+ const config = readConfig();
63
+ const email = config.user?.email || 'unknown';
64
+ clearAuth();
65
+ printSuccess(`Logged out from ${email}`);
66
+ });
67
+ auth
68
+ .command('status')
69
+ .description('Show current authentication state')
70
+ .action(async () => {
71
+ const config = readConfig();
72
+ if (!config.access_token) {
73
+ console.log(`${chalk.yellow('Not authenticated')}`);
74
+ console.log(`Run ${chalk.cyan('actionxm auth login')} to get started.`);
75
+ return;
76
+ }
77
+ const spinner = ora('Checking auth status...').start();
78
+ const { valid, user } = await validateToken();
79
+ spinner.stop();
80
+ if (!valid) {
81
+ console.log(`${chalk.red('Token expired or invalid')}`);
82
+ console.log(`Run ${chalk.cyan('actionxm auth login')} to re-authenticate.`);
83
+ return;
84
+ }
85
+ console.log(chalk.green('Authenticated'));
86
+ console.log();
87
+ printKeyValue('Email', user.email);
88
+ printKeyValue('Name', user.displayName);
89
+ printKeyValue('Role', user.role);
90
+ printKeyValue('Tenant', user.tenantId);
91
+ printKeyValue('Config', getConfigPath());
92
+ });
93
+ }
94
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerConfigCommands(program: Command): void;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8C7D"}
@@ -0,0 +1,48 @@
1
+ import chalk from 'chalk';
2
+ import { readConfig, updateConfig, getConfigPath } from '../lib/config.js';
3
+ import { exitWithError, printKeyValue, printSuccess } from '../utils/output.js';
4
+ const ALLOWED_KEYS = ['api_url'];
5
+ export function registerConfigCommands(program) {
6
+ const config = program.command('config').description('Manage CLI configuration');
7
+ config
8
+ .command('get <key>')
9
+ .description('Get a config value')
10
+ .action((key) => {
11
+ if (!ALLOWED_KEYS.includes(key)) {
12
+ exitWithError(`Unknown config key "${key}". Allowed: ${ALLOWED_KEYS.join(', ')}`);
13
+ }
14
+ const cfg = readConfig();
15
+ const value = cfg[key];
16
+ console.log(value ?? '');
17
+ });
18
+ config
19
+ .command('set <key> <value>')
20
+ .description('Set a config value')
21
+ .action((key, value) => {
22
+ if (!ALLOWED_KEYS.includes(key)) {
23
+ exitWithError(`Unknown config key "${key}". Allowed: ${ALLOWED_KEYS.join(', ')}`);
24
+ }
25
+ updateConfig({ [key]: value });
26
+ printSuccess(`Set ${key} = ${value}`);
27
+ });
28
+ config
29
+ .command('path')
30
+ .description('Show config file path')
31
+ .action(() => {
32
+ console.log(getConfigPath());
33
+ });
34
+ config
35
+ .command('list')
36
+ .description('Show all config values')
37
+ .action(() => {
38
+ const cfg = readConfig();
39
+ console.log(chalk.bold('Configuration'));
40
+ console.log();
41
+ printKeyValue('Config file', getConfigPath());
42
+ console.log();
43
+ for (const key of ALLOWED_KEYS) {
44
+ printKeyValue(key, cfg[key] ?? chalk.dim('(not set)'));
45
+ }
46
+ });
47
+ }
48
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEhF,MAAM,YAAY,GAAG,CAAC,SAAS,CAAU,CAAC;AAG1C,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAEjF,MAAM;SACH,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,oBAAoB,CAAC;SACjC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;QACtB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAgB,CAAC,EAAE,CAAC;YAC7C,aAAa,CAAC,uBAAuB,GAAG,eAAe,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAgB,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,oBAAoB,CAAC;SACjC,MAAM,CAAC,CAAC,GAAW,EAAE,KAAa,EAAE,EAAE;QACrC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAgB,CAAC,EAAE,CAAC;YAC7C,aAAa,CAAC,uBAAuB,GAAG,eAAe,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/B,YAAY,CAAC,OAAO,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uBAAuB,CAAC;SACpC,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEL,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,wBAAwB,CAAC;SACrC,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,aAAa,CAAC,aAAa,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSitesCommands(program: Command): void;
3
+ //# sourceMappingURL=sites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../src/commands/sites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuF5D"}
@@ -0,0 +1,74 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { readConfig, updateConfig, isAuthenticated } from '../lib/config.js';
4
+ import { apiRequest, ApiError } from '../lib/api-client.js';
5
+ import { exitWithError, printTable, printSuccess } from '../utils/output.js';
6
+ export function registerSitesCommands(program) {
7
+ const sites = program.command('sites').description('Manage sites');
8
+ sites
9
+ .command('list')
10
+ .description('List all accessible sites')
11
+ .action(async () => {
12
+ if (!isAuthenticated()) {
13
+ exitWithError(`Not authenticated. Run ${chalk.cyan('actionxm auth login')} first.`);
14
+ }
15
+ const spinner = ora('Fetching sites...').start();
16
+ try {
17
+ const result = await apiRequest('/api/sites');
18
+ spinner.stop();
19
+ if (result.length === 0) {
20
+ console.log('No sites found.');
21
+ return;
22
+ }
23
+ const config = readConfig();
24
+ const headers = ['', 'Name', 'Domain', 'ID'];
25
+ const rows = result.map((site) => [
26
+ site.id === config.current_site_id ? chalk.green('*') : ' ',
27
+ site.name,
28
+ site.domain,
29
+ chalk.dim(site.id),
30
+ ]);
31
+ printTable(headers, rows);
32
+ console.log();
33
+ console.log(chalk.dim(`${chalk.green('*')} = active site. Use ${chalk.cyan('actionxm sites select <id>')} to switch.`));
34
+ }
35
+ catch (err) {
36
+ spinner.stop();
37
+ if (err instanceof ApiError && err.statusCode === 401) {
38
+ exitWithError(`Session expired. Run ${chalk.cyan('actionxm auth login')} to re-authenticate.`);
39
+ }
40
+ exitWithError(err instanceof Error ? err.message : String(err));
41
+ }
42
+ });
43
+ sites
44
+ .command('select <site-id>')
45
+ .description('Set the active site for subsequent commands')
46
+ .action(async (siteId) => {
47
+ if (!isAuthenticated()) {
48
+ exitWithError(`Not authenticated. Run ${chalk.cyan('actionxm auth login')} first.`);
49
+ }
50
+ // Validate site ID by checking it's in the user's sites
51
+ const spinner = ora('Validating site...').start();
52
+ try {
53
+ const sites = await apiRequest('/api/sites');
54
+ spinner.stop();
55
+ const site = sites.find((s) => s.id === siteId || s.name === siteId);
56
+ if (!site) {
57
+ exitWithError(`Site "${siteId}" not found. Run ${chalk.cyan('actionxm sites list')} to see available sites.`);
58
+ }
59
+ updateConfig({
60
+ current_site_id: site.id,
61
+ current_site_name: site.name,
62
+ });
63
+ printSuccess(`Active site set to ${chalk.bold(site.name)} (${site.domain})`);
64
+ }
65
+ catch (err) {
66
+ spinner.stop();
67
+ if (err instanceof ApiError && err.statusCode === 401) {
68
+ exitWithError(`Session expired. Run ${chalk.cyan('actionxm auth login')} to re-authenticate.`);
69
+ }
70
+ exitWithError(err instanceof Error ? err.message : String(err));
71
+ }
72
+ });
73
+ }
74
+ //# sourceMappingURL=sites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sites.js","sourceRoot":"","sources":["../../src/commands/sites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerStatusCommand(program: Command): void;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuD5D"}
@@ -0,0 +1,54 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { readConfig, isAuthenticated, getConfigPath } from '../lib/config.js';
4
+ import { validateToken } from '../lib/auth.js';
5
+ import { printKeyValue } from '../utils/output.js';
6
+ export function registerStatusCommand(program) {
7
+ program
8
+ .command('status')
9
+ .description('Show current auth, site, and CLI state')
10
+ .action(async () => {
11
+ const config = readConfig();
12
+ console.log(chalk.bold('ActionXM CLI Status'));
13
+ console.log();
14
+ // Auth
15
+ if (!config.access_token) {
16
+ printKeyValue('Auth', chalk.yellow('Not authenticated'));
17
+ console.log(` Run ${chalk.cyan('actionxm auth login')} to get started.`);
18
+ console.log();
19
+ printKeyValue('API URL', config.api_url);
20
+ printKeyValue('Config', getConfigPath());
21
+ return;
22
+ }
23
+ const spinner = ora('Checking...').start();
24
+ const { valid, user, sites } = await validateToken();
25
+ spinner.stop();
26
+ if (!valid) {
27
+ printKeyValue('Auth', chalk.red('Token expired'));
28
+ console.log(` Run ${chalk.cyan('actionxm auth login')} to re-authenticate.`);
29
+ return;
30
+ }
31
+ printKeyValue('Auth', chalk.green('Authenticated'));
32
+ printKeyValue('User', `${user.displayName} <${user.email}>`);
33
+ printKeyValue('Role', user.role);
34
+ console.log();
35
+ // Active site
36
+ if (!isAuthenticated() || !config.current_site_id) {
37
+ printKeyValue('Site', chalk.yellow('No site selected'));
38
+ if (sites && sites.length > 0) {
39
+ console.log(` Run ${chalk.cyan('actionxm sites select <id>')} to choose a site.`);
40
+ }
41
+ }
42
+ else {
43
+ printKeyValue('Site', config.current_site_name || config.current_site_id);
44
+ }
45
+ // Sites count
46
+ if (sites) {
47
+ printKeyValue('Sites', `${sites.length} accessible`);
48
+ }
49
+ console.log();
50
+ printKeyValue('API URL', config.api_url);
51
+ printKeyValue('Config', getConfigPath());
52
+ });
53
+ }
54
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { registerAuthCommands } from './commands/auth.js';
4
+ import { registerSitesCommands } from './commands/sites.js';
5
+ import { registerStatusCommand } from './commands/status.js';
6
+ import { registerConfigCommands } from './commands/config.js';
7
+ const program = new Command();
8
+ program
9
+ .name('actionxm')
10
+ .description('ActionXM CLI — command-line interface for the ActionXM analytics platform')
11
+ .version('0.1.1');
12
+ // Register commands
13
+ registerAuthCommands(program);
14
+ registerSitesCommands(program);
15
+ registerStatusCommand(program);
16
+ registerConfigCommands(program);
17
+ // Add docs command (opens documentation site in browser)
18
+ program
19
+ .command('docs')
20
+ .description('Open ActionXM CLI documentation in your browser')
21
+ .action(async () => {
22
+ const docsUrl = 'https://cli.action-xm.com';
23
+ console.log(`Opening ${docsUrl} ...`);
24
+ try {
25
+ const open = await import('open');
26
+ await open.default(docsUrl);
27
+ }
28
+ catch {
29
+ console.log(`Visit: ${docsUrl}`);
30
+ }
31
+ });
32
+ program.parse();
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,2EAA2E,CAAC;KACxF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB;AACpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAEhC,yDAAyD;AACzD,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,OAAO,GAAG,2BAA2B,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,MAAM,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IACnC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare class ApiError extends Error {
2
+ statusCode: number;
3
+ body?: unknown | undefined;
4
+ constructor(statusCode: number, message: string, body?: unknown | undefined);
5
+ }
6
+ interface RequestOptions {
7
+ method?: string;
8
+ body?: unknown;
9
+ token?: string;
10
+ }
11
+ export declare function apiRequest<T>(path: string, options?: RequestOptions): Promise<T>;
12
+ export {};
13
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAS,SAAQ,KAAK;IAExB,UAAU,EAAE,MAAM;IAElB,IAAI,CAAC,EAAE,OAAO;gBAFd,UAAU,EAAE,MAAM,EACzB,OAAO,EAAE,MAAM,EACR,IAAI,CAAC,EAAE,OAAO,YAAA;CAKxB;AAED,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CA+C1F"}
@@ -0,0 +1,56 @@
1
+ import { readConfig } from './config.js';
2
+ export class ApiError extends Error {
3
+ statusCode;
4
+ body;
5
+ constructor(statusCode, message, body) {
6
+ super(message);
7
+ this.statusCode = statusCode;
8
+ this.body = body;
9
+ this.name = 'ApiError';
10
+ }
11
+ }
12
+ export async function apiRequest(path, options = {}) {
13
+ const config = readConfig();
14
+ const { method = 'GET', body, token } = options;
15
+ const accessToken = token ?? config.access_token;
16
+ const url = `${config.api_url}${path}`;
17
+ const headers = {
18
+ 'Content-Type': 'application/json',
19
+ };
20
+ if (accessToken) {
21
+ headers['Authorization'] = `Bearer ${accessToken}`;
22
+ }
23
+ let response;
24
+ try {
25
+ response = await fetch(url, {
26
+ method,
27
+ headers,
28
+ body: body ? JSON.stringify(body) : undefined,
29
+ signal: AbortSignal.timeout(30_000),
30
+ });
31
+ }
32
+ catch (err) {
33
+ if (err instanceof Error && err.name === 'TimeoutError') {
34
+ throw new ApiError(0, 'Request timed out. Check your network connection and API URL.');
35
+ }
36
+ if (err instanceof TypeError && err.message.includes('fetch')) {
37
+ throw new ApiError(0, `Unable to connect to ${config.api_url}. Is the server running?`);
38
+ }
39
+ throw new ApiError(0, `Network error: ${err instanceof Error ? err.message : String(err)}`);
40
+ }
41
+ if (!response.ok) {
42
+ let errorBody;
43
+ try {
44
+ errorBody = await response.json();
45
+ }
46
+ catch {
47
+ errorBody = await response.text().catch(() => '');
48
+ }
49
+ const message = errorBody?.error ||
50
+ errorBody?.error_description ||
51
+ `HTTP ${response.status}`;
52
+ throw new ApiError(response.status, message, errorBody);
53
+ }
54
+ return response.json();
55
+ }
56
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IAEA;IAHT,YACS,UAAkB,EACzB,OAAe,EACR,IAAc;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QAJR,eAAU,GAAV,UAAU,CAAQ;QAElB,SAAI,GAAJ,IAAI,CAAU;QAGrB,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAQD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,IAAY,EAAE,UAA0B,EAAE;IAC5E,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,WAAW,GAAG,KAAK,IAAI,MAAM,CAAC,YAAY,CAAC;IAEjD,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;IAEvC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,WAAW,EAAE,CAAC;IACrD,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACxD,MAAM,IAAI,QAAQ,CAAC,CAAC,EAAE,+DAA+D,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,GAAG,YAAY,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,QAAQ,CAAC,CAAC,EAAE,wBAAwB,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,CAAC,EAAE,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,SAAkB,CAAC;QACvB,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,OAAO,GACV,SAAgC,EAAE,KAAK;YACvC,SAA4C,EAAE,iBAAiB;YAChE,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;AACvC,CAAC"}
@@ -0,0 +1,51 @@
1
+ interface DeviceCodeResponse {
2
+ device_code: string;
3
+ user_code: string;
4
+ verification_uri: string;
5
+ expires_in: number;
6
+ interval: number;
7
+ }
8
+ interface TokenResponse {
9
+ access_token: string;
10
+ token_type: string;
11
+ expires_in: number;
12
+ user: {
13
+ id: string;
14
+ email: string;
15
+ displayName: string;
16
+ role: string;
17
+ tenantId: string;
18
+ };
19
+ sites: Array<{
20
+ id: string;
21
+ name: string;
22
+ domain: string;
23
+ }>;
24
+ }
25
+ export declare function requestDeviceCode(): Promise<DeviceCodeResponse>;
26
+ /**
27
+ * Poll for token approval. Returns the token response on success,
28
+ * or null if still pending. Throws on permanent errors.
29
+ */
30
+ export declare function pollForToken(deviceCode: string): Promise<TokenResponse | null>;
31
+ /**
32
+ * Complete device auth flow: request code, poll until approved, save token.
33
+ */
34
+ export declare function deviceAuthFlow(onCode: (userCode: string, verificationUri: string) => void, onPolling: () => void): Promise<TokenResponse>;
35
+ export declare function validateToken(): Promise<{
36
+ valid: boolean;
37
+ user?: {
38
+ id: string;
39
+ email: string;
40
+ displayName: string;
41
+ tenantId: string;
42
+ role: string;
43
+ };
44
+ sites?: Array<{
45
+ id: string;
46
+ name: string;
47
+ domain: string;
48
+ }>;
49
+ }>;
50
+ export {};
51
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAGA,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,aAAa;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAIrE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAmBpF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,KAAK,IAAI,EAC3D,SAAS,EAAE,MAAM,IAAI,GACpB,OAAO,CAAC,aAAa,CAAC,CA4BxB;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC;IAC7C,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ,CAAC,CA+BD"}
@@ -0,0 +1,79 @@
1
+ import { apiRequest, ApiError } from './api-client.js';
2
+ import { updateConfig, readConfig } from './config.js';
3
+ export async function requestDeviceCode() {
4
+ return apiRequest('/api/auth/device/code', {
5
+ method: 'POST',
6
+ });
7
+ }
8
+ /**
9
+ * Poll for token approval. Returns the token response on success,
10
+ * or null if still pending. Throws on permanent errors.
11
+ */
12
+ export async function pollForToken(deviceCode) {
13
+ try {
14
+ return await apiRequest('/api/auth/device/token', {
15
+ method: 'POST',
16
+ body: { device_code: deviceCode },
17
+ });
18
+ }
19
+ catch (err) {
20
+ if (err instanceof ApiError && err.body) {
21
+ const body = err.body;
22
+ if (body.error === 'authorization_pending') {
23
+ return null; // Still waiting
24
+ }
25
+ if (body.error === 'slow_down') {
26
+ return null; // Increase interval, but return null for simplicity
27
+ }
28
+ // expired_token, access_denied, etc. — rethrow
29
+ }
30
+ throw err;
31
+ }
32
+ }
33
+ /**
34
+ * Complete device auth flow: request code, poll until approved, save token.
35
+ */
36
+ export async function deviceAuthFlow(onCode, onPolling) {
37
+ const codeResponse = await requestDeviceCode();
38
+ onCode(codeResponse.user_code, codeResponse.verification_uri);
39
+ const interval = codeResponse.interval * 1000;
40
+ const deadline = Date.now() + codeResponse.expires_in * 1000;
41
+ onPolling();
42
+ while (Date.now() < deadline) {
43
+ await sleep(interval);
44
+ const tokenResponse = await pollForToken(codeResponse.device_code);
45
+ if (tokenResponse) {
46
+ // Save to config
47
+ updateConfig({
48
+ access_token: tokenResponse.access_token,
49
+ user: tokenResponse.user,
50
+ sites: tokenResponse.sites,
51
+ current_site_id: tokenResponse.sites[0]?.id,
52
+ current_site_name: tokenResponse.sites[0]?.name,
53
+ });
54
+ return tokenResponse;
55
+ }
56
+ }
57
+ throw new Error('Device code expired. Please try again.');
58
+ }
59
+ export async function validateToken() {
60
+ const config = readConfig();
61
+ if (!config.access_token) {
62
+ return { valid: false };
63
+ }
64
+ try {
65
+ const result = await apiRequest('/api/auth/me');
66
+ return {
67
+ valid: true,
68
+ user: result.user,
69
+ sites: result.sites.map((s) => ({ id: s.id, name: s.name, domain: s.domain })),
70
+ };
71
+ }
72
+ catch {
73
+ return { valid: false };
74
+ }
75
+ }
76
+ function sleep(ms) {
77
+ return new Promise((resolve) => setTimeout(resolve, ms));
78
+ }
79
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface ActionXmConfig {
2
+ api_url: string;
3
+ access_token?: string;
4
+ current_site_id?: string;
5
+ current_site_name?: string;
6
+ user?: {
7
+ id: string;
8
+ email: string;
9
+ displayName: string;
10
+ role: string;
11
+ tenantId: string;
12
+ };
13
+ sites?: Array<{
14
+ id: string;
15
+ name: string;
16
+ domain: string;
17
+ }>;
18
+ }
19
+ export declare function getConfigPath(): string;
20
+ export declare function readConfig(): ActionXmConfig;
21
+ export declare function writeConfig(config: ActionXmConfig): void;
22
+ export declare function updateConfig(partial: Partial<ActionXmConfig>): void;
23
+ export declare function clearAuth(): void;
24
+ export declare function isAuthenticated(): boolean;
25
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAeD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,IAAI,cAAc,CAU3C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAIxD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAGnE;AAED,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC"}
@@ -0,0 +1,51 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'actionxm');
5
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
6
+ const DEFAULT_CONFIG = {
7
+ api_url: 'http://localhost:3002',
8
+ };
9
+ function ensureConfigDir() {
10
+ if (!fs.existsSync(CONFIG_DIR)) {
11
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
12
+ }
13
+ }
14
+ export function getConfigPath() {
15
+ return CONFIG_FILE;
16
+ }
17
+ export function readConfig() {
18
+ try {
19
+ if (!fs.existsSync(CONFIG_FILE)) {
20
+ return { ...DEFAULT_CONFIG };
21
+ }
22
+ const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
23
+ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
24
+ }
25
+ catch {
26
+ return { ...DEFAULT_CONFIG };
27
+ }
28
+ }
29
+ export function writeConfig(config) {
30
+ ensureConfigDir();
31
+ const data = JSON.stringify(config, null, 2) + '\n';
32
+ fs.writeFileSync(CONFIG_FILE, data, { mode: 0o600 });
33
+ }
34
+ export function updateConfig(partial) {
35
+ const config = readConfig();
36
+ writeConfig({ ...config, ...partial });
37
+ }
38
+ export function clearAuth() {
39
+ const config = readConfig();
40
+ delete config.access_token;
41
+ delete config.user;
42
+ delete config.sites;
43
+ delete config.current_site_id;
44
+ delete config.current_site_name;
45
+ writeConfig(config);
46
+ }
47
+ export function isAuthenticated() {
48
+ const config = readConfig();
49
+ return !!config.access_token;
50
+ }
51
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAqBzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAClE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,cAAc,GAAmB;IACrC,OAAO,EAAE,uBAAuB;CACjC,CAAC;AAEF,SAAS,eAAe;IACtB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,eAAe,EAAE,CAAC;IAClB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgC;IAC3D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,YAAY,CAAC;IAC3B,OAAO,MAAM,CAAC,IAAI,CAAC;IACnB,OAAO,MAAM,CAAC,KAAK,CAAC;IACpB,OAAO,MAAM,CAAC,eAAe,CAAC;IAC9B,OAAO,MAAM,CAAC,iBAAiB,CAAC;IAChC,WAAW,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Print a simple table to stdout.
3
+ */
4
+ export declare function printTable(headers: string[], rows: string[][]): void;
5
+ /**
6
+ * Print a key-value pair.
7
+ */
8
+ export declare function printKeyValue(key: string, value: string): void;
9
+ /**
10
+ * Print an error and exit with code 1.
11
+ */
12
+ export declare function exitWithError(message: string): never;
13
+ /**
14
+ * Print a success message.
15
+ */
16
+ export declare function printSuccess(message: string): void;
17
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAcpE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAGpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD"}
@@ -0,0 +1,37 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Print a simple table to stdout.
4
+ */
5
+ export function printTable(headers, rows) {
6
+ // Calculate column widths
7
+ const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] || '').length)));
8
+ // Header
9
+ const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(' ');
10
+ console.log(chalk.bold(headerLine));
11
+ console.log(widths.map((w) => '─'.repeat(w)).join('──'));
12
+ // Rows
13
+ for (const row of rows) {
14
+ const line = row.map((cell, i) => (cell || '').padEnd(widths[i])).join(' ');
15
+ console.log(line);
16
+ }
17
+ }
18
+ /**
19
+ * Print a key-value pair.
20
+ */
21
+ export function printKeyValue(key, value) {
22
+ console.log(`${chalk.dim(key + ':')} ${value}`);
23
+ }
24
+ /**
25
+ * Print an error and exit with code 1.
26
+ */
27
+ export function exitWithError(message) {
28
+ console.error(chalk.red('Error:'), message);
29
+ process.exit(1);
30
+ }
31
+ /**
32
+ * Print a success message.
33
+ */
34
+ export function printSuccess(message) {
35
+ console.log(chalk.green('✓'), message);
36
+ }
37
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAiB,EAAE,IAAgB;IAC5D,0BAA0B;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAElG,SAAS;IACT,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEzD,OAAO;IACP,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,KAAa;IACtD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "actionxm",
3
+ "version": "0.1.1",
4
+ "description": "ActionXM CLI — command-line interface for the ActionXM analytics platform",
5
+ "type": "module",
6
+ "bin": {
7
+ "actionxm": "./dist/index.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsx src/index.ts",
17
+ "typecheck": "tsc --noEmit",
18
+ "test": "vitest run",
19
+ "lint": "eslint src/"
20
+ },
21
+ "dependencies": {
22
+ "commander": "^13.1.0",
23
+ "chalk": "^5.4.1",
24
+ "ora": "^8.2.0",
25
+ "open": "^10.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^24.0.0",
29
+ "eslint": "^10.0.0",
30
+ "eslint-plugin-sonarjs": "^3.0.7",
31
+ "globals": "^17.3.0",
32
+ "tsx": "^4.6.2",
33
+ "typescript": "^5.3.2",
34
+ "typescript-eslint": "^8.56.0",
35
+ "vitest": "^4.0.18"
36
+ },
37
+ "overrides": {
38
+ "eslint-plugin-sonarjs": {
39
+ "eslint": "$eslint"
40
+ },
41
+ "typescript-eslint": {
42
+ "eslint": "$eslint"
43
+ }
44
+ },
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ }
48
+ }