@jacebenson/jsn 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jacebenson/jsn",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "A command-line interface for ServiceNow that follows the Unix philosophy: simple, composable, and scriptable.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  // Generic command builder for CRUD operations on a ServiceNow table
2
2
  // Used by incidents, changes, requests, tasks, and most dev subcommands
3
3
 
4
- import { getStringField, formatRecordForDisplay, buildQuerySuffix } from '../helpers.js';
4
+ import { getStringField, formatRecordForDisplay, buildQuerySuffix, resolveFieldsParam } from '../helpers.js';
5
5
  import search from '@inquirer/search';
6
6
  import { isTTY, FormatAuto } from '../output.js';
7
7
 
@@ -114,13 +114,13 @@ export function buildTicketCommands(table, displayName, alias, defaultColumns, s
114
114
  params.set('sysparm_limit', String(limit));
115
115
  params.set('sysparm_offset', String(offset));
116
116
  params.set('sysparm_display_value', 'all');
117
- const fetchColumns = ['sys_id', ...columns];
118
- params.set('sysparm_fields', fetchColumns.join(','));
117
+ const fields = resolveFieldsParam(columns);
118
+ if (fields) params.set('sysparm_fields', fields);
119
119
  const q = query ? query + '^ORDERBYDESCsys_updated_on' : 'ORDERBYDESCsys_updated_on';
120
120
  params.set('sysparm_query', q);
121
121
 
122
122
  const records = await app.sdk.list(table, params);
123
- const displayRecords = records.map(r => formatRecordForDisplay(r, columns));
123
+ const displayRecords = fields ? records.map(r => formatRecordForDisplay(r, columns)) : records;
124
124
 
125
125
  const breadcrumbs = [
126
126
  { action: 'create', cmd: `jsn ${alias} create --description "..."`, description: `Create a new ${displayName}` },
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, getStringField } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  export function groupMembersCmd(wrap) {
4
4
  return {
@@ -20,14 +20,15 @@ export function groupMembersCmd(wrap) {
20
20
  const params = new URLSearchParams();
21
21
  params.set('sysparm_limit', String(argv.limit));
22
22
  params.set('sysparm_display_value', 'all');
23
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
23
+ const fields = resolveFieldsParam(columns);
24
+ if (fields) params.set('sysparm_fields', fields);
24
25
  if (argv.query) params.set('sysparm_query', argv.query);
25
26
  const records = await app.sdk.list('sys_user_grmember', params);
26
27
  app.ok({
27
28
  table: 'sys_user_grmember',
28
29
  count: records.length,
29
30
  columns,
30
- records: records.map(r => formatRecordForDisplay(r, columns)),
31
+ records: fields ? records.map(r => formatRecordForDisplay(r, columns)) : records,
31
32
  context: { instance_url: app.getEffectiveInstance() },
32
33
  }, { summary: `${records.length} group member(s)` });
33
34
  }),
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, getStringField } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  export function groupRolesCmd(wrap) {
4
4
  return {
@@ -20,14 +20,15 @@ export function groupRolesCmd(wrap) {
20
20
  const params = new URLSearchParams();
21
21
  params.set('sysparm_limit', String(argv.limit));
22
22
  params.set('sysparm_display_value', 'all');
23
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
23
+ const fields = resolveFieldsParam(columns);
24
+ if (fields) params.set('sysparm_fields', fields);
24
25
  if (argv.query) params.set('sysparm_query', argv.query);
25
26
  const records = await app.sdk.list('sys_group_has_role', params);
26
27
  app.ok({
27
28
  table: 'sys_group_has_role',
28
29
  count: records.length,
29
30
  columns,
30
- records: records.map(r => formatRecordForDisplay(r, columns)),
31
+ records: fields ? records.map(r => formatRecordForDisplay(r, columns)) : records,
31
32
  context: { instance_url: app.getEffectiveInstance() },
32
33
  }, { summary: `${records.length} group role(s)` });
33
34
  }),
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, getStringField, interactiveList } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, interactiveList, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  export function groupsCmd(wrap) {
4
4
  return {
@@ -31,14 +31,15 @@ export function groupsCmd(wrap) {
31
31
  const params = new URLSearchParams();
32
32
  params.set('sysparm_limit', String(argv.limit));
33
33
  params.set('sysparm_display_value', 'all');
34
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
34
+ const fields = resolveFieldsParam(columns);
35
+ if (fields) params.set('sysparm_fields', fields);
35
36
  if (argv.query) params.set('sysparm_query', argv.query);
36
37
  const records = await app.sdk.list('sys_user_group', params);
37
38
  app.ok({
38
39
  table: 'sys_user_group',
39
40
  count: records.length,
40
41
  columns,
41
- records: records.map(r => formatRecordForDisplay(r, columns)),
42
+ records: fields ? records.map(r => formatRecordForDisplay(r, columns)) : records,
42
43
  context: { instance_url: app.getEffectiveInstance() },
43
44
  }, { summary: `${records.length} group(s)` });
44
45
  }),
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, buildQuerySuffix, parseDataArg, getStringField, interactiveList } from '../helpers.js';
1
+ import { formatRecordForDisplay, buildQuerySuffix, parseDataArg, getStringField, interactiveList, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  const tableDefaultColumns = {
4
4
  incident: ['number', 'short_description', 'priority', 'state', 'assigned_to'],
@@ -66,10 +66,11 @@ export function recordsCmd(wrap) {
66
66
  params.set('sysparm_limit', argv['sys-id'] ? '1' : String(argv.limit));
67
67
  params.set('sysparm_offset', String(argv.offset));
68
68
  params.set('sysparm_display_value', 'all');
69
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
69
+ const fields = resolveFieldsParam(columns);
70
+ if (fields) params.set('sysparm_fields', fields);
70
71
  if (query) params.set('sysparm_query', query);
71
72
  const records = await app.sdk.list(table, params);
72
- const displayRecords = records.map(r => formatRecordForDisplay(r, columns));
73
+ const displayRecords = fields ? records.map(r => formatRecordForDisplay(r, columns)) : records;
73
74
  const breadcrumbs = [
74
75
  { action: 'create', cmd: `jsn records create --table ${table} --data '{...}'`, description: 'Create a new record' },
75
76
  { action: 'filter', cmd: `jsn records list --table ${table} --query "priority=1"`, description: 'Filter: priority 1 only' },
@@ -118,7 +119,7 @@ export function recordsCmd(wrap) {
118
119
  params.set('sysparm_query', `sys_id=${argv['sys-id']}`);
119
120
  params.set('sysparm_limit', '1');
120
121
  params.set('sysparm_display_value', 'true');
121
- if (argv.columns) params.set('sysparm_fields', argv.columns);
122
+ if (argv.columns && argv.columns !== '*') params.set('sysparm_fields', argv.columns);
122
123
  const records = await app.sdk.list(argv.table, params);
123
124
  if (records.length === 0) {
124
125
  throw new Error(`Record not found: ${argv['sys-id']}`);
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, getStringField, buildQuerySuffix } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, buildQuerySuffix, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  export function ticketsCmd(wrap) {
4
4
  return {
@@ -22,11 +22,12 @@ export function ticketsCmd(wrap) {
22
22
  params.set('sysparm_limit', String(argv.limit));
23
23
  params.set('sysparm_offset', String(argv.offset));
24
24
  params.set('sysparm_display_value', 'all');
25
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
25
+ const fields = resolveFieldsParam(columns);
26
+ if (fields) params.set('sysparm_fields', fields);
26
27
  const q = argv.query ? argv.query + '^ORDERBYDESCsys_updated_on' : 'ORDERBYDESCsys_updated_on';
27
28
  params.set('sysparm_query', q);
28
29
  const records = await app.sdk.list('ticket', params);
29
- const displayRecords = records.map(r => formatRecordForDisplay(r, columns));
30
+ const displayRecords = fields ? records.map(r => formatRecordForDisplay(r, columns)) : records;
30
31
  const breadcrumbs = [
31
32
  { action: 'create', cmd: 'jsn tickets create --data \'{...}\'', description: 'Create a new ticket' },
32
33
  ];
@@ -1,4 +1,4 @@
1
- import { formatRecordForDisplay, getStringField, interactiveList } from '../helpers.js';
1
+ import { formatRecordForDisplay, getStringField, interactiveList, resolveFieldsParam } from '../helpers.js';
2
2
 
3
3
  export function usersCmd(wrap) {
4
4
  return {
@@ -31,14 +31,15 @@ export function usersCmd(wrap) {
31
31
  const params = new URLSearchParams();
32
32
  params.set('sysparm_limit', String(argv.limit));
33
33
  params.set('sysparm_display_value', 'all');
34
- params.set('sysparm_fields', ['sys_id', ...columns].join(','));
34
+ const fields = resolveFieldsParam(columns);
35
+ if (fields) params.set('sysparm_fields', fields);
35
36
  if (argv.query) params.set('sysparm_query', argv.query);
36
37
  const records = await app.sdk.list('sys_user', params);
37
38
  app.ok({
38
39
  table: 'sys_user',
39
40
  count: records.length,
40
41
  columns,
41
- records: records.map(r => formatRecordForDisplay(r, columns)),
42
+ records: fields ? records.map(r => formatRecordForDisplay(r, columns)) : records,
42
43
  context: { instance_url: app.getEffectiveInstance() },
43
44
  }, { summary: `${records.length} user(s)` });
44
45
  }),
package/src/helpers.js CHANGED
@@ -63,6 +63,17 @@ export function buildQuerySuffix(query) {
63
63
  return query ? ` --query "${query}"` : '';
64
64
  }
65
65
 
66
+ /**
67
+ * Resolve sysparm_fields value from user-supplied columns.
68
+ * Returns null when columns includes '*' (signals "fetch all fields"),
69
+ * so callers should omit sysparm_fields and skip formatRecordForDisplay.
70
+ * Otherwise returns the fields string with sys_id prepended.
71
+ */
72
+ export function resolveFieldsParam(columns) {
73
+ if (columns.includes('*')) return null;
74
+ return ['sys_id', ...columns].join(',');
75
+ }
76
+
66
77
  /**
67
78
  * Shared interactive list helper with search-as-you-type.
68
79
  * All list commands that want an interactive TTY picker should use this.
@@ -84,11 +95,12 @@ export async function interactiveList({ app, table, singular, columns, limit = 2
84
95
  return null; // not interactive — caller should fall back to text/table
85
96
  }
86
97
 
87
- const pickerColumns = ['sys_id', labelField, ...columns.filter(c => c !== labelField && c !== 'sys_id')];
98
+ const pickerColumns = ['sys_id', labelField, ...columns.filter(c => c !== labelField && c !== 'sys_id' && c !== '*')];
88
99
  const params = new URLSearchParams();
89
100
  params.set('sysparm_limit', String(limit));
90
101
  params.set('sysparm_display_value', 'all');
91
- params.set('sysparm_fields', pickerColumns.join(','));
102
+ const pickerFields = pickerColumns.join(',');
103
+ if (pickerFields) params.set('sysparm_fields', pickerFields);
92
104
  params.set('sysparm_query', 'ORDERBYDESCsys_updated_on');
93
105
 
94
106
  const records = await app.sdk.list(table, params);