Cross-platform packages / Validate source (push) Waiting to run
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, macos, macos-15) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, linux, ubuntu-24.04) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, macos, macos-15-intel) (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (x64, windows, windows-2025) (push) Blocked by required conditions
Cross-platform packages / Publish GitHub Release (push) Blocked by required conditions
Cross-platform packages / ${{ matrix.platform }} ${{ matrix.arch }} (arm64, linux, ubuntu-24.04-arm) (push) Blocked by required conditions
197 lines
4.7 KiB
TypeScript
197 lines
4.7 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
export const CHANNEL_SETTINGS_LIMITS = {
|
|
maximumIdentifierLength: 256,
|
|
maximumSecretLength: 4_096,
|
|
maximumAllowedSenders: 100,
|
|
maximumStatusMessageLength: 500,
|
|
maximumWarningLength: 500
|
|
} as const
|
|
|
|
export const managedChannelSchema = z.enum(['wecom', 'dingtalk'])
|
|
export type ManagedChannel = z.infer<typeof managedChannelSchema>
|
|
|
|
const identifierSchema = z
|
|
.string()
|
|
.trim()
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumIdentifierLength)
|
|
|
|
const senderIdentifierSchema = identifierSchema.min(1)
|
|
|
|
export const allowedSenderIdsSchema = z
|
|
.array(senderIdentifierSchema)
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumAllowedSenders)
|
|
.transform((values) => [...new Set(values)])
|
|
|
|
export const channelSecretUpdateSchema = z.discriminatedUnion('action', [
|
|
z.object({ action: z.literal('keep') }).strict(),
|
|
z
|
|
.object({
|
|
action: z.literal('replace'),
|
|
value: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumSecretLength)
|
|
})
|
|
.strict(),
|
|
z.object({ action: z.literal('clear') }).strict()
|
|
])
|
|
export type ChannelSecretUpdate = z.infer<
|
|
typeof channelSecretUpdateSchema
|
|
>
|
|
|
|
const editableChannelFields = {
|
|
enabled: z.boolean(),
|
|
secret: channelSecretUpdateSchema,
|
|
allowedSenderIds: allowedSenderIdsSchema,
|
|
allowGroupMessages: z.boolean()
|
|
} as const
|
|
|
|
export const weComChannelSettingsInputSchema = z
|
|
.object({
|
|
...editableChannelFields,
|
|
botId: identifierSchema
|
|
})
|
|
.strict()
|
|
export type WeComChannelSettingsInput = z.infer<
|
|
typeof weComChannelSettingsInputSchema
|
|
>
|
|
|
|
export const dingTalkChannelSettingsInputSchema = z
|
|
.object({
|
|
...editableChannelFields,
|
|
clientId: identifierSchema
|
|
})
|
|
.strict()
|
|
export type DingTalkChannelSettingsInput = z.infer<
|
|
typeof dingTalkChannelSettingsInputSchema
|
|
>
|
|
|
|
export const channelSettingsApplySchema = z
|
|
.object({
|
|
wecom: weComChannelSettingsInputSchema.optional(),
|
|
dingtalk: dingTalkChannelSettingsInputSchema.optional()
|
|
})
|
|
.strict()
|
|
.refine(
|
|
(input) => input.wecom !== undefined || input.dingtalk !== undefined,
|
|
'至少需要提供一个通道设置'
|
|
)
|
|
export type ChannelSettingsApply = z.infer<
|
|
typeof channelSettingsApplySchema
|
|
>
|
|
|
|
export const channelCredentialSourceSchema = z.enum([
|
|
'none',
|
|
'encrypted',
|
|
'environment'
|
|
])
|
|
export type ChannelCredentialSource = z.infer<
|
|
typeof channelCredentialSourceSchema
|
|
>
|
|
|
|
export const channelRuntimeStateSchema = z.enum([
|
|
'disabled',
|
|
'stopped',
|
|
'starting',
|
|
'running',
|
|
'error'
|
|
])
|
|
export type ChannelRuntimeState = z.infer<
|
|
typeof channelRuntimeStateSchema
|
|
>
|
|
|
|
export const channelRuntimeStatusSchema = z
|
|
.object({
|
|
state: channelRuntimeStateSchema,
|
|
lastError: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumStatusMessageLength)
|
|
.optional()
|
|
})
|
|
.strict()
|
|
export type ChannelRuntimeStatus = z.infer<
|
|
typeof channelRuntimeStatusSchema
|
|
>
|
|
|
|
const publicChannelFields = {
|
|
enabled: z.boolean(),
|
|
secretConfigured: z.boolean(),
|
|
source: channelCredentialSourceSchema,
|
|
readOnly: z.boolean(),
|
|
allowedSenderIds: allowedSenderIdsSchema,
|
|
allowGroupMessages: z.boolean(),
|
|
status: channelRuntimeStatusSchema
|
|
} as const
|
|
|
|
export const weComChannelSettingsSchema = z
|
|
.object({
|
|
...publicChannelFields,
|
|
botId: identifierSchema
|
|
})
|
|
.strict()
|
|
export type WeComChannelSettings = z.infer<
|
|
typeof weComChannelSettingsSchema
|
|
>
|
|
|
|
export const dingTalkChannelSettingsSchema = z
|
|
.object({
|
|
...publicChannelFields,
|
|
clientId: identifierSchema
|
|
})
|
|
.strict()
|
|
export type DingTalkChannelSettings = z.infer<
|
|
typeof dingTalkChannelSettingsSchema
|
|
>
|
|
|
|
export const channelSettingsSnapshotSchema = z
|
|
.object({
|
|
wecom: weComChannelSettingsSchema,
|
|
dingtalk: dingTalkChannelSettingsSchema,
|
|
warning: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumWarningLength)
|
|
.optional()
|
|
})
|
|
.strict()
|
|
export type ChannelSettingsSnapshot = z.infer<
|
|
typeof channelSettingsSnapshotSchema
|
|
>
|
|
|
|
export const channelConnectionTestResultSchema = z
|
|
.object({
|
|
channel: managedChannelSchema,
|
|
ok: z.boolean(),
|
|
error: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.max(CHANNEL_SETTINGS_LIMITS.maximumStatusMessageLength)
|
|
.optional()
|
|
})
|
|
.strict()
|
|
.superRefine((result, context) => {
|
|
if (result.ok && result.error !== undefined) {
|
|
context.addIssue({
|
|
code: 'custom',
|
|
path: ['error'],
|
|
message: '成功结果不能包含错误'
|
|
})
|
|
}
|
|
if (!result.ok && result.error === undefined) {
|
|
context.addIssue({
|
|
code: 'custom',
|
|
path: ['error'],
|
|
message: '失败结果必须包含错误'
|
|
})
|
|
}
|
|
})
|
|
export type ChannelConnectionTestResult = z.infer<
|
|
typeof channelConnectionTestResultSchema
|
|
>
|