mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-22 01:51:19 +00:00
refactor: rename aris to aelis (#59)
Rename all references across the codebase: package names, imports, source IDs, directory names, docs, and configs. Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
99
packages/aelis-source-location/src/location-source.ts
Normal file
99
packages/aelis-source-location/src/location-source.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { ActionDefinition, ContextEntry, FeedSource } from "@aelis/core"
|
||||
|
||||
import { Context, UnknownActionError, contextKey, type ContextKey } from "@aelis/core"
|
||||
import { type } from "arktype"
|
||||
|
||||
import { Location, type LocationSourceOptions } from "./types.ts"
|
||||
|
||||
export const LocationKey: ContextKey<Location> = contextKey("aelis.location", "location")
|
||||
|
||||
/**
|
||||
* A FeedSource that provides location context.
|
||||
*
|
||||
* This source accepts external location pushes and does not query location itself.
|
||||
* Use `pushLocation` to update the location from an external provider (e.g., GPS, network).
|
||||
*
|
||||
* Does not produce feed items - always returns empty array from `fetchItems`.
|
||||
*/
|
||||
export class LocationSource implements FeedSource {
|
||||
readonly id = "aelis.location"
|
||||
|
||||
private readonly historySize: number
|
||||
private locations: Location[] = []
|
||||
private listeners = new Set<(entries: readonly ContextEntry[]) => void>()
|
||||
|
||||
constructor(options: LocationSourceOptions = {}) {
|
||||
this.historySize = options.historySize ?? 1
|
||||
}
|
||||
|
||||
async listActions(): Promise<Record<string, ActionDefinition>> {
|
||||
return {
|
||||
"update-location": {
|
||||
id: "update-location",
|
||||
description: "Push a new location update",
|
||||
input: Location,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async executeAction(actionId: string, params: unknown): Promise<void> {
|
||||
switch (actionId) {
|
||||
case "update-location": {
|
||||
const result = Location(params)
|
||||
if (result instanceof type.errors) {
|
||||
throw new Error(result.summary)
|
||||
}
|
||||
this.pushLocation(result)
|
||||
return
|
||||
}
|
||||
default:
|
||||
throw new UnknownActionError(actionId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a new location update. Notifies all context listeners.
|
||||
*/
|
||||
pushLocation(location: Location): void {
|
||||
this.locations.push(location)
|
||||
if (this.locations.length > this.historySize) {
|
||||
this.locations.shift()
|
||||
}
|
||||
const entries: readonly ContextEntry[] = [[LocationKey, location]]
|
||||
this.listeners.forEach((listener) => {
|
||||
listener(entries)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Most recent location, or null if none pushed.
|
||||
*/
|
||||
get lastLocation(): Location | null {
|
||||
return this.locations[this.locations.length - 1] ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* Location history, oldest first. Length limited by `historySize`.
|
||||
*/
|
||||
get locationHistory(): readonly Location[] {
|
||||
return this.locations
|
||||
}
|
||||
|
||||
onContextUpdate(callback: (entries: readonly ContextEntry[]) => void): () => void {
|
||||
this.listeners.add(callback)
|
||||
return () => {
|
||||
this.listeners.delete(callback)
|
||||
}
|
||||
}
|
||||
|
||||
async fetchContext(): Promise<readonly ContextEntry[] | null> {
|
||||
if (this.lastLocation) {
|
||||
return [[LocationKey, this.lastLocation]]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async fetchItems(): Promise<[]> {
|
||||
return []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user