#!/bin/bash # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" EXTENSIONS_ROOT="$REPO_ROOT/packages" # Strict local targets for bombproof isolation TARGET_DIRS=( "$REPO_ROOT/packages/cms-infra/extensions" "$REPO_ROOT/directus/extensions" ) # List of extension packages to sync EXTENSION_PACKAGES=( "acquisition" "acquisition-manager" "company-manager" "customer-manager" "feedback-commander" "people-manager" "unified-dashboard" ) # Parse flags LINK_MODE=false for arg in "$@"; do if [ "$arg" == "--link" ]; then LINK_MODE=true fi done echo "๐Ÿš€ Starting isolated extension sync..." # Ensure target directories exist for TARGET in "${TARGET_DIRS[@]}"; do mkdir -p "$TARGET" done # Build the acquisition library if it exists if [ -d "$REPO_ROOT/packages/acquisition" ]; then echo "๐Ÿ“ฆ Building acquisition..." (cd "$REPO_ROOT/packages/acquisition" && pnpm build) fi for PKG in "${EXTENSION_PACKAGES[@]}"; do PKG_PATH="$EXTENSIONS_ROOT/$PKG" if [ -d "$PKG_PATH" ]; then echo "๐Ÿ“ฆ Processing $PKG..." # 1. Build the extension (cd "$PKG_PATH" && pnpm build) EXT_NAME="$PKG" echo "๐Ÿšš Syncing $EXT_NAME..." # 3. Sync to each target directory for TARGET_BASE in "${TARGET_DIRS[@]}"; do # FLAT STRUCTURE: Directus 11.15.x local scanner is FLAT. FINAL_TARGET="$TARGET_BASE/$EXT_NAME" echo "๐Ÿšš Syncing $EXT_NAME to $FINAL_TARGET..." # Clean target first to avoid ghost files mkdir -p "$FINAL_TARGET" rm -rf "${FINAL_TARGET:?}"/* # Copy build artifacts if [ -f "$PKG_PATH/dist/index.js" ]; then cp "$PKG_PATH/dist/index.js" "$FINAL_TARGET/index.js" elif [ -f "$PKG_PATH/index.js" ]; then cp "$PKG_PATH/index.js" "$FINAL_TARGET/index.js" fi if [ -f "$PKG_PATH/package.json" ]; then # We ALWAYS copy and patch package.json to avoid messing with source cp "$PKG_PATH/package.json" "$FINAL_TARGET/" # We force the registration path to index.js and ensure host/source are set node -e " const fs = require('fs'); const pkgPath = '$FINAL_TARGET/package.json'; const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); if (!pkg['directus:extension']) pkg['directus:extension'] = {}; // Standard metadata for Directus 11.15.x (with core patch applied) pkg['directus:extension'].path = 'index.js'; if (!pkg['directus:extension'].host) { pkg['directus:extension'].host = pkg['directus:extension'].type === 'endpoint' ? 'api' : 'app'; } if (!pkg['directus:extension'].source) { pkg['directus:extension'].source = 'src/index.ts'; } fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2)); " fi if [ -d "$PKG_PATH/dist" ]; then if [ "$LINK_MODE" = true ]; then REL_PATH=$(python3 -c "import os; print(os.path.relpath('$PKG_PATH/dist', '$FINAL_TARGET'))") ln -sf "$REL_PATH" "$FINAL_TARGET/dist" else cp -r "$PKG_PATH/dist" "$FINAL_TARGET/" fi fi done echo "โœ… $PKG synced." else echo "โŒ Extension source not found: $PKG_PATH" fi done # Cleanup: remove anything from extensions root that isn't in our whitelist WHITELIST=("${EXTENSION_PACKAGES[@]}" "sources" "endpoints" "hooks" "layouts" "modules" "operations" "panels" "displays" "interfaces") for TARGET_BASE in "${TARGET_DIRS[@]}"; do echo "๐Ÿงน Cleaning up $TARGET_BASE..." for ITEM in "$TARGET_BASE"/*; do [ -e "$ITEM" ] || continue BN=$(basename "$ITEM") IS_ALLOWED=false for W in "${WHITELIST[@]}"; do if [[ "$BN" == "$W" ]]; then IS_ALLOWED=true; break; fi done if [ "$IS_ALLOWED" = false ]; then echo " ๐Ÿ—‘๏ธ Removing extra/legacy item: $BN" rm -rf "$ITEM" fi done done # Container patching is now handled by scripts/patch-cms.sh # which should be run AFTER the containers are up. echo "โœจ Sync complete! Extensions are in packages/cms-infra/extensions."