mage-remote-run 1.2.0 → 1.3.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.
@@ -215,6 +215,7 @@ export async function confirmCustomerAction(customerId, options) {
215
215
  export async function listCustomerGroupsAction(options) {
216
216
  try {
217
217
  const client = await createClient();
218
+ const headers = getFormatHeaders(options);
218
219
 
219
220
  const { params: filterParams } = buildSearchCriteria(options);
220
221
  const { params: sortParams } = buildSortCriteria(options);
@@ -224,7 +225,12 @@ export async function listCustomerGroupsAction(options) {
224
225
  ...filterParams,
225
226
  ...sortParams
226
227
  };
227
- const data = await client.get('V1/customerGroups/search', params);
228
+ const data = await client.get('V1/customerGroups/search', params, { headers });
229
+
230
+ if (formatOutput(options, data)) {
231
+ return;
232
+ }
233
+
228
234
  const rows = (data.items || []).map(g => [g.id, g.code, g.tax_class_id]);
229
235
  console.log(chalk.bold(`Total: ${data.total_count}, Page: ${options.page}, Size: ${options.size}`));
230
236
  printTable(['ID', 'Code', 'Tax Class ID'], rows);
@@ -87,12 +87,13 @@ Examples:
87
87
 
88
88
  const groups = customers.command('group').description('Manage customer groups');
89
89
 
90
- addSortOption(addFilterOption(addPaginationOptions(groups.command('list')
91
- .description('List customer groups'))))
90
+ addFormatOption(addSortOption(addFilterOption(addPaginationOptions(groups.command('list')
91
+ .description('List customer groups')))))
92
92
  .addHelpText('after', `
93
93
  Examples:
94
94
  $ mage-remote-run customer group list
95
95
  $ mage-remote-run customer group list --page 1 --size 50
96
+ $ mage-remote-run customer group list --format json
96
97
  $ mage-remote-run customer group list --filter "code=%VIP%"
97
98
  $ mage-remote-run customer group list --sort "code:ASC"
98
99
  `)
@@ -1,5 +1,5 @@
1
1
  import { createClient } from '../api/factory.js';
2
- import { printTable, handleError, getFormatHeaders, formatOutput } from '../utils.js';
2
+ import { printTable, handleError, getFormatHeaders, formatOutput, applyLocalSearchCriteria } from '../utils.js';
3
3
  import chalk from 'chalk';
4
4
  import inquirer from 'inquirer';
5
5
 
@@ -10,11 +10,13 @@ export async function listStoreGroupsAction(options) {
10
10
 
11
11
  const data = await client.get('V1/store/storeGroups', {}, { headers });
12
12
 
13
- if (formatOutput(options, data)) {
13
+ let result = applyLocalSearchCriteria(data, options);
14
+
15
+ if (formatOutput(options, result)) {
14
16
  return;
15
17
  }
16
18
 
17
- const rows = data.map(s => [s.id, s.code, s.name, s.website_id, s.root_category_id]);
19
+ const rows = result.map(s => [s.id, s.code, s.name, s.website_id, s.root_category_id]);
18
20
  printTable(['ID', 'Code', 'Name', 'Web ID', 'Root Cat'], rows);
19
21
  } catch (e) {
20
22
  handleError(e);
@@ -72,11 +74,13 @@ export async function listStoreViewsAction(options) {
72
74
 
73
75
  const data = await client.get('V1/store/storeViews', {}, { headers });
74
76
 
75
- if (formatOutput(options, data)) {
77
+ let result = applyLocalSearchCriteria(data, options);
78
+
79
+ if (formatOutput(options, result)) {
76
80
  return;
77
81
  }
78
82
 
79
- const rows = data.map(v => [v.id, v.code, v.name, v.store_group_id, v.is_active]);
83
+ const rows = result.map(v => [v.id, v.code, v.name, v.store_group_id, v.is_active]);
80
84
  printTable(['ID', 'Code', 'Name', 'Group ID', 'Active'], rows);
81
85
  } catch (e) {
82
86
  handleError(e);
@@ -9,19 +9,20 @@ import {
9
9
  searchStoreGroupsAction,
10
10
  searchStoreViewsAction
11
11
  } from './stores-actions.js';
12
- import { addFormatOption } from '../utils.js';
12
+ import { addFormatOption, addFilterOption, addSortOption, addPaginationOptions } from '../utils.js';
13
13
 
14
14
  export function registerStoresCommands(program) {
15
15
  const stores = program.command('store').description('Manage stores');
16
16
 
17
17
  const groups = stores.command('group').description('Manage store groups');
18
18
 
19
- addFormatOption(groups.command('list')
20
- .description('List store groups'))
19
+ addFormatOption(addSortOption(addFilterOption(addPaginationOptions(groups.command('list')
20
+ .description('List store groups')))))
21
21
  .addHelpText('after', `
22
22
  Examples:
23
23
  $ mage-remote-run store group list
24
24
  $ mage-remote-run store group list --format json
25
+ $ mage-remote-run store group list --filter "code=%main%"
25
26
  `)
26
27
  .action(listStoreGroupsAction);
27
28
 
@@ -51,12 +52,13 @@ Examples:
51
52
 
52
53
  const views = stores.command('view').description('Manage store views');
53
54
 
54
- addFormatOption(views.command('list')
55
- .description('List store views'))
55
+ addFormatOption(addSortOption(addFilterOption(addPaginationOptions(views.command('list')
56
+ .description('List store views')))))
56
57
  .addHelpText('after', `
57
58
  Examples:
58
59
  $ mage-remote-run store view list
59
60
  $ mage-remote-run store view list --format json
61
+ $ mage-remote-run store view list --filter "code=%en%"
60
62
  `)
61
63
  .action(listStoreViewsAction);
62
64
 
@@ -1,4 +1,4 @@
1
- import { printTable, handleError, getFormatHeaders, formatOutput } from '../utils.js';
1
+ import { printTable, handleError, getFormatHeaders, formatOutput, applyLocalSearchCriteria } from '../utils.js';
2
2
  import { createClient } from '../api/factory.js';
3
3
  import chalk from 'chalk';
4
4
  import inquirer from 'inquirer';
@@ -10,11 +10,13 @@ export async function listWebsitesAction(options) {
10
10
 
11
11
  const data = await client.get('V1/store/websites', {}, { headers });
12
12
 
13
- if (formatOutput(options, data)) {
13
+ let result = applyLocalSearchCriteria(data, options);
14
+
15
+ if (formatOutput(options, result)) {
14
16
  return;
15
17
  }
16
18
 
17
- const rows = data.map(w => [w.id, w.code, w.name, w.default_group_id]);
19
+ const rows = result.map(w => [w.id, w.code, w.name, w.default_group_id]);
18
20
  printTable(['ID', 'Code', 'Name', 'Def Group ID'], rows);
19
21
  } catch (e) {
20
22
  handleError(e);
@@ -4,13 +4,13 @@ import {
4
4
  listWebsitesAction,
5
5
  searchWebsitesAction
6
6
  } from './websites-actions.js';
7
- import { addFormatOption } from '../utils.js';
7
+ import { addFormatOption, addFilterOption, addSortOption, addPaginationOptions } from '../utils.js';
8
8
 
9
9
  export function registerWebsitesCommands(program) {
10
10
  const websites = program.command('website').description('Manage websites');
11
11
 
12
- addFormatOption(websites.command('list')
13
- .description('List all websites'))
12
+ addFormatOption(addSortOption(addFilterOption(addPaginationOptions(websites.command('list')
13
+ .description('List all websites')))))
14
14
  .addHelpText('after', `
15
15
  Examples:
16
16
  $ mage-remote-run website list
package/lib/utils.js CHANGED
@@ -238,3 +238,112 @@ export function formatOutput(options, data) {
238
238
  return false;
239
239
  }
240
240
 
241
+ export function applyLocalSearchCriteria(data, options) {
242
+ let result = [...data];
243
+
244
+ if (options.filter && options.filter.length > 0) {
245
+ options.filter.forEach(group => {
246
+ const orFilters = group.split(/\s*\|\|\s*/);
247
+ result = result.filter(item => {
248
+ return orFilters.some(f => {
249
+ const match = f.match(/^([\w\.]+)(?::([a-z!]+))?(?:(<=|>=|<|>|=|!=|!~|~|\?|!|@@)(.*))?$/);
250
+ if (!match) return false;
251
+
252
+ const field = match[1];
253
+ const opString = match[2];
254
+ const shorthand = match[3];
255
+ let value = match[4] || '';
256
+
257
+ let condition = 'eq';
258
+ if (opString) {
259
+ condition = opString === '!in' ? 'nin' : opString;
260
+ } else if (shorthand) {
261
+ switch (shorthand) {
262
+ case '>': condition = 'gt'; break;
263
+ case '<': condition = 'lt'; break;
264
+ case '>=': condition = 'gteq'; break;
265
+ case '<=': condition = 'lteq'; break;
266
+ case '!=': condition = 'neq'; break;
267
+ case '~': condition = 'like'; break;
268
+ case '!~': condition = 'nlike'; break;
269
+ case '@@': condition = 'finset'; break;
270
+ case '?': condition = 'null'; value = '1'; break;
271
+ case '!': condition = 'notnull'; value = '1'; break;
272
+ default: condition = 'eq';
273
+ }
274
+ }
275
+
276
+ if ((condition === 'like' || condition === 'nlike') && value.includes('*')) {
277
+ value = value.replaceAll('*', '%');
278
+ }
279
+
280
+ const itemValue = item[field];
281
+ const strItemVal = String(itemValue || '').toLowerCase();
282
+ const strVal = String(value).toLowerCase();
283
+ const numItemVal = Number(itemValue);
284
+ const numVal = Number(value);
285
+
286
+ switch (condition) {
287
+ case 'eq': return String(itemValue) === String(value);
288
+ case 'neq': return String(itemValue) !== String(value);
289
+ case 'gt': return numItemVal > numVal;
290
+ case 'gteq': return numItemVal >= numVal;
291
+ case 'lt': return numItemVal < numVal;
292
+ case 'lteq': return numItemVal <= numVal;
293
+ case 'like':
294
+ const regexFromLike = new RegExp('^' + strVal.replace(/%/g, '.*') + '$', 'i');
295
+ return regexFromLike.test(strItemVal);
296
+ case 'nlike':
297
+ const nregexFromLike = new RegExp('^' + strVal.replace(/%/g, '.*') + '$', 'i');
298
+ return !nregexFromLike.test(strItemVal);
299
+ case 'in':
300
+ return String(value).split(',').map(s => s.trim()).includes(String(itemValue));
301
+ case 'nin':
302
+ return !String(value).split(',').map(s => s.trim()).includes(String(itemValue));
303
+ case 'null': return itemValue === null || itemValue === undefined;
304
+ case 'notnull': return itemValue !== null && itemValue !== undefined;
305
+ case 'finset':
306
+ return String(itemValue).split(',').map(s => s.trim()).includes(String(value));
307
+ default: return false;
308
+ }
309
+ });
310
+ });
311
+ });
312
+ }
313
+
314
+ if (options.sort && options.sort.length > 0) {
315
+ options.sort.forEach(s => {
316
+ const parts = s.split(':');
317
+ const field = parts[0];
318
+ const direction = parts.length > 1 ? parts[1].toUpperCase() : 'ASC';
319
+ result.sort((a, b) => {
320
+ if (a[field] < b[field]) return direction === 'ASC' ? -1 : 1;
321
+ if (a[field] > b[field]) return direction === 'ASC' ? 1 : -1;
322
+ return 0;
323
+ });
324
+ });
325
+ } else if (options.sortBy) {
326
+ const field = options.sortBy;
327
+ const direction = (options.sortOrder || 'ASC').toUpperCase();
328
+ result.sort((a, b) => {
329
+ if (a[field] < b[field]) return direction === 'ASC' ? -1 : 1;
330
+ if (a[field] > b[field]) return direction === 'ASC' ? 1 : -1;
331
+ return 0;
332
+ });
333
+ }
334
+
335
+ if (options.page && options.size) {
336
+ // Technically addPaginationOptions sets defaults
337
+ const page = parseInt(options.page || 1, 10);
338
+ const size = parseInt(options.size || 20, 10);
339
+ const start = (page - 1) * size;
340
+ result = result.slice(start, start + size);
341
+ } else if (options.page || options.size) {
342
+ const page = parseInt(options.page || 1, 10);
343
+ const size = parseInt(options.size || 20, 10);
344
+ const start = (page - 1) * size;
345
+ result = result.slice(start, start + size);
346
+ }
347
+
348
+ return result;
349
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mage-remote-run",
3
- "version": "1.2.0",
3
+ "version": "1.3.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": {