awscdk-construct-scte-scheduler
Version:
AWS CDK Construct for scheduling SCTE-35 events using the MediaLive schedule API
861 lines (814 loc) • 31.9 kB
JavaScript
;
var protocols = require('@smithy/core/protocols');
var client = require('@smithy/core/client');
var types = require('@smithy/types');
const getEndpointFromConfig = async (serviceId) => undefined;
const resolveParamsForS3 = async (endpointParams) => {
const bucket = endpointParams?.Bucket || "";
if (typeof endpointParams.Bucket === "string") {
endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?"));
}
if (isArnBucketName(bucket)) {
if (endpointParams.ForcePathStyle === true) {
throw new Error("Path-style addressing cannot be used with ARN buckets");
}
}
else if (!isDnsCompatibleBucketName(bucket) ||
(bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:")) ||
bucket.toLowerCase() !== bucket ||
bucket.length < 3) {
endpointParams.ForcePathStyle = true;
}
if (endpointParams.DisableMultiRegionAccessPoints) {
endpointParams.disableMultiRegionAccessPoints = true;
endpointParams.DisableMRAP = true;
}
return endpointParams;
};
const DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/;
const IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/;
const DOTS_PATTERN = /\.\./;
const isDnsCompatibleBucketName = (bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName);
const isArnBucketName = (bucketName) => {
const [arn, partition, service, , , bucket] = bucketName.split(":");
const isArn = arn === "arn" && bucketName.split(":").length >= 6;
const isValidArn = Boolean(isArn && partition && service && bucket);
if (isArn && !isValidArn) {
throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`);
}
return isValidArn;
};
const createConfigValueProvider = (configKey, canonicalEndpointParamKey, config, isClientContextParam = false) => {
const configProvider = async () => {
let configValue;
if (isClientContextParam) {
const clientContextParams = config.clientContextParams;
const nestedValue = clientContextParams?.[configKey];
configValue = nestedValue ?? config[configKey] ?? config[canonicalEndpointParamKey];
}
else {
configValue = config[configKey] ?? config[canonicalEndpointParamKey];
}
if (typeof configValue === "function") {
return configValue();
}
return configValue;
};
if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.credentialScope ?? credentials?.CredentialScope;
return configValue;
};
}
if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") {
return async () => {
const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials;
const configValue = credentials?.accountId ?? credentials?.AccountId;
return configValue;
};
}
if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") {
return async () => {
if (config.isCustomEndpoint === false) {
return undefined;
}
const endpoint = await configProvider();
if (endpoint && typeof endpoint === "object") {
if ("url" in endpoint) {
return endpoint.url.href;
}
if ("hostname" in endpoint) {
const { protocol, hostname, port, path } = endpoint;
return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`;
}
}
return endpoint;
};
}
return configProvider;
};
const toEndpointV1 = (endpoint) => {
if (typeof endpoint === "object") {
if ("url" in endpoint) {
const v1Endpoint = protocols.parseUrl(endpoint.url);
if (endpoint.headers) {
v1Endpoint.headers = {};
for (const name in endpoint.headers) {
v1Endpoint.headers[name.toLowerCase()] = endpoint.headers[name].join(", ");
}
}
return v1Endpoint;
}
return endpoint;
}
return protocols.parseUrl(endpoint);
};
function bindGetEndpointFromInstructions(getEndpointFromConfig) {
return async (commandInput, instructionsSupplier, clientConfig, context) => {
if (!clientConfig.isCustomEndpoint) {
let endpointFromConfig;
if (clientConfig.serviceConfiguredEndpoint) {
endpointFromConfig = await clientConfig.serviceConfiguredEndpoint();
}
else {
endpointFromConfig = await getEndpointFromConfig(clientConfig.serviceId);
}
if (endpointFromConfig) {
clientConfig.endpoint = () => Promise.resolve(toEndpointV1(endpointFromConfig));
clientConfig.isCustomEndpoint = true;
}
}
const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig);
if (typeof clientConfig.endpointProvider !== "function") {
throw new Error("config.endpointProvider is not set.");
}
const endpoint = clientConfig.endpointProvider(endpointParams, context);
if (clientConfig.isCustomEndpoint && clientConfig.endpoint) {
const customEndpoint = await clientConfig.endpoint();
if (customEndpoint?.headers) {
endpoint.headers ??= {};
for (const [name, value] of Object.entries(customEndpoint.headers)) {
endpoint.headers[name] = Array.isArray(value) ? value : [value];
}
}
}
return endpoint;
};
}
const resolveParams = async (commandInput, instructionsSupplier, clientConfig) => {
const endpointParams = {};
const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {};
for (const [name, instruction] of Object.entries(instructions)) {
switch (instruction.type) {
case "staticContextParams":
endpointParams[name] = instruction.value;
break;
case "contextParams":
endpointParams[name] = commandInput[instruction.name];
break;
case "clientContextParams":
case "builtInParams":
endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig, instruction.type !== "builtInParams")();
break;
case "operationContextParams":
endpointParams[name] = instruction.get(commandInput);
break;
default:
throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction));
}
}
if (Object.keys(instructions).length === 0) {
Object.assign(endpointParams, clientConfig);
}
if (String(clientConfig.serviceId).toLowerCase() === "s3") {
await resolveParamsForS3(endpointParams);
}
return endpointParams;
};
function setFeature(context, feature, value) {
if (!context.__smithy_context) {
context.__smithy_context = { features: {} };
}
else if (!context.__smithy_context.features) {
context.__smithy_context.features = {};
}
context.__smithy_context.features[feature] = value;
}
function bindEndpointMiddleware(getEndpointFromConfig) {
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
return ({ config, instructions, }) => {
return (next, context) => async (args) => {
if (config.isCustomEndpoint) {
setFeature(context, "ENDPOINT_OVERRIDE", "N");
}
const endpoint = await getEndpointFromInstructions(args.input, {
getEndpointParameterInstructions() {
return instructions;
},
}, { ...config }, context);
context.endpointV2 = endpoint;
context.authSchemes = endpoint.properties?.authSchemes;
const authScheme = context.authSchemes?.[0];
if (authScheme) {
context["signing_region"] = authScheme.signingRegion;
context["signing_service"] = authScheme.signingName;
const smithyContext = client.getSmithyContext(context);
const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption;
if (httpAuthOption) {
httpAuthOption.signingProperties = Object.assign(httpAuthOption.signingProperties || {}, {
signing_region: authScheme.signingRegion,
signingRegion: authScheme.signingRegion,
signing_service: authScheme.signingName,
signingName: authScheme.signingName,
signingRegionSet: authScheme.signingRegionSet,
}, authScheme.properties);
}
}
return next({
...args,
});
};
};
}
const serializerMiddlewareOption = {
name: "serializerMiddleware"};
const endpointMiddlewareOptions = {
step: "serialize",
tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"],
name: "endpointV2Middleware",
override: true,
relation: "before",
toMiddleware: serializerMiddlewareOption.name,
};
function bindGetEndpointPlugin(getEndpointFromConfig) {
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
return (config, instructions) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(endpointMiddleware({
config,
instructions,
}), endpointMiddlewareOptions);
},
});
}
function bindResolveEndpointConfig(getEndpointFromConfig) {
return (input) => {
const tls = input.tls ?? true;
const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input;
const customEndpointProvider = endpoint != null ? async () => toEndpointV1(await client.normalizeProvider(endpoint)()) : undefined;
const isCustomEndpoint = !!endpoint;
const resolvedConfig = Object.assign(input, {
endpoint: customEndpointProvider,
tls,
isCustomEndpoint,
useDualstackEndpoint: client.normalizeProvider(useDualstackEndpoint ?? false),
useFipsEndpoint: client.normalizeProvider(useFipsEndpoint ?? false),
});
let configuredEndpointPromise = undefined;
resolvedConfig.serviceConfiguredEndpoint = async () => {
if (input.serviceId && !configuredEndpointPromise) {
configuredEndpointPromise = getEndpointFromConfig(input.serviceId);
}
return configuredEndpointPromise;
};
return resolvedConfig;
};
}
class BinaryDecisionDiagram {
nodes;
root;
conditions;
results;
constructor(bdd, root, conditions, results) {
this.nodes = bdd;
this.root = root;
this.conditions = conditions;
this.results = results;
}
static from(bdd, root, conditions, results) {
return new BinaryDecisionDiagram(bdd, root, conditions, results);
}
}
class EndpointCache {
capacity;
data = new Map();
parameters = [];
constructor({ size, params }) {
this.capacity = size ?? 50;
if (params) {
this.parameters = params;
}
}
get(endpointParams, resolver) {
const key = this.hash(endpointParams);
if (key === false) {
return resolver();
}
if (!this.data.has(key)) {
if (this.data.size > this.capacity + 10) {
const keys = this.data.keys();
let i = 0;
while (true) {
const { value, done } = keys.next();
this.data.delete(value);
if (done || ++i > 10) {
break;
}
}
}
this.data.set(key, resolver());
}
return this.data.get(key);
}
size() {
return this.data.size;
}
hash(endpointParams) {
let buffer = "";
const { parameters } = this;
if (parameters.length === 0) {
return false;
}
for (const param of parameters) {
const val = String(endpointParams[param] ?? "");
if (val.includes("|;")) {
return false;
}
buffer += val + "|;";
}
return buffer;
}
}
class EndpointError extends Error {
constructor(message) {
super(message);
this.name = "EndpointError";
}
}
const debugId = "endpoints";
function toDebugString(input) {
if (typeof input !== "object" || input == null) {
return input;
}
if ("ref" in input) {
return `$${toDebugString(input.ref)}`;
}
if ("fn" in input) {
return `${input.fn}(${(input.argv || []).map(toDebugString).join(", ")})`;
}
return JSON.stringify(input, null, 2);
}
const customEndpointFunctions = {};
const booleanEquals = (value1, value2) => value1 === value2;
function coalesce(...args) {
for (const arg of args) {
if (arg != null) {
return arg;
}
}
return undefined;
}
const getAttrPathList = (path) => {
const parts = path.split(".");
const pathList = [];
for (const part of parts) {
const squareBracketIndex = part.indexOf("[");
if (squareBracketIndex !== -1) {
if (part.indexOf("]") !== part.length - 1) {
throw new EndpointError(`Path: '${path}' does not end with ']'`);
}
const arrayIndex = part.slice(squareBracketIndex + 1, -1);
if (Number.isNaN(parseInt(arrayIndex))) {
throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path}'`);
}
if (squareBracketIndex !== 0) {
pathList.push(part.slice(0, squareBracketIndex));
}
pathList.push(arrayIndex);
}
else {
pathList.push(part);
}
}
return pathList;
};
const getAttr = (value, path) => getAttrPathList(path).reduce((acc, index) => {
if (typeof acc !== "object") {
throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`);
}
else if (Array.isArray(acc)) {
const i = parseInt(index);
return acc[i < 0 ? acc.length + i : i];
}
return acc[index];
}, value);
const isSet = (value) => value != null;
const VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`);
const isValidHostLabel = (value, allowSubDomains = false) => {
if (!allowSubDomains) {
return VALID_HOST_LABEL_REGEX.test(value);
}
const labels = value.split(".");
for (const label of labels) {
if (!isValidHostLabel(label)) {
return false;
}
}
return true;
};
function ite(condition, trueValue, falseValue) {
return condition ? trueValue : falseValue;
}
const not = (value) => !value;
const IP_V4_REGEX = new RegExp(`^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$`);
const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
const DEFAULT_PORTS = {
[types.EndpointURLScheme.HTTP]: 80,
[types.EndpointURLScheme.HTTPS]: 443,
};
const parseURL = (value) => {
const whatwgURL = (() => {
try {
if (value instanceof URL) {
return value;
}
if (typeof value === "object" && "hostname" in value) {
const { hostname, port, protocol = "", path = "", query = {} } = value;
const url = new URL(`${protocol}//${hostname}${port ? `:${port}` : ""}${path}`);
url.search = Object.entries(query)
.map(([k, v]) => `${k}=${v}`)
.join("&");
return url;
}
return new URL(value);
}
catch (error) {
return null;
}
})();
if (!whatwgURL) {
console.error(`Unable to parse ${JSON.stringify(value)} as a whatwg URL.`);
return null;
}
const urlString = whatwgURL.href;
const { host, hostname, pathname, protocol, search } = whatwgURL;
if (search) {
return null;
}
const scheme = protocol.slice(0, -1);
if (!Object.values(types.EndpointURLScheme).includes(scheme)) {
return null;
}
const isIp = isIpAddress(hostname);
const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) ||
(typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`));
const authority = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`;
return {
scheme,
authority,
path: pathname,
normalizedPath: pathname.endsWith("/") ? pathname : `${pathname}/`,
isIp,
};
};
function split(value, delimiter, limit) {
if (limit === 1) {
return [value];
}
if (value === "") {
return [""];
}
const parts = value.split(delimiter);
if (limit === 0) {
return parts;
}
return parts.slice(0, limit - 1).concat(parts.slice(1).join(delimiter));
}
const stringEquals = (value1, value2) => value1 === value2;
const substring = (input, start, stop, reverse) => {
if (input == null || start >= stop || input.length < stop || /[^\u0000-\u007f]/.test(input)) {
return null;
}
if (!reverse) {
return input.substring(start, stop);
}
return input.substring(input.length - stop, input.length - start);
};
const uriEncode = (value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
const endpointFunctions = {
booleanEquals,
coalesce,
getAttr,
isSet,
isValidHostLabel,
ite,
not,
parseURL,
split,
stringEquals,
substring,
uriEncode,
};
const evaluateTemplate = (template, options) => {
const evaluatedTemplateArr = [];
const { referenceRecord, endpointParams } = options;
let currentIndex = 0;
while (currentIndex < template.length) {
const openingBraceIndex = template.indexOf("{", currentIndex);
if (openingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(currentIndex));
break;
}
evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex));
const closingBraceIndex = template.indexOf("}", openingBraceIndex);
if (closingBraceIndex === -1) {
evaluatedTemplateArr.push(template.slice(openingBraceIndex));
break;
}
if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") {
evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex));
currentIndex = closingBraceIndex + 2;
}
const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex);
if (parameterName.includes("#")) {
const [refName, attrName] = parameterName.split("#");
evaluatedTemplateArr.push(getAttr((referenceRecord[refName] ?? endpointParams[refName]), attrName));
}
else {
evaluatedTemplateArr.push((referenceRecord[parameterName] ?? endpointParams[parameterName]));
}
currentIndex = closingBraceIndex + 1;
}
return evaluatedTemplateArr.join("");
};
const getReferenceValue = ({ ref }, options) => {
return options.referenceRecord[ref] ?? options.endpointParams[ref];
};
const evaluateExpression = (obj, keyName, options) => {
if (typeof obj === "string") {
return evaluateTemplate(obj, options);
}
else if (obj["fn"]) {
return group$2.callFunction(obj, options);
}
else if (obj["ref"]) {
return getReferenceValue(obj, options);
}
throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
};
const callFunction = ({ fn, argv }, options) => {
const evaluatedArgs = Array(argv.length);
for (let i = 0; i < evaluatedArgs.length; ++i) {
const arg = argv[i];
if (typeof arg === "boolean" || typeof arg === "number") {
evaluatedArgs[i] = arg;
}
else {
evaluatedArgs[i] = group$2.evaluateExpression(arg, "arg", options);
}
}
const namespaceSeparatorIndex = fn.indexOf(".");
if (namespaceSeparatorIndex !== -1) {
const namespaceFunctions = customEndpointFunctions[fn.slice(0, namespaceSeparatorIndex)];
const customFunction = namespaceFunctions?.[fn.slice(namespaceSeparatorIndex + 1)];
if (typeof customFunction === "function") {
return customFunction(...evaluatedArgs);
}
}
const callable = endpointFunctions[fn];
if (typeof callable === "function") {
return callable(...evaluatedArgs);
}
throw new Error(`function ${fn} not loaded in endpointFunctions.`);
};
const group$2 = {
evaluateExpression,
callFunction,
};
const evaluateCondition = (condition, options) => {
const { assign } = condition;
if (assign && assign in options.referenceRecord) {
throw new EndpointError(`'${assign}' is already defined in Reference Record.`);
}
const value = callFunction(condition, options);
options.logger?.debug?.(`${debugId} evaluateCondition: ${toDebugString(condition)} = ${toDebugString(value)}`);
const result = value === "" ? true : !!value;
if (assign != null) {
return { result, toAssign: { name: assign, value } };
}
return { result };
};
const getEndpointHeaders = (headers, options) => Object.entries(headers ?? {}).reduce((acc, [headerKey, headerVal]) => {
acc[headerKey] = headerVal.map((headerValEntry) => {
const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options);
if (typeof processedExpr !== "string") {
throw new EndpointError(`Header '${headerKey}' value '${processedExpr}' is not a string`);
}
return processedExpr;
});
return acc;
}, {});
const getEndpointProperties = (properties, options) => Object.entries(properties).reduce((acc, [propertyKey, propertyVal]) => {
acc[propertyKey] = group$1.getEndpointProperty(propertyVal, options);
return acc;
}, {});
const getEndpointProperty = (property, options) => {
if (Array.isArray(property)) {
return property.map((propertyEntry) => getEndpointProperty(propertyEntry, options));
}
switch (typeof property) {
case "string":
return evaluateTemplate(property, options);
case "object":
if (property === null) {
throw new EndpointError(`Unexpected endpoint property: ${property}`);
}
return group$1.getEndpointProperties(property, options);
case "boolean":
return property;
default:
throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`);
}
};
const group$1 = {
getEndpointProperty,
getEndpointProperties,
};
const getEndpointUrl = (endpointUrl, options) => {
const expression = evaluateExpression(endpointUrl, "Endpoint URL", options);
if (typeof expression === "string") {
try {
return new URL(expression);
}
catch (error) {
console.error(`Failed to construct URL with ${expression}`, error);
throw error;
}
}
throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`);
};
const RESULT = 100_000_000;
const decideEndpoint = (bdd, options) => {
const { nodes, root, results, conditions } = bdd;
let ref = root;
const referenceRecord = {};
const closure = {
referenceRecord,
endpointParams: options.endpointParams,
logger: options.logger,
};
while (ref !== 1 && ref !== -1 && ref < RESULT) {
const node_i = 3 * (Math.abs(ref) - 1);
const [condition_i, highRef, lowRef] = [nodes[node_i], nodes[node_i + 1], nodes[node_i + 2]];
const [fn, argv, assign] = conditions[condition_i];
const evaluation = evaluateCondition({ fn, assign, argv }, closure);
if (evaluation.toAssign) {
const { name, value } = evaluation.toAssign;
referenceRecord[name] = value;
}
ref = ref >= 0 === evaluation.result ? highRef : lowRef;
}
if (ref >= RESULT) {
const result = results[ref - RESULT];
if (result[0] === -1) {
const [, errorExpression] = result;
throw new EndpointError(evaluateExpression(errorExpression, "Error", closure));
}
const [url, properties, headers] = result;
return {
url: getEndpointUrl(url, closure),
properties: getEndpointProperties(properties, closure),
headers: getEndpointHeaders(headers ?? {}, closure),
};
}
throw new EndpointError(`No matching endpoint.`);
};
const evaluateConditions = (conditions = [], options) => {
const conditionsReferenceRecord = {};
const conditionOptions = {
...options,
referenceRecord: { ...options.referenceRecord },
};
let didAssign = false;
for (const condition of conditions) {
const { result, toAssign } = evaluateCondition(condition, conditionOptions);
if (!result) {
return { result };
}
if (toAssign) {
didAssign = true;
conditionsReferenceRecord[toAssign.name] = toAssign.value;
conditionOptions.referenceRecord[toAssign.name] = toAssign.value;
options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`);
}
}
if (didAssign) {
return { result: true, referenceRecord: conditionsReferenceRecord };
}
return { result: true };
};
const evaluateEndpointRule = (endpointRule, options) => {
const { conditions, endpoint } = endpointRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const endpointRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
const { url, properties, headers } = endpoint;
options.logger?.debug?.(`${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`);
const endpointToReturn = { url: getEndpointUrl(url, endpointRuleOptions) };
if (headers != null) {
endpointToReturn.headers = getEndpointHeaders(headers, endpointRuleOptions);
}
if (properties != null) {
endpointToReturn.properties = getEndpointProperties(properties, endpointRuleOptions);
}
return endpointToReturn;
};
const evaluateErrorRule = (errorRule, options) => {
const { conditions, error } = errorRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const errorRuleOptions = referenceRecord
? {
...options,
referenceRecord: { ...options.referenceRecord, ...referenceRecord },
}
: options;
throw new EndpointError(evaluateExpression(error, "Error", errorRuleOptions));
};
const evaluateRules = (rules, options) => {
for (const rule of rules) {
if (rule.type === "endpoint") {
const endpointOrUndefined = evaluateEndpointRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else if (rule.type === "error") {
evaluateErrorRule(rule, options);
}
else if (rule.type === "tree") {
const endpointOrUndefined = group.evaluateTreeRule(rule, options);
if (endpointOrUndefined) {
return endpointOrUndefined;
}
}
else {
throw new EndpointError(`Unknown endpoint rule: ${rule}`);
}
}
throw new EndpointError(`Rules evaluation failed`);
};
const evaluateTreeRule = (treeRule, options) => {
const { conditions, rules } = treeRule;
const { result, referenceRecord } = evaluateConditions(conditions, options);
if (!result) {
return;
}
const treeRuleOptions = referenceRecord
? { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }
: options;
return group.evaluateRules(rules, treeRuleOptions);
};
const group = {
evaluateRules,
evaluateTreeRule,
};
const resolveEndpoint = (ruleSetObject, options) => {
const { endpointParams, logger } = options;
const { parameters, rules } = ruleSetObject;
options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`);
for (const paramKey in parameters) {
const parameter = parameters[paramKey];
const endpointParam = endpointParams[paramKey];
if (endpointParam == null && parameter.default != null) {
endpointParams[paramKey] = parameter.default;
continue;
}
if (parameter.required && endpointParam == null) {
throw new EndpointError(`Missing required parameter: '${paramKey}'`);
}
}
const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} });
options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`);
return endpoint;
};
const resolveEndpointRequiredConfig = (input) => {
const { endpoint } = input;
if (endpoint === undefined) {
input.endpoint = async () => {
throw new Error("@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint.");
};
}
return input;
};
const getEndpointFromInstructions = bindGetEndpointFromInstructions(getEndpointFromConfig);
const resolveEndpointConfig = bindResolveEndpointConfig(getEndpointFromConfig);
const endpointMiddleware = bindEndpointMiddleware(getEndpointFromConfig);
const getEndpointPlugin = bindGetEndpointPlugin(getEndpointFromConfig);
exports.BinaryDecisionDiagram = BinaryDecisionDiagram;
exports.EndpointCache = EndpointCache;
exports.EndpointError = EndpointError;
exports.customEndpointFunctions = customEndpointFunctions;
exports.decideEndpoint = decideEndpoint;
exports.endpointMiddleware = endpointMiddleware;
exports.endpointMiddlewareOptions = endpointMiddlewareOptions;
exports.getEndpointFromInstructions = getEndpointFromInstructions;
exports.getEndpointPlugin = getEndpointPlugin;
exports.isIpAddress = isIpAddress;
exports.isValidHostLabel = isValidHostLabel;
exports.middlewareEndpointToEndpointV1 = toEndpointV1;
exports.resolveEndpoint = resolveEndpoint;
exports.resolveEndpointConfig = resolveEndpointConfig;
exports.resolveEndpointRequiredConfig = resolveEndpointRequiredConfig;
exports.resolveParams = resolveParams;
exports.toEndpointV1 = toEndpointV1;