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

227 lines (198 loc) 7.5 kB
import { Pricing } from '../../../types'; import { DZNKeywords, Chunk } from '.'; import { EOL } from 'os'; import { AddOn, calculateAddOnAvailableForMatrix, calculateAddOnsDependsOnOExcludesMatrix, calculateAddOnsFeaturesMatrix, calculateAddOnsUsageLimitsExtensionsMatrix, calculateAddOnsUsageLimitsMatrix, getAddOnNames, getAddOnPrices, } from '../../../main/models/pricing2yaml/addon'; import { calculatePlanFeaturesMatrix, calculatePlanUsageLimitsMatrix, getPlanPrices, getPlanNames, Plan, } from '../../../main/models/pricing2yaml/plan'; import { getFeatureNames, getNumberOfFeatures } from '../../../main/models/pricing2yaml/feature'; import { calculateLinkedFeaturesMatrix, getNumberOfUsageLimits, getUsageLimitNames, UsageLimit, } from '../../../main/models/pricing2yaml/usage-limit'; import { formatMatrixToString, generateChunk, generateChunkBlock } from './string-utils'; export function pricing2DZN(pricing: Pricing): string { const numFeatures = getNumberOfFeatures(pricing.features); const numUsageLimits = getNumberOfUsageLimits(pricing.usageLimits); const numPlans = pricing.plans ? Object.keys(pricing.plans).length : 0; const numAddOns = pricing.addOns ? Object.keys(pricing.addOns).length : 0; const variableChunks: Chunk[] = [ { left: DZNKeywords.NumberOfFeatures, value: JSON.stringify(numFeatures), }, { left: DZNKeywords.NumberOfUsageLimits, value: JSON.stringify(numUsageLimits), }, { left: DZNKeywords.NumberOfPlans, value: JSON.stringify(numPlans) }, { left: DZNKeywords.NumberOfAddOns, value: JSON.stringify(numAddOns) }, ]; const variablesBlock = generateChunkBlock(variableChunks); const featureNames = getFeatureNames(pricing.features); const usageLimitNames = getUsageLimitNames(pricing.usageLimits); const planNames = getPlanNames(pricing.plans); const addOnNames = getAddOnNames(pricing.addOns); const namesChunks: Chunk[] = [ { left: DZNKeywords.Features, value: JSON.stringify(featureNames) }, { left: DZNKeywords.UsageLimits, value: JSON.stringify(usageLimitNames), }, { left: DZNKeywords.Plans, value: JSON.stringify(planNames) }, { left: DZNKeywords.AddOns, value: JSON.stringify(addOnNames) }, ]; const namesBlock = generateChunkBlock(namesChunks); const pricesChunk = generatePricesChunk(pricing.plans, pricing.addOns); const booleanUsageLimitsChunk = generateBooleanUsageLimitsChunk(pricing.usageLimits); const planChunks = generatePlanChunks(pricing.usageLimits || {}, pricing.plans); const linkedFeatures = generateLinkedFeaturesMatrix(pricing); const addOnsChunks = generateAddOnsChunks(pricing); return [variablesBlock, namesBlock, pricesChunk, booleanUsageLimitsChunk, linkedFeatures, planChunks, addOnsChunks].join( EOL ); } function generatePricesChunk(plans?: Record<string, Plan>, addOns?: Record<string, AddOn>): string { const plansPrices = getPlanPrices(plans); if (plans && Object.keys(plans).length !== 0 && plansPrices.every(p => p === null)) { throw new Error(`Either prices are not defined for all plans, or they are not numbers. Current parsed prices: ${plansPrices}`); } const addOnPrices = getAddOnPrices(addOns); const pricesChunks: Chunk[] = [ { left: DZNKeywords.PlansPrices, value: JSON.stringify(plansPrices), }, { left: DZNKeywords.AddOnsPrices, value: JSON.stringify(addOnPrices), }, ]; return generateChunkBlock(pricesChunks); } function generateBooleanUsageLimitsChunk(usageLimits?: Record<string, UsageLimit> | undefined): string { if (!usageLimits){ return ''; } const booleanUsageLimits = Object.values(usageLimits).map(ul => ul.valueType === 'BOOLEAN' ? 1 : 0); const booleanUsageLimitsChunks: Chunk[] = [ { left: DZNKeywords.BooleanUsageLimits, value: JSON.stringify(booleanUsageLimits), }, ]; return generateChunkBlock(booleanUsageLimitsChunks); } function generatePlanChunks(usageLimits: Record<string, UsageLimit>, plans?: Record<string, Plan>): string { if (!plans){ return ''; } const planNames = Object.values(plans).map(plan => plan.name); const planFeaturesMatrix = calculatePlanFeaturesMatrix(plans); const planUsageLimitsMatrix = calculatePlanUsageLimitsMatrix(usageLimits, plans); const addOnChunks: Chunk[] = [ { left: DZNKeywords.PlansFeatures, row: DZNKeywords.Plans, col: DZNKeywords.Features, value: formatMatrixToString(planNames, planFeaturesMatrix), }, { left: DZNKeywords.PlansUsageLimits, row: DZNKeywords.Plans, col: DZNKeywords.UsageLimits, value: formatMatrixToString(planNames, planUsageLimitsMatrix), }, ]; return generateChunkBlock(addOnChunks); } function generateAddOnsChunks(pricing: Pricing): string { if (!pricing.addOns) { return ''; } if (!pricing.usageLimits) { return ''; } const addOnNames = getAddOnNames(pricing.addOns); const planNames = getPlanNames(pricing.plans); const addOnsFeatureMatrix = calculateAddOnsFeaturesMatrix(pricing.features, pricing.addOns); const addOnsUsageLimitsMatrix = calculateAddOnsUsageLimitsMatrix( pricing.usageLimits, pricing.addOns ); const addOnsUsageLimitsExtensionsMatrix = calculateAddOnsUsageLimitsExtensionsMatrix( pricing.usageLimits, pricing.addOns ); const addOnsAvailableForMatrix = calculateAddOnAvailableForMatrix(planNames, pricing.addOns); const addOnsDependsOnMatrix = calculateAddOnsDependsOnOExcludesMatrix(pricing.addOns); const addOnsExcludesOnMatrix = calculateAddOnsDependsOnOExcludesMatrix(pricing.addOns, "excludes"); const addOnChunks: Chunk[] = [ { left: DZNKeywords.AddOnsFeatures, row: DZNKeywords.AddOns, col: DZNKeywords.Features, value: formatMatrixToString(addOnNames, addOnsFeatureMatrix), }, { left: DZNKeywords.AddOnsUsageLimits, row: DZNKeywords.AddOns, col: DZNKeywords.UsageLimits, value: formatMatrixToString(addOnNames, addOnsUsageLimitsMatrix), }, { left: DZNKeywords.AddOnsUsageLimitsExtensions, row: DZNKeywords.AddOns, col: DZNKeywords.UsageLimits, value: formatMatrixToString(addOnNames, addOnsUsageLimitsExtensionsMatrix), }, { left: DZNKeywords.AddOnsAvailableFor, row: DZNKeywords.AddOns, col: DZNKeywords.Plans, value: formatMatrixToString(addOnNames, addOnsAvailableForMatrix), }, { left: DZNKeywords.AddOnsDependsOn, row: DZNKeywords.AddOns, col: DZNKeywords.AddOns, value: formatMatrixToString(addOnNames, addOnsDependsOnMatrix), }, { left: DZNKeywords.AddOnsExcludes, row: DZNKeywords.AddOns, col: DZNKeywords.AddOns, value: formatMatrixToString(addOnNames, addOnsExcludesOnMatrix), }, ]; return generateChunkBlock(addOnChunks); } function generateLinkedFeaturesMatrix(pricing: Pricing): string { if (!pricing.usageLimits) { return ''; } const usageLimitsNames = getUsageLimitNames(pricing.usageLimits); const featureNames = getFeatureNames(pricing.features); const linkedFeaturesMatrix = calculateLinkedFeaturesMatrix(pricing.usageLimits, featureNames); return generateChunk({ left: DZNKeywords.LinkedFeatures, row: DZNKeywords.UsageLimits, col: DZNKeywords.Features, value: formatMatrixToString(usageLimitsNames, linkedFeaturesMatrix), }); }