@jacebenson/jsn 4.3.13-dev.84.1 → 4.3.13-dev.85.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
package/src/commands/_generic.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enrichRelatedLists, relatedListOptions } from '../related-lists.js';
|
|
1
2
|
// Generic table-based CRUD command builder
|
|
2
3
|
|
|
3
4
|
import { formatRecordForDisplay, getStringField, buildRecordPayload, confirmDelete, interactiveList, canPrompt } from '../helpers.js';
|
|
@@ -182,7 +183,7 @@ export function buildDevCmd(name, table, aliases, defaultColumns, wrap, opts = {
|
|
|
182
183
|
aliases: ['get'],
|
|
183
184
|
describe: `Show ${vowelArticle(singular)} ${singular} by name or sys_id`,
|
|
184
185
|
builder: y => {
|
|
185
|
-
const command = recordOptions(y);
|
|
186
|
+
const command = relatedListOptions(recordOptions(y));
|
|
186
187
|
return opts.relationships?.essential?.length ? command.option('essential', { type: 'boolean', default: true,
|
|
187
188
|
describe: 'Fetch profile-declared essential children; --no-essential skips them. Supplementary lists remain lazy.' }) : command;
|
|
188
189
|
},
|
|
@@ -204,6 +205,7 @@ export function buildDevCmd(name, table, aliases, defaultColumns, wrap, opts = {
|
|
|
204
205
|
await opts.onShow(record, app, argv);
|
|
205
206
|
}
|
|
206
207
|
|
|
208
|
+
await enrichRelatedLists(record, { table, argv, app });
|
|
207
209
|
const summary = typeof showSummary === 'function' ? showSummary(record, id) : showSummary;
|
|
208
210
|
const breadcrumbs = typeof showBreadcrumbs === 'function' ? showBreadcrumbs(record, id) : showBreadcrumbs;
|
|
209
211
|
|
package/src/commands/_ticket.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enrichRelatedLists, relatedListOptions } from '../related-lists.js';
|
|
1
2
|
// Generic command builder for CRUD operations on a ServiceNow table
|
|
2
3
|
// Used by incidents, changes, requests, tasks, and most dev subcommands
|
|
3
4
|
|
|
@@ -127,13 +128,14 @@ export function buildTicketCommands(table, displayName, alias, defaultColumns, s
|
|
|
127
128
|
aliases: ['get'],
|
|
128
129
|
describe: `Show a specific ${displayName}`,
|
|
129
130
|
builder: y => {
|
|
130
|
-
const command = recordOptions(y);
|
|
131
|
+
const command = relatedListOptions(recordOptions(y));
|
|
131
132
|
return opts.relationships?.essential?.length ? command.option('essential', { type: 'boolean', default: true, describe: 'Fetch declared essential children; use --no-essential to skip' }) : command;
|
|
132
133
|
},
|
|
133
134
|
handler: wrap(async (argv, app) => {
|
|
134
135
|
const number = argv.number;
|
|
135
136
|
const record = await getRecord(app.sdk, { table, identifier: number, identifierField: argv.identifierField, displayValues: argv.displayValues ?? opts.referenceMode, matchField: opts.identifierField || 'number', resource: displayName });
|
|
136
137
|
if (opts.onShow) await opts.onShow(record, app, argv);
|
|
138
|
+
await enrichRelatedLists(record, { table, argv, app });
|
|
137
139
|
record._context = {
|
|
138
140
|
instance_url: app.getEffectiveInstance(),
|
|
139
141
|
table,
|
package/src/commands/requests.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enrichRelatedLists, relatedListOptions } from '../related-lists.js';
|
|
1
2
|
import { getRecord, recordOptions } from '../records-engine.js';
|
|
2
3
|
import { unwrapSysId } from '../resolve-record.js';
|
|
3
4
|
import { buildProfileCommand } from '../record-profiles.js';
|
|
@@ -16,7 +17,7 @@ export function requestsCmd(wrap) {
|
|
|
16
17
|
command: 'show <number>',
|
|
17
18
|
aliases: ['get'],
|
|
18
19
|
describe: 'Show a specific request with attachments and catalog variables',
|
|
19
|
-
builder: y => recordOptions(y),
|
|
20
|
+
builder: y => relatedListOptions(recordOptions(y)),
|
|
20
21
|
handler: wrap(enrichedShowHandler),
|
|
21
22
|
});
|
|
22
23
|
};
|
|
@@ -42,6 +43,7 @@ async function enrichedShowHandler(argv, app) {
|
|
|
42
43
|
table: 'sc_req_item',
|
|
43
44
|
};
|
|
44
45
|
|
|
46
|
+
await enrichRelatedLists(record, { table: 'sc_req_item', argv, app });
|
|
45
47
|
app.ok(record, {
|
|
46
48
|
summary: `Request ${number}`,
|
|
47
49
|
breadcrumbs: [
|
package/src/commands/tickets.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enrichRelatedLists, relatedListOptions } from '../related-lists.js';
|
|
1
2
|
import { formatRecordForDisplay, getStringField, buildQuerySuffix, resolveFieldsParam, buildRecordPayload, confirmDelete } from '../helpers.js';
|
|
2
3
|
import { getRecord, listRecords, recordListParams, createRecord, updateRecord, deleteRecord, recordOptions } from '../records-engine.js';
|
|
3
4
|
import { resolveSysId } from '../resolve-record.js';
|
|
@@ -59,9 +60,10 @@ export function ticketsCmd(wrap) {
|
|
|
59
60
|
command: 'show <number>',
|
|
60
61
|
aliases: ['get'],
|
|
61
62
|
describe: 'Show a ticket',
|
|
62
|
-
builder: y => recordOptions(y),
|
|
63
|
+
builder: y => relatedListOptions(recordOptions(y)),
|
|
63
64
|
handler: wrap(async (argv, app) => {
|
|
64
65
|
const record = await getRecord(app.sdk, { table: 'task', identifier: argv.number, identifierField: argv.identifierField, displayValues: argv.displayValues, matchField: 'number', resource: 'Ticket' });
|
|
66
|
+
await enrichRelatedLists(record, { table: 'task', argv, app });
|
|
65
67
|
app.ok(record, { summary: `Ticket ${argv.number}` });
|
|
66
68
|
}),
|
|
67
69
|
})
|
package/src/metadata/records.js
CHANGED
|
@@ -237,7 +237,11 @@ function buildRelationships({ entries, dictionary, relationships, sourceTable, n
|
|
|
237
237
|
const existing = result.get(id);
|
|
238
238
|
const descriptor = existing || { id, kind: 'unresolved', table: '', reference_field: '', query_status: 'unavailable',
|
|
239
239
|
reason: 'Configured related list metadata is absent, unsupported, or not visible' };
|
|
240
|
-
|
|
240
|
+
const filter = entry.filter;
|
|
241
|
+
const filterAvailable = Boolean(Object.hasOwn(entry, 'filter') && (filter === null || typeof filter === 'string'
|
|
242
|
+
|| (filter && typeof filter === 'object' && Object.hasOwn(filter, 'value') && (filter.value === null || typeof filter.value === 'string'))));
|
|
243
|
+
if (!filterAvailable) warnings.push({ source: 'sys_ui_related_list_entry', reason: 'A configured filter is absent or not visible; do not assume an unfiltered list' });
|
|
244
|
+
result.set(id, { ...descriptor, configured: true, filter_available: filterAvailable, source_table: sourceTable, position: position(entry),
|
|
241
245
|
filter: field(entry, 'filter'), order_by: field(entry, 'order_by') });
|
|
242
246
|
if (!existing) warnings.push({ source: 'sys_ui_related_list_entry', reason: descriptor.reason });
|
|
243
247
|
}
|
package/src/output.js
CHANGED
|
@@ -529,6 +529,17 @@ export class OutputWriter {
|
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
if (data._related && typeof data._related === 'object') {
|
|
533
|
+
this.writer.write('─ Related lists ─\n');
|
|
534
|
+
for (const list of data._related.nonempty || []) {
|
|
535
|
+
this.writer.write(` ${list.label}: ${list.count}\n`);
|
|
536
|
+
if (list.command) this.writer.write(` Retrieve: ${list.command}\n`);
|
|
537
|
+
}
|
|
538
|
+
this.writer.write(` Coverage: ${data._related.coverage?.state || 'unknown'}; counts reflect aggregate API access and visible metadata.\n`);
|
|
539
|
+
for (const warning of data._related.coverage?.warnings || []) this.writer.write(` Unknown (${warning.source}): ${warning.reason}\n`);
|
|
540
|
+
this.writer.write('\n');
|
|
541
|
+
}
|
|
542
|
+
|
|
532
543
|
// ── Attachments ──
|
|
533
544
|
if (data._attachments && Array.isArray(data._attachments) && data._attachments.length > 0) {
|
|
534
545
|
this.writer.write('─ Attachments ─\n');
|
package/src/related-lists.js
CHANGED
|
@@ -145,3 +145,9 @@ export async function enrichRelatedLists(record, { table, argv = {}, app }) {
|
|
|
145
145
|
instance: app.getEffectiveInstance?.() || '' });
|
|
146
146
|
return record;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
export function relatedListOptions(y) {
|
|
150
|
+
return y.option('related', { type: 'boolean', default: false, describe: 'Count related lists under Aggregate API access; suggest commands without loading supplementary records' })
|
|
151
|
+
.option('view', { type: 'string', describe: 'Form view for --related metadata (default: Default view)' })
|
|
152
|
+
.option('related-limit', { type: 'number', describe: 'Max related-list descriptors to count with --related (default 50)' });
|
|
153
|
+
}
|