mage-remote-run 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.
- package/README.md +101 -0
- package/api-specs/2.4.8/swagger-paas.json +70180 -0
- package/api-specs/2.4.8/swagger-saas.json +58076 -0
- package/bin/mage-remote-run.js +61 -0
- package/lib/api/client.js +22 -0
- package/lib/api/factory.js +27 -0
- package/lib/api/paas.js +103 -0
- package/lib/api/saas.js +97 -0
- package/lib/api/spec-loader.js +23 -0
- package/lib/commands/connections.js +214 -0
- package/lib/commands/customers.js +196 -0
- package/lib/commands/eav.js +49 -0
- package/lib/commands/orders.js +247 -0
- package/lib/commands/products.js +133 -0
- package/lib/commands/stores.js +113 -0
- package/lib/commands/tax.js +46 -0
- package/lib/commands/websites.js +76 -0
- package/lib/config.js +54 -0
- package/lib/prompts.js +99 -0
- package/lib/utils.js +18 -0
- package/package.json +43 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { createClient } from '../api/factory.js';
|
|
2
|
+
import { printTable, handleError } from '../utils.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
|
|
6
|
+
export function registerStoresCommands(program) {
|
|
7
|
+
const stores = program.command('store').description('Manage store groups');
|
|
8
|
+
|
|
9
|
+
stores.command('list')
|
|
10
|
+
.action(async () => {
|
|
11
|
+
try {
|
|
12
|
+
const client = await createClient();
|
|
13
|
+
const data = await client.get('store/storeGroups');
|
|
14
|
+
const rows = data.map(s => [s.id, s.code, s.name, s.website_id, s.root_category_id]);
|
|
15
|
+
printTable(['ID', 'Code', 'Name', 'Web ID', 'Root Cat'], rows);
|
|
16
|
+
} catch (e) { handleError(e); }
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
stores.command('search <query>')
|
|
20
|
+
.action(async (query) => {
|
|
21
|
+
try {
|
|
22
|
+
const client = await createClient();
|
|
23
|
+
const data = await client.get('store/storeGroups');
|
|
24
|
+
const filtered = data.filter(s => s.name.includes(query) || s.code.includes(query));
|
|
25
|
+
const rows = filtered.map(s => [s.id, s.code, s.name]);
|
|
26
|
+
printTable(['ID', 'Code', 'Name'], rows);
|
|
27
|
+
} catch (e) { handleError(e); }
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
stores.command('delete <id>')
|
|
31
|
+
.action(async (id) => {
|
|
32
|
+
try {
|
|
33
|
+
const client = await createClient();
|
|
34
|
+
const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: `Delete Store Group ${id}?` }]);
|
|
35
|
+
if (!confirm) return;
|
|
36
|
+
await client.delete(`store/storeGroups/${id}`);
|
|
37
|
+
console.log(chalk.green(`Store Group ${id} deleted.`));
|
|
38
|
+
} catch (e) { handleError(e); }
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
stores.command('edit <id>')
|
|
42
|
+
.action(async (id) => {
|
|
43
|
+
try {
|
|
44
|
+
const client = await createClient();
|
|
45
|
+
const all = await client.get('store/storeGroups');
|
|
46
|
+
const current = all.find(s => s.id == id);
|
|
47
|
+
if (!current) throw new Error(`Store ${id} not found`);
|
|
48
|
+
|
|
49
|
+
const answers = await inquirer.prompt([
|
|
50
|
+
{ name: 'name', message: 'Name', default: current.name },
|
|
51
|
+
{ name: 'code', message: 'Code', default: current.code },
|
|
52
|
+
{ name: 'website_id', message: 'Website ID', default: current.website_id }
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
await client.put(`store/storeGroups/${id}`, { group: { id: parseInt(id), ...answers } });
|
|
56
|
+
console.log(chalk.green(`Store ${id} updated.`));
|
|
57
|
+
} catch (e) { handleError(e); }
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Store Views
|
|
61
|
+
const views = stores.command('view').description('Manage store views');
|
|
62
|
+
|
|
63
|
+
views.command('list')
|
|
64
|
+
.action(async () => {
|
|
65
|
+
try {
|
|
66
|
+
const client = await createClient();
|
|
67
|
+
const data = await client.get('store/storeViews');
|
|
68
|
+
const rows = data.map(v => [v.id, v.code, v.name, v.store_group_id, v.is_active]);
|
|
69
|
+
printTable(['ID', 'Code', 'Name', 'Group ID', 'Active'], rows);
|
|
70
|
+
} catch (e) { handleError(e); }
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
views.command('search <query>')
|
|
74
|
+
.action(async (query) => {
|
|
75
|
+
try {
|
|
76
|
+
const client = await createClient();
|
|
77
|
+
const data = await client.get('store/storeViews');
|
|
78
|
+
const filtered = data.filter(v => v.name.includes(query) || v.code.includes(query));
|
|
79
|
+
const rows = filtered.map(v => [v.id, v.code, v.name]);
|
|
80
|
+
printTable(['ID', 'Code', 'Name'], rows);
|
|
81
|
+
} catch (e) { handleError(e); }
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
views.command('delete <id>')
|
|
85
|
+
.action(async (id) => {
|
|
86
|
+
try {
|
|
87
|
+
const client = await createClient();
|
|
88
|
+
const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: `Delete Store View ${id}?` }]);
|
|
89
|
+
if (!confirm) return;
|
|
90
|
+
await client.delete(`store/storeViews/${id}`);
|
|
91
|
+
console.log(chalk.green(`Store View ${id} deleted.`));
|
|
92
|
+
} catch (e) { handleError(e); }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
views.command('edit <id>')
|
|
96
|
+
.action(async (id) => {
|
|
97
|
+
try {
|
|
98
|
+
const client = await createClient();
|
|
99
|
+
const all = await client.get('store/storeViews');
|
|
100
|
+
const current = all.find(v => v.id == id);
|
|
101
|
+
if (!current) throw new Error(`View ${id} not found`);
|
|
102
|
+
|
|
103
|
+
const answers = await inquirer.prompt([
|
|
104
|
+
{ name: 'name', message: 'Name', default: current.name },
|
|
105
|
+
{ name: 'code', message: 'Code', default: current.code },
|
|
106
|
+
{ name: 'is_active', message: 'Is Active (0/1)', default: current.is_active }
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
await client.put(`store/storeViews/${id}`, { store: { id: parseInt(id), ...answers } });
|
|
110
|
+
console.log(chalk.green(`Store View ${id} updated.`));
|
|
111
|
+
} catch (e) { handleError(e); }
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createClient } from '../api/factory.js';
|
|
2
|
+
import { printTable, handleError } from '../utils.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
export function registerTaxCommands(program) {
|
|
6
|
+
const tax = program.command('tax').description('Manage tax classes');
|
|
7
|
+
|
|
8
|
+
const taxClass = tax.command('class').description('Manage tax classes');
|
|
9
|
+
|
|
10
|
+
taxClass.command('list')
|
|
11
|
+
.description('List tax classes')
|
|
12
|
+
.option('-p, --page <number>', 'Page number', '1')
|
|
13
|
+
.option('-s, --size <number>', 'Page size', '20')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
try {
|
|
16
|
+
const client = await createClient();
|
|
17
|
+
const params = {
|
|
18
|
+
'searchCriteria[currentPage]': options.page,
|
|
19
|
+
'searchCriteria[pageSize]': options.size
|
|
20
|
+
};
|
|
21
|
+
const data = await client.get('taxClasses/search', params);
|
|
22
|
+
const rows = (data.items || []).map(tc => [
|
|
23
|
+
tc.class_id,
|
|
24
|
+
tc.class_name,
|
|
25
|
+
tc.class_type
|
|
26
|
+
]);
|
|
27
|
+
console.log(chalk.bold(`Total: ${data.total_count}, Page: ${options.page}, Size: ${options.size}`));
|
|
28
|
+
printTable(['ID', 'Name', 'Type'], rows);
|
|
29
|
+
} catch (e) { handleError(e); }
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
taxClass.command('show <id>')
|
|
33
|
+
.description('Show tax class details')
|
|
34
|
+
.action(async (id) => {
|
|
35
|
+
try {
|
|
36
|
+
const client = await createClient();
|
|
37
|
+
const data = await client.get(`taxClasses/${id}`);
|
|
38
|
+
|
|
39
|
+
console.log(chalk.bold.blue('\nTax Class Details:'));
|
|
40
|
+
console.log(`${chalk.bold('ID:')} ${data.class_id}`);
|
|
41
|
+
console.log(`${chalk.bold('Name:')} ${data.class_name}`);
|
|
42
|
+
console.log(`${chalk.bold('Type:')} ${data.class_type}`);
|
|
43
|
+
|
|
44
|
+
} catch (e) { handleError(e); }
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createClient } from '../api/factory.js';
|
|
2
|
+
import { printTable, handleError } from '../utils.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
|
|
6
|
+
export function registerWebsitesCommands(program) {
|
|
7
|
+
const websites = program.command('website').description('Manage websites');
|
|
8
|
+
|
|
9
|
+
websites.command('list')
|
|
10
|
+
.description('List all websites')
|
|
11
|
+
.action(async () => {
|
|
12
|
+
try {
|
|
13
|
+
const client = await createClient();
|
|
14
|
+
const data = await client.get('store/websites');
|
|
15
|
+
const rows = data.map(w => [w.id, w.code, w.name, w.default_group_id]);
|
|
16
|
+
printTable(['ID', 'Code', 'Name', 'Def Group ID'], rows);
|
|
17
|
+
} catch (e) { handleError(e); }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
websites.command('search <query>')
|
|
21
|
+
.description('Search websites by code or name (local filter)')
|
|
22
|
+
.action(async (query) => {
|
|
23
|
+
try {
|
|
24
|
+
const client = await createClient();
|
|
25
|
+
const data = await client.get('store/websites');
|
|
26
|
+
const filtered = data.filter(w =>
|
|
27
|
+
w.code.includes(query) || w.name.includes(query)
|
|
28
|
+
);
|
|
29
|
+
const rows = filtered.map(w => [w.id, w.code, w.name]);
|
|
30
|
+
printTable(['ID', 'Code', 'Name'], rows);
|
|
31
|
+
} catch (e) { handleError(e); }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
websites.command('delete <id>')
|
|
35
|
+
.description('Delete a website by ID')
|
|
36
|
+
.action(async (id) => {
|
|
37
|
+
try {
|
|
38
|
+
const client = await createClient();
|
|
39
|
+
// Confirm
|
|
40
|
+
const { confirm } = await inquirer.prompt([{
|
|
41
|
+
type: 'confirm',
|
|
42
|
+
name: 'confirm',
|
|
43
|
+
message: `Are you sure you want to delete website ID ${id}?`
|
|
44
|
+
}]);
|
|
45
|
+
if (!confirm) return;
|
|
46
|
+
|
|
47
|
+
await client.delete(`store/websites/${id}`);
|
|
48
|
+
console.log(chalk.green(`Website ${id} deleted.`));
|
|
49
|
+
} catch (e) { handleError(e); }
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
websites.command('edit <id>')
|
|
53
|
+
.description('Edit a website')
|
|
54
|
+
.action(async (id) => {
|
|
55
|
+
try {
|
|
56
|
+
const client = await createClient();
|
|
57
|
+
// Fetch current
|
|
58
|
+
// Actually Magento doesn't have a single GET /store/websites/:id easily publicly documented distinct from the list?
|
|
59
|
+
// But let's assume we fetch list and find it.
|
|
60
|
+
const all = await client.get('store/websites');
|
|
61
|
+
const current = all.find(w => w.id == id);
|
|
62
|
+
if (!current) throw new Error(`Website ${id} not found`);
|
|
63
|
+
|
|
64
|
+
const answers = await inquirer.prompt([
|
|
65
|
+
{ name: 'name', message: 'Name', default: current.name },
|
|
66
|
+
{ name: 'code', message: 'Code', default: current.code },
|
|
67
|
+
{ name: 'default_group_id', message: 'Group ID', default: current.default_group_id },
|
|
68
|
+
{ name: 'sort_order', message: 'Sort Order', default: current.sort_order }
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
// PUT /V1/store/websites/:id
|
|
72
|
+
await client.put(`store/websites/${id}`, { website: { id: parseInt(id), ...answers } });
|
|
73
|
+
console.log(chalk.green(`Website ${id} updated.`));
|
|
74
|
+
} catch (e) { handleError(e); }
|
|
75
|
+
});
|
|
76
|
+
}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import envPaths from 'env-paths';
|
|
4
|
+
import { mkdirp } from 'mkdirp';
|
|
5
|
+
|
|
6
|
+
const paths = envPaths('mage-remote-run', { suffix: '' });
|
|
7
|
+
const CONFIG_DIR = paths.config;
|
|
8
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
9
|
+
|
|
10
|
+
export async function loadConfig() {
|
|
11
|
+
try {
|
|
12
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
13
|
+
return { profiles: {}, activeProfile: null };
|
|
14
|
+
}
|
|
15
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
16
|
+
return JSON.parse(data);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
console.error("Error loading config:", e.message);
|
|
19
|
+
return { profiles: {}, activeProfile: null };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function saveConfig(config) {
|
|
24
|
+
try {
|
|
25
|
+
await mkdirp(CONFIG_DIR);
|
|
26
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
27
|
+
console.log(`Configuration saved to ${CONFIG_FILE}`);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error("Error saving config:", e.message);
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function addProfile(name, settings) {
|
|
35
|
+
const config = await loadConfig();
|
|
36
|
+
config.profiles[name] = settings;
|
|
37
|
+
// Set as active if it's the first one
|
|
38
|
+
if (!config.activeProfile) {
|
|
39
|
+
config.activeProfile = name;
|
|
40
|
+
}
|
|
41
|
+
await saveConfig(config);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getActiveProfile() {
|
|
45
|
+
const config = await loadConfig();
|
|
46
|
+
if (!config.activeProfile || !config.profiles[config.activeProfile]) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return config.profiles[config.activeProfile];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getConfigPath() {
|
|
53
|
+
return CONFIG_FILE;
|
|
54
|
+
}
|
package/lib/prompts.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { input, select, password, confirm } from '@inquirer/prompts';
|
|
2
|
+
|
|
3
|
+
export async function askForProfileSettings(defaults = {}) {
|
|
4
|
+
const type = await select({
|
|
5
|
+
message: 'System Type:',
|
|
6
|
+
default: defaults.type,
|
|
7
|
+
choices: [
|
|
8
|
+
{ name: 'Magento Open Source (On-Premises)', value: 'magento-os' },
|
|
9
|
+
{ name: 'Mage-OS (On-Premises)', value: 'mage-os' },
|
|
10
|
+
{ name: 'Adobe Commerce (On-Premises)', value: 'ac-on-prem' },
|
|
11
|
+
{ name: 'Adobe Commerce Cloud (PaaS)', value: 'ac-cloud-paas' },
|
|
12
|
+
{ name: 'Adobe Commerce as a Cloud Service (SaaS)', value: 'ac-saas' }
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const url = await input({
|
|
17
|
+
message: 'Instance URL (e.g., https://magento.test):',
|
|
18
|
+
default: defaults.url,
|
|
19
|
+
validate: value => value ? true : 'URL is required'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
let authConfig = {};
|
|
23
|
+
|
|
24
|
+
if (type === 'ac-saas') {
|
|
25
|
+
const clientId = await input({
|
|
26
|
+
message: 'Client ID:',
|
|
27
|
+
default: defaults.auth?.clientId,
|
|
28
|
+
validate: value => value ? true : 'Client ID is required'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const clientSecret = await password({
|
|
32
|
+
message: 'Client Secret:',
|
|
33
|
+
description: defaults.auth?.clientSecret ? '(Leave empty to keep current)' : undefined,
|
|
34
|
+
validate: value => (value || defaults.auth?.clientSecret) ? true : 'Client Secret is required'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// If user entered nothing but we have default, use default.
|
|
38
|
+
// Inquirer password prompt with default returns default if empty.
|
|
39
|
+
// We just need to make sure we don't return empty string if default missed.
|
|
40
|
+
// Actually, inquirer returns default.
|
|
41
|
+
|
|
42
|
+
authConfig = { clientId, clientSecret: clientSecret || defaults.auth?.clientSecret };
|
|
43
|
+
} else {
|
|
44
|
+
const method = await select({
|
|
45
|
+
message: 'Authentication Method:',
|
|
46
|
+
default: defaults.auth?.method,
|
|
47
|
+
choices: [
|
|
48
|
+
{ name: 'Bearer Token', value: 'bearer' },
|
|
49
|
+
{ name: 'OAuth 1.0a', value: 'oauth1' }
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (method === 'bearer') {
|
|
54
|
+
const token = await password({
|
|
55
|
+
message: 'Access Token:',
|
|
56
|
+
description: defaults.auth?.token ? '(Leave empty to keep current)' : undefined,
|
|
57
|
+
validate: value => (value || defaults.auth?.token) ? true : 'Token is required'
|
|
58
|
+
});
|
|
59
|
+
authConfig = { method: 'bearer', token: token || defaults.auth?.token };
|
|
60
|
+
} else {
|
|
61
|
+
const consumerKey = await input({
|
|
62
|
+
message: 'Consumer Key:',
|
|
63
|
+
default: defaults.auth?.consumerKey
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const consumerSecret = await password({
|
|
67
|
+
message: 'Consumer Secret:',
|
|
68
|
+
description: defaults.auth?.consumerSecret ? '(Leave empty to keep current)' : undefined,
|
|
69
|
+
validate: value => (value || defaults.auth?.consumerSecret) ? true : 'Consumer Secret is required'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const accessToken = await password({
|
|
73
|
+
message: 'Access Token:',
|
|
74
|
+
description: defaults.auth?.accessToken ? '(Leave empty to keep current)' : undefined,
|
|
75
|
+
validate: value => (value || defaults.auth?.accessToken) ? true : 'Access Token is required'
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const tokenSecret = await password({
|
|
79
|
+
message: 'Token Secret:',
|
|
80
|
+
description: defaults.auth?.tokenSecret ? '(Leave empty to keep current)' : undefined,
|
|
81
|
+
validate: value => (value || defaults.auth?.tokenSecret) ? true : 'Token Secret is required'
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
authConfig = {
|
|
85
|
+
method: 'oauth1',
|
|
86
|
+
consumerKey,
|
|
87
|
+
consumerSecret: consumerSecret || defaults.auth?.consumerSecret,
|
|
88
|
+
accessToken: accessToken || defaults.auth?.accessToken,
|
|
89
|
+
tokenSecret: tokenSecret || defaults.auth?.tokenSecret
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
type,
|
|
96
|
+
url,
|
|
97
|
+
auth: authConfig
|
|
98
|
+
};
|
|
99
|
+
}
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
|
+
|
|
4
|
+
export function printTable(headers, data) {
|
|
5
|
+
const table = new Table({
|
|
6
|
+
head: headers.map(h => chalk.cyan(h)),
|
|
7
|
+
style: { head: [] }
|
|
8
|
+
});
|
|
9
|
+
data.forEach(row => table.push(row));
|
|
10
|
+
console.log(table.toString());
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function handleError(error) {
|
|
14
|
+
console.error(chalk.red('Error:'), error.message);
|
|
15
|
+
if (process.env.DEBUG) {
|
|
16
|
+
console.error(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mage-remote-run",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The remote swiss army knife for Magento Open Source, Mage-OS, Adobe Commerce",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
8
|
+
"start": "node bin/mage-remote-run.js",
|
|
9
|
+
"release": "release-it"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Christian Münch",
|
|
14
|
+
"email": "christian@muench.dev",
|
|
15
|
+
"url": "https://muench.dev"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"bin": {
|
|
20
|
+
"mage-remote-run": "./bin/mage-remote-run.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"bin/*",
|
|
24
|
+
"lib/*",
|
|
25
|
+
"**/api-specs/*",
|
|
26
|
+
"!**/*.test.js"
|
|
27
|
+
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@inquirer/prompts": "^8.1.0",
|
|
30
|
+
"axios": "^1.13.2",
|
|
31
|
+
"chalk": "^5.6.2",
|
|
32
|
+
"cli-table3": "^0.6.5",
|
|
33
|
+
"commander": "^14.0.2",
|
|
34
|
+
"env-paths": "^3.0.0",
|
|
35
|
+
"inquirer": "^13.1.0",
|
|
36
|
+
"mkdirp": "^3.0.1",
|
|
37
|
+
"oauth-1.0a": "^2.2.6",
|
|
38
|
+
"openapi-client-axios": "^7.8.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"jest": "^30.2.0"
|
|
42
|
+
}
|
|
43
|
+
}
|