release: prepare RealeseV2.3

This commit is contained in:
hectorzhao
2026-08-06 10:48:36 +08:00
parent 57b58f1c40
commit 8ad8e61793
37 changed files with 997 additions and 64 deletions
+9
View File
@@ -336,9 +336,18 @@ export function normalizeChannelRuntimeConfig(
);
base.extensionDigits = normalizeExtensionDigits(base.extensionDigits);
base.serviceId = normalizeCmppServiceId(base.serviceId);
base.longMessageReceiptMode = normalizeLongMessageReceiptMode(base.longMessageReceiptMode);
return base;
}
export function normalizeLongMessageReceiptMode(value: unknown) {
const normalized = String(value ?? 'per_segment').trim() || 'per_segment';
if (!['per_segment', 'message_level'].includes(normalized)) {
throw new BadRequestException('longMessageReceiptMode must be per_segment or message_level');
}
return normalized;
}
export function normalizeCmppServiceId(value: unknown) {
const normalized = String(value ?? 'SMS').trim() || 'SMS';
if (!/^[\x20-\x7E]{1,10}$/.test(normalized)) {
+15
View File
@@ -585,6 +585,7 @@ describe('ChannelsService', () => {
await expect(service.createChannel({ ...channel, rateLimitPerSecond: 2001 })).rejects.toThrow('rateLimitPerSecond must be between 1 and 2000');
await expect(service.createChannel({ ...channel, config: { extensionDigits: 21 } })).rejects.toThrow('extensionDigits must be an integer between 0 and 20');
await expect(service.createChannel({ ...channel, config: { serviceId: '业务代码' } })).rejects.toThrow('serviceId must contain 1 to 10 ASCII characters');
await expect(service.createChannel({ ...channel, config: { longMessageReceiptMode: 'unknown' } })).rejects.toThrow('longMessageReceiptMode must be per_segment or message_level');
});
it('updates CMPP channel configuration without requiring password changes', async () => {
@@ -686,6 +687,20 @@ describe('ChannelsService', () => {
}));
});
it('persists a message-level long-message receipt mode without requesting a reconnect', async () => {
const prisma = createPrismaMock();
const service = new ChannelsService(prisma as never);
await service.updateChannel('channel-1', { config: { longMessageReceiptMode: 'message_level' } });
expect(prisma.smsChannel.update).toHaveBeenCalledWith(expect.objectContaining({
data: expect.objectContaining({
config: expect.objectContaining({ longMessageReceiptMode: 'message_level' }),
}),
}));
expect(mockFetch).not.toHaveBeenCalled();
});
it('rejects invalid channel update ports', async () => {
const prisma = createPrismaMock();
const service = new ChannelsService(prisma as never);