UNPKG

pricing4ts

Version:

![NPM Version](https://img.shields.io/npm/v/pricing4ts) Pricing4TS is a TypeScript-based toolkit designed to enhance the server-side functionality of a pricing-driven SaaS by enabling the seamless integration of pricing plans into the application logic. T

764 lines (763 loc) 39 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.validateName = validateName; exports.validateSyntaxVersion = validateSyntaxVersion; exports.validateVersion = validateVersion; exports.validateCreatedAt = validateCreatedAt; exports.validateCurrency = validateCurrency; exports.validateDescription = validateDescription; exports.validateValueType = validateValueType; exports.validateDefaultValue = validateDefaultValue; exports.validateExpression = validateExpression; exports.validateValue = validateValue; exports.validateFeatureType = validateFeatureType; exports.validateFeatureIntegrationType = validateFeatureIntegrationType; exports.validateFeatureAutomationType = validateFeatureAutomationType; exports.validateUnit = validateUnit; exports.validateUsageLimitType = validateUsageLimitType; exports.validateLinkedFeatures = validateLinkedFeatures; exports.validateRenderMode = validateRenderMode; exports.validatePlanFeatures = validatePlanFeatures; exports.validatePlanUsageLimits = validatePlanUsageLimits; exports.validatePrice = validatePrice; exports.validateAddonFeatures = validateAddonFeatures; exports.validateAddonUsageLimits = validateAddonUsageLimits; exports.validateAddonUsageLimitsExtensions = validateAddonUsageLimitsExtensions; exports.validateAvailableFor = validateAvailableFor; exports.validateDependsOnOrExcludes = validateDependsOnOrExcludes; exports.postValidateDependsOnOrExclude = postValidateDependsOnOrExclude; exports.validateTags = validateTags; exports.validatePlan = validatePlan; exports.validatePlans = validatePlans; exports.validateFeatures = validateFeatures; exports.validateFeature = validateFeature; exports.validateUsageLimits = validateUsageLimits; exports.validateUsageLimit = validateUsageLimit; exports.validateBilling = validateBilling; exports.validateVariables = validateVariables; exports.validateUrl = validateUrl; exports.validatePrivate = validatePrivate; exports.validatePricingUrls = validatePricingUrls; exports.validateDocUrl = validateDocUrl; exports.validatePeriodUnit = validatePeriodUnit; exports.validatePeriodValue = validatePeriodValue; exports.validateTrackable = validateTrackable; exports.validateSubscriptionConstraintMinQuantity = validateSubscriptionConstraintMinQuantity; exports.validateSubscriptionConstraintMaxQuantity = validateSubscriptionConstraintMaxQuantity; exports.validateSubscriptionConstraintQuantityStep = validateSubscriptionConstraintQuantityStep; exports.validateCustom = validateCustom; var cc = __importStar(require("currency-codes")); var feature_1 = require("../models/pricing2yaml/feature"); var VERSION_REGEXP = /^\d+\.\d+$/; var unlimitedValue = 100000000; function validateName(name, item) { if (name === null || name === undefined) { throw new Error("The ".concat(item, " must have a name")); } if (typeof name !== 'string') { throw new TypeError("The ".concat(item, " name must be a string")); } var trimmedName = name.trim(); if (trimmedName.length === 0) { throw new Error("The ".concat(item, " name must not be empty")); } if (trimmedName.length < 3) { throw new Error("The ".concat(item, " name must have at least 3 characters")); } if (trimmedName.length > 255) { throw new Error("The ".concat(item, " name must have at most 255 characters")); } return trimmedName; } function validateSyntaxVersion(version) { if (version === null || version === undefined) { throw new Error("The syntaxVersion field of the pricing must not be null or undefined. Please ensure that the syntaxVersion field is present and correctly formatted"); } if (typeof version !== 'string' || !VERSION_REGEXP.test(version)) { throw new TypeError("The syntaxVersion field of the pricing does not follow the required structure: X.Y (being X and Y numbers). Please ensure it is a string in the format X.Y"); } return version; } function validateVersion(version, createdAt) { version !== null && version !== void 0 ? version : (version = "".concat(createdAt.getFullYear(), "-").concat(createdAt.getMonth() + 1, "-").concat(createdAt.getDate())); if (typeof version !== 'string') { throw new TypeError("The version field of the pricing must be a string. Please ensure that the version field is present and correctly formatted"); } return version; } function validateCreatedAt(createdAt) { if (createdAt === null || createdAt === undefined) { throw new Error("The createdAt field must not be null or undefined. Please ensure that the createdAt field is present and correctly formatted (as Date or string)"); } if (typeof createdAt === 'string') { if (/^\d{4}-\d{2}-\d{2}$/.test(createdAt)) { createdAt = new Date(createdAt); } else { throw new TypeError("The createdAt field must be a string in the format yyyy-mm-dd or a valid Date object"); } } if (!(createdAt instanceof Date) || isNaN(createdAt.getTime())) { throw new TypeError("The createdAt field must be a valid Date object or a string in a recognized date format"); } var now = new Date(); if (createdAt > now) { throw new Error("The createdAt field must not be a future date"); } return createdAt; } function validateCurrency(currency) { if (currency === null || currency === undefined) { throw new Error("The currency field of the pricing must not be null or undefined. Please ensure that the currency field is present and correctly formatted"); } if (typeof currency !== 'string') { throw new TypeError("The currency field of the pricing must be a string"); } var trimmedCurrency = currency.trim(); if (trimmedCurrency.length === 0) { throw new Error("The currency field of the pricing must not be empty"); } var currencyCode = cc.code(trimmedCurrency); if (!currencyCode) { throw new Error("The currency code ".concat(trimmedCurrency, " is not a valid ISO 4217 currency code")); } return currency; } function validateDescription(description) { description !== null && description !== void 0 ? description : (description = undefined); return description; } function validateValueType(valueType) { if (valueType === null || valueType === undefined) { throw new Error("The valueType field of a feature must not be null or undefined. Please ensure that the valueType field is present and it's value correspond to either BOOLEAN, NUMERIC or TEXT"); } if (typeof valueType !== 'string') { throw new TypeError("The valueType field of a feature must be a string, and its value must be either BOOLEAN, NUMERIC or TEXT. Received: ".concat(valueType, " ")); } valueType = valueType.trim().toUpperCase(); if (!['NUMERIC', 'BOOLEAN', 'TEXT'].includes(valueType)) { throw new Error("The valueType field of a feature must be one of NUMERIC, BOOLEAN, or TEXT. Received: ".concat(valueType)); } return valueType; } function validateDefaultValue(elem, item) { if (elem.defaultValue === null || elem.defaultValue === undefined) { throw new Error("The defaultValue field of a ".concat(item, " must not be null or undefined. Please ensure that the defaultValue field is present and its defaultValue type correspond to the declared valueType")); } switch (elem.valueType) { case 'NUMERIC': if (typeof elem.defaultValue !== 'number') { throw new TypeError("The defaultValue field of a ".concat(item, " must be a number when its valueType is NUMERIC. Received: ").concat(elem.defaultValue)); } if (elem.defaultValue > unlimitedValue) { elem.defaultValue = unlimitedValue; } break; case 'BOOLEAN': if (typeof elem.defaultValue !== 'boolean') { throw new TypeError("The defaultValue field of a ".concat(item, " must be a boolean when its valueType is BOOLEAN. Received: ").concat(elem.defaultValue)); } break; case 'TEXT': if (elem.type === 'PAYMENT') { if (!(elem.defaultValue instanceof Array)) { throw new TypeError("Payment method value must be an array of payment methods"); } for (var _i = 0, _a = elem.defaultValue; _i < _a.length; _i++) { var paymentMethod = _a[_i]; if (!['CARD', 'GATEWAY', 'INVOICE', 'ACH', 'WIRE_TRANSFER', 'OTHER'].includes(paymentMethod)) { throw new Error("Invalid payment method: ".concat(paymentMethod, ". Please provide one of the following: CARD, GATEWAY, INVOICE, ACH, WIRE_TRANSFER, OTHER")); } } break; } if (typeof elem.defaultValue !== 'string') { throw new Error("The defaultValue field of a ".concat(item, " must be a string when its valueType is TEXT. Received: ").concat(elem.defaultValue)); } break; default: throw new Error("The valueType field of a ".concat(item, " must be either BOOLEAN, NUMERIC or TEXT. Received: ").concat(elem.valueType)); } return elem.defaultValue; } function validateExpression(expression, item) { expression !== null && expression !== void 0 ? expression : (expression = undefined); if (typeof expression === 'string') { if (expression.trim().length === 0) { throw new Error("The ".concat(item, " field of a feature must not be empty. If you don't want to declare an expression for this feature, either use null or undefined")); } } return expression; } function validateValue(elem, item, valueType) { var _a; if (valueType === void 0) { valueType = undefined; } (_a = elem.value) !== null && _a !== void 0 ? _a : (elem.value = undefined); var valueTypeToValidate = valueType || elem.valueType; switch (valueTypeToValidate) { case 'NUMERIC': if (typeof elem.value !== 'number' && elem.value !== undefined) { throw new TypeError("The value field of a ".concat(item, " must be a number when its valueType is NUMERIC. Received: ").concat(elem.value)); } if (elem.value > unlimitedValue) { elem.value = unlimitedValue; } break; case 'BOOLEAN': if (typeof elem.value !== 'boolean' && elem.value !== undefined) { throw new TypeError("The value field of a ".concat(item, " must be a boolean when its valueType is BOOLEAN. Received: ").concat(elem.value)); } break; case 'TEXT': if (elem.type === 'PAYMENT' && elem.value !== undefined) { if (!(elem.value instanceof Array)) { throw new TypeError("Payment method value must be an array of payment methods"); } for (var _i = 0, _b = elem.value; _i < _b.length; _i++) { var paymentMethod = _b[_i]; if (!['CARD', 'GATEWAY', 'INVOICE', 'ACH', 'WIRE_TRANSFER', 'OTHER'].includes(paymentMethod)) { throw new Error("Invalid payment method: ".concat(paymentMethod, ". Please provide one of the following: CARD, GATEWAY, INVOICE, ACH, WIRE_TRANSFER, OTHER")); } } break; } if (typeof elem.value !== 'string' && elem.value !== undefined) { throw new TypeError("The value field of a ".concat(item, " must be a string when its valueType is TEXT. Received: ").concat(elem.value)); } break; default: throw new TypeError("The valueType field of a ".concat(item, " must be either BOOLEAN, NUMERIC or TEXT. Received: ").concat(elem.valueType)); } return elem.value; } function validateFeatureType(type) { if (type === null || type === undefined) { throw new Error("The type field of a feature must not be null or undefined. Please ensure that the type field is present and it's value correspond to either INFORMATION, INTEGRATION, DOMAIN, AUTOMATION, MANAGEMENT, GUARANTEE, SUPPORT or PAYMENT"); } if (typeof type !== 'string') { throw new TypeError("The type field of a feature must be a string, and its value must be either INFORMATION, INTEGRATION, DOMAIN, AUTOMATION, MANAGEMENT, GUARANTEE, SUPPORT or PAYMENT. Received: ".concat(type, " ")); } type = type.trim().toUpperCase(); if (![ 'INFORMATION', 'INTEGRATION', 'DOMAIN', 'AUTOMATION', 'MANAGEMENT', 'GUARANTEE', 'SUPPORT', 'PAYMENT', ].includes(type)) { throw new Error("The type field of a feature must be one of INFORMATION, INTEGRATION, DOMAIN, AUTOMATION, MANAGEMENT, GUARANTEE, SUPPORT or PAYMENT. Received: ".concat(type)); } return type; } function validateFeatureIntegrationType(integrationType, featureType) { if (integrationType === null || integrationType === undefined) { integrationType = undefined; } if (integrationType && typeof integrationType !== 'string') { throw new TypeError("The integrationType field of a feature must be an IntegrationType ('API' | 'EXTENSION' | 'IDENTITY_PROVIDER' | 'WEB_SAAS' | 'MARKETPLACE' | 'EXTERNAL_DEVICE'). Received: ".concat(integrationType)); } else if (featureType === 'INTEGRATION' && !integrationType) { throw new Error("The integrationType field of a feature of type INTEGRATION must not be null or undefined. Please ensure that the integrationType field is present and it's value correspond to either API, EXTENSION, IDENTITY_PROVIDER, WEB_SAAS, MARKETPLACE or EXTERNAL_DEVICE"); } else if (integrationType && typeof integrationType === "string" && !(0, feature_1.isIntegrationType)(integrationType)) { throw new Error("The integrationType field of a feature must be one of API, EXTENSION, IDENTITY_PROVIDER, WEB_SAAS, MARKETPLACE or EXTERNAL_DEVICE. Received: ".concat(integrationType)); } return integrationType; } function validateFeatureAutomationType(automationType, featureType) { if (automationType === null || automationType === undefined) { automationType = undefined; } if (automationType && typeof automationType !== 'string') { throw new TypeError("The automationType field of a feature must be an AutomationType ('BOT' | 'FILTERING' | 'TRACKING' | 'TASK_AUTOMATION'). Received: ".concat(automationType)); } else if (featureType === 'AUTOMATION' && !automationType) { throw new Error("The automationType field of a feature of type AUTOMATION must not be null or undefined. Please ensure that the automationType field is present and its value corresponds to either BOT, FILTERING, TRACKING, or TASK_AUTOMATION"); } else if (automationType && typeof automationType === "string" && !(0, feature_1.isAutomationType)(automationType)) { throw new Error("The automationType field of a feature must be one of BOT, FILTERING, TRACKING, or TASK_AUTOMATION. Received: ".concat(automationType)); } return automationType; } function validateUnit(unit) { if (unit === null || unit === undefined) { unit = ''; } if (typeof unit !== 'string') { throw new TypeError("The unit field of a usage limit must be a string. Received: ".concat(unit, " ")); } return unit; } function validateUsageLimitType(type) { if (type === null || type === undefined) { throw new Error("The type field of a usage limit must not be null or undefined. Please ensure that the type field is present and it's value correspond to either RENEWABLE or NON_RENEWABLE"); } if (typeof type !== 'string') { throw new TypeError("The type field of a usage limit must be a string, and its value must be either RENEWABLE or NON_RENEWABLE. Received: ".concat(type, " ")); } type = type.trim().toUpperCase(); if (!['RENEWABLE', 'NON_RENEWABLE'].includes(type)) { throw new Error("The type field of a usage limit must be one of RENEWABLE or NON_RENEWABLE. Received: ".concat(type)); } return type; } function validateLinkedFeatures(linkedFeatures, pricing) { linkedFeatures !== null && linkedFeatures !== void 0 ? linkedFeatures : (linkedFeatures = undefined); // Check if linked features is an array if (Array.isArray(linkedFeatures)) { var pricingFeatures = Object.values(pricing.features).map(function (f) { return f.name; }); for (var _i = 0, linkedFeatures_1 = linkedFeatures; _i < linkedFeatures_1.length; _i++) { var featureName = linkedFeatures_1[_i]; if (!pricingFeatures.includes(featureName)) { throw new Error("The feature ".concat(featureName, ", declared as a linked feature for an usage limit, is not defined in the global features")); } } } return linkedFeatures; } function validateRenderMode(renderMode) { if (renderMode === null || renderMode === undefined) { renderMode !== null && renderMode !== void 0 ? renderMode : (renderMode = 'AUTO'); } renderMode = renderMode.toUpperCase(); if (!['AUTO', 'ENABLED', 'DISABLED'].includes(renderMode)) { throw new Error("The render field of a feature or usage limit must be one of AUTO, ENABLED or DISABLED. Received: ".concat(renderMode)); } return renderMode; } function validatePlanFeatures(plan, planFeatures) { var featuresModifiedByPlan = plan.features; plan.features = planFeatures; var _loop_1 = function (planFeature) { try { if (!Object.values(planFeatures).some(function (f) { return f.name === planFeature.name; })) { throw new Error("Feature ".concat(planFeature.name, " is not defined in the global features.")); } var featureWithDefaultValue = Object.values(plan.features).find(function (f) { return f.name === planFeature.name; }); featureWithDefaultValue.value = planFeature.value; featureWithDefaultValue.value = validateValue(featureWithDefaultValue, 'feature'); } catch (err) { throw new Error("Error while parsing the feature ".concat(planFeature.name, " of the plan ").concat(plan.name, ". Error: ").concat(err.message)); } }; for (var _i = 0, _a = Object.values(featuresModifiedByPlan); _i < _a.length; _i++) { var planFeature = _a[_i]; _loop_1(planFeature); } return plan.features; } function validatePlanUsageLimits(plan, planUsageLimits) { var usageLimitsModifiedByPlan = plan.usageLimits; plan.usageLimits = planUsageLimits; var _loop_2 = function (planUsageLimit) { try { if (!Object.values(planUsageLimits).some(function (l) { return l.name === planUsageLimit.name; })) { throw new Error("Usage limit ".concat(planUsageLimit.name, " is not defined in the global usage limits.")); } var globalUsageLimit = Object.values(planUsageLimits).find(function (l) { return l.name === planUsageLimit.name; }); globalUsageLimit.value = planUsageLimit.value; globalUsageLimit.value = validateValue(globalUsageLimit, 'usage limit'); } catch (err) { throw new Error("Error while parsing the usage limit ".concat(planUsageLimit.name, " of the plan ").concat(plan.name, ". Error: ").concat(err.message)); } }; for (var _i = 0, _a = Object.values(usageLimitsModifiedByPlan); _i < _a.length; _i++) { var planUsageLimit = _a[_i]; _loop_2(planUsageLimit); } return plan.usageLimits; } function validatePrice(price, variables) { if (variables === void 0) { variables = {}; } if (price === null || price === undefined) { throw new Error("The price field must not be null or undefined. Please ensure that the price field is present and it's a number"); } if (typeof price !== 'string' && typeof price !== 'number') { throw new TypeError("The price field must be a number or a string (which can contain a formula). Received: ".concat(price)); } if (typeof price === 'number' && price < 0) { throw new Error("The price field must be a positive number. Received: ".concat(price, " ")); } if (typeof price === 'string') { if (price.includes('#')) { for (var _i = 0, _a = Object.entries(variables); _i < _a.length; _i++) { var _b = _a[_i], variable = _b[0], value = _b[1]; var replacement = void 0; if (typeof value === 'string') { var escaped = value.replace(/'/g, "\\'"); replacement = "'".concat(escaped, "'"); } else if (value === null) { replacement = 'null'; } else if (typeof value === 'object') { // Use JSON.stringify and wrap in parentheses so object/array literals // evaluate correctly inside eval (e.g. ({"test":"a"}).test ) replacement = "(".concat(JSON.stringify(value), ")"); } else { replacement = String(value); } price = price.replace(new RegExp("#".concat(variable), 'g'), replacement); } try { // eslint-disable-next-line no-eval var evaluatedPrice = eval(price); if (typeof evaluatedPrice !== 'number' || isNaN(evaluatedPrice)) { throw new Error("The evaluated price must result in a valid number. Current result after evaluation: ".concat(evaluatedPrice)); } price = evaluatedPrice; } catch (err) { throw new Error("Error evaluating the price formula: ".concat(err.message)); } } else if (price.match(/^[0-9]+(\.[0-9]+)?$/)) { price = parseFloat(price); } } return price; } function validateAddonFeatures(addon, addOnFeatures) { var _loop_3 = function (addOnFeature) { try { if (!Object.values(addOnFeatures).some(function (f) { return f.name === addOnFeature.name; })) { throw new Error("Feature ".concat(addOnFeature.name, " is not defined in the global features.")); } addon.features[addOnFeature.name].value = addOnFeature.value; addon.features[addOnFeature.name].value = validateValue(addon.features[addOnFeature.name], 'feature', addOnFeatures[addOnFeature.name].valueType); } catch (err) { throw new Error("Error while parsing the feature ".concat(addOnFeature.name, " of the plan ").concat(addon.name, ". Error: ").concat(err.message)); } }; for (var _i = 0, _a = Object.values(addon.features); _i < _a.length; _i++) { var addOnFeature = _a[_i]; _loop_3(addOnFeature); } return addon.features; } function validateAddonUsageLimits(addon, addonUsageLimits) { var _loop_4 = function (addonUsageLimit) { try { if (!Object.values(addonUsageLimits).some(function (l) { return l.name === addonUsageLimit.name; })) { throw new Error("Usage limit ".concat(addonUsageLimit.name, " is not defined in the global usage limits.")); } if (!('value' in addonUsageLimit)) { throw new Error("When declaring a new value for an usage limit or a usage limit extension within an add-on, it must be provided through the 'value' field"); } addon.usageLimits[addonUsageLimit.name].value = addonUsageLimit.value; addon.usageLimits[addonUsageLimit.name].value = validateValue(addon.usageLimits[addonUsageLimit.name], 'usage limit', addonUsageLimits[addonUsageLimit.name].valueType); } catch (err) { throw new Error("Error while parsing the usage limit ".concat(addonUsageLimit.name, " of the add-on ").concat(addon.name, ". Error: ").concat(err.message)); } }; for (var _i = 0, _a = Object.values(addon.usageLimits); _i < _a.length; _i++) { var addonUsageLimit = _a[_i]; _loop_4(addonUsageLimit); } return addon.usageLimits; } function validateAddonUsageLimitsExtensions(addon, addonUsageLimits) { var _loop_5 = function (addonUsageLimitExtension) { try { if (!Object.values(addonUsageLimits).some(function (l) { return l.name === addonUsageLimitExtension.name; })) { throw new Error("Usage limit ".concat(addonUsageLimitExtension.name, " is not defined in the global usage limits.")); } if (!('value' in addonUsageLimitExtension)) { throw new Error("When declaring a new value for an usage limit or a usage limit extension within an add-on, it must be provided through the 'value' field"); } addon.usageLimitsExtensions[addonUsageLimitExtension.name].value = addonUsageLimitExtension.value; addon.usageLimitsExtensions[addonUsageLimitExtension.name].value = validateValue(addon.usageLimitsExtensions[addonUsageLimitExtension.name], 'usage limit', addonUsageLimits[addonUsageLimitExtension.name].valueType); } catch (err) { throw new Error("Error while parsing the usage limit ".concat(addonUsageLimitExtension.name, " of the add-on ").concat(addon.name, ". Error: ").concat(err.message)); } }; for (var _i = 0, _a = Object.values(addon.usageLimitsExtensions); _i < _a.length; _i++) { var addonUsageLimitExtension = _a[_i]; _loop_5(addonUsageLimitExtension); } return addon.usageLimitsExtensions; } function validateAvailableFor(availableFor, pricing) { var planNames = pricing.plans ? Object.values(pricing.plans).map(function (p) { return p.name; }) : []; availableFor !== null && availableFor !== void 0 ? availableFor : (availableFor = planNames); if (!Array.isArray(availableFor)) { throw new TypeError("The availableFor field must be an array of the plan names for which the addon can be contracted. Received: ".concat(availableFor)); } for (var _i = 0, availableFor_1 = availableFor; _i < availableFor_1.length; _i++) { var planName = availableFor_1[_i]; if (!planNames.includes(planName)) { throw new Error("The plan ".concat(planName, " is not defined in the pricing.")); } } return availableFor; } function validateDependsOnOrExcludes(fieldValue, pricing, fieldType) { var addonNames = pricing.addOns ? Object.values(pricing.addOns).map(function (a) { return a.name; }) : []; fieldValue !== null && fieldValue !== void 0 ? fieldValue : (fieldValue = []); if (!Array.isArray(fieldValue)) { throw new TypeError("The ".concat(fieldType, " field must be an array of the addons required to contract the addon. Received: ").concat(fieldValue)); } return fieldValue; } function postValidateDependsOnOrExclude(fieldValue, pricing) { var addonNames = pricing.addOns ? Object.values(pricing.addOns).map(function (a) { return a.name; }) : []; if (!fieldValue) return; for (var _i = 0, fieldValue_1 = fieldValue; _i < fieldValue_1.length; _i++) { var addonName = fieldValue_1[_i]; if (!addonNames.includes(addonName)) { throw new Error("The addon ".concat(addonName, " is not defined in the pricing.")); } } } function validateTags(tags) { tags !== null && tags !== void 0 ? tags : (tags = []); if (!Array.isArray(tags) || tags.some(function (tag) { return typeof tag !== 'string'; })) { throw new TypeError("The tags field must be an array of strings."); } return tags; } function validatePlan(plan) { if (typeof plan === 'object' && 'features' in plan) { return; } else { throw new TypeError("The plan must be an object of type Plan"); } } function validatePlans(plans) { if (!(typeof plans === 'object')) { throw new TypeError("The plans field must be a map of Plan objects"); } } function validateFeatures(features) { if (!(typeof features === 'object') || features === null || features === undefined) { throw new TypeError("The features field must be a map of Feature objects"); } } function validateFeature(feature) { if (typeof feature === 'object' && 'type' in feature && 'valueType' in feature && 'defaultValue' in feature) { return; } else { throw new TypeError("The feature must be an object of type Feature"); } } function validateUsageLimits(usageLimits) { if (!(typeof usageLimits === 'object')) { throw new TypeError("The usageLimits field must be a map of UsageLimit objects or undefined"); } } function validateUsageLimit(usageLimit) { if (typeof usageLimit === 'object' && 'type' in usageLimit && 'valueType' in usageLimit && 'defaultValue' in usageLimit) { return; } else { throw new TypeError("The usage limit must be an object of type UsageLimit"); } } function validateBilling(billing) { if (billing === undefined || billing === null) { billing !== null && billing !== void 0 ? billing : (billing = { monthly: 1, }); } if (!(typeof billing === 'object')) { throw new TypeError("The billing field must be an object of type {[key: string]: number}"); } for (var _i = 0, _a = Object.entries(billing); _i < _a.length; _i++) { var _b = _a[_i], key = _b[0], value = _b[1]; if (typeof value !== 'number') { throw new TypeError("The billing entry for ".concat(key, " must be a number. Received: ").concat(value)); } if (value <= 0 || value > 1) { throw new Error("The billing entry for ".concat(key, " must be a value in the range (0,1]. Received: ").concat(value)); } } return billing; } function validateVariables(variables) { variables !== null && variables !== void 0 ? variables : (variables = {}); if (typeof variables !== 'object') { throw new TypeError("The 'variables' field must be an object of type {[key: string]: any}"); } // Allow any value types for variables (object, array, string, number, boolean, etc.) return variables; } function validateUrl(url) { if (url === undefined || url === null) { url !== null && url !== void 0 ? url : (url = undefined); return; } if (typeof url !== 'string') { throw new TypeError("The url field must be a string. Received: ".concat(url)); } var urlPattern = /^(https?):\/\/[^\s\/$.?#].[^\s]*$/i; if (!urlPattern.test(url)) { throw new Error("The url field must be a valid URL with the http or https protocol. Received: ".concat(url)); } return url; } function validatePrivate(isPrivate) { if (isPrivate === undefined || isPrivate === null) { isPrivate !== null && isPrivate !== void 0 ? isPrivate : (isPrivate = false); } if (typeof isPrivate !== 'boolean') { throw new TypeError("The private field must be a boolean. Received: ".concat(isPrivate)); } return isPrivate; } function validatePricingUrls(featureType, featureIntegrationType, pricingUrls) { pricingUrls !== null && pricingUrls !== void 0 ? pricingUrls : (pricingUrls = undefined); if (pricingUrls !== undefined) { if (!Array.isArray(pricingUrls) || pricingUrls.some(function (url) { return typeof url !== 'string'; })) { throw new TypeError("The pricingUrls field must be an array of strings."); } for (var _i = 0, pricingUrls_1 = pricingUrls; _i < pricingUrls_1.length; _i++) { var url = pricingUrls_1[_i]; var urlPattern = /^(https?):\/\/[^^\s\/$.?#].[^\s]*$/i; if (!urlPattern.test(url)) { throw new Error("The pricingUrls field must contain only valid URLs. Invalid URL: ".concat(url)); } } if (featureType !== 'INTEGRATION' || featureIntegrationType !== 'WEB_SAAS') { console.log("[WARNING] The pricingUrls field is only valid for features of 'type' INTEGRATION and 'integrationType' WEB_SAAS. The field will be ignored."); pricingUrls = undefined; } } return pricingUrls; } function validateDocUrl(featureType, docUrl) { docUrl !== null && docUrl !== void 0 ? docUrl : (docUrl = undefined); if (docUrl !== undefined) { if (typeof docUrl !== 'string') { throw new TypeError("The docUrl field must be a string."); } var urlPattern = /^(https?):\/\/[^^\s\/$.?#].[^\s]*$/i; if (!urlPattern.test(docUrl)) { throw new Error("The docUrl field must be a valid URL with the http or https protocol. Received: ".concat(docUrl)); } if (featureType !== 'GUARANTEE') { console.log("[WARNING] The docUrl field is only valid for features of 'type' GUARANTEE. The field will be ignored."); docUrl = undefined; } } return docUrl; } function validatePeriodUnit(periodUnit) { periodUnit !== null && periodUnit !== void 0 ? periodUnit : (periodUnit = 'MONTH'); if (typeof periodUnit !== 'string') { throw new TypeError("The periodUnit field must be one of the following string values: \"SEC\" | \"MIN\" | \"HOUR\" | \"DAY\" | \"MONTH\" | \"YEAR\". Received: ".concat(periodUnit)); } periodUnit = periodUnit.toUpperCase(); if (!["SEC", "MIN", "HOUR", "DAY", "MONTH", "YEAR"].includes(periodUnit)) { throw new Error("The periodUnit field must be one of \"SEC\" | \"MIN\" | \"HOUR\" | \"DAY\" | \"MONTH\" | \"YEAR\". Received: ".concat(periodUnit)); } return periodUnit; } function validatePeriodValue(periodValue) { periodValue !== null && periodValue !== void 0 ? periodValue : (periodValue = 1); if (typeof periodValue !== 'number') { throw new TypeError("The periodValue field must be a number. Received: ".concat(periodValue)); } if (periodValue <= 0) { throw new Error("The periodValue field must be a positive number. Received: ".concat(periodValue)); } return periodValue; } function validateTrackable(trackable) { trackable !== null && trackable !== void 0 ? trackable : (trackable = false); if (typeof trackable === 'string') { trackable = trackable.toLowerCase() === 'true'; } if (typeof trackable !== 'boolean') { throw new TypeError("The trackable field must be a boolean. Received: ".concat(trackable)); } return trackable; } function validateSubscriptionConstraintMinQuantity(subscriptionConstraintMinQuantity) { subscriptionConstraintMinQuantity !== null && subscriptionConstraintMinQuantity !== void 0 ? subscriptionConstraintMinQuantity : (subscriptionConstraintMinQuantity = 1); if (typeof subscriptionConstraintMinQuantity !== 'number') { throw new TypeError("The subscriptionConstraintMinQuantity field must be a number. Received: ".concat(subscriptionConstraintMinQuantity)); } if (subscriptionConstraintMinQuantity < 0) { throw new Error("The subscriptionConstraintMinQuantity field must be a positive number. Received: ".concat(subscriptionConstraintMinQuantity)); } return subscriptionConstraintMinQuantity; } function validateSubscriptionConstraintMaxQuantity(subscriptionConstraintMaxQuantity, minQuantity) { subscriptionConstraintMaxQuantity !== null && subscriptionConstraintMaxQuantity !== void 0 ? subscriptionConstraintMaxQuantity : (subscriptionConstraintMaxQuantity = unlimitedValue); if (typeof subscriptionConstraintMaxQuantity !== 'number') { throw new TypeError("The subscriptionConstraintMaxQuantity field must be a number. Received: ".concat(subscriptionConstraintMaxQuantity)); } if (subscriptionConstraintMaxQuantity < minQuantity) { throw new Error("The subscriptionConstraintMaxQuantity field must be greater than or equal to the min quantity. Received: ".concat(subscriptionConstraintMaxQuantity)); } return subscriptionConstraintMaxQuantity; } function validateSubscriptionConstraintQuantityStep(subscriptionConstraintQuantityStep, minQuantity) { subscriptionConstraintQuantityStep !== null && subscriptionConstraintQuantityStep !== void 0 ? subscriptionConstraintQuantityStep : (subscriptionConstraintQuantityStep = 1); if (typeof subscriptionConstraintQuantityStep !== 'number') { throw new TypeError("The subscriptionConstraintQuantityStep field must be a number. Received: ".concat(subscriptionConstraintQuantityStep)); } if (!(minQuantity % subscriptionConstraintQuantityStep === 0)) { throw new Error("The subscriptionConstraintQuantityStep field must be a divisor of, at least, the min quantity. Received: ".concat(subscriptionConstraintQuantityStep)); } return subscriptionConstraintQuantityStep; } function validateCustom(custom) { custom !== null && custom !== void 0 ? custom : (custom = {}); if (typeof custom !== 'object') { throw new TypeError("The custom field must be an object of type {[key: string]: any}"); } return custom; }