Skip to content
Inkoxide

Search covers every page and heading of the docs. Use ↑ ↓ and ↵.

@inkoxide/schema

TypeScript types and the JSON Schema for version 1 documents, and validating them before rendering.

Edit this page

npm install @inkoxide/schema

The package is an ES module and needs Node.js 22 or later. Its version is independent of the document schema version: @inkoxide/schema 2.x describes schema version 1.

Types

import type { Document, Node, TextRun } from '@inkoxide/schema';

const doc: Document = {
  version: 1,
  fonts: [{ id: 'Inter-Regular', family: 'Inter' }],
  pages: [{ size: { width: 595.28, height: 841.89 },
            children: [{ type: 'text', runs: [{ text: 'Hello', font: 'Inter-Regular', size: 24 }] }] }],
};

Every $defs entry of the schema is exported under its own name: Style, TableNode, Color, and so on. Node is a union of the node types, discriminated by type.

Two rules cannot be expressed in TypeScript:

  • A text run has exactly one of text, placeholder, image and note.
  • An image node, a backgroundImage and the image of a run each have exactly one of src or data.

All of them are optional in the types. The engine and ajv report a document that breaks either rule.

Client-side validation (ajv)

import { Ajv2020 } from 'ajv/dist/2020.js';
import { schema, enginePath } from '@inkoxide/schema';

const validate = new Ajv2020({ discriminator: true, strict: false, validateFormats: false }).compile(schema);
if (!validate(doc)) {
  for (const e of validate.errors!) console.log(enginePath(e), e.message);
}

Pass discriminator: true. Without it, ajv reports an error for every node type that does not match, not only for the one the type field names. strict: false lets ajv accept the discriminator annotation alongside properties. validateFormats: false skips date-time; add ajv-formats if you want ajv to check it.

enginePath(error) turns an ajv error into the engine's path syntax, pages[0].children[3].style.width. Paths from ajv and from the engine (validate() / InkoxideError.path) then compare as follows:

Problemajv keywordSame path as the engine?
Unknown propertyadditionalPropertiesyes (enginePath appends the property, as the engine does)
Wrong type, bad enum value, bad patterntype, enum, const, pattern, oneOfyes
Number out of rangeminimum, maximum, exclusiveMinimum, …yes, except in a colour (the engine reports ….backgroundColor, ajv ….backgroundColor[2]) and in fontFeatures (the engine reports ….fontFeatures, ajv the tag)
Missing required field of an object (size.height)requiredyes
Missing required field of a node (text without runs)requiredno: the engine reports the node's path, ajv the field's
Unsupported versionconstyes (version)
text and placeholder both setnot / oneOf on the runno: the engine reports ….placeholder, ajv the run
Unknown or unregistered font or image, duplicate id, unknown anchor, table structure(none)engine only: these need the registered fonts and images, or cross-references

The schema checks shape only. Always handle errors from the engine as well: ajv lets you show problems early, but the engine has the final word.

Exports

  • SCHEMA_VERSION: 1.
  • schema: the JSON Schema object. It is also available as @inkoxide/schema/document.v1.json.
  • enginePath(error): see above.

Synced from packages/schema/README.md in the inkoxide repository.