@jacebenson/jsn 4.3.7-dev.32 → 4.3.7-dev.33
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 +1 -1
- package/src/commands/midservers.js +84 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { input, password as passwordPrompt, select } from '@inquirer/prompts';
|
|
4
|
-
import { confirmDelete, formatRecordForDisplay, getStringField, interactiveList, canPrompt } from '../helpers.js';
|
|
4
|
+
import { confirmDelete, formatRecordForDisplay, getStringField, interactiveList, canPrompt, assertSafeExactMatch } from '../helpers.js';
|
|
5
5
|
import { FormatAuto } from '../output.js';
|
|
6
6
|
import { declareCapabilities } from '../capabilities.js';
|
|
7
7
|
import { resolveRecord, unwrapSysId } from '../resolve-record.js';
|
|
@@ -91,6 +91,85 @@ async function resolveMidServer(sdk, identifier) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
async function showMidDiagnostics(app, argv, kind) {
|
|
95
|
+
app.requireInstance();
|
|
96
|
+
let mid;
|
|
97
|
+
if (argv.identifier) {
|
|
98
|
+
mid = await resolveMidServer(app.sdk, argv.identifier);
|
|
99
|
+
} else {
|
|
100
|
+
if (!canPrompt() || app.output.getFormat() !== FormatAuto) {
|
|
101
|
+
throw new Error('An identifier is required outside an interactive terminal');
|
|
102
|
+
}
|
|
103
|
+
mid = await interactiveList({
|
|
104
|
+
app, table: AGENT_TABLE, singular: 'MID Server', columns: LIST_FIELDS,
|
|
105
|
+
limit: 50, labelField: 'name', message: `Select a MID Server for ${kind}`,
|
|
106
|
+
formatLabel: record => `${getStringField(record, 'name')} [${getStringField(record, 'status')}]`,
|
|
107
|
+
});
|
|
108
|
+
if (!mid) return;
|
|
109
|
+
}
|
|
110
|
+
const name = getStringField(mid, 'name');
|
|
111
|
+
const sysId = unwrapSysId(mid);
|
|
112
|
+
assertSafeExactMatch(name);
|
|
113
|
+
assertSafeExactMatch(sysId);
|
|
114
|
+
const issues = kind === 'issues';
|
|
115
|
+
const table = issues ? 'ecc_agent_issue' : 'mid_server_event';
|
|
116
|
+
const columns = issues
|
|
117
|
+
? ['sys_id', 'state', 'source', 'message', 'last_detected']
|
|
118
|
+
: ['sys_id', 'event', 'source', 'message', 'sys_created_on'];
|
|
119
|
+
const query = issues
|
|
120
|
+
? `mid_server=${sysId}${argv.all ? '' : '^state!=resolved'}^ORDERBYDESClast_detected`
|
|
121
|
+
: `agent=${name}^ORDERBYDESCsys_created_on`;
|
|
122
|
+
const limit = argv.limit ?? 50;
|
|
123
|
+
const offset = argv.offset ?? 0;
|
|
124
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 1000 || !Number.isInteger(offset) || offset < 0) {
|
|
125
|
+
throw new Error('Use --limit between 1 and 1000 and a nonnegative --offset');
|
|
126
|
+
}
|
|
127
|
+
const records = await app.sdk.list(table, new URLSearchParams({
|
|
128
|
+
sysparm_query: query, sysparm_fields: columns.join(','), sysparm_display_value: 'all',
|
|
129
|
+
sysparm_limit: String(limit), sysparm_offset: String(offset),
|
|
130
|
+
}));
|
|
131
|
+
const instanceURL = app.getEffectiveInstance();
|
|
132
|
+
const url = new URL(`/${table}_list.do`, instanceURL);
|
|
133
|
+
url.searchParams.set('sysparm_query', query);
|
|
134
|
+
const rows = records.map(record => ({
|
|
135
|
+
...record,
|
|
136
|
+
url: new URL(`/${table}.do?sys_id=${encodeURIComponent(unwrapSysId(record))}`, instanceURL).href,
|
|
137
|
+
}));
|
|
138
|
+
const label = issues ? (argv.all ? 'issues' : 'unresolved issues') : 'lifecycle events';
|
|
139
|
+
const summary = rows.length
|
|
140
|
+
? `Showing ${rows.length} ${label} for MID Server '${name}' (offset ${offset})`
|
|
141
|
+
: `No ${label} returned for MID Server '${name}' (offset ${offset})`;
|
|
142
|
+
const lines = [summary, ''];
|
|
143
|
+
for (const record of rows) {
|
|
144
|
+
lines.push(`${getStringField(record, issues ? 'last_detected' : 'sys_created_on')} ${getStringField(record, issues ? 'state' : 'event')}`);
|
|
145
|
+
const source = getStringField(record, 'source');
|
|
146
|
+
const message = getStringField(record, 'message');
|
|
147
|
+
if (source) lines.push(` ${source}`);
|
|
148
|
+
if (message) lines.push(` ${message}`);
|
|
149
|
+
lines.push(` ${record.url}`, '');
|
|
150
|
+
}
|
|
151
|
+
lines.push(`View in ServiceNow: ${url.href}`);
|
|
152
|
+
app.ok({
|
|
153
|
+
mid_server: name, sys_id: sysId, table, count: rows.length, records: rows,
|
|
154
|
+
pagination: { limit, offset }, url: url.href, context: { instance_url: instanceURL },
|
|
155
|
+
_formatted: `${lines.join('\n')}\n`,
|
|
156
|
+
}, { summary });
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function midDiagnosticsCommand(kind, wrap) {
|
|
160
|
+
return {
|
|
161
|
+
command: `${kind} [identifier]`,
|
|
162
|
+
describe: kind === 'issues' ? 'Show MID Server issues (unresolved by default)' : 'Show MID Server lifecycle history',
|
|
163
|
+
builder: b => {
|
|
164
|
+
b.option('limit', { alias: 'l', type: 'number', default: 50, describe: 'Max records (1-1000)' })
|
|
165
|
+
.option('offset', { type: 'number', default: 0, describe: 'Result offset' });
|
|
166
|
+
if (kind === 'issues') b.option('all', { type: 'boolean', default: false, describe: 'Include resolved issues' });
|
|
167
|
+
return b;
|
|
168
|
+
},
|
|
169
|
+
handler: wrap(async (argv, app) => showMidDiagnostics(app, argv, kind)),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
94
173
|
async function listAgents(app, argv) {
|
|
95
174
|
const columns = argv.columns
|
|
96
175
|
? [...new Set(argv.columns.split(',').map(column => column.trim()).filter(Boolean))]
|
|
@@ -244,6 +323,8 @@ export function midserversCmd(wrap) {
|
|
|
244
323
|
aliases: ['midserver', 'mid'],
|
|
245
324
|
describe: 'Manage ServiceNow MID Servers and run commands through them',
|
|
246
325
|
builder: (y) => y
|
|
326
|
+
.command(midDiagnosticsCommand('issues', wrap))
|
|
327
|
+
.command(midDiagnosticsCommand('events', wrap))
|
|
247
328
|
.command({
|
|
248
329
|
command: 'list',
|
|
249
330
|
aliases: ['ls'],
|
|
@@ -479,6 +560,8 @@ export function midserversCmd(wrap) {
|
|
|
479
560
|
console.log('');
|
|
480
561
|
console.log('Available subcommands:');
|
|
481
562
|
console.log(' list List MID Servers');
|
|
563
|
+
console.log(' issues [name_or_sys_id] Show unresolved issues (--all includes resolved)');
|
|
564
|
+
console.log(' events [name_or_sys_id] Show lifecycle history');
|
|
482
565
|
console.log(' show <name_or_sys_id> Show a MID Server');
|
|
483
566
|
console.log(' add --name <name> Create a MID Server record');
|
|
484
567
|
console.log(' remove <name_or_sys_id> Remove a MID Server record');
|