feat(spec): accept optional name on extract()

Add an (name, getter) overload so each extractor handle carries a
debuggable label that future trace fields (per-step diffs) can key
off. The web-runtime falls back to extractor_\${index} when none is
supplied so existing call sites keep working unchanged.
This commit is contained in:
pj committed 2026-05-30 21:54:20 +05:30
1 parent 7291d5965b
commit 6fdbf9d2ab
3 files changed
+22 -5

No files matched your search

+13 -2
View File
@@ -1,7 +1,18 @@
import type { AccessibilityElement, Extracted, State } from "./types.ts";
export function extract<T>(getter: (state: State) => T): Extracted<T> {
return globalThis.__sanderling__.extract(getter);
export function extract<T>(getter: (state: State) => T): Extracted<T>;
export function extract<T>(name: string, getter: (state: State) => T): Extracted<T>;
export function extract<T>(
nameOrGetter: string | ((state: State) => T),
maybeGetter?: (state: State) => T,
): Extracted<T> {
if (typeof nameOrGetter === "string") {
if (maybeGetter == null) {
throw new TypeError("extract(name, getter): getter is required when a name is supplied");
}
return globalThis.__sanderling__.extract(maybeGetter, nameOrGetter);
}
return globalThis.__sanderling__.extract(nameOrGetter);
}
const KEY_DELIMITER = "\x1f";
+1 -1
View File
@@ -187,7 +187,7 @@ export interface Sampler<T> {
}
export interface SanderlingRuntime {
extract: <T>(getter: (state: State) => T) => Extracted<T>;
extract: <T>(getter: (state: State) => T, name?: string) => Extracted<T>;
always: (predicateOrFormula: (() => boolean) | Formula) => Formula;
now: (predicate: () => boolean) => Formula;
next: (predicate: () => boolean) => Formula;
+8 -2
View File
@@ -20,6 +20,7 @@ interface Handle {
interface ExtractorEntry {
getter: (state: unknown) => unknown;
handle: Handle;
name: string;
}
interface ActionGeneratorHandle {
@@ -290,9 +291,14 @@ function buildState(): unknown {
}
const runtime = {
extract<T>(getter: (state: unknown) => T): Handle {
extract<T>(getter: (state: unknown) => T, name?: string): Handle {
const handle: Handle = { current: undefined, previous: undefined };
extractors.push({ getter: getter as (s: unknown) => unknown, handle });
const resolvedName = name && name.length > 0 ? name : `extractor_${extractors.length}`;
extractors.push({
getter: getter as (s: unknown) => unknown,
handle,
name: resolvedName,
});
return handle;
},
always: noopFormula,