Namespace dataModel

xeokit DataModel Inspector


Schema-aware validator for DataModel — catches structural defects (dangling references, missing types, cyclic containment) and schema-level violations (unknown types, forbidden type pairings, missing required property sets) and surfaces them as a structured InspectionReport.


Same shape as @xeokit/sdk/inspect/sceneModel — pluggable inspections + a default registry — minus the auto-fix half. No fixes ship for DataModel issues: SDK policy is to surface defects in user data rather than silently rewrite it. Triage is human work. Unlike geometry — where glitches (degenerate triangles, duplicate vertices) are clearly mechanical artefacts safe to clean up automatically — defects in the data graph almost always reflect intentional or authoring-decision content the application owner needs to see and decide on.


%%{init:{"theme":"dark"}}%% classDiagram direction TB class inspectDataModel { +(params) InspectionReport } class InspectDataModelParams { +dataModel : DataModel +schema? : DataFormatSchema +registry? : InspectionRegistry +checkX? : boolean } class InspectionReport { +issues : Issue[] +errors / warnings / info +byCode : Map } class Issue { +code : string +severity : error | warning | info +message : string +resourceId? / context? } class Inspection { +codes : string[] +schemas?: string[] +run(dataModel, push) } class InspectionRegistry class DataFormatSchema { +id : string +objectTypes : Map +relationshipTypes : Map } class DataModel { <<data>> } inspectDataModel ..> InspectDataModelParams : reads inspectDataModel ..> InspectionReport : returns InspectDataModelParams o-- DataModel InspectDataModelParams o-- DataFormatSchema InspectDataModelParams o-- InspectionRegistry InspectionRegistry "1" *-- "*" Inspection InspectionReport "1" *-- "*" Issue Inspection ..> DataFormatSchema : optional schemas[]
%%{init:{"theme":"default"}}%% classDiagram direction TB class inspectDataModel { +(params) InspectionReport } class InspectDataModelParams { +dataModel : DataModel +schema? : DataFormatSchema +registry? : InspectionRegistry +checkX? : boolean } class InspectionReport { +issues : Issue[] +errors / warnings / info +byCode : Map } class Issue { +code : string +severity : error | warning | info +message : string +resourceId? / context? } class Inspection { +codes : string[] +schemas?: string[] +run(dataModel, push) } class InspectionRegistry class DataFormatSchema { +id : string +objectTypes : Map +relationshipTypes : Map } class DataModel { <<data>> } inspectDataModel ..> InspectDataModelParams : reads inspectDataModel ..> InspectionReport : returns InspectDataModelParams o-- DataModel InspectDataModelParams o-- DataFormatSchema InspectDataModelParams o-- InspectionRegistry InspectionRegistry "1" *-- "*" Inspection InspectionReport "1" *-- "*" Issue Inspection ..> DataFormatSchema : optional schemas[]
classDiagram
    direction TB
    class inspectDataModel {
      +(params) InspectionReport
    }
    class InspectDataModelParams {
      +dataModel : DataModel
      +schema?   : DataFormatSchema
      +registry? : InspectionRegistry
      +checkX?   : boolean
    }
    class InspectionReport {
      +issues   : Issue[]
      +errors / warnings / info
      +byCode   : Map
    }
    class Issue {
      +code     : string
      +severity : error | warning | info
      +message  : string
      +resourceId? / context?
    }
    class Inspection {
      +codes   : string[]
      +schemas?: string[]
      +run(dataModel, push)
    }
    class InspectionRegistry
    class DataFormatSchema {
      +id                : string
      +objectTypes       : Map
      +relationshipTypes : Map
    }
    class DataModel {
      <<data>>
    }
    inspectDataModel ..> InspectDataModelParams : reads
    inspectDataModel ..> InspectionReport : returns
    InspectDataModelParams o-- DataModel
    InspectDataModelParams o-- DataFormatSchema
    InspectDataModelParams o-- InspectionRegistry
    InspectionRegistry "1" *-- "*" Inspection
    InspectionReport "1" *-- "*" Issue
    Inspection ..> DataFormatSchema : optional schemas[]

%%{init:{"theme":"dark"}}%% flowchart LR A[DataModel] --> B[inspectDataModel] C[DataFormatSchema] --> B B --> D[InspectionReport] D -. errors block downstream optimisation .-> E[caller triages]
%%{init:{"theme":"default"}}%% flowchart LR A[DataModel] --> B[inspectDataModel] C[DataFormatSchema] --> B B --> D[InspectionReport] D -. errors block downstream optimisation .-> E[caller triages]
flowchart LR
    A[DataModel] --> B[inspectDataModel]
    C[DataFormatSchema] --> B
    B --> D[InspectionReport]
    D -. errors block downstream optimisation .-> E[caller triages]

  • Inspection-only — no auto-fix half. Defects surface as issues; the caller decides how (and whether) to remediate.
  • Schema-aware — supply a DataFormatSchema and the schema-tagged inspections fire (unknown types, forbidden type pairings, required-property-set checks). Omit it and only the schema-agnostic structural inspections run.
  • Pluggable rules — register custom inspections into the DEFAULT_INSPECTION_REGISTRY (or build a fresh InspectionRegistry per pipeline).
  • Schema segregation — each Inspection can declare schemas: [...]; the orchestrator skips any inspection whose schema list doesn't match the model's schema id. IFC-tagged inspections only fire on IFC4 / IFC2x3 / IFC4x3 schemas.
  • Severity tierserrors, warnings, info. Same convention as sceneModel: errors block downstream optimisation; warnings inform.
  • Opt-in expensive walks — cycle detection, schema-tagging audits, IFC-specific hierarchy / containment checks are off by default and enabled via checkX flags.
  • Async variantinspectDataModelAsync yields to the host periodically so very large data graphs don't block the main thread.

npm install @xeokit/sdk
  • Issue — one finding (severity, code, message, resourceId, structured context).
  • InspectionReport — flat list plus per-severity and per-code groupings.
  • Inspection{codes[], description, run}. Walks the DataModel and returns issues.

The validator's rule book is a DataFormatSchema — declarative spec listing allowed object types, allowed relationship types, super-type chains for inheritance, and per-type required / forbidden property sets. Pass one via InspectDataModelParams.schema; omit it and only the structural always-on inspections fire.

const schema: DataFormatSchema = {
id: "MyApp/v1",
objectTypes: {
Building: {label: "Building"},
Floor: {superType: "Building"},
Door: {superType: "Floor", requiredPropertySets: ["DoorMetadata"]},
},
relationshipTypes: {
contains: {
allowedRelatingTypes: ["Building", "Floor"],
allowedRelatedTypes: ["Floor", "Door"],
},
},
};

const report = inspectDataModel({dataModel, schema});
if (report.errors.length > 0) { ... }

Inspections are pluggable via InspectionRegistry. The SDK ships DEFAULT_INSPECTION_REGISTRY pre-loaded with the built-ins; plug-ins extend it on import:

import {DEFAULT_INSPECTION_REGISTRY} from "@xeokit/sdk/inspect/dataModel";

DEFAULT_INSPECTION_REGISTRY.register({
codes: ["MyApp/CHECK_NAMING"],
description: "Enforce DataObject-naming convention",
run(dataModel) { ... },
});

Tests / one-off pipelines build a fresh InspectionRegistry and pass it via InspectDataModelParams.registry.

Inspection Codes
objectIntegrity OBJECT_MISSING_TYPE (error), OBJECT_DUPLICATE_PROPERTY_SET_REF (warning)
objectTypeRegistration OBJECT_UNKNOWN_TYPE (error, when schema supplied)
relationshipReferences RELATIONSHIP_SELF_REFERENCE (warning)
relationshipTypeRegistration RELATIONSHIP_UNKNOWN_TYPE (error, when schema supplied)
propertySetReferences OBJECT_REQUIRED_PROPERTY_SET_MISSING / OBJECT_FORBIDDEN_PROPERTY_SET (warnings, when schema supplied)
relationshipTypeBinding RELATIONSHIP_FORBIDDEN_RELATING_TYPE / RELATIONSHIP_FORBIDDEN_RELATED_TYPE / RELATIONSHIP_SELF_REFERENCE_FORBIDDEN (errors, opt-in via checkRelationshipTypeBinding)
schemaTagging OBJECT_SCHEMA_MISMATCH / RELATIONSHIP_SCHEMA_MISMATCH (warnings, opt-in via checkSchemaTagging)
relationshipCycles RELATIONSHIP_CYCLE (error, opt-in via checkRelationshipCycles)
ifcSpatialHierarchy IFC_NO_PROJECT / IFC_MULTIPLE_PROJECTS / IFC_PROJECT_HAS_PARENT / IFC_SPATIAL_PARENT_TYPE_MISMATCH (errors), IFC_SPATIAL_ORPHAN (warning); opt-in via checkIfcSpatialHierarchy; IFC-only
ifcElementContainment IFC_ELEMENT_AGGREGATED_NOT_CONTAINED (warning, opt-in via checkIfcElementContainment); IFC-only

Each Inspection can declare a list of schema ids it applies to. The orchestrator resolves the model's schema id (params.schema?.id ?? dataModel.schema) and skips any inspection whose schemas list doesn't include it. The IFC-tagged inspections only fire when the model's schema id is one of IFC4 / IFC4x3 / IFC4X3 / IFC4x1 / IFC4X1 / IFC4_ADD2_TC1 / IFC2x3 / IFC2X3. Schema-agnostic inspections leave schemas undefined and run regardless. A model with no schema id at all (no dataModel.schema, no params.schema) runs only the schema-agnostic inspections.

Dangling-reference checks (RELATIONSHIP_DANGLING_*, OBJECT_DANGLING_PROPERTY_SET_REF) aren't included — DataModel's builder methods reject unknown ids at construction time, so a live DataModel can't carry dangling endpoints.

Classes

InspectionRegistry

Interfaces

CodeAggregateJson
DataFormatSchema
InspectDataModelParams
Inspection
InspectionReport
InspectionReportJson
InspectionReportToJsonParams
InspectionRunJson
InspectProgress
Issue
IssueJson
ObjectTypeSpec
RelationshipTypeSpec

Type Aliases

IssueSeverity

Variables

DEFAULT_INSPECTION_REGISTRY
IFC_SCHEMAS
ifcElementContainment
ifcSpatialHierarchy
objectIntegrity
objectTypeRegistration
propertySetReferences
relationshipCycles
relationshipReferences
relationshipTypeBinding
relationshipTypeRegistration
schemaTagging

Functions

descriptionForCode
inspectDataModel
inspectDataModelAsync
inspectionReportToJson
issueToJson
labelForCode
relationshipLocator
typeMatchesOrInherits