🚀. Socket Launch Week Day 3:Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions.Learn more
Sign In

@smithy/util-endpoints

Package Overview
Dependencies
Maintainers
3
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@smithy/util-endpoints - npm Package Compare versions

Comparing version
3.4.2
to
3.5.0
+12
-573
dist-cjs/index.js

@@ -1,573 +0,12 @@

'use strict';
var types = require('@smithy/types');
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;
};
exports.BinaryDecisionDiagram = BinaryDecisionDiagram;
exports.EndpointCache = EndpointCache;
exports.EndpointError = EndpointError;
exports.customEndpointFunctions = customEndpointFunctions;
exports.decideEndpoint = decideEndpoint;
exports.isIpAddress = isIpAddress;
exports.isValidHostLabel = isValidHostLabel;
exports.resolveEndpoint = resolveEndpoint;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EndpointError = exports.resolveEndpoint = exports.customEndpointFunctions = exports.isValidHostLabel = exports.isIpAddress = exports.decideEndpoint = exports.EndpointCache = exports.BinaryDecisionDiagram = void 0;
var endpoints_1 = require("@smithy/core/endpoints");
Object.defineProperty(exports, "BinaryDecisionDiagram", { enumerable: true, get: function () { return endpoints_1.BinaryDecisionDiagram; } });
Object.defineProperty(exports, "EndpointCache", { enumerable: true, get: function () { return endpoints_1.EndpointCache; } });
Object.defineProperty(exports, "decideEndpoint", { enumerable: true, get: function () { return endpoints_1.decideEndpoint; } });
Object.defineProperty(exports, "isIpAddress", { enumerable: true, get: function () { return endpoints_1.isIpAddress; } });
Object.defineProperty(exports, "isValidHostLabel", { enumerable: true, get: function () { return endpoints_1.isValidHostLabel; } });
Object.defineProperty(exports, "customEndpointFunctions", { enumerable: true, get: function () { return endpoints_1.customEndpointFunctions; } });
Object.defineProperty(exports, "resolveEndpoint", { enumerable: true, get: function () { return endpoints_1.resolveEndpoint; } });
Object.defineProperty(exports, "EndpointError", { enumerable: true, get: function () { return endpoints_1.EndpointError; } });

@@ -1,8 +0,1 @@

export { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
export * from "./cache/EndpointCache";
export { decideEndpoint } from "./decideEndpoint";
export * from "./lib/isIpAddress";
export * from "./lib/isValidHostLabel";
export * from "./utils/customEndpointFunctions";
export * from "./resolveEndpoint";
export * from "./types";
export { BinaryDecisionDiagram, EndpointCache, decideEndpoint, isIpAddress, isValidHostLabel, customEndpointFunctions, resolveEndpoint, EndpointError, } from "@smithy/core/endpoints";
+3
-8

@@ -1,8 +0,3 @@

export { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
export * from "./cache/EndpointCache";
export { decideEndpoint } from "./decideEndpoint";
export * from "./lib/isIpAddress";
export * from "./lib/isValidHostLabel";
export * from "./utils/customEndpointFunctions";
export * from "./resolveEndpoint";
export * from "./types";
/** @deprecated Use @smithy/core/endpoints instead. */
export { BinaryDecisionDiagram, EndpointCache, decideEndpoint, isIpAddress, isValidHostLabel, customEndpointFunctions, resolveEndpoint, EndpointError, } from "@smithy/core/endpoints";
export type { ConditionObject, DeprecatedObject, EndpointFunctions, EndpointObject, EndpointObjectHeaders, EndpointObjectProperties, EndpointParams, EndpointResolverOptions, EndpointRuleObject, ErrorRuleObject, EvaluateOptions, Expression, FunctionArgv, FunctionObject, FunctionReturn, ParameterObject, ReferenceObject, ReferenceRecord, RuleSetObject, RuleSetRules, TreeRuleObject, } from "@smithy/core/endpoints";
{
"name": "@smithy/util-endpoints",
"version": "3.4.2",
"version": "3.5.0",
"description": "Utilities to help with endpoint resolution.",

@@ -8,14 +8,5 @@ "main": "./dist-cjs/index.js",

"scripts": {
"build": "concurrently 'yarn:build:types' 'yarn:build:es:cjs'",
"build:es:cjs": "yarn g:tsc -p tsconfig.es.json && node ../../scripts/inline util-endpoints",
"build:types": "yarn g:tsc -p tsconfig.types.json",
"build:types:downlevel": "premove dist-types/ts3.4 && downlevel-dts dist-types dist-types/ts3.4",
"clean": "premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo",
"format": "prettier --config ../../prettier.config.js --ignore-path ../../.prettierignore --write \"**/*.{ts,md,json}\"",
"lint": "eslint -c ../../.eslintrc.js \"src/**/*.ts\"",
"stage-release": "premove .release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz",
"test": "yarn g:vitest run",
"test:integration": "yarn g:vitest run -c vitest.config.integ.mts",
"test:integration:watch": "yarn g:vitest watch -c vitest.config.integ.mts",
"test:watch": "yarn g:vitest watch"
"build": "yarn g:tsc -p tsconfig.cjs.json && yarn g:tsc -p tsconfig.es.json && yarn g:tsc -p tsconfig.types.json",
"clean": "rm -rf dist-cjs dist-es dist-types",
"stage-release": "rm -rf .release && yarn pack && mkdir ./.release && tar zxvf ./package.tgz --directory ./.release && rm ./package.tgz"
},

@@ -32,13 +23,5 @@ "keywords": [

"dependencies": {
"@smithy/node-config-provider": "^4.3.14",
"@smithy/types": "^4.14.1",
"@smithy/core": "^3.24.0",
"tslib": "^2.6.2"
},
"devDependencies": {
"@types/node": "^18.11.9",
"concurrently": "7.0.0",
"downlevel-dts": "0.10.1",
"premove": "4.0.0",
"typedoc": "0.23.23"
},
"types": "./dist-types/index.d.ts",

@@ -48,9 +31,2 @@ "engines": {

},
"typesVersions": {
"<4.5": {
"types/*": [
"types/ts3.4/*"
]
}
},
"files": [

@@ -57,0 +33,0 @@ "dist-*/**"

export 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);
}
}
export 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;
}
}
export const debugId = "endpoints";
export * from "./debugId";
export * from "./toDebugString";
export 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);
}
import { EndpointError } from "./types";
import { evaluateCondition } from "./utils/evaluateCondition";
import { evaluateExpression } from "./utils/evaluateExpression";
import { getEndpointHeaders } from "./utils/getEndpointHeaders";
import { getEndpointProperties } from "./utils/getEndpointProperties";
import { getEndpointUrl } from "./utils/getEndpointUrl";
const RESULT = 100_000_000;
export 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 ENV_ENDPOINT_URL = "AWS_ENDPOINT_URL";
const CONFIG_ENDPOINT_URL = "endpoint_url";
export const getEndpointUrlConfig = (serviceId) => ({
environmentVariableSelector: (env) => {
const serviceEndpointUrlSections = [ENV_ENDPOINT_URL, ...serviceId.split(" ").map((w) => w.toUpperCase())];
const serviceEndpointUrl = env[serviceEndpointUrlSections.join("_")];
if (serviceEndpointUrl)
return serviceEndpointUrl;
const endpointUrl = env[ENV_ENDPOINT_URL];
if (endpointUrl)
return endpointUrl;
return undefined;
},
configFileSelector: (profile) => {
const endpointUrl = profile[CONFIG_ENDPOINT_URL];
if (endpointUrl)
return endpointUrl;
return undefined;
},
default: undefined,
});
export const booleanEquals = (value1, value2) => value1 === value2;
export function coalesce(...args) {
for (const arg of args) {
if (arg != null) {
return arg;
}
}
return undefined;
}
import { EndpointError } from "../types";
import { getAttrPathList } from "./getAttrPathList";
export 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);
import { EndpointError } from "../types";
export 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;
};
export * from "./booleanEquals";
export * from "./coalesce";
export * from "./getAttr";
export * from "./isSet";
export * from "./isValidHostLabel";
export * from "./ite";
export * from "./not";
export * from "./parseURL";
export * from "./split";
export * from "./stringEquals";
export * from "./substring";
export * from "./uriEncode";
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}$`);
export const isIpAddress = (value) => IP_V4_REGEX.test(value) || (value.startsWith("[") && value.endsWith("]"));
export const isSet = (value) => value != null;
const VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`);
export 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;
};
export function ite(condition, trueValue, falseValue) {
return condition ? trueValue : falseValue;
}
export const not = (value) => !value;
import { EndpointURLScheme } from "@smithy/types";
import { isIpAddress } from "./isIpAddress";
const DEFAULT_PORTS = {
[EndpointURLScheme.HTTP]: 80,
[EndpointURLScheme.HTTPS]: 443,
};
export 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(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,
};
};
export 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));
}
export const stringEquals = (value1, value2) => value1 === value2;
export 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);
};
export const uriEncode = (value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
import { debugId, toDebugString } from "./debug";
import { EndpointError } from "./types";
import { evaluateRules } from "./utils";
export 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;
};
export class EndpointError extends Error {
constructor(message) {
super(message);
this.name = "EndpointError";
}
}
export * from "./EndpointError";
export * from "./EndpointFunctions";
export * from "./EndpointRuleObject";
export * from "./ErrorRuleObject";
export * from "./RuleSetObject";
export * from "./TreeRuleObject";
export * from "./shared";
export { callFunction } from "./evaluateExpression";
export const customEndpointFunctions = {};
import { booleanEquals, coalesce, getAttr, isSet, isValidHostLabel, ite, not, parseURL, split, stringEquals, substring, uriEncode, } from "../lib";
export const endpointFunctions = {
booleanEquals,
coalesce,
getAttr,
isSet,
isValidHostLabel,
ite,
not,
parseURL,
split,
stringEquals,
substring,
uriEncode,
};
import { debugId, toDebugString } from "../debug";
import { EndpointError } from "../types";
import { callFunction } from "./callFunction";
export 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 };
};
import { debugId, toDebugString } from "../debug";
import { evaluateCondition } from "./evaluateCondition";
export 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 };
};
import { debugId, toDebugString } from "../debug";
import { evaluateConditions } from "./evaluateConditions";
import { getEndpointHeaders } from "./getEndpointHeaders";
import { getEndpointProperties } from "./getEndpointProperties";
import { getEndpointUrl } from "./getEndpointUrl";
export 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;
};
import { EndpointError } from "../types";
import { evaluateConditions } from "./evaluateConditions";
import { evaluateExpression } from "./evaluateExpression";
export 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));
};
import { EndpointError } from "../types";
import { customEndpointFunctions } from "./customEndpointFunctions";
import { endpointFunctions } from "./endpointFunctions";
import { evaluateTemplate } from "./evaluateTemplate";
import { getReferenceValue } from "./getReferenceValue";
export const evaluateExpression = (obj, keyName, options) => {
if (typeof obj === "string") {
return evaluateTemplate(obj, options);
}
else if (obj["fn"]) {
return group.callFunction(obj, options);
}
else if (obj["ref"]) {
return getReferenceValue(obj, options);
}
throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`);
};
export 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.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.`);
};
export const group = {
evaluateExpression,
callFunction,
};
import { EndpointError } from "../types";
import { evaluateConditions } from "./evaluateConditions";
import { evaluateEndpointRule } from "./evaluateEndpointRule";
import { evaluateErrorRule } from "./evaluateErrorRule";
export 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`);
};
export 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);
};
export const group = {
evaluateRules,
evaluateTreeRule,
};
import { getAttr } from "../lib";
export 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("");
};
export { evaluateTreeRule } from "./evaluateRules";
import { EndpointError } from "../types";
import { evaluateExpression } from "./evaluateExpression";
export 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;
}, {});
import { EndpointError } from "../types";
import { evaluateTemplate } from "./evaluateTemplate";
export const getEndpointProperties = (properties, options) => Object.entries(properties).reduce((acc, [propertyKey, propertyVal]) => {
acc[propertyKey] = group.getEndpointProperty(propertyVal, options);
return acc;
}, {});
export 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.getEndpointProperties(property, options);
case "boolean":
return property;
default:
throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`);
}
};
export const group = {
getEndpointProperty,
getEndpointProperties,
};
export { getEndpointProperty } from "./getEndpointProperties";
import { EndpointError } from "../types";
import { evaluateExpression } from "./evaluateExpression";
export 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}`);
};
export const getReferenceValue = ({ ref }, options) => {
return options.referenceRecord[ref] ?? options.endpointParams[ref];
};
export * from "./customEndpointFunctions";
export * from "./evaluateRules";
import type { EndpointObjectHeaders, ParameterObject } from "@smithy/types";
import type { Expression, FunctionArgv } from "../types/shared";
/**
* @internal
*/
type BddCondition = [string, FunctionArgv] | [string, FunctionArgv, string];
/**
* @internal
*/
type BddResult = [-1] | [-1, Expression] | [string, Record<string, ParameterObject>, EndpointObjectHeaders] | [string, Record<string, ParameterObject>];
/**
* @internal
*/
export declare class BinaryDecisionDiagram {
nodes: Int32Array;
root: number;
conditions: BddCondition[];
results: BddResult[];
private constructor();
static from(bdd: Int32Array, root: number, conditions: BddCondition[] | any[], results: BddResult[] | any[]): BinaryDecisionDiagram;
}
export {};
import type { EndpointParams, EndpointV2 } from "@smithy/types";
/**
* @internal
*
* Cache for endpoint ruleSet resolution.
*/
export declare class EndpointCache {
private capacity;
private data;
private parameters;
/**
* @param [size] - desired average maximum capacity. A buffer of 10 additional keys will be allowed
* before keys are dropped.
* @param [params] - list of params to consider as part of the cache key.
*
* If the params list is not populated, no caching will happen.
* This may be out of order depending on how the object is created and arrives to this class.
*/
constructor({ size, params }: {
size?: number;
params?: string[];
});
/**
* @param endpointParams - query for endpoint.
* @param resolver - provider of the value if not present.
* @returns endpoint corresponding to the query.
*/
get(endpointParams: EndpointParams, resolver: () => EndpointV2): EndpointV2;
size(): number;
/**
* @returns cache key or false if not cachable.
*/
private hash;
}
export declare const debugId = "endpoints";
export * from "./debugId";
export * from "./toDebugString";
import type { EndpointParameters, EndpointV2 } from "@smithy/types";
import type { GetAttrValue } from "../lib";
import type { EndpointObject, FunctionObject, FunctionReturn } from "../types";
export declare function toDebugString(input: EndpointParameters): string;
export declare function toDebugString(input: EndpointV2): string;
export declare function toDebugString(input: GetAttrValue): string;
export declare function toDebugString(input: FunctionObject): string;
export declare function toDebugString(input: FunctionReturn): string;
export declare function toDebugString(input: EndpointObject): string;
import type { EndpointV2 } from "@smithy/types";
import type { BinaryDecisionDiagram } from "./bdd/BinaryDecisionDiagram";
import type { EndpointResolverOptions } from "./types";
/**
* Resolves an endpoint URL by processing the endpoints bdd and options.
*/
export declare const decideEndpoint: (bdd: BinaryDecisionDiagram, options: EndpointResolverOptions) => EndpointV2;
import type { LoadedConfigSelectors } from "@smithy/node-config-provider";
export declare const getEndpointUrlConfig: (serviceId: string) => LoadedConfigSelectors<string | undefined>;
/**
* Evaluates two boolean values value1 and value2 for equality and returns
* true if both values match.
*/
export declare const booleanEquals: (value1: boolean, value2: boolean) => boolean;
/**
* Evaluates arguments in order and returns the first non-empty result,
* otherwise returns the result of the last argument.
*
* @internal
*/
export declare function coalesce<T>(...args: (T | undefined)[]): T | undefined;
export type GetAttrValue = string | boolean | {
[key: string]: GetAttrValue;
} | Array<GetAttrValue>;
/**
* Returns value corresponding to pathing string for an array or object.
*/
export declare const getAttr: (value: GetAttrValue, path: string) => GetAttrValue;
/**
* Parses path as a getAttr expression, returning a list of strings.
*/
export declare const getAttrPathList: (path: string) => Array<string>;
export * from "./booleanEquals";
export * from "./coalesce";
export * from "./getAttr";
export * from "./isSet";
export * from "./isValidHostLabel";
export * from "./ite";
export * from "./not";
export * from "./parseURL";
export * from "./split";
export * from "./stringEquals";
export * from "./substring";
export * from "./uriEncode";
/**
* Validates if the provided value is an IP address.
*/
export declare const isIpAddress: (value: string) => boolean;
/**
* Evaluates whether a value is set (aka not null or undefined).
* Returns true if the value is set, otherwise returns false.
*/
export declare const isSet: (value: unknown) => value is {};
/**
* Evaluates whether one or more string values are valid host labels per RFC 1123.
*
* If allowSubDomains is true, then the provided value may be zero or more dotted
* subdomains which are each validated per RFC 1123.
*/
export declare const isValidHostLabel: (value: string, allowSubDomains?: boolean) => boolean;
/**
* An if-then-else function that returns one of two values based on a boolean condition.
*
* @internal
*/
export declare function ite<T>(condition: boolean, trueValue: T | undefined, falseValue: T | undefined): T | undefined;
/**
* Performs logical negation on the provided boolean value,
* returning the negated value.
*/
export declare const not: (value: boolean) => boolean;
import type { Endpoint, EndpointURL } from "@smithy/types";
/**
* Parses a string, URL, or Endpoint into it’s Endpoint URL components.
*/
export declare const parseURL: (value: string | URL | Endpoint) => EndpointURL | null;
/**
* The split function divides a string into an array of substrings based on a non-empty delimiter.
* The behavior is controlled by the limit parameter:
*
* limit = 0: Split all occurrences (unlimited).
* limit = 1: No split performed (returns original string as single element array).
* limit > 1: Split into at most 'limit' parts (performs limit-1 splits).
*
* @internal
*/
export declare function split(value: string, delimiter: string, limit: number): string[];
/**
* Evaluates two string values value1 and value2 for equality and returns
* true if both values match.
*/
export declare const stringEquals: (value1: string, value2: string) => boolean;
/**
* Computes the substring of a given string, conditionally indexing from the end of the string.
* When the string is long enough to fully include the substring, return the substring.
* Otherwise, return None. The start index is inclusive and the stop index is exclusive.
* The length of the returned string will always be stop-start.
*/
export declare const substring: (input: string, start: number, stop: number, reverse: boolean) => string | null;
/**
* Performs percent-encoding per RFC3986 section 2.1
*/
export declare const uriEncode: (value: string) => string;
import type { EndpointV2 } from "@smithy/types";
import type { EndpointResolverOptions, RuleSetObject } from "./types";
/**
* Resolves an endpoint URL by processing the endpoints ruleset and options.
*/
export declare const resolveEndpoint: (ruleSetObject: RuleSetObject, options: EndpointResolverOptions) => EndpointV2;
export declare class EndpointError extends Error {
constructor(message: string);
}
import type { FunctionReturn } from "./shared";
export type EndpointFunctions = Record<string, (...args: any[]) => FunctionReturn>;
import type { EndpointObject as __EndpointObject, EndpointObjectHeaders as __EndpointObjectHeaders, EndpointObjectProperties as __EndpointObjectProperties, EndpointRuleObject as __EndpointRuleObject } from "@smithy/types";
export type EndpointObjectProperties = __EndpointObjectProperties;
export type EndpointObjectHeaders = __EndpointObjectHeaders;
export type EndpointObject = __EndpointObject;
export type EndpointRuleObject = __EndpointRuleObject;
import type { ErrorRuleObject as __ErrorRuleObject } from "@smithy/types";
export type ErrorRuleObject = __ErrorRuleObject;
export * from "./EndpointError";
export * from "./EndpointFunctions";
export * from "./EndpointRuleObject";
export * from "./ErrorRuleObject";
export * from "./RuleSetObject";
export * from "./TreeRuleObject";
export * from "./shared";
import type { DeprecatedObject as __DeprecatedObject, ParameterObject as __ParameterObject, RuleSetObject as __RuleSetObject } from "@smithy/types";
export type DeprecatedObject = __DeprecatedObject;
export type ParameterObject = __ParameterObject;
export type RuleSetObject = __RuleSetObject;
import type { EndpointARN, EndpointPartition, EndpointURL, Logger } from "@smithy/types";
export type ReferenceObject = {
ref: string;
};
export type FunctionObject = {
fn: string;
argv: FunctionArgv;
};
export type FunctionArgv = Array<Expression | boolean | number>;
export type FunctionReturn = string | boolean | number | EndpointARN | EndpointPartition | EndpointURL | {
[key: string]: FunctionReturn;
} | Array<FunctionReturn> | null;
export type ConditionObject = FunctionObject & {
assign?: string;
};
export type Expression = string | ReferenceObject | FunctionObject;
export type EndpointParams = Record<string, string | boolean>;
export type EndpointResolverOptions = {
endpointParams: EndpointParams;
logger?: Logger;
};
export type ReferenceRecord = Record<string, FunctionReturn>;
export type EvaluateOptions = EndpointResolverOptions & {
referenceRecord: ReferenceRecord;
};
import type { RuleSetRules as __RuleSetRules, TreeRuleObject as __TreeRuleObject } from "@smithy/types";
export type RuleSetRules = __RuleSetRules;
export type TreeRuleObject = __TreeRuleObject;
export { callFunction } from "./evaluateExpression";
import type { EndpointFunctions } from "../types/EndpointFunctions";
export declare const customEndpointFunctions: {
[key: string]: EndpointFunctions;
};
import type { EndpointFunctions } from "../types";
export declare const endpointFunctions: EndpointFunctions;
import type { ConditionObject, EvaluateOptions } from "../types";
export declare const evaluateCondition: (condition: ConditionObject, options: EvaluateOptions) => {
result: boolean;
toAssign: {
name: string;
value: import("../types").FunctionReturn;
};
} | {
result: boolean;
toAssign?: undefined;
};
import type { ConditionObject, EvaluateOptions, FunctionReturn } from "../types";
export declare const evaluateConditions: (conditions: ConditionObject[] | undefined, options: EvaluateOptions) => {
result: boolean;
referenceRecord: Record<string, FunctionReturn>;
} | {
result: boolean;
referenceRecord?: undefined;
};
import type { EndpointV2 } from "@smithy/types";
import type { EndpointRuleObject, EvaluateOptions } from "../types";
export declare const evaluateEndpointRule: (endpointRule: EndpointRuleObject, options: EvaluateOptions) => EndpointV2 | undefined;
import type { ErrorRuleObject, EvaluateOptions } from "../types";
export declare const evaluateErrorRule: (errorRule: ErrorRuleObject, options: EvaluateOptions) => void;
import type { EvaluateOptions, Expression, FunctionObject, FunctionReturn } from "../types";
export declare const evaluateExpression: (obj: Expression, keyName: string, options: EvaluateOptions) => FunctionReturn;
export declare const callFunction: ({ fn, argv }: FunctionObject, options: EvaluateOptions) => FunctionReturn;
export declare const group: {
evaluateExpression: (obj: Expression, keyName: string, options: EvaluateOptions) => FunctionReturn;
callFunction: ({ fn, argv }: FunctionObject, options: EvaluateOptions) => FunctionReturn;
};
import type { EndpointV2 } from "@smithy/types";
import type { EvaluateOptions, RuleSetRules, TreeRuleObject } from "../types";
export declare const evaluateRules: (rules: RuleSetRules, options: EvaluateOptions) => EndpointV2;
export declare const evaluateTreeRule: (treeRule: TreeRuleObject, options: EvaluateOptions) => EndpointV2 | undefined;
export declare const group: {
evaluateRules: (rules: RuleSetRules, options: EvaluateOptions) => EndpointV2;
evaluateTreeRule: (treeRule: TreeRuleObject, options: EvaluateOptions) => EndpointV2 | undefined;
};
import type { EvaluateOptions } from "../types";
export declare const evaluateTemplate: (template: string, options: EvaluateOptions) => string;
export { evaluateTreeRule } from "./evaluateRules";
import type { EndpointObjectHeaders, EvaluateOptions } from "../types";
export declare const getEndpointHeaders: (headers: EndpointObjectHeaders, options: EvaluateOptions) => Record<string, string[]>;
import type { EndpointObjectProperty } from "@smithy/types";
import type { EndpointObjectProperties, EvaluateOptions } from "../types";
export declare const getEndpointProperties: (properties: EndpointObjectProperties, options: EvaluateOptions) => Record<string, EndpointObjectProperty>;
export declare const getEndpointProperty: (property: EndpointObjectProperty, options: EvaluateOptions) => EndpointObjectProperty;
export declare const group: {
getEndpointProperty: (property: EndpointObjectProperty, options: EvaluateOptions) => EndpointObjectProperty;
getEndpointProperties: (properties: EndpointObjectProperties, options: EvaluateOptions) => Record<string, EndpointObjectProperty>;
};
export { getEndpointProperty } from "./getEndpointProperties";
import type { EvaluateOptions, Expression } from "../types";
export declare const getEndpointUrl: (endpointUrl: Expression, options: EvaluateOptions) => URL;
import type { EvaluateOptions, ReferenceObject } from "../types";
export declare const getReferenceValue: ({ ref }: ReferenceObject, options: EvaluateOptions) => string | number | boolean | import("@smithy/types").EndpointPartition | import("@smithy/types").EndpointARN | import("@smithy/types").EndpointURL | {
[key: string]: import("../types").FunctionReturn;
} | import("../types").FunctionReturn[];
export * from "./customEndpointFunctions";
export * from "./evaluateRules";
# @smithy/util-endpoints
[![NPM version](https://img.shields.io/npm/v/@smithy/util-endpoints/latest.svg)](https://www.npmjs.com/package/@smithy/util-endpoints)
[![NPM downloads](https://img.shields.io/npm/dm/@smithy/util-endpoints.svg)](https://www.npmjs.com/package/@smithy/util-endpoints)
### :warning: Internal API :warning:
> This is an internal package.
> That means this is used as a dependency for other, public packages, but
> should not be taken directly as a dependency in your application's `package.json`.
> If you are updating the version of this package, for example to bring in a
> bug-fix, you should do so by updating your application lockfile with
> e.g. `npm up @scope/package` or equivalent command in another
> package manager, rather than taking a direct dependency.
---