@unito/integration-debugger
Version:
The Unito Integration Debugger
182 lines (181 loc) • 10.7 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const blessed_1 = __importDefault(require("blessed"));
const react_blessed_1 = require("react-blessed");
const commander_1 = require("commander");
const polyfills_1 = require("./polyfills");
const app_1 = __importDefault(require("./app"));
const CrawlerDriver = __importStar(require("./services/crawlerDriver"));
const stepChecks_1 = __importDefault(require("./services/stepChecks"));
const configuration_1 = require("./resources/configuration");
const nonInteractive_1 = require("./resources/nonInteractive");
if (typeof fetch === 'undefined') {
// eslint-disable-next-line no-console
console.log('The debugger requires the fetch API, available in Node >= 18.');
process.exit(-1);
}
// Kill the app on Ctrl + C and other signals.
['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
process.on(signalType, async () => {
process.exit();
});
});
const program = new commander_1.Command();
Promise.all([(0, configuration_1.getDefaultConfiguration)(), (0, configuration_1.readConfiguration)()])
.then(([effectiveConfig, configFromFile]) => {
program
.name('integration-debugger')
.addOption(new commander_1.Option('--environment <string>', 'the environment').choices(Object.values(configuration_1.Environment)))
.addOption(new commander_1.Option('--api-key <string>', 'your API key'))
.addOption(new commander_1.Option('--integration <number>', 'the ID of the integration')
.conflicts(['integration-url'])
.argParser(value => parseInt(value)))
.addOption(new commander_1.Option('--credential <number>', 'the ID of the credential').argParser(value => parseInt(value)))
.addOption(new commander_1.Option('--integration-url <string>', 'the URL of the integration').conflicts(['integration']))
.addOption(new commander_1.Option('--graph-relative-url <string>', 'the relative URL of the graph').conflicts(['integration']))
.addOption(new commander_1.Option('--credential-account-relative-url <string>', 'the relative URL of the credential account').conflicts(['integration']))
.addOption(new commander_1.Option('--webhook-parsing-relative-url <string>', 'the relative URL to parse a webhook payload').conflicts([
'integration',
]))
.addOption(new commander_1.Option('--webhook-subscriptions-relative-url <string>', 'the relative URL to operate on a webhook subscription').conflicts(['integration']))
.addOption(new commander_1.Option('--webhook-acknowledge-relative-url <string>', 'the relative URL to acknowledge reception of a webhook').conflicts(['integration']))
.addOption(new commander_1.Option('--spawn-process <string>', 'spawn the integration process'))
.addOption(new commander_1.Option('--credential-payload <string>', 'the X-Unito-Credentials payload')
.conflicts('credential')
.argParser(value => JSON.parse(value)))
.addOption(new commander_1.Option('--secrets-payload <string>', 'the X-Unito-Secrets payload').argParser(value => JSON.parse(value)))
.addOption(new commander_1.Option('--non-interactive', 'run the debugger non-interactively'))
.addOption(new commander_1.Option('--verbose', 'output more (debug) information'))
.addOption(new commander_1.Option('--starting-path <string>', 'starting path of the crawler'))
.addOption(new commander_1.Option('--checks <string>', 'checks to perform when crawling').argParser(value => value ? value.split(',').map(v => v.trim()) : []))
.addOption(new commander_1.Option('--starting-operation <string>', 'starting operation of the crawler').choices(Object.values(CrawlerDriver.Operation)))
.addOption(new commander_1.Option('--operation-collection-items-per-page <value>', 'number of items crawled per collection page').argParser(value => parseInt(value)))
.addOption(new commander_1.Option('--operation-collection-follow-next-pages <value>', 'whether to follow next pages when crawling collections').argParser(value => value === 'true'))
.addOption(new commander_1.Option('--output-path <string>', 'output report in JSON format at the specified path'))
.addOption(new commander_1.Option('--read-only', 'whether or not to only perform read operations'))
.addOption(new commander_1.Option('--timeout <value>', `timeout in seconds passed as 'X-Unito-Operation-Deadline' header to the integration. Set to 0 for no timeout.`).argParser(value => parseInt(value)))
.action(args => {
effectiveConfig.environment = args.environment ?? configFromFile.environment;
effectiveConfig.apiKey = args.apiKey ?? configFromFile.apiKey;
effectiveConfig.integrationId = args.integration ?? configFromFile.integrationId;
effectiveConfig.credentialId = args.credential ?? configFromFile.credentialId;
effectiveConfig.integrationUrl = args.integrationUrl ?? configFromFile.integrationUrl;
effectiveConfig.graphRelativeUrl = args.graphRelativeUrl ?? configFromFile.graphRelativeUrl;
effectiveConfig.credentialAccountRelativeUrl =
args.credentialAccountRelativeUrl ?? configFromFile.credentialAccountRelativeUrl;
effectiveConfig.webhookParsingRelativeUrl =
args.webhookParsingRelativeUrl ?? configFromFile.webhookParsingRelativeUrl;
effectiveConfig.webhookSubscriptionsRelativeUrl =
args.webhookSubscriptionsRelativeUrl ?? configFromFile.webhookSubscriptionsRelativeUrl;
effectiveConfig.webhookAcknowledgeRelativeUrl =
args.webhookAcknowledgeRelativeUrl ?? configFromFile.webhookAcknowledgeRelativeUrl;
effectiveConfig.credentialPayload = args.credentialPayload ?? configFromFile.credentialPayload;
effectiveConfig.secretsPayload = args.secretsPayload ?? configFromFile.secretsPayload;
effectiveConfig.spawnProcessCommand = args.spawnProcess ?? configFromFile.spawnProcessCommand;
effectiveConfig.interactive = args.nonInteractive ? false : configFromFile.interactive;
effectiveConfig.readOnly = args.readOnly ?? configFromFile.readOnly;
effectiveConfig.timeout = args.timeout ?? configFromFile.timeout;
effectiveConfig.verbose = args.verbose ?? configFromFile.verbose;
effectiveConfig.startingPath = args.startingPath ?? configFromFile.startingPath;
effectiveConfig.startingOperation = args.startingOperation ?? configFromFile.startingOperation;
effectiveConfig.outputFilePath = args.outputPath ?? configFromFile.outputFilePath;
if (args.operationCollectionItemsPerPage !== undefined) {
effectiveConfig.operationCollectionItemsPerPage = args.operationCollectionItemsPerPage;
}
if (args.operationCollectionFollowNextPages !== undefined) {
effectiveConfig.operationCollectionFollowNextPages = args.operationCollectionFollowNextPages;
}
// Step Checks.
const availableChecks = Object.entries(stepChecks_1.default);
const availableCheckKeys = Object.keys(stepChecks_1.default);
const defaultCheckKeys = availableChecks
.filter(([_, check]) => check.activatedByDefault)
.map(([key, _]) => key);
const checkKeys = args.checks ?? defaultCheckKeys;
for (const checkKey of checkKeys) {
if (!availableCheckKeys.includes(checkKey)) {
process.stdout.write(`Invalid value found in parameter '--checks': [${checkKey}]\n Possible values: [${availableCheckKeys.join(', ')}]`);
process.stdout.write('\n');
process.exit(-1);
}
}
effectiveConfig.stepCheckKeys = checkKeys;
});
program.parse();
if (effectiveConfig.interactive) {
/* Interactive mode */
(0, polyfills_1.polyfillRequestAnimationFrame)();
const screen = blessed_1.default.screen({
autoPadding: true,
smartCSR: true,
title: 'Integration Debugger',
});
(0, react_blessed_1.render)((0, jsx_runtime_1.jsx)(app_1.default, { screen: screen, configuration: effectiveConfig }), screen);
}
else {
/* Non-interactive mode */
['SIGTERM', 'SIGINT', 'SIGQUIT', 'SIGHUP'].forEach(signalType => {
process.once(signalType, () => {
process.exit(2);
});
});
new nonInteractive_1.Runner({ ...effectiveConfig, inputs: true, outputs: true })
.run()
.then(report => {
if (report.steps.some(step => step.errors.length > 0)) {
process.exit(1);
}
else {
process.exit(0);
}
})
.catch(error => {
throw error;
})
.finally(() => {
process.exit(process.exitCode === undefined ? 3 : process.exitCode);
});
}
})
.catch(error => {
process.stdout.write(`Error: ${error.message}`);
process.stdout.write('\n');
process.exit(-1);
});
;