This commit is contained in:
2026-01-31 23:32:01 +01:00
parent 06bbed8c21
commit 2ed038174d
43 changed files with 280 additions and 20145 deletions

18
.env
View File

@@ -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

View File

@@ -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

View File

@@ -1,6 +0,0 @@
node_modules
.tmp
.cache
dist
build
.env

View File

@@ -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"]

View File

@@ -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'),
},
},
});

View File

@@ -1,7 +0,0 @@
export default {
rest: {
defaultLimit: 25,
maxLimit: 100,
withCount: true,
},
};

View File

@@ -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) },
},
});

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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"
}

View File

@@ -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"
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::application.application');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::application.application');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::application.application');

View File

@@ -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"
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::category.category');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::category.category');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::category.category');

View File

@@ -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
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::contact-message.contact-message');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::contact-message.contact-message');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::contact-message.contact-message');

View File

@@ -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
}
}
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::job.job');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::job.job');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::job.job');

View File

@@ -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
}
}
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::product.product');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::product.product');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::product.product');

View File

@@ -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"
]
}
}
}

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::setting.setting');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::setting.setting');

View File

@@ -1,2 +0,0 @@
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::setting.setting');

View File

@@ -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 }*/) {},
};

View File

@@ -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/**"
]
}

View File

@@ -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

View File

@@ -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
View 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
View 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
View File

@@ -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",

View File

@@ -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