@atomist/automation-client
Version:
Atomist API for software low-level client
198 lines • 8.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const GraphQL = require("../../internal/graph/graphQL");
const metadata_1 = require("./metadata");
/**
* Extract metadata from a handler instance. We need an
* instance to pull the decorator data from
* @param h handler instance
* @return {any}
*/
function metadataFromInstance(h) {
let md = null;
if (metadata_1.isEventHandlerMetadata(h)) {
md = addName(h);
}
else if (metadata_1.isCommandHandlerMetadata(h)) {
md = addName(h);
}
else {
// We need to find the instance from which to extract metadata.
// It will be the handler itself unless it implements the optional freshParametersInstance method
const knowsHowToMakeMyParams = h;
if (!!knowsHowToMakeMyParams.freshParametersInstance) {
const paramsInstance = knowsHowToMakeMyParams.freshParametersInstance();
if (!paramsInstance.__kind) {
paramsInstance.__kind = "parameters";
}
md = metadataFromDecorator(h, paramsInstance);
}
else {
md = metadataFromDecorator(h, h);
}
}
// Clone metadata as otherwise we mess with previous created instances
return _.cloneDeep(md);
}
exports.metadataFromInstance = metadataFromInstance;
function addName(r) {
if (!r.name) {
r.name = r.constructor.name;
}
return r;
}
function metadataFromDecorator(h, params) {
switch (params.__kind) {
case "command-handler":
return {
name: params.__name,
description: params.__description,
tags: params.__tags ? params.__tags : [],
intent: params.__intent ? params.__intent : [],
auto_submit: params.__autoSubmit,
parameters: parametersFromInstance(params),
mapped_parameters: mappedParameterMetadataFromInstance(params),
secrets: secretsMetadataFromInstance(params),
values: valueMetadataFromInstance(params),
};
case "parameters":
return {
name: h.__name,
description: h.__description,
tags: h.__tags ? h.__tags : [],
intent: h.__intent ? h.__intent : [],
auto_submit: h.__autoSubmit,
parameters: parametersFromInstance(params),
mapped_parameters: mappedParameterMetadataFromInstance(params),
secrets: secretsMetadataFromInstance(params),
values: valueMetadataFromInstance(params),
};
case "event-handler":
// Remove any linebreaks and spaces from those subscription
const subscription = GraphQL.inlineQuery(GraphQL.replaceOperationName(params.__subscription, h.__name));
const subscriptionName = GraphQL.operationName(subscription);
return {
name: h.__name,
description: h.__description,
tags: h.__tags ? h.__tags : [],
subscription,
subscriptionName,
secrets: secretsMetadataFromInstance(h),
values: valueMetadataFromInstance(h),
};
default:
throw new Error(`Unsupported automation '${params.constructor.name}'`);
}
}
function parametersFromInstance(r, prefix = "") {
const directParams = directParameters(r, prefix);
const nestedParameters = _.flatten(Object.keys(r)
.map(key => [key, r[key]])
.filter(nestedFieldInfo => !!nestedFieldInfo[1])
.filter(nestedFieldInfo => typeof nestedFieldInfo[1] === "object")
.map(nestedFieldInfo => parametersFromInstance(nestedFieldInfo[1], prefix + nestedFieldInfo[0] + ".")));
const allParameters = directParams.concat(nestedParameters).map(p => {
if (!!p.type && p.type !== "boolean" && p.type !== "number" && p.type !== "string" && p.type !== "freeChoices") {
const chooser = p.type;
let kind = "single";
if (chooser.pickOne !== undefined && chooser.pickOne !== null) {
kind = chooser.pickOne ? "single" : "multiple";
}
else if (chooser.kind !== undefined && chooser.kind !== null) {
kind = chooser.kind;
}
let options = [];
if (chooser.choices !== undefined && chooser.choices !== null) {
options = chooser.choices;
}
else if (chooser.options !== undefined && chooser.options !== null) {
options = chooser.options;
}
options = options.map(o => ({ value: o.value, description: o.description || o.value }));
const newChooser = {
kind,
options,
};
return Object.assign(Object.assign({}, p), { type: newChooser });
}
else {
return p;
}
});
return allParameters.sort((p1, p2) => {
const o1 = p1.order || Number.MAX_SAFE_INTEGER;
const o2 = p2.order || Number.MAX_SAFE_INTEGER;
return o1 - o2;
});
}
function directParameters(r, prefix) {
return !!r && r.__parameters ? r.__parameters.map(p => {
const nameToUse = prefix + p.name;
const parameter = {
name: nameToUse,
pattern: p.pattern ? p.pattern.source : "^.*$",
description: p.description,
required: p.required,
group: p.group,
displayable: p.displayable !== false,
type: p.type,
max_length: p.maxLength,
min_length: p.minLength,
valid_input: p.validInput,
default_value: r[p.name],
display_name: p.displayName ? p.displayName : nameToUse,
order: p.order,
control: p.control,
};
// Make this optional parameter explicit
if (parameter.default_value) {
// right now the bot only supports string parameter values
parameter.default_value = parameter.default_value.toString();
}
return parameter;
}) : [];
}
function secretsMetadataFromInstance(r, prefix = "", visited = []) {
visited.push(r);
const directSecrets = !!r && r.__secrets ? r.__secrets.map(s => ({ name: prefix + s.name, uri: s.uri })) : [];
const nestedParameters = _.flatten(Object.keys(r)
.map(key => [key, r[key]])
.filter(nestedFieldInfo => !!nestedFieldInfo[1])
.filter(nestedFieldInfo => typeof nestedFieldInfo[1] === "object")
.filter(nestedFieldInfo => !visited.includes(nestedFieldInfo[1]))
.map(nestedFieldInfo => secretsMetadataFromInstance(nestedFieldInfo[1], prefix + nestedFieldInfo[0] + ".", visited)));
return directSecrets.concat(nestedParameters);
}
function mappedParameterMetadataFromInstance(r, prefix = "", visited = []) {
visited.push(r);
const directMappedParams = !!r && r.__mappedParameters ? r.__mappedParameters.map(mp => ({
name: prefix + mp.name,
uri: mp.uri,
required: mp.required !== false,
})) : [];
const nestedParameters = _.flatten(Object.keys(r)
.map(key => [key, r[key]])
.filter(nestedFieldInfo => !!nestedFieldInfo[1])
.filter(nestedFieldInfo => typeof nestedFieldInfo[1] === "object")
.filter(nestedFieldInfo => !visited.includes(nestedFieldInfo[1]))
.map(nestedFieldInfo => mappedParameterMetadataFromInstance(nestedFieldInfo[1], prefix + nestedFieldInfo[0] + ".", visited)));
return directMappedParams.concat(nestedParameters);
}
function valueMetadataFromInstance(r, prefix = "", visited = []) {
visited.push(r);
const directValues = !!r && r.__values ? r.__values.map(mp => ({
name: prefix + mp.name,
path: mp.value.path,
required: mp.value.required !== false,
type: mp.value.type ? mp.value.type : "string",
})) : [];
const nestedValues = _.flatten(Object.keys(r)
.map(key => [key, r[key]])
.filter(nestedFieldInfo => !!nestedFieldInfo[1])
.filter(nestedFieldInfo => typeof nestedFieldInfo[1] === "object")
.filter(nestedFieldInfo => !visited.includes(nestedFieldInfo[1]))
.map(nestedFieldInfo => valueMetadataFromInstance(nestedFieldInfo[1], prefix + nestedFieldInfo[0] + ".", visited)));
return directValues.concat(nestedValues);
}
//# sourceMappingURL=metadataReading.js.map