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.
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +94 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +48 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/sites.d.ts +3 -0
- package/dist/commands/sites.d.ts.map +1 -0
- package/dist/commands/sites.js +74 -0
- package/dist/commands/sites.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +13 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +56 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/auth.d.ts +51 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +79 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +25 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +51 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/utils/output.d.ts +17 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +37 -0
- package/dist/utils/output.js.map +1 -0
- package/package.json +48 -0
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/lib/auth.js
ADDED
|
@@ -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
|
+
}
|