@coasys/ad4m / Exports / FlowTransitionProposal
Class: FlowTransitionProposal
Base class for defining data models in AD4M.
Description
Ad4mModel provides the foundation for creating data models that are stored in AD4M perspectives. Each model instance is represented as a subgraph in the perspective, with properties and relations mapped to links in that graph. The class uses Prolog-based queries to efficiently search and filter instances based on their properties and relationships.
Key concepts:
- Each model instance has a unique base expression that serves as its identifier
- Properties are stored as links with predicates defined by the
throughoption - Relations represent one-to-many relationships as sets of links
- Queries are translated to Prolog for efficient graph pattern matching
- Changes are tracked through the perspective's subscription system
Example
// Define a recipe model
@Model({ name: "Recipe" })
class Recipe extends Ad4mModel {
// Plain property — no `resolveLanguage` → deterministic typed literal
// storage (fast POS-index path). This is the perf default.
@Property({ through: "recipe://name" })
name: string = "";
// Property that needs per-value provenance (e.g. a signed message body):
// `resolveLanguage: "literal"` routes values through expression_create on
// the built-in literal language, producing a signed envelope URI
// (author/timestamp/proof) instead of a bare typed literal.
@Property({
through: "recipe://signed_note",
resolveLanguage: "literal"
})
signedNote: string = "";
// Property resolved through a custom language: values are routed through
// expression_create on that language (signed expression URIs).
@Optional({
through: "recipe://photo",
resolveLanguage: "QmFileStorageLanguageAddress..."
})
photo: string = "";
// Optional property with custom initial value
@Optional({
through: "recipe://status",
initial: "recipe://draft"
})
status: string = "";
// Read-only computed property
@ReadOnly({
through: "recipe://rating",
getter: `
findall(Rating, triple(Base, "recipe://user_rating", Rating), Ratings),
sum_list(Ratings, Sum),
length(Ratings, Count),
Value is Sum / Count
`
})
averageRating: number = 0;
// Relation of ingredients
* @HasMany({ through: "recipe://ingredient" })
* ingredients: string[] = [];
// Relation of comments linked to another model
@HasMany(() => Comment, { through: "recipe://comment" })
comments: Comment[] = [];
}
// Create and save a new recipe
const recipe = new Recipe(perspective);
recipe.name = "Chocolate Cake";
recipe.ingredients = ["flour", "sugar", "cocoa"];
await recipe.save();
// Query recipes in different ways
// Get all recipes
const allRecipes = await Recipe.findAll(perspective);
// Find recipes with specific criteria
const desserts = await Recipe.findAll(perspective, {
where: {
status: "recipe://published",
averageRating: { gt: 4 }
},
order: { name: "ASC" },
limit: 10
});
// Use the fluent query builder
const popularRecipes = await Recipe.query(perspective)
.where({ averageRating: { gt: 4.5 } })
.order({ averageRating: "DESC" })
.limit(5)
.get();
// Subscribe to real-time updates
await Recipe.query(perspective)
.where({ status: "recipe://cooking" })
.subscribe(recipes => {
console.log("Currently being cooked:", recipes);
});
// Paginate results
const { results, totalCount, pageNumber } = await Recipe.query(perspective)
.where({ status: "recipe://published" })
.paginate(10, 1);Hierarchy
-
↳
FlowTransitionProposal
Table of contents
Constructors
Properties
- __links
- acceptedBy
- author
- createdAt
- evidence
- evidenceHashes
- flowInstance
- fromState
- nonce
- outputs
- outputsHash
- proposer
- rationale
- resolvedAs
- runUri
- toState
- updatedAt
Accessors
Methods
- changedFields
- delete
- get
- isDirty
- save
- count
- create
- delete
- evaluateGetters
- findAll
- findAllAndCount
- findOne
- fromJSONSchema
- fromSHACL
- generateSDNA
- generateSHACL
- getClassName
- getModelMetadata
- paginate
- query
- queryToSPARQL
- register
- registerAll
- remove
- transaction
- update
Constructors
constructor
• new FlowTransitionProposal(perspective, baseExpression?)
Constructs a new model instance.
Parameters
| Name | Type | Description |
|---|---|---|
perspective | PerspectiveProxy | The perspective where this model will be stored |
baseExpression? | string | Optional expression URI for this instance. If omitted, a random ad4m://obj/<id> IRI is generated, independent of any property content — this is what keeps two instances with identical property values distinct. |
Example
// Create a new recipe with auto-generated base expression
const recipe = new Recipe(perspective);
// Create with specific base expression
const recipe = new Recipe(perspective, "ad4m://obj/existing-id");Inherited from
Defined in
core/src/model/Ad4mModel.ts:721 (opens in a new tab)
Properties
__links
• Optional __links: LinksMap
Per-link rows for the entries asked for with Query.links, keyed as they
were asked. Absent when the query did not ask for any.
Inherited from
Defined in
core/src/model/Ad4mModel.ts:499 (opens in a new tab)
acceptedBy
• acceptedBy: string[] = []
DIDs that accepted this proposal, as the consensus engine counts them:
an ad4m://acceptedBy link counts only when it is signed by the DID it
names, since anyone can write one naming someone else, and each DID once.
The proposer's vote is implicit and the proposer may also accept, so the
voters are the set { proposer } ∪ acceptedBy, not its sum.
Read-only: vote with acceptProposal, withdraw with rejectProposal.
Defined in
core/src/perspectives/FlowModels.ts:160 (opens in a new tab)
author
• author: string
Inherited from
Defined in
core/src/model/Ad4mModel.ts:492 (opens in a new tab)
createdAt
• createdAt: any
Inherited from
Defined in
core/src/model/Ad4mModel.ts:493 (opens in a new tab)
evidence
• evidence: string[] = []
URIs of instances offered as evidence that toState.requires is now
satisfied. Multiple links, one per cited instance; ordering is not
significant.
Defined in
core/src/perspectives/FlowModels.ts:90 (opens in a new tab)
evidenceHashes
• evidenceHashes: string = ""
JSON blob: { [uri]: sha256_hex } — one entry per evidence URI, hashing
the canonicalized graph-visible properties (sorted by property URI,
multi-values sorted lexicographically) at proposal time. Downstream
verifiers use it to detect edits to cited instances after the proposal
was written. Stored as an opaque string because SHACL properties carry
no rich-object type; the engine parses it back into a map.
Defined in
core/src/perspectives/FlowModels.ts:101 (opens in a new tab)
flowInstance
• flowInstance: string = ""
URI of the running FlowInstance this proposal targets. First-declared
property so buildSHACL derives the shape namespace from its through
prefix — ad4m://flow/instance → ad4m:// → target_class
ad4m://FlowTransitionProposal. Also the identity predicate: the
discriminator findAll uses to isolate proposal nodes.
Defined in
core/src/perspectives/FlowModels.ts:65 (opens in a new tab)
fromState
• fromState: string = ""
Name of the state the flow instance is currently in.
Defined in
core/src/perspectives/FlowModels.ts:69 (opens in a new tab)
nonce
• nonce: string = ""
The proposer's uniqueness salt for this proposal's content-addressed
URI (ad4m://flow/proposal/<hash>; the hash covers the instance, the
edge, the seal, the outputs commitment, the proposer DID and this
nonce). The engine writes a UUID. A proposal without one — or whose URI
does not match its own signed fields — is not engine-visible:
co-signatures name the URI, so the URI must commit to what they sign
(#1108).
Defined in
core/src/perspectives/FlowModels.ts:132 (opens in a new tab)
outputs
• outputs: string[] = []
The instances the proposer names as the run's outputs. Written only on
a proposal into a terminal state; one link per output, ordering not
significant. Each entry is the canonical JSON text of a
{ className, id } pair (FlowOutputRef); JSON.parse it to read one.
Defined in
core/src/perspectives/FlowModels.ts:110 (opens in a new tab)
outputsHash
• outputsHash: string = ""
SHA-256 (hex) over the named outputs' content (each instance as
model_query returns it through its class), signed by the proposer
next to the evidence seal. Co-signers load the outputs and recompute it
before voting, and a flow receipt's output preimages must hash to it.
Empty on a proposal into a non-terminal state.
Defined in
core/src/perspectives/FlowModels.ts:120 (opens in a new tab)
proposer
• proposer: string = ""
DID of the agent that issued the proposal, read the way the engine reads
it: only from a proposer link signed by the DID it names. Any member
can write a proposer link naming someone else, and an unchecked read
would show that DID instead (and drop the real proposer from the voters).
Defined in
core/src/perspectives/FlowModels.ts:82 (opens in a new tab)
rationale
• Optional rationale: string
Free-form human-readable justification. Optional — the LLM includes it
when it wants to explain why the cited evidence satisfies the state's
requires; the UI shows it to reviewers.
Defined in
core/src/perspectives/FlowModels.ts:149 (opens in a new tab)
resolvedAs
• Optional resolvedAs: string
"fired" once this replica's consensus pass has recorded the transition
this proposal settled. Per-replica bookkeeping, never an input to the
engine's own derivation. Only this replica's own Local mark is read:
a Shared one a peer wrote says nothing about what happened here.
Read-only.
Defined in
core/src/perspectives/FlowModels.ts:170 (opens in a new tab)
runUri
• Optional runUri: string
URI of the InterpretationRun node that produced this proposal, when
the proposal came from an LLM extraction pass. Absent when a human
clicked "propose" in the UI or an external tool wrote the proposal
directly.
Defined in
core/src/perspectives/FlowModels.ts:141 (opens in a new tab)
toState
• toState: string = ""
Name of the state the proposal wants to transition to.
Defined in
core/src/perspectives/FlowModels.ts:73 (opens in a new tab)
updatedAt
• updatedAt: any
Inherited from
Defined in
core/src/model/Ad4mModel.ts:494 (opens in a new tab)
Accessors
id
• get id(): string
The unique identifier (expression URI) of this model instance.
Returns
string
Inherited from
Ad4mModel.id
Defined in
core/src/model/Ad4mModel.ts:738 (opens in a new tab)
perspective
• Protected get perspective(): PerspectiveProxy
Protected getter for the perspective. Allows subclasses to access the perspective while keeping it private from external code.
Returns
Inherited from
Ad4mModel.perspective
Defined in
core/src/model/Ad4mModel.ts:746 (opens in a new tab)
timestamp
• get timestamp(): any
Backwards compatibility alias for createdAt.
Returns
any
Deprecated
Use createdAt instead. This will be removed in a future version.
Inherited from
Ad4mModel.timestamp
Defined in
core/src/model/Ad4mModel.ts:505 (opens in a new tab)
Methods
changedFields
▸ changedFields(): string[]
Returns the names of properties/relations that differ from the snapshot taken at the last hydration.
Returns all field names if no snapshot exists.
Returns
string[]
Example
recipe.name = "New Name";
recipe.changedFields(); // ["name"]Inherited from
Defined in
core/src/model/Ad4mModel.ts:927 (opens in a new tab)
delete
▸ delete(batchId?): Promise<void>
Deletes the model instance from the perspective.
Parameters
| Name | Type | Description |
|---|---|---|
batchId? | string | Optional batch ID for batch operations |
Returns
Promise<void>
Throws
Will throw if removal fails
Example
const recipe = await Recipe.findAll(perspective)[0];
await recipe.delete();
// Or with batch operations:
const batchId = await perspective.createBatch();
await recipe.delete(batchId);
await perspective.commitBatch(batchId);Inherited from
Defined in
core/src/model/Ad4mModel.ts:1870 (opens in a new tab)
get
▸ get(optsOrInclude?): Promise<FlowTransitionProposal>
Gets the model instance with all properties and relations populated.
Parameters
| Name | Type | Description |
|---|---|---|
optsOrInclude? | IncludeMap | GetOptions | Optional hydration options. Accepts two forms: - GetOptions wrapper: { include: { comments: true }, properties: ['title'] } - IncludeMap shorthand: { comments: true } (equivalent to { include: { comments: true } }) |
Returns
Promise<FlowTransitionProposal>
The populated model instance
Throws
Will throw if data retrieval fails
Example
const recipe = new Recipe(perspective, existingId);
await recipe.get();
console.log(recipe.name, recipe.ingredients);
// Shorthand — pass IncludeMap directly:
await recipe.get({ ingredients: true });
// Full options — includes sparse fieldset:
await recipe.get({ include: { ingredients: true }, properties: ['name'] });Inherited from
Defined in
core/src/model/Ad4mModel.ts:1838 (opens in a new tab)
isDirty
▸ isDirty(): boolean
Returns true if any tracked property or relation has changed
since the last hydration (or since takeSnapshot() was last called).
Always returns true if no snapshot exists (e.g. a freshly
constructed instance that hasn't been fetched yet).
Returns
boolean
Example
const recipe = await Recipe.create(perspective, { name: "Pasta" });
recipe.isDirty(); // false — just hydrated
recipe.name = "Risotto";
recipe.isDirty(); // trueInherited from
Defined in
core/src/model/Ad4mModel.ts:910 (opens in a new tab)
save
▸ save(batchId?): Promise<void>
Saves the model instance to the perspective.
New instances (no snapshot yet): creates the subject via
createSubject with initial scalar values, then sets relations
via innerUpdate.
Existing instances (snapshot present, i.e. fetched via get()
or a query): updates only dirty fields via innerUpdate, then
refreshes from the perspective.
Parameters
| Name | Type | Description |
|---|---|---|
batchId? | string | Optional batch ID for batch operations |
Returns
Promise<void>
Throws
Will throw if instance creation, linking, or updating fails
Example
// Create
const recipe = new Recipe(perspective);
recipe.name = "Spaghetti";
await recipe.save();
// Update
recipe.rating = 10;
await recipe.save();Inherited from
Defined in
core/src/model/Ad4mModel.ts:1528 (opens in a new tab)
count
▸ Static count<T>(this, perspective, query?, options?): Promise<number>
Gets a count of all matching instances.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to search in |
query? | TypedQuery<T> | Optional query parameters to filter results |
options? | CallOptions | - |
Returns
Promise<number>
Total count of matching entities
Example
const totalRecipes = await Recipe.count(perspective);
const activeRecipes = await Recipe.count(perspective, {
where: { status: "active" }
});Inherited from
Defined in
core/src/model/Ad4mModel.ts:1384 (opens in a new tab)
create
▸ Static create<T>(this, perspective, data?, options?): Promise<T>
Creates and saves a new model instance in one step.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to create the instance in |
data | Record<string, any> | Property values to assign before saving |
options? | Object | Optional settings: - parent — a Scope (model form or raw form) whose id will be used to create an incoming link from the parent to the new instance. - batchId — an existing batch id; when provided the link write and save() are added to the batch instead of committed immediately. |
options.batchId? | string | - |
options.parent? | Scope | - |
Returns
Promise<T>
The saved model instance
Example
// Simple create
const recipe = await Recipe.create(perspective, {
name: "Spaghetti",
rating: 5,
});
// Create under a parent (link auto-created)
const comment = await Comment.create(perspective, { text: "Great!" }, {
parent: { model: Post, id: postId },
});
// Create inside a transaction
await Ad4mModel.transaction(perspective, async (tx) => {
await Recipe.create(perspective, { name: "Pasta" }, { batchId: tx.batchId });
});Inherited from
Defined in
core/src/model/Ad4mModel.ts:1960 (opens in a new tab)
delete
▸ Static delete(this, perspective, id): Promise<void>
Deletes an existing model instance identified by id.
Also cleans up any incoming links that point to this instance.
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => Ad4mModel | - |
perspective | PerspectiveProxy | The perspective containing the instance |
id | string | The expression URI of the instance to delete |
Returns
Promise<void>
Example
await Recipe.delete(perspective, recipeId);Inherited from
Defined in
core/src/model/Ad4mModel.ts:2075 (opens in a new tab)
evaluateGetters
▸ Static evaluateGetters<T>(instances, perspective, propertyNames?): Promise<void>
Evaluate SPARQL getters for a batch of instances on demand.
Since deepQuery defaults to true, property getters are evaluated automatically during collection queries. Use this method when deepQuery was explicitly set to false and you want to lazily resolve getter-backed properties for a subset of instances.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type | Description |
|---|---|---|
instances | T[] | Array of model instances to evaluate getters on |
perspective | PerspectiveProxy | The perspective to query against |
propertyNames? | string[] | Optional list of getter-backed property names to evaluate. If omitted, all getters are evaluated. |
Returns
Promise<void>
Example
const messages = await Message.query(perspective).deepQuery(false).limit(30).get();
// messages[i].replyingTo is undefined (getter skipped)
// Evaluate getters for the visible subset
await Message.evaluateGetters(messages.slice(0, 10), perspective, ['replyingTo']);
// messages[0..9].replyingTo is now populatedInherited from
Defined in
core/src/model/Ad4mModel.ts:1760 (opens in a new tab)
findAll
▸ Static findAll<T, Q>(this, perspective, query?, options?): Promise<T & IncludeExtras<T, IncludeOf<Q>>[]>
Gets all instances of the model in the perspective that match the query params.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Q | extends Query | StrictTypedQuery<T> = {} |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to search in |
query? | Q | Optional query parameters to filter results |
options? | CallOptions | - |
Returns
Promise<T & IncludeExtras<T, IncludeOf<Q>>[]>
Array of matching models
Example
const allRecipes = await Recipe.findAll(perspective);
const recipes = await Recipe.findAll(perspective, {
where: {
name: "Pasta",
rating: { gt: 4 }
},
order: { createdAt: "DESC" },
limit: 10
});Inherited from
Defined in
core/src/model/Ad4mModel.ts:1255 (opens in a new tab)
findAllAndCount
▸ Static findAllAndCount<T, Q>(this, perspective, query?, options?): Promise<ResultsWithTotalCount<T & IncludeExtras<T, IncludeOf<Q>>>>
Gets all instances with count of total matches without offset & limit applied.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Q | extends Query | StrictTypedQuery<T> = {} |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to search in |
query? | Q | Optional query parameters to filter results |
options? | CallOptions | - |
Returns
Promise<ResultsWithTotalCount<T & IncludeExtras<T, IncludeOf<Q>>>>
Object containing results array and total count
Example
const { results, totalCount } = await Recipe.findAllAndCount(perspective, {
where: { category: "Dessert" },
limit: 10
});
console.log(`Showing 10 of ${totalCount} dessert recipes`);Inherited from
Defined in
core/src/model/Ad4mModel.ts:1318 (opens in a new tab)
findOne
▸ Static findOne<T, Q>(this, perspective, query?, options?): Promise<T & IncludeExtras<T, IncludeOf<Q>>>
Finds the first instance matching the query, or null if none exists.
Equivalent to findAll with limit: 1 — only one instance is hydrated.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Q | extends Query | StrictTypedQuery<T> = {} |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to search in |
query? | Q | Optional query parameters to filter results |
options? | CallOptions | - |
Returns
Promise<T & IncludeExtras<T, IncludeOf<Q>>>
The first matching instance, or null
Example
const recipe = await Recipe.findOne(perspective, {
where: { name: "Pasta" }
});
if (recipe) {
console.log(recipe.name);
}Inherited from
Defined in
core/src/model/Ad4mModel.ts:1290 (opens in a new tab)
fromJSONSchema
▸ Static fromJSONSchema(schema, options): typeof Ad4mModel
Creates an Ad4mModel class from a JSON Schema definition.
Parameters
| Name | Type | Description |
|---|---|---|
schema | JSONSchema | JSON Schema definition |
options | JSONSchemaToModelOptions | Configuration options |
Returns
typeof Ad4mModel
Generated Ad4mModel subclass
Description
This method dynamically generates an Ad4mModel subclass from a JSON Schema, enabling integration with systems that use JSON Schema for type definitions.
The method follows a cascading approach for determining predicates:
- Explicit configuration in options parameter (highest precedence)
- x-ad4m metadata in the JSON Schema
- Inference from schema title and property names
- Error if no namespace can be determined
Example
// With explicit configuration
const PersonClass = Ad4mModel.fromJSONSchema(schema, {
name: "Person",
namespace: "person://"
});
// With property mapping
const ContactClass = Ad4mModel.fromJSONSchema(schema, {
name: "Contact",
namespace: "contact://",
propertyMapping: {
"name": "foaf://name",
"email": "foaf://mbox"
}
});
// With x-ad4m metadata in schema
const schema = {
"title": "Product",
"x-ad4m": { "namespace": "product://" },
"properties": {
"name": {
"type": "string",
"x-ad4m": { "through": "product://title" }
}
}
};
const ProductClass = Ad4mModel.fromJSONSchema(schema, { name: "Product" });Throws
Error when namespace cannot be inferred
Inherited from
Defined in
core/src/model/Ad4mModel.ts:2244 (opens in a new tab)
fromSHACL
▸ Static fromSHACL(shape, name, classResolver?): typeof Ad4mModel
Synthesise an Ad4mModel subclass from a SHACL shape.
Parameters
| Name | Type | Description |
|---|---|---|
shape | SHACLShape | The SHACL shape to synthesise from. |
name | string | The model name (e.g. "Channel"). |
classResolver? | (localName: string) => typeof Ad4mModel | Optional thunk factory. When provided, any collection property that carries a sh:class URI will have its target wired up lazily: target: () => classResolver(localName). Because target is only called at query time (inside enrichShapeForIncludes / jsonToModelInstance), the resolver just needs to return the correct class by the time a query runs — making it safe to pass a closure over a registry object that is still being populated (e.g. the result record inside getModelClasses). |
Returns
typeof Ad4mModel
Inherited from
Defined in
core/src/model/Ad4mModel.ts:2288 (opens in a new tab)
generateSDNA
▸ Static generateSDNA(): Object
Generates the SDNA (Subject DNA) Prolog rules for this model class.
Injected at class-definition time by the @Model decorator.
Returns a default value on un-decorated base classes.
Returns
Object
| Name | Type |
|---|---|
name | string |
sdna | string |
Inherited from
Defined in
core/src/model/Ad4mModel.ts:516 (opens in a new tab)
generateSHACL
▸ Static generateSHACL(): Object
Generates the SHACL shape graph for this model class.
Injected at class-definition time by the @Model decorator.
Returns { shape: null, name: '' } on un-decorated base classes —
the decorator's parentSHACL?.shape?.nodeShapeUri check handles this.
Returns
Object
| Name | Type |
|---|---|
name | string |
shape | any |
Inherited from
Defined in
core/src/model/Ad4mModel.ts:526 (opens in a new tab)
getClassName
▸ Static getClassName(perspective): Promise<string>
Parameters
| Name | Type |
|---|---|
perspective | PerspectiveProxy |
Returns
Promise<string>
Inherited from
Defined in
core/src/model/Ad4mModel.ts:530 (opens in a new tab)
getModelMetadata
▸ Static getModelMetadata(): ModelMetadata
Extracts metadata from decorators for query building.
Returns
Structured metadata object containing className, properties, and relations
Description
This method reads the metadata stored by decorators (@Property, @HasMany, etc.) and returns it in a structured format that's easier to work with for query builders and other systems that need to introspect model structure.
The metadata includes:
- Class name from
Model
- Property metadata (predicates, types, constraints, etc.)
- Relation metadata (predicates, filters, etc.)
For models created via fromJSONSchema(), this method will derive metadata from
the WeakMap registries that were populated during the dynamic class creation.
If these structures are empty but a JSON schema was attached to the class,
it can fall back to deriving metadata from that schema.
Throws
Error if the class doesn't have
Model
decorator
Example
@Model({ name: "Recipe" })
class Recipe extends Ad4mModel {
@Property({ through: "recipe://name" })
name: string = "";
@HasMany({ through: "recipe://ingredient" })
ingredients: string[] = [];
}
const metadata = Recipe.getModelMetadata();
console.log(metadata.className); // "Recipe"
console.log(metadata.properties.name.predicate); // "recipe://name"
console.log(metadata.relations.ingredients.predicate); // "recipe://ingredient"Inherited from
Defined in
core/src/model/Ad4mModel.ts:593 (opens in a new tab)
paginate
▸ Static paginate<T, Q>(this, perspective, pageSize, pageNumber, query?, options?): Promise<PaginationResult<T & IncludeExtras<T, IncludeOf<Q>>>>
Helper function for pagination with explicit page size and number.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Q | extends Query | StrictTypedQuery<T> = {} |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to search in |
pageSize | number | Number of items per page |
pageNumber | number | Which page to retrieve (1-based) |
query? | Q | Optional additional query parameters |
options? | CallOptions | - |
Returns
Promise<PaginationResult<T & IncludeExtras<T, IncludeOf<Q>>>>
Paginated results with metadata
Example
const page = await Recipe.paginate(perspective, 10, 1, {
where: { category: "Main Course" }
});
console.log(`Page ${page.pageNumber} of recipes, ${page.results.length} items`);Inherited from
Defined in
core/src/model/Ad4mModel.ts:1345 (opens in a new tab)
query
▸ Static query<T>(this, perspective, query?): ModelQueryBuilder<T>
Creates a query builder for fluent query construction.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective to query |
query? | TypedQuery<T> | Optional initial query parameters |
Returns
A new query builder instance
Example
const recipes = await Recipe.query(perspective)
.where({ category: "Dessert" })
.order({ rating: "DESC" })
.limit(5)
.run();
// With real-time updates
await Recipe.query(perspective)
.where({ status: "cooking" })
.subscribe(recipes => {
console.log("Currently cooking:", recipes);
});Inherited from
Defined in
core/src/model/Ad4mModel.ts:2186 (opens in a new tab)
queryToSPARQL
▸ Static queryToSPARQL(perspective, query): Promise<string>
Generates a SPARQL query from a Query object.
Parameters
| Name | Type | Description |
|---|---|---|
perspective | PerspectiveProxy | The perspective to query (used for metadata extraction) |
query | Query | Query parameters (where, order, limit, offset, properties, relations) |
Returns
Promise<string>
Complete SPARQL query string ready for execution
Description
This method translates high-level query parameters into a SPARQL query string that can be executed against the SPARQL backend. Unlike Prolog queries which operate on SDNA-aware predicates, SPARQL queries operate directly on raw links stored in SPARQL.
The generated query uses a CTE (Common Table Expression) pattern:
- First, identify candidate base expressions by filtering links based on where conditions
- Then, for each candidate base, resolve properties and relations via subqueries
- Finally, apply ordering, pagination (LIMIT/START) at the SQL level
Key architectural notes:
- SPARQL stores only raw links (source, predicate, target, author, timestamp)
- No SDNA knowledge at the database level
- Properties are resolved via subqueries that look for links with specific predicates
- Relations are similar but return multiple values instead of one
- Special fields (base, author, timestamp) are accessed directly, not via subqueries
Example
const query = Recipe.queryToSPARQL(perspective, {
where: { name: "Pasta", rating: { gt: 4 } },
order: { timestamp: "DESC" },
limit: 10
});
// Returns: SELECT source AS base, array::first(target[WHERE predicate = ...]) AS name, ...
// FROM link WHERE ... GROUP BY source ORDER BY timestamp DESC LIMIT 10Inherited from
Defined in
core/src/model/Ad4mModel.ts:1065 (opens in a new tab)
register
▸ Static register(this, perspective): Promise<void>
Registers this model's SHACL schema on the given perspective.
This ensures the perspective knows about the model's shape (properties, relations, constraints) so instances can be created, queried, and validated.
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel | - |
perspective | PerspectiveProxy | The perspective to register the model on |
Returns
Promise<void>
Example
await Recipe.register(perspective);
// Now you can create / query Recipe instances on this perspectiveInherited from
Defined in
core/src/model/Ad4mModel.ts:2099 (opens in a new tab)
registerAll
▸ Static registerAll(perspective, models): Promise<void>
Batch-registers multiple model classes on a perspective in a single RPC call.
This is significantly faster than calling register() on each model individually
because it eliminates N-1 round-trips and mutex acquisitions.
Parameters
| Name | Type | Description |
|---|---|---|
perspective | PerspectiveProxy | The perspective to register the models on |
models | typeof Ad4mModel[] | Array of Ad4mModel subclasses to register |
Returns
Promise<void>
Example
await Ad4mModel.registerAll(perspective, [Community, Channel, Message, Task]);Inherited from
Defined in
core/src/model/Ad4mModel.ts:2119 (opens in a new tab)
remove
▸ Static remove(this, perspective, id): Promise<void>
Deletes an existing model instance identified by id.
Also cleans up any incoming links that point to this instance.
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => Ad4mModel | - |
perspective | PerspectiveProxy | The perspective containing the instance |
id | string | The expression URI of the instance to delete |
Returns
Promise<void>
Example
await Recipe.delete(perspective, recipeId);Deprecated
Use the name delete — remove is preserved as an alias.
Inherited from
Defined in
core/src/model/Ad4mModel.ts:2054 (opens in a new tab)
transaction
▸ Static transaction<R>(perspective, fn): Promise<R>
Executes a set of model operations inside a single batch (transaction).
All save, update, and delete calls made via the provided batchId
are buffered and flushed atomically when the callback completes.
If the callback throws, the batch is not committed, preventing
partial writes.
Type parameters
| Name | Type |
|---|---|
R | void |
Parameters
| Name | Type | Description |
|---|---|---|
perspective | PerspectiveProxy | The perspective to operate on |
fn | (tx: { batchId: string }) => Promise<R> | Async callback that receives a TransactionContext object. Pass tx.batchId to save(tx.batchId), update(tx.batchId), delete(tx.batchId), etc. |
Returns
Promise<R>
The value returned by fn
Example
await Ad4mModel.transaction(perspective, async (tx) => {
const recipe = new Recipe(perspective);
recipe.name = "Spaghetti";
await recipe.save(tx.batchId);
const old = await Recipe.query(perspective).where({ name: "Stale" }).run();
for (const r of old) await r.delete(tx.batchId);
});
// All changes committed atomically hereInherited from
Defined in
core/src/model/Ad4mModel.ts:2153 (opens in a new tab)
update
▸ Static update<T>(this, perspective, id, data): Promise<T>
Updates an existing model instance identified by id.
Fetches the instance, applies the provided changes, calls save(),
and returns the refreshed instance.
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type | Description |
|---|---|---|
this | typeof Ad4mModel & (...args: any[]) => T | - |
perspective | PerspectiveProxy | The perspective containing the instance |
id | string | The expression URI of the instance to update |
data | Record<string, any> | Property values to merge before saving |
Returns
Promise<T>
The updated model instance
Example
const recipe = await Recipe.update(perspective, recipeId, {
rating: 10,
});