npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

adapt-schemas

v1.0.0

Published

Standalone JSON Schema library for the Adapt framework

Readme

adapt-schemas

A standalone JSON Schema library for the Adapt framework stack. Load schemas from plugin folders via glob patterns, validate JSON data, and extract defaults including _globals from course schemas.

Installation

npm install adapt-schemas

Quick Start

import Schemas from 'adapt-schemas'

// Create and initialize the library
const library = new Schemas()
await library.init()

// Load schemas from plugin directories
await library.loadSchemas('**/schema/*.schema.json', {
  cwd: './plugins',
  ignore: ['**/node_modules/**']
})

// Validate data against a schema
const validatedData = await library.validate('course', {
  title: 'My Course'
})

// Get _globals defaults from the course schema
const globals = await library.getGlobalsDefaults('course')

API Reference

Schemas

Constructor Options

const library = new Schemas({
  enableCache: true,              // Enable schema build caching (default: true)
  xssWhitelist: {},               // Custom XSS whitelist tags/attributes
  xssWhitelistOverride: false,    // Replace defaults instead of extending
  formatOverrides: {},            // Custom string format RegExp patterns
  directoryReplacements: {        // Replacements for isDirectory keyword
    '$ROOT': '/app',
    '$DATA': '/app/data'
  }
})

Methods

init()

Initializes the library and loads the base schema.

await library.init()
loadSchemas(patterns, options)

Loads schemas from directories matching glob patterns.

await library.loadSchemas('**/schema/*.schema.json', {
  cwd: './plugins',           // Base directory for patterns
  ignore: ['**/excluded/**']  // Patterns to exclude
})

// Multiple patterns
await library.loadSchemas([
  'core/**/schema/*.schema.json',
  'plugins/**/schema/*.schema.json'
], { ignore: ['**/node_modules/**'] })
registerSchema(filePath, options)

Registers a single schema file.

await library.registerSchema('/path/to/schema.json', {
  replace: false  // Replace existing schema with same name
})
getSchema(schemaName, options)

Retrieves and builds a schema by name.

const schema = await library.getSchema('course', {
  useCache: true,        // Use cached build if available
  compile: true,         // Compile the schema
  applyExtensions: true  // Apply $patch extensions
})
getBuiltSchema(schemaName)

Returns the built schema object.

const schemaObj = await library.getBuiltSchema('course')
console.log(schemaObj.properties)
validate(schemaName, data, options)

Validates data against a named schema.

const validated = await library.validate('course', inputData, {
  useDefaults: true,     // Apply schema defaults (default: true)
  ignoreRequired: false  // Ignore required field errors
})
getSchemaDefaults(schemaName)

Returns all defaults as a structured object.

const defaults = await library.getSchemaDefaults('course')
// { title: 'Untitled', _globals: { ... } }
getGlobalsDefaults(schemaName)

Extracts _globals defaults from a schema.

const globals = await library.getGlobalsDefaults('course')
// { _accessibility: { _isEnabled: true, ... }, _extensions: { ... } }
getSchemaNames()

Returns list of all registered schema names.

const names = library.getSchemaNames()
// ['base', 'course', 'content', 'component', ...]
getSchemaInfo()

Returns information about all registered schemas.

const info = library.getSchemaInfo()
// { course: { filePath: '...', extensions: [...], isPatch: false } }
extendSchema(baseSchemaName, extSchemaName)

Manually extends a schema with another.

library.extendSchema('course', 'my-course-extension')
addKeyword(definition)

Adds a custom AJV keyword.

library.addKeyword({
  keyword: 'isPositive',
  type: 'number',
  validate: (schema, data) => data > 0
})
addStringFormats(formats)

Adds custom string format validators.

library.addStringFormats({
  'phone': /^\+?[\d\s-]+$/
})

Events

The library extends EventEmitter and emits the following events:

library.on('initialized', () => { })
library.on('reset', () => { })
library.on('schemasLoaded', (schemaNames) => { })
library.on('schemaRegistered', (name, filePath) => { })
library.on('schemaDeregistered', (name) => { })
library.on('schemaExtended', (baseName, extName) => { })
library.on('warning', (message) => { })

Schema Format

Basic Schema with Inheritance

Schemas use $merge to inherit from a parent schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$anchor": "content",
  "$merge": {
    "source": { "$ref": "base" },
    "with": {
      "properties": {
        "title": {
          "type": "string",
          "default": ""
        },
        "body": {
          "type": "string",
          "default": ""
        }
      },
      "required": ["title"]
    }
  }
}

Patch Schema (Extensions)

Use $patch to extend an existing schema without creating a new one:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$anchor": "course-trickle-extension",
  "$patch": {
    "source": { "$ref": "course" },
    "with": {
      "properties": {
        "_globals": {
          "type": "object",
          "properties": {
            "_trickle": {
              "type": "object",
              "properties": {
                "incompleteContent": {
                  "type": "string",
                  "default": "There is incomplete content above"
                }
              }
            }
          }
        }
      }
    }
  }
}

Custom Keywords

The library includes these custom AJV keywords:

| Keyword | Description | Example | |---------|-------------|---------| | isBytes | Parses byte strings | "1MB"1048576 | | isDate | Parses date strings | "2024-01-01"Date | | isTimeMs | Parses duration strings | "7d"604800000 | | isDirectory | Resolves path tokens | "$ROOT/data""/app/data" | | isObjectId | Marks ObjectId fields | No transformation |

Error Handling

The library throws SchemaError with the following codes:

| Code | Description | |------|-------------| | INVALID_PARAMS | Invalid method parameters | | SCHEMA_EXISTS | Schema with same name already registered | | SCHEMA_LOAD_FAILED | Failed to read/parse schema file | | INVALID_SCHEMA | Schema fails JSON Schema validation | | MISSING_SCHEMA | Requested schema not found | | VALIDATION_FAILED | Data fails schema validation | | MODIFY_PROTECTED_ATTR | Attempt to modify internal/read-only field |

import { SchemaError } from 'adapt-schemas'

try {
  await library.validate('course', data)
} catch (e) {
  if (e instanceof SchemaError) {
    console.log(e.code)    // 'VALIDATION_FAILED'
    console.log(e.data)    // { schemaName, errors, data }
  }
}

License

MIT