mage-remote-run 0.11.0 → 0.13.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.
@@ -38,40 +38,12 @@ program
38
38
 
39
39
 
40
40
 
41
- import { registerWebsitesCommands } from '../lib/commands/websites.js';
42
- import { registerStoresCommands } from '../lib/commands/stores.js';
43
- import { registerConnectionCommands } from '../lib/commands/connections.js';
44
- import { registerCustomersCommands } from '../lib/commands/customers.js';
45
- import { registerOrdersCommands } from '../lib/commands/orders.js';
46
- import { registerEavCommands } from '../lib/commands/eav.js';
47
- import { registerProductsCommands } from '../lib/commands/products.js';
48
- import { registerCompanyCommands } from '../lib/commands/company.js';
49
- import { registerTaxCommands } from '../lib/commands/tax.js';
50
- import { registerInventoryCommands } from '../lib/commands/inventory.js';
51
- import { registerAdobeIoEventsCommands } from '../lib/commands/adobe-io-events.js';
52
- import { registerWebhooksCommands } from '../lib/commands/webhooks.js';
41
+ import { registerCommands } from '../lib/command-registry.js';
53
42
  import { getActiveProfile } from '../lib/config.js';
54
43
 
55
- registerConnectionCommands(program);
56
-
57
44
  const profile = await getActiveProfile();
58
45
 
59
- if (profile) {
60
- registerWebsitesCommands(program);
61
- registerStoresCommands(program);
62
- registerCustomersCommands(program);
63
- registerOrdersCommands(program);
64
- registerEavCommands(program);
65
- registerProductsCommands(program);
66
- registerTaxCommands(program);
67
- registerInventoryCommands(program);
68
-
69
- if (profile.type === 'ac-cloud-paas' || profile.type === 'ac-saas') {
70
- registerAdobeIoEventsCommands(program);
71
- registerCompanyCommands(program);
72
- registerWebhooksCommands(program);
73
- }
74
- }
46
+ registerCommands(program, profile);
75
47
 
76
48
  program.hook('preAction', async (thisCommand, actionCommand) => {
77
49
  // Check if we have an active profile and if format is not json/xml
@@ -89,70 +61,7 @@ program.hook('preAction', async (thisCommand, actionCommand) => {
89
61
  }
90
62
  });
91
63
 
92
- function resolveCommandMatch(parent, token) {
93
- const tokenLower = token.toLowerCase();
94
-
95
- // Check for exact match first
96
- const exactMatch = parent.commands.find((cmd) => {
97
- return cmd.name().toLowerCase() === tokenLower;
98
- });
99
-
100
- if (exactMatch) {
101
- return {
102
- match: exactMatch,
103
- matches: [exactMatch]
104
- };
105
- }
106
-
107
- const matches = parent.commands.filter((cmd) => {
108
- const name = cmd.name().toLowerCase();
109
- if (name.startsWith(tokenLower)) return true;
110
- const aliases = cmd.aliases ? cmd.aliases() : [];
111
- return aliases.some((alias) => alias.toLowerCase().startsWith(tokenLower));
112
- });
113
-
114
- return {
115
- match: matches.length === 1 ? matches[0] : null,
116
- matches
117
- };
118
- }
119
-
120
- function expandCommandAbbreviations(rootCommand, argv) {
121
- const expanded = [];
122
- let current = rootCommand;
123
- const path = [];
124
-
125
- for (let i = 0; i < argv.length; i += 1) {
126
- const token = argv[i];
127
- if (token.startsWith('-')) {
128
- expanded.push(token);
129
- continue;
130
- }
131
-
132
- if (!current.commands || current.commands.length === 0) {
133
- expanded.push(...argv.slice(i));
134
- break;
135
- }
136
-
137
- const { match, matches } = resolveCommandMatch(current, token);
138
- if (!match) {
139
- if (matches.length > 1) {
140
- const parentName = path.length > 0 ? path.join(' ') : current.name();
141
- const options = matches.map((cmd) => cmd.name()).join(', ');
142
- console.error(`Ambiguous command "${token}" under "${parentName}". Options: ${options}.`);
143
- process.exit(1);
144
- }
145
- expanded.push(token);
146
- continue;
147
- }
148
-
149
- expanded.push(match.name());
150
- current = match;
151
- path.push(match.name());
152
- }
153
-
154
- return expanded;
155
- }
64
+ import { expandCommandAbbreviations } from '../lib/command-helper.js';
156
65
 
157
66
  // Check for first run (no profiles configured and no arguments or just help)
158
67
  // We need to check args length.
@@ -177,7 +86,15 @@ if (!hasProfiles && args.length === 0) {
177
86
  args = ['connection', 'add'];
178
87
  }
179
88
 
180
- args = expandCommandAbbreviations(program, args);
89
+ try {
90
+ args = expandCommandAbbreviations(program, args);
91
+ } catch (e) {
92
+ if (e.isAmbiguous) {
93
+ console.error(e.message);
94
+ process.exit(1);
95
+ }
96
+ throw e;
97
+ }
181
98
  process.argv = [...process.argv.slice(0, 2), ...args];
182
99
 
183
100
  program.parse(process.argv);
@@ -0,0 +1,100 @@
1
+
2
+ export function resolveCommandMatch(parent, token) {
3
+ const tokenLower = token.toLowerCase();
4
+
5
+ // Check for exact match first
6
+ const exactMatch = parent.commands.find((cmd) => {
7
+ return cmd.name().toLowerCase() === tokenLower;
8
+ });
9
+
10
+ if (exactMatch) {
11
+ return {
12
+ match: exactMatch,
13
+ matches: [exactMatch]
14
+ };
15
+ }
16
+
17
+ const matches = parent.commands.filter((cmd) => {
18
+ const name = cmd.name().toLowerCase();
19
+ if (name.startsWith(tokenLower)) return true;
20
+ const aliases = cmd.aliases ? cmd.aliases() : [];
21
+ return aliases.some((alias) => alias.toLowerCase().startsWith(tokenLower));
22
+ });
23
+
24
+ return {
25
+ match: matches.length === 1 ? matches[0] : null,
26
+ matches
27
+ };
28
+ }
29
+
30
+ export function expandCommandAbbreviations(rootCommand, argv) {
31
+ const expanded = [];
32
+ let current = rootCommand;
33
+ const path = [];
34
+
35
+ for (let i = 0; i < argv.length; i += 1) {
36
+ const token = argv[i];
37
+ if (token.startsWith('-')) {
38
+ expanded.push(token);
39
+ continue;
40
+ }
41
+
42
+ if (!current.commands || current.commands.length === 0) {
43
+ expanded.push(...argv.slice(i));
44
+ break;
45
+ }
46
+
47
+ // Feature: Support colon separators
48
+ // If the token contains colons, try to split it and resolve parts
49
+ if (token.includes(':')) {
50
+ const parts = token.split(':');
51
+ const originalArgv = argv.slice(0); // copy
52
+
53
+ // Modify argv effectively for this lookahead
54
+ const remainingArgv = [...parts, ...argv.slice(i + 1)];
55
+
56
+ // Recursively expand the new sequence from current point
57
+ // We need to resolve from 'current' but since expandCommandAbbreviations takes rootCommand,
58
+ // we should probably just verify if these parts are valid commands.
59
+ // But expandCommandAbbreviations is designed to walk from root.
60
+ // However, we are currently at 'current'.
61
+
62
+ // To properly handle "cust:list" where "cust" is from root, we can just replace the token in the list
63
+ // and continue loop, IF the first part matches something.
64
+
65
+ // Let's check if the first part matches a command in current scope
66
+ const firstPart = parts[0];
67
+ const result = resolveCommandMatch(current, firstPart);
68
+
69
+ if (result.match) {
70
+ // If the first part matches, we replace the current token with the split parts
71
+ // and effectively 'restart' processing or just insert them into argv and decrement i to re-process first part
72
+ argv.splice(i, 1, ...parts);
73
+ i--; // Stay on same index to process the first part of the split
74
+ continue;
75
+ }
76
+ }
77
+
78
+ const { match, matches } = resolveCommandMatch(current, token);
79
+ if (!match) {
80
+ if (matches.length > 1) {
81
+ const parentName = path.length > 0 ? path.join(' ') : (current.name() !== 'mage-remote-run' ? current.name() : 'root');
82
+ const options = matches.map((cmd) => cmd.name()).join(', ');
83
+ let errorMessage = `Ambiguous command "${token}" under "${parentName}". Options: ${options}.`;
84
+ // If this is a script, we might not want to console.error directly if we want to test it easily,
85
+ // but complying with original code which did process.exit
86
+ const error = new Error(errorMessage);
87
+ error.isAmbiguous = true;
88
+ throw error;
89
+ }
90
+ expanded.push(token);
91
+ continue;
92
+ }
93
+
94
+ expanded.push(match.name());
95
+ current = match;
96
+ path.push(match.name());
97
+ }
98
+
99
+ return expanded;
100
+ }
@@ -0,0 +1,35 @@
1
+ import { registerWebsitesCommands } from './commands/websites.js';
2
+ import { registerStoresCommands } from './commands/stores.js';
3
+ import { registerConnectionCommands } from './commands/connections.js';
4
+ import { registerCustomersCommands } from './commands/customers.js';
5
+ import { registerOrdersCommands } from './commands/orders.js';
6
+ import { registerEavCommands } from './commands/eav.js';
7
+ import { registerProductsCommands } from './commands/products.js';
8
+ import { registerCompanyCommands } from './commands/company.js';
9
+ import { registerTaxCommands } from './commands/tax.js';
10
+ import { registerInventoryCommands } from './commands/inventory.js';
11
+ import { registerAdobeIoEventsCommands } from './commands/adobe-io-events.js';
12
+ import { registerWebhooksCommands } from './commands/webhooks.js';
13
+ import { registerConsoleCommand } from './commands/console.js';
14
+
15
+ export function registerCommands(program, profile) {
16
+ registerConnectionCommands(program);
17
+ registerConsoleCommand(program);
18
+
19
+ if (profile) {
20
+ registerWebsitesCommands(program);
21
+ registerStoresCommands(program);
22
+ registerCustomersCommands(program);
23
+ registerOrdersCommands(program);
24
+ registerEavCommands(program);
25
+ registerProductsCommands(program);
26
+ registerTaxCommands(program);
27
+ registerInventoryCommands(program);
28
+
29
+ if (profile.type === 'ac-cloud-paas' || profile.type === 'ac-saas') {
30
+ registerAdobeIoEventsCommands(program);
31
+ registerCompanyCommands(program);
32
+ registerWebhooksCommands(program);
33
+ }
34
+ }
35
+ }
@@ -5,6 +5,10 @@ import chalk from 'chalk';
5
5
  export function registerAdobeIoEventsCommands(program) {
6
6
  const adobeIoEvents = program.command('adobe-io-event').description('Manage Adobe I/O Events');
7
7
 
8
+
9
+ //-------------------------------------------------------
10
+ // "adobe-io-event check-configuration" Command
11
+ //-------------------------------------------------------
8
12
  adobeIoEvents.command('check-configuration')
9
13
  .description('Check Adobe I/O Event configuration')
10
14
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -5,6 +5,10 @@ import chalk from 'chalk';
5
5
  export function registerCompanyCommands(program) {
6
6
  const company = program.command('company').description('Manage companies');
7
7
 
8
+
9
+ //-------------------------------------------------------
10
+ // "company list" Command
11
+ //-------------------------------------------------------
8
12
  company.command('list')
9
13
  .description('List companies')
10
14
  .option('-p, --page <number>', 'Page number', '1')
@@ -56,6 +60,10 @@ Examples:
56
60
  } catch (e) { handleError(e); }
57
61
  });
58
62
 
63
+
64
+ //-------------------------------------------------------
65
+ // "company show" Command
66
+ //-------------------------------------------------------
59
67
  company.command('show <companyId>')
60
68
  .description('Show company details')
61
69
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -60,6 +60,10 @@ async function configureAndTestConnection(name, initialSettings = {}) {
60
60
  export function registerConnectionCommands(program) {
61
61
  const connections = program.command('connection').description('Manage mage-remote-run connection profiles');
62
62
 
63
+
64
+ //-------------------------------------------------------
65
+ // "connection add" Command
66
+ //-------------------------------------------------------
63
67
  connections.command('add')
64
68
  .description('Configure a new connection profile')
65
69
  .addHelpText('after', `
@@ -106,6 +110,10 @@ Examples:
106
110
  }
107
111
  });
108
112
 
113
+
114
+ //-------------------------------------------------------
115
+ // "connection list" Command
116
+ //-------------------------------------------------------
109
117
  connections.command('list')
110
118
  .description('List connection profiles')
111
119
  .addHelpText('after', `
@@ -125,6 +133,10 @@ Examples:
125
133
  } catch (e) { handleError(e); }
126
134
  });
127
135
 
136
+
137
+ //-------------------------------------------------------
138
+ // "connection search" Command
139
+ //-------------------------------------------------------
128
140
  connections.command('search <query>')
129
141
  .description('Search connection profiles')
130
142
  .addHelpText('after', `
@@ -140,6 +152,10 @@ Examples:
140
152
  } catch (e) { handleError(e); }
141
153
  });
142
154
 
155
+
156
+ //-------------------------------------------------------
157
+ // "connection delete" Command
158
+ //-------------------------------------------------------
143
159
  connections.command('delete <name>')
144
160
  .description('Delete a connection profile')
145
161
  .addHelpText('after', `
@@ -161,6 +177,10 @@ Examples:
161
177
  } catch (e) { handleError(e); }
162
178
  });
163
179
 
180
+
181
+ //-------------------------------------------------------
182
+ // "connection edit" Command
183
+ //-------------------------------------------------------
164
184
  connections.command('edit [name]')
165
185
  .description('Edit a connection profile')
166
186
  .addHelpText('after', `
@@ -208,6 +228,10 @@ Examples:
208
228
  }
209
229
  });
210
230
 
231
+
232
+ //-------------------------------------------------------
233
+ // "connection test" Command
234
+ //-------------------------------------------------------
211
235
  connections.command('test')
212
236
  .description('Test connection(s)')
213
237
  .option('--all', 'Test all configured connections')
@@ -270,6 +294,10 @@ Examples:
270
294
  if (process.env.DEBUG) console.error(e);
271
295
  }
272
296
  });
297
+
298
+ //-------------------------------------------------------
299
+ // "connection status" Command
300
+ //-------------------------------------------------------
273
301
  connections.command('status')
274
302
  .description('Show current configuration status')
275
303
  .addHelpText('after', `
@@ -294,6 +322,10 @@ Examples:
294
322
  } catch (e) { handleError(e); }
295
323
  });
296
324
 
325
+
326
+ //-------------------------------------------------------
327
+ // "connection select" Command
328
+ //-------------------------------------------------------
297
329
  connections.command('select')
298
330
  .description('Select the active connection profile (aliases: change, switch)')
299
331
  .aliases(['switch', 'change'])
@@ -323,6 +355,10 @@ Examples:
323
355
  } catch (e) { handleError(e); }
324
356
  });
325
357
 
358
+
359
+ //-------------------------------------------------------
360
+ // "connection clear-token-cache" Command
361
+ //-------------------------------------------------------
326
362
  connections.command('clear-token-cache')
327
363
  .description('Clear cached access tokens')
328
364
  .addHelpText('after', `
@@ -336,6 +372,10 @@ Examples:
336
372
  } catch (e) { handleError(e); }
337
373
  });
338
374
 
375
+
376
+ //-------------------------------------------------------
377
+ // "connection status-header" Command
378
+ //-------------------------------------------------------
339
379
  connections.command('status-header <state>')
340
380
  .description('Enable or disable the active connection header (on|off)')
341
381
  .addHelpText('after', `
@@ -0,0 +1,269 @@
1
+ import repl from 'repl';
2
+ import chalk from 'chalk';
3
+ import { Command } from 'commander';
4
+ import { createClient } from '../api/factory.js';
5
+ import { loadConfig, getActiveProfile } from '../config.js';
6
+ import { registerCommands } from '../command-registry.js';
7
+ import { expandCommandAbbreviations } from '../command-helper.js';
8
+
9
+ export function registerConsoleCommand(program) {
10
+ program
11
+ .command('console')
12
+ .alias('repl')
13
+ .description('Start an interactive console')
14
+ .option('-d, --debug', 'Enable debug output')
15
+ .action(async (options) => {
16
+ if (options.debug) {
17
+ process.env.DEBUG = '1';
18
+ console.log(chalk.gray('Debug mode enabled'));
19
+ }
20
+
21
+ console.log(chalk.bold.blue('Mage Remote Run Interactive Console'));
22
+ console.log(chalk.gray('Type your commands directly or write JS code.'));
23
+ console.log(chalk.gray('Global variables available: client (async factory), config, chalk'));
24
+ console.log(chalk.gray('Example JS: await (await client()).get("V1/store/websites")'));
25
+ console.log(chalk.gray('Type "list" to see available commands.'));
26
+ console.log(chalk.gray('Type .exit to quit.\n'));
27
+
28
+ // Create a fresh program instance for the REPL
29
+ const localProgram = new Command();
30
+
31
+ // Configure custom output for REPL to avoid duplicate error printing when we catch it
32
+ localProgram.configureOutput({
33
+ writeOut: (str) => process.stdout.write(str),
34
+ writeErr: (str) => process.stderr.write(str),
35
+ });
36
+
37
+ // Apply exitOverride recursively to ensure all subcommands (and sub-subcommands)
38
+ // handle help/errors without exiting the process.
39
+ const applyExitOverride = (cmd) => {
40
+ cmd.exitOverride((err) => {
41
+ throw err;
42
+ });
43
+ // Check for subcommands
44
+ if (cmd.commands) {
45
+ cmd.commands.forEach(applyExitOverride);
46
+ }
47
+ };
48
+
49
+ // Register all commands on the local instance
50
+ const profile = await getActiveProfile();
51
+ registerCommands(localProgram, profile);
52
+
53
+ // Apply overrides AFTER registration to catch all commands
54
+ applyExitOverride(localProgram);
55
+
56
+ const r = repl.start({
57
+ prompt: chalk.green('mage> '),
58
+ // We do NOT provide 'eval' here so we get the default one which supports top-level await
59
+ });
60
+
61
+ const defaultEval = r.eval;
62
+
63
+ // Capture default completer
64
+ const defaultCompleter = r.completer;
65
+
66
+ // Custom completer
67
+ const myCompleter = (line, callback) => {
68
+ const parts = line.split(/\s+/);
69
+ // Remove empty start if line starts with space (not typical for completion line but safe)
70
+ if (parts[0] === '') parts.shift();
71
+
72
+ let current = '';
73
+ let contextParts = [];
74
+
75
+ if (line.match(/\s$/)) {
76
+ current = '';
77
+ contextParts = parts.filter(p => p.length > 0);
78
+ } else {
79
+ current = parts.pop();
80
+ contextParts = parts;
81
+ }
82
+
83
+ // Helper to get candidates from a command object
84
+ const getCandidates = (cmdObj) => {
85
+ return cmdObj.commands.map(c => c.name());
86
+ };
87
+
88
+ let hits = [];
89
+
90
+ // Top-level completion (start of line)
91
+ if (contextParts.length === 0) {
92
+ const candidates = getCandidates(localProgram);
93
+ hits = candidates.filter(c => c.startsWith(current));
94
+ } else {
95
+ // Subcommand completion
96
+ let cmd = localProgram;
97
+ let validContext = true;
98
+
99
+ for (const part of contextParts) {
100
+ const found = cmd.commands.find(c => c.name() === part || (c.aliases && c.aliases().includes(part)));
101
+ if (found) {
102
+ cmd = found;
103
+ } else {
104
+ validContext = false;
105
+ break;
106
+ }
107
+ }
108
+
109
+ if (validContext) {
110
+ const candidates = getCandidates(cmd);
111
+ hits = candidates.filter(c => c.startsWith(current));
112
+ }
113
+ }
114
+
115
+ // If we have distinct command hits, return them
116
+ if (hits.length > 0) {
117
+ return callback(null, [hits, current]);
118
+ }
119
+
120
+ // Fallback to default JS completion
121
+ return defaultCompleter(line, callback);
122
+ };
123
+
124
+ // Override completer
125
+ r.completer = myCompleter;
126
+
127
+ // Custom evaluator to support both CLI commands and JS
128
+ const myEval = async (cmd, context, filename, callback) => {
129
+ cmd = cmd.trim();
130
+
131
+ if (!cmd) {
132
+ callback(null);
133
+ return;
134
+ }
135
+
136
+ if (cmd === 'list') {
137
+ console.log(chalk.bold('\nAvailable Commands:'));
138
+ // Use localProgram commands
139
+ localProgram.commands.filter(c => !c._hidden).sort((a, b) => a.name().localeCompare(b.name())).forEach(c => {
140
+ console.log(` ${chalk.cyan(c.name().padEnd(25))} ${c.description()}`);
141
+ });
142
+ console.log('');
143
+ callback(null);
144
+ return;
145
+ }
146
+
147
+ if (cmd === 'help') {
148
+ localProgram.outputHelp();
149
+ callback(null);
150
+ return;
151
+ }
152
+
153
+ try {
154
+ // Parse arguments nicely
155
+ // This regex handles quoted arguments
156
+ const args = (cmd.match(/[^\s"']+|"([^"]*)"|'([^']*)'/g) || []).map(arg => {
157
+ if (arg.startsWith('"') && arg.endsWith('"')) return arg.slice(1, -1);
158
+ if (arg.startsWith("'") && arg.endsWith("'")) return arg.slice(1, -1);
159
+ return arg;
160
+ });
161
+
162
+ if (args.length > 0) {
163
+ if (process.env.DEBUG) {
164
+ console.log(chalk.gray('DEBUG: Parsing args:'), args);
165
+ }
166
+ let expandedArgs;
167
+ try {
168
+ expandedArgs = expandCommandAbbreviations(localProgram, args);
169
+ if (process.env.DEBUG) {
170
+ console.log(chalk.gray('DEBUG: Expanded args:'), expandedArgs);
171
+ }
172
+ } catch (e) {
173
+ if (e.isAmbiguous) {
174
+ // If ambiguous, print error and return (don't execute JS, as user likelihood meant a command)
175
+ // But wait, what if "c" is a var?
176
+ // If I type "c", it is ambiguous.
177
+ // If I fallback to JS, "c" might work.
178
+ // If I print error, "c" access is blocked.
179
+
180
+ // Compromise: If it LOOKS like a command usage (e.g. multiple args), treat as command error?
181
+ // Or just always fallback to JS if ambiguous?
182
+ // If fallback to JS, user sees "c is not defined".
183
+ // User asks: "Why didn't it run command?". Answer: "Ambiguous".
184
+ // Explicit ambiguity error is arguably better than generic ReferenceError.
185
+
186
+ // However, "c = 1" or "const c = 1"
187
+ // "const" -> ambiguous? "connection", "console"... no "const" is not in list of commands.
188
+ // "const" might NOT match any command prefix if lucky.
189
+ // But if it does...
190
+
191
+ // Let's stick to safe approach: fallback to JS if ambiguous, unless we are SURE it's not JS?
192
+ // Or: Just print the ambiguous error if the first arg matched *something*.
193
+
194
+ // Let's try to assume command first. If ambiguous, show error.
195
+ console.error(chalk.red(e.message));
196
+ callback(null);
197
+ return;
198
+ }
199
+ // Other errors?
200
+ throw e;
201
+ }
202
+
203
+ const firstWord = expandedArgs[0];
204
+ const knownCommands = localProgram.commands.map(c => c.name());
205
+
206
+ if (knownCommands.includes(firstWord)) {
207
+ // Valid command found
208
+ try {
209
+ r.pause();
210
+ await localProgram.parseAsync(['node', 'mage-remote-run', ...expandedArgs]);
211
+
212
+ // Restore REPL state
213
+ if (process.stdin.isTTY) {
214
+ process.stdin.setRawMode(true);
215
+ }
216
+ process.stdin.resume();
217
+ r.resume();
218
+ r.displayPrompt();
219
+ } catch (e) {
220
+ if (process.stdin.isTTY) {
221
+ process.stdin.setRawMode(true);
222
+ }
223
+ process.stdin.resume();
224
+ r.resume();
225
+ if (e.code === 'commander.helpDisplayed') {
226
+ // Help was displayed, clean exit for us
227
+ } else if (e.code === 'commander.unknownOption' || e.code === 'commander.unknownCommand') {
228
+ console.error(chalk.red(e.message));
229
+ } else {
230
+ if (e.code) {
231
+ // Likely a commander exit error we rethrew
232
+ } else {
233
+ console.error(chalk.red('Command execution error:'), e);
234
+ }
235
+ }
236
+ }
237
+ callback(null);
238
+ return;
239
+ }
240
+ }
241
+ } catch (e) {
242
+ // unexpected error during CLI detection
243
+ }
244
+
245
+ // Fallback to default eval which supports top-level await
246
+ defaultEval.call(r, cmd, context, filename, callback);
247
+ };
248
+
249
+ // Override the eval function
250
+ r.eval = myEval;
251
+
252
+ // Initialize context
253
+ r.context.client = createClient;
254
+ r.context.config = await loadConfig();
255
+ r.context.chalk = chalk;
256
+ r.context.program = program; // Expose global program just in case? Or local?
257
+ r.context.localProgram = localProgram; // Expose local debugging
258
+
259
+ // Helper to reload config if changed
260
+ r.context.reload = async () => {
261
+ r.context.config = await loadConfig();
262
+ console.log(chalk.gray('Config reloaded.'));
263
+ };
264
+
265
+ r.on('exit', () => {
266
+ process.exit();
267
+ });
268
+ });
269
+ }
@@ -6,6 +6,10 @@ import inquirer from 'inquirer';
6
6
  export function registerCustomersCommands(program) {
7
7
  const customers = program.command('customer').description('Manage customers');
8
8
 
9
+
10
+ //-------------------------------------------------------
11
+ // "customer list" Command
12
+ //-------------------------------------------------------
9
13
  customers.command('list')
10
14
  .description('List customers')
11
15
  .option('-p, --page <number>', 'Page number', '1')
@@ -45,6 +49,10 @@ Examples:
45
49
  } catch (e) { handleError(e); }
46
50
  });
47
51
 
52
+
53
+ //-------------------------------------------------------
54
+ // "customer search" Command
55
+ //-------------------------------------------------------
48
56
  customers.command('search <query>')
49
57
  .description('Search customers by email')
50
58
  .addHelpText('after', `
@@ -65,6 +73,10 @@ Examples:
65
73
  } catch (e) { handleError(e); }
66
74
  });
67
75
 
76
+
77
+ //-------------------------------------------------------
78
+ // "customer edit" Command
79
+ //-------------------------------------------------------
68
80
  customers.command('edit <id>')
69
81
  .description('Edit a customer')
70
82
  .addHelpText('after', `
@@ -96,6 +108,10 @@ Examples:
96
108
  } catch (e) { handleError(e); }
97
109
  });
98
110
 
111
+
112
+ //-------------------------------------------------------
113
+ // "customer show" Command
114
+ //-------------------------------------------------------
99
115
  customers.command('show <customerId>')
100
116
  .description('Show detailed customer information')
101
117
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -156,6 +172,10 @@ Examples:
156
172
  } catch (e) { handleError(e); }
157
173
  });
158
174
 
175
+
176
+ //-------------------------------------------------------
177
+ // "customer delete" Command
178
+ //-------------------------------------------------------
159
179
  customers.command('delete <customerId>')
160
180
  .description('Delete a customer')
161
181
  .option('--force', 'Force delete without confirmation')
@@ -185,6 +205,10 @@ Examples:
185
205
  } catch (e) { handleError(e); }
186
206
  });
187
207
 
208
+
209
+ //-------------------------------------------------------
210
+ // "customer confirm" Command
211
+ //-------------------------------------------------------
188
212
  customers.command('confirm [customerId]')
189
213
  .description('Resend customer confirmation email')
190
214
  .option('--redirect-url <url>', 'Redirect URL after confirmation')
@@ -242,6 +266,10 @@ Examples:
242
266
  });
243
267
  const groups = customers.command('group').description('Manage customer groups');
244
268
 
269
+
270
+ //-------------------------------------------------------
271
+ // "customer group list" Command
272
+ //-------------------------------------------------------
245
273
  groups.command('list')
246
274
  .description('List customer groups')
247
275
  .option('-p, --page <number>', 'Page number', '1')
@@ -8,6 +8,10 @@ export function registerEavCommands(program) {
8
8
  // Attribute Sets
9
9
  const attributeSets = eav.command('attribute-set').description('Manage attribute sets');
10
10
 
11
+
12
+ //-------------------------------------------------------
13
+ // "eav attribute-set list" Command
14
+ //-------------------------------------------------------
11
15
  attributeSets.command('list')
12
16
  .description('List all attribute sets')
13
17
  .option('-p, --page <number>', 'Page number', '1')
@@ -51,6 +55,10 @@ Examples:
51
55
  } catch (e) { handleError(e); }
52
56
  });
53
57
 
58
+
59
+ //-------------------------------------------------------
60
+ // "eav attribute-set show" Command
61
+ //-------------------------------------------------------
54
62
  attributeSets.command('show <id>')
55
63
  .description('Show attribute set details')
56
64
  .addHelpText('after', `
@@ -8,6 +8,10 @@ export function registerInventoryCommands(program) {
8
8
 
9
9
  const stock = inventory.command('stock').description('Manage inventory stocks');
10
10
 
11
+
12
+ //-------------------------------------------------------
13
+ // "inventory stock list" Command
14
+ //-------------------------------------------------------
11
15
  stock.command('list')
12
16
  .description('List inventory stocks')
13
17
  .addHelpText('after', `
@@ -28,6 +32,10 @@ Examples:
28
32
  } catch (e) { handleError(e); }
29
33
  });
30
34
 
35
+
36
+ //-------------------------------------------------------
37
+ // "inventory stock show" Command
38
+ //-------------------------------------------------------
31
39
  stock.command('show <stockId>')
32
40
  .description('Show stock details')
33
41
  .addHelpText('after', `
@@ -52,6 +60,10 @@ Examples:
52
60
  } catch (e) { handleError(e); }
53
61
  });
54
62
 
63
+
64
+ //-------------------------------------------------------
65
+ // "inventory resolve-stock" Command
66
+ //-------------------------------------------------------
55
67
  inventory.command('resolve-stock <type> <code>')
56
68
  .description('Resolve stock for a sales channel')
57
69
  .addHelpText('after', `
@@ -68,6 +80,10 @@ Examples:
68
80
 
69
81
  const source = inventory.command('source').description('Manage inventory sources');
70
82
 
83
+
84
+ //-------------------------------------------------------
85
+ // "inventory source list" Command
86
+ //-------------------------------------------------------
71
87
  source.command('list')
72
88
  .description('List inventory sources')
73
89
  .option('-p, --page <number>', 'Page number', '1')
@@ -108,6 +124,10 @@ Examples:
108
124
 
109
125
  const ssa = source.command('selection-algorithm').description('Manage source selection algorithms');
110
126
 
127
+
128
+ //-------------------------------------------------------
129
+ // "inventory source selection-algorithm list" Command
130
+ //-------------------------------------------------------
111
131
  ssa.command('list')
112
132
  .description('List available source selection algorithms')
113
133
  .addHelpText('after', `
@@ -6,6 +6,10 @@ import inquirer from 'inquirer';
6
6
  export function registerOrdersCommands(program) {
7
7
  const orders = program.command('order').description('Manage orders');
8
8
 
9
+
10
+ //-------------------------------------------------------
11
+ // "order list" Command
12
+ //-------------------------------------------------------
9
13
  orders.command('list')
10
14
  .option('-p, --page <number>', 'Page number', '1')
11
15
  .option('-s, --size <number>', 'Page size', '20')
@@ -44,6 +48,10 @@ Examples:
44
48
  } catch (e) { handleError(e); }
45
49
  });
46
50
 
51
+
52
+ //-------------------------------------------------------
53
+ // "order search" Command
54
+ //-------------------------------------------------------
47
55
  orders.command('search <query>')
48
56
  .description('Search orders by Increment ID')
49
57
  .addHelpText('after', `
@@ -64,6 +72,10 @@ Examples:
64
72
  } catch (e) { handleError(e); }
65
73
  });
66
74
 
75
+
76
+ //-------------------------------------------------------
77
+ // "order edit" Command
78
+ //-------------------------------------------------------
67
79
  orders.command('edit <id>')
68
80
  .description('Update order status (via Comment)')
69
81
  .addHelpText('after', `
@@ -92,6 +104,10 @@ Examples:
92
104
  console.log(chalk.green(`Order ${id} updated.`));
93
105
  } catch (e) { handleError(e); }
94
106
  });
107
+
108
+ //-------------------------------------------------------
109
+ // "order show" Command
110
+ //-------------------------------------------------------
95
111
  orders.command('show <identifier>')
96
112
  .description('Show detailed order information by ID or Increment ID')
97
113
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -106,6 +122,10 @@ Examples:
106
122
  } catch (e) { handleError(e); }
107
123
  });
108
124
 
125
+
126
+ //-------------------------------------------------------
127
+ // "order latest" Command
128
+ //-------------------------------------------------------
109
129
  orders.command('latest')
110
130
  .description('List latest orders sorted by created_at DESC with selection')
111
131
  .option('-p, --page <number>', 'Page number', '1')
@@ -199,7 +219,7 @@ async function showOrder(identifier, format = 'text') {
199
219
  order = await client.get(`V1/orders/${order.entity_id}`, {}, { headers });
200
220
  } catch (subError) {
201
221
  // ignore or log? If we fail to get formatted, fallback or throw?
202
- // If we found it via search, 'order' is the object.
222
+ // If we found it via search, 'order' is the object.
203
223
  // If format is json, we are good.
204
224
  // If format is xml, we NEED to re-fetch because 'order' is currently a JS object from JSON response.
205
225
  if (format === 'xml') throw subError;
@@ -267,8 +287,8 @@ function statusColor(status) {
267
287
  // Basic color coding
268
288
  if (['pending'].includes(status)) return status;
269
289
  if (['processing'].includes(status)) return status;
270
- if (['complete'].includes(status)) return status; // green?
271
- // Since we don't have direct chalk access in this helper easily without passing it,
290
+ if (['complete'].includes(status)) return status; // green?
291
+ // Since we don't have direct chalk access in this helper easily without passing it,
272
292
  // and I don't want to import it again if I can avoid it or I can just return string.
273
293
  // Actually, I can import properly in module scope if I change top imports but I am overwriting the file so I can add imports.
274
294
  return status;
@@ -5,6 +5,10 @@ import chalk from 'chalk';
5
5
  export function registerProductsCommands(program) {
6
6
  const products = program.command('product').description('Manage products');
7
7
 
8
+
9
+ //-------------------------------------------------------
10
+ // "product list" Command
11
+ //-------------------------------------------------------
8
12
  products.command('list')
9
13
  .description('List products')
10
14
  .option('-p, --page <number>', 'Page number', '1')
@@ -48,6 +52,10 @@ Examples:
48
52
  } catch (e) { handleError(e); }
49
53
  });
50
54
 
55
+
56
+ //-------------------------------------------------------
57
+ // "product show" Command
58
+ //-------------------------------------------------------
51
59
  products.command('show <sku>')
52
60
  .description('Show product details')
53
61
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -165,6 +173,10 @@ Examples:
165
173
 
166
174
  const types = products.command('type').description('Manage product types');
167
175
 
176
+
177
+ //-------------------------------------------------------
178
+ // "product type list" Command
179
+ //-------------------------------------------------------
168
180
  types.command('list')
169
181
  .description('List available product types')
170
182
  .addHelpText('after', `
@@ -182,6 +194,10 @@ Examples:
182
194
 
183
195
  const attributes = products.command('attribute').description('Manage product attributes');
184
196
 
197
+
198
+ //-------------------------------------------------------
199
+ // "product attribute list" Command
200
+ //-------------------------------------------------------
185
201
  attributes.command('list')
186
202
  .description('List product attributes')
187
203
  .option('-p, --page <number>', 'Page number', '1')
@@ -213,6 +229,10 @@ Examples:
213
229
  } catch (e) { handleError(e); }
214
230
  });
215
231
 
232
+
233
+ //-------------------------------------------------------
234
+ // "product attribute show" Command
235
+ //-------------------------------------------------------
216
236
  attributes.command('show <attributeCode>')
217
237
  .description('Show product attribute details')
218
238
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -293,6 +313,10 @@ Examples:
293
313
  });
294
314
 
295
315
  const attributeTypes = attributes.command('type').description('Manage attribute types');
316
+
317
+ //-------------------------------------------------------
318
+ // "product attribute type list" Command
319
+ //-------------------------------------------------------
296
320
  attributeTypes.command('list')
297
321
  .description('List product attribute types')
298
322
  .addHelpText('after', `
@@ -9,6 +9,10 @@ export function registerStoresCommands(program) {
9
9
  // Store Groups
10
10
  const groups = stores.command('group').description('Manage store groups');
11
11
 
12
+
13
+ //-------------------------------------------------------
14
+ // "store group list" Command
15
+ //-------------------------------------------------------
12
16
  groups.command('list')
13
17
  .description('List store groups')
14
18
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -40,6 +44,10 @@ Examples:
40
44
  } catch (e) { handleError(e); }
41
45
  });
42
46
 
47
+
48
+ //-------------------------------------------------------
49
+ // "store group search" Command
50
+ //-------------------------------------------------------
43
51
  groups.command('search <query>')
44
52
  .description('Search store groups')
45
53
  .addHelpText('after', `
@@ -56,6 +64,10 @@ Examples:
56
64
  } catch (e) { handleError(e); }
57
65
  });
58
66
 
67
+
68
+ //-------------------------------------------------------
69
+ // "store group delete" Command
70
+ //-------------------------------------------------------
59
71
  groups.command('delete <id>')
60
72
  .description('Delete store group')
61
73
  .addHelpText('after', `
@@ -72,6 +84,10 @@ Examples:
72
84
  } catch (e) { handleError(e); }
73
85
  });
74
86
 
87
+
88
+ //-------------------------------------------------------
89
+ // "store group edit" Command
90
+ //-------------------------------------------------------
75
91
  groups.command('edit <id>')
76
92
  .description('Edit store group')
77
93
  .addHelpText('after', `
@@ -99,6 +115,10 @@ Examples:
99
115
  // Store Views
100
116
  const views = stores.command('view').description('Manage store views');
101
117
 
118
+
119
+ //-------------------------------------------------------
120
+ // "store view list" Command
121
+ //-------------------------------------------------------
102
122
  views.command('list')
103
123
  .description('List store views')
104
124
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -130,6 +150,10 @@ Examples:
130
150
  } catch (e) { handleError(e); }
131
151
  });
132
152
 
153
+
154
+ //-------------------------------------------------------
155
+ // "store view search" Command
156
+ //-------------------------------------------------------
133
157
  views.command('search <query>')
134
158
  .description('Search store views')
135
159
  .addHelpText('after', `
@@ -146,6 +170,10 @@ Examples:
146
170
  } catch (e) { handleError(e); }
147
171
  });
148
172
 
173
+
174
+ //-------------------------------------------------------
175
+ // "store view delete" Command
176
+ //-------------------------------------------------------
149
177
  views.command('delete <id>')
150
178
  .description('Delete store view')
151
179
  .addHelpText('after', `
@@ -162,6 +190,10 @@ Examples:
162
190
  } catch (e) { handleError(e); }
163
191
  });
164
192
 
193
+
194
+ //-------------------------------------------------------
195
+ // "store view edit" Command
196
+ //-------------------------------------------------------
165
197
  views.command('edit <id>')
166
198
  .description('Edit store view')
167
199
  .addHelpText('after', `
@@ -189,6 +221,10 @@ Examples:
189
221
  // Store Configs
190
222
  const configs = stores.command('config').description('Manage store configurations');
191
223
 
224
+
225
+ //-------------------------------------------------------
226
+ // "store config list" Command
227
+ //-------------------------------------------------------
192
228
  configs.command('list')
193
229
  .description('List store configurations')
194
230
  .addHelpText('after', `
@@ -7,6 +7,10 @@ export function registerTaxCommands(program) {
7
7
 
8
8
  const taxClass = tax.command('class').description('Manage tax classes');
9
9
 
10
+
11
+ //-------------------------------------------------------
12
+ // "tax class list" Command
13
+ //-------------------------------------------------------
10
14
  taxClass.command('list')
11
15
  .description('List tax classes')
12
16
  .option('-p, --page <number>', 'Page number', '1')
@@ -49,6 +53,10 @@ Examples:
49
53
  } catch (e) { handleError(e); }
50
54
  });
51
55
 
56
+
57
+ //-------------------------------------------------------
58
+ // "tax class show" Command
59
+ //-------------------------------------------------------
52
60
  taxClass.command('show <id>')
53
61
  .description('Show tax class details')
54
62
  .addHelpText('after', `
@@ -5,6 +5,10 @@ import chalk from 'chalk';
5
5
  export function registerWebhooksCommands(program) {
6
6
  const webhooks = program.command('webhook').description('Manage webhooks');
7
7
 
8
+
9
+ //-------------------------------------------------------
10
+ // "webhook list" Command
11
+ //-------------------------------------------------------
8
12
  webhooks.command('list')
9
13
  .description('List available webhooks')
10
14
  .option('-p, --page <number>', 'Page number', '1')
@@ -6,6 +6,10 @@ import inquirer from 'inquirer';
6
6
  export function registerWebsitesCommands(program) {
7
7
  const websites = program.command('website').description('Manage websites');
8
8
 
9
+
10
+ //-------------------------------------------------------
11
+ // "website list" Command
12
+ //-------------------------------------------------------
9
13
  websites.command('list')
10
14
  .description('List all websites')
11
15
  .option('-f, --format <type>', 'Output format (text, json, xml)', 'text')
@@ -37,6 +41,10 @@ Examples:
37
41
  } catch (e) { handleError(e); }
38
42
  });
39
43
 
44
+
45
+ //-------------------------------------------------------
46
+ // "website search" Command
47
+ //-------------------------------------------------------
40
48
  websites.command('search <query>')
41
49
  .description('Search websites by code or name (local filter)')
42
50
  .addHelpText('after', `
@@ -55,6 +63,10 @@ Examples:
55
63
  } catch (e) { handleError(e); }
56
64
  });
57
65
 
66
+
67
+ //-------------------------------------------------------
68
+ // "website delete" Command
69
+ //-------------------------------------------------------
58
70
  websites.command('delete <id>')
59
71
  .description('Delete a website by ID')
60
72
  .addHelpText('after', `
@@ -77,6 +89,10 @@ Examples:
77
89
  } catch (e) { handleError(e); }
78
90
  });
79
91
 
92
+
93
+ //-------------------------------------------------------
94
+ // "website edit" Command
95
+ //-------------------------------------------------------
80
96
  websites.command('edit <id>')
81
97
  .description('Edit a website')
82
98
  .addHelpText('after', `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mage-remote-run",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "The remote swiss army knife for Magento Open Source, Mage-OS, Adobe Commerce",
5
5
  "main": "index.js",
6
6
  "scripts": {