### Installation Setup with UpdateManager Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Sets up the installation process for schema synchronization. This involves ensuring the system is installed, copying configuration, exporting data, and committing updates if a new export meta is available. ```typescript // Called by: directus schema-sync install await updateMgr.ensureInstalled(); await copyConfig(false, { logger }); await exportManager().exportAll(); const meta = await ExportHelper.updateExportMeta(); if (meta) { await updateMgr.commitUpdates(); } ``` -------------------------------- ### Integration Example: ExportManager Setup and Usage Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-exportmanager.md Demonstrates how to create an ExportManager, add schema and collection exporters, load initial data, attach watchers, and perform manual exports. ```typescript import { ExportManager } from './exportManager'; import { SchemaExporter } from './schemaExporter'; import { CollectionExporter } from './collectionExporter'; // Create manager const manager = new ExportManager(logger, () => { schema = null; }); // Add schema exporter manager.addExporter({ watch: ['collections', 'fields', 'relations'], exporter: new SchemaExporter(getSchemaService, logger), }); // Add collection exporters const syncConfigs = { directus_roles: { watch: ['roles'], query: { sort: ['name'] } }, directus_dashboards: { watch: ['dashboards'] }, }; manager.addCollectionExporter(syncConfigs, getItemsService); // On startup: import if needed await manager.loadAll(false); // Then watch for changes manager.attachAllWatchers(action, updateMeta); // Or export everything manually await manager.exportAll(); ``` -------------------------------- ### Complete Sync Workflow Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Demonstrates a full schema synchronization process, including loading configuration, checking export state, comparing items, and updating metadata. Requires setup with Directus services and a database connection. ```typescript import { ExportHelper, nodeImport, ADMIN_ACCOUNTABILITY, sortObject, deepEqual, getDiff, } from './utils'; // Load configuration const configDir = ExportHelper.schemaDir; const config = await nodeImport(configDir, 'config.js'); const { syncCustomCollections } = config; // Check current export state const meta = await ExportHelper.getExportMeta(); if (!meta) { console.log('No prior export, creating new one'); } // Create services with admin privileges const itemsSvc = new ItemsService('posts', { accountability: ADMIN_ACCOUNTABILITY, schema: currentSchema, knex: database, }); // Compare items const dbItem = { id: 1, title: 'Original', status: 'draft' }; const fileItem = { id: 1, title: 'Original', status: 'published' }; const changes = getDiff(fileItem, dbItem); if (changes) { console.log('Differences:', changes); await itemsSvc.updateOne(dbItem.id, changes); } // Ensure sorted output const output = sortObject({ z: [3, 1, 2], a: { c: 1, b: 0 }, }); console.log(JSON.stringify(output, null, 2)); // Update metadata const newMeta = await ExportHelper.updateExportMeta(); if (newMeta) { console.log(`Export hash: ${newMeta.hash}`); } ``` -------------------------------- ### Install Directus Schema Sync via NPM Source: https://github.com/bcc-code/directus-schema-sync/blob/main/README.md Install the schema-sync package using NPM and run the install command to set up the extension. ```bash npm install directus-extension-schema-sync directus schema-sync install ``` -------------------------------- ### Basic Schema Exporter Setup Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md Demonstrates the basic setup for initializing the SchemaExporter and performing export and load operations. ```typescript import { SchemaExporter } from './schemaExporter'; const exporter = new SchemaExporter( getSchemaService, logger, { split: true, safe: false } ); // Export current database schema await exporter.export(); // Later, import schema from file await exporter.load(); ``` -------------------------------- ### Production Deployment of Directus Schema Sync Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md This example demonstrates how to deploy Directus schema changes to a production environment using Docker. It covers building the Docker image with schema files and either auto-importing on container start or manually triggering the import. ```bash # 1. Build Docker image with schema files # Dockerfile: # COPY ./schema-sync /directus/schema-sync # docker-compose.yaml: # volumes: # - ./schema-sync:/directus/schema-sync # 2. On container start, auto-import (SCHEMA_SYNC=IMPORT in .env) # OR manually trigger: npx directus schema-sync import # 3. Verify import (check logs) # Look for: "Schema updated" or "Schema is already up-to-date" # 4. Optionally verify no changes remain npx directus schema-sync export-schema # If no changes in git, all is synced ``` -------------------------------- ### Execute Directus Schema Sync Install Command Source: https://github.com/bcc-code/directus-schema-sync/blob/main/README.md Run the install command to set up the extension's database columns and configuration folder. Use `--force` to overwrite existing files. ```bash // docker exec -it docker compose exec -it my-directus npx directus schema-sync install --force ``` -------------------------------- ### Verbose Schema Export and Import Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md A detailed example demonstrating the setup and usage of SchemaExporter for both exporting a schema from a development database and importing it into a production environment. It highlights the 'safe' mode for import, which filters out deletes. ```typescript import { SchemaExporter } from './schemaExporter'; // Setup const exporter = new SchemaExporter( async () => new SchemaService({ schema, database, accountability }), logger, { split: true, safe: true } ); // Export schema from development database console.log('Exporting schema...'); await exporter.export(); // Creates: schema-sync/data/schema.json (metadata) // schema-sync/data/schema/users.json // schema-sync/data/schema/posts.json // etc. // Later, import to production console.log('Importing schema...'); await exporter.load(); // Reads all files, computes diff vs current production schema // Filters out deletes (safe mode) // Applies only creates/updates // Logs: "Schema updated" or "Schema is already up-to-date" console.log('Done!'); ``` -------------------------------- ### Build and Start Docker Compose Source: https://github.com/bcc-code/directus-schema-sync/blob/main/test/README.md Builds the Docker image and starts the services defined in docker-compose.yml. Navigate to the 'test' directory before running. ```bash cd test docker-compose up --build ``` -------------------------------- ### Install Extension via NPM Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md Use this command to install the `directus-extension-schema-sync` package from the NPM registry. ```bash npm install directus-extension-schema-sync ``` -------------------------------- ### Customized Directus System Collection Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md An example of `schema-sync/directus_config.js` demonstrating customization for your Directus setup. It shows how to enable specific collections (roles, permissions, settings), exclude certain data (admin role permissions), and skip others by commenting them out. ```javascript export const syncDirectusCollections = { // Enable roles directus_roles: { watch: ['roles'], linkedFields: ['parent'], query: { sort: ['name'] }, }, // Enable permissions but exclude admin role directus_permissions: { watch: ['permissions', 'collections', 'fields'], excludeFields: ['id'], getKey: o => `${o.policy}-${o.collection}-${o.action}`, query: { filter: { policy: { _nin: ['admin'] } }, sort: ['policy', 'collection', 'action'], }, }, // Skip dashboards (comment out) // directus_dashboards: { ... }, // Add settings directus_settings: { watch: ['settings'], excludeFields: ['mv_hash', 'mv_ts', 'mv_locked', 'project_url'], }, }; ``` -------------------------------- ### One-Way Import Flow Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Demonstrates a production setup for one-way data import. Schema and data are imported on Directus startup, but automatic exports are disabled, requiring manual exports via CLI. ```bash SCHEMA_SYNC=IMPORT ``` -------------------------------- ### Install Extension via Docker Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md This Dockerfile snippet shows how to install the schema-sync extension within a Docker image, including package installation and copying local files. ```dockerfile RUN pnpm install directus-extension-schema-sync COPY ./schema-sync /directus/schema-sync ``` -------------------------------- ### Install Schema Sync Extension Source: https://github.com/bcc-code/directus-schema-sync/blob/main/test/README.md Executes the schema sync install command within the running Directus container. Use --force to overwrite existing configurations if necessary. ```bash docker-compose exec directus npx directus schema-sync install --force ``` -------------------------------- ### Example Exporter Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Example configuration for an `IExporterConfig`. This links the 'collections', 'fields', and 'relations' to a `SchemaExporter` instance. ```typescript const config: IExporterConfig = { watch: ['collections', 'fields', 'relations'], exporter: new SchemaExporter(getSchemaService, logger), }; ``` -------------------------------- ### Example User-Defined Collection Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md An example of `schema-sync/config.js` demonstrating how to configure synchronization for 'posts' and 'categories' collections. It includes options for filtering, sorting, excluding fields, defining linked fields, and custom export logic. ```javascript export const syncCustomCollections = { posts: { watch: ['posts.items'], excludeFields: ['user_created', 'user_updated', 'content_draft'], linkedFields: ['parent'], query: { filter: { published: { _eq: true } }, sort: ['published_at'], }, onExport: async (item, srv) => { // Redact sensitive content item.internal_notes = null; return item; }, }, categories: { watch: ['categories.items'], groupBy: ['type'], // Separate files per type query: { sort: ['type', 'name'] }, }, }; ``` -------------------------------- ### Implement Custom Exporter Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Example of a custom exporter implementation for a specific collection. This demonstrates how to define the `name`, `export`, and `load` methods according to the `IExporter` interface. ```typescript const customExporter: IExporter = { name: 'my_collection', export: async () => { /* write to file */ }, load: async (merge) => { /* read from file and sync database */ return async () => { /* cleanup */ }; }, }; ``` -------------------------------- ### Directus Multi-Instance Synchronization Flow: Two Instances Starting Up Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Illustrates the sequence of operations when two Directus instances start simultaneously. Instance A acquires a lock, performs an import, and commits updates, while Instance B detects the existing metadata and skips its import. ```text Instance A (boots first) Instance B (boots second) ├─ Read export meta │ └─ hash=abc123, ts=2024-01-01 ├─ Call lockForUpdates() │ └─ Check: new hash != db hash? ✓ │ └─ Check: new ts > db ts? ✓ │ └─ Acquire lock ✓ │ └─ Set mv_locked=true ✓ ├─ Import schema/data └─ commitUpdates() └─ Set mv_hash=abc123 └─ Set mv_ts=2024-01-01 └─ Set mv_locked=false ├─ Read export meta │ └─ hash=abc123, ts=2024-01-01 ├─ Call lockForUpdates() │ └─ Check: new hash != db hash? ✗ │ (A already set it) │ └─ Return false ├─ Skip import (already done) └─ Continue startup ``` -------------------------------- ### Verify Directus Schema Sync Installation Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md Command to check if the Directus Schema Sync is installed and its configuration folder exists. It should indicate if the folder already exists or create it if it's a fresh install. ```bash # Check columns exist npx directus schema-sync install # Should print: "Config folder already exists" # (or create if fresh install) ``` -------------------------------- ### Directus Schema Sync Extension Lifecycle Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Outlines the steps involved in installing, configuring, and running the Directus Schema Sync extension, including its initialization and runtime behavior. ```text 1. Installation npm install directus-extension-schema-sync npx directus schema-sync install 2. Configuration Edit schema-sync/config.js and directus_config.js 3. Hook Registration Directus loads extension hook on startup 4. Initialization Phase - Parse environment variables - Create service factories - Register action/init handlers 5. Runtime - If SCHEMA_SYNC=IMPORT: import on app.before - If SCHEMA_SYNC=EXPORT: watch database for changes - If SCHEMA_SYNC=BOTH: both import and export 6. CLI Commands npx directus schema-sync [export|import|install|hash] ``` -------------------------------- ### ExportCollectionConfig Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Provides a practical example of how to configure `ExportCollectionConfig` for different collections, specifying watch paths, query parameters, and fields to exclude. ```typescript const config: ExportCollectionConfig = { directus_roles: { watch: ['roles'], query: { sort: ['name'] }, }, custom_posts: { watch: ['posts.items'], excludeFields: ['content_draft'], linkedFields: ['parent'], groupBy: ['status'], onExport: async (item) => { item.description = 'redacted'; return item; }, }, }; ``` -------------------------------- ### Full Sync Flow Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Illustrates the development workflow for a full schema and data synchronization. This flow enables automatic schema and data import on Directus startup and automatic exports on database changes. ```bash SCHEMA_SYNC=BOTH ``` -------------------------------- ### Install Directus Schema Sync via Docker Source: https://github.com/bcc-code/directus-schema-sync/blob/main/README.md Add the schema-sync extension to your Directus Dockerfile and configure volumes for persistent storage of configuration files. ```dockerfile RUN pnpm install directus-extension-schema-sync # This is for when building for production COPY ./schema-sync ./schema-sync ``` ```yaml // docker-compose.yaml volumes: - ./schema-sync:/directus/schema-sync ``` -------------------------------- ### Basic Collection Export and Import Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-collectionexporter.md Demonstrates the basic setup for exporting and then importing data for a collection. Use this for straightforward data synchronization tasks. ```typescript import { CollectionExporter } from './collectionExporter'; const exporter = new CollectionExporter( 'posts', getItemsService, { excludeFields: ['user_created', 'user_updated'], query: { sort: ['title'] }, }, logger ); await exporter.export(); // Export posts to file const finishUp = await exporter.load(false); // Import posts from file if (finishUp) await finishUp(); ``` -------------------------------- ### Production Schema Exporter Setup (Safe Mode) Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md Illustrates how to configure the SchemaExporter for production environments using safe mode, ensuring only creates and updates are applied during load operations. ```typescript const exporter = new SchemaExporter( getSchemaService, logger, { split: true, safe: true } ); // Imports will never delete collections/fields/relations // Only creates and updates are applied await exporter.load(); ``` -------------------------------- ### Clear Sync State (Reset to Fresh Install) Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Resets the schema sync settings to their initial state, effectively simulating a fresh installation. This clears the hash, sets a default timestamp, and unlocks the system. ```sql UPDATE directus_settings SET mv_hash = '', mv_ts = '2020-01-01', mv_locked = false WHERE id = 1; ``` -------------------------------- ### Define Custom Collections in test_config.js Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Example of a custom configuration file defining sync behavior for specific collections, including watch triggers and queries. ```javascript export const syncCustomCollections = { test_users: { watch: ['test_users.items'], query: { limit: 10 }, }, }; ``` -------------------------------- ### Complete Collection Export Configuration Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Demonstrates how to define an export configuration for a collection, including watch triggers, field exclusions, linked fields, grouping, custom queries, and on-export/on-import hooks for data transformation. Shows instantiation and usage of CollectionExporter. ```typescript // Define export configuration const config: ExportCollectionConfig = { posts: { watch: ['posts.items'], excludeFields: ['draft_content'], linkedFields: ['parent'], // For nested posts groupBy: ['status'], // Separate files per status query: { filter: { published: { _eq: true } }, sort: ['published_at'], limit: 1000, }, onExport: async (item, srv) => { // Encrypt sensitive fields item.secret = await encrypt(item.secret); return item; }, onImport: async (item, srv) => { // Decrypt sensitive fields item.secret = await decrypt(item.secret); return item; }, }, }; // Create exporter const exporter = new CollectionExporter('posts', getItemsService, config.posts, logger); // Export await exporter.export(); // Writes to schema-sync/data/posts.json and grouped files // Import const finishUp = await exporter.load(false); if (finishUp) { await finishUp(); // Cleanup/deletions } ``` -------------------------------- ### ToUpdateItemDiff Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Demonstrates how to construct a `ToUpdateItemDiff` object and use it to update a single item via the `itemsSvc.updateOne` method. ```typescript const update: ToUpdateItemDiff = { pkey: 1, diff: { status: 'published', updated_at: '2024-01-15' } }; await itemsSvc.updateOne(update.pkey, update.diff); ``` -------------------------------- ### Directus Items Service Usage Example Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/types.md Demonstrates common operations using the `IItemsService` interface, including creating, reading, updating, and deleting items. Assumes `getItemsService` is available to retrieve an instance. ```typescript const itemsSvc: IItemsService = await getItemsService('posts'); // Create const id = await itemsSvc.createOne({ title: 'New Post' }); // Read const post = await itemsSvc.readOne(id); const allPosts = await itemsSvc.readByQuery({ filter: { status: { _eq: 'published' } }, sort: ['created_at'], limit: 10 }); // Update await itemsSvc.updateOne(id, { status: 'published' }); // Delete await itemsSvc.deleteOne(id); ``` -------------------------------- ### Run Docker Compose with Environment Variable Source: https://github.com/bcc-code/directus-schema-sync/blob/main/test/README.md Starts the Docker Compose services, setting the SCHEMA_SYNC environment variable. This is useful for configuring the extension's behavior during startup. ```bash SCHEMA_SYNC=BOTH docker-compose up ``` -------------------------------- ### Setup Export Watcher Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md Attaches database change listeners for the export phase if SCHEMA_SYNC is set to 'BOTH' or 'EXPORT'. This ensures that changes are watched and processed. ```typescript // Attach database change listeners if (env.SCHEMA_SYNC === 'BOTH' || env.SCHEMA_SYNC === 'EXPORT') { exportManager().then(expMng => { expMng.attachAllWatchers(action, updateMeta); }); } ``` -------------------------------- ### Register Init Event for CLI Command Setup Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md This snippet registers a 'cli.before' init event listener. It's used to set up custom CLI commands, such as registering the 'schema-sync' command and its subcommands like 'export' and 'import'. ```typescript init('cli.before', async ({ program }) => { const dbCommand = program.command('schema-sync'); dbCommand.command('export').action(async () => { ... }); dbCommand.command('import').action(async () => { ... }); // etc. }); ``` -------------------------------- ### Get Hash File Path Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Retrieves the absolute path to the schema-sync/hash.txt metadata file. This file tracks the current export state. ```typescript static get hashFile(): string ``` ```typescript const file = ExportHelper.hashFile; // Returns: /path/to/project/schema-sync/hash.txt ``` -------------------------------- ### Development Workflow for Directus Schema Sync Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md This sequence of commands outlines a typical development workflow for managing Directus schema and configuration files. It includes installation, configuration edits, exporting, committing, pulling changes on another machine, and importing. ```bash # 1. Initial setup npx directus schema-sync install # 2. Edit config files # (Edit schema-sync/config.js and directus_config.js) # 3. Restart Directus (auto-export if SCHEMA_SYNC=BOTH) # OR manually export npx directus schema-sync export # 4. Commit to git git add schema-sync/ git commit -m "Update schema and configuration" # 5. On other machine, pull changes git pull # 6. Import changes npx directus schema-sync import ``` -------------------------------- ### Development Custom Collections Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Defines synchronization settings for custom collections like posts and categories. Use this for development setups. ```javascript export const syncCustomCollections = { posts: { watch: ['posts.items'], excludeFields: ['user_created', 'user_updated'], linkedFields: ['parent'], query: { sort: ['published_at'] }, }, categories: { watch: ['categories.items'], query: { sort: ['name'] }, }, }; ``` -------------------------------- ### Data Transformation with Export/Import Hooks Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Provides an example of transforming data during export and import operations using `onExport` and `onImport` hooks. This allows for custom data manipulation, such as encryption and decryption. ```javascript // config.js export const syncCustomCollections = { users: { watch: ['users.items'], onExport: async (item, srv) => { item.email = encrypt(item.email); return item; }, onImport: async (item, srv) => { item.email = decrypt(item.email); return item; }, }, }; ``` -------------------------------- ### Register Init Event for Schema/Data Import Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md This snippet registers an 'app.before' init event listener. It's used to import schema and data from files when the Directus app is initializing, before the HTTP server starts. It includes a lock mechanism to prevent concurrent updates. ```typescript init('app.before', async () => { // Import schema/data from files if (await updateManager.lockForUpdates(meta.hash, ts)) { await exporter.loadAll(); await updateManager.commitUpdates(); } }); ``` -------------------------------- ### Ensure Schema Sync Columns Installed Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Ensures that the necessary database columns (`mv_hash`, `mv_ts`, `mv_locked`) for schema synchronization are present in the `directus_settings` table. This method creates them if they do not already exist. ```typescript public async ensureInstalled(): Promise ``` ```typescript table.string('mv_hash').defaultTo('').notNullable(); table.timestamp('mv_ts', { useTz: true }).defaultTo('2020-01-01').notNullable(); table.boolean('mv_locked').defaultTo(false).notNullable(); ``` ```typescript await updateManager.ensureInstalled(); console.log('Schema sync columns ready'); ``` -------------------------------- ### Grouped Export Main File JSON Content Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-collectionexporter.md Example JSON structure for the main file in a grouped export. Indicates that the export is partial and specifies the grouping field. ```json { "partial": true, "groupedBy": ["status"], "count": 100 } ``` -------------------------------- ### Register Directus Schema Sync Hook Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md This TypeScript code demonstrates the complete registration flow for a Directus hook, including setup for import, export, and CLI functionalities. It initializes managers and services, conditionally sets up import logic based on environment variables, attaches watchers for export, and registers CLI commands. ```typescript // 1. REGISTRATION PHASE const registerHook: HookConfig = async ({ action, init }, { env, services, database, getSchema, logger }) => { // Setup factories and managers const updateManager = new UpdateManager(database); let schema: SchemaOverview | null = null; let _exportManager: ExportManager; const getSchemaService = async () => new SchemaService({...}); const getItemsService = async (coll) => new ItemsService(coll, {...}); // 2. IMPORT PHASE (if configured) if (env.SCHEMA_SYNC === 'IMPORT' || env.SCHEMA_SYNC === 'BOTH') { init('app.before', async () => { // App is starting up // Check if new export exists // If yes and no lock held, acquire lock and import // Release lock or commit }); } // 3. EXPORT SETUP PHASE if (env.SCHEMA_SYNC === 'EXPORT' || env.SCHEMA_SYNC === 'BOTH') { // Attach watchers to listen for changes exportManager().then(expMng => { expMng.attachAllWatchers(action, updateMeta); }); } // 4. CLI SETUP PHASE init('cli.before', async ({ program }) => { // Register schema-sync command // Register export, import, install, hash subcommands }); }; export default registerHook; ``` -------------------------------- ### Load Configuration Files at Runtime Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md Demonstrates loading Directus configuration files dynamically at runtime, including optional custom configurations based on environment variables. ```typescript const { syncDirectusCollections } = await nodeImport( ExportHelper.schemaDir, 'directus_config.js' ); const { syncCustomCollections } = await nodeImport( ExportHelper.schemaDir, 'config.js' ); // Optional additional config if (env.SCHEMA_SYNC_CONFIG) { const { syncCustomCollections: additional } = await nodeImport( ExportHelper.schemaDir, env.SCHEMA_SYNC_CONFIG ); if (additional) { exportMng.addCollectionExporter(additional, getItemsService); } } ``` -------------------------------- ### Get Data Directory Path Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Retrieves the absolute path to the schema-sync/data directory. Use this to access exported data files. ```typescript static get dataDir(): string ``` ```typescript const dir = ExportHelper.dataDir; // Returns: /path/to/project/schema-sync/data ``` -------------------------------- ### Initialize Hook Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md Sets up environment variables, factories, services, and the export manager during hook initialization. This block runs when Directus loads the extension. ```typescript const registerHook: HookConfig = async ({ action, init }, { ... }) => { // This block runs when Directus loads the extension // 1. Parse environment variables const schemaOptions = { split: typeof env.SCHEMA_SYNC_SPLIT === 'boolean' ? env.SCHEMA_SYNC_SPLIT : true, safe: !!env.SCHEMA_SYNC_SAFE, }; // 2. Set up factories and services const getSchemaService = async () => new SchemaService({ ... }); const getItemsService = async (collectionName) => new ItemsService(...); const updateManager = new UpdateManager(database); // 3. Define async factory for exporters const createExportManager = async (dataOnly = false) => { const exportMng = new ExportManager(logger); exportMng.addExporter({ ... }); // Add schema exporter exportMng.addCollectionExporter(syncDirectusCollections, getItemsService); exportMng.addCollectionExporter(syncCustomCollections, getItemsService); return exportMng; }; } ``` -------------------------------- ### Get Schema Directory Path Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Retrieves the absolute path to the schema-sync directory. Use this to access project-specific schema files. ```typescript static get schemaDir(): string ``` ```typescript const dir = ExportHelper.schemaDir; // Returns: /path/to/project/schema-sync ``` -------------------------------- ### Condensed Execution for Rapid Changes Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Demonstrates how multiple rapid database changes are consolidated into a single export action using `condenseAction()` to improve performance. ```text change 1 → condenseAction → EXPORT change 2 → queue change 3 → queue [export completes] → EXPORT (consolidated) ``` -------------------------------- ### ensureInstalled Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Ensures that the necessary schema synchronization columns (`mv_hash`, `mv_ts`, `mv_locked`) exist in the `directus_settings` table. If they do not exist, this method creates them. ```APIDOC ## ensureInstalled ### Description Creates the schema sync columns in `directus_settings` table if they don't exist. ### Method Signature ```typescript public async ensureInstalled(): Promise ``` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Returns - `true` if columns were created; `false` if already existed ### Behavior 1. Checks if `mv_hash` column exists 2. If not, creates three new columns: - `mv_hash` (string): SHA256 hash of export state - `mv_ts` (timestamp): ISO 8601 timestamp of export - `mv_locked` (boolean): Lock flag 3. All columns have defaults and `NOT NULL` constraints ### Columns Added: ```typescript table.string('mv_hash').defaultTo('').notNullable(); table.timestamp('mv_ts', { useTz: true }).defaultTo('2020-01-01').notNullable(); table.boolean('mv_locked').defaultTo(false).notNullable(); ``` ### Called by: `schema-sync install` CLI command ### Example ```typescript await updateManager.ensureInstalled(); console.log('Schema sync columns ready'); ``` ``` -------------------------------- ### Update timestamps during import Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md The onImport hook can be used to automatically set or update timestamps for items being imported. This example sets a 'last_imported_at' timestamp. ```javascript export const syncCustomCollections = { posts: { watch: ['posts.items'], onImport: async (item, srv) => { // Set import timestamp item.last_imported_at = new Date().toISOString(); return item; }, }, }; ``` -------------------------------- ### Single File Export JSON Content Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-collectionexporter.md Example JSON structure for a single file export when no grouping is applied. Contains an array of items. ```json [ { "id": 1, "name": "Item 1" }, { "id": 2, "name": "Item 2" } ] ``` -------------------------------- ### Development Directus Collections Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Defines synchronization settings for Directus system collections like roles and permissions. Use this for development setups. ```javascript export const syncDirectusCollections = { directus_roles: { watch: ['roles'], linkedFields: ['parent'], 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_dashboards: { watch: ['dashboards'], excludeFields: ['user_created', 'date_created'], }, directus_settings: { watch: ['settings'], excludeFields: ['mv_hash', 'mv_ts', 'mv_locked', 'project_url'], }, }; ``` -------------------------------- ### ExportHelper.hashFile Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Provides the absolute path to the 'schema-sync/hash.txt' metadata file. This is a static getter. ```APIDOC ## ExportHelper.hashFile ### Description Provides the absolute path to `schema-sync/hash.txt` (metadata file tracking current export state). ### Method `static get hashFile(): string` ### Returns `string` - The absolute path to the `schema-sync/hash.txt` file. ### Example ```typescript const file = ExportHelper.hashFile; // Returns: /path/to/project/schema-sync/hash.txt ``` ``` -------------------------------- ### Multi-Step Sync with Verification for Directus Schema Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md This command sequence details a robust synchronization process for Directus schemas and data, including export, manual review, import, and verification steps. It ensures schema consistency before and after data import. ```bash # 1. Export schema only npx directus schema-sync export-schema # 2. Review schema changes git diff schema-sync/schema/ read -p "Approve schema changes? (y/n)" -n 1 [[ $REPLY =~ ^[Yy]$ ]] || exit 1 # 3. Import schema npx directus schema-sync import-schema # 4. Verify schema is consistent npx directus schema-sync export-schema git diff schema-sync/schema/ > /dev/null || \ { echo "Schema not consistent after import!"; exit 1; } # 5. Import data npx directus schema-sync import --data # 6. Final verification npx directus schema-sync export echo "Sync complete!" ``` -------------------------------- ### Directus Filter: Exclude Specific Roles Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Example of filtering Directus roles to exclude those with specific names, such as 'Administrator' or 'Guest'. This snippet utilizes the `_nin` (not in) operator. ```javascript // Exclude specific roles export const syncDirectusCollections = { directus_roles: { watch: ['roles'], query: { filter: { name: { _nin: ['Administrator', 'Guest'] }, }, }, }, }; ``` -------------------------------- ### Default Directus System Collection Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md This is a sample of the default content for `schema-sync/directus_config.js`. It shows how to configure synchronization for common Directus system collections like roles, permissions, and dashboards, including options for `watch`, `excludeFields`, `getKey`, and `query`. ```javascript export const syncDirectusCollections = { directus_roles: { watch: ['roles'], linkedFields: ['parent'], 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_dashboards: { watch: ['dashboards'], excludeFields: ['user_created', 'date_created'], query: { sort: ['name'] }, }, }; ``` -------------------------------- ### Get Schema File Path Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md Constructs the full path to a schema file for a specific collection. The generated path follows the pattern `schema-sync/data/schema/{collection}.json`. ```typescript protected schemaFilesPath(collection: string): string ``` -------------------------------- ### SchemaExporter Constructor Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md Initializes a new instance of the SchemaExporter. It requires a function to get the SchemaService, a logger instance, and optional configuration for splitting schemas and safe mode. ```APIDOC ## Constructor SchemaExporter ### Description Initializes a new instance of the SchemaExporter. It requires a function to get the SchemaService, a logger instance, and optional configuration for splitting schemas and safe mode. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `getSchemaService` | `() => Promise` | — | Function that returns the Directus SchemaService | | `logger` | `ApiExtensionContext['logger']` | — | Logger instance | | `options.split` | `boolean` | `true` | If `true`, save schema as per-collection files; if `false`, save as single file | | `options.safe` | `boolean` | `false` | If `true`, filter out destructive (DELETE) operations from diffs | ``` -------------------------------- ### ExportHelper.dataDir Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Provides the absolute path to the 'schema-sync/data' directory. This is a static getter. ```APIDOC ## ExportHelper.dataDir ### Description Provides the absolute path to the `schema-sync/data` directory. ### Method `static get dataDir(): string` ### Returns `string` - The absolute path to the `schema-sync/data` directory. ### Example ```typescript const dir = ExportHelper.dataDir; // Returns: /path/to/project/schema-sync/data ``` ``` -------------------------------- ### Directus Filter: Export Specific Users Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Example of using Directus filter syntax to export only specific users by their IDs. This snippet demonstrates the `_in` operator for filtering. ```javascript // Exported users export const syncDirectusCollections = { directus_users: { watch: ['users'], query: { filter: { id: { _in: ['uuid1', 'uuid2'] }, // Specific users }, }, }, }; ``` -------------------------------- ### Hook API: Action and Init Functions Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md Provides functions to register event listeners for database actions and initialization events within the Directus lifecycle. ```typescript { action: (event: string, handler: ActionHandler) => void, init: (event: string, handler: InitHandler) => void } ``` -------------------------------- ### Standard Import Flow with UpdateManager Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Demonstrates the standard flow for importing schema and data using UpdateManager. It includes acquiring a lock, loading schema and data, and committing updates. Ensure necessary imports and a database instance are available. ```typescript import { UpdateManager } from './updateManager'; import { ExportHelper } from './utils'; const updateMgr = new UpdateManager(database); // Get latest export state const meta = await ExportHelper.getExportMeta(); if (!meta) { logger.info('No export found, skipping sync'); return; } // Try to acquire lock if (await updateMgr.lockForUpdates(meta.hash, meta.ts)) { try { logger.info(`Syncing with hash: ${meta.hash}`); // Load schema and data const exporter = await createExportManager(); await exporter.loadAll(false); // Commit the sync await updateMgr.commitUpdates(); logger.info('Sync complete'); } catch (error) { logger.error('Sync failed:', error); await updateMgr.releaseLock(); throw error; } } else { logger.info('Could not acquire lock (another instance syncing or no changes)'); } ``` -------------------------------- ### Development Environment Variables Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Configure schema sync for bidirectional synchronization during development. Set SCHEMA_SYNC to BOTH. ```env SCHEMA_SYNC=BOTH SCHEMA_SYNC_SPLIT=true SCHEMA_SYNC_SAFE=false SCHEMA_SYNC_MERGE=false SCHEMA_SYNC_DATA_ONLY=false ``` -------------------------------- ### Directus Extension Bundle Structure Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md This shows the typical file structure of a compiled Directus extension bundle, including the compiled hook entry point and other source files. ```text dist/ ├── index.js # Compiled hook entry point └── [other files] # Compiled source files ``` -------------------------------- ### Manual Schema Export Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Command to manually export the Directus schema, creating a JSON schema file and individual files per collection. This is useful for initial setup or manual synchronization. ```bash npx directus schema-sync export-schema --split # Creates schema-sync/data/schema.json + per-collection files git diff schema-sync/data/ ``` -------------------------------- ### Constructor Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-collectionexporter.md Initializes a new instance of the CollectionExporter class. ```APIDOC ## Constructor Initializes a new instance of the CollectionExporter class. ### Parameters - **collectionName** (string) - Required - Name of the collection to export/import - **getItemsService** (IGetItemsService) - Required - Function returning ItemsService for any collection - **options** (CollectionExporterOptions | undefined) - Optional - Export configuration. Defaults to DEFAULT_COLLECTION_EXPORTER_OPTIONS. - **logger** (ApiExtensionContext['logger']) - Required - Logger instance ``` -------------------------------- ### Get Export Metadata Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Reads and parses the hash and timestamp from the hash.txt file. Returns null if the file is not found or its content is invalid. Used for retrieving the current export state for synchronization. ```typescript static async getExportMeta(): Promise<{ hash: string; ts: string } | null> ``` ```typescript const meta = await ExportHelper.getExportMeta(); if (meta) { console.log(`Current export: hash=${meta.hash}, ts=${meta.ts}`); } else { console.log('No export found'); } ``` -------------------------------- ### ExportHelper.schemaDir Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-utilities.md Provides the absolute path to the 'schema-sync' directory within the current working directory. This is a static getter. ```APIDOC ## ExportHelper.schemaDir ### Description Provides the absolute path to the `schema-sync` directory in the current working directory. ### Method `static get schemaDir(): string` ### Returns `string` - The absolute path to the `schema-sync` directory. ### Example ```typescript const dir = ExportHelper.schemaDir; // Returns: /path/to/project/schema-sync ``` ``` -------------------------------- ### Default User-Defined Collection Configuration Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md This is the default content for `schema-sync/config.js`. It shows the structure for exporting custom collections and provides commented-out examples of configuration options like `watch`, `excludeFields`, `linkedFields`, and `query`. ```javascript /** * This file is used to configure which data from your collections * you want to export and eventually import across environments. */ export const syncCustomCollections = { /* posts: { watch: ['posts.items'], excludeFields: ['user_created', 'user_updated'], linkedFields: ['parent'], query: { filter: { shared: { _eq: true } }, sort: ['published_at'], }, }, */ }; ``` -------------------------------- ### CI/CD Environment Variables Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Configure schema sync for exporting state during CI/CD. Set SCHEMA_SYNC to EXPORT and specify the configuration file. ```env SCHEMA_SYNC=EXPORT SCHEMA_SYNC_SPLIT=true SCHEMA_SYNC_CONFIG=test_config.js ``` -------------------------------- ### Transforming Fields via Export Hooks Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Example of using an `onExport` hook to transform or nullify sensitive fields before export. This provides a programmatic way to manage sensitive data during schema synchronization. ```javascript // Or transform via hooks directus_users: { onExport: async (item, srv) => { item.password = null; return item; }, } ``` -------------------------------- ### Configure PostgreSQL Environment Variables Source: https://github.com/bcc-code/directus-schema-sync/blob/main/test/README.md Sets environment variables to configure Directus to use a PostgreSQL database instead of the default SQLite. These variables should be set in the test directory or passed directly to docker-compose. ```bash DB_CLIENT=pg DB_HOST=postgres DB_PORT=5432 DB_DATABASE=directus DB_USER=directus DB_PASSWORD=directus ``` -------------------------------- ### load Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md Imports schema from files and applies it to the database. This method handles reading schema files, calculating diffs, and applying changes, with options to filter destructive operations. ```APIDOC ## load ### Description Imports schema from files and applies it to the database. This method handles reading schema files, calculating diffs, and applying changes, with options to filter destructive operations. ### Method `load: () => Promise` ### Endpoint N/A (Method call) ### Parameters None ### Behavior 1. Reads `schema-sync/data/schema.json` (or partial schema files if split mode) 2. If split mode and `partial: true`, reconstructs full snapshot from individual collection files 3. Computes current database snapshot and calculates diff 4. If `safe: true`, filters out destructive operations (deletes) 5. Applies diff to the database 6. Logs completion or skips if already up-to-date ### Response Nothing (void) ### Request Example ```typescript try { await exporter.load(); logger.info('Schema imported successfully'); } catch (error) { logger.error('Schema import failed:', error); } ``` ``` -------------------------------- ### Force Commit Updates Without Lock Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-updatemanager.md Bypasses the locking mechanism to directly write the new hash and timestamp to the database. Use this for direct imports, manual recovery, or in single-instance setups where locking is not required. ```typescript public async forceCommitUpdates(newHash: string, isoTS: string): Promise ``` ```typescript // Direct import without locking const meta = await getExportMeta(); await exporter.load(); await updateManager.forceCommitUpdates(meta.hash, meta.ts); ``` -------------------------------- ### Schema Sync Lock Acquisition Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/api-reference-schemaexporter.md This snippet shows how to integrate SchemaExporter with UpdateManager in a main hook setup. It retrieves export metadata, attempts to acquire a lock for updates, and proceeds with schema export if the lock is obtained. ```typescript // In main hook setup const meta = await ExportHelper.getExportMeta(); // Gets hash from hash.txt if (await updateManager.lockForUpdates(meta.hash, meta.ts)) { // This instance acquired lock const exporter = new SchemaExporter(...); await exporter.load(); await updateManager.commitUpdates(); } ``` -------------------------------- ### Verify Schema Import Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/README.md Command to export the schema for verification. If there is no difference compared to the existing schema (checked via `git diff`), it indicates the schema is in sync. ```bash npx directus schema-sync export-schema # If no git diff, schema is in sync ``` -------------------------------- ### Fetch and add related data during export Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Utilize the onExport hook to fetch related data using the provided ItemsService (srv) and enrich the item before export. This example adds the author's name to a post item. ```javascript export const syncCustomCollections = { posts: { watch: ['posts.items'], onExport: async (item, srv) => { // Enrich with author name const author = await srv.readOne(item.author_id); item.author_name = author.name; return item; }, }, }; ``` -------------------------------- ### Hook Entry Point Implementation Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/hook-registration.md The default export function implements the `HookConfig` interface, receiving hook APIs and the Directus context for extension logic. ```typescript import type { HookConfig } from '@directus/extensions'; const registerHook: HookConfig = async ( { action, init }, { env, services, database, getSchema, logger } ) => { // Hook implementation }; export default registerHook; ``` -------------------------------- ### Directus Filter: Export Published Posts by Date Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/configuration.md Example of filtering posts to export only those that are published and created within a specific date range. It uses `_eq` for status and `_gte`/`_lt` for date range filtering, combined with `_and`. ```javascript // Published posts only export const syncCustomCollections = { posts: { watch: ['posts.items'], query: { filter: { status: { _eq: 'published' }, _and: [ { created_at: { _gte: '2024-01-01' } }, { created_at: { _lt: '2025-01-01' } }, ], }, }, }, }; ``` -------------------------------- ### Full Schema and Data Import Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md Performs a full import including schema and data. It will delete items not present in the imported files. Use this for a complete synchronization. ```bash npx directus schema-sync import ``` -------------------------------- ### Data Only Import (Skip Schema) Source: https://github.com/bcc-code/directus-schema-sync/blob/main/_autodocs/cli-commands.md Imports only the data, skipping the schema synchronization. This is useful when the schema is managed separately or already in place. ```bash npx directus schema-sync import --data ```