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

@@ -9,7 +9,7 @@ describe("LocationService", () => {
const source = service.feedSourceForUser("user-1")
expect(source).toBeDefined()
expect(source.id).toBe("location")
expect(source.id).toBe("aris.location")
})
test("feedSourceForUser returns same source for same user", () => {

View File

@@ -64,7 +64,7 @@ describe("TflService", () => {
const source = service.feedSourceForUser("user-1")
expect(source).toBeDefined()
expect(source.id).toBe("tfl")
expect(source.id).toBe("aris.tfl")
})
test("feedSourceForUser returns same source for same user", () => {
@@ -128,8 +128,8 @@ describe("TflService", () => {
service.feedSourceForUser("user-1")
service.feedSourceForUser("user-2")
expect(service.feedSourceForUser("user-1").id).toBe("tfl")
expect(service.feedSourceForUser("user-2").id).toBe("tfl")
expect(service.feedSourceForUser("user-1").id).toBe("aris.tfl")
expect(service.feedSourceForUser("user-2").id).toBe("aris.tfl")
})
describe("returned source fetches items", () => {

View File

@@ -34,7 +34,7 @@ describe("WeatherService", () => {
const source = service.feedSourceForUser("user-1")
expect(source).toBeDefined()
expect(source.id).toBe("weather")
expect(source.id).toBe("aris.weather")
})
test("feedSourceForUser returns same source for same user", () => {