UNPKG

polyv-live-cli

Version:

CLI tool for managing PolyV live streaming services.

375 lines 17.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CouponHandler = void 0; const base_handler_1 = require("./base.handler"); const sdk_1 = require("../sdk"); const errors_1 = require("../utils/errors"); const api_command_1 = require("../utils/api-command"); const COUPON_NAME_MAX_LENGTH = 50; const BATCH_DELETE_MAX_IDS = 200; const PAGE_SIZE_MAX = 1000; class CouponHandler extends base_handler_1.BaseHandler { constructor(authConfig, serviceConfig) { super(); this.authConfig = authConfig; this.serviceConfig = serviceConfig; } async addCoupon(options) { return this.executeWithErrorHandling(async () => { this.validateAddOptions(options); const params = this.transformToAddParams(options); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); const couponId = await client.v4Platform.createCoupon(params); this.displayAddResult(couponId, options.name, options.output); }, 'coupon.add'); } async listCoupons(options = {}) { return this.executeWithErrorHandling(async () => { this.validateListOptions(options); const params = this.transformToListParams(options); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); const result = await client.v4Platform.searchCoupons(params); this.displayListResult(result.contents, result.total, params.pageNumber ?? 1, params.pageSize ?? 10, options.output); }, 'coupon.list'); } async deleteCoupons(options) { return this.executeWithErrorHandling(async () => { this.validateDeleteOptions(options); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); await client.v4Platform.deleteCouponsBatch({ couponIds: options.couponIds }); this.displayDeleteResult(options.couponIds.length, options.output); }, 'coupon.delete'); } async getChannelCouponEnabled(options) { return this.executeWithErrorHandling(async () => { this.validateChannelId(options.channelId); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); const result = await client.v4Channel.getCouponEnabled({ channelId: options.channelId }); this.displayData(result, options.output || 'table'); }, 'coupon.channel.enabled'); } async updateChannelCouponEnabled(options) { return this.executeWithErrorHandling(async () => { this.validateChannelId(options.channelId); this.validateYn(options.enabled, 'enabled'); await (0, api_command_1.confirmWrite)(options.force, `Update channel coupon switch for channel ${options.channelId}?`); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); await client.v4Channel.updateCouponEnabled({ channelId: options.channelId, enabled: options.enabled, }); this.displayGenericWriteResult('Channel coupon switch updated successfully', { channelId: options.channelId, enabled: options.enabled, }, options.output); }, 'coupon.channel.update-enabled'); } async listChannelCoupons(options) { return this.executeWithErrorHandling(async () => { this.validateChannelId(options.channelId); this.validateChannelCouponListOptions(options); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); const result = await client.v4Channel.listChannelCoupons({ channelId: options.channelId, pageNumber: options.page ?? 1, pageSize: options.size ?? 10, ...(options.name && { name: options.name }), }); this.displayData(result, options.output || 'table'); }, 'coupon.channel.list'); } async addChannelCoupons(options) { return this.executeWithErrorHandling(async () => { this.validateChannelId(options.channelId); this.validateChannelCouponIds(options.couponIds); await (0, api_command_1.confirmWrite)(options.force, `Add ${options.couponIds.length} coupon(s) to channel ${options.channelId}?`); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); const result = await client.v4Channel.addChannelCoupon({ channelId: options.channelId, couponIds: options.couponIds, }); this.displayGenericWriteResult('Channel coupon(s) added successfully', { channelId: options.channelId, couponIds: options.couponIds, result, }, options.output); }, 'coupon.channel.add'); } async deleteChannelCoupons(options) { return this.executeWithErrorHandling(async () => { this.validateChannelId(options.channelId); this.validateChannelCouponIds(options.couponIds); await (0, api_command_1.confirmWrite)(options.force, `Delete ${options.couponIds.length} coupon(s) from channel ${options.channelId}?`); const client = (0, sdk_1.createSdkClient)(this.authConfig, this.serviceConfig.baseUrl); await client.v4Channel.deleteChannelCoupons({ channelId: options.channelId, couponIds: options.couponIds, }); this.displayGenericWriteResult('Channel coupon(s) deleted successfully', { channelId: options.channelId, couponIds: options.couponIds, }, options.output); }, 'coupon.channel.delete'); } validateAddOptions(options) { const errors = []; if (!options.name || options.name.trim().length === 0) { errors.push('name is required'); } else if (options.name.length > COUPON_NAME_MAX_LENGTH) { errors.push(`name must not exceed ${COUPON_NAME_MAX_LENGTH} characters`); } if (!options.type || !['MAX_OUT', 'DISCOUNT'].includes(options.type)) { errors.push('type must be either MAX_OUT or DISCOUNT'); } if (options.availableAmount === undefined || options.availableAmount < 0) { errors.push('availableAmount must be >= 0'); } if (!options.receiveStart || !options.receiveEnd) { errors.push('receiveStart and receiveEnd are required'); } else if (options.receiveStart >= options.receiveEnd) { errors.push('receiveEnd must be greater than receiveStart'); } if (!options.useTimeType || !['RANGE', 'DAY'].includes(options.useTimeType)) { errors.push('useTimeType must be either RANGE or DAY'); } if (options.useTimeType === 'RANGE') { if (!options.useStart || !options.useEnd) { errors.push('useStart and useEnd are required when useTimeType is RANGE'); } else if (options.useStart >= options.useEnd) { errors.push('useEnd must be greater than useStart'); } } if (options.useTimeType === 'DAY') { if (options.dayOfUse === undefined || options.dayOfUse < 1) { errors.push('dayOfUse is required and must be >= 1 when useTimeType is DAY'); } } if (!options.condition || !['UNCONDITIONAL', 'FULL_REDUCE'].includes(options.condition)) { errors.push('condition must be either UNCONDITIONAL or FULL_REDUCE'); } if (options.condition === 'UNCONDITIONAL') { if (options.discount === undefined || options.discount <= 0) { errors.push('discount is required and must be > 0 when condition is UNCONDITIONAL'); } } if (options.condition === 'FULL_REDUCE') { if (options.full === undefined || options.full < 0) { errors.push('full is required and must be >= 0 when condition is FULL_REDUCE'); } if (options.reduce === undefined || options.reduce < 0) { errors.push('reduce is required and must be >= 0 when condition is FULL_REDUCE'); } } if (options.limitPerPerson === undefined || options.limitPerPerson < -1) { errors.push('limitPerPerson must be >= -1'); } if (options.output !== undefined && !['table', 'json'].includes(options.output)) { errors.push('output must be either "table" or "json"'); } if (errors.length > 0) { throw new errors_1.PolyVValidationError(`Coupon add options validation failed: ${errors.join(', ')}`, 'options', options, 'validation_failed'); } } validateListOptions(options) { const errors = []; if (options.page !== undefined) { if (typeof options.page !== 'number' || !Number.isInteger(options.page) || options.page < 1) { errors.push('page must be a positive integer (minimum 1)'); } } if (options.size !== undefined) { if (typeof options.size !== 'number' || !Number.isInteger(options.size) || options.size < 1 || options.size > PAGE_SIZE_MAX) { errors.push(`size must be an integer between 1 and ${PAGE_SIZE_MAX}`); } } if (options.status !== undefined && !['NOT_START', 'GOING', 'FINISHED', 'INVALID'].includes(options.status)) { errors.push('status must be one of: NOT_START, GOING, FINISHED, INVALID'); } if (options.output !== undefined && !['table', 'json'].includes(options.output)) { errors.push('output must be either "table" or "json"'); } if (errors.length > 0) { throw new errors_1.PolyVValidationError(`Coupon list options validation failed: ${errors.join(', ')}`, 'options', options, 'validation_failed'); } } validateDeleteOptions(options) { const errors = []; if (!options.couponIds || !Array.isArray(options.couponIds) || options.couponIds.length === 0) { errors.push('couponIds is required and must not be empty'); } else if (options.couponIds.length > BATCH_DELETE_MAX_IDS) { errors.push(`couponIds must not exceed ${BATCH_DELETE_MAX_IDS} items`); } else { const uniqueIds = new Set(options.couponIds); if (uniqueIds.size !== options.couponIds.length) { errors.push('couponIds contains duplicate values'); } } if (options.output !== undefined && !['table', 'json'].includes(options.output)) { errors.push('output must be either "table" or "json"'); } if (errors.length > 0) { throw new errors_1.PolyVValidationError(`Coupon delete options validation failed: ${errors.join(', ')}`, 'options', options, 'validation_failed'); } } validateChannelId(channelId) { if (!channelId || channelId.trim() === '') { throw new errors_1.PolyVValidationError('channelId is required', 'channelId', channelId, 'required'); } } validateYn(value, fieldName) { if (value !== 'Y' && value !== 'N') { throw new errors_1.PolyVValidationError(`${fieldName} must be Y or N`, fieldName, value, 'invalid_value'); } } validateChannelCouponListOptions(options) { const errors = []; if (options.page !== undefined && (!Number.isInteger(options.page) || options.page < 1)) { errors.push('page must be a positive integer'); } if (options.size !== undefined && (!Number.isInteger(options.size) || options.size < 1 || options.size > PAGE_SIZE_MAX)) { errors.push(`size must be an integer between 1 and ${PAGE_SIZE_MAX}`); } if (options.output !== undefined && !['table', 'json'].includes(options.output)) { errors.push('output must be either "table" or "json"'); } if (errors.length > 0) { throw new errors_1.PolyVValidationError(`Channel coupon list options validation failed: ${errors.join(', ')}`, 'options', options, 'validation_failed'); } } validateChannelCouponIds(couponIds) { if (!Array.isArray(couponIds) || couponIds.length === 0) { throw new errors_1.PolyVValidationError('couponIds is required and must not be empty', 'couponIds', couponIds, 'required'); } if (couponIds.length > 30) { throw new errors_1.PolyVValidationError('couponIds must not exceed 30 items', 'couponIds', couponIds, 'max_items'); } const uniqueIds = new Set(couponIds); if (uniqueIds.size !== couponIds.length) { throw new errors_1.PolyVValidationError('couponIds contains duplicate values', 'couponIds', couponIds, 'duplicate'); } } transformToAddParams(options) { const rule = { condition: options.condition, limitPerPerson: options.limitPerPerson, }; if (options.condition === 'UNCONDITIONAL') { rule.unconditional = { enable: true, value: options.discount, unit: options.type === 'DISCOUNT' ? 'DISCOUNT' : 'MONEY', }; } else if (options.condition === 'FULL_REDUCE') { rule.fullReduce = { enable: true, full: options.full ?? 0, reduce: options.reduce ?? 0, unit: options.type === 'DISCOUNT' ? 'DISCOUNT' : 'MONEY', }; } const params = { name: options.name, type: options.type, availableAmount: options.availableAmount, receiveStartTime: options.receiveStart, receiveEndTime: options.receiveEnd, useTimeType: options.useTimeType, rule, }; if (options.useTimeType === 'RANGE') { params.useStartTime = options.useStart; params.useEndTime = options.useEnd; } else if (options.useTimeType === 'DAY') { params.dayOfUse = options.dayOfUse; } return params; } transformToListParams(options) { return { pageNumber: options.page ?? 1, pageSize: options.size ?? 10, ...(options.status && { status: options.status }), }; } displayAddResult(couponId, name, format = 'table') { const data = { couponId, name, created: new Date().toISOString(), }; if (format === 'json') { this.displayData(data, 'json'); } else { this.displaySuccess(`Coupon created successfully`, data, 'table'); } } displayListResult(coupons, total, page, size, format = 'table') { if (coupons.length === 0) { this.displayInfo('No coupons found'); return; } const fromItem = (page - 1) * size + 1; const toItem = Math.min(fromItem + coupons.length - 1, fromItem + size - 1); this.displayInfo(`Showing coupons ${fromItem}-${toItem} of ${total} (page ${page}, size ${size})`); if (format === 'json') { this.displayData(coupons, 'json'); } else { this.displayCouponsTable(coupons); } } displayCouponsTable(coupons) { const tableData = coupons.map((coupon) => ({ 'Coupon ID': coupon.couponId, 'Name': coupon.name, 'Type': coupon.useTimeType === 'DAY' ? 'Days' : 'Range', 'Status': this.formatStatus(coupon.status), 'Available': coupon.availableAmount, 'Received': coupon.receivedAmount, 'Receive Period': `${this.formatDate(coupon.receiveStartTime)} - ${this.formatDate(coupon.receiveEndTime)}`, })); this.displayAsTable(tableData); } displayDeleteResult(count, format = 'table') { const data = { deleted: count, timestamp: new Date().toISOString(), }; if (format === 'json') { this.displayData(data, 'json'); } else { this.displaySuccess(`Successfully deleted ${count} coupon(s)`, data, 'table'); } } displayGenericWriteResult(message, data, format = 'table') { if (format === 'json') { this.displayData({ success: true, data }, 'json'); } else { this.displaySuccess(message, data, 'table'); } } formatStatus(status) { const statusMap = { NOT_START: 'Not Started', GOING: 'Active', FINISHED: 'Finished', INVALID: 'Invalid', }; return statusMap[status] || status; } formatDate(timestamp) { return new Date(timestamp).toLocaleDateString(); } } exports.CouponHandler = CouponHandler; //# sourceMappingURL=coupon.handler.js.map