mage-remote-run 0.18.0 → 0.20.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/bin/mage-remote-run.js +5 -12
- package/lib/command-registry.js +49 -38
- package/lib/commands/events.js +277 -0
- package/lib/commands/import.js +275 -0
- package/lib/commands/webhooks.js +461 -22
- package/lib/utils.js +44 -0
- package/package.json +3 -1
- package/lib/commands/adobe-io-events.js +0 -70
package/bin/mage-remote-run.js
CHANGED
|
@@ -39,14 +39,14 @@ program
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
import {
|
|
42
|
-
|
|
43
|
-
registerCoreCommands,
|
|
44
|
-
registerCloudCommands
|
|
42
|
+
registerCommands
|
|
45
43
|
} from '../lib/command-registry.js';
|
|
46
44
|
import { getActiveProfile } from '../lib/config.js';
|
|
47
45
|
import { startMcpServer } from '../lib/mcp.js';
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
// Connection commands are registered dynamically via registerCommands
|
|
48
|
+
// But we need them registered early if we want them to show up in help even if config fails?
|
|
49
|
+
// Actually registerCommands handles null profile by registering connection commands only.
|
|
50
50
|
|
|
51
51
|
program.command('mcp')
|
|
52
52
|
.description('Run as MCP server')
|
|
@@ -58,14 +58,7 @@ program.command('mcp')
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
const profile = await getActiveProfile();
|
|
61
|
-
|
|
62
|
-
if (profile) {
|
|
63
|
-
registerCoreCommands(program);
|
|
64
|
-
|
|
65
|
-
if (profile.type === 'ac-cloud-paas' || profile.type === 'ac-saas') {
|
|
66
|
-
registerCloudCommands(program);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
61
|
+
registerCommands(program, profile);
|
|
69
62
|
|
|
70
63
|
program.hook('preAction', async (thisCommand, actionCommand) => {
|
|
71
64
|
// Check if we have an active profile and if format is not json/xml
|
package/lib/command-registry.js
CHANGED
|
@@ -8,63 +8,74 @@ import { registerProductsCommands } from './commands/products.js';
|
|
|
8
8
|
import { registerCompanyCommands } from './commands/company.js';
|
|
9
9
|
import { registerTaxCommands } from './commands/tax.js';
|
|
10
10
|
import { registerInventoryCommands } from './commands/inventory.js';
|
|
11
|
-
import {
|
|
11
|
+
import { registerEventsCommands } from './commands/events.js';
|
|
12
12
|
import { registerWebhooksCommands } from './commands/webhooks.js';
|
|
13
13
|
import { registerPurchaseOrderCartCommands } from './commands/purchase-order-cart.js';
|
|
14
|
+
import { registerImportCommands } from './commands/import.js';
|
|
14
15
|
import { registerConsoleCommand } from './commands/console.js';
|
|
15
16
|
|
|
16
17
|
export { registerConnectionCommands, registerConsoleCommand };
|
|
17
18
|
|
|
19
|
+
const GROUPS = {
|
|
20
|
+
CORE: [
|
|
21
|
+
registerWebsitesCommands,
|
|
22
|
+
registerStoresCommands,
|
|
23
|
+
registerCustomersCommands,
|
|
24
|
+
registerOrdersCommands,
|
|
25
|
+
registerEavCommands,
|
|
26
|
+
registerProductsCommands,
|
|
27
|
+
registerTaxCommands,
|
|
28
|
+
registerInventoryCommands,
|
|
29
|
+
registerConsoleCommand
|
|
30
|
+
],
|
|
31
|
+
COMMERCE: [
|
|
32
|
+
registerCompanyCommands,
|
|
33
|
+
registerPurchaseOrderCartCommands
|
|
34
|
+
],
|
|
35
|
+
CLOUD: [
|
|
36
|
+
registerEventsCommands,
|
|
37
|
+
registerWebhooksCommands
|
|
38
|
+
],
|
|
39
|
+
IMPORT: [
|
|
40
|
+
registerImportCommands
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const TYPE_MAPPINGS = {
|
|
45
|
+
'magento-os': [...GROUPS.CORE],
|
|
46
|
+
'mage-os': [...GROUPS.CORE],
|
|
47
|
+
'ac-on-prem': [...GROUPS.CORE, ...GROUPS.COMMERCE, ...GROUPS.IMPORT],
|
|
48
|
+
'ac-cloud-paas': [...GROUPS.CORE, ...GROUPS.COMMERCE, ...GROUPS.CLOUD, ...GROUPS.IMPORT],
|
|
49
|
+
'ac-saas': [...GROUPS.CORE, ...GROUPS.COMMERCE, ...GROUPS.CLOUD, ...GROUPS.IMPORT] // Assuming SaaS has same feature set as PaaS for CLI
|
|
50
|
+
};
|
|
51
|
+
|
|
18
52
|
export function registerCoreCommands(program) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
registerCustomersCommands(program);
|
|
22
|
-
registerOrdersCommands(program);
|
|
23
|
-
registerEavCommands(program);
|
|
24
|
-
registerProductsCommands(program);
|
|
25
|
-
registerTaxCommands(program);
|
|
26
|
-
registerInventoryCommands(program);
|
|
27
|
-
registerConsoleCommand(program);
|
|
53
|
+
// Backward compatibility: Register CORE group
|
|
54
|
+
GROUPS.CORE.forEach(registrar => registrar(program));
|
|
28
55
|
}
|
|
29
56
|
|
|
30
57
|
export function registerCloudCommands(program) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
registerPurchaseOrderCartCommands(program);
|
|
34
|
-
registerWebhooksCommands(program);
|
|
58
|
+
// Backward compatibility
|
|
59
|
+
[...GROUPS.COMMERCE, ...GROUPS.CLOUD, ...GROUPS.IMPORT].forEach(registrar => registrar(program));
|
|
35
60
|
}
|
|
36
61
|
|
|
62
|
+
// Deprecated: Use registerCommands instead
|
|
37
63
|
export function registerAllCommands(program) {
|
|
38
64
|
registerConnectionCommands(program);
|
|
39
|
-
|
|
40
|
-
|
|
65
|
+
const all = new Set([...GROUPS.CORE, ...GROUPS.COMMERCE, ...GROUPS.CLOUD, ...GROUPS.IMPORT]);
|
|
66
|
+
all.forEach(registrar => registrar(program));
|
|
41
67
|
}
|
|
42
68
|
|
|
43
|
-
// Alias for backwards compatibility with console.js (and potential other usages)
|
|
44
69
|
export const registerCommands = (program, profile) => {
|
|
45
|
-
// Note: console.js passes profile, but registerAllCommands doesn't strictly use it
|
|
46
|
-
// (it registers everything, profile checks happen inside or via selective registration).
|
|
47
|
-
// The original behavior in console.js:
|
|
48
|
-
// const profile = await getActiveProfile();
|
|
49
|
-
// registerCommands(localProgram, profile);
|
|
50
|
-
|
|
51
|
-
// In bin/mage-remote-run.js old logic:
|
|
52
|
-
// registerConnectionCommands(program);
|
|
53
|
-
// if (profile) { registerWebsitesCommands... }
|
|
54
|
-
|
|
55
|
-
// We should replicate that 'selective' registration if we want to match exact behavior?
|
|
56
|
-
// BUT console.js wants to register ALL available commands for the profile.
|
|
57
|
-
|
|
58
70
|
registerConnectionCommands(program);
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
registerCloudCommands(program);
|
|
72
|
+
if (profile && profile.type) {
|
|
73
|
+
const registrars = TYPE_MAPPINGS[profile.type];
|
|
74
|
+
if (registrars) {
|
|
75
|
+
registrars.forEach(registrar => registrar(program, profile));
|
|
76
|
+
} else {
|
|
77
|
+
// Fallback for unknown types
|
|
78
|
+
GROUPS.CORE.forEach(registrar => registrar(program));
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
81
|
};
|
|
@@ -0,0 +1,277 @@
|
|
|
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 registerEventsCommands(program) {
|
|
7
|
+
const events = program.command('event').description('Manage Adobe I/O Events');
|
|
8
|
+
|
|
9
|
+
//-------------------------------------------------------
|
|
10
|
+
// "event check-configuration" Command (Renamed from adobe-io-event)
|
|
11
|
+
//-------------------------------------------------------
|
|
12
|
+
events.command('check-configuration')
|
|
13
|
+
.description('Check Adobe I/O Event configuration')
|
|
14
|
+
.option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
|
|
15
|
+
.addHelpText('after', `
|
|
16
|
+
Examples:
|
|
17
|
+
$ mage-remote-run event check-configuration
|
|
18
|
+
$ mage-remote-run event check-configuration --format json
|
|
19
|
+
`)
|
|
20
|
+
.action(async (options) => {
|
|
21
|
+
try {
|
|
22
|
+
const client = await createClient();
|
|
23
|
+
const headers = {};
|
|
24
|
+
if (options.format === 'json') headers['Accept'] = 'application/json';
|
|
25
|
+
else if (options.format === 'xml') headers['Accept'] = 'application/xml';
|
|
26
|
+
|
|
27
|
+
const data = await client.get('V1/adobe_io_events/check_configuration', {}, { headers });
|
|
28
|
+
|
|
29
|
+
if (options.format === 'json') {
|
|
30
|
+
console.log(JSON.stringify(data, null, 2));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (options.format === 'xml') {
|
|
34
|
+
console.log(data);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log(chalk.bold.blue('\n🔍 Configuration Check Result'));
|
|
39
|
+
console.log(chalk.gray('━'.repeat(60)));
|
|
40
|
+
|
|
41
|
+
if (typeof data === 'object' && data !== null) {
|
|
42
|
+
if (Array.isArray(data)) {
|
|
43
|
+
console.log(JSON.stringify(data, null, 2));
|
|
44
|
+
} else {
|
|
45
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
46
|
+
const label = key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
47
|
+
let displayValue = value;
|
|
48
|
+
if (typeof value === 'boolean') {
|
|
49
|
+
displayValue = value ? chalk.green('Yes') : chalk.red('No');
|
|
50
|
+
} else if (value === null) {
|
|
51
|
+
displayValue = chalk.gray('null');
|
|
52
|
+
} else if (typeof value === 'object') {
|
|
53
|
+
displayValue = JSON.stringify(value);
|
|
54
|
+
}
|
|
55
|
+
console.log(` ${chalk.bold(label + ':').padEnd(35)} ${displayValue}`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
console.log(` ${data}`);
|
|
60
|
+
}
|
|
61
|
+
console.log('');
|
|
62
|
+
} catch (e) { handleError(e); }
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const provider = events.command('provider').description('Manage event providers');
|
|
66
|
+
|
|
67
|
+
//-------------------------------------------------------
|
|
68
|
+
// "event provider list" Command
|
|
69
|
+
//-------------------------------------------------------
|
|
70
|
+
provider.command('list')
|
|
71
|
+
.description('List event providers')
|
|
72
|
+
.option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
|
|
73
|
+
.addHelpText('after', `
|
|
74
|
+
Examples:
|
|
75
|
+
$ mage-remote-run event provider list
|
|
76
|
+
`)
|
|
77
|
+
.action(async (options) => {
|
|
78
|
+
try {
|
|
79
|
+
const client = await createClient();
|
|
80
|
+
const headers = {};
|
|
81
|
+
if (options.format === 'json') headers['Accept'] = 'application/json';
|
|
82
|
+
|
|
83
|
+
const data = await client.get('V1/eventing/eventProvider', {}, { headers });
|
|
84
|
+
|
|
85
|
+
if (options.format === 'json') {
|
|
86
|
+
console.log(JSON.stringify(data, null, 2));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const rows = (data || []).map(p => [p.id, p.label, p.description]);
|
|
91
|
+
printTable(['ID', 'Label', 'Description'], rows);
|
|
92
|
+
} catch (e) { handleError(e); }
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
//-------------------------------------------------------
|
|
96
|
+
// "event provider show" Command
|
|
97
|
+
//-------------------------------------------------------
|
|
98
|
+
provider.command('show <id>')
|
|
99
|
+
.description('Show event provider details')
|
|
100
|
+
.option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
|
|
101
|
+
.action(async (id, options) => {
|
|
102
|
+
try {
|
|
103
|
+
const client = await createClient();
|
|
104
|
+
const headers = {};
|
|
105
|
+
if (options.format === 'json') headers['Accept'] = 'application/json';
|
|
106
|
+
|
|
107
|
+
// We try fetching all and filtering because the user mapped "show" to the specific endpoint that looks like a collection
|
|
108
|
+
const data = await client.get('V1/eventing/eventProvider', {}, { headers });
|
|
109
|
+
|
|
110
|
+
let item;
|
|
111
|
+
if (Array.isArray(data)) {
|
|
112
|
+
item = data.find(p => p.id == id);
|
|
113
|
+
} else if (data.id == id) {
|
|
114
|
+
item = data;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!item) {
|
|
118
|
+
throw new Error(`Event Provider '${id}' not found.`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (options.format === 'json') {
|
|
122
|
+
console.log(JSON.stringify(item, null, 2));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
console.log(chalk.bold.blue('\n🔍 Event Provider Details'));
|
|
127
|
+
console.log(chalk.gray('━'.repeat(60)));
|
|
128
|
+
Object.entries(item).forEach(([key, value]) => {
|
|
129
|
+
console.log(` ${chalk.bold(key + ':').padEnd(20)} ${value}`);
|
|
130
|
+
});
|
|
131
|
+
console.log('');
|
|
132
|
+
|
|
133
|
+
} catch (e) { handleError(e); }
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
//-------------------------------------------------------
|
|
137
|
+
// "event provider create" Command
|
|
138
|
+
//-------------------------------------------------------
|
|
139
|
+
provider.command('create')
|
|
140
|
+
.description('Create a new event provider')
|
|
141
|
+
.action(async () => {
|
|
142
|
+
try {
|
|
143
|
+
const client = await createClient();
|
|
144
|
+
|
|
145
|
+
// Attempt to auto-detect instance_id from profile settings (SaaS only)
|
|
146
|
+
let defaultInstanceId = undefined;
|
|
147
|
+
try {
|
|
148
|
+
console.log(chalk.gray('Attempting to auto-detect Instance ID...'));
|
|
149
|
+
const { getActiveProfile } = await import('../config.js');
|
|
150
|
+
const profile = await getActiveProfile();
|
|
151
|
+
|
|
152
|
+
if (profile && (profile.type === 'ac-saas' || profile.type === 'saas')) {
|
|
153
|
+
try {
|
|
154
|
+
// Extract last part of URL path
|
|
155
|
+
const url = new URL(profile.url);
|
|
156
|
+
const pathParts = url.pathname.split('/').filter(p => p.length > 0);
|
|
157
|
+
if (pathParts.length > 0) {
|
|
158
|
+
defaultInstanceId = pathParts[pathParts.length - 1];
|
|
159
|
+
console.log(chalk.gray(`Found Instance ID (from URL): ${defaultInstanceId}`));
|
|
160
|
+
} else {
|
|
161
|
+
console.log(chalk.gray('Could not extract Instance ID from URL.'));
|
|
162
|
+
}
|
|
163
|
+
} catch (e) {
|
|
164
|
+
console.log(chalk.gray('Invalid URL in profile configuration.'));
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
console.log(chalk.gray('Instance ID detection only supported for SaaS connections.'));
|
|
168
|
+
}
|
|
169
|
+
} catch (e) {
|
|
170
|
+
console.log(chalk.gray('Could not auto-detect Instance ID.'));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const answers = await inquirer.prompt([
|
|
174
|
+
{
|
|
175
|
+
type: 'input',
|
|
176
|
+
name: 'provider_id',
|
|
177
|
+
message: `Enter Provider ID ${chalk.dim('(Found in Adobe Developer Console > Project > Events > Event Provider > ID)')}:`,
|
|
178
|
+
validate: input => input ? true : 'Provider ID is required'
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'input',
|
|
182
|
+
name: 'label',
|
|
183
|
+
message: `Enter Provider Label ${chalk.dim('(A friendly name for this provider)')}:`,
|
|
184
|
+
validate: input => input ? true : 'Label is required'
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
type: 'input',
|
|
188
|
+
name: 'description',
|
|
189
|
+
message: `Enter Provider Description ${chalk.dim('(Optional)')}:`
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
type: 'input',
|
|
193
|
+
name: 'instance_id',
|
|
194
|
+
message: `Enter Instance ID ${chalk.dim('(Found in "check-configuration" or Adobe Developer Console)')}:`,
|
|
195
|
+
default: defaultInstanceId
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'editor',
|
|
199
|
+
name: 'workspace_configuration',
|
|
200
|
+
message: `Enter Workspace Configuration ${chalk.dim('(JSON from Adobe Developer Console > Download Project Config)')}:`
|
|
201
|
+
}
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
const payload = {
|
|
205
|
+
eventProvider: {
|
|
206
|
+
provider_id: answers.provider_id,
|
|
207
|
+
instance_id: answers.instance_id,
|
|
208
|
+
label: answers.label,
|
|
209
|
+
description: answers.description,
|
|
210
|
+
workspace_configuration: answers.workspace_configuration
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const result = await client.post('V1/eventing/eventProvider', payload);
|
|
215
|
+
console.log(chalk.green('\n✅ Event Provider Created Successfully'));
|
|
216
|
+
console.log(JSON.stringify(result, null, 2));
|
|
217
|
+
|
|
218
|
+
} catch (e) { handleError(e); }
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
//-------------------------------------------------------
|
|
222
|
+
// "event provider delete" Command
|
|
223
|
+
//-------------------------------------------------------
|
|
224
|
+
provider.command('delete <id>')
|
|
225
|
+
.description('Delete an event provider')
|
|
226
|
+
.action(async (id) => {
|
|
227
|
+
try {
|
|
228
|
+
const client = await createClient();
|
|
229
|
+
// Assumed endpoint based on standard REST, though prompt said DELETE /V1/eventing/eventProvider
|
|
230
|
+
// Usually DELETE requires an ID. I will append the ID.
|
|
231
|
+
// Wait, if the prompt says DELETE /V1/eventing/eventProvider, it MIGHT expect a body or query param?
|
|
232
|
+
// Standard Magento: DELETE /V1/eventing/eventProvider/:id
|
|
233
|
+
// I will try appending ID.
|
|
234
|
+
await client.delete(`V1/eventing/eventProvider/${id}`);
|
|
235
|
+
console.log(chalk.green(`\n✅ Event Provider '${id}' deleted successfully.`));
|
|
236
|
+
} catch (e) { handleError(e); }
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
//-------------------------------------------------------
|
|
240
|
+
// "event supported-list" Command
|
|
241
|
+
//-------------------------------------------------------
|
|
242
|
+
events.command('supported-list')
|
|
243
|
+
.description('List supported events')
|
|
244
|
+
.option('-f, --format <type>', 'Output format (text, json)', 'text')
|
|
245
|
+
.action(async (options) => {
|
|
246
|
+
try {
|
|
247
|
+
const client = await createClient();
|
|
248
|
+
const headers = {};
|
|
249
|
+
if (options.format === 'json') headers['Accept'] = 'application/json';
|
|
250
|
+
|
|
251
|
+
const data = await client.get('V1/eventing/supportedList', {}, { headers });
|
|
252
|
+
|
|
253
|
+
if (options.format === 'json') {
|
|
254
|
+
console.log(JSON.stringify(data, null, 2));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Assuming data is list of strings or objects.
|
|
259
|
+
// If objects, we might need to know structure.
|
|
260
|
+
// Prompt didn't specify structure. Assuming list of strings or objects with 'name'/'id'.
|
|
261
|
+
if (Array.isArray(data)) {
|
|
262
|
+
if (data.length > 0 && typeof data[0] === 'string') {
|
|
263
|
+
data.forEach(d => console.log(d));
|
|
264
|
+
} else {
|
|
265
|
+
// Fallback table
|
|
266
|
+
const keys = Object.keys(data[0] || {});
|
|
267
|
+
const rows = data.map(d => Object.values(d));
|
|
268
|
+
printTable(keys, rows);
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
console.log(data);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
} catch (e) { handleError(e); }
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
}
|