@asterql/view-protocol
v0.3.0
Published
Registered AsterQL view ids, manifests, params URLs, and handlers.
Maintainers
Readme
@asterql/view-protocol
npm install @asterql/view-protocolRegistered view definitions, deterministic view ids, canonical params, and a small handler shape for AsterQL.
This package is the bridge between "run this query locally" and "ship a cacheable UI data endpoint." Production requests use manifest-backed ids, while local tools can opt into raw query evaluation explicitly.
import {
createViewCacheHeaders,
createManifest,
createViewHandler,
createViewUrl,
defineView,
} from "@asterql/view-protocol";
const recentOrders = defineView({
service: "dashboard",
query: `*.orders[status == $status] | sort(-createdAt)[:10]{id, total}`,
});
const manifest = createManifest([recentOrders]);
const url = createViewUrl(recentOrders, { status: "paid" });
const cacheHeaders = createViewCacheHeaders(recentOrders, { status: "paid" });
const handle = createViewHandler({
views: [recentOrders],
async load({ params }) {
return loadDashboardData(params);
},
});API
defineView(input): normalize a query and compute a deterministic view id.getViewId(view): return the content hash id for a view.createManifest(views): emit a stable manifest keyed by view id.createViewETag(view, params?, options?): compute a weak ETag from the view id, canonical params hash, and optional service data version.createViewCacheHeaders(view, params?, options?): createCache-ControlandETagheaders from the view cache policy.encodeParams(params)/decodeParams(value): base64url canonical JSON.createViewUrl(view, params?, options?): build/views/:viewIdURLs.createViewHandler(options): execute registered views against host data.fetchView(view, params?, options?): tiny fetch helper for clients.
State sync primitives:
createEntityKey(kind, id)/parseEntityKey(key): stable normalized entity ids inkind:idform.createScopeKey(kind, id)/parseScopeKey(scope): stable scope ids such asagent:agent_123.hashRecordVersion(input)andhashServerEventId(input): deterministic record/event ids over canonical JSON.ServerEvent,ServerEventEnvelope,EntityRecord,EntityPatch, andInvalidationClass: browser-safe wire and store contracts for normalized state sync.invalidationIntersects(a, b): match entity, entity-kind, scope, service, and view invalidation classes.parseEntityPath(path)/formatEntityPath(path): JSON Pointer helpers for patch paths.getEntityPathValue,setEntityPathValue,unsetEntityPathValue,applyEntityPatch, andapplyEntityPatches: immutable JSON patch helpers forset,unset,merge,appendText, keyedinsert, andremoveKey.canonicalJsonBytes(value),sha256Base64Url(bytes),hashCanonicalJson(prefix, value),hashParams,hashSchema, andhashViewDefinition: canonical hashing helpers matching the package's existing view/schema/params ids.createVersionedViewETag(input)/parseVersionedViewETag(etag): weak ETags that embed the view id, canonical params hash, auth-scope hash, body hash, and a sorted invalidation-class version map, so revalidation can answer "did any class this view depends on advance?" from the ETag alone.formatInvalidationClass(class),classVersionFromDate(value),mergeClassVersions(...maps),advancedClassVersions(current, baseline, keys?),classVersionsFromETagPayload(payload),hashAuthScope(value), andifNoneMatchIncludes(header, etag): the class-version vocabulary used by versioned ETags and invalidation-driven cache revalidation.
The handler only executes registered views by default. Registered view responses
include explicit cache headers: views with a cache policy use that policy, and
views without one are no-store. Raw dev _eval responses are always
no-store and exist only when allowEval: true is passed.
