functions/transfer/transfer/attribute/attribute.js
import typedError from 'error/typed';
/**
* An unsupported parameter value object was encountered.
*
* @type {Error}
*/
const artifactParameterError = typedError({
message: 'Unsupported object key "{keys}"',
type: 'pipeline.attribute',
});
/**
* The defined remote artifact does not exist or access has not been granted.
*
* @type {Error}
*/
const artifactNotFound = typedError({
message: 'Artifact "{artifactName}" was referenced, but is not a valid InputArtifact.',
type: 'pipeline.attribute.artifact.not_found',
});
/**
* Indicates a remote artifact type
*
* @type {String}
*/
const REMOTE = 'REMOTE';
/**
* Indicates a static artifact type
*
* @type {String}
*/
const STATIC = 'STATIC';
/**
* Resolves an attribute that has been defined as part of the UserParameters.
* An attribute can either be a static, hardcoded value or can be a reference
* to a key, found inside a file present in an input artifact.
*/
export default class Attribute {
/**
* @param {String,Object} mapping - a mapping object, either a hardcoded value
* or a reference to a key, found inside a file present in an input artifact.
* @param {Array[Artifact]} artifacts - an array of artifacts that any remote
* attribute value could be found inside.
*/
constructor(mapping, artifacts) {
/**
* Either a hardcoded value (a string) or an object denoting a remote reference.
*
* @type {String,Object}
*/
this.mapping = mapping;
/**
* An object containing {@link Artifact} instances, with the keys denoting
* the logical name of the artifact inside CodePipeline.
*
* @type {Array[Artifact]}
*/
this.artifacts = artifacts;
}
/**
* Determine if the type of mapping that has been provided for the attribute
* value is either a static value, or needs to be resolved using a remote
* input artifact.
*
* @return {String} the type of attribute mapping provided
*/
get type() {
const { mapping } = this;
if (typeof mapping !== 'string') {
return REMOTE;
}
return STATIC;
}
/**
* Resolves the value for the attribute, either returning the static attribute
* value, or the resolved value from inside a remote artifact.
*
* @return {String} the attribute's value
*/
async value() {
const { type, mapping } = this;
if (type === STATIC) {
return mapping;
}
const properties = mapping['Fn::GetParam'];
if (!properties) {
const keys = Object.keys(mapping).join(', ');
throw artifactParameterError({ keys });
}
return this.fetch(...properties);
}
/**
* @private
*
* Fetch the value of a specific parameter using the key found inside a json file
* inside the specific artifact.
*
* @param {String} artifactName - the name of the artifact the file resides in.
* @param {String} filename - The name of the JSON file inside the artifact
* @param {String} key - The property key inside the JSON file
*
* @return {String} the value of the key inside the JSON file, inside the artifact.
*/
async fetch(artifactName, filename, key) {
const artifact = this.artifacts[artifactName];
if (!artifact) {
throw artifactNotFound({ artifactName });
} else {
await artifact.ready();
return artifact.attribute(filename, key);
}
}
}