@petarmihaylov/node-raas
Version:
A tiny library and CLI for interacting with the Reports as a Service - RAAS - API from UKG - Ultimate Kronos Group. This project is maintained by the team behind RaasTastic and the community. It provides a balanced set of features that should suit a broad
325 lines (324 loc) • 15.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const inquirer = tslib_1.__importStar(require("inquirer"));
const actions_1 = require("../lib/actions");
const core_raas_1 = require("../lib/core-raas");
const formatters_1 = require("../utils/formatters");
class Pull extends core_1.Command {
async run() {
const { flags } = await this.parse(Pull);
let responses = {};
if (flags.baseEndpointUrl === undefined ||
flags.username === undefined ||
flags.password === undefined ||
flags.customerApiKey === undefined ||
flags.userApiKey === undefined ||
flags.verbose === undefined) {
responses = await inquirer.prompt([
{
name: 'baseEndpointUrl',
message: 'Select your environment:',
type: 'rawlist',
// Ask for this when the base endpoint was not set via a parameter
when: () => {
return flags.baseEndpointUrl === undefined;
},
default: 8,
loop: true,
choices: [
new inquirer.Separator('PRODUCTION Environments'),
{ name: 'service2.ultipro.com' },
{ name: 'service3.ultipro.ca' },
{ name: 'service4.ultipro.com' },
{ name: 'service5.ultipro.com' },
new inquirer.Separator('TEST Environments'),
{ name: 'rental2.ultipro.com' },
{ name: 'rental3.ultipro.ca' },
{ name: 'rental4.ultipro.com' },
{ name: 'rental5.ultipro.com' },
{ name: 'servicet.ultipro.com' },
],
},
{
name: 'maskPassword',
message: 'Mask password input?',
type: 'confirm',
default: true,
when: () => {
return (flags.password === undefined && process.env.PASSWORD === undefined);
},
},
{
name: 'username',
message: 'Enter an employee username or a service account username:',
type: 'input',
validate: (input) => input.length > 0
? true
: 'Username cannot be blank. Please enter a username.',
when: () => {
return flags.username === undefined;
},
},
{
name: 'password',
message: 'Enter the password:',
type: 'password',
when: (responses) => responses.maskPassword === true && flags.password === undefined,
mask: '*',
validate: (input) => input.length > 0
? true
: 'Password cannot be blank. Please enter a password.',
},
{
name: 'password',
message: 'Enter the password:',
type: 'input',
when: (responses) => responses.maskPassword === false && flags.password === undefined,
validate: (input) => input.length > 0
? true
: 'Password cannot be blank. Please enter a password.',
},
{
name: 'userApiKey',
message: 'Enter User API Key (12-characters):',
type: 'input',
validate: (input) => input.length === 12
? true
: 'Please enter a valid 12-character User API Key from UKG Pro > MENU > SYSTEM CONFIGURATION > Security > Service Account Administration (Service Accounts) | Web Services (Employee Users) page. Service Accounts that have the same Username in PROD and TEST (if available) may still have different User API Keys in each environment.',
when: () => {
return flags.userApiKey === undefined;
},
},
{
name: 'customerApiKey',
message: 'Enter Customer API Key (5-characters):',
type: 'input',
validate: (input) => input.length === 5
? true
: 'Please enter a valid 5-character ampha-numeric Customer API Key. This is the 5-character alpha-numeric key listed at the top-left in UKG Pro > MENU > SYSTEM CONFIGURATION > Security > Service Account Administration page. The Customer API Key in PRODUCTION and TEST (if available) are different.',
when: () => {
return flags.customerApiKey === undefined;
},
},
{
name: 'verbose',
message: 'Verbose output?\n(Print the raw request/response pair for calls that result in an error.)',
type: 'confirm',
// Ask for this when the verbosity flag is not passed endpoint was not set via a parameter
when: () => {
return (flags.verbose === undefined && process.env.VERBOSE === undefined);
},
default: false,
env: 'VERBOSE',
},
{
name: 'verbose',
message: 'WARNING: Earlier you selected to hide the password. Error on the LogOn step will print your credentials to the console when Verbose output is selected. Please confirm Verbose output should be enabled:',
type: 'confirm',
askAnswered: true,
// Ask for this when the verbosity flag is not passed endpoint was not set via a parameter
when: (responses) => {
return (responses.maskPassword === true && responses.verbose === true);
},
default: false,
},
]);
// Assign the answer for verbosity back to flags so it can be passed to the *Action methods
if (responses === null || responses === void 0 ? void 0 : responses.verbose)
flags.verbose = responses.verbose;
}
flags.console = true; // Signal to actions that the call is coming from the console command
const raasCredential = {
UserName: responses.username || flags.username,
Password: responses.password || flags.password,
ClientAccessKey: responses.customerApiKey || flags.customerApiKey,
UserAccessKey: responses.userApiKey || flags.userApiKey,
};
// Ask the user what they would like to do
const beginPrompt = [
{
name: 'action',
message: 'What would you like to do?',
type: 'rawlist',
// Ask for this when the base endpoint was not set via a parameter
default: 8,
loop: true,
choices: [
{ name: 'GetReportList' },
{ name: 'GetReportParameters' },
{ name: 'ExecuteReport' },
{ name: 'RetrieveReport' },
{ name: 'LogOff and Exit' },
],
},
];
const getReportPathOrId = [
{
name: 'reportPathOrId',
message: 'What is the Report Path or ID?',
type: 'input',
default: process.env.REPORT_PATH_OR_ID || '',
validate: (input) => input.length > 0 ? true : 'Reort path or ID cannot be blank.',
filter: (input) => {
return input[0] === 'i' ? `storeID("${input}")` : input;
},
},
];
const clients = await (0, core_raas_1.config)(responses.baseEndpointUrl || flags.baseEndpointUrl);
const logOnResult = await (0, actions_1.logOnAction)(clients, raasCredential, flags);
let reportPathOrId = '';
let reportKey = '';
// Used as a check to make sure the user retrieves reports for which they have started execution
let retrievedLastReport = true;
let executeReportResult;
async function repl() {
let answer = await inquirer.prompt(beginPrompt);
let keepLooping = true;
const keepReportId = [
{
name: 'keepReportId',
message: 'Enter a new Report Path or ID?',
type: 'confirm',
default: false,
},
];
switch (answer.action) {
case 'GetReportList':
console.log(`Getting Report List for: ${answer.reportPathOrId} `);
break;
case 'GetReportParameters':
if (reportPathOrId === '') {
answer = await inquirer.prompt(getReportPathOrId);
reportPathOrId = answer.reportPathOrId;
}
else {
answer = await inquirer.prompt(keepReportId);
if (answer.keepReportId) {
answer = await inquirer.prompt(getReportPathOrId);
reportPathOrId = answer.reportPathOrId;
}
}
await (0, actions_1.getReportParametersAction)(clients, logOnResult, reportPathOrId, flags).catch((error) => {
console.error(error.message);
});
break;
case 'ExecuteReport':
if (retrievedLastReport) {
if (reportPathOrId === '') {
answer = await inquirer.prompt(getReportPathOrId);
reportPathOrId = answer.reportPathOrId;
}
else {
answer = await inquirer.prompt(keepReportId);
if (answer.keepReportId) {
answer = await inquirer.prompt(getReportPathOrId);
reportPathOrId = answer.reportPathOrId;
}
}
try {
executeReportResult = await (0, actions_1.executeReportAction)(clients, logOnResult, reportPathOrId, flags);
}
catch (error) {
let errorMessage = 'Failed to do something exceptional';
if (error instanceof Error) {
errorMessage = error.message;
console.error(errorMessage);
}
}
// If there are no errors store the report key and indicate there is a pending report
if (!(executeReportResult === null || executeReportResult === void 0 ? void 0 : executeReportResult.hasErrors)) {
reportKey =
executeReportResult === null || executeReportResult === void 0 ? void 0 : executeReportResult.result[0].ExecuteReportResult.ReportKey;
retrievedLastReport = false;
}
}
else {
console.log(chalk_1.default.red('Running more than one (1) report is not supported. Please run RetrieveReport first.'));
}
break;
case 'RetrieveReport':
if (reportKey !== '' && retrievedLastReport === false) {
const retrieveReportResult = await (0, actions_1.retrieveReportAction)(clients, executeReportResult, flags);
const decodedStream = await (0, formatters_1.decodeStream)(retrieveReportResult.result[0].ReportStream);
console.log(decodedStream);
reportKey = '';
retrievedLastReport = true;
}
else
console.log(chalk_1.default.red('You must ExecuteReport before you can RetrieveReport.'));
break;
case 'LogOff and Exit':
keepLooping = false;
break;
}
if (keepLooping) {
repl();
}
else {
await (0, actions_1.logOffAction)(clients, logOnResult, flags);
}
}
await repl();
}
}
exports.default = Pull;
Pull.description = 'Quickly test reports and access with this interactive console pulling data from a BI report through Reports as a Service (RAAS).';
Pull.examples = [
'$ node-raas console',
'$ node-raas console -e rental4.ultipro.com',
];
Pull.flags = {
// flag with no value (-h, --help)
help: core_1.Flags.help({ char: 'h' }),
// flag with a value (-u, --username="VALUE")
username: core_1.Flags.string({
char: 'u',
description: 'Username of user or service account. Employee user is required for pulling UKG Time Management data.',
env: 'USERNAME',
}),
// flag with a value (-p, --password="VALUE")
password: core_1.Flags.string({
char: 'p',
description: 'Password for the provided username.',
env: 'PASSWORD',
}),
// flag with a value (-c, --customer-api-key="VALUE")
customerApiKey: core_1.Flags.string({
char: 'c',
description: 'A 5-character alpha-numeric key from UKG Pro > MENU > SYSTEM CONFIGURATION > Security > Service Account Administration.',
env: 'CUSTOMER_API_KEY',
}),
// flag with a value (-a, --user-api-key="VALUE")
userApiKey: core_1.Flags.string({
char: 'a',
description: 'A 12-character alpha-numeric key for the provided username from UKG Pro > MENU > SYSTEM CONFIGURATION > Security > Service Account Administration.',
env: 'USER_API_KEY',
}),
// flag with a value (-e, --base-endpoint-url="VALUE")
baseEndpointUrl: core_1.Flags.string({
char: 'e',
options: [
'servicet.ultipro.com',
'service2.ultipro.com',
'service3.ultipro.ca',
'service4.ultipro.com',
'service5.ultipro.com',
'rental2.ultipro.com',
'rental3.ultipro.ca',
'rental4.ultipro.com',
'rental5.ultipro.com',
],
description: 'Base endpoint URL from UKG Pro > MENU > SYSTEM CONFIGURATION > Security > Web Services. Do not include the protocol (https://).',
env: 'BASE_ENDPOINT_URL',
}),
// flag with no value (-v, --verbose)
verbose: core_1.Flags.boolean({
char: 'v',
description: 'Output raw request/response combination for failing requests.',
env: 'VERBOSE',
}),
console: core_1.Flags.boolean(),
};