v2.10.0
Minor Changes
-
#114
30dd8d4Thanks @flyon! - Flip the query contract: datasets receive the live query, DSL-JSON is the wire format, and the IR becomes an opt-in store detail behind a freelower().Breaking changes (the package is pre-adoption, so this ships as a minor rather than a major — there are no published consumers to protect yet)
build()is removed from all builders. Use the freelower(query)function to produce IR:import { lower } from "@_linked/core"; const ir = lower(query); // select or any mutation
IDatasetmethods now receive the live (closed) query object, not IR. A dataset opts into the IR by callinglower(query), or forwards the query as DSL-JSON viaquery.toJSON():class MyStore implements IDataset { async selectQuery(query: SelectQuery) { return run(lower(query)); } }
SelectQuery/CreateQuery/UpdateQuery/DeleteQueryare now closed read-only interfaces (the live query), not aliases of the IR. The IR types areIRSelectQuery/IRCreateMutation/IRUpdateMutation/IRDeleteMutation.QueryBuilderis renamed toSelectBuilder(a deprecatedQueryBuilderalias is still exported).
New: DSL-JSON, the standardized wire format
Every query — select and every mutation — serializes losslessly to a compact, versioned JSON structure and rehydrates anywhere:
import { fromJSON } from "@_linked/core"; const json = query.toJSON(); // builder → DSL-JSON (carries a wire version `v` and the shape) await fromJSON(json).exec(); // DSL-JSON → live query → run (kind-detected by `op`)
See the new DSL-JSON specification for the envelope shapes, value encodings, and versioning.
New:
{$ctx}query-context referencesA query can reference the current context (e.g. the signed-in user) without resolving it yet — it travels on the wire as
{$ctx: "user"}and is resolved at lowering time, whether the context is set or unset when the query is built. Works for the select subject, update target, mutation field values, delete ids, and where-clause args:Person.select((p) => p.name).for(getQueryContext("user")); // subject: {$ctx:"user"} Person.delete(getQueryContext("user")); // delete-by-context (no .for() needed) Person.update({ hobby: "x" }).for(getQueryContext("user"));
Mutations throw
UnresolvedContextErrorif the context isn't set at lowering; selects resolve tonull.subscribeQueryContext(fn)is exported as the reactivity primitive for re-running queries when a context lands.New / changed exports
lower,fromJSON,lowerMutationJSON,encodeNodeData,decodeNodeData,subscribeQueryContext,UnresolvedContextError,encodeContextRef,isContextRefJSON,resolveContextId,CONTEXT_REF_KEY, and the typesContextRefJSON/DeleteId/IRSelectQuery/IR*Mutation.Tree-shaking
The IR pipeline (and the SPARQL layer) is reachable only through
lower(). A client that builds, serializes, and forwards queries but never lowers them tree-shakes the entire IR + SPARQL pipeline out of its bundle.package.jsonnow declaressideEffectsaccordingly.