Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

directus-extension-schema-sync

bcc-code3.1k3.0.9

Sync schema and data betwreen Directus instances

directus, directus-extension, directus-custom-hook, directus-schema, directus-data

readme

Schema Sync for Directus

The better way to sync your Directus schema, configuration and selected data between environments.

Splits the schema file into multiple files once per collection, for easier management in git and working with the schema files in general.

Schema Sync

Sync chosen data such as

  • Permissions
  • Flows
  • Dashboards
  • Your own data
  • Test data for CI/CD flows

Automatically export and import both the schema and data when you make changes via Directus or in the json data files

Upon installing configure what data you wish to export from the DB and be able to commit to your repository. Then on the other environments you can import the schema and data automatically.

Auto Import the schema and data when Directus starts up. This is useful for production environments. Using a locking mechanism, only one instance of Directus will import the schema and data.

IMPORTANT Always be careful with what you export and commit to your repository.

Install

Depending on how you already are using Directus you can either install this plugin using a custom Docker image, or npm.

NOTE: Installing via marketplace is not recommended as you would still need to execute the install command as well as configure the config files.

  • ** DIRECTUS 11 ** Use latest version
  • * DIRECTUS < 10 ** Use version 2.

Follow the instructions below to install the extension, ensure to first install the extension on your local environment and then export the schema and data. This will create the necessary files for the extension to work. Only once you have the files can you update your .env file with the SCHEMA_SYNC variable.

1 via Docker

If you don't already have a Dockerfile, you can use the following instructions to get started.

Create a folder called schema-sync on root. This will soon contain the config and data files for what you want to import and export.

Update your Dockerfile to include the following:

RUN pnpm install directus-extension-schema-sync
# This is for when building for production
COPY ./schema-sync ./schema-sync

In your docker-compose file we need to add the schema-sync so that we can commit it to git, and so you can edit/change the config files and have it in sync with the docker container

// docker-compose.yaml
volumes:
  - ./schema-sync:/directus/schema-sync

(re)Build and run your container.

Once it is running, run the following command (from host) to install the extension's columns in the database and add the config folder.

 Replace the `my-directus` with the name of your service running directus if it is different
// docker exec -it <container> <command>
docker compose exec -it my-directus npx directus schema-sync install --force
We are using force since we do want to replace the `schema-sync` folder already added as a volume

1 via NPM (Assuming you are running Directus via NPM)

  1. npm install directus-extension-schema-sync
  2. Then run directus schema-sync install to install the extension's columns in the database and add the config folder
  3. Edit the config.js in the schema directory and add your collections you want to sync
  4. Finally run directus schema-sync export to export the schema and data from the Directus API

2 Configuration

View and edit the schema-sync/*config.js file to include the collections you want to sync.

To automatically import and export the schema and data, set the SCHEMA_SYNC environment variable to IMPORT, EXPORT or BOTH. In production it is advised to set SCHEMA_SYNC to IMPORT and in local development to BOTH.

Note: This extension will not work if there is no row in the directus_settings database table. To avoid this happening, make sure PROJECT_NAME configuration variable is set when Directus is first time installed into the database. Alternatively, if Directus is already installed, just manually create a row in directus_settings, if one is not already there, with whatever project name you want and keep everything else to defaults.

Tips

Order matters when importing and exporting. For example if you have a collection (A) with a relation to another collection (B), then ensure in the config that collection (B) comes first. This is so when we import, we first import B, then A. Deletions happen afterward in the reverse order.

You can create additional config files with the other config files, and set the name on the SCHEMA_SYNC_CONFIG env variable. For example to include a test data set used during testing in CI/CD. Additional config files need to export syncCustomCollections object like in the config.js file.

View the comments in the config.js file for more information.

Exporting users with passwords

This does not work out of the box due to Directus masking the exported password. In order to export the hashed value you can add the following to the schema-sync/directus_config.js file within the directus_users object.

onExport: async (item, itemsSrv) => {
    if (item.password && item.password === '**********') {
        const user = await itemsSrv.knex.select('password').from('directus_users').where('id', item.id).first();
        if (user) {
            item.password = user.password;
        }
    }

    return item;
},
// And then to import the password
onImport: async (item, itemsSrv) => {
    if (item.password && item.password.startsWith('$argon')) {
        await itemsSrv.knex('directus_users').update('password', item.password).where('id', item.id);
        item.password = '**********';
    }

    return item;
},

Environment Variables

Variable Description Default
SCHEMA_SYNC Set to automatically do IMPORT, EXPORT or BOTH null
SCHEMA_SYNC_CONFIG (optional) An additional config file to use in addition, eg. test_config.js null
SCHEMA_SYNC_SPLIT (optional) Splits the schema file into multiple files once per collection true
SCHEMA_SYNC_MERGE (optional) Only insert and update items found in the import set (including duplicates). Does not remove items in the DB that are not in the import set. false
SCHEMA_SYNC_DATA_ONLY (optional) Only sync data. Does not sync the schema (schema.json or the split schema). false

CI Commands

Besides auto importing and exporting, you can also run the commands manually.

npx directus schema-sync [command]

Command Description
export Export the schema and data from the Directus API
import Import the schema and data to the Directus API (options: merge, data)
hash Recalculate the hash for all the data files (already happens after export)
install Install the extension's columns in the database and add the config folder (options: force)
export-schema Export only the schema (options: --split <boolean>)
import-schema Import only the schema

Migrating from V2 to V3

Update the schema-sync/directus_config.js file with the following:

Replace directus_roles Add directus_policies Replace directus_permissions Add directus_access

…
    directus_roles: {
        watch: ['roles'],
        linkedFields: ['parent'],
        query: {
            sort: ['name'],
        },
    },
    directus_policies: {
        watch: ['policies'],
        query: {
            sort: ['name'],
        },
    },
    directus_permissions: {
        watch: ['permissions', 'collections', 'fields'],
        excludeFields: ['id'],
        getKey: o => `${o.policy}-${o.collection}-${o.action}`,
        query: {
            sort: ['policy', 'collection', 'action'],
        },
    },
    directus_access: {
        watch: ['access'],
        excludeFields: ['id'],
        getKey: o => `${o.role ?? o.user ?? 'public'}-${o.policy}`,
        query: {
            sort: ['role', 'policy'],
            filter: {
                user: { _null: true },
            },
        },
    },
…

Contributing

Contributions are welcome. Please open an issue or pull request.

View changelog for more information. CHANGELOG.md

changelog

Version 3.0.8

  • Fixed Slight performance improvement when importing data.

Version 3.0.7

  • Fixed SCHEMA_SYNC_DATA_ONLY being the opposite of what it should be.

Version 3.0.6

  • Added Way to only import data and not the schema, for cases where you use something else to migrate your schema.
    • Set SCHEMA_SYNC_DATA_ONLY=true in your environment file.
    • Or when using import command, use --data option.

Version 3.0.5

  • Added SCHEMA_SYNC_MERGE option to environment variables
    • Only insert and update items found in the import set (including duplicates). Does not remove items in the DB that are not in the import set.
  • Fixed issue where duplicate items were not being deleted when importing when --merge was used.
  • Fixed order of deleting duplicates before inserting new items.

Version 2.1.2

  • Remove old schema files when generating new schema files.
    • This is to remove files of deleted collections.

Version 2.1.1

  • Outputs additional helpful information when error occurs.
    • Link to an issue when trying to import empty files.

Version 2.1.0

  • Added groupBy parameter to collection options
    • (optional) array of fields to group the exported data into multiple files, eg. ['collection'] (per collection)
    • This is useful when you have a large amount of data in a collection (such as directus_permissions) and want to split it up into multiple files.

Version 2.0.0 ⚠️ Breaking change, due to new feature

By default will split schema file up into multiple files per collection

  • Why? This is to make it easier to manage the schema files in git, as well as to make it easier to work with the schema files in general.

  • How? The schema files will be split up into multiple files per collection. The main file will be named schema.json and will contain a flag stating if it is partial (split). The collection files will be named after the collection name, and will contain the schema for that collection. All collection files will be placed in schema-sync/data/schema.

  • What do I need to do?

    • If you have any custom scripts that rely on the schema file, you will need to update them to work with the new structure.
    • You will also need to export the schema again to get the new structure.
    • Add the new schema files to git.
  • What if I don't want this? You can set SCHEMA_SYNC_SPLIT=false in your environment file to disable this feature.

Version 1.6.4

  • Update hash and timestamp after manually triggering import via cli.
    • This will also force reset the lock if any errors occurred during an earlier import.

Version 1.6.3

  • Add linkedFields to fix inserting ordered items that might depend on each other.
    • Specifically fixes importing of flow operations, update the directus_config and add linkedFields.
      {
      directus_operations: {
        watch: ['operations'],
        excludeFields: ['user_created'],
        linkedFields: ['resolve', 'reject'],
        query: {
          filter: {
            flow: { trigger: { _neq: 'webhook' } },
          },
        },
      },
      }
  • Also fix auto IMPORT issue when mv_ts is null.

Version 1.6.2

  • (postgres only) Fixed import issue due to default_value containing functions for auto increment

Version 1.6.1

  • Fixed error thrown when installing config folder without --force
  • Fixed installing of config folder

Version 1.5.0 ⚠️

  • Sorts exported object keys
    • Fixes issue where the order of the exported object keys would change between exports, causing unnecessary changes in git.
  • merge option fixed
    • The merge option was introduced in version 1.3.0, but it was not working as intended. This has now been fixed.

Version 1.4.2

  • Add import-schema and export-schema commands to import/export only the schema.

Version 1.4.1

  • Fixed config for directus_presets getKey should be ${o.role ?? 'all'}-${o.collection}-${o.bookmark || 'default'} instead of ${o.role ?? 'all'}-${o.collection}-${o.name || 'default'}

Version 1.4.0

  • Replaced cli command for install from npx schema-sync install to npx directus schema-sync install.
    • This way we directly create the required columns in the directus_settings table.
    • NOTE: If you have installed before, you can now remove the migration file from your migrations folder.
  • Added config for directus_presets to sync global presets.

Version 1.3.1

  • Fix bug where process returns early without importing all data, when using onImport.

Version 1.3.0

  • Add --merge option to import command in order to upsert data only and not delete other data.
  • Add onImport and onExport hooks to allow for custom logic to be run before items are imported/exported.
    • Can be used to encode or decode data before it is imported/exported.
    • Return null to skip the item.
  • Fixed invalid field issue due to memory leak.

Version 1.2.2

  • Sort automatically by sort field first with fallback to primary key.

Version 1.2.1 ⚠️

  • NOTE This update will remove duplicate rows if the same key matches multiple rows.
    • This is to fix an issue where the same permission was imported multiple times.
  • Change order in which deletions work.
    • This fixes an issue where a collection with a relation to another collection would fail to import due to the relation being a constraint.
  • Add try/catch to use best-effort when importing data.

Version 1.2.0

  • Excluding alias fields by default.

    • Benefit Reduces the amount of fields you have to add to the exclude list.

    • Why? Since alias fields don't exist in the DB, they often end up being an array containing the ids of the related items. Since you should be exporting the related items anyways with the foreign key fields, this is both redundant and causes issues when importing.

Version 1.1.7

  • Fix order in which tasks are exported and imported. Specifically crucial for fields and relations.
  • Fix issue for dynamic import of config on windows systems. Update logging to reflect amount of items being imported/exported.

Version 1.1.6

  • Switch from using path.join to path.resolve to use absolute paths as required by Windows.

Version 1.1.5

  • Set query limit to -1, unless manually set in config.js inside the query option.
    • This fixes an issue with not all permissions being fetched.

Version 1.1.4

  • Add optional prefix option to differentiate between different sets of data.
    • Prefix can be set on the collection configuration in config.js eg. test or prod.

Version 1.1.3

  • Fix issue with syncing across servers with different timezones.

Version 1.1.2

  • Add hash command, to regenerate hash for all data files.
  • Add delay when reinstalling Schema Sync