var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { EndpointError: () => EndpointError, customEndpointFunctions: () => customEndpointFunctions, isIpAddress: () => isIpAddress, isValidHostLabel: () => isValidHostLabel, resolveEndpoint: () => resolveEndpoint }); module.exports = __toCommonJS(src_exports); // src/lib/isIpAddress.ts var 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}$` ); var isIpAddress = /* @__PURE__ */ __name((value) => IP_V4_REGEX.test(value) || value.startsWith("[") && value.endsWith("]"), "isIpAddress"); // src/lib/isValidHostLabel.ts var VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`); var isValidHostLabel = /* @__PURE__ */ __name((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; }, "isValidHostLabel"); // src/utils/customEndpointFunctions.ts var customEndpointFunctions = {}; // src/debug/debugId.ts var debugId = "endpoints"; // src/debug/toDebugString.ts 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); } __name(toDebugString, "toDebugString"); // src/types/EndpointError.ts var _EndpointError = class _EndpointError extends Error { constructor(message) { super(message); this.name = "EndpointError"; } }; __name(_EndpointError, "EndpointError"); var EndpointError = _EndpointError; // src/lib/booleanEquals.ts var booleanEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "booleanEquals"); // src/lib/getAttrPathList.ts var getAttrPathList = /* @__PURE__ */ __name((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; }, "getAttrPathList"); // src/lib/getAttr.ts var getAttr = /* @__PURE__ */ __name((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)) { return acc[parseInt(index)]; } return acc[index]; }, value), "getAttr"); // src/lib/isSet.ts var isSet = /* @__PURE__ */ __name((value) => value != null, "isSet"); // src/lib/not.ts var not = /* @__PURE__ */ __name((value) => !value, "not"); // src/lib/parseURL.ts var import_types3 = require("@smithy/types"); var DEFAULT_PORTS = { [import_types3.EndpointURLScheme.HTTP]: 80, [import_types3.EndpointURLScheme.HTTPS]: 443 }; var parseURL = /* @__PURE__ */ __name((value) => { const whatwgURL = (() => { try { if (value instanceof URL) { return value; } if (typeof value === "object" && "hostname" in value) { const { hostname: hostname2, port, protocol: protocol2 = "", path = "", query = {} } = value; const url = new URL(`${protocol2}//${hostname2}${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(import_types3.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 }; }, "parseURL"); // src/lib/stringEquals.ts var stringEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "stringEquals"); // src/lib/substring.ts var substring = /* @__PURE__ */ __name((input, start, stop, reverse) => { if (start >= stop || input.length < stop) { return null; } if (!reverse) { return input.substring(start, stop); } return input.substring(input.length - stop, input.length - start); }, "substring"); // src/lib/uriEncode.ts var uriEncode = /* @__PURE__ */ __name((value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`), "uriEncode"); // src/utils/endpointFunctions.ts var endpointFunctions = { booleanEquals, getAttr, isSet, isValidHostLabel, not, parseURL, stringEquals, substring, uriEncode }; // src/utils/evaluateTemplate.ts var evaluateTemplate = /* @__PURE__ */ __name((template, options) => { const evaluatedTemplateArr = []; const templateContext = { ...options.endpointParams, ...options.referenceRecord }; 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(templateContext[refName], attrName)); } else { evaluatedTemplateArr.push(templateContext[parameterName]); } currentIndex = closingBraceIndex + 1; } return evaluatedTemplateArr.join(""); }, "evaluateTemplate"); // src/utils/getReferenceValue.ts var getReferenceValue = /* @__PURE__ */ __name(({ ref }, options) => { const referenceRecord = { ...options.endpointParams, ...options.referenceRecord }; return referenceRecord[ref]; }, "getReferenceValue"); // src/utils/evaluateExpression.ts var evaluateExpression = /* @__PURE__ */ __name((obj, keyName, options) => { if (typeof obj === "string") { return evaluateTemplate(obj, options); } else if (obj["fn"]) { return callFunction(obj, options); } else if (obj["ref"]) { return getReferenceValue(obj, options); } throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`); }, "evaluateExpression"); // src/utils/callFunction.ts var callFunction = /* @__PURE__ */ __name(({ fn, argv }, options) => { const evaluatedArgs = argv.map( (arg) => ["boolean", "number"].includes(typeof arg) ? arg : evaluateExpression(arg, "arg", options) ); const fnSegments = fn.split("."); if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) { return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs); } return endpointFunctions[fn](...evaluatedArgs); }, "callFunction"); // src/utils/evaluateCondition.ts var evaluateCondition = /* @__PURE__ */ __name(({ assign, ...fnArgs }, options) => { var _a, _b; if (assign && assign in options.referenceRecord) { throw new EndpointError(`'${assign}' is already defined in Reference Record.`); } const value = callFunction(fnArgs, options); (_b = (_a = options.logger) == null ? void 0 : _a.debug) == null ? void 0 : _b.call(_a, `${debugId} evaluateCondition: ${toDebugString(fnArgs)} = ${toDebugString(value)}`); return { result: value === "" ? true : !!value, ...assign != null && { toAssign: { name: assign, value } } }; }, "evaluateCondition"); // src/utils/evaluateConditions.ts var evaluateConditions = /* @__PURE__ */ __name((conditions = [], options) => { var _a, _b; const conditionsReferenceRecord = {}; for (const condition of conditions) { const { result, toAssign } = evaluateCondition(condition, { ...options, referenceRecord: { ...options.referenceRecord, ...conditionsReferenceRecord } }); if (!result) { return { result }; } if (toAssign) { conditionsReferenceRecord[toAssign.name] = toAssign.value; (_b = (_a = options.logger) == null ? void 0 : _a.debug) == null ? void 0 : _b.call(_a, `${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`); } } return { result: true, referenceRecord: conditionsReferenceRecord }; }, "evaluateConditions"); // src/utils/getEndpointHeaders.ts var getEndpointHeaders = /* @__PURE__ */ __name((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; }) }), {} ), "getEndpointHeaders"); // src/utils/getEndpointProperty.ts var getEndpointProperty = /* @__PURE__ */ __name((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 getEndpointProperties(property, options); case "boolean": return property; default: throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`); } }, "getEndpointProperty"); // src/utils/getEndpointProperties.ts var getEndpointProperties = /* @__PURE__ */ __name((properties, options) => Object.entries(properties).reduce( (acc, [propertyKey, propertyVal]) => ({ ...acc, [propertyKey]: getEndpointProperty(propertyVal, options) }), {} ), "getEndpointProperties"); // src/utils/getEndpointUrl.ts var getEndpointUrl = /* @__PURE__ */ __name((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}`); }, "getEndpointUrl"); // src/utils/evaluateEndpointRule.ts var evaluateEndpointRule = /* @__PURE__ */ __name((endpointRule, options) => { var _a, _b; const { conditions, endpoint } = endpointRule; const { result, referenceRecord } = evaluateConditions(conditions, options); if (!result) { return; } const endpointRuleOptions = { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }; const { url, properties, headers } = endpoint; (_b = (_a = options.logger) == null ? void 0 : _a.debug) == null ? void 0 : _b.call(_a, `${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`); return { ...headers != void 0 && { headers: getEndpointHeaders(headers, endpointRuleOptions) }, ...properties != void 0 && { properties: getEndpointProperties(properties, endpointRuleOptions) }, url: getEndpointUrl(url, endpointRuleOptions) }; }, "evaluateEndpointRule"); // src/utils/evaluateErrorRule.ts var evaluateErrorRule = /* @__PURE__ */ __name((errorRule, options) => { const { conditions, error } = errorRule; const { result, referenceRecord } = evaluateConditions(conditions, options); if (!result) { return; } throw new EndpointError( evaluateExpression(error, "Error", { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }) ); }, "evaluateErrorRule"); // src/utils/evaluateTreeRule.ts var evaluateTreeRule = /* @__PURE__ */ __name((treeRule, options) => { const { conditions, rules } = treeRule; const { result, referenceRecord } = evaluateConditions(conditions, options); if (!result) { return; } return evaluateRules(rules, { ...options, referenceRecord: { ...options.referenceRecord, ...referenceRecord } }); }, "evaluateTreeRule"); // src/utils/evaluateRules.ts var evaluateRules = /* @__PURE__ */ __name((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 = evaluateTreeRule(rule, options); if (endpointOrUndefined) { return endpointOrUndefined; } } else { throw new EndpointError(`Unknown endpoint rule: ${rule}`); } } throw new EndpointError(`Rules evaluation failed`); }, "evaluateRules"); // src/resolveEndpoint.ts var resolveEndpoint = /* @__PURE__ */ __name((ruleSetObject, options) => { var _a, _b, _c, _d, _e; const { endpointParams, logger } = options; const { parameters, rules } = ruleSetObject; (_b = (_a = options.logger) == null ? void 0 : _a.debug) == null ? void 0 : _b.call(_a, `${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`); const paramsWithDefault = Object.entries(parameters).filter(([, v]) => v.default != null).map(([k, v]) => [k, v.default]); if (paramsWithDefault.length > 0) { for (const [paramKey, paramDefaultValue] of paramsWithDefault) { endpointParams[paramKey] = endpointParams[paramKey] ?? paramDefaultValue; } } const requiredParams = Object.entries(parameters).filter(([, v]) => v.required).map(([k]) => k); for (const requiredParam of requiredParams) { if (endpointParams[requiredParam] == null) { throw new EndpointError(`Missing required parameter: '${requiredParam}'`); } } const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} }); if ((_c = options.endpointParams) == null ? void 0 : _c.Endpoint) { try { const givenEndpoint = new URL(options.endpointParams.Endpoint); const { protocol, port } = givenEndpoint; endpoint.url.protocol = protocol; endpoint.url.port = port; } catch (e) { } } (_e = (_d = options.logger) == null ? void 0 : _d.debug) == null ? void 0 : _e.call(_d, `${debugId} Resolved endpoint: ${toDebugString(endpoint)}`); return endpoint; }, "resolveEndpoint"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { isIpAddress, isValidHostLabel, customEndpointFunctions, resolveEndpoint, EndpointError });