The Bookstore Domain
Every example throughout this documentation uses a single running domain: an eCommerce bookstore. This page defines the folder structure and the schemas that appear in all subsequent guides. Later guides build on this foundation, and examples reference these types by name without re-defining them.
Source: the full domain (TBox schemas, ABox seed data, transforms, anti-pattern fixtures) lives at
examples/docs/bookstore/. Every code block on this page is excerpted from those files; clone the repo and run them directly.
Why a shared domain
Reading scattered docs is hard when every page introduces fresh data types. By anchoring everything to one domain you can see how concepts compose - instantiate in the Validation guide operates on the same Customer you defined here; extend in Composition derives CustomerWithDiscount from that same Customer; dump in Serialization serializes the order produced by Coercion.
Folder layout
examples/docs/bookstore/
├── index.ts # JsonTology.create + re-exports
├── aboxFixtures.ts # Concrete ABox instance data (Bastian orders the Neverending Story)
├── transforms.ts # ETL transform examples
├── antiPatterns.ts # Patterns the registry rejects (documentation)
└── entities/
├── Amount.ts # primitive: number, minimum 0
├── AuthorName.ts # primitive: string, minLength 1 (subtype of PersonName)
├── BindingType.ts # primitive: enum hardcover | paperback | spiral | leatherbound
├── CityName.ts # primitive: string, 1-100 chars
├── CountryCode.ts # primitive: string, pattern ^[A-Z]{2}$
├── CurrencyCode.ts # primitive: string, enum of 6 codes
├── CustomerId.ts # primitive: string, format uuid
├── CustomerName.ts # primitive: string, subtype of PersonName
├── DownloadUrl.ts # primitive: string, format uri, x-jt-iriRef: true
├── EBookFormat.ts # primitive: enum epub | pdf | mobi | azw3
├── Email.ts # primitive: string, format email
├── EstimatedAgeYears.ts # primitive: integer, minimum 0
├── FileSizeBytes.ts # primitive: integer, minimum 0
├── FirstEditionYear.ts # primitive: integer, minimum 1400, maximum 2100
├── Isbn.ts # primitive: string, pattern ^\d{13}$
├── Iso8601.ts # primitive: string, format date-time
├── OrderId.ts # primitive: string, format uuid
├── PageCount.ts # primitive: integer, minimum 0
├── PageNumber.ts # primitive: integer, minimum 1
├── PageSize.ts # primitive: integer, minimum 1
├── PersonName.ts # primitive: string, 1-200 chars
├── PostalCode.ts # primitive: string, 3-12 chars
├── PrintPageCount.ts # primitive: integer, minimum 1
├── PrintStatus.ts # primitive: enum inPrint | outOfPrint | limitedRun
├── Provenance.ts # primitive: string, x-jt-language: de
├── PublicationDate.ts # primitive: string, format date
├── Quantity.ts # primitive: integer, minimum 1
├── RatingCount.ts # primitive: integer, minimum 0
├── RatingScore.ts # primitive: integer, 1-5
├── ReviewBody.ts # primitive: string, minLength 1
├── ReviewId.ts # primitive: string, format uuid
├── StockLevel.ts # primitive: integer, minimum 0, multipleOf 5
├── StreetLine.ts # primitive: string, 1-200 chars
├── Title.ts # primitive: string, 1-500 chars
├── VerifiedPurchase.ts # primitive: boolean, default false
├── WeightGrams.ts # primitive: integer, minimum 1
├── Money.ts # composite: { amount: Amount, currency: CurrencyCode }
├── Address.ts # entity: composes StreetLine + CityName + PostalCode + CountryCode
├── BibliographicRecord.ts # entity: isbn (inverseFunctional) + title + authors + publishedOn
├── Book.ts # entity: subClassOf BibliographicRecord, adds price + printStatus + inStock + stockLevel + ratings + annotations
├── BookAnnotations.ts # entity: free-text tag array on a book
├── BookCatalogEntry.ts # entity: isbn + variants array (kind + variantPrice)
├── BookListPage.ts # entity: paginated Book results with cursor pagination metadata
├── BookRatingHistogram.ts # entity: histogram of RatingScore → RatingCount
├── Customer.ts # entity: composes CustomerId + Email + CustomerName + Address
├── EBook.ts # subClassOf Book + disjointWith PrintBook — digital format (epub/pdf/mobi/azw3)
├── InPrintBook.ts # subClassOf Book, hasValue(printStatus, 'inPrint')
├── Order.ts # entity: composes OrderId + CustomerId + OrderLine[] + Money + shippingAddress
├── OrderLine.ts # entity: composes Isbn + Quantity + Money
├── OutOfPrintBook.ts # complementOf InPrintBook, allOf-bounded to Book
├── PrintBook.ts # subClassOf Book + disjointWith EBook — physical format with binding + pageCount + weightGrams
├── RareBook.ts # subClassOf PrintBook + someValuesFrom(authors) + maxCardinality(authors, 1)
├── Review.ts # entity: ReviewId + Isbn + CustomerId + RatingScore + ReviewBody + Iso8601 + annotated edge
├── Sequel.ts # relation: book + predecessor (asymmetric: true)
├── SignedFirstEdition.ts # subClassOf RareBook + Provenance + signedBy + solo-author invariant
└── SimilarBook.ts # relation: a + b (symmetric: true, reflexive: true)Cross-field rules that JSON Schema and TypeScript can't express structurally (like "a SignedFirstEdition has exactly one author") are registered on the schema as invariants (bookstoreEntities.addInvariant). The invariant function runs after structural validation and surfaces failures in the same ValidationErrors shape as any structural error, with keyword: 'jt:invariant'. This is how json-tology augments TypeScript: schema declarations carry not just shape but the runtime axioms that shape can't express, and the inferred TS type tracks both.
Each primitive file exports a single schema constant with a stable $id using the urn:bookstore: IRI pattern. Entity files import only the primitives they reference — every $ref is { $ref: SourceSchema.$id } with an explicit named import at the top of the file.
The IRI pattern
All bookstore schemas use URN-style identifiers:
urn:bookstore:{PascalCaseName}Examples: urn:bookstore:Isbn, urn:bookstore:Customer, urn:bookstore:Order.
Primitives (named, single source of truth)
Isbn
/**
* Bookstore domain: Isbn primitive — named, single source of truth
*
* `IsbnSchema` is the canonical primitive for ISBN-13 identifiers. It is
* imported by `BookSchema`, `OrderLineSchema`, and `ReviewSchema` via
* `{ $ref: IsbnSchema.$id }` — never repeated inline.
*
* The 1979 Thienemann Verlag first edition of Michael Ende's
* "Die unendliche Geschichte" has ISBN-13 `9783522128001`.
*/
import { IsbnSchema } from '../bookstore/index.js';
const isbnId: string = IsbnSchema.$id;
const isbnType: string = IsbnSchema.type;
const isbnPattern: string = IsbnSchema.pattern;
console.assert(isbnId === 'urn:bookstore:Isbn');
console.assert(isbnType === 'string');
// Pattern enforces ISBN-13 format: exactly 13 decimal digits.
console.assert(isbnPattern === '^\\d{13}$');
console.log('IsbnSchema.$id :', isbnId);
console.log('IsbnSchema.type :', isbnType);
console.log('IsbnSchema.pattern :', isbnPattern);
// A named primitive is a single schema constant that every entity references
// via { $ref: IsbnSchema.$id } — never a repeated inline shape.
console.log('single source of truth: $ref targets this $id');
CustomerId
export const CustomerIdSchema = {
'$id': 'urn:bookstore:CustomerId',
'format': 'uuid',
'type': 'string'
} as const;Email
export const EmailSchema = {
'$id': 'urn:bookstore:Email',
'format': 'email',
'type': 'string'
} as const;Money
import { AmountSchema } from './Amount.js';
import { CurrencyCodeSchema } from './CurrencyCode.js';
export const MoneySchema = {
'$id': 'urn:bookstore:Money',
'properties': {
'amount': { '$ref': AmountSchema.$id },
'currency': { '$ref': CurrencyCodeSchema.$id }
},
'required': [
'amount',
'currency'
],
'type': 'object'
} as const;Entities (composed of named primitives)
Address
import { CityNameSchema } from './CityName.js';
import { CountryCodeSchema } from './CountryCode.js';
import { PostalCodeSchema } from './PostalCode.js';
import { StreetLineSchema } from './StreetLine.js';
export const AddressSchema = {
'$id': 'urn:bookstore:Address',
'properties': {
'city': { '$ref': CityNameSchema.$id },
'country': { '$ref': CountryCodeSchema.$id },
'postalCode': { '$ref': PostalCodeSchema.$id },
'street': { '$ref': StreetLineSchema.$id }
},
'required': [
'street',
'city',
'postalCode'
],
'type': 'object'
} as const;Customer
import { AddressSchema } from './Address.js';
import { CustomerIdSchema } from './CustomerId.js';
import { CustomerNameSchema } from './CustomerName.js';
import { EmailSchema } from './Email.js';
export const CustomerSchema = {
'$id': 'urn:bookstore:Customer',
'properties': {
'addresses': {
'default': [],
'items': { '$ref': AddressSchema.$id },
'type': 'array'
},
// inverseFunctional: true — each Customer ID (UUID) uniquely identifies at
// most one Customer individual. No two distinct customers share the same id.
// OWL 2: owl:InverseFunctionalProperty on customerId.
'customerId': {
'$ref': CustomerIdSchema.$id,
'inverseFunctional': true
},
'email': { '$ref': EmailSchema.$id },
'name': { '$ref': CustomerNameSchema.$id }
},
'required': [
'customerId',
'email',
'name'
],
'type': 'object'
} as const;Book
import { Compose } from '../../../../src/index.js';
import { BibliographicRecordSchema } from './BibliographicRecord.js';
import { BookAnnotationsSchema } from './BookAnnotations.js';
import { BookRatingHistogramSchema } from './BookRatingHistogram.js';
import { MoneySchema } from './Money.js';
import { PrintStatusSchema } from './PrintStatus.js';
import { StockLevelSchema } from './StockLevel.js';
/**
* Book — a {@link BibliographicRecordSchema} offered for sale. The retail
* listing extends the bibliographic core (isbn / title / authors / publishedOn)
* with commercial state via `Compose.subClassOf`:
*
* - `price` — the asking price (required to be on sale).
* - `printStatus` — publisher editorial state (`inPrint` | `outOfPrint` |
* `limitedRun`); drives the InPrintBook / OutOfPrintBook OWL classes.
* - `inStock` / `stockLevel` — operational inventory state, changing daily as
* copies sell or restock arrives. Orthogonal to `printStatus`.
* - `ratings` / `annotations` — merchandising metadata.
*
* The TBox emits `urn:bookstore:Book rdfs:subClassOf
* urn:bookstore:BibliographicRecord`. Book inherits the `isbn` inverse-
* functional identity from the bibliographic record.
*/
export const BookSchema = Compose.subClassOf(BibliographicRecordSchema, {
'$id': 'urn:bookstore:Book',
'properties': {
'annotations': { '$ref': BookAnnotationsSchema.$id },
'inStock': {
'default': true,
'type': 'boolean'
},
'price': { '$ref': MoneySchema.$id },
'printStatus': { '$ref': PrintStatusSchema.$id },
'ratings': { '$ref': BookRatingHistogramSchema.$id },
'stockLevel': { '$ref': StockLevelSchema.$id }
},
'required': [
'price',
'printStatus'
],
'type': 'object'
} as const);OrderLine
import { IsbnSchema } from './Isbn.js';
import { MoneySchema } from './Money.js';
import { QuantitySchema } from './Quantity.js';
export const OrderLineSchema = {
'$id': 'urn:bookstore:OrderLine',
'properties': {
'bookIsbn': { '$ref': IsbnSchema.$id },
'quantity': { '$ref': QuantitySchema.$id },
'unitPrice': { '$ref': MoneySchema.$id }
},
'required': [
'bookIsbn',
'quantity',
'unitPrice'
],
'type': 'object'
} as const;Order
import type { ValidateSchemaType } from '../../../../src/types/SchemaValidation.js';
import { AddressSchema } from './Address.js';
import { CustomerIdSchema } from './CustomerId.js';
import { Iso8601Schema } from './Iso8601.js';
import { MoneySchema } from './Money.js';
import { OrderIdSchema } from './OrderId.js';
import { OrderLineSchema } from './OrderLine.js';
export const OrderSchema = {
'$id': 'urn:bookstore:Order',
'properties': {
'customerId': { '$ref': CustomerIdSchema.$id },
'orderId': { '$ref': OrderIdSchema.$id },
'orderLines': {
'items': { '$ref': OrderLineSchema.$id },
'minItems': 1,
'type': 'array'
},
'orderTotal': { '$ref': MoneySchema.$id },
// transitive: true — timestamp ordering is transitive: if order A was
// placed before B and B before C, then A was placed before C.
// irreflexive: true — an order cannot be placed before itself; the
// "before" relation on timestamps is strictly irreflexive.
// OWL 2: owl:TransitiveProperty + owl:IrreflexiveProperty on placedAt.
'placedAt': {
'$ref': Iso8601Schema.$id,
'irreflexive': true,
'transitive': true
},
'shippingAddress': { '$ref': AddressSchema.$id }
},
'required': [
'orderId',
'customerId',
'orderLines',
'orderTotal',
'placedAt',
'shippingAddress'
],
'type': 'object'
} as const;
// Compile-time self-check: every `required` entry must be in `properties`.
const _orderShapeOk: ValidateSchemaType<typeof OrderSchema> = OrderSchema;
void _orderShapeOk;Review
/**
* Bookstore domain: ReviewSchema — entity composed of named primitives
*
* `ReviewSchema` composes six primitive schemas via `$ref`. Each `$ref`
* value is `SourceSchema.$id` with an explicit named import at the top
* of the entity file — never a bare string literal.
*
* Bastian Balthazar Bux's review of the 1979 Thienemann first edition
* of "Die unendliche Geschichte" is the canonical review fixture.
*/
import {
aboxFixtures, bookstoreEntities, ReviewSchema
} from '../bookstore/index.js';
// Validate the canonical review fixture.
const errs = bookstoreEntities.validate(ReviewSchema.$id, aboxFixtures.review);
console.assert(errs.length === 0);
// ReviewSchema is composed of six referenced primitives.
const reviewId: string = ReviewSchema.$id;
const reviewType: string = ReviewSchema.type;
console.assert(reviewId === 'urn:bookstore:Review');
console.assert(reviewType === 'object');
console.assert(ReviewSchema.required.includes('reviewId'));
console.assert(ReviewSchema.required.includes('bookIsbn'));
console.assert(ReviewSchema.required.includes('customerId'));
console.assert(ReviewSchema.required.includes('rating'));
console.assert(ReviewSchema.required.includes('body'));
console.assert(ReviewSchema.required.includes('postedAt'));
console.log('ReviewSchema.$id :', reviewId);
console.log('ReviewSchema.type :', reviewType);
console.log('required fields :', ReviewSchema.required.join(', '));
// The validate call above exercises $ref resolution: each property range is
// looked up by $id in the registry, not re-declared inline.
console.log('validation errors :', errs.length, '(fixture conforms to all six required fields)');
Annotated edge: reviewsBook
The Review entity carries an optional reviewsBook property built with Compose.annotatedEdge. This is json-tology's RDF 1.2 triple-term pattern: the base triple asserts that a review is about a book, and the annotation quads attach additional facts directly to that triple rather than to the review individual.
The base triple emitted by toQuads is:
<review-iri> <https://bookstore.example/reviews> <book-iri>Two annotations ride the edge, each with an explicitly grounded predicate IRI via x-jt-predicate:
| Annotation | Type | Grounded predicate |
|---|---|---|
ratingGiven | RatingScore (integer 1–5) | https://schema.org/ratingValue |
verifiedPurchase | VerifiedPurchase (boolean) | https://schema.org/verified |
The annotation quads in triple-term form are:
<< <review-iri> <https://bookstore.example/reviews> <book-iri> >>
<https://schema.org/ratingValue> "5"^^xsd:integer .
<< <review-iri> <https://bookstore.example/reviews> <book-iri> >>
<https://schema.org/verified> "true"^^xsd:boolean .Without x-jt-predicate, each annotation predicate auto-derives from the schema IRI and property path. Grounding to a shared vocabulary (schema.org here) makes the annotation predicates interoperable with any consumer that understands that vocabulary. The x-jt-predicate keyword is the same one that pins regular property predicates to external IRIs — it works on annotation sub-schemas in exactly the same way.
import { Compose } from '../../../../src/index.js';
import type { ValidateSchemaType } from '../../../../src/types/SchemaValidation.js';
import { BookSchema } from './Book.js';
import { CustomerIdSchema } from './CustomerId.js';
import { IsbnSchema } from './Isbn.js';
import { Iso8601Schema } from './Iso8601.js';
import { RatingScoreSchema } from './RatingScore.js';
import { ReviewBodySchema } from './ReviewBody.js';
import { ReviewIdSchema } from './ReviewId.js';
import { VerifiedPurchaseSchema } from './VerifiedPurchase.js';
/**
* ReviewsBook — RDF-star annotated edge from a Review individual to a Book
* individual. Carries two annotations at the edge level:
*
* - `ratingGiven` — the numeric rating score, predicate grounded to
* `https://schema.org/ratingValue` via `x-jt-predicate`.
* - `verifiedPurchase` — boolean flag indicating the reviewer purchased
* the item, predicate grounded to `https://schema.org/verified` via
* `x-jt-predicate`.
*
* This is the bookstore demonstration of `Compose.annotatedEdge` /
* `jt:annotatedEdge` with explicit predicate grounding. The base triple is:
* <review-iri> <https://bookstore.example/reviews> <book-iri>
*
* The annotation quads (triple-term form) are:
* << <review-iri> <https://bookstore.example/reviews> <book-iri> >>
* <https://schema.org/ratingValue> "5"^^xsd:integer .
* << <review-iri> <https://bookstore.example/reviews> <book-iri> >>
* <https://schema.org/verified> "true"^^xsd:boolean .
*
* The property is OPTIONAL so existing Review fixtures (which supply
* `bookIsbn` for the ISBN) continue to validate unchanged.
*/
export const ReviewsBookEdge = Compose.annotatedEdge({
'annotations': {
'ratingGiven': {
'$ref': RatingScoreSchema.$id,
'x-jt-predicate': 'https://schema.org/ratingValue'
},
'verifiedPurchase': {
'$ref': VerifiedPurchaseSchema.$id,
'x-jt-predicate': 'https://schema.org/verified'
}
},
'predicate': 'https://bookstore.example/reviews',
'targetRef': BookSchema.$id
});
export const ReviewSchema = {
'$id': 'urn:bookstore:Review',
'properties': {
'body': { '$ref': ReviewBodySchema.$id },
'bookIsbn': { '$ref': IsbnSchema.$id },
// functional: true — each Review has at most one customer (a review is
// written by exactly one person; the customerId property maps to a single
// Customer individual). OWL 2: owl:FunctionalProperty on customerId.
'customerId': {
'$ref': CustomerIdSchema.$id,
'functional': true
},
'postedAt': { '$ref': Iso8601Schema.$id },
'rating': { '$ref': RatingScoreSchema.$id },
'reviewId': { '$ref': ReviewIdSchema.$id },
// reviewsBook — optional RDF-star annotated edge to the Book individual.
// When populated in a fixture, `toQuads` must receive a `graphIri` option.
// Demonstrates jt:annotatedEdge: the ratingGiven annotation rides the
// edge triple itself, not just as a scalar property on the Review.
'reviewsBook': ReviewsBookEdge
},
'required': [
'reviewId',
'bookIsbn',
'customerId',
'rating',
'body',
'postedAt'
],
'type': 'object'
} as const;
// Compile-time self-check: every `required` entry must be in `properties`.
const _reviewShapeOk: ValidateSchemaType<typeof ReviewSchema> = ReviewSchema;
void _reviewShapeOk;Registering everything at once
The orchestrator examples/docs/bookstore/index.ts creates the shared jt instance with all 56 schemas pre-registered. Primitives register first (required by $ref resolution):
/**
* Bookstore domain: registry orchestrator — JsonTology.create with all schemas
*
* The `examples/docs/bookstore/index.ts` file creates the shared
* `bookstoreEntities` instance with all 31 schemas pre-registered.
* Primitives register first (required by `$ref` resolution); entities
* register after because they reference the primitives.
*
* `as const` on the `schemas` array is required so TypeScript preserves
* the literal types needed for `InferType<T>` inference.
*
* This example confirms the registry has all expected schemas and can
* validate concrete ABox data against each entity.
*/
import {
aboxFixtures,
AddressSchema,
bookstoreEntities,
bookstoreSchemas,
CustomerSchema,
OrderLineSchema,
OrderSchema,
ReviewSchema
} from '../bookstore/index.js';
// Validate a concrete instance for each entity schema — zero errors
// confirms the schema is registered and its $refs resolve correctly.
const addressErrs = bookstoreEntities.validate(AddressSchema.$id, aboxFixtures.customer.addresses[0]);
const customerErrs = bookstoreEntities.validate(CustomerSchema.$id, aboxFixtures.customer);
const orderErrs = bookstoreEntities.validate(OrderSchema.$id, aboxFixtures.order);
const lineErrs = bookstoreEntities.validate(OrderLineSchema.$id, aboxFixtures.order.orderLines[0]);
const reviewErrs = bookstoreEntities.validate(ReviewSchema.$id, aboxFixtures.review);
console.assert(addressErrs.length === 0);
console.assert(customerErrs.length === 0);
console.assert(orderErrs.length === 0);
console.assert(lineErrs.length === 0);
console.assert(reviewErrs.length === 0);
console.log('registered schemas :', bookstoreSchemas.length);
console.log('Address errors :', addressErrs.length);
console.log('Customer errors :', customerErrs.length);
console.log('Order errors :', orderErrs.length);
console.log('OrderLine errors :', lineErrs.length);
console.log('Review errors :', reviewErrs.length);
// Each validate call exercises $ref resolution across the full registry:
// OrderLine.$ref → Isbn, Quantity, Money; Money.$ref → Amount, CurrencyCode.
console.log('all $refs resolve : true (zero errors across all five entities)');
as const is required so TypeScript preserves the literal types needed for InferType<T> inference.
Class taxonomy (advanced)
The bookstore domain extends to an OWL-style class hierarchy with subClassOf and disjointWith axioms. See Bookstore OWL taxonomy for the full example.
Importing in your examples
All subsequent guide pages import from the shared orchestrator:
/**
* Bookstore domain: import from shared orchestrator
*
* All doc-page examples import from the shared orchestrator at
* `examples/docs/bookstore/index.js`. This gives every guide page access
* to the same pre-registered `bookstoreEntities`, the same schema
* constants, the same ABox fixtures, and the same exported types.
*
* The path depth from guide example files is `../bookstore/index.js`.
* From a new directory at the same level it is also `../bookstore/index.js`.
*/
import {
aboxFixtures,
bookstoreEntities,
CustomerSchema
} from '../bookstore/index.js';
// bookstoreEntities is the shared registry — same instance across all guides.
const errs = bookstoreEntities.validate(
CustomerSchema.$id,
aboxFixtures.customer
);
console.assert(errs.length === 0);
const customerName: string = aboxFixtures.customer.name;
console.assert(customerName === 'Bastian Balthazar Bux');
console.log('shared registry size:', bookstoreEntities.registry.size);
console.log('customer validates against shared CustomerSchema, errors:', errs.length);
console.log('shared fixture name:', customerName);
Or import directly from the specific entity file when only one is needed:
/**
* Bookstore domain: import directly from an entity file
*
* When a guide page needs only one entity's schema — without the full
* registry — it can import directly from the entity's source file.
* This avoids pulling in all 31 schemas and their side effects.
*
* Use the direct-entity import when: the entity schema is self-contained
* (no cross-schema $ref needed at runtime), or when running a compile-time
* type assertion that doesn't need `bookstoreEntities`.
*/
import { JsonTology } from '../../../src/index.js';
import { IsbnSchema } from '../bookstore/entities/Isbn.js';
// Direct entity import — schema constant available without registry.
const isbnId: string = IsbnSchema.$id;
console.assert(isbnId === 'urn:bookstore:Isbn');
// Validate with one-shot static form — no shared registry needed.
const errs = JsonTology.validate(IsbnSchema, '9783522128001');
// IsbnSchema validates a raw string (type: 'string'), not an object.
// An empty collection confirms the ISBN-13 format passes.
console.assert(errs.length === 0);
console.log('direct entity $id:', isbnId);
console.log('valid ISBN-13 errors:', errs.length);
console.log('rejected non-ISBN errors:', JsonTology.validate(IsbnSchema, 'not-an-isbn').length);
What comes next
The guides that follow build concepts one at a time, each adding to what came before:
| Guide | What it adds |
|---|---|
| Schemas | How register, has, get, list work with these definitions |
| Type Inference | How InferType<typeof CustomerSchema> resolves at compile time |
| Validation | validate, is, errors - checking incoming data against these schemas |
| Coercion | instantiate - validated + defaults applied, typed result |
| Error Views | aggregate, report |
| Composition | Derive CustomerWithDiscount, BookSummary, PatchOrder |
| Value Operations | clone, hash, diff on a coerced Order |
| Serialization | dump, dumpJson - serialize an Order back to wire form |
| Ontology | Advanced: RDF/OWL/SHACL from these schemas |
Related
- Schemas - how
register,has,getwork with these definitions - Type Inference - how
InferType<typeof CustomerSchema>resolves - Validation - coercing incoming data against these schemas
See also
- Graph concepts - TBox/ABox from these schemas
- Graph-native authoring - named primitives and
$ref