@jacebenson/jsn 1.0.6 → 2.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.
Files changed (45) hide show
  1. package/README.md +196 -243
  2. package/bin/jsn.js +2 -57
  3. package/package.json +35 -32
  4. package/skills/servicenow/SKILL.md +137 -0
  5. package/src/app.js +172 -0
  6. package/src/auth.js +517 -0
  7. package/src/cli.js +174 -0
  8. package/src/commands/_ticket.js +260 -0
  9. package/src/commands/auth.js +227 -0
  10. package/src/commands/catalog.js +325 -0
  11. package/src/commands/changes.js +7 -0
  12. package/src/commands/dev/_generic.js +342 -0
  13. package/src/commands/dev/_simple.js +89 -0
  14. package/src/commands/dev/eval.js +38 -0
  15. package/src/commands/dev/flows.js +573 -0
  16. package/src/commands/dev/forms.js +313 -0
  17. package/src/commands/dev/lists.js +233 -0
  18. package/src/commands/dev/logs.js +64 -0
  19. package/src/commands/dev/rest.js +64 -0
  20. package/src/commands/dev/scopes.js +156 -0
  21. package/src/commands/dev/updatesets.js +184 -0
  22. package/src/commands/dev.js +53 -0
  23. package/src/commands/groupmembers.js +152 -0
  24. package/src/commands/grouproles.js +152 -0
  25. package/src/commands/groups.js +141 -0
  26. package/src/commands/incidents.js +7 -0
  27. package/src/commands/profiles.js +91 -0
  28. package/src/commands/records.js +171 -0
  29. package/src/commands/requests.js +59 -0
  30. package/src/commands/setup.js +39 -0
  31. package/src/commands/skill.js +144 -0
  32. package/src/commands/tasks.js +7 -0
  33. package/src/commands/tickets.js +121 -0
  34. package/src/commands/users.js +144 -0
  35. package/src/commands/version.js +81 -0
  36. package/src/config.js +154 -0
  37. package/src/context.js +62 -0
  38. package/src/errors.js +101 -0
  39. package/src/help.js +85 -0
  40. package/src/helpers.js +182 -0
  41. package/src/output.js +440 -0
  42. package/src/sdk.js +615 -0
  43. package/scripts/install.sh +0 -227
  44. package/scripts/npm-install.js +0 -235
  45. package/scripts/pre-commit-check.sh +0 -61
@@ -0,0 +1,89 @@
1
+ import { buildDevCmd } from './_generic.js';
2
+ import { getStringField } from '../../helpers.js';
3
+
4
+ // Simple table-based dev commands — singular names passed for grammar
5
+ // Default columns and aliases match the Go version exactly
6
+
7
+ async function fetchExtensionChain(sdk, record) {
8
+ const chain = [];
9
+ let current = record;
10
+ let depth = 0;
11
+ const maxDepth = 10;
12
+
13
+ while (current && depth < maxDepth) {
14
+ const name = getStringField(current, 'name');
15
+ if (name) {
16
+ chain.push(name);
17
+ }
18
+
19
+ const superClass = current.super_class;
20
+ if (!superClass) break;
21
+
22
+ let superClassSysId;
23
+ if (typeof superClass === 'object' && superClass != null) {
24
+ superClassSysId = superClass.value;
25
+ } else if (typeof superClass === 'string') {
26
+ superClassSysId = superClass;
27
+ } else {
28
+ break;
29
+ }
30
+
31
+ if (!superClassSysId) break;
32
+
33
+ const params = new URLSearchParams();
34
+ params.set('sysparm_query', `sys_id=${superClassSysId}`);
35
+ params.set('sysparm_limit', '1');
36
+ params.set('sysparm_fields', 'name,super_class');
37
+ params.set('sysparm_display_value', 'all');
38
+
39
+ const records = await sdk.list('sys_db_object', params);
40
+ if (records.length === 0) break;
41
+
42
+ current = records[0];
43
+ depth++;
44
+ }
45
+
46
+ return chain;
47
+ }
48
+
49
+ export const actionsCmd = (wrap) => buildDevCmd('actions', 'sys_hub_action_type_definition', ['action'], ['name', 'active', 'sys_scope', 'sys_updated_on'], wrap, { singular: 'action', scopeValidation: true });
50
+
51
+ export const includesCmd = (wrap) => buildDevCmd('includes', 'sys_script_include', ['include', 'si'], ['name', 'api_name', 'active', 'sys_scope'], wrap, { singular: 'script include', scopeValidation: true });
52
+
53
+ export const rulesCmd = (wrap) => buildDevCmd('rules', 'sys_script', ['rule', 'br'], ['name', 'collection', 'active', 'order', 'sys_scope'], wrap, { singular: 'business rule', scopeValidation: true });
54
+
55
+ export const clientScriptsCmd = (wrap) => buildDevCmd('clientscripts', 'sys_script_client', ['clientscript', 'cs'], ['name', 'table', 'active', 'type', 'sys_scope'], wrap, { singular: 'client script', scopeValidation: true });
56
+
57
+ export const uiActionsCmd = (wrap) => buildDevCmd('uiactions', 'sys_ui_action', ['uiaction', 'ua'], ['name', 'table', 'active', 'order', 'sys_scope'], wrap, { singular: 'UI action', scopeValidation: true });
58
+
59
+ export const uiPoliciesCmd = (wrap) => buildDevCmd('uipolicies', 'sys_ui_policy', ['uipolicy', 'up'], ['short_description', 'table', 'active', 'order', 'sys_scope'], wrap, { singular: 'UI policy', scopeValidation: true });
60
+
61
+ export const tablesCmd = (wrap) => buildDevCmd('tables', 'sys_db_object', ['table', 't'], ['name', 'label', 'super_class', 'create_access_controls'], wrap, {
62
+ singular: 'table',
63
+ scopeValidation: true,
64
+ showFields: ['name', 'label', 'super_class', 'create_access_controls', 'sys_scope', 'sys_created_on', 'sys_updated_on', 'sys_created_by', 'sys_updated_by', 'is_extendable'],
65
+ async onShow(record, app) {
66
+ const tableName = getStringField(record, 'name');
67
+ const [count, extChain] = await Promise.all([
68
+ app.sdk.aggregateCount('sys_dictionary', 'name=' + tableName),
69
+ fetchExtensionChain(app.sdk, record),
70
+ ]);
71
+ record._column_count = count;
72
+ record._extension_info = { chain: extChain };
73
+ },
74
+ });
75
+
76
+ export const columnsCmd = (wrap) => buildDevCmd('columns', 'sys_dictionary', ['column', 'col'], ['element', 'column_label', 'internal_type', 'mandatory', 'max_length', 'active'], wrap, { singular: 'column', scopeValidation: true });
77
+
78
+ // Read-only commands (Go only has list/show)
79
+ export const importCmd = (wrap) => buildDevCmd('import', 'sys_import_set', ['imports', 'imp'], ['sys_import_set', 'sys_import_row', 'sys_target_table', 'sys_target_sys_id'], wrap, { singular: 'import set', readOnly: true });
80
+ export const spPagesCmd = (wrap) => buildDevCmd('sppages', 'sp_page', ['sp-pages', 'pages'], ['id', 'title', 'sys_scope'], wrap, { singular: 'Service Portal page', readOnly: true });
81
+ export const spWidgetsCmd = (wrap) => buildDevCmd('spwidgets', 'sp_widget', ['sp-widget', 'widgets'], ['id', 'name', 'sys_scope'], wrap, { singular: 'Service Portal widget', readOnly: true });
82
+ export const uiPagesCmd = (wrap) => buildDevCmd('uipages', 'sys_ui_page', ['ui-page', 'pages'], ['name', 'sys_scope'], wrap, { singular: 'UI page', readOnly: true });
83
+ export const appMenuCmd = (wrap) => buildDevCmd('appmenu', 'sys_app_application', ['app-menu', 'menu'], ['name', 'active', 'sys_scope'], wrap, { singular: 'application menu', readOnly: true });
84
+ export const scRAPICmd = (wrap) => buildDevCmd('scrapi', 'sys_ws_operation', ['scripted-rest', 'rest-api'], ['name', 'sys_ws_definition', 'sys_scope'], wrap, { singular: 'scripted REST API', readOnly: true });
85
+
86
+ // Commands with full CRUD
87
+ export const aclsCmd = (wrap) => buildDevCmd('acls', 'sys_security_acl', ['acl'], ['name', 'operation', 'type', 'active', 'sys_scope'], wrap, { singular: 'ACL', readOnly: true });
88
+ export const rolesCmd = (wrap) => buildDevCmd('roles', 'sys_user_role', ['role', 'r'], ['name', 'description', 'elevated_privilege', 'sys_scope'], wrap, { singular: 'role', scopeValidation: true });
89
+ export const propertiesCmd = (wrap) => buildDevCmd('properties', 'sys_properties', ['property', 'prop'], ['name', 'value', 'description', 'sys_scope'], wrap, { singular: 'property', readOnly: true });
@@ -0,0 +1,38 @@
1
+ import fs from 'node:fs';
2
+
3
+ export function evalCmd(wrap) {
4
+ return {
5
+ command: 'eval',
6
+ describe: 'Execute background scripts on the instance',
7
+ builder: (yargs) => {
8
+ return yargs
9
+ .option('script', { alias: 's', type: 'string', describe: 'JavaScript code to execute' })
10
+ .option('file', { alias: 'f', type: 'string', describe: 'Read script from file' });
11
+ },
12
+ handler: wrap(async (argv, app) => {
13
+ let script;
14
+
15
+ if (argv.file) {
16
+ script = fs.readFileSync(argv.file, 'utf-8');
17
+ } else if (argv.script) {
18
+ script = argv.script;
19
+ } else {
20
+ throw new Error('--script or --file is required');
21
+ }
22
+
23
+ const output = await app.sdk.executeScript(script);
24
+ app.ok({
25
+ script,
26
+ output,
27
+ instance: app.getEffectiveInstance(),
28
+ }, {
29
+ summary: 'Script executed',
30
+ breadcrumbs: [{
31
+ action: 'eval',
32
+ cmd: 'jsn dev eval --script \'...\'',
33
+ description: 'Execute a background script on the ServiceNow instance',
34
+ }],
35
+ });
36
+ }),
37
+ };
38
+ }