Compare commits
No commits in common. "23c1d33adb123b39fb2af7fb0dc0f7cf5392fe92" and "1c6dfc4f8ba5fd2b8eed5553c60ff365168a9798" have entirely different histories.
23c1d33adb
...
1c6dfc4f8b
|
|
@ -1,79 +0,0 @@
|
||||||
# Dependencies
|
|
||||||
node_modules
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
|
|
||||||
# Build outputs
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Environment files
|
|
||||||
.env
|
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.docker
|
|
||||||
|
|
||||||
# IDE files
|
|
||||||
.vscode
|
|
||||||
.idea
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
*~
|
|
||||||
|
|
||||||
# OS generated files
|
|
||||||
.DS_Store
|
|
||||||
.DS_Store?
|
|
||||||
._*
|
|
||||||
.Spotlight-V100
|
|
||||||
.Trashes
|
|
||||||
ehthumbs.db
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Coverage directory
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Git
|
|
||||||
.git
|
|
||||||
.gitignore
|
|
||||||
|
|
||||||
# Docker
|
|
||||||
Dockerfile*
|
|
||||||
docker-compose*
|
|
||||||
.dockerignore
|
|
||||||
|
|
||||||
# Data directories (will be mounted as volumes)
|
|
||||||
data
|
|
||||||
uploads
|
|
||||||
results
|
|
||||||
|
|
||||||
# Temporary files
|
|
||||||
temp
|
|
||||||
tmp
|
|
||||||
|
|
||||||
# Test files
|
|
||||||
tests
|
|
||||||
test-*.sh
|
|
||||||
|
|
||||||
# Documentation
|
|
||||||
README.md
|
|
||||||
docs
|
|
||||||
infrastructure.md
|
|
||||||
|
|
||||||
# Other
|
|
||||||
.claude
|
|
||||||
.mcp.json
|
|
||||||
41
.env.docker
41
.env.docker
|
|
@ -1,41 +0,0 @@
|
||||||
# Application Configuration
|
|
||||||
NODE_ENV=development
|
|
||||||
PORT=3000
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
|
|
||||||
# CORS Configuration
|
|
||||||
CORS_ORIGIN=*
|
|
||||||
|
|
||||||
# Database Configuration
|
|
||||||
DB_HOST=postgres
|
|
||||||
DB_PORT=5432
|
|
||||||
DB_NAME=banatie_db
|
|
||||||
DB_USER=banatie_user
|
|
||||||
DB_PASSWORD=development_password
|
|
||||||
|
|
||||||
# MinIO Storage Configuration
|
|
||||||
STORAGE_TYPE=minio
|
|
||||||
MINIO_ENDPOINT=minio:9000
|
|
||||||
MINIO_ACCESS_KEY=minioadmin
|
|
||||||
MINIO_SECRET_KEY=minioadmin
|
|
||||||
MINIO_USE_SSL=false
|
|
||||||
MINIO_BUCKET_PREFIX=banatie
|
|
||||||
MINIO_PUBLIC_URL=http://localhost:9000
|
|
||||||
|
|
||||||
# AI Service Configuration (using the existing API key from .env)
|
|
||||||
GEMINI_API_KEY=AIzaSyBaOt9JMPGKA3811FL-ssf1n5Hh9Jauly8
|
|
||||||
|
|
||||||
# File Upload Configuration
|
|
||||||
MAX_FILE_SIZE=5242880
|
|
||||||
MAX_FILES=3
|
|
||||||
|
|
||||||
# Multi-tenancy Configuration
|
|
||||||
DEFAULT_ORG_ID=demo
|
|
||||||
DEFAULT_USER_ID=guest
|
|
||||||
|
|
||||||
# Directory Configuration (for Docker containers)
|
|
||||||
RESULTS_DIR=/app/results
|
|
||||||
UPLOADS_DIR=/app/uploads/temp
|
|
||||||
|
|
||||||
# Logging Configuration
|
|
||||||
LOG_LEVEL=info
|
|
||||||
|
|
@ -78,12 +78,3 @@ uploads/
|
||||||
# Temporary files
|
# Temporary files
|
||||||
temp/
|
temp/
|
||||||
tmp/
|
tmp/
|
||||||
|
|
||||||
# Docker data directories
|
|
||||||
data/
|
|
||||||
.env.docker
|
|
||||||
.env.production
|
|
||||||
|
|
||||||
# Docker volumes (persistent data)
|
|
||||||
postgres-data/
|
|
||||||
minio-data/
|
|
||||||
44
.mcp.json
44
.mcp.json
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"context7": {
|
|
||||||
"type": "stdio",
|
|
||||||
"command": "npx",
|
|
||||||
"args": [
|
|
||||||
"-y",
|
|
||||||
"@upstash/context7-mcp",
|
|
||||||
"--api-key",
|
|
||||||
"ctx7sk-48cb1995-935a-4cc5-b9b0-535d600ea5e6"
|
|
||||||
],
|
|
||||||
"env": {}
|
|
||||||
},
|
|
||||||
"brave-search": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": [
|
|
||||||
"-y",
|
|
||||||
"@modelcontextprotocol/server-brave-search"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"BRAVE_API_KEY": "BSAcRGGikEzY4B2j3NZ8Qy5NYh9l4HZ"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postgres": {
|
|
||||||
"command": "docker",
|
|
||||||
"args": ["run", "-i", "--rm", "-e", "DATABASE_URI", "crystaldba/postgres-mcp", "--access-mode=unrestricted"],
|
|
||||||
"env": {
|
|
||||||
"DATABASE_URI": "postgresql://postgres:postgres@localhost:5433/prime_db"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mastra": {
|
|
||||||
"type": "stdio",
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["@mastra/mcp-docs-server@latest"],
|
|
||||||
"env": {}
|
|
||||||
},
|
|
||||||
"browsermcp": {
|
|
||||||
"type": "stdio",
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["-y", "@browsermcp/mcp@latest"],
|
|
||||||
"env": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
76
Dockerfile
76
Dockerfile
|
|
@ -1,76 +0,0 @@
|
||||||
# Development stage - for docker-compose development with hot reload
|
|
||||||
FROM node:20-alpine AS development
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install pnpm globally
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
|
|
||||||
# Copy package files for dependency installation
|
|
||||||
COPY package*.json pnpm-lock.yaml ./
|
|
||||||
RUN pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Use development command with hot reload
|
|
||||||
CMD ["pnpm", "dev"]
|
|
||||||
|
|
||||||
# Builder stage - for production build
|
|
||||||
FROM node:20-alpine AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install pnpm globally
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
COPY package*.json pnpm-lock.yaml ./
|
|
||||||
|
|
||||||
# Install all dependencies (including dev dependencies for build)
|
|
||||||
RUN pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Build TypeScript to JavaScript
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
# Production stage - optimized final image
|
|
||||||
FROM node:20-alpine AS production
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Create non-root user for security
|
|
||||||
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
|
||||||
|
|
||||||
# Install pnpm globally
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
COPY --from=builder /app/package*.json ./
|
|
||||||
COPY --from=builder /app/pnpm-lock.yaml ./
|
|
||||||
|
|
||||||
# Install only production dependencies
|
|
||||||
RUN pnpm install --prod --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy built application
|
|
||||||
COPY --from=builder /app/dist ./dist
|
|
||||||
|
|
||||||
# Create required directories and set ownership
|
|
||||||
RUN mkdir -p logs && chown -R nodejs:nodejs /app
|
|
||||||
|
|
||||||
# Switch to non-root user
|
|
||||||
USER nodejs
|
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Health check
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
||||||
CMD node -e "require('http').request('http://localhost:3000/health', (res) => { \
|
|
||||||
process.exit(res.statusCode === 200 ? 0 : 1) \
|
|
||||||
}).on('error', () => process.exit(1)).end()"
|
|
||||||
|
|
||||||
# Start the application
|
|
||||||
CMD ["node", "dist/server.js"]
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: development
|
|
||||||
container_name: banatie-app-dev
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
volumes:
|
|
||||||
- ./src:/app/src # Hot reload for development
|
|
||||||
- ./logs:/app/logs # Persistent logs
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
minio:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=development
|
|
||||||
env_file:
|
|
||||||
- .env.docker
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: banatie-postgres-dev
|
|
||||||
ports:
|
|
||||||
- "5434:5432" # Avoid conflicts with other PostgreSQL instances
|
|
||||||
volumes:
|
|
||||||
- ./data/postgres:/var/lib/postgresql/data
|
|
||||||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: banatie_db
|
|
||||||
POSTGRES_USER: banatie_user
|
|
||||||
POSTGRES_PASSWORD: development_password
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie_db"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 40s
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
minio:
|
|
||||||
image: minio/minio:latest
|
|
||||||
container_name: banatie-minio-dev
|
|
||||||
ports:
|
|
||||||
- "9000:9000" # S3 API
|
|
||||||
- "9001:9001" # Web Console
|
|
||||||
volumes:
|
|
||||||
- ./data/minio:/data
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
environment:
|
|
||||||
MINIO_ROOT_USER: minioadmin
|
|
||||||
MINIO_ROOT_PASSWORD: minioadmin
|
|
||||||
command: server /data --console-address ":9001"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 40s
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
minio-init:
|
|
||||||
image: minio/mc:latest
|
|
||||||
container_name: banatie-minio-init
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
depends_on:
|
|
||||||
minio:
|
|
||||||
condition: service_healthy
|
|
||||||
entrypoint: >
|
|
||||||
/bin/sh -c "
|
|
||||||
echo 'Setting up MinIO alias...';
|
|
||||||
mc alias set minio http://minio:9000 minioadmin minioadmin;
|
|
||||||
|
|
||||||
echo 'Creating demo bucket...';
|
|
||||||
mc mb --ignore-existing minio/banatie-demo;
|
|
||||||
|
|
||||||
echo 'Setting up public read policy for generated images...';
|
|
||||||
mc anonymous set download minio/banatie-demo/users/guest/generated;
|
|
||||||
|
|
||||||
echo 'Creating banatie service user...';
|
|
||||||
mc admin user add minio banatie-user banatie-password;
|
|
||||||
|
|
||||||
echo 'Attaching readwrite policy to banatie user...';
|
|
||||||
mc admin policy attach minio readwrite --user=banatie-user;
|
|
||||||
|
|
||||||
echo 'Creating lifecycle policy for temp files (7 days retention)...';
|
|
||||||
cat > /tmp/lifecycle.json << EOF
|
|
||||||
{
|
|
||||||
\"Rules\": [
|
|
||||||
{
|
|
||||||
\"ID\": \"temp-files-cleanup\",
|
|
||||||
\"Status\": \"Enabled\",
|
|
||||||
\"Filter\": {
|
|
||||||
\"Prefix\": \"users/\"
|
|
||||||
},
|
|
||||||
\"Expiration\": {
|
|
||||||
\"Days\": 7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
mc ilm import minio/banatie-demo < /tmp/lifecycle.json;
|
|
||||||
|
|
||||||
echo 'MinIO initialization completed successfully!';
|
|
||||||
exit 0;
|
|
||||||
"
|
|
||||||
restart: "no"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
banatie-dev:
|
|
||||||
driver: bridge
|
|
||||||
name: banatie-dev-network
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres-data:
|
|
||||||
driver: local
|
|
||||||
minio-data:
|
|
||||||
driver: local
|
|
||||||
|
|
@ -1,937 +0,0 @@
|
||||||
# Banatie Service Infrastructure Documentation
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This document defines the complete containerization and deployment architecture for the Banatie AI image generation service with MinIO object storage and PostgreSQL database integration.
|
|
||||||
|
|
||||||
## Architecture Summary
|
|
||||||
|
|
||||||
### Core Principles
|
|
||||||
- **Complete Service Isolation**: Banatie ecosystem is fully isolated from core VPS services
|
|
||||||
- **Dedicated Database**: Separate PostgreSQL container exclusively for Banatie
|
|
||||||
- **S3-Compatible Storage**: MinIO for scalable object storage with multi-tenant support
|
|
||||||
- **Container-First Approach**: All components run as Docker containers
|
|
||||||
- **Network Segregation**: Internal communication via dedicated Docker networks
|
|
||||||
|
|
||||||
### Service Components
|
|
||||||
|
|
||||||
```
|
|
||||||
Banatie Ecosystem (Isolated)
|
|
||||||
├── Banatie App Container (Node.js/TypeScript/Express)
|
|
||||||
├── PostgreSQL Container (Dedicated instance)
|
|
||||||
└── MinIO Container (S3-compatible object storage)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Network Architecture
|
|
||||||
|
|
||||||
### Production Networks
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
networks:
|
|
||||||
banatie-network:
|
|
||||||
driver: bridge
|
|
||||||
internal: true # No external internet access
|
|
||||||
|
|
||||||
proxy-network:
|
|
||||||
external: true # Existing Caddy reverse proxy network
|
|
||||||
```
|
|
||||||
|
|
||||||
### Network Access Matrix
|
|
||||||
|
|
||||||
| Service | banatie-network | proxy-network | External Access |
|
|
||||||
|---------|----------------|---------------|-----------------|
|
|
||||||
| Banatie App | ✅ Internal | ✅ HTTP only | ❌ Direct |
|
|
||||||
| PostgreSQL | ✅ Internal | ❌ None | ❌ None |
|
|
||||||
| MinIO | ✅ Internal | ✅ Console only | ❌ Direct |
|
|
||||||
| Caddy Proxy | ❌ None | ✅ Routing | ✅ Internet |
|
|
||||||
|
|
||||||
### VPS Integration Points
|
|
||||||
|
|
||||||
**Isolation from Core Services:**
|
|
||||||
- **NO** shared resources with existing PostgreSQL (`/opt/services/`)
|
|
||||||
- **NO** access to NextCloud, Gitea, or other core services
|
|
||||||
- **ONLY** connection point: Caddy reverse proxy for HTTP routing
|
|
||||||
|
|
||||||
**Shared Infrastructure:**
|
|
||||||
- Caddy reverse proxy for SSL termination and routing
|
|
||||||
- Host filesystem for persistent data storage
|
|
||||||
- UFW firewall rules and security policies
|
|
||||||
|
|
||||||
## Directory Structure
|
|
||||||
|
|
||||||
### Development Environment
|
|
||||||
```
|
|
||||||
banatie-service/
|
|
||||||
├── src/ # Application source code
|
|
||||||
├── Dockerfile # Multi-stage container build
|
|
||||||
├── docker-compose.yml # Local development setup
|
|
||||||
├── .env.example # Environment template
|
|
||||||
├── .dockerignore # Build exclusions
|
|
||||||
└── data/ # Local development data
|
|
||||||
├── postgres/ # PostgreSQL data
|
|
||||||
└── minio/ # MinIO data
|
|
||||||
```
|
|
||||||
|
|
||||||
### Production Environment (VPS)
|
|
||||||
```
|
|
||||||
/opt/banatie/ # Isolated deployment directory
|
|
||||||
├── docker-compose.yml # Production configuration
|
|
||||||
├── .env # Production environment (secure)
|
|
||||||
├── Dockerfile # Production Dockerfile
|
|
||||||
├── data/ # Persistent data storage
|
|
||||||
│ ├── postgres/ # PostgreSQL data
|
|
||||||
│ └── minio/ # MinIO data
|
|
||||||
├── configs/ # Service configurations
|
|
||||||
├── logs/ # Application logs
|
|
||||||
└── scripts/ # Deployment scripts
|
|
||||||
```
|
|
||||||
|
|
||||||
## Container Specifications
|
|
||||||
|
|
||||||
### 1. Banatie Application Container
|
|
||||||
|
|
||||||
**Base Image**: `node:20-alpine`
|
|
||||||
**Build Strategy**: Multi-stage for optimization
|
|
||||||
**Runtime**: Node.js with TypeScript compilation
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
# Multi-stage build for production
|
|
||||||
FROM node:20-alpine AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package*.json pnpm-lock.yaml ./
|
|
||||||
RUN npm install -g pnpm && pnpm install --frozen-lockfile
|
|
||||||
COPY . .
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
FROM node:20-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
RUN npm install -g pnpm
|
|
||||||
COPY --from=builder /app/dist ./dist
|
|
||||||
COPY --from=builder /app/package*.json ./
|
|
||||||
COPY --from=builder /app/pnpm-lock.yaml ./
|
|
||||||
RUN pnpm install --prod --frozen-lockfile
|
|
||||||
EXPOSE 3000
|
|
||||||
CMD ["node", "dist/server.js"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key Features:**
|
|
||||||
- Hot-reload support in development
|
|
||||||
- Production-optimized build with dependencies pruning
|
|
||||||
- Health check endpoints for monitoring
|
|
||||||
- Structured logging to stdout
|
|
||||||
|
|
||||||
### 2. PostgreSQL Container
|
|
||||||
|
|
||||||
**Image**: `postgres:15-alpine`
|
|
||||||
**Purpose**: Metadata storage for user sessions, image metadata, organization data
|
|
||||||
**Data**: User accounts, image metadata, upload sessions, organization settings
|
|
||||||
|
|
||||||
**Database Schema:**
|
|
||||||
- `users` - User authentication and profiles
|
|
||||||
- `organizations` - Multi-tenant organization data
|
|
||||||
- `images` - Generated image metadata and references
|
|
||||||
- `sessions` - User session management
|
|
||||||
- `uploads` - Temporary upload tracking
|
|
||||||
|
|
||||||
### 3. MinIO Container
|
|
||||||
|
|
||||||
**Image**: `minio/minio:latest`
|
|
||||||
**Purpose**: S3-compatible object storage for images and files
|
|
||||||
**Ports**: 9000 (S3 API), 9001 (Web Console)
|
|
||||||
|
|
||||||
**Storage Strategy:**
|
|
||||||
- Persistent volumes for data durability
|
|
||||||
- Bucket-per-organization architecture
|
|
||||||
- Lifecycle policies for temporary file cleanup
|
|
||||||
- Presigned URLs for direct browser uploads
|
|
||||||
|
|
||||||
## Multi-Tenant Storage Architecture
|
|
||||||
|
|
||||||
### MinIO Bucket Organization
|
|
||||||
|
|
||||||
```
|
|
||||||
banatie-{org-id}/ # Organization bucket (e.g., banatie-demo)
|
|
||||||
├── users/
|
|
||||||
│ └── {user-id}/ # User-specific namespace
|
|
||||||
│ ├── generated/ # AI-generated images
|
|
||||||
│ │ ├── 2024/01/ # Date-based organization
|
|
||||||
│ │ └── thumbnails/ # Generated thumbnails
|
|
||||||
│ ├── references/ # User-uploaded reference images
|
|
||||||
│ └── temp/ # Temporary processing files (7-day TTL)
|
|
||||||
├── shared/ # Organization-wide shared resources
|
|
||||||
│ ├── templates/ # Shared image templates
|
|
||||||
│ └── public/ # Public organization assets
|
|
||||||
└── metadata/ # JSON metadata files
|
|
||||||
├── users.json # User directory metadata
|
|
||||||
└── policies.json # Access control policies
|
|
||||||
```
|
|
||||||
|
|
||||||
### Demo Organization Setup
|
|
||||||
|
|
||||||
**Default Configuration:**
|
|
||||||
- **Organization**: `demo` (org-id: demo)
|
|
||||||
- **User**: `guest` (user-id: guest)
|
|
||||||
- **Bucket**: `banatie-demo`
|
|
||||||
- **Access**: Public read for demo images
|
|
||||||
|
|
||||||
**Demo Bucket Structure:**
|
|
||||||
```
|
|
||||||
banatie-demo/
|
|
||||||
├── users/
|
|
||||||
│ └── guest/
|
|
||||||
│ ├── generated/ # Guest user's generated images
|
|
||||||
│ └── references/ # Guest user's reference uploads
|
|
||||||
└── shared/
|
|
||||||
└── examples/ # Example images for UI
|
|
||||||
```
|
|
||||||
|
|
||||||
## Environment Configuration
|
|
||||||
|
|
||||||
### Development Environment (.env)
|
|
||||||
|
|
||||||
```env
|
|
||||||
# Application Configuration
|
|
||||||
NODE_ENV=development
|
|
||||||
PORT=3000
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
|
|
||||||
# Database Configuration
|
|
||||||
DB_HOST=postgres
|
|
||||||
DB_PORT=5432
|
|
||||||
DB_NAME=banatie_db
|
|
||||||
DB_USER=banatie_user
|
|
||||||
DB_PASSWORD=development_password
|
|
||||||
|
|
||||||
# MinIO Configuration
|
|
||||||
STORAGE_TYPE=minio
|
|
||||||
MINIO_ENDPOINT=minio:9000
|
|
||||||
MINIO_ACCESS_KEY=minioadmin
|
|
||||||
MINIO_SECRET_KEY=minioadmin
|
|
||||||
MINIO_USE_SSL=false
|
|
||||||
MINIO_BUCKET_PREFIX=banatie
|
|
||||||
|
|
||||||
# AI Service Configuration
|
|
||||||
GEMINI_API_KEY=your_gemini_api_key_here
|
|
||||||
|
|
||||||
# Multi-tenancy Configuration
|
|
||||||
DEFAULT_ORG_ID=demo
|
|
||||||
DEFAULT_USER_ID=guest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Production Environment (.env.production)
|
|
||||||
|
|
||||||
```env
|
|
||||||
# Application Configuration
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=3000
|
|
||||||
LOG_LEVEL=info
|
|
||||||
|
|
||||||
# Database Configuration
|
|
||||||
DB_HOST=banatie-postgres
|
|
||||||
DB_PORT=5432
|
|
||||||
DB_NAME=banatie_db
|
|
||||||
DB_USER=banatie_user
|
|
||||||
DB_PASSWORD=${SECURE_DB_PASSWORD}
|
|
||||||
|
|
||||||
# MinIO Configuration
|
|
||||||
STORAGE_TYPE=minio
|
|
||||||
MINIO_ENDPOINT=banatie-minio:9000
|
|
||||||
MINIO_ACCESS_KEY=${SECURE_MINIO_ACCESS_KEY}
|
|
||||||
MINIO_SECRET_KEY=${SECURE_MINIO_SECRET_KEY}
|
|
||||||
MINIO_USE_SSL=false
|
|
||||||
MINIO_BUCKET_PREFIX=banatie
|
|
||||||
|
|
||||||
# AI Service Configuration
|
|
||||||
GEMINI_API_KEY=${SECURE_GEMINI_API_KEY}
|
|
||||||
|
|
||||||
# Multi-tenancy Configuration
|
|
||||||
DEFAULT_ORG_ID=demo
|
|
||||||
DEFAULT_USER_ID=guest
|
|
||||||
|
|
||||||
# Security
|
|
||||||
JWT_SECRET=${SECURE_JWT_SECRET}
|
|
||||||
SESSION_SECRET=${SECURE_SESSION_SECRET}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Docker Compose Configurations
|
|
||||||
|
|
||||||
### Development Configuration
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml (Local Development)
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: development
|
|
||||||
container_name: banatie-app-dev
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
volumes:
|
|
||||||
- ./src:/app/src # Hot reload
|
|
||||||
- ./logs:/app/logs
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- minio
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=development
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: banatie-postgres-dev
|
|
||||||
ports:
|
|
||||||
- "5433:5432" # Avoid conflicts with system PostgreSQL
|
|
||||||
volumes:
|
|
||||||
- ./data/postgres:/var/lib/postgresql/data
|
|
||||||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: banatie_db
|
|
||||||
POSTGRES_USER: banatie_user
|
|
||||||
POSTGRES_PASSWORD: development_password
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie_db"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
minio:
|
|
||||||
image: minio/minio:latest
|
|
||||||
container_name: banatie-minio-dev
|
|
||||||
ports:
|
|
||||||
- "9000:9000" # S3 API
|
|
||||||
- "9001:9001" # Web Console
|
|
||||||
volumes:
|
|
||||||
- ./data/minio:/data
|
|
||||||
networks:
|
|
||||||
- banatie-dev
|
|
||||||
environment:
|
|
||||||
MINIO_ROOT_USER: minioadmin
|
|
||||||
MINIO_ROOT_PASSWORD: minioadmin
|
|
||||||
command: server /data --console-address ":9001"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
networks:
|
|
||||||
banatie-dev:
|
|
||||||
driver: bridge
|
|
||||||
```
|
|
||||||
|
|
||||||
### Production Configuration
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml (Production on VPS)
|
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
banatie-app:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
target: production
|
|
||||||
container_name: banatie-app
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- banatie-network
|
|
||||||
- proxy-network
|
|
||||||
depends_on:
|
|
||||||
banatie-postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
banatie-minio:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=production
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
volumes:
|
|
||||||
- ./logs:/app/logs
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
banatie-postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: banatie-postgres
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- banatie-network
|
|
||||||
volumes:
|
|
||||||
- ./data/postgres:/var/lib/postgresql/data
|
|
||||||
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: banatie_db
|
|
||||||
POSTGRES_USER: banatie_user
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U banatie_user -d banatie_db"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
banatie-minio:
|
|
||||||
image: minio/minio:latest
|
|
||||||
container_name: banatie-minio
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- banatie-network
|
|
||||||
- proxy-network
|
|
||||||
volumes:
|
|
||||||
- ./data/minio:/data
|
|
||||||
environment:
|
|
||||||
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
|
|
||||||
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
|
|
||||||
command: server /data --console-address ":9001"
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
networks:
|
|
||||||
banatie-network:
|
|
||||||
driver: bridge
|
|
||||||
internal: true # No external internet access
|
|
||||||
|
|
||||||
proxy-network:
|
|
||||||
external: true # Existing Caddy network
|
|
||||||
```
|
|
||||||
|
|
||||||
## Caddy Integration
|
|
||||||
|
|
||||||
### Caddy Configuration Addition
|
|
||||||
|
|
||||||
Add to existing Caddyfile in `/opt/services/configs/caddy/Caddyfile`:
|
|
||||||
|
|
||||||
```caddy
|
|
||||||
# Banatie App - Main API
|
|
||||||
banatie.app {
|
|
||||||
reverse_proxy banatie-app:3000
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
header {
|
|
||||||
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
|
||||||
X-Content-Type-Options "nosniff"
|
|
||||||
X-Frame-Options "DENY"
|
|
||||||
X-XSS-Protection "1; mode=block"
|
|
||||||
Referrer-Policy "strict-origin-when-cross-origin"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Rate limiting
|
|
||||||
rate_limit {
|
|
||||||
zone banatie_api {
|
|
||||||
key {remote_host}
|
|
||||||
events 100
|
|
||||||
window 1m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
log {
|
|
||||||
output file /opt/services/logs/banatie_access.log
|
|
||||||
format json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# MinIO Console - Admin Interface
|
|
||||||
minio.banatie.app {
|
|
||||||
reverse_proxy banatie-minio:9001
|
|
||||||
|
|
||||||
# Security headers for console
|
|
||||||
header {
|
|
||||||
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
|
||||||
X-Content-Type-Options "nosniff"
|
|
||||||
X-Frame-Options "SAMEORIGIN"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
log {
|
|
||||||
output file /opt/services/logs/minio_console_access.log
|
|
||||||
format json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# MinIO S3 API - Direct file access
|
|
||||||
s3.banatie.app {
|
|
||||||
reverse_proxy banatie-minio:9000
|
|
||||||
|
|
||||||
# CORS for browser uploads
|
|
||||||
header {
|
|
||||||
Access-Control-Allow-Origin "*"
|
|
||||||
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
|
||||||
Access-Control-Allow-Headers "Content-Type, Authorization"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Rate limiting for uploads
|
|
||||||
rate_limit {
|
|
||||||
zone banatie_s3 {
|
|
||||||
key {remote_host}
|
|
||||||
events 50
|
|
||||||
window 1m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
log {
|
|
||||||
output file /opt/services/logs/minio_s3_access.log
|
|
||||||
format json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Service Implementation Strategy
|
|
||||||
|
|
||||||
### 1. Storage Service Abstraction
|
|
||||||
|
|
||||||
Create `src/services/StorageService.ts`:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export interface StorageService {
|
|
||||||
// Bucket management
|
|
||||||
createBucket(orgId: string): Promise<void>;
|
|
||||||
deleteBucket(orgId: string): Promise<void>;
|
|
||||||
listBuckets(): Promise<string[]>;
|
|
||||||
|
|
||||||
// File operations
|
|
||||||
uploadFile(orgId: string, userId: string, fileName: string, buffer: Buffer, contentType: string): Promise<string>;
|
|
||||||
downloadFile(orgId: string, userId: string, fileName: string): Promise<Buffer>;
|
|
||||||
deleteFile(orgId: string, userId: string, fileName: string): Promise<void>;
|
|
||||||
|
|
||||||
// URL generation
|
|
||||||
getPresignedUploadUrl(orgId: string, userId: string, fileName: string, expirySeconds: number): Promise<string>;
|
|
||||||
getPresignedDownloadUrl(orgId: string, userId: string, fileName: string, expirySeconds: number): Promise<string>;
|
|
||||||
|
|
||||||
// File management
|
|
||||||
listUserFiles(orgId: string, userId: string): Promise<FileMetadata[]>;
|
|
||||||
moveFile(fromPath: string, toPath: string): Promise<void>;
|
|
||||||
copyFile(fromPath: string, toPath: string): Promise<void>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. MinIO Implementation
|
|
||||||
|
|
||||||
Create `src/services/MinioStorageService.ts`:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Client as MinioClient } from 'minio';
|
|
||||||
import { StorageService } from './StorageService';
|
|
||||||
|
|
||||||
export class MinioStorageService implements StorageService {
|
|
||||||
private client: MinioClient;
|
|
||||||
private bucketPrefix: string;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
endpoint: string,
|
|
||||||
accessKey: string,
|
|
||||||
secretKey: string,
|
|
||||||
useSSL: boolean = false,
|
|
||||||
bucketPrefix: string = 'banatie'
|
|
||||||
) {
|
|
||||||
this.client = new MinioClient({
|
|
||||||
endPoint: endpoint.replace(/^https?:\/\//, ''),
|
|
||||||
port: useSSL ? 443 : 9000,
|
|
||||||
useSSL,
|
|
||||||
accessKey,
|
|
||||||
secretKey
|
|
||||||
});
|
|
||||||
this.bucketPrefix = bucketPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getBucketName(orgId: string): string {
|
|
||||||
return `${this.bucketPrefix}-${orgId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getFilePath(userId: string, category: 'generated' | 'references' | 'temp', fileName: string): string {
|
|
||||||
const now = new Date();
|
|
||||||
const year = now.getFullYear();
|
|
||||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
||||||
|
|
||||||
return `users/${userId}/${category}/${year}/${month}/${fileName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation methods...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Database Schema
|
|
||||||
|
|
||||||
Create `scripts/init-db.sql`:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- Banatie Database Initialization
|
|
||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
||||||
|
|
||||||
-- Organizations table
|
|
||||||
CREATE TABLE organizations (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
slug VARCHAR(100) UNIQUE NOT NULL,
|
|
||||||
settings JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Users table
|
|
||||||
CREATE TABLE users (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
||||||
username VARCHAR(100) NOT NULL,
|
|
||||||
email VARCHAR(255),
|
|
||||||
role VARCHAR(50) DEFAULT 'user',
|
|
||||||
settings JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
UNIQUE(organization_id, username)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Images table
|
|
||||||
CREATE TABLE images (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
||||||
filename VARCHAR(255) NOT NULL,
|
|
||||||
file_path VARCHAR(500) NOT NULL,
|
|
||||||
original_prompt TEXT,
|
|
||||||
enhanced_prompt TEXT,
|
|
||||||
model_used VARCHAR(100),
|
|
||||||
file_size BIGINT,
|
|
||||||
content_type VARCHAR(100),
|
|
||||||
metadata JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Upload sessions table (for tracking multi-part uploads)
|
|
||||||
CREATE TABLE upload_sessions (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
||||||
session_data JSONB NOT NULL,
|
|
||||||
expires_at TIMESTAMP WITH TIME ZONE,
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Create indexes
|
|
||||||
CREATE INDEX idx_users_org_id ON users(organization_id);
|
|
||||||
CREATE INDEX idx_images_user_id ON images(user_id);
|
|
||||||
CREATE INDEX idx_images_created_at ON images(created_at);
|
|
||||||
CREATE INDEX idx_upload_sessions_user_id ON upload_sessions(user_id);
|
|
||||||
CREATE INDEX idx_upload_sessions_expires_at ON upload_sessions(expires_at);
|
|
||||||
|
|
||||||
-- Insert demo organization and user
|
|
||||||
INSERT INTO organizations (id, name, slug) VALUES
|
|
||||||
('00000000-0000-0000-0000-000000000001', 'Demo Organization', 'demo');
|
|
||||||
|
|
||||||
INSERT INTO users (id, organization_id, username, role) VALUES
|
|
||||||
('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', 'guest', 'user');
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Local Development Setup
|
|
||||||
|
|
||||||
1. **Clone Repository**
|
|
||||||
```bash
|
|
||||||
git clone <repository-url>
|
|
||||||
cd banatie-service
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Environment Configuration**
|
|
||||||
```bash
|
|
||||||
cp .env.example .env
|
|
||||||
# Edit .env with development settings
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Start Development Environment**
|
|
||||||
```bash
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Verify Services**
|
|
||||||
```bash
|
|
||||||
# Check service status
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# View logs
|
|
||||||
docker-compose logs -f app
|
|
||||||
|
|
||||||
# Access services
|
|
||||||
# App: http://localhost:3000
|
|
||||||
# MinIO Console: http://localhost:9001 (minioadmin/minioadmin)
|
|
||||||
# PostgreSQL: localhost:5433
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Development with Hot Reload**
|
|
||||||
```bash
|
|
||||||
# Edit source files in src/
|
|
||||||
# Changes automatically reload in container
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing Workflow
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run tests in development environment
|
|
||||||
docker-compose exec app pnpm test
|
|
||||||
|
|
||||||
# Run with coverage
|
|
||||||
docker-compose exec app pnpm test:coverage
|
|
||||||
|
|
||||||
# Run linting
|
|
||||||
docker-compose exec app pnpm lint
|
|
||||||
```
|
|
||||||
|
|
||||||
## Production Deployment
|
|
||||||
|
|
||||||
### VPS Deployment Process
|
|
||||||
|
|
||||||
1. **Prepare VPS Directory**
|
|
||||||
```bash
|
|
||||||
# SSH to VPS
|
|
||||||
ssh usul-vps
|
|
||||||
|
|
||||||
# Create Banatie directory
|
|
||||||
sudo mkdir -p /opt/banatie
|
|
||||||
sudo chown usul:usul /opt/banatie
|
|
||||||
cd /opt/banatie
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Clone and Configure**
|
|
||||||
```bash
|
|
||||||
# Clone repository
|
|
||||||
git clone <repository-url> .
|
|
||||||
|
|
||||||
# Create production environment
|
|
||||||
cp .env.example .env
|
|
||||||
# Edit .env with production settings and secure passwords
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Generate Secure Credentials**
|
|
||||||
```bash
|
|
||||||
# Generate secure passwords
|
|
||||||
DB_PASSWORD=$(openssl rand -base64 32 | tr -d '\n\r ')
|
|
||||||
MINIO_ACCESS_KEY=$(openssl rand -base64 20 | tr -d '\n\r ')
|
|
||||||
MINIO_SECRET_KEY=$(openssl rand -base64 40 | tr -d '\n\r ')
|
|
||||||
JWT_SECRET=$(openssl rand -base64 64 | tr -d '\n\r ')
|
|
||||||
|
|
||||||
# Add to .env file
|
|
||||||
echo "DB_PASSWORD=$DB_PASSWORD" >> .env
|
|
||||||
echo "MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY" >> .env
|
|
||||||
echo "MINIO_SECRET_KEY=$MINIO_SECRET_KEY" >> .env
|
|
||||||
echo "JWT_SECRET=$JWT_SECRET" >> .env
|
|
||||||
|
|
||||||
# Secure the file
|
|
||||||
chmod 600 .env
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Update Caddy Configuration**
|
|
||||||
```bash
|
|
||||||
# Add Banatie routes to Caddyfile
|
|
||||||
sudo nano /opt/services/configs/caddy/Caddyfile
|
|
||||||
# Add the Banatie configuration from above
|
|
||||||
|
|
||||||
# Reload Caddy
|
|
||||||
cd /opt/services
|
|
||||||
./manage-services.sh caddy reload
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Deploy Services**
|
|
||||||
```bash
|
|
||||||
cd /opt/banatie
|
|
||||||
|
|
||||||
# Build and start services
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# Verify deployment
|
|
||||||
docker-compose ps
|
|
||||||
docker-compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **Verify Deployment**
|
|
||||||
```bash
|
|
||||||
# Check health endpoints
|
|
||||||
curl https://banatie.app/health
|
|
||||||
curl https://minio.banatie.app/minio/health/live
|
|
||||||
|
|
||||||
# Check logs
|
|
||||||
docker-compose logs banatie-app
|
|
||||||
docker-compose logs banatie-postgres
|
|
||||||
docker-compose logs banatie-minio
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Update Process
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# SSH to VPS
|
|
||||||
ssh usul-vps
|
|
||||||
cd /opt/banatie
|
|
||||||
|
|
||||||
# Pull latest changes
|
|
||||||
git pull origin main
|
|
||||||
|
|
||||||
# Rebuild and restart
|
|
||||||
docker-compose build banatie-app
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# Verify update
|
|
||||||
docker-compose logs -f banatie-app
|
|
||||||
curl https://banatie.app/health
|
|
||||||
```
|
|
||||||
|
|
||||||
## Monitoring and Maintenance
|
|
||||||
|
|
||||||
### Health Checks
|
|
||||||
|
|
||||||
**Application Health Check** (`/health`):
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"status": "healthy",
|
|
||||||
"timestamp": "2024-01-01T12:00:00.000Z",
|
|
||||||
"services": {
|
|
||||||
"database": "connected",
|
|
||||||
"minio": "connected",
|
|
||||||
"gemini_api": "accessible"
|
|
||||||
},
|
|
||||||
"version": "1.0.0"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**MinIO Health Check** (`/minio/health/live`):
|
|
||||||
- Returns 200 OK when MinIO is operational
|
|
||||||
- Used by Docker healthcheck and monitoring
|
|
||||||
|
|
||||||
### Log Management
|
|
||||||
|
|
||||||
**Application Logs**:
|
|
||||||
- Location: `/opt/banatie/logs/`
|
|
||||||
- Format: Structured JSON
|
|
||||||
- Rotation: Daily with 30-day retention
|
|
||||||
|
|
||||||
**Access Logs**:
|
|
||||||
- Caddy logs: `/opt/services/logs/banatie_*.log`
|
|
||||||
- Format: JSON with request/response details
|
|
||||||
|
|
||||||
### Backup Strategy
|
|
||||||
|
|
||||||
**Database Backup**:
|
|
||||||
```bash
|
|
||||||
# Create backup
|
|
||||||
docker exec banatie-postgres pg_dump -U banatie_user banatie_db > banatie_db_backup.sql
|
|
||||||
|
|
||||||
# Restore backup
|
|
||||||
docker exec -i banatie-postgres psql -U banatie_user banatie_db < banatie_db_backup.sql
|
|
||||||
```
|
|
||||||
|
|
||||||
**MinIO Data Backup**:
|
|
||||||
```bash
|
|
||||||
# Backup MinIO data
|
|
||||||
sudo tar -czf banatie_minio_backup.tar.gz -C /opt/banatie/data minio/
|
|
||||||
|
|
||||||
# Restore MinIO data
|
|
||||||
sudo tar -xzf banatie_minio_backup.tar.gz -C /opt/banatie/data
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Considerations
|
|
||||||
|
|
||||||
### Container Security
|
|
||||||
- Non-root users in containers
|
|
||||||
- Read-only root filesystems where possible
|
|
||||||
- Resource limits (memory, CPU)
|
|
||||||
- Health checks for automatic restart
|
|
||||||
|
|
||||||
### Network Security
|
|
||||||
- Internal network isolation
|
|
||||||
- No direct external access to database or MinIO
|
|
||||||
- Rate limiting at proxy level
|
|
||||||
- HTTPS-only external access
|
|
||||||
|
|
||||||
### Data Security
|
|
||||||
- Encrypted environment variables
|
|
||||||
- Secure secret generation
|
|
||||||
- Regular credential rotation
|
|
||||||
- Audit logging
|
|
||||||
|
|
||||||
### Access Control
|
|
||||||
- MinIO bucket policies per organization
|
|
||||||
- PostgreSQL row-level security
|
|
||||||
- JWT-based API authentication
|
|
||||||
- Role-based access control
|
|
||||||
|
|
||||||
## Future Scalability
|
|
||||||
|
|
||||||
### Horizontal Scaling Options
|
|
||||||
- Multiple Banatie app containers behind load balancer
|
|
||||||
- MinIO distributed mode for storage scaling
|
|
||||||
- PostgreSQL read replicas for read scaling
|
|
||||||
- Redis for session storage and caching
|
|
||||||
|
|
||||||
### Multi-Region Deployment
|
|
||||||
- Regional MinIO clusters
|
|
||||||
- Database replication
|
|
||||||
- CDN integration for static assets
|
|
||||||
- Geo-distributed deployment
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
**Container Won't Start**:
|
|
||||||
```bash
|
|
||||||
# Check logs
|
|
||||||
docker-compose logs [service-name]
|
|
||||||
|
|
||||||
# Check resource usage
|
|
||||||
docker stats
|
|
||||||
|
|
||||||
# Rebuild container
|
|
||||||
docker-compose build [service-name]
|
|
||||||
docker-compose up -d [service-name]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Database Connection Issues**:
|
|
||||||
```bash
|
|
||||||
# Test database connectivity
|
|
||||||
docker exec banatie-postgres pg_isready -U banatie_user -d banatie_db
|
|
||||||
|
|
||||||
# Check environment variables
|
|
||||||
docker exec banatie-app env | grep DB_
|
|
||||||
|
|
||||||
# Restart database
|
|
||||||
docker-compose restart banatie-postgres
|
|
||||||
```
|
|
||||||
|
|
||||||
**MinIO Access Issues**:
|
|
||||||
```bash
|
|
||||||
# Check MinIO status
|
|
||||||
docker exec banatie-minio mc admin info local
|
|
||||||
|
|
||||||
# Test S3 API
|
|
||||||
curl -f http://localhost:9000/minio/health/live
|
|
||||||
|
|
||||||
# Check access keys
|
|
||||||
docker exec banatie-app env | grep MINIO_
|
|
||||||
```
|
|
||||||
|
|
||||||
**Network Connectivity**:
|
|
||||||
```bash
|
|
||||||
# Check networks
|
|
||||||
docker network ls
|
|
||||||
docker network inspect banatie_banatie-network
|
|
||||||
|
|
||||||
# Test internal connectivity
|
|
||||||
docker exec banatie-app ping banatie-postgres
|
|
||||||
docker exec banatie-app ping banatie-minio
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Document Version**: 1.0
|
|
||||||
**Last Updated**: 2024-09-26
|
|
||||||
**Maintained By**: Banatie Development Team
|
|
||||||
|
|
@ -43,8 +43,7 @@
|
||||||
"express-rate-limit": "^7.4.1",
|
"express-rate-limit": "^7.4.1",
|
||||||
"express-validator": "^7.2.0",
|
"express-validator": "^7.2.0",
|
||||||
"helmet": "^8.0.0",
|
"helmet": "^8.0.0",
|
||||||
"mime": "3.0.0",
|
"mime": "^4.1.0",
|
||||||
"minio": "^8.0.6",
|
|
||||||
"multer": "^2.0.2",
|
"multer": "^2.0.2",
|
||||||
"winston": "^3.17.0"
|
"winston": "^3.17.0"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
310
pnpm-lock.yaml
310
pnpm-lock.yaml
|
|
@ -30,11 +30,8 @@ importers:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.1.0
|
version: 8.1.0
|
||||||
mime:
|
mime:
|
||||||
specifier: 3.0.0
|
specifier: ^4.1.0
|
||||||
version: 3.0.0
|
version: 4.1.0
|
||||||
minio:
|
|
||||||
specifier: ^8.0.6
|
|
||||||
version: 8.0.6
|
|
||||||
multer:
|
multer:
|
||||||
specifier: ^2.0.2
|
specifier: ^2.0.2
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
|
|
@ -770,9 +767,6 @@ packages:
|
||||||
resolution: {integrity: sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==}
|
resolution: {integrity: sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@zxing/text-encoding@0.9.0':
|
|
||||||
resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==}
|
|
||||||
|
|
||||||
accepts@2.0.0:
|
accepts@2.0.0:
|
||||||
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
|
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
@ -832,10 +826,6 @@ packages:
|
||||||
asynckit@0.4.0:
|
asynckit@0.4.0:
|
||||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||||
|
|
||||||
available-typed-arrays@1.0.7:
|
|
||||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
babel-jest@29.7.0:
|
babel-jest@29.7.0:
|
||||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
|
|
@ -878,9 +868,6 @@ packages:
|
||||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
block-stream2@2.1.0:
|
|
||||||
resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==}
|
|
||||||
|
|
||||||
body-parser@2.2.0:
|
body-parser@2.2.0:
|
||||||
resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
|
resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -895,9 +882,6 @@ packages:
|
||||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
browser-or-node@2.1.1:
|
|
||||||
resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==}
|
|
||||||
|
|
||||||
browserslist@4.26.2:
|
browserslist@4.26.2:
|
||||||
resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==}
|
resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==}
|
||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
|
|
@ -910,10 +894,6 @@ packages:
|
||||||
bser@2.1.1:
|
bser@2.1.1:
|
||||||
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
||||||
|
|
||||||
buffer-crc32@1.0.0:
|
|
||||||
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
|
|
||||||
engines: {node: '>=8.0.0'}
|
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1:
|
buffer-equal-constant-time@1.0.1:
|
||||||
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
|
|
@ -932,10 +912,6 @@ packages:
|
||||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
call-bind@1.0.8:
|
|
||||||
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
call-bound@1.0.4:
|
call-bound@1.0.4:
|
||||||
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -1065,10 +1041,6 @@ packages:
|
||||||
supports-color:
|
supports-color:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
decode-uri-component@0.2.2:
|
|
||||||
resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
|
|
||||||
engines: {node: '>=0.10'}
|
|
||||||
|
|
||||||
dedent@1.7.0:
|
dedent@1.7.0:
|
||||||
resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==}
|
resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -1084,10 +1056,6 @@ packages:
|
||||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
define-data-property@1.1.4:
|
|
||||||
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
delayed-stream@1.0.0:
|
delayed-stream@1.0.0:
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
@ -1248,9 +1216,6 @@ packages:
|
||||||
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
eventemitter3@5.0.1:
|
|
||||||
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
|
|
||||||
|
|
||||||
execa@5.1.1:
|
execa@5.1.1:
|
||||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -1299,10 +1264,6 @@ packages:
|
||||||
fast-safe-stringify@2.1.1:
|
fast-safe-stringify@2.1.1:
|
||||||
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
||||||
|
|
||||||
fast-xml-parser@4.5.3:
|
|
||||||
resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
fastq@1.19.1:
|
fastq@1.19.1:
|
||||||
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
|
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
|
||||||
|
|
||||||
|
|
@ -1320,10 +1281,6 @@ packages:
|
||||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
filter-obj@1.1.0:
|
|
||||||
resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
finalhandler@2.1.0:
|
finalhandler@2.1.0:
|
||||||
resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
|
resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
@ -1346,10 +1303,6 @@ packages:
|
||||||
fn.name@1.1.0:
|
fn.name@1.1.0:
|
||||||
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
||||||
|
|
||||||
for-each@0.3.5:
|
|
||||||
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
form-data@4.0.4:
|
form-data@4.0.4:
|
||||||
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
@ -1463,9 +1416,6 @@ packages:
|
||||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
has-property-descriptors@1.0.2:
|
|
||||||
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
|
|
||||||
|
|
||||||
has-symbols@1.1.0:
|
has-symbols@1.1.0:
|
||||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -1540,14 +1490,6 @@ packages:
|
||||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
ipaddr.js@2.2.0:
|
|
||||||
resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==}
|
|
||||||
engines: {node: '>= 10'}
|
|
||||||
|
|
||||||
is-arguments@1.2.0:
|
|
||||||
resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-arrayish@0.2.1:
|
is-arrayish@0.2.1:
|
||||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||||
|
|
||||||
|
|
@ -1558,10 +1500,6 @@ packages:
|
||||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
is-callable@1.2.7:
|
|
||||||
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-core-module@2.16.1:
|
is-core-module@2.16.1:
|
||||||
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
|
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
@ -1578,10 +1516,6 @@ packages:
|
||||||
resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==}
|
resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
is-generator-function@1.1.0:
|
|
||||||
resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-glob@4.0.3:
|
is-glob@4.0.3:
|
||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -1593,18 +1527,10 @@ packages:
|
||||||
is-promise@4.0.0:
|
is-promise@4.0.0:
|
||||||
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
|
||||||
|
|
||||||
is-regex@1.2.1:
|
|
||||||
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
is-stream@2.0.1:
|
is-stream@2.0.1:
|
||||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
is-typed-array@1.1.15:
|
|
||||||
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
isexe@2.0.0:
|
isexe@2.0.0:
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||||
|
|
||||||
|
|
@ -1910,9 +1836,9 @@ packages:
|
||||||
engines: {node: '>=4.0.0'}
|
engines: {node: '>=4.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
mime@3.0.0:
|
mime@4.1.0:
|
||||||
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
|
resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=16'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
mimic-fn@2.1.0:
|
mimic-fn@2.1.0:
|
||||||
|
|
@ -1929,10 +1855,6 @@ packages:
|
||||||
minimist@1.2.8:
|
minimist@1.2.8:
|
||||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||||
|
|
||||||
minio@8.0.6:
|
|
||||||
resolution: {integrity: sha512-sOeh2/b/XprRmEtYsnNRFtOqNRTPDvYtMWh+spWlfsuCV/+IdxNeKVUMKLqI7b5Dr07ZqCPuaRGU/rB9pZYVdQ==}
|
|
||||||
engines: {node: ^16 || ^18 || >=20}
|
|
||||||
|
|
||||||
mkdirp@0.5.6:
|
mkdirp@0.5.6:
|
||||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -2073,10 +1995,6 @@ packages:
|
||||||
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
|
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0:
|
|
||||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
@ -2116,10 +2034,6 @@ packages:
|
||||||
resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
|
resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
|
||||||
engines: {node: '>=0.6'}
|
engines: {node: '>=0.6'}
|
||||||
|
|
||||||
query-string@7.1.3:
|
|
||||||
resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
queue-microtask@1.2.3:
|
queue-microtask@1.2.3:
|
||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
|
|
||||||
|
|
@ -2184,10 +2098,6 @@ packages:
|
||||||
safe-buffer@5.2.1:
|
safe-buffer@5.2.1:
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||||
|
|
||||||
safe-regex-test@1.1.0:
|
|
||||||
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
safe-stable-stringify@2.5.0:
|
safe-stable-stringify@2.5.0:
|
||||||
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -2195,9 +2105,6 @@ packages:
|
||||||
safer-buffer@2.1.2:
|
safer-buffer@2.1.2:
|
||||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||||
|
|
||||||
sax@1.4.1:
|
|
||||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
|
||||||
|
|
||||||
semver@6.3.1:
|
semver@6.3.1:
|
||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -2215,10 +2122,6 @@ packages:
|
||||||
resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
|
resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
|
||||||
engines: {node: '>= 18'}
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
|
||||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
setprototypeof@1.2.0:
|
setprototypeof@1.2.0:
|
||||||
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
||||||
|
|
||||||
|
|
@ -2270,10 +2173,6 @@ packages:
|
||||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
split-on-first@1.1.0:
|
|
||||||
resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
sprintf-js@1.0.3:
|
sprintf-js@1.0.3:
|
||||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||||
|
|
||||||
|
|
@ -2292,20 +2191,10 @@ packages:
|
||||||
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
stream-chain@2.2.5:
|
|
||||||
resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==}
|
|
||||||
|
|
||||||
stream-json@1.9.1:
|
|
||||||
resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==}
|
|
||||||
|
|
||||||
streamsearch@1.1.0:
|
streamsearch@1.1.0:
|
||||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
|
|
||||||
strict-uri-encode@2.0.0:
|
|
||||||
resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
|
|
||||||
string-length@4.0.2:
|
string-length@4.0.2:
|
||||||
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
|
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -2333,9 +2222,6 @@ packages:
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
strnum@1.1.2:
|
|
||||||
resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==}
|
|
||||||
|
|
||||||
superagent@10.2.3:
|
superagent@10.2.3:
|
||||||
resolution: {integrity: sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==}
|
resolution: {integrity: sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==}
|
||||||
engines: {node: '>=14.18.0'}
|
engines: {node: '>=14.18.0'}
|
||||||
|
|
@ -2371,9 +2257,6 @@ packages:
|
||||||
text-hex@1.0.0:
|
text-hex@1.0.0:
|
||||||
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
||||||
|
|
||||||
through2@4.0.2:
|
|
||||||
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
|
|
||||||
|
|
||||||
tmpl@1.0.5:
|
tmpl@1.0.5:
|
||||||
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
|
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
|
||||||
|
|
||||||
|
|
@ -2493,9 +2376,6 @@ packages:
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
util@0.12.5:
|
|
||||||
resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
|
|
||||||
|
|
||||||
uuid@9.0.1:
|
uuid@9.0.1:
|
||||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -2515,19 +2395,12 @@ packages:
|
||||||
walker@1.0.8:
|
walker@1.0.8:
|
||||||
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
||||||
|
|
||||||
web-encoding@1.1.5:
|
|
||||||
resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==}
|
|
||||||
|
|
||||||
webidl-conversions@3.0.1:
|
webidl-conversions@3.0.1:
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
|
||||||
whatwg-url@5.0.0:
|
whatwg-url@5.0.0:
|
||||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
|
||||||
which-typed-array@1.1.19:
|
|
||||||
resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
@ -2571,14 +2444,6 @@ packages:
|
||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
xml2js@0.6.2:
|
|
||||||
resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==}
|
|
||||||
engines: {node: '>=4.0.0'}
|
|
||||||
|
|
||||||
xmlbuilder@11.0.1:
|
|
||||||
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
|
|
||||||
engines: {node: '>=4.0'}
|
|
||||||
|
|
||||||
xtend@4.0.2:
|
xtend@4.0.2:
|
||||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||||
engines: {node: '>=0.4'}
|
engines: {node: '>=0.4'}
|
||||||
|
|
@ -3381,9 +3246,6 @@ snapshots:
|
||||||
'@typescript-eslint/types': 8.44.0
|
'@typescript-eslint/types': 8.44.0
|
||||||
eslint-visitor-keys: 4.2.1
|
eslint-visitor-keys: 4.2.1
|
||||||
|
|
||||||
'@zxing/text-encoding@0.9.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
accepts@2.0.0:
|
accepts@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-types: 3.0.1
|
mime-types: 3.0.1
|
||||||
|
|
@ -3435,10 +3297,6 @@ snapshots:
|
||||||
|
|
||||||
asynckit@0.4.0: {}
|
asynckit@0.4.0: {}
|
||||||
|
|
||||||
available-typed-arrays@1.0.7:
|
|
||||||
dependencies:
|
|
||||||
possible-typed-array-names: 1.1.0
|
|
||||||
|
|
||||||
babel-jest@29.7.0(@babel/core@7.28.4):
|
babel-jest@29.7.0(@babel/core@7.28.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.4
|
'@babel/core': 7.28.4
|
||||||
|
|
@ -3504,10 +3362,6 @@ snapshots:
|
||||||
|
|
||||||
binary-extensions@2.3.0: {}
|
binary-extensions@2.3.0: {}
|
||||||
|
|
||||||
block-stream2@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
|
|
||||||
body-parser@2.2.0:
|
body-parser@2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes: 3.1.2
|
bytes: 3.1.2
|
||||||
|
|
@ -3535,8 +3389,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range: 7.1.1
|
fill-range: 7.1.1
|
||||||
|
|
||||||
browser-or-node@2.1.1: {}
|
|
||||||
|
|
||||||
browserslist@4.26.2:
|
browserslist@4.26.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
baseline-browser-mapping: 2.8.6
|
baseline-browser-mapping: 2.8.6
|
||||||
|
|
@ -3553,8 +3405,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
node-int64: 0.4.0
|
node-int64: 0.4.0
|
||||||
|
|
||||||
buffer-crc32@1.0.0: {}
|
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1: {}
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
@ -3570,13 +3420,6 @@ snapshots:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
|
|
||||||
call-bind@1.0.8:
|
|
||||||
dependencies:
|
|
||||||
call-bind-apply-helpers: 1.0.2
|
|
||||||
es-define-property: 1.0.1
|
|
||||||
get-intrinsic: 1.3.0
|
|
||||||
set-function-length: 1.2.2
|
|
||||||
|
|
||||||
call-bound@1.0.4:
|
call-bound@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
|
|
@ -3711,20 +3554,12 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
supports-color: 5.5.0
|
supports-color: 5.5.0
|
||||||
|
|
||||||
decode-uri-component@0.2.2: {}
|
|
||||||
|
|
||||||
dedent@1.7.0: {}
|
dedent@1.7.0: {}
|
||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
deepmerge@4.3.1: {}
|
deepmerge@4.3.1: {}
|
||||||
|
|
||||||
define-data-property@1.1.4:
|
|
||||||
dependencies:
|
|
||||||
es-define-property: 1.0.1
|
|
||||||
es-errors: 1.3.0
|
|
||||||
gopd: 1.2.0
|
|
||||||
|
|
||||||
delayed-stream@1.0.0: {}
|
delayed-stream@1.0.0: {}
|
||||||
|
|
||||||
depd@2.0.0: {}
|
depd@2.0.0: {}
|
||||||
|
|
@ -3902,8 +3737,6 @@ snapshots:
|
||||||
|
|
||||||
etag@1.8.1: {}
|
etag@1.8.1: {}
|
||||||
|
|
||||||
eventemitter3@5.0.1: {}
|
|
||||||
|
|
||||||
execa@5.1.1:
|
execa@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
|
|
@ -3987,10 +3820,6 @@ snapshots:
|
||||||
|
|
||||||
fast-safe-stringify@2.1.1: {}
|
fast-safe-stringify@2.1.1: {}
|
||||||
|
|
||||||
fast-xml-parser@4.5.3:
|
|
||||||
dependencies:
|
|
||||||
strnum: 1.1.2
|
|
||||||
|
|
||||||
fastq@1.19.1:
|
fastq@1.19.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify: 1.1.0
|
reusify: 1.1.0
|
||||||
|
|
@ -4009,8 +3838,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
|
|
||||||
filter-obj@1.1.0: {}
|
|
||||||
|
|
||||||
finalhandler@2.1.0:
|
finalhandler@2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.3(supports-color@5.5.0)
|
debug: 4.4.3(supports-color@5.5.0)
|
||||||
|
|
@ -4041,10 +3868,6 @@ snapshots:
|
||||||
|
|
||||||
fn.name@1.1.0: {}
|
fn.name@1.1.0: {}
|
||||||
|
|
||||||
for-each@0.3.5:
|
|
||||||
dependencies:
|
|
||||||
is-callable: 1.2.7
|
|
||||||
|
|
||||||
form-data@4.0.4:
|
form-data@4.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
asynckit: 0.4.0
|
asynckit: 0.4.0
|
||||||
|
|
@ -4180,10 +4003,6 @@ snapshots:
|
||||||
|
|
||||||
has-flag@4.0.0: {}
|
has-flag@4.0.0: {}
|
||||||
|
|
||||||
has-property-descriptors@1.0.2:
|
|
||||||
dependencies:
|
|
||||||
es-define-property: 1.0.1
|
|
||||||
|
|
||||||
has-symbols@1.1.0: {}
|
has-symbols@1.1.0: {}
|
||||||
|
|
||||||
has-tostringtag@1.0.2:
|
has-tostringtag@1.0.2:
|
||||||
|
|
@ -4250,13 +4069,6 @@ snapshots:
|
||||||
|
|
||||||
ipaddr.js@1.9.1: {}
|
ipaddr.js@1.9.1: {}
|
||||||
|
|
||||||
ipaddr.js@2.2.0: {}
|
|
||||||
|
|
||||||
is-arguments@1.2.0:
|
|
||||||
dependencies:
|
|
||||||
call-bound: 1.0.4
|
|
||||||
has-tostringtag: 1.0.2
|
|
||||||
|
|
||||||
is-arrayish@0.2.1: {}
|
is-arrayish@0.2.1: {}
|
||||||
|
|
||||||
is-arrayish@0.3.4: {}
|
is-arrayish@0.3.4: {}
|
||||||
|
|
@ -4265,8 +4077,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions: 2.3.0
|
binary-extensions: 2.3.0
|
||||||
|
|
||||||
is-callable@1.2.7: {}
|
|
||||||
|
|
||||||
is-core-module@2.16.1:
|
is-core-module@2.16.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
|
|
@ -4277,13 +4087,6 @@ snapshots:
|
||||||
|
|
||||||
is-generator-fn@2.1.0: {}
|
is-generator-fn@2.1.0: {}
|
||||||
|
|
||||||
is-generator-function@1.1.0:
|
|
||||||
dependencies:
|
|
||||||
call-bound: 1.0.4
|
|
||||||
get-proto: 1.0.1
|
|
||||||
has-tostringtag: 1.0.2
|
|
||||||
safe-regex-test: 1.1.0
|
|
||||||
|
|
||||||
is-glob@4.0.3:
|
is-glob@4.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
|
@ -4292,19 +4095,8 @@ snapshots:
|
||||||
|
|
||||||
is-promise@4.0.0: {}
|
is-promise@4.0.0: {}
|
||||||
|
|
||||||
is-regex@1.2.1:
|
|
||||||
dependencies:
|
|
||||||
call-bound: 1.0.4
|
|
||||||
gopd: 1.2.0
|
|
||||||
has-tostringtag: 1.0.2
|
|
||||||
hasown: 2.0.2
|
|
||||||
|
|
||||||
is-stream@2.0.1: {}
|
is-stream@2.0.1: {}
|
||||||
|
|
||||||
is-typed-array@1.1.15:
|
|
||||||
dependencies:
|
|
||||||
which-typed-array: 1.1.19
|
|
||||||
|
|
||||||
isexe@2.0.0: {}
|
isexe@2.0.0: {}
|
||||||
|
|
||||||
istanbul-lib-coverage@3.2.2: {}
|
istanbul-lib-coverage@3.2.2: {}
|
||||||
|
|
@ -4781,7 +4573,7 @@ snapshots:
|
||||||
|
|
||||||
mime@2.6.0: {}
|
mime@2.6.0: {}
|
||||||
|
|
||||||
mime@3.0.0: {}
|
mime@4.1.0: {}
|
||||||
|
|
||||||
mimic-fn@2.1.0: {}
|
mimic-fn@2.1.0: {}
|
||||||
|
|
||||||
|
|
@ -4795,23 +4587,6 @@ snapshots:
|
||||||
|
|
||||||
minimist@1.2.8: {}
|
minimist@1.2.8: {}
|
||||||
|
|
||||||
minio@8.0.6:
|
|
||||||
dependencies:
|
|
||||||
async: 3.2.6
|
|
||||||
block-stream2: 2.1.0
|
|
||||||
browser-or-node: 2.1.1
|
|
||||||
buffer-crc32: 1.0.0
|
|
||||||
eventemitter3: 5.0.1
|
|
||||||
fast-xml-parser: 4.5.3
|
|
||||||
ipaddr.js: 2.2.0
|
|
||||||
lodash: 4.17.21
|
|
||||||
mime-types: 2.1.35
|
|
||||||
query-string: 7.1.3
|
|
||||||
stream-json: 1.9.1
|
|
||||||
through2: 4.0.2
|
|
||||||
web-encoding: 1.1.5
|
|
||||||
xml2js: 0.6.2
|
|
||||||
|
|
||||||
mkdirp@0.5.6:
|
mkdirp@0.5.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
|
|
@ -4941,8 +4716,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up: 4.1.0
|
find-up: 4.1.0
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0: {}
|
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
prettier-linter-helpers@1.0.0:
|
prettier-linter-helpers@1.0.0:
|
||||||
|
|
@ -4977,13 +4750,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
side-channel: 1.1.0
|
side-channel: 1.1.0
|
||||||
|
|
||||||
query-string@7.1.3:
|
|
||||||
dependencies:
|
|
||||||
decode-uri-component: 0.2.2
|
|
||||||
filter-obj: 1.1.0
|
|
||||||
split-on-first: 1.1.0
|
|
||||||
strict-uri-encode: 2.0.0
|
|
||||||
|
|
||||||
queue-microtask@1.2.3: {}
|
queue-microtask@1.2.3: {}
|
||||||
|
|
||||||
range-parser@1.2.1: {}
|
range-parser@1.2.1: {}
|
||||||
|
|
@ -5045,18 +4811,10 @@ snapshots:
|
||||||
|
|
||||||
safe-buffer@5.2.1: {}
|
safe-buffer@5.2.1: {}
|
||||||
|
|
||||||
safe-regex-test@1.1.0:
|
|
||||||
dependencies:
|
|
||||||
call-bound: 1.0.4
|
|
||||||
es-errors: 1.3.0
|
|
||||||
is-regex: 1.2.1
|
|
||||||
|
|
||||||
safe-stable-stringify@2.5.0: {}
|
safe-stable-stringify@2.5.0: {}
|
||||||
|
|
||||||
safer-buffer@2.1.2: {}
|
safer-buffer@2.1.2: {}
|
||||||
|
|
||||||
sax@1.4.1: {}
|
|
||||||
|
|
||||||
semver@6.3.1: {}
|
semver@6.3.1: {}
|
||||||
|
|
||||||
semver@7.7.2: {}
|
semver@7.7.2: {}
|
||||||
|
|
@ -5086,15 +4844,6 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
set-function-length@1.2.2:
|
|
||||||
dependencies:
|
|
||||||
define-data-property: 1.1.4
|
|
||||||
es-errors: 1.3.0
|
|
||||||
function-bind: 1.1.2
|
|
||||||
get-intrinsic: 1.3.0
|
|
||||||
gopd: 1.2.0
|
|
||||||
has-property-descriptors: 1.0.2
|
|
||||||
|
|
||||||
setprototypeof@1.2.0: {}
|
setprototypeof@1.2.0: {}
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
|
|
@ -5152,8 +4901,6 @@ snapshots:
|
||||||
|
|
||||||
source-map@0.6.1: {}
|
source-map@0.6.1: {}
|
||||||
|
|
||||||
split-on-first@1.1.0: {}
|
|
||||||
|
|
||||||
sprintf-js@1.0.3: {}
|
sprintf-js@1.0.3: {}
|
||||||
|
|
||||||
stack-trace@0.0.10: {}
|
stack-trace@0.0.10: {}
|
||||||
|
|
@ -5166,16 +4913,8 @@ snapshots:
|
||||||
|
|
||||||
statuses@2.0.2: {}
|
statuses@2.0.2: {}
|
||||||
|
|
||||||
stream-chain@2.2.5: {}
|
|
||||||
|
|
||||||
stream-json@1.9.1:
|
|
||||||
dependencies:
|
|
||||||
stream-chain: 2.2.5
|
|
||||||
|
|
||||||
streamsearch@1.1.0: {}
|
streamsearch@1.1.0: {}
|
||||||
|
|
||||||
strict-uri-encode@2.0.0: {}
|
|
||||||
|
|
||||||
string-length@4.0.2:
|
string-length@4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
char-regex: 1.0.2
|
char-regex: 1.0.2
|
||||||
|
|
@ -5201,8 +4940,6 @@ snapshots:
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
strnum@1.1.2: {}
|
|
||||||
|
|
||||||
superagent@10.2.3:
|
superagent@10.2.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
component-emitter: 1.3.1
|
component-emitter: 1.3.1
|
||||||
|
|
@ -5250,10 +4987,6 @@ snapshots:
|
||||||
|
|
||||||
text-hex@1.0.0: {}
|
text-hex@1.0.0: {}
|
||||||
|
|
||||||
through2@4.0.2:
|
|
||||||
dependencies:
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
|
|
||||||
tmpl@1.0.5: {}
|
tmpl@1.0.5: {}
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
|
|
@ -5345,14 +5078,6 @@ snapshots:
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
util@0.12.5:
|
|
||||||
dependencies:
|
|
||||||
inherits: 2.0.4
|
|
||||||
is-arguments: 1.2.0
|
|
||||||
is-generator-function: 1.1.0
|
|
||||||
is-typed-array: 1.1.15
|
|
||||||
which-typed-array: 1.1.19
|
|
||||||
|
|
||||||
uuid@9.0.1: {}
|
uuid@9.0.1: {}
|
||||||
|
|
||||||
v8-to-istanbul@9.3.0:
|
v8-to-istanbul@9.3.0:
|
||||||
|
|
@ -5369,12 +5094,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
makeerror: 1.0.12
|
makeerror: 1.0.12
|
||||||
|
|
||||||
web-encoding@1.1.5:
|
|
||||||
dependencies:
|
|
||||||
util: 0.12.5
|
|
||||||
optionalDependencies:
|
|
||||||
'@zxing/text-encoding': 0.9.0
|
|
||||||
|
|
||||||
webidl-conversions@3.0.1: {}
|
webidl-conversions@3.0.1: {}
|
||||||
|
|
||||||
whatwg-url@5.0.0:
|
whatwg-url@5.0.0:
|
||||||
|
|
@ -5382,16 +5101,6 @@ snapshots:
|
||||||
tr46: 0.0.3
|
tr46: 0.0.3
|
||||||
webidl-conversions: 3.0.1
|
webidl-conversions: 3.0.1
|
||||||
|
|
||||||
which-typed-array@1.1.19:
|
|
||||||
dependencies:
|
|
||||||
available-typed-arrays: 1.0.7
|
|
||||||
call-bind: 1.0.8
|
|
||||||
call-bound: 1.0.4
|
|
||||||
for-each: 0.3.5
|
|
||||||
get-proto: 1.0.1
|
|
||||||
gopd: 1.2.0
|
|
||||||
has-tostringtag: 1.0.2
|
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|
@ -5435,13 +5144,6 @@ snapshots:
|
||||||
|
|
||||||
ws@8.18.3: {}
|
ws@8.18.3: {}
|
||||||
|
|
||||||
xml2js@0.6.2:
|
|
||||||
dependencies:
|
|
||||||
sax: 1.4.1
|
|
||||||
xmlbuilder: 11.0.1
|
|
||||||
|
|
||||||
xmlbuilder@11.0.1: {}
|
|
||||||
|
|
||||||
xtend@4.0.2: {}
|
xtend@4.0.2: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
|
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
-- Banatie Database Initialization Script
|
|
||||||
-- This script creates the database schema for the Banatie image generation service
|
|
||||||
|
|
||||||
-- Enable UUID extension for generating UUIDs
|
|
||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
||||||
|
|
||||||
-- Organizations table - for multi-tenant support
|
|
||||||
CREATE TABLE organizations (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
slug VARCHAR(100) UNIQUE NOT NULL,
|
|
||||||
settings JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Users table - users within organizations
|
|
||||||
CREATE TABLE users (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
||||||
username VARCHAR(100) NOT NULL,
|
|
||||||
email VARCHAR(255),
|
|
||||||
role VARCHAR(50) DEFAULT 'user',
|
|
||||||
settings JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
UNIQUE(organization_id, username)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Images table - metadata for generated and uploaded images
|
|
||||||
CREATE TABLE images (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
||||||
filename VARCHAR(255) NOT NULL,
|
|
||||||
file_path VARCHAR(500), -- Legacy: local file path (for backward compatibility)
|
|
||||||
minio_key VARCHAR(500), -- MinIO object key
|
|
||||||
url VARCHAR(1000), -- Public or presigned URL to access the image
|
|
||||||
original_prompt TEXT,
|
|
||||||
enhanced_prompt TEXT,
|
|
||||||
model_used VARCHAR(100),
|
|
||||||
file_size BIGINT,
|
|
||||||
content_type VARCHAR(100),
|
|
||||||
category VARCHAR(50) DEFAULT 'generated', -- 'generated', 'references', 'temp'
|
|
||||||
metadata JSONB DEFAULT '{}',
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Sessions table - for tracking user upload sessions
|
|
||||||
CREATE TABLE upload_sessions (
|
|
||||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
||||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
||||||
session_data JSONB NOT NULL,
|
|
||||||
expires_at TIMESTAMP WITH TIME ZONE,
|
|
||||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- Create indexes for better query performance
|
|
||||||
CREATE INDEX idx_users_org_id ON users(organization_id);
|
|
||||||
CREATE INDEX idx_users_username ON users(username);
|
|
||||||
CREATE INDEX idx_images_user_id ON images(user_id);
|
|
||||||
CREATE INDEX idx_images_created_at ON images(created_at);
|
|
||||||
CREATE INDEX idx_images_category ON images(category);
|
|
||||||
CREATE INDEX idx_images_minio_key ON images(minio_key);
|
|
||||||
CREATE INDEX idx_upload_sessions_user_id ON upload_sessions(user_id);
|
|
||||||
CREATE INDEX idx_upload_sessions_expires_at ON upload_sessions(expires_at);
|
|
||||||
|
|
||||||
-- Insert demo organization and user for development/testing
|
|
||||||
INSERT INTO organizations (id, name, slug, settings) VALUES
|
|
||||||
('00000000-0000-0000-0000-000000000001', 'Demo Organization', 'demo', '{"description": "Default demo organization for testing"}');
|
|
||||||
|
|
||||||
INSERT INTO users (id, organization_id, username, email, role, settings) VALUES
|
|
||||||
('00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000001', 'guest', 'guest@demo.banatie.app', 'user', '{"description": "Default guest user for testing"}');
|
|
||||||
|
|
||||||
-- Create a function to update updated_at timestamp
|
|
||||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
||||||
RETURNS TRIGGER AS $$
|
|
||||||
BEGIN
|
|
||||||
NEW.updated_at = NOW();
|
|
||||||
RETURN NEW;
|
|
||||||
END;
|
|
||||||
$$ language 'plpgsql';
|
|
||||||
|
|
||||||
-- Create triggers to automatically update updated_at
|
|
||||||
CREATE TRIGGER update_organizations_updated_at
|
|
||||||
BEFORE UPDATE ON organizations
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
||||||
|
|
||||||
CREATE TRIGGER update_users_updated_at
|
|
||||||
BEFORE UPDATE ON users
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
||||||
|
|
||||||
CREATE TRIGGER update_images_updated_at
|
|
||||||
BEFORE UPDATE ON images
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
||||||
|
|
||||||
-- Display initialization completion message
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
RAISE NOTICE 'Banatie database initialization completed successfully!';
|
|
||||||
RAISE NOTICE 'Created tables: organizations, users, images, upload_sessions';
|
|
||||||
RAISE NOTICE 'Created demo organization (id: 00000000-0000-0000-0000-000000000001) with guest user';
|
|
||||||
END $$;
|
|
||||||
|
|
@ -48,7 +48,7 @@ export const validateGenerateRequest = (
|
||||||
try {
|
try {
|
||||||
enhancementOptions = JSON.parse(enhancementOptions);
|
enhancementOptions = JSON.parse(enhancementOptions);
|
||||||
req.body.enhancementOptions = enhancementOptions;
|
req.body.enhancementOptions = enhancementOptions;
|
||||||
} catch {
|
} catch (error) {
|
||||||
errors.push("enhancementOptions must be valid JSON");
|
errors.push("enhancementOptions must be valid JSON");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { GoogleGenAI } from "@google/genai";
|
import { GoogleGenAI } from "@google/genai";
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
import mime from "mime";
|
||||||
const mime = require("mime") as any;
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue