fix(directus): resolve login failures and standardize project branding

- Fixed project isolation bypass (identity shadowing) by prefixing database service name.
- Standardized health check paths and protocols in docker-compose.yml.
- Resolved extension SyntaxError caused by duplicate banner injections in build scripts.
- Migrated extension build system to clean esbuild-based bundles (removing shims).
- Updated sync-directus.sh for project-prefixed service name.
- Synchronized latest production data and branding (AT Mintel).
This commit is contained in:
2026-02-12 19:21:53 +01:00
parent efba82337c
commit 7498c24c9a
12 changed files with 50 additions and 811 deletions

View File

@@ -24,6 +24,12 @@ services:
directus: directus:
image: registry.infra.mintel.me/mintel/directus:${IMAGE_TAG:-latest} image: registry.infra.mintel.me/mintel/directus:${IMAGE_TAG:-latest}
healthcheck:
test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8055/server/health" ]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
restart: always restart: always
networks: networks:
- infra - infra
@@ -35,7 +41,7 @@ services:
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL:-admin@mintel.me} ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL:-admin@mintel.me}
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD:-mintel-admin} ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD:-mintel-admin}
DB_CLIENT: 'pg' DB_CLIENT: 'pg'
DB_HOST: 'directus-db' DB_HOST: 'at-mintel-directus-db'
DB_PORT: '5432' DB_PORT: '5432'
DB_DATABASE: ${DIRECTUS_DB_NAME:-directus} DB_DATABASE: ${DIRECTUS_DB_NAME:-directus}
DB_USER: ${DIRECTUS_DB_USER:-directus} DB_USER: ${DIRECTUS_DB_USER:-directus}
@@ -53,7 +59,7 @@ services:
- "traefik.http.routers.sample-website-directus.rule=Host(`${DIRECTUS_HOST:-cms.sample-website.localhost}`)" - "traefik.http.routers.sample-website-directus.rule=Host(`${DIRECTUS_HOST:-cms.sample-website.localhost}`)"
- "traefik.http.services.sample-website-directus.loadbalancer.server.port=8055" - "traefik.http.services.sample-website-directus.loadbalancer.server.port=8055"
directus-db: at-mintel-directus-db:
image: postgres:15-alpine image: postgres:15-alpine
restart: always restart: always
networks: networks:

View File

@@ -22,19 +22,19 @@ build({
target: 'node18', target: 'node18',
outfile: outfile, outfile: outfile,
format: 'esm', format: 'esm',
external: [], external: ["jsdom", "jsdom/*", "jquery", "jquery/*", "canvas"],
plugins: [{ plugins: [{
name: 'mock-jquery',
setup(build) {
build.onResolve({ filter: /^jquery$/ }, args => ({ path: args.path, namespace: 'mock-jquery' }));
build.onLoad({ filter: /.*/, namespace: 'mock-jquery' }, () => ({ contents: 'export default {};', loader: 'js' }));
}
}, {
name: 'mock-canvas', name: 'mock-canvas',
setup(build) { setup(build) {
build.onResolve({ filter: /^canvas$/ }, args => ({ path: args.path, namespace: 'mock-canvas' })); build.onResolve({ filter: /^canvas/ }, args => ({ path: args.path, namespace: 'mock-canvas' }));
build.onLoad({ filter: /.*/, namespace: 'mock-canvas' }, () => ({ contents: 'export default {};', loader: 'js' })); build.onLoad({ filter: /.*/, namespace: 'mock-canvas' }, () => ({ contents: 'export default {};', loader: 'js' }));
} }
}, {
name: 'mock-jsdom',
setup(build) {
build.onResolve({ filter: /^jsdom/ }, args => ({ path: args.path, namespace: 'mock-jsdom' }));
build.onLoad({ filter: /.*/, namespace: 'mock-jsdom' }, () => ({ contents: 'export default {};', loader: 'js' }));
}
}] }]
}).then(() => { }).then(() => {
console.log("Build succeeded!"); console.log("Build succeeded!");

View File

@@ -5,8 +5,8 @@
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.js", "module": "dist/index.js",
"scripts": { "scripts": {
"build": "node build.js", "build": "node build.mjs",
"dev": "node build.js --watch" "dev": "node build.mjs --watch"
}, },
"devDependencies": { "devDependencies": {
"@directus/extensions-sdk": "11.0.2", "@directus/extensions-sdk": "11.0.2",
@@ -14,12 +14,12 @@
"typescript": "^5.6.3" "typescript": "^5.6.3"
}, },
"dependencies": { "dependencies": {
"@crawlee/cheerio": "^3.16.0",
"@mintel/mail": "workspace:*", "@mintel/mail": "workspace:*",
"@react-pdf/renderer": "^4.3.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"crawlee": "^3.12.2",
"cheerio": "^1.0.0", "cheerio": "^1.0.0",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4"
"@react-pdf/renderer": "^4.3.0"
} }
} }

View File

@@ -1,4 +1,4 @@
import { CheerioCrawler } from "crawlee"; import { CheerioCrawler } from "@crawlee/cheerio";
import axios from "axios"; import axios from "axios";
import { FileCacheAdapter } from "../utils/cache/FileCacheAdapter.js"; import { FileCacheAdapter } from "../utils/cache/FileCacheAdapter.js";
import { initialState } from "../logic/pricing/constants.js"; import { initialState } from "../logic/pricing/constants.js";

View File

@@ -1,22 +0,0 @@
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import { createRequire } from 'module';
try {
const url = import.meta?.url;
// Hardcode fallback path for Directus Docker environment
const fallbackPath = '/directus/extensions/acquisition/dist/index.js';
const filename = url ? fileURLToPath(url) : fallbackPath;
const dir = dirname(filename);
// @ts-ignore
globalThis.__filename = filename;
// @ts-ignore
globalThis.__dirname = dir;
// @ts-ignore
globalThis.require = createRequire(url || `file://${fallbackPath}`);
console.log(`[Shim] Loaded. __dirname: ${dir}`);
} catch (e) {
console.warn("[Shim] Failed to shim __dirname/require", e);
}

View File

@@ -23,23 +23,18 @@ build({
outfile: outfile, outfile: outfile,
format: 'esm', format: 'esm',
// Bundle everything, including Directus SDK, to avoid resolution issues in Docker // Bundle everything, including Directus SDK, to avoid resolution issues in Docker
external: [], external: ["jsdom", "jsdom/*", "jquery", "jquery/*", "canvas"],
plugins: [{ plugins: [{
name: 'mock-jquery',
setup(build) {
build.onResolve({ filter: /^jquery$/ }, args => ({ path: args.path, namespace: 'mock-jquery' }));
build.onLoad({ filter: /.*/, namespace: 'mock-jquery' }, () => ({ contents: 'export default {};', loader: 'js' }));
}
}, {
name: 'mock-canvas', name: 'mock-canvas',
setup(build) { setup(build) {
build.onResolve({ filter: /^canvas$/ }, args => ({ path: args.path, namespace: 'mock-canvas' })); build.onResolve({ filter: /^canvas/ }, args => ({ path: args.path, namespace: 'mock-canvas' }));
build.onLoad({ filter: /.*/, namespace: 'mock-canvas' }, () => ({ contents: 'export default {};', loader: 'js' })); build.onLoad({ filter: /.*/, namespace: 'mock-canvas' }, () => ({ contents: 'export default {};', loader: 'js' }));
} }
}, { }, {
name: 'mock-jsdom', name: 'mock-jsdom',
setup(build) { setup(build) {
return; build.onResolve({ filter: /^jsdom/ }, args => ({ path: args.path, namespace: 'mock-jsdom' }));
build.onLoad({ filter: /.*/, namespace: 'mock-jsdom' }, () => ({ contents: 'export default {};', loader: 'js' }));
} }
}] }]
}).then(() => { }).then(() => {

View File

@@ -9,8 +9,8 @@
"host": "^11.0.0" "host": "^11.0.0"
}, },
"scripts": { "scripts": {
"build": "node build.js", "build": "node build.mjs",
"dev": "node build.js --watch" "dev": "node build.mjs --watch"
}, },
"devDependencies": { "devDependencies": {
"@directus/extensions-sdk": "11.0.2", "@directus/extensions-sdk": "11.0.2",
@@ -24,4 +24,4 @@
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4" "react-dom": "^19.2.4"
} }
} }

View File

@@ -1,6 +1,5 @@
import "./shim";
import { defineEndpoint } from "@directus/extensions-sdk"; import { defineEndpoint } from "@directus/extensions-sdk";
import { AcquisitionService, PdfEngine } from "../../acquisition-library/src/index"; import { AcquisitionService, PdfEngine } from "@mintel/acquisition";
import { render, SiteAuditTemplate, ProjectEstimateTemplate } from "@mintel/mail"; import { render, SiteAuditTemplate, ProjectEstimateTemplate } from "@mintel/mail";
import { createElement } from "react"; import { createElement } from "react";
import * as path from "path"; import * as path from "path";

View File

@@ -1,22 +0,0 @@
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import { createRequire } from 'module';
try {
const url = import.meta?.url;
// Hardcode fallback path for Directus Docker environment
const fallbackPath = '/directus/extensions/acquisition/dist/index.js';
const filename = url ? fileURLToPath(url) : fallbackPath;
const dir = dirname(filename);
// @ts-ignore
globalThis.__filename = filename;
// @ts-ignore
globalThis.__dirname = dir;
// @ts-ignore
globalThis.require = createRequire(url || `file://${fallbackPath}`);
console.log(`[Shim] Loaded. __dirname: ${dir}`);
} catch (e) {
console.warn("[Shim] Failed to shim __dirname/require", e);
}

740
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@ esac
# Detect local containers # Detect local containers
echo "🔍 Detecting local database..." echo "🔍 Detecting local database..."
LOCAL_DB_CONTAINER=$(docker compose ps -q directus-db) LOCAL_DB_CONTAINER=$(docker compose ps -q at-mintel-directus-db)
if [ -z "$LOCAL_DB_CONTAINER" ]; then if [ -z "$LOCAL_DB_CONTAINER" ]; then
echo "❌ Local directus-db container not found. Is it running? (npm run dev)" echo "❌ Local directus-db container not found. Is it running? (npm run dev)"
exit 1 exit 1

View File

@@ -4,7 +4,7 @@
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
EXTENSIONS_ROOT="$REPO_ROOT/packages" EXTENSIONS_ROOT="$REPO_ROOT/packages"
TARGET_DIR="$REPO_ROOT/packages/cms-infra/extensions" TARGET_DIR="$REPO_ROOT/directus/extensions"
# List of extensions to sync - including modules and endpoints # List of extensions to sync - including modules and endpoints
EXTENSIONS=( EXTENSIONS=(
@@ -20,6 +20,10 @@ echo "🚀 Starting extension sync..."
# Ensure target directory exists # Ensure target directory exists
mkdir -p "$TARGET_DIR" mkdir -p "$TARGET_DIR"
# Build the acquisition library first so extensions use the updated build
echo "📦 Building acquisition-library..."
(cd "$REPO_ROOT/packages/acquisition-library" && pnpm build)
for EXT in "${EXTENSIONS[@]}"; do for EXT in "${EXTENSIONS[@]}"; do
EXT_PATH="$EXTENSIONS_ROOT/$EXT" EXT_PATH="$EXTENSIONS_ROOT/$EXT"
@@ -55,10 +59,11 @@ for EXT in "${EXTENSIONS[@]}"; do
fi fi
# Sync node_modules if they exist (sometimes needed if not everything is bundled) # Sync node_modules if they exist (sometimes needed if not everything is bundled)
if [ -d "$EXT_PATH/node_modules" ]; then # Deactivated: Causes global scope pollution and login issues in Directus
echo "📚 Syncing node_modules for $EXT..." # if [ -d "$EXT_PATH/node_modules" ]; then
rsync -a --delete "$EXT_PATH/node_modules/" "$TARGET_DIR/$EXT/node_modules/" # echo "📚 Syncing node_modules for $EXT..."
fi # rsync -aL --delete "$EXT_PATH/node_modules/" "$TARGET_DIR/$EXT/node_modules/"
# fi
echo "$EXT synced." echo "$EXT synced."
else else