From e963f2bcdee21d5038f2c2569cab0d166e8435dd Mon Sep 17 00:00:00 2001 From: Greirson Lee-Thorp Date: Sun, 4 May 2025 10:29:48 -0700 Subject: [PATCH] feat: Improve dev experience, Improve Environmental Variable and Folder Control, resolves BASE_URL junk (#49) * feat: Add ALLOWED_IFRAME_ORIGINS configuration and update security headers (#47) - Introduced ALLOWED_IFRAME_ORIGINS environment variable to specify trusted origins for iframe embedding. - Updated security headers middleware to conditionally allow specified origins in Content Security Policy. - Enhanced documentation in README.md to explain the new configuration and its security implications. Fixes #35 * feat: Update .env.example and .gitignore for improved configuration management - Enhanced .env.example with detailed comments for environment variables, including upload settings, security options, and notification configurations. - Updated .gitignore to include additional editor and OS-specific files, ensuring a cleaner repository. - Modified package.json to add a predev script for Node.js version validation and adjusted the dev script for nodemon. - Improved server.js shutdown handling to prevent multiple shutdowns and ensure graceful exits. - Refactored config/index.js to log loaded environment variables and ensure the upload directory exists based on environment settings. - Cleaned up fileUtils.js by removing unused functions and improving logging for directory creation. This commit enhances clarity and maintainability of configuration settings and improves application shutdown behavior. * feat: Update Docker configuration and documentation for upload handling - Explicitly set the upload directory environment variable in docker-compose.yml to ensure clarity in file storage. - Simplified the Dockerfile by removing the creation of the local_uploads directory, as it is now managed by the host system. - Enhanced README.md to reflect changes in upload directory management and provide clearer instructions for users. - Removed outdated development configuration files to streamline the development setup. This commit improves the clarity and usability of the Docker setup for file uploads. * feat: Add Local Development Guide and update README for clarity - Introduced a comprehensive LOCAL_DEVELOPMENT.md file with setup instructions, testing guidelines, and troubleshooting tips for local development. - Updated README.md to include a link to the new Local Development Guide and revised sections for clarity regarding upload directory management. - Enhanced the Quick Start section to direct users to the dedicated local development documentation. This commit improves the onboarding experience for developers and provides clear instructions for local setup. * feat: Implement BASE_URL configuration for asset management and API requests - Added BASE_URL configuration to README.md, emphasizing the need for a trailing slash when deploying under a subpath. - Updated index.html and login.html to utilize BASE_URL for linking stylesheets, icons, and API requests, ensuring correct asset loading. - Enhanced app.js to replace placeholders with the actual BASE_URL during HTML rendering. - Implemented a validation check in config/index.js to ensure BASE_URL is a valid URL and ends with a trailing slash. This commit improves the flexibility of the application for different deployment scenarios and enhances asset management. Fixes #34, Fixes #39, Fixes #38 * Update app.js, borked some of the css n such * resolved BASE_URL breaking frontend * fix: Update BASE_URL handling and security headers - Ensured BASE_URL has a trailing slash in app.js to prevent asset loading issues. - Refactored index.html and login.html to remove leading slashes from API paths for correct concatenation with BASE_URL. - Enhanced security headers middleware to include 'connect-src' directive in Content Security Policy. This commit addresses issues with asset management and improves security configurations. --- .env.example | 78 +++++-- .gitignore | 36 +++- Dockerfile | 4 +- LOCAL_DEVELOPMENT.md | 122 +++++++++++ README.md | 101 ++++----- dev/.dockerignore | 50 ----- dev/.env.dev.example | 22 -- dev/Dockerfile.dev | 46 ---- dev/README.md | 73 ------- dev/dev.sh | 74 ------- dev/docker-compose.dev.yml | 33 --- docker-compose.yml | 2 + package-lock.json | 432 ++++++++++++++++++------------------- package.json | 5 +- public/index.html | 27 ++- public/login.html | 20 +- src/app.js | 11 +- src/config/index.js | 171 ++++++++++++--- src/middleware/security.js | 1 + src/server.js | 8 +- src/utils/fileUtils.js | 23 +- 21 files changed, 685 insertions(+), 654 deletions(-) create mode 100644 LOCAL_DEVELOPMENT.md delete mode 100644 dev/.dockerignore delete mode 100644 dev/.env.dev.example delete mode 100644 dev/Dockerfile.dev delete mode 100644 dev/README.md delete mode 100755 dev/dev.sh delete mode 100644 dev/docker-compose.dev.yml diff --git a/.env.example b/.env.example index af9e4b2..93b3137 100644 --- a/.env.example +++ b/.env.example @@ -1,18 +1,68 @@ -# Server Configuration -PORT=3000 # The port the server will listen on -BASE_URL=http://localhost:3000 # The base URL for the application +######################################### +# SERVER CONFIGURATION +######################################### -# Upload Settings -MAX_FILE_SIZE=1024 # Maximum file size in MB -AUTO_UPLOAD=false # Enable automatic upload on file selection +# Port for the server (default: 3000) +PORT=3000 -# Security -DUMBDROP_PIN= # Optional PIN protection (4-10 digits) -DUMBDROP_TITLE=DumbDrop # Site title displayed in header +# Base URL for the application (default: http://localhost:PORT) +BASE_URL=http://localhost:3000/ -# Notifications (Optional) -APPRISE_URL= # Apprise URL for notifications (e.g., tgram://bottoken/ChatID) -APPRISE_MESSAGE=New file uploaded - {filename} ({size}), Storage used {storage} -APPRISE_SIZE_UNIT=auto # Size unit for notifications (auto, B, KB, MB, GB, TB) +# Node environment (default: development) +NODE_ENV=development -DEMO_MODE=false +######################################### +# FILE UPLOAD SETTINGS +######################################### + +# Maximum file size in MB (default: 1024) +MAX_FILE_SIZE=1024 + +# Directory for uploads (Docker/production; optional) +UPLOAD_DIR= + +# Directory for uploads (local dev, fallback: './local_uploads') +LOCAL_UPLOAD_DIR=./local_uploads + +# Comma-separated list of allowed file extensions (optional, e.g. .jpg,.png,.pdf) +# ALLOWED_EXTENSIONS=.jpg,.png,.pdf +ALLOWED_EXTENSIONS= + +######################################### +# SECURITY +######################################### + +# PIN protection (4-10 digits, optional) +# DUMBDROP_PIN=1234 +DUMBDROP_PIN= + +######################################### +# UI SETTINGS +######################################### + +# Site title displayed in header (default: DumbDrop) +DUMBDROP_TITLE=DumbDrop + +######################################### +# NOTIFICATION SETTINGS +######################################### + +# Apprise URL for notifications (optional) +APPRISE_URL= + +# Notification message template (default: New file uploaded {filename} ({size}), Storage used {storage}) +APPRISE_MESSAGE=New file uploaded {filename} ({size}), Storage used {storage} + +# Size unit for notifications (B, KB, MB, GB, TB, or Auto; default: Auto) +APPRISE_SIZE_UNIT=Auto + +######################################### +# ADVANCED +######################################### + +# Enable automatic upload on file selection (true/false, default: false) +AUTO_UPLOAD=false + +# Comma-separated list of origins allowed to embed the app in an iframe (optional) +# ALLOWED_IFRAME_ORIGINS=https://example.com,https://another.com +ALLOWED_IFRAME_ORIGINS= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 715357a..7a98752 100644 --- a/.gitignore +++ b/.gitignore @@ -203,4 +203,38 @@ Thumbs.db *.log .env.* !.env.example -!dev/.env.dev.example \ No newline at end of file +!dev/.env.dev.example + +# Added by Claude Task Master +dev-debug.log +# Environment variables +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +# OS specific +# Task files +.windsurfrules +README-task-master.md +.cursor/mcp.json +.cursor/rules/cursor_rules.mdc +.cursor/rules/dev_workflow.mdc +.cursor/rules/self_improve.mdc +.cursor/rules/taskmaster.mdc +scripts/example_prd.txt +scripts/prd.txt +tasks/task_001.txt +tasks/task_002.txt +tasks/task_003.txt +tasks/task_004.txt +tasks/task_005.txt +tasks/task_006.txt +tasks/task_007.txt +tasks/task_008.txt +tasks/task_009.txt +tasks/task_010.txt +tasks/tasks.json diff --git a/Dockerfile b/Dockerfile index aca9278..04a9654 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,8 +32,8 @@ ENV NODE_ENV=development RUN npm install && \ npm cache clean --force -# Create upload directories -RUN mkdir -p uploads local_uploads +# Create upload directory +RUN mkdir -p uploads # Copy source with specific paths to avoid unnecessary files COPY src/ ./src/ diff --git a/LOCAL_DEVELOPMENT.md b/LOCAL_DEVELOPMENT.md new file mode 100644 index 0000000..40765f0 --- /dev/null +++ b/LOCAL_DEVELOPMENT.md @@ -0,0 +1,122 @@ +# Local Development (Recommended Quick Start) + +## Prerequisites + +- **Node.js** >= 20.0.0 + _Why?_: The app uses features only available in Node 20+. +- **npm** (comes with Node.js) +- **Python 3** (for notification testing, optional) +- **Apprise** (for notification testing, optional) + +## Setup Instructions + +1. **Clone the repository** + ```bash + git clone https://github.com/yourusername/dumbdrop.git + cd dumbdrop + ``` + +2. **Copy and configure environment variables** + ```bash + cp .env.example .env + ``` + - Open `.env` in your editor and review the variables. + - At minimum, set: + - `PORT=3000` + - `LOCAL_UPLOAD_DIR=./local_uploads` + - `MAX_FILE_SIZE=1024` + - `DUMBDROP_PIN=` (optional, for PIN protection) + - `APPRISE_URL=` (optional, for notifications) + +3. **Install dependencies** + ```bash + npm install + ``` + +4. **Start the development server** + ```bash + npm run dev + ``` + - You should see output like: + ``` + DumbDrop server running on http://localhost:3000 + ``` + +5. **Open the app** + - Go to [http://localhost:3000](http://localhost:3000) in your browser. + +--- + +## Testing File Uploads + +- Drag and drop files onto the web interface. +- Supported file types: _All_, unless restricted by `ALLOWED_EXTENSIONS` in `.env`. +- Maximum file size: as set by `MAX_FILE_SIZE` (default: 1024 MB). +- Uploaded files are stored in the directory specified by `LOCAL_UPLOAD_DIR` (default: `./local_uploads`). +- To verify uploads: + - Check the `local_uploads` folder for your files. + - The UI will show a success message on upload. + +--- + +## Notification Testing (Python/Apprise) + +If you want to test notifications (e.g., for new uploads): + +1. **Install Python 3** + - [Download Python](https://www.python.org/downloads/) if not already installed. + +2. **Install Apprise** + ```bash + pip install apprise + ``` + +3. **Configure Apprise in `.env`** + - Set `APPRISE_URL` to your notification service URL (see [Apprise documentation](https://github.com/caronc/apprise)). + - Example for a local test: + ``` + APPRISE_URL=mailto://your@email.com + ``` + +4. **Trigger a test notification** + - Upload a file via the web UI. + - If configured, you should receive a notification. + +--- + +## Troubleshooting + +**Problem:** Port already in use +**Solution:** +- Change the `PORT` in `.env` to a free port. + +**Problem:** "Cannot find module 'express'" +**Solution:** +- Run `npm install` to install dependencies. + +**Problem:** File uploads not working +**Solution:** +- Ensure `LOCAL_UPLOAD_DIR` exists and is writable. +- Check file size and extension restrictions in `.env`. + +**Problem:** Notifications not sent +**Solution:** +- Verify `APPRISE_URL` is set and correct. +- Ensure Apprise is installed and accessible. + +**Problem:** Permission denied on uploads +**Solution:** +- Make sure your user has write permissions to `local_uploads`. + +**Problem:** Environment variables not loading +**Solution:** +- Double-check that `.env` exists and is formatted correctly. +- Restart the server after making changes. + +--- + +## Additional Notes + +- For Docker-based development, see the "Quick Start" and "Docker Compose" sections in the main README. +- For more advanced configuration, review the "Configuration" section in the main README. +- If you encounter issues not listed here, please open an issue on GitHub or check the Discussions tab. \ No newline at end of file diff --git a/README.md b/README.md index 6a42a50..b867f1c 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,11 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up ## Table of Contents - [Quick Start](#quick-start) +- [Production Deployment with Docker](#production-deployment-with-docker) +- [Local Development (Recommended Quick Start)](LOCAL_DEVELOPMENT.md) - [Features](#features) - [Configuration](#configuration) - [Security](#security) -- [Development](#development) - [Technical Details](#technical-details) - [Demo Mode](demo.md) - [Contributing](#contributing) @@ -19,17 +20,13 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up ## Quick Start -### Prerequisites -- Docker (recommended) -- Node.js >=20.0.0 (for local development) - ### Option 1: Docker (For Dummies) ```bash # Pull and run with one command -docker run -p 3000:3000 -v ./local_uploads:/app/uploads dumbwareio/dumbdrop:latest +docker run -p 3000:3000 -v ./uploads:/app/uploads dumbwareio/dumbdrop:latest ``` 1. Go to http://localhost:3000 -2. Upload a File - It'll show up in ./local_uploads +2. Upload a File - It'll show up in ./uploads 3. Celebrate on how dumb easy this was ### Option 2: Docker Compose (For Dummies who like customizing) @@ -42,8 +39,10 @@ services: - 3000:3000 volumes: # Where your uploaded files will land - - ./local_uploads:/app/uploads + - ./uploads:/app/uploads environment: + # Explicitly set upload directory inside the container + UPLOAD_DIR: /app/uploads # The title shown in the web interface DUMBDROP_TITLE: DumbDrop # Maximum file size in MB @@ -55,42 +54,21 @@ services: # The base URL for the application BASE_URL: http://localhost:3000 ``` - Then run: ```bash docker compose up -d ``` - 1. Go to http://localhost:3000 -2. Upload a File - It'll show up in ./local_uploads +2. Upload a File - It'll show up in ./uploads 3. Rejoice in the glory of your dumb uploads +> **Note:** The `UPLOAD_DIR` environment variable is now explicitly set to `/app/uploads` in the container. The Dockerfile only creates the `uploads` directory, not `local_uploads`. The host directory `./uploads` is mounted to `/app/uploads` for persistent storage. + ### Option 3: Running Locally (For Developers) -> If you're a developer, check out our [Dev Guide](#development) for the dumb setup. +For local development setup, troubleshooting, and advanced usage, see the dedicated guide: -1. Install dependencies: -```bash -npm install -``` - -2. Set environment variables in `.env`: -```env -PORT=3000 # Port to run the server on -MAX_FILE_SIZE=1024 # Maximum file size in MB -DUMBDROP_PIN=123456 # Optional PIN protection -``` - -3. Start the server: -```bash -npm start -``` - -#### Windows Users -If you're using Windows PowerShell with Docker, use this format for paths: -```bash -docker run -p 3000:3000 -v "${PWD}\local_uploads:/app/uploads" dumbwareio/dumbdrop:latest -``` +👉 [Local Development Guide](LOCAL_DEVELOPMENT.md) ## Features @@ -111,23 +89,33 @@ docker run -p 3000:3000 -v "${PWD}\local_uploads:/app/uploads" dumbwareio/dumbdr ### Environment Variables -| Variable | Description | Default | Required | -|------------------|---------------------------------------|---------|----------| -| PORT | Server port | 3000 | No | -| BASE_URL | Base URL for the application | http://localhost:PORT | No | -| MAX_FILE_SIZE | Maximum file size in MB | 1024 | No | -| DUMBDROP_PIN | PIN protection (4-10 digits) | None | No | -| DUMBDROP_TITLE | Site title displayed in header | DumbDrop| No | -| APPRISE_URL | Apprise URL for notifications | None | No | -| APPRISE_MESSAGE | Notification message template | New file uploaded {filename} ({size}), Storage used {storage} | No | -| APPRISE_SIZE_UNIT| Size unit for notifications | Auto | No | -| AUTO_UPLOAD | Enable automatic upload on file selection | false | No | -| ALLOWED_EXTENSIONS| Comma-separated list of allowed file extensions | None | No | -| ALLOWED_IFRAME_ORIGINS | Comma-separated list of origins allowed to embed the app in an iframe (e.g. https://organizr.example.com,https://myportal.com) | None | No | +| Variable | Description | Default | Required | +|------------------------|------------------------------------------------------------------|-----------------------------------------|----------| +| PORT | Server port | 3000 | No | +| BASE_URL | Base URL for the application | http://localhost:PORT | No | +| MAX_FILE_SIZE | Maximum file size in MB | 1024 | No | +| DUMBDROP_PIN | PIN protection (4-10 digits) | None | No | +| DUMBDROP_TITLE | Site title displayed in header | DumbDrop | No | +| APPRISE_URL | Apprise URL for notifications | None | No | +| APPRISE_MESSAGE | Notification message template | New file uploaded {filename} ({size}), Storage used {storage} | No | +| APPRISE_SIZE_UNIT | Size unit for notifications (B, KB, MB, GB, TB, or Auto) | Auto | No | +| AUTO_UPLOAD | Enable automatic upload on file selection | false | No | +| ALLOWED_EXTENSIONS | Comma-separated list of allowed file extensions | None | No | +| ALLOWED_IFRAME_ORIGINS | Comma-separated list of origins allowed to embed the app in an iframe | None | No | +| UPLOAD_DIR | Directory for uploads (Docker/production; should be `/app/uploads` in container) | None (see LOCAL_UPLOAD_DIR fallback) | No | +| LOCAL_UPLOAD_DIR | Directory for uploads (local dev, fallback: './local_uploads') | ./local_uploads | No | -### ALLOWED_IFRAME_ORIGINS +- **UPLOAD_DIR** is used in Docker/production. If not set, LOCAL_UPLOAD_DIR is used for local development. If neither is set, the default is `./local_uploads`. +- **Docker Note:** The Dockerfile now only creates the `uploads` directory inside the container. The host's `./local_uploads` is mounted to `/app/uploads` and should be managed on the host system. +- **BASE_URL**: If you are deploying DumbDrop under a subpath (e.g., `https://example.com/watchfolder/`), you **must** set `BASE_URL` to the full path including the trailing slash (e.g., `https://example.com/watchfolder/`). All API and asset requests will be prefixed with this value. If you deploy at the root, use `https://example.com/`. +- **BASE_URL** must end with a trailing slash. The app will fail to start if this is not the case. -To allow this app to be embedded in an iframe on specific origins (such as Organizr), set the `ALLOWED_IFRAME_ORIGINS` environment variable to a comma-separated list of allowed parent origins. Example: +See `.env.example` for a template and more details. + +
+ALLOWED_IFRAME_ORIGINS + +To allow this app to be embedded in an iframe on specific origins (such as Organizr), set the `ALLOWED_IFRAME_ORIGINS` environment variable. For example: ```env ALLOWED_IFRAME_ORIGINS=https://organizr.example.com,https://myportal.com @@ -136,15 +124,20 @@ ALLOWED_IFRAME_ORIGINS=https://organizr.example.com,https://myportal.com - If not set, the app will only allow itself to be embedded in an iframe on the same origin (default security). - If set, the app will allow embedding in iframes on the specified origins and itself. - **Security Note:** Only add trusted origins. Allowing arbitrary origins can expose your app to clickjacking and other attacks. +
+ +
+File Extension Filtering -### File Extension Filtering To restrict which file types can be uploaded, set the `ALLOWED_EXTENSIONS` environment variable. For example: ```env ALLOWED_EXTENSIONS=.jpg,.jpeg,.png,.pdf,.doc,.docx,.txt ``` If not set, all file extensions will be allowed. +
-### Notification Setup +
+Notification Setup #### Message Templates The notification message supports the following placeholders: @@ -168,6 +161,7 @@ Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UN - Support for all Apprise notification services - Customizable notification messages with filename templating - Optional - disabled if no APPRISE_URL is set +
## Security @@ -206,10 +200,7 @@ Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UN 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request -See [Development Guide](dev/README.md) for local setup and guidelines. - - - +See [Local Development (Recommended Quick Start)](LOCAL_DEVELOPMENT.md) for local setup and guidelines. --- Made with â¤ī¸ by [DumbWare.io](https://dumbware.io) diff --git a/dev/.dockerignore b/dev/.dockerignore deleted file mode 100644 index d939583..0000000 --- a/dev/.dockerignore +++ /dev/null @@ -1,50 +0,0 @@ -# Version control -.git -.gitignore - -# Dependencies -node_modules -npm-debug.log -yarn-debug.log -yarn-error.log - -# Environment variables -.env -.env.* -!.env.example - -# Development -.vscode -.idea -*.swp -*.swo - -# Build outputs -dist -build -coverage - -# Local uploads (development only) -local_uploads - -# Logs -logs -*.log - -# System files -.DS_Store -Thumbs.db - -# Docker -.docker -docker-compose*.yml -Dockerfile* - -# Documentation -README.md -CHANGELOG.md -docs - -# Development configurations -.editorconfig -nodemon.json \ No newline at end of file diff --git a/dev/.env.dev.example b/dev/.env.dev.example deleted file mode 100644 index b21f298..0000000 --- a/dev/.env.dev.example +++ /dev/null @@ -1,22 +0,0 @@ -# Development Environment Settings - -# Server Configuration -PORT=3000 # Development server port - -# Upload Settings -MAX_FILE_SIZE=1024 # Maximum file size in MB for development -AUTO_UPLOAD=false # Disable auto-upload by default in development -UPLOAD_DIR=../local_uploads # Local development upload directory - -# Development Specific -DUMBDROP_TITLE=DumbDrop-Dev # Development environment indicator -DUMBDROP_PIN=123456 # Default development PIN (change in production) - -# Optional Development Features -NODE_ENV=development # Ensures development mode -DEBUG=dumbdrop:* # Enable debug logging (if implemented) - -# Development Notifications (Optional) -APPRISE_URL= # Test notification endpoint -APPRISE_MESSAGE=[DEV] New file uploaded - {filename} ({size}), Storage used {storage} -APPRISE_SIZE_UNIT=auto \ No newline at end of file diff --git a/dev/Dockerfile.dev b/dev/Dockerfile.dev deleted file mode 100644 index a5e9261..0000000 --- a/dev/Dockerfile.dev +++ /dev/null @@ -1,46 +0,0 @@ -# Base stage for shared configurations -FROM node:20-alpine as base - -# Install python and create virtual environment with minimal dependencies -RUN apk add --no-cache python3 py3-pip && \ - python3 -m venv /opt/venv && \ - rm -rf /var/cache/apk/* - -# Activate virtual environment and install apprise -RUN . /opt/venv/bin/activate && \ - pip install --no-cache-dir apprise && \ - find /opt/venv -type d -name "__pycache__" -exec rm -r {} + - -# Add virtual environment to PATH -ENV PATH="/opt/venv/bin:$PATH" - -WORKDIR /usr/src/app - -# Dependencies stage -FROM base as deps - -COPY package*.json ./ -RUN npm ci --only=production && \ - npm cache clean --force - -# Development stage -FROM deps as development -ENV NODE_ENV=development - -# Install dev dependencies -RUN npm install && \ - npm cache clean --force - -# Create upload directories -RUN mkdir -p uploads local_uploads - -# Copy source with specific paths to avoid unnecessary files -COPY src/ ./src/ -COPY public/ ./public/ -COPY dev/ ./dev/ -COPY .eslintrc.json .eslintignore ./ - -# Expose port -EXPOSE 3000 - -CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/dev/README.md b/dev/README.md deleted file mode 100644 index 6f717da..0000000 --- a/dev/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# DumbDrop Development Guide - -## Quick Start - -1. Clone the repository: - ```bash - git clone https://github.com/yourusername/DumbDrop.git - cd DumbDrop - ``` - -2. Set up development environment: - ```bash - cd dev - cp .env.dev.example .env.dev - ``` - -3. Start development server: - ```bash - docker-compose -f docker-compose.dev.yml up - ``` - -The application will be available at http://localhost:3000 with hot-reloading enabled. - -## Development Environment Features - -- Hot-reloading with nodemon -- Development-specific environment variables -- Local file storage in `../local_uploads` -- Debug logging enabled -- Development-specific notifications - -## Project Structure - -``` -DumbDrop/ -├── dev/ # Development configurations -│ ├── docker-compose.dev.yml -│ ├── .env.dev.example -│ └── README.md -├── src/ # Application source code -├── public/ # Static assets -├── local_uploads/ # Development file storage -└── [Production files in root] -``` - -## Development Workflow - -1. Create feature branches from `main`: - ```bash - git checkout -b feature/your-feature-name - ``` - -2. Make changes and test locally -3. Commit using conventional commits: - ```bash - feat: add new feature - fix: resolve bug - docs: update documentation - ``` - -4. Push and create pull request - -## Debugging - -- Use `DEBUG=dumbdrop:*` for detailed logs -- Container shell access: `docker-compose -f docker-compose.dev.yml exec app sh` -- Logs: `docker-compose -f docker-compose.dev.yml logs -f app` - -## Common Issues - -1. Port conflicts: Change port in `.env.dev` -2. File permissions: Ensure proper ownership of `local_uploads` -3. Node modules: Remove and rebuild with `docker-compose -f docker-compose.dev.yml build --no-cache` diff --git a/dev/dev.sh b/dev/dev.sh deleted file mode 100755 index 17496fa..0000000 --- a/dev/dev.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# Set script to exit on error -set -e - -# Enable Docker BuildKit -export DOCKER_BUILDKIT=1 - -# Colors for pretty output -GREEN='\033[0;32m' -BLUE='\033[0;34m' -RED='\033[0;31m' -NC='\033[0m' # No Color - -# Helper function for pretty printing -print_message() { - echo -e "${BLUE}🔧 ${1}${NC}" -} - -# Ensure we're in the right directory -cd "$(dirname "$0")" - -case "$1" in - "up") - print_message "Starting DumbDrop in development mode..." - if [ ! -f .env.dev ]; then - print_message "No .env.dev found. Creating from example..." - cp .env.dev.example .env.dev - fi - docker compose -f docker-compose.dev.yml up -d --build - print_message "Container logs:" - docker compose -f docker-compose.dev.yml logs - ;; - "down") - print_message "Stopping DumbDrop development environment..." - docker compose -f docker-compose.dev.yml down - ;; - "logs") - print_message "Showing DumbDrop logs..." - docker compose -f docker-compose.dev.yml logs -f - ;; - "rebuild") - print_message "Rebuilding DumbDrop..." - docker compose -f docker-compose.dev.yml build --no-cache - docker compose -f docker-compose.dev.yml up - ;; - "clean") - print_message "Cleaning up development environment..." - docker compose -f docker-compose.dev.yml down -v --remove-orphans - rm -f .env.dev - print_message "Cleaned up containers, volumes, and env file" - ;; - "shell") - print_message "Opening shell in container..." - docker compose -f docker-compose.dev.yml exec app sh - ;; - "lint") - print_message "Running linter..." - docker compose -f docker-compose.dev.yml exec app npm run lint - ;; - *) - echo -e "${GREEN}DumbDrop Development Helper${NC}" - echo "Usage: ./dev.sh [command]" - echo "" - echo "Commands:" - echo " up - Start development environment (creates .env.dev if missing)" - echo " down - Stop development environment" - echo " logs - Show container logs" - echo " rebuild - Rebuild container without cache and start" - echo " clean - Clean up everything (containers, volumes, env)" - echo " shell - Open shell in container" - echo " lint - Run linter" - ;; -esac \ No newline at end of file diff --git a/dev/docker-compose.dev.yml b/dev/docker-compose.dev.yml deleted file mode 100644 index 1b67621..0000000 --- a/dev/docker-compose.dev.yml +++ /dev/null @@ -1,33 +0,0 @@ -services: - app: - build: - context: .. - dockerfile: dev/Dockerfile.dev - target: development - args: - DOCKER_BUILDKIT: 1 - x-bake: - options: - dockerignore: dev/.dockerignore - volumes: - - ..:/usr/src/app - - /usr/src/app/node_modules - ports: - - "3000:3000" - environment: - - NODE_ENV=development - - PORT=3000 - - MAX_FILE_SIZE=1024 - - AUTO_UPLOAD=false - - DUMBDROP_TITLE=DumbDrop-Dev - # - APPRISE_URL=ntfy://dumbdrop-test - # - APPRISE_MESSAGE=[DEV] New file uploaded - {filename} ({size}), Storage used {storage} - # - APPRISE_SIZE_UNIT=auto - command: npm run dev - restart: unless-stopped - # Enable container debugging if needed - # stdin_open: true - # tty: true - # Add development labels - labels: - - "dev.dumbware.environment=development" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 7bc5336..0364faf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,8 @@ services: # Replace "./local_uploads" ( before the colon ) with the path where the files land - ./local_uploads:/app/uploads environment: # Environment variables for the DumbDrop service + # Explicitly set upload directory inside the container + UPLOAD_DIR: /app/uploads DUMBDROP_TITLE: DumbDrop # The title shown in the web interface MAX_FILE_SIZE: 1024 # Maximum file size in MB DUMBDROP_PIN: 123456 # Optional PIN protection (4-10 digits, leave empty to disable) diff --git a/package-lock.json b/package-lock.json index 4406201..cd4d0fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,9 +29,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -81,31 +81,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/@eslint/js": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", @@ -132,31 +107,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -238,9 +188,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", "bin": { @@ -390,6 +340,21 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -441,9 +406,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -454,13 +419,13 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -496,29 +461,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -544,6 +486,19 @@ "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -608,9 +563,9 @@ } }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -629,15 +584,6 @@ "node": ">= 0.8.0" } }, - "node_modules/cookie-parser/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -679,12 +625,21 @@ } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/deep-is": { @@ -727,9 +682,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -935,16 +890,6 @@ "eslint": ">=5.16.0" } }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -1001,44 +946,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -1173,6 +1080,30 @@ "express": "^4.11 || 5 || ^5.0.0-beta.1" } }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1195,9 +1126,9 @@ "license": "MIT" }, "node_modules/fastq": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -1248,6 +1179,21 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1281,9 +1227,9 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, @@ -1337,17 +1283,17 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -1396,16 +1342,16 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/globals": { @@ -1444,13 +1390,13 @@ "license": "MIT" }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-symbols": { @@ -1846,15 +1792,15 @@ } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", @@ -1886,9 +1832,9 @@ } }, "node_modules/nodemon": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", - "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", "dev": true, "license": "MIT", "dependencies": { @@ -1914,31 +1860,42 @@ "url": "https://opencollective.com/nodemon" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=4" } }, - "node_modules/nodemon/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1959,9 +1916,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -2130,9 +2087,9 @@ } }, "node_modules/prettier": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz", - "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -2320,9 +2277,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -2398,16 +2355,13 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/send": { @@ -2434,6 +2388,21 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -2443,12 +2412,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", @@ -2578,6 +2541,19 @@ "node": ">=10" } }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2637,16 +2613,16 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { diff --git a/package.json b/package.json index eca5709..f3717f5 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ "main": "src/server.js", "scripts": { "start": "node src/server.js", - "dev": "nodemon --legacy-watch src/server.js", + "dev": "nodemon src/server.js", "lint": "eslint .", "lint:fix": "eslint . --fix", - "format": "prettier --write ." + "format": "prettier --write .", + "predev": "node -e \"const v=process.versions.node.split('.');if(v[0]<20) {console.error('Node.js >=20.0.0 required');process.exit(1)}\"" }, "keywords": [], "author": "", diff --git a/public/index.html b/public/index.html index 119e774..09de367 100644 --- a/public/index.html +++ b/public/index.html @@ -4,11 +4,12 @@ {{SITE_TITLE}} - Simple File Upload - + - - + + +
@@ -116,7 +117,9 @@ headers['X-Batch-ID'] = this.batchId; } - const response = await fetch('/api/upload/init', { + // Remove leading slash from API path before concatenating + const apiUrl = '/api/upload/init'.startsWith('/') ? '/api/upload/init'.substring(1) : '/api/upload/init'; + const response = await fetch(window.BASE_URL + apiUrl, { method: 'POST', headers, body: JSON.stringify({ @@ -152,7 +155,10 @@ } async uploadChunk(chunk) { - const response = await fetch(`/api/upload/chunk/${this.uploadId}`, { + // Remove leading slash from API path before concatenating + const chunkApiUrlPath = `/api/upload/chunk/${this.uploadId}`; + const chunkApiUrl = chunkApiUrlPath.startsWith('/') ? chunkApiUrlPath.substring(1) : chunkApiUrlPath; + const response = await fetch(window.BASE_URL + chunkApiUrl, { method: 'POST', headers: { 'Content-Type': 'application/octet-stream', @@ -824,6 +830,17 @@ const savedTheme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); setTheme(savedTheme); + + document.addEventListener('DOMContentLoaded', function() { + // Rewrite asset URLs to use BASE_URL as prefix if not absolute + const baseUrl = window.BASE_URL; + document.querySelectorAll('link[rel="stylesheet"], link[rel="manifest"], link[rel="icon"]').forEach(link => { + const href = link.getAttribute('href'); + if (href && !href.startsWith('http') && !href.startsWith('data:') && !href.startsWith(baseUrl)) { + link.setAttribute('href', baseUrl + href.replace(/^\//, '')); + } + }); + }); diff --git a/public/login.html b/public/login.html index cf45426..a87faa6 100644 --- a/public/login.html +++ b/public/login.html @@ -4,8 +4,8 @@ {{SITE_TITLE}} - Login - - + + +