Comprehensive TypeScript library extending ServiceNow SDK with application management, ATF testing, real-time log monitoring, AMB event subscriptions, and automation tools
npm install @sonisoft/now-sdk-ext-core


A comprehensive TypeScript library that extends the ServiceNow SDK with powerful features for application management, automated testing, log monitoring, and more. Perfect for CI/CD pipelines, development automation, and DevOps workflows.
- π Application Management - Install, upgrade, and manage ServiceNow applications programmatically
- π§ͺ ATF Test Execution - Run automated tests and get detailed results
- π Real-time Log Monitoring - Tail ServiceNow logs with two efficient methods
- π AMB (Asynchronous Message Bus) - WebSocket-based real-time event monitoring
- π Background Script Execution - Execute server-side scripts programmatically
- π Authentication - Seamless integration with ServiceNow CLI authentication
- π‘ Table API - Full CRUD operations on ServiceNow tables
- π οΈ Type-Safe - Complete TypeScript definitions for all APIs
``bash`
npm install @sonisoft/now-sdk-ext-core
- Node.js 14.x or higher
- ServiceNow CLI configured with instance credentials
- TypeScript 4.x or higher (optional, for TypeScript projects)
`bashInstall ServiceNow CLI globally
npm install -g @servicenow/sdk
π Quick Start
$3
`typescript
import { ServiceNowInstance } from '@sonisoft/now-sdk-ext-core';
import { getCredentials } from '@servicenow/sdk-cli/dist/auth/index.js';// Get credentials from ServiceNow CLI
const credential = await getCredentials('your-instance-alias');
// Create instance connection
const instance = new ServiceNowInstance({
alias: 'your-instance-alias',
credential: credential
});
`$3
`typescript
import { SyslogReader } from '@sonisoft/now-sdk-ext-core';const syslogReader = new SyslogReader(instance);
// Method 1: Using ChannelAjax (faster, more efficient)
await syslogReader.startTailingWithChannelAjax({
interval: 1000, // Poll every second
onLog: (log) => {
console.log(
[${log.sequence}] ${log.message});
},
outputFile: './logs/servicenow.log'
});// Method 2: Using Table API (supports filtering)
await syslogReader.startTailing('syslog', {
interval: 5000,
query: 'level=error^ORDERBYDESCsys_created_on',
onLog: (log) => {
console.error(
ERROR: ${log.message});
}
});// Stop tailing
syslogReader.stopTailing();
`$3
`typescript
import { BackgroundScriptExecutor } from '@sonisoft/now-sdk-ext-core';const executor = new BackgroundScriptExecutor(instance, 'global');
const script =
;const result = await executor.executeScript(script);
console.log('Script output:', result.output);
`$3
`typescript
import { ATFTestExecutor } from '@sonisoft/now-sdk-ext-core';const testExecutor = new ATFTestExecutor(instance);
// Execute a test suite
const result = await testExecutor.executeTestSuite('test_suite_sys_id', {
timeout: 300000,
onProgress: (update) => {
console.log(
Progress: ${update.progress}% - ${update.status});
}
});console.log(
Tests passed: ${result.testsPassedCount}/${result.totalTests});
`π Core Features
$3
Programmatically manage ServiceNow applications, plugins, and updates.
`typescript
import { ApplicationManager, BatchInstallation } from '@sonisoft/now-sdk-ext-core';const appManager = new ApplicationManager(instance);
// Install from batch definition
const success = await appManager.installBatch('./batch-definition.json');
// Get application details
const appDetails = await appManager.getApplicationDetails('com.example.my_app');
// Check which apps need updates
const needsAction = await appManager.getApplicationsNeedingAction('./batch-definition.json');
`Batch Definition Example:
`json
{
"packages": [
{
"id": "com.snc.sdlc.agile.multi.2.0",
"type": "plugin",
"load_demo_data": false
},
{
"id": "sn_cicd_spoke",
"type": "application",
"version": "1.2.3",
"load_demo_data": false
}
]
}
`$3
Execute tests and retrieve detailed results programmatically.
`typescript
import { ATFTestExecutor } from '@sonisoft/now-sdk-ext-core';const testExecutor = new ATFTestExecutor(instance);
// Execute a single test
const result = await testExecutor.executeTest('test_sys_id', {
timeout: 120000,
onProgress: (update) => {
console.log(
Test: ${update.testName} - ${update.status});
}
});// Execute test suite
const suiteResult = await testExecutor.executeTestSuite('suite_sys_id', {
timeout: 600000,
pollInterval: 5000
});
// Get detailed results
console.log(
Pass Rate: ${(suiteResult.testsPassedCount / suiteResult.totalTests * 100).toFixed(2)}%);
console.log(Failed Tests:, suiteResult.testResults.filter(t => t.status === 'failure'));
`$3
Two methods for log monitoring, each optimized for different use cases.
#### ChannelAjax Method (Recommended for Real-Time)
Benefits:
- β‘ Faster (1s default polling vs 5s)
- π― 100% reliable (sequence-based tracking)
- πͺ Minimal server load
- β
No duplicates or missed logs
`typescript
import { SyslogReader } from '@sonisoft/now-sdk-ext-core';const syslogReader = new SyslogReader(instance);
await syslogReader.startTailingWithChannelAjax({
interval: 1000,
onLog: (log) => {
const timestamp = new Date(log.sys_created_on).toLocaleString();
console.log(
[${timestamp}] [Seq:${log.sequence}] ${log.message});
},
outputFile: './logs/tail.log'
});
`#### Table API Method (Supports Filtering)
Benefits:
- π Server-side filtering with encoded queries
- π Access to syslog_app_scope table
- π¨ Custom field selection
- π Rich formatting options
`typescript
await syslogReader.startTailing('syslog', {
interval: 5000,
query: 'level=error^sys_created_on>javascript:gs.minutesAgoStart(10)',
onLog: (log) => {
if (log.level === 'error') {
sendAlert(log);
}
},
formatOptions: {
fields: ['sys_created_on', 'level', 'source', 'message'],
dateFormat: 'relative',
maxMessageWidth: 100
}
});
`#### Query and Export Logs
`typescript
// Query recent errors
const errors = await syslogReader.querySyslog(
'level=error^ORDERBYDESCsys_created_on',
50
);// Print formatted table
syslogReader.printTable(errors, {
fields: ['sys_created_on', 'level', 'source', 'message'],
maxMessageWidth: 80
});
// Export to file
await syslogReader.saveToFile(errors, './logs/errors.json', 'json');
await syslogReader.saveToFile(errors, './logs/errors.csv', 'csv');
await syslogReader.saveToFile(errors, './logs/errors.txt', 'table');
`$3
Monitor real-time events and record changes via WebSocket.
`typescript
import { AMBClient, MessageClientBuilder } from '@sonisoft/now-sdk-ext-core';const builder = new MessageClientBuilder();
const subscriptions = builder.buildClientSubscriptions();
const client = new AMBClient(subscriptions, instance);
// Authenticate and connect
await client.authenticate();
client.connect();
// Watch for incident changes
const channel = client.getRecordWatcherChannel('incident', 'active=true', null, {
subscriptionCallback: (message) => {
console.log('Incident updated:', message);
}
});
channel.subscribe((message) => {
console.log('Change detected:', message);
});
// Disconnect when done
client.disconnect();
`$3
Full CRUD operations on ServiceNow tables.
`typescript
import { TableAPIRequest } from '@sonisoft/now-sdk-ext-core';const tableAPI = new TableAPIRequest(instance);
// Create a record
const createResponse = await tableAPI.post('incident', {}, {
short_description: 'Test incident',
urgency: '2',
impact: '2'
});
// Read records
const readResponse = await tableAPI.get('incident', {
sysparm_query: 'active=true',
sysparm_limit: 10
});
// Update a record
const updateResponse = await tableAPI.put('incident', 'sys_id_here', {
state: '6', // Resolved
close_notes: 'Issue resolved'
});
// Partial update
const patchResponse = await tableAPI.patch('incident', 'sys_id_here', {
work_notes: 'Added update via API'
});
`$3
Execute server-side GlideScript with full control.
`typescript
import { BackgroundScriptExecutor } from '@sonisoft/now-sdk-ext-core';const executor = new BackgroundScriptExecutor(instance, 'global');
// Execute script
const result = await executor.executeScript(
);console.log('Script output:', result.output);
console.log('Return value:', result.result);
`π API Reference
$3
-
ServiceNowInstance - Instance connection and configuration
- ServiceNowRequest - HTTP request handling with authentication
- TableAPIRequest - ServiceNow Table API wrapper$3
-
ApplicationManager - High-level application management
- AppRepoApplication - App repository operations
- BatchDefinition - Batch installation definitions
- CompanyApplications - Company application queries$3
-
ATFTestExecutor - ATF test execution and monitoring
- BackgroundScriptExecutor - Server-side script execution$3
-
SyslogReader - Log querying and real-time monitoring
- AMBClient - Real-time event subscriptions
- MessageClientBuilder - AMB client configuration$3
-
Logger - Winston-based logging
- NowStringUtil - String manipulation utilities
- AppUtil - Application utility functionsπ― Use Cases
$3
`typescript
// Install required apps before deployment
const appManager = new ApplicationManager(instance);
await appManager.installBatch('./required-apps.json');// Run tests
const testExecutor = new ATFTestExecutor(instance);
const testResults = await testExecutor.executeTestSuite('deployment_test_suite');
if (testResults.testsPassedCount !== testResults.totalTests) {
throw new Error('Tests failed, aborting deployment');
}
`$3
`typescript
// Real-time error monitoring with alerts
const syslogReader = new SyslogReader(instance);await syslogReader.startTailing('syslog', {
query: 'level=error',
onLog: async (log) => {
if (log.message.includes('OutOfMemory')) {
await sendPageAlert('Critical: OOM detected');
}
await saveToElasticsearch(log);
}
});
`$3
`typescript
const executor = new BackgroundScriptExecutor(instance, 'global');
const tableAPI = new TableAPIRequest(instance);// Export data
const response = await tableAPI.get('custom_table', {
sysparm_limit: 1000,
sysparm_query: 'sys_created_on>2024-01-01'
});
// Process and transform
const records = response.bodyObject.result;
// ... transformation logic ...
// Import to another instance
for (const record of transformedRecords) {
await targetTableAPI.post('target_table', {}, record);
}
`π Command-Line Tools
The library includes ready-to-use CLI tools:
$3
`bash
node docs/examples/syslog-tail-channel.mjs your-instance ./logs/tail.log 1000
`$3
`bash
node docs/examples/syslog-tail.mjs your-instance error ./logs/errors.log
`π Documentation
Comprehensive documentation is available in the
/docs directory:- Getting Started - Setup and basic usage
- API Reference - Complete API documentation
- Application Manager - Application management guide
- ATF Test Executor - Testing automation
- Syslog Reader - Log monitoring guide
- ChannelAjax Tailing - Advanced log tailing
- AMB Guide - Real-time event monitoring
- Examples - Working code examples
π§ Advanced Configuration
$3
`typescript
import { RequestHandler, ServiceNowInstance } from '@sonisoft/now-sdk-ext-core';const handler = new RequestHandler(instance, {
timeout: 30000,
maxRetries: 3,
retryDelay: 1000
});
`$3
`typescript
import { Logger } from '@sonisoft/now-sdk-ext-core';const logger = Logger.createLogger('MyApp');
logger.info('Application started');
logger.error('Error occurred', { details: errorObj });
`$3
`typescript
import { NowSDKAuthenticationHandler } from '@sonisoft/now-sdk-ext-core';const authHandler = new NowSDKAuthenticationHandler(
'instance-alias',
credential
);
const token = await authHandler.getToken();
`π€ TypeScript Support
The library is written in TypeScript and includes full type definitions:
`typescript
import type {
ServiceNowInstance,
SyslogRecord,
ATFTestResult,
ApplicationDetailModel,
BatchDefinition
} from '@sonisoft/now-sdk-ext-core';
`π Error Handling
`typescript
import {
FileException,
InvalidParameterException
} from '@sonisoft/now-sdk-ext-core';try {
await appManager.installBatch('./batch.json');
} catch (error) {
if (error instanceof FileException) {
console.error('File not found:', error.message);
} else if (error instanceof InvalidParameterException) {
console.error('Invalid parameter:', error.message);
} else {
console.error('Unexpected error:', error);
}
}
`β‘ Performance Tips
1. Use ChannelAjax for log tailing - 5x faster than Table API polling
2. Batch operations - Group multiple API calls when possible
3. Adjust poll intervals - Balance responsiveness vs. API load
4. Use encoded queries - Server-side filtering is more efficient
5. Implement retry logic - Handle transient network issues
π Security Best Practices
1. Never hardcode credentials - Use ServiceNow CLI authentication
2. Use environment variables - For configuration
3. Implement role-based access - Verify user permissions
4. Audit API usage - Log all operations
5. Use HTTPS - Always use secure connections
π¦ Dependencies
-
@servicenow/sdk - ServiceNow SDK
- @servicenow/sdk-cli - ServiceNow CLI tools
- cometd - WebSocket support for AMB
- xml2js - XML parsing
- winston - Logging
- axios - HTTP clientπ§ͺ Testing
`bash
Run all tests
npm testRun specific test suite
npm test -- --testPathPattern=SyslogReaderRun with coverage
npm test -- --coverage
`ποΈ Building from Source
`bash
Clone the repository
git clone Install dependencies
npm installBuild TypeScript
npm run buildtsRun tests
npm testCreate package
npm pack
`π License
MIT License - see LICENSE file for details
π Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes with tests
4. Submit a pull request
π Support
For issues, questions, or contributions:
- π§ Create an issue in the repository
- π Check the documentation in
/docs
- π¬ Review existing examples in /docs/examples`- [ ] GraphQL API support
- [ ] Webhook integration
- [ ] Enhanced batch operations
- [ ] Performance metrics
- [ ] CLI tool package
- [ ] Plugin development tools
See CHANGELOG for version history and release notes.
---
Made with β€οΈ for the ServiceNow Developer Community