UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

176 lines 7.22 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.VariableResolver = void 0; const crypto = __importStar(require("crypto")); const MS_PER_DAY = 24 * 60 * 60 * 1000; const MAX_RANDOM_LENGTH = 10000; const MAX_DAY_OFFSET = 3650; class VariableResolver { constructor() { this.baseTimestamp = Date.now(); } resetTimestamp() { this.baseTimestamp = Date.now(); } resolve(template, outputs) { let result = template; const openBraces = (template.match(/\{/g) || []).length; const closeBraces = (template.match(/\}/g) || []).length; if (openBraces !== closeBraces) { throw new Error('Malformed variable syntax: unclosed braces'); } result = result.replace(/\{timestamp\}/g, this.baseTimestamp.toString()); result = this.resolveNowVariables(result); result = this.resolveRandomVariables(result); if (outputs) { result = this.resolveResourceReferences(result, outputs); } return result; } resolveObject(obj, outputs) { const result = {}; for (const [key, value] of Object.entries(obj)) { if (typeof value === 'string') { result[key] = this.resolve(value, outputs); } else if (Array.isArray(value)) { result[key] = value.map(item => { if (typeof item === 'string') { return this.resolve(item, outputs); } else if (typeof item === 'object' && item !== null) { return this.resolveObject(item, outputs); } return item; }); } else if (typeof value === 'object' && value !== null) { result[key] = this.resolveObject(value, outputs); } else { result[key] = value; } } return result; } renderTemplate(template, outputs) { return this.resolve(template, outputs); } resolveNowVariables(template) { const invalidNowPattern = /\{now\+([^}]+)\}/g; let invalidMatch; while ((invalidMatch = invalidNowPattern.exec(template)) !== null) { const content = invalidMatch[1]; if (content && !/^\d+d$/.test(content)) { throw new Error(`Invalid now offset format: {now+${content}}`); } } const nowPlusPattern = /\{now\+(\d+)d\}/g; let result = template.replace(nowPlusPattern, (_match, days) => { const dayCount = parseInt(days, 10); if (dayCount > MAX_DAY_OFFSET) { throw new Error(`Invalid now offset: day count ${dayCount} exceeds maximum ${MAX_DAY_OFFSET}`); } return (this.baseTimestamp + dayCount * MS_PER_DAY).toString(); }); result = result.replace(/\{now\}/g, this.baseTimestamp.toString()); return result; } resolveRandomVariables(template) { const randomPattern = /\{random:(\d+)-(\d+)\}/g; return template.replace(randomPattern, (_match, minStr, maxStr) => { const min = parseInt(minStr, 10); const max = parseInt(maxStr, 10); if (min < 1) { throw new Error('Invalid random range: min must be >= 1'); } if (min > max) { throw new Error('Invalid random range: min must be <= max'); } if (max > MAX_RANDOM_LENGTH) { throw new Error(`Invalid random range: max ${max} exceeds maximum ${MAX_RANDOM_LENGTH}`); } const length = Math.floor(Math.random() * (max - min + 1)) + min; return this.generateRandomString(length); }); } resolveResourceReferences(template, outputs) { const refPattern = /\{([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*))\}/g; return template.replace(refPattern, (_match, ref) => { const parts = ref.split('.'); const resourceId = parts[0]; if (!resourceId) { throw new Error('Invalid resource reference: empty resource id'); } const fieldPath = parts.slice(1); const resourceOutput = outputs[resourceId]; if (!resourceOutput) { throw new Error(`Resource "${resourceId}" not found in outputs`); } let value = resourceOutput; for (const field of fieldPath) { if (value === undefined || value === null) { throw new Error(`Field "${field}" not found in resource "${resourceId}" (value is undefined)`); } if (typeof value !== 'object') { throw new Error(`Cannot access field "${field}" on non-object value in resource "${resourceId}"`); } value = value[field]; } if (value === undefined) { throw new Error(`Field "${fieldPath.join('.')}" not found in resource "${resourceId}"`); } if (typeof value === 'object') { return JSON.stringify(value); } return String(value); }); } generateRandomString(length) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const randomBytes = crypto.randomBytes(length); let result = ''; for (let i = 0; i < length; i++) { const byte = randomBytes[i]; if (byte !== undefined) { result += chars[byte % chars.length]; } } return result; } } exports.VariableResolver = VariableResolver; //# sourceMappingURL=variable-resolver.js.map