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

@onderwijsin/directus-schema-snapshot-bundle

v1.0.1

Published

Split Directus schema snapshots into version-controlled YAML files and apply them with the SchemaService.

Readme

@onderwijsin/directus-schema-snapshot-bundle

Split Directus schema snapshots into YAML files for version control, apply split snapshots through the Directus CLI, and optionally snapshot schema changes automatically.

Installation

Install in the Directus server runtime, then restart Directus:

pnpm add @onderwijsin/directus-schema-snapshot-bundle

Requires Directus >=12.0.0 <13.0.0 and Node.js >=24.10.0. This is a non-sandboxed bundle for a trusted installation that permits custom server extensions and filesystem access. The Directus process needs read/write access to the snapshot folder and its temporary directory. Mount the snapshot folder into containers when it must persist or be supplied by a deployment.

Configuration

| Variable | Default | Behavior | | ----------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | SCHEMA_SNAPSHOT_ENABLED | true | Master switch. Boolean false or string false disables both CLI registration and automatic snapshots. | | SCHEMA_SPLIT_MANAGEMENT_SNAPSHOT_FOLDER | /directus/snapshots | Default input/output directory. A nonempty string is trimmed; other values use the default. Explicit CLI paths override it. | | SCHEMA_SPLIT_MANAGEMENT_AUTO_SNAPSHOT | false | Boolean after Directus type casting. true enables automatic snapshots; false disables them. Other types fail configuration validation. | | SCHEMA_SPLIT_HARD_EXIT | true | Raw process environment string. Accepted values below select immediate process exit or soft exit. Invalid values cause a validation error and a nonzero exit code. |

Set SCHEMA_SPLIT_MANAGEMENT_AUTO_SNAPSHOT=true or false; Directus converts these values to booleans before extension validation. Numbers and strings that remain uncast are rejected.

For SCHEMA_SPLIT_HARD_EXIT, true, 1, yes, on, y, and enabled select immediate process exit. false, 0, no, off, n, and disabled select soft exit, setting the command's exit code and letting the process finish naturally. Values are case-insensitive and are not trimmed. An unset value defaults to immediate exit; empty strings, surrounding whitespace, and other values fail validation, even when the command itself succeeded.

For automatic snapshots:

SCHEMA_SNAPSHOT_ENABLED=true
SCHEMA_SPLIT_MANAGEMENT_SNAPSHOT_FOLDER=/directus/snapshots
SCHEMA_SPLIT_MANAGEMENT_AUTO_SNAPSHOT=true

CLI commands

Run these commands in the configured Directus runtime:

npx directus schema-split snapshot -o /directus/snapshots
npx directus schema-split apply /directus/snapshots
npx directus schema-split migrate -i /directus/schema.yaml -o /directus/snapshots

For hardened Directus images, which omit npx, invoke the CLI entrypoint directly:

docker compose exec directus node /directus/cli.js schema-split snapshot -o /directus/snapshots
docker compose exec directus node /directus/cli.js schema-split apply /directus/snapshots
docker compose exec directus node /directus/cli.js schema-split migrate -i /directus/schema.yaml -o /directus/snapshots

The command signatures remain:

schema-split apply [folder]
schema-split snapshot [-o, --output [folder]]
schema-split migrate -i, --input <file> [-o, --output [folder]]

Omitting the folder or output option uses the configured default folder. Supplying -o or --output without a folder fails.

  • snapshot reads the current schema, clears the output directory, and writes a new split snapshot. Use a directory dedicated to schema files.
  • apply reconstructs the snapshot and calls SchemaService.diff() and SchemaService.apply() with administrator accountability. The diff uses force: true, bypassing Directus version/vendor compatibility checks. It applies immediately without confirmation or a dry run and can remove schema objects absent from the snapshot. Review the snapshot and back up the database first.
  • migrate converts a monolithic YAML snapshot to the split format without changing the database. It writes into the output directory without clearing it; use an empty directory to avoid retaining obsolete definitions.

apply repeats diff/apply passes until no changes remain, with at most ten applications. If the fresh diff after the tenth application still contains changes, it logs the full remaining diff once at error level as a separate structured log entry after a descriptive message, before reporting Schema did not converge after 10 applications. This includes collections, fields, relations, and system fields. Detailed diffs are not logged during intermediate passes or on successful convergence, including convergence on the tenth application. Inspect the remaining diff for snapshot configuration problems before retrying. Missing or invalid metadata, malformed recognized YAML files, service errors, and failure to converge produce a nonzero exit code. Commands normally terminate the process explicitly; SCHEMA_SPLIT_HARD_EXIT=false is useful when debugging open handles.

apply uses only the metadata.yml directly in the selected snapshot folder. Metadata in subfolders cannot replace it or change the snapshot root.

The apply hash uses the running Directus version, so forced cross-version diffs retain the host's concurrency check. Names containing path separators are rejected during snapshot creation or migration.

Snapshot format

snapshots/
├── metadata.yml
└── collection_<hash>/
    ├── collection_<hash>.yml
    ├── fields/
    │   └── field_<hash>.yml
    ├── relations/
    │   └── field_<hash>.yml
    └── systemFields/
        └── field_<hash>.yml

metadata.yml records the snapshot version, Directus version, and database vendor. Collection, field, relation, and system-field files contain their respective Directus snapshot definitions. Names use the lowercase original name plus the first eight characters of its case-sensitive object-hash hash; the YAML contents preserve the original names. Keep the generated layout when editing or moving files.

Each systemFields entry is stored under its collection's hashed directory, even when that system collection has no collection definition in the snapshot. Snapshot creation and migration preserve these entries, and apply uses them as the desired system-field index state. Full snapshots remove target system-field indexes whose entries are absent from the snapshot.

Compatibility with older snapshots

Older split snapshots omitted systemFields. Before applying them with this version, regenerate the snapshot from an authoritative instance with the intended indexes, or migrate a complete native YAML snapshot containing the intended systemFields into an empty directory. Review the generated files before deployment. A snapshot with no systemFields files represents an empty array; apply no longer preserves the target's current entries and can remove its system-field indexes. Migration cannot recover index definitions missing from its input.

This bundle manages schema, not collection records, uploads, or a complete database backup.

Automatic snapshots

[!NOTE]

Automatic snapshots are intended as a development convenience, primarily for local development workflows. Production use has not been tested or validated, as this feature was not designed for that purpose.

When enabled, collection, field, and relation create/update/delete events schedule a snapshot after a 15-second debounce. The automatic scheduler uses a renewable five-minute filesystem lease and skips work while directus-schema-applying.flag exists in the process temporary directory. Apply removes that flag on ordinary completion and failure.

Concurrent operations and interrupted writes

Automatic snapshots, CLI snapshots, migration, and the complete apply operation share an exclusive filesystem lock at directus-schema-snapshot/operation.lock under the process temporary directory. The lock covers schema capture, all file reads/writes, and every diff/apply pass including the final convergence check. An overlapping operation fails immediately; CLI commands return a nonzero exit code and automatic tasks log the failure. Retry after the active operation finishes. The apply flag suppresses automatic triggers; the exclusive lock also protects work already scheduled or running.

Choose a dedicated snapshot output folder that does not contain the temporary coordination directory. Writers remove metadata.yml before changing definitions and publish it atomically after all files are written. The output directory itself stays in place, including when mounted into a container. A failed or cancelled write can leave incomplete files without metadata; apply rejects them. Recreate the snapshot or rerun migration successfully before applying. This is fail-closed publication, not a backup of the previous output or a database transaction.

The operation lock has no expiry, so a paused process cannot lose ownership to another operation. A forcibly killed process can leave operation.lock and the apply flag behind. After confirming all schema-split operations have stopped, remove the stale lock directory and flag, then repair any incomplete snapshot before retrying. Never remove a live owner's lock.

Coordination requires the same filesystem-backed temporary directory in every participating process. Separate container temporary directories, older bundle versions, external snapshot edits, and schema changes outside this bundle are not synchronized. For those deployments, run snapshot writing and apply sequentially with other writers stopped, or provide shared temporary storage. Sharing only the snapshot folder is insufficient. No distributed or database-wide lock is provided.

If commands are absent, check SCHEMA_SNAPSHOT_ENABLED and extension loading. If automatic snapshots are absent, also check SCHEMA_SPLIT_MANAGEMENT_AUTO_SNAPSHOT, filesystem permissions, and the apply flag. The bundle logs failures through the Directus logger.