directus
This commit is contained in:
18
.env
18
.env
@@ -20,12 +20,12 @@ MAIL_PASSWORD=4592fcb94599ee1a45b4ac2386fd0a64-102c75d8-ca2870e6
|
||||
MAIL_FROM="KLZ Cables <postmaster@mg.mintel.me>"
|
||||
MAIL_RECIPIENTS=marc@cablecreations.de,info@klz-cables.com
|
||||
|
||||
# Strapi
|
||||
STRAPI_DATABASE_NAME=strapi
|
||||
STRAPI_DATABASE_USERNAME=strapi
|
||||
STRAPI_DATABASE_PASSWORD=strapi_password_change_me
|
||||
APP_KEYS=toBeModified1,toBeModified2,toBeModified3,toBeModified4
|
||||
API_TOKEN_SALT=tobemodified
|
||||
ADMIN_JWT_SECRET=tobemodified
|
||||
TRANSFER_TOKEN_SALT=tobemodified
|
||||
JWT_SECRET=tobemodified
|
||||
# Directus
|
||||
DIRECTUS_URL=https://cms.klz-cables.com
|
||||
DIRECTUS_KEY=59fb8f4c1a51b18fe28ad947f713914e
|
||||
DIRECTUS_SECRET=7459038d41401dfb11254cf7f1ef2d0f
|
||||
DIRECTUS_ADMIN_EMAIL=admin@klz-cables.com
|
||||
DIRECTUS_ADMIN_PASSWORD=admin
|
||||
DIRECTUS_DB_NAME=directus
|
||||
DIRECTUS_DB_USER=directus
|
||||
DIRECTUS_DB_PASSWORD=directus
|
||||
|
||||
@@ -85,10 +85,21 @@ jobs:
|
||||
MAIL_FROM=${{ secrets.MAIL_FROM }}
|
||||
MAIL_RECIPIENTS=${{ secrets.MAIL_RECIPIENTS }}
|
||||
|
||||
# Directus
|
||||
DIRECTUS_URL=https://cms.klz-cables.com
|
||||
DIRECTUS_KEY=${{ secrets.DIRECTUS_KEY }}
|
||||
DIRECTUS_SECRET=${{ secrets.DIRECTUS_SECRET }}
|
||||
DIRECTUS_ADMIN_EMAIL=${{ secrets.DIRECTUS_ADMIN_EMAIL }}
|
||||
DIRECTUS_ADMIN_PASSWORD=${{ secrets.DIRECTUS_ADMIN_PASSWORD }}
|
||||
DIRECTUS_DB_NAME=directus
|
||||
DIRECTUS_DB_USER=directus
|
||||
DIRECTUS_DB_PASSWORD=${{ secrets.DIRECTUS_DB_PASSWORD }}
|
||||
|
||||
EOF
|
||||
|
||||
# Upload .env and deploy
|
||||
# Upload .env and docker-compose.yml
|
||||
scp -o StrictHostKeyChecking=accept-new /tmp/klz-cables.env root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/.env
|
||||
scp -o StrictHostKeyChecking=accept-new docker-compose.yml root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/docker-compose.yml
|
||||
|
||||
ssh -o StrictHostKeyChecking=accept-new root@alpha.mintel.me bash << EOF
|
||||
set -e
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
node_modules
|
||||
.tmp
|
||||
.cache
|
||||
dist
|
||||
build
|
||||
.env
|
||||
@@ -1,16 +0,0 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
# Installing libvips-dev for sharp Compatibility
|
||||
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
|
||||
|
||||
WORKDIR /opt/
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm install -g node-gyp
|
||||
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm ci
|
||||
ENV PATH=/opt/node_modules/.bin:$PATH
|
||||
|
||||
WORKDIR /opt/app
|
||||
COPY . .
|
||||
RUN NODE_ENV=production npm run build
|
||||
EXPOSE 1337
|
||||
CMD ["npm", "run", "develop"]
|
||||
@@ -1,13 +0,0 @@
|
||||
export default ({ env }) => ({
|
||||
auth: {
|
||||
secret: env('ADMIN_JWT_SECRET'),
|
||||
},
|
||||
apiToken: {
|
||||
salt: env('API_TOKEN_SALT'),
|
||||
},
|
||||
transfer: {
|
||||
token: {
|
||||
salt: env('TRANSFER_TOKEN_SALT'),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
export default {
|
||||
rest: {
|
||||
defaultLimit: 25,
|
||||
maxLimit: 100,
|
||||
withCount: true,
|
||||
},
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
export default ({ env }) => ({
|
||||
connection: {
|
||||
client: 'postgres',
|
||||
connection: {
|
||||
host: env('DATABASE_HOST', '127.0.0.1'),
|
||||
port: env.int('DATABASE_PORT', 5432),
|
||||
database: env('DATABASE_NAME', 'strapi'),
|
||||
user: env('DATABASE_USERNAME', 'strapi'),
|
||||
password: env('DATABASE_PASSWORD', 'strapi'),
|
||||
ssl: env.bool('DATABASE_SSL', false),
|
||||
},
|
||||
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
|
||||
},
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
export default ({ env }) => ({
|
||||
host: env('HOST', '0.0.0.0'),
|
||||
port: env.int('PORT', 1337),
|
||||
app: {
|
||||
keys: env.array('APP_KEYS'),
|
||||
},
|
||||
webhooks: {
|
||||
populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),
|
||||
},
|
||||
});
|
||||
19637
cms/package-lock.json
generated
19637
cms/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "klz-cms",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "Strapi CMS for KLZ Cables",
|
||||
"scripts": {
|
||||
"develop": "strapi develop",
|
||||
"start": "strapi start",
|
||||
"build": "strapi build",
|
||||
"strapi": "strapi"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/strapi": "4.25.11",
|
||||
"@strapi/plugin-users-permissions": "4.25.11",
|
||||
"@strapi/plugin-i18n": "4.25.11",
|
||||
"pg": "8.11.3",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"styled-components": "^5.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer"
|
||||
},
|
||||
"strapi": {
|
||||
"uuid": "klz-cms"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <=20.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "applications",
|
||||
"info": {
|
||||
"singularName": "application",
|
||||
"pluralName": "applications",
|
||||
"displayName": "Application"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"attributes": {
|
||||
"job": {
|
||||
"type": "relation",
|
||||
"relation": "manyToOne",
|
||||
"target": "api::job.job"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
"type": "email",
|
||||
"required": true
|
||||
},
|
||||
"resume": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"allowedTypes": [
|
||||
"files"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::application.application');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::application.application');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::application.application');
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "categories",
|
||||
"info": {
|
||||
"singularName": "category",
|
||||
"pluralName": "categories",
|
||||
"displayName": "Category"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"slug": {
|
||||
"type": "uid",
|
||||
"targetField": "name",
|
||||
"required": true
|
||||
},
|
||||
"products": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::product.product",
|
||||
"mappedBy": "categories"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::category.category');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::category.category');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::category.category');
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "contact_messages",
|
||||
"info": {
|
||||
"singularName": "contact-message",
|
||||
"pluralName": "contact-messages",
|
||||
"displayName": "Contact Message"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"attributes": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
"type": "email",
|
||||
"required": true
|
||||
},
|
||||
"subject": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "text",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::contact-message.contact-message');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::contact-message.contact-message');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::contact-message.contact-message');
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "jobs",
|
||||
"info": {
|
||||
"singularName": "job",
|
||||
"pluralName": "jobs",
|
||||
"displayName": "Job"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "richtext",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::job.job');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::job.job');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::job.job');
|
||||
@@ -1,80 +0,0 @@
|
||||
{
|
||||
"kind": "collectionType",
|
||||
"collectionName": "products",
|
||||
"info": {
|
||||
"singularName": "product",
|
||||
"pluralName": "products",
|
||||
"displayName": "Product",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"sku": {
|
||||
"type": "uid",
|
||||
"targetField": "title",
|
||||
"required": true
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"application": {
|
||||
"type": "text",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"type": "richtext",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"images": {
|
||||
"type": "media",
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images"
|
||||
]
|
||||
},
|
||||
"categories": {
|
||||
"type": "relation",
|
||||
"relation": "manyToMany",
|
||||
"target": "api::category.category",
|
||||
"inversedBy": "products"
|
||||
},
|
||||
"technicalData": {
|
||||
"type": "json",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::product.product');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::product.product');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::product.product');
|
||||
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"kind": "singleType",
|
||||
"collectionName": "settings",
|
||||
"info": {
|
||||
"singularName": "setting",
|
||||
"pluralName": "settings",
|
||||
"displayName": "Setting"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"siteName": {
|
||||
"type": "string",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"siteDescription": {
|
||||
"type": "text",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"logo": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"allowedTypes": [
|
||||
"images"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreController('api::setting.setting');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreRouter('api::setting.setting');
|
||||
@@ -1,2 +0,0 @@
|
||||
import { factories } from '@strapi/strapi';
|
||||
export default factories.createCoreService('api::setting.setting');
|
||||
@@ -1,18 +0,0 @@
|
||||
export default {
|
||||
/**
|
||||
* An asynchronous register function that runs before
|
||||
* your application is initialized.
|
||||
*
|
||||
* This gives you an opportunity to extend code.
|
||||
*/
|
||||
register(/*{ strapi }*/) {},
|
||||
|
||||
/**
|
||||
* An asynchronous bootstrap function that runs before
|
||||
* your application gets started.
|
||||
*
|
||||
* This gives you an opportunity to set up your data model,
|
||||
* run jobs, or perform some special logic.
|
||||
*/
|
||||
bootstrap(/*{ strapi }*/) {},
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"extends": "@strapi/typescript-utils/tsconfigs/server",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"config/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules/",
|
||||
"build/",
|
||||
"dist/",
|
||||
".cache/",
|
||||
".tmp/",
|
||||
"src/admin/",
|
||||
"**/*.test.ts",
|
||||
"src/plugins/**"
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,23 @@
|
||||
services:
|
||||
app:
|
||||
env_file:
|
||||
- .env
|
||||
cms:
|
||||
ports:
|
||||
- "1337:1337"
|
||||
image: node:20-alpine
|
||||
working_dir: /app
|
||||
command: sh -c "npm install && npx next dev"
|
||||
volumes:
|
||||
- .:/app
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.klz-app-local.rule=Host(`klz.local`)"
|
||||
- "traefik.http.routers.klz-app-local.entrypoints=web"
|
||||
- "traefik.http.routers.klz-app-local.service=klz-cables"
|
||||
|
||||
directus:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.klz-directus-local.rule=Host(`cms.klz.local`)"
|
||||
- "traefik.http.routers.klz-directus-local.entrypoints=web"
|
||||
- "traefik.http.routers.klz-directus-local.service=klz-directus"
|
||||
environment:
|
||||
PUBLIC_URL: http://cms.klz.local
|
||||
|
||||
@@ -4,8 +4,6 @@ services:
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
ports:
|
||||
- "3000:3000"
|
||||
env_file:
|
||||
- .env
|
||||
labels:
|
||||
@@ -28,55 +26,54 @@ services:
|
||||
# Middlewares
|
||||
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||
|
||||
cms:
|
||||
build:
|
||||
context: ./cms
|
||||
dockerfile: Dockerfile
|
||||
directus:
|
||||
image: directus/directus:10.10
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
DATABASE_CLIENT: postgres
|
||||
DATABASE_HOST: cms-db
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_NAME: ${STRAPI_DATABASE_NAME:-strapi}
|
||||
DATABASE_USERNAME: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||
DATABASE_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||
NODE_ENV: ${NODE_ENV:-development}
|
||||
STRAPI_URL: ${STRAPI_URL:-https://cms.klz-cables.com}
|
||||
KEY: ${DIRECTUS_KEY}
|
||||
SECRET: ${DIRECTUS_SECRET}
|
||||
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL}
|
||||
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD}
|
||||
DB_CLIENT: 'pg'
|
||||
DB_HOST: 'directus-db'
|
||||
DB_PORT: '5432'
|
||||
DB_DATABASE: ${DIRECTUS_DB_NAME:-directus}
|
||||
DB_USER: ${DIRECTUS_DB_USER:-directus}
|
||||
DB_PASSWORD: ${DIRECTUS_DB_PASSWORD:-directus}
|
||||
WEBSOCKETS_ENABLED: 'true'
|
||||
PUBLIC_URL: ${DIRECTUS_URL:-https://cms.klz-cables.com}
|
||||
volumes:
|
||||
- ./cms/config:/opt/app/config
|
||||
- ./cms/src:/opt/app/src
|
||||
- ./cms/package.json:/opt/app/package.json
|
||||
- ./cms/package-lock.json:/opt/app/package-lock.json
|
||||
- ./cms/public/uploads:/opt/app/public/uploads
|
||||
- ./directus/uploads:/directus/uploads
|
||||
- ./directus/extensions:/directus/extensions
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.klz-cms.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
||||
- "traefik.http.routers.klz-cms.entrypoints=websecure"
|
||||
- "traefik.http.routers.klz-cms.tls.certresolver=le"
|
||||
- "traefik.http.routers.klz-cms.tls=true"
|
||||
- "traefik.http.services.klz-cms.loadbalancer.server.port=1337"
|
||||
- "traefik.http.routers.klz-directus.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
||||
- "traefik.http.routers.klz-directus.entrypoints=websecure"
|
||||
- "traefik.http.routers.klz-directus.tls.certresolver=le"
|
||||
- "traefik.http.routers.klz-directus.tls=true"
|
||||
- "traefik.http.services.klz-directus.loadbalancer.server.port=8055"
|
||||
|
||||
cms-db:
|
||||
image: postgres:16-alpine
|
||||
directus-db:
|
||||
image: postgres:15-alpine
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
POSTGRES_DB: ${STRAPI_DATABASE_NAME:-strapi}
|
||||
POSTGRES_USER: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||
POSTGRES_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||
POSTGRES_DB: ${DIRECTUS_DB_NAME:-directus}
|
||||
POSTGRES_USER: ${DIRECTUS_DB_USER:-directus}
|
||||
POSTGRES_PASSWORD: ${DIRECTUS_DB_PASSWORD:-directus}
|
||||
volumes:
|
||||
- cms-db-data:/var/lib/postgresql/data
|
||||
- directus-db-data:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
infra:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
cms-db-data:
|
||||
directus-db-data:
|
||||
|
||||
81
docker-compose.yml.bak
Normal file
81
docker-compose.yml.bak
Normal file
@@ -0,0 +1,81 @@
|
||||
services:
|
||||
app:
|
||||
image: registry.infra.mintel.me/mintel/klz-cables.com:latest
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# HTTP ⇒ HTTPS redirect
|
||||
- "traefik.http.routers.klz-cables-web.rule=(Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)) && !PathPrefix(`/.well-known/acme-challenge/`)"
|
||||
- "traefik.http.routers.klz-cables-web.entrypoints=web"
|
||||
- "traefik.http.routers.klz-cables-web.middlewares=redirect-https"
|
||||
# HTTPS router
|
||||
- "traefik.http.routers.klz-cables.rule=Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)"
|
||||
- "traefik.http.routers.klz-cables.entrypoints=websecure"
|
||||
- "traefik.http.routers.klz-cables.tls.certresolver=le"
|
||||
- "traefik.http.routers.klz-cables.tls=true"
|
||||
- "traefik.http.routers.klz-cables.service=klz-cables"
|
||||
- "traefik.http.services.klz-cables.loadbalancer.server.port=3000"
|
||||
- "traefik.http.services.klz-cables.loadbalancer.server.scheme=http"
|
||||
# Forwarded Headers
|
||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
||||
# Middlewares
|
||||
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||
|
||||
cms:
|
||||
build:
|
||||
context: ./cms
|
||||
dockerfile: Dockerfile
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
DATABASE_CLIENT: postgres
|
||||
DATABASE_HOST: cms-db
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_NAME: ${STRAPI_DATABASE_NAME:-strapi}
|
||||
DATABASE_USERNAME: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||
DATABASE_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||
NODE_ENV: ${NODE_ENV:-development}
|
||||
STRAPI_URL: ${STRAPI_URL:-https://cms.klz-cables.com}
|
||||
volumes:
|
||||
- ./cms/config:/opt/app/config
|
||||
- ./cms/src:/opt/app/src
|
||||
- ./cms/package.json:/opt/app/package.json
|
||||
- ./cms/package-lock.json:/opt/app/package-lock.json
|
||||
- ./cms/public/uploads:/opt/app/public/uploads
|
||||
- ./cms/dist:/opt/app/dist
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.klz-cms.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
||||
- "traefik.http.routers.klz-cms.entrypoints=websecure"
|
||||
- "traefik.http.routers.klz-cms.tls.certresolver=le"
|
||||
- "traefik.http.routers.klz-cms.tls=true"
|
||||
- "traefik.http.services.klz-cms.loadbalancer.server.port=1337"
|
||||
|
||||
cms-db:
|
||||
image: postgres:16-alpine
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
POSTGRES_DB: ${STRAPI_DATABASE_NAME:-strapi}
|
||||
POSTGRES_USER: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||
POSTGRES_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||
volumes:
|
||||
- cms-db-data:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
infra:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
cms-db-data:
|
||||
111
lib/directus.ts
Normal file
111
lib/directus.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { createDirectus, rest, staticToken, authentication, readItems, readItem } from '@directus/sdk';
|
||||
|
||||
const DIRECTUS_URL = process.env.DIRECTUS_URL || 'http://localhost:8055';
|
||||
// We use Admin credentials for server-side operations if no token is provided
|
||||
// This approach allows "auto-connect" without manual token generation
|
||||
const DIRECTUS_EMAIL = process.env.DIRECTUS_ADMIN_EMAIL;
|
||||
const DIRECTUS_PASSWORD = process.env.DIRECTUS_ADMIN_PASSWORD;
|
||||
|
||||
// Use a static token if provided (preferred for prod), otherwise fall back to admin auth
|
||||
const DIRECTUS_TOKEN = process.env.DIRECTUS_API_TOKEN;
|
||||
|
||||
// Initialize the client
|
||||
const client = createDirectus(DIRECTUS_URL)
|
||||
.with(rest())
|
||||
.with(authentication());
|
||||
|
||||
// Helper to authenticate if needed
|
||||
async function ensureAuthenticated() {
|
||||
if (DIRECTUS_TOKEN) {
|
||||
client.setToken(DIRECTUS_TOKEN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DIRECTUS_EMAIL && DIRECTUS_PASSWORD) {
|
||||
// Check if we already have a valid token (optional optimization, but simple login is robust)
|
||||
try {
|
||||
await client.login(DIRECTUS_EMAIL, DIRECTUS_PASSWORD);
|
||||
} catch (e) {
|
||||
console.error("Failed to authenticate with Directus:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
id: string;
|
||||
title: string;
|
||||
sku: string;
|
||||
description: string;
|
||||
application: string;
|
||||
content: string; // rich text
|
||||
technical_data: any; // json
|
||||
locale: string;
|
||||
images?: {
|
||||
directus_files_id: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
// Maps Directus response to match our internal Product interface (mimicking Strapi for now)
|
||||
function mapDirectusProduct(item: any): any {
|
||||
return {
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
sku: item.sku,
|
||||
description: item.description,
|
||||
application: item.application,
|
||||
content: item.content,
|
||||
technicalData: item.technical_data,
|
||||
locale: item.locale || 'de', // default
|
||||
// Map images structure if needed
|
||||
images: item.images ? {
|
||||
data: item.images.map((img: any) => ({
|
||||
attributes: {
|
||||
url: `${DIRECTUS_URL}/assets/${img.directus_files_id}`,
|
||||
alternativeText: img.caption || ''
|
||||
}
|
||||
}))
|
||||
} : undefined
|
||||
};
|
||||
}
|
||||
|
||||
export async function getProducts(locale: string = 'de') {
|
||||
await ensureAuthenticated();
|
||||
try {
|
||||
const items = await client.request(readItems('products', {
|
||||
filter: {
|
||||
_and: [
|
||||
{ locale: { _eq: locale } }
|
||||
]
|
||||
},
|
||||
fields: ['*', 'images.directus_files_id']
|
||||
}));
|
||||
|
||||
return items.map(mapDirectusProduct);
|
||||
} catch (error) {
|
||||
console.error('Error fetching products from Directus:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getProductBySku(sku: string, locale: string = 'de') {
|
||||
await ensureAuthenticated();
|
||||
try {
|
||||
const items = await client.request(readItems('products', {
|
||||
filter: {
|
||||
_and: [
|
||||
{ sku: { _eq: sku } },
|
||||
{ locale: { _eq: locale } }
|
||||
]
|
||||
},
|
||||
fields: ['*', 'images.directus_files_id']
|
||||
}));
|
||||
|
||||
if (!items || items.length === 0) return null;
|
||||
return mapDirectusProduct(items[0]);
|
||||
} catch (error) {
|
||||
console.error(`Error fetching product ${sku} from Directus:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default client;
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "klz-cables-nextjs",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@directus/sdk": "^18.0.3",
|
||||
"@react-email/components": "^1.0.6",
|
||||
"@react-pdf/renderer": "^4.3.2",
|
||||
"@sentry/nextjs": "^8.55.0",
|
||||
@@ -1360,6 +1361,18 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@directus/sdk": {
|
||||
"version": "18.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-18.0.3.tgz",
|
||||
"integrity": "sha512-PnEDRDqr2x/DG3HZ3qxU7nFp2nW6zqJqswjii57NhriXgTz4TBUI8NmSdzQvnyHuTL9J0nedYfQGfW4v8odS1A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/directus/directus?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
||||
|
||||
12
package.json
12
package.json
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@directus/sdk": "^18.0.3",
|
||||
"@react-email/components": "^1.0.6",
|
||||
"@react-pdf/renderer": "^4.3.2",
|
||||
"@sentry/nextjs": "^8.55.0",
|
||||
@@ -57,7 +58,8 @@
|
||||
"name": "klz-cables-nextjs",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"dev": "docker network create infra 2>/dev/null || true && docker-compose up -d",
|
||||
"dev:local": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
@@ -65,13 +67,7 @@
|
||||
"test": "vitest run --passWithNoTests",
|
||||
"test:og": "vitest run tests/og-image.test.ts",
|
||||
"pdf:datasheets": "tsx ./scripts/generate-pdf-datasheets.ts",
|
||||
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts",
|
||||
"cms:dev": "docker network create infra 2>/dev/null || true && docker-compose up -d cms cms-db",
|
||||
"cms:stop": "docker-compose stop cms cms-db",
|
||||
"cms:logs": "docker-compose logs -f cms",
|
||||
"cms:export": "./scripts/strapi-sync.sh export",
|
||||
"cms:import": "./scripts/strapi-sync.sh import",
|
||||
"cms:migrate": "tsx ./scripts/migrate-to-strapi.ts"
|
||||
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts"
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user