You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/sema/validation.ts

53 lines
1.7 KiB

import { isSemaEvent, isSemaEventLabel, isIntent, isIntentBinding } from './event'
import { SemaInvariantError } from './errors'
import { SEMA_FAMILY_POLICY, type SemaActionEvent, type IntentBinding } from './types'
export { SemaInvariantError } from './errors'
export function validateIntentBinding(binding: IntentBinding, ctx = 'sema.intent'): void {
if (!isIntentBinding(binding)) {
throw new SemaInvariantError(`${ctx} is not a valid IntentBinding`)
}
const supported = binding.supported ?? []
if (supported.length === 0) return
for (const intent of supported) {
if (!isIntent(intent)) {
throw new SemaInvariantError(`${ctx}: intent "${String(intent)}" is not a valid Intent`)
}
}
if (!supported.includes(binding.default)) {
throw new SemaInvariantError(
`${ctx}: default intent "${binding.default}" must be included in supported intents`
)
}
}
export function validateSemaEvent(event: SemaActionEvent, ctx = 'sema.event'): void {
if (isSemaEventLabel(event)) return
if (!isSemaEvent(event)) {
throw new SemaInvariantError(`${ctx} is not a valid canonical semantic event`)
}
const intent = 'intent' in event ? event.intent : undefined
// Policy enforcement: families marked `intentRequirement: 'required'` MUST
// declare intent.
if (
intent === undefined &&
SEMA_FAMILY_POLICY[event.family].intentRequirement === 'required'
) {
throw new SemaInvariantError(
`${ctx}: family "${event.family}" requires intent (intentRequirement: 'required')`
)
}
// Bindings need structural validation; literals + absence are fine.
if (intent === undefined || typeof intent === 'string') return
validateIntentBinding(intent, `${ctx}.intent`)
}

Powered by TurnKey Linux.