feat: add actions to FeedSource interface

Add listActions() and executeAction() to FeedSource for write
operations back to external services. Actions use arktype schemas
for input validation via StandardSchemaV1.

- ActionDefinition type with optional input schema
- FeedEngine routes actions with existence and ID validation
- Source IDs use reverse-domain format (aris.location, aris.tfl)
- LocationSource: update-location action with schema validation
- TflSource: set-lines-of-interest action with lineId validation
- No-op implementations for sources without actions

Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
2026-02-15 12:26:23 +00:00
parent 4d6cac7ec8
commit 699155e0d8
29 changed files with 1169 additions and 116 deletions

View File

@@ -0,0 +1,27 @@
import type { StandardSchemaV1 } from "@standard-schema/spec"
/**
* Describes an action a source can perform.
*
* Action IDs use descriptive verb-noun kebab-case (e.g., "update-location", "play-track").
* Combined with the source's reverse-domain ID, they form a globally unique identifier:
* `<sourceId>/<actionId>` (e.g., "aris.location/update-location").
*/
export class UnknownActionError extends Error {
readonly actionId: string
constructor(actionId: string) {
super(`Unknown action: ${actionId}`)
this.name = "UnknownActionError"
this.actionId = actionId
}
}
export interface ActionDefinition<TInput = unknown> {
/** Descriptive action name in kebab-case (e.g., "update-location", "play-track") */
readonly id: string
/** Optional longer description */
readonly description?: string
/** Schema for input validation. Accepts any Standard Schema compatible validator (arktype, zod, valibot, etc.). */
readonly input?: StandardSchemaV1<TInput>
}