mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-07-27 07:35:22 +00:00
Merge remote-tracking branch 'origin/V2' into react-overhaul-tauri-integration
This commit is contained in:
commit
70350743b4
221
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
221
.github/workflows/PR-Auto-Deploy-V2.yml
vendored
@ -2,7 +2,7 @@ name: Auto PR V2 Deployment
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened, closed]
|
||||||
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@ -12,6 +12,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-pr:
|
check-pr:
|
||||||
|
if: github.event.action != 'closed'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
should_deploy: ${{ steps.check-conditions.outputs.should_deploy }}
|
should_deploy: ${{ steps.check-conditions.outputs.should_deploy }}
|
||||||
@ -46,6 +47,7 @@ jobs:
|
|||||||
"reecebrowne"
|
"reecebrowne"
|
||||||
"DarioGii"
|
"DarioGii"
|
||||||
"ConnorYoh"
|
"ConnorYoh"
|
||||||
|
"EthanHealy01"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if author is in the authorized list
|
# Check if author is in the authorized list
|
||||||
@ -57,10 +59,10 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# If PR is targeting feature/react-overhaul and user is authorized, deploy unconditionally
|
# If PR is targeting V2 and user is authorized, deploy unconditionally
|
||||||
PR_BASE_BRANCH="${{ github.event.pull_request.base.ref }}"
|
PR_BASE_BRANCH="${{ github.event.pull_request.base.ref }}"
|
||||||
if [[ "$PR_BASE_BRANCH" == "feature/react-overhaul" && "$is_authorized" == "true" ]]; then
|
if [[ "$PR_BASE_BRANCH" == "V2" && "$is_authorized" == "true" ]]; then
|
||||||
echo "✅ Deployment forced: PR targets feature/react-overhaul and author is authorized."
|
echo "✅ Deployment forced: PR targets V2 and author is authorized."
|
||||||
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@ -183,19 +185,8 @@ jobs:
|
|||||||
repository: ${{ needs.check-pr.outputs.pr_repository }}
|
repository: ${{ needs.check-pr.outputs.pr_repository }}
|
||||||
ref: ${{ needs.check-pr.outputs.pr_ref }}
|
ref: ${{ needs.check-pr.outputs.pr_ref }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
fetch-depth: 0 # Fetch full history for commit hash detection
|
||||||
|
|
||||||
- name: Set up JDK
|
|
||||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with:
|
|
||||||
java-version: "17"
|
|
||||||
distribution: "temurin"
|
|
||||||
|
|
||||||
- name: Build backend
|
|
||||||
run: |
|
|
||||||
export DISABLE_ADDITIONAL_FEATURES=true
|
|
||||||
./gradlew clean build
|
|
||||||
env:
|
|
||||||
STIRLING_PDF_DESKTOP_UI: false
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
@ -212,13 +203,81 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_API }}
|
password: ${{ secrets.DOCKER_HUB_API }}
|
||||||
|
|
||||||
- name: Build and push V2 monolith image
|
- name: Get commit hashes for frontend and backend
|
||||||
|
id: commit-hashes
|
||||||
|
run: |
|
||||||
|
# Get last commit that touched the frontend folder, docker/frontend, or docker/compose
|
||||||
|
FRONTEND_HASH=$(git log -1 --format="%H" -- frontend/ docker/frontend/ docker/compose/ 2>/dev/null || echo "")
|
||||||
|
if [ -z "$FRONTEND_HASH" ]; then
|
||||||
|
FRONTEND_HASH="no-frontend-changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get last commit that touched backend code, docker/backend, or docker/compose
|
||||||
|
BACKEND_HASH=$(git log -1 --format="%H" -- app/ docker/backend/ docker/compose/ 2>/dev/null || echo "")
|
||||||
|
if [ -z "$BACKEND_HASH" ]; then
|
||||||
|
BACKEND_HASH="no-backend-changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Frontend hash: $FRONTEND_HASH"
|
||||||
|
echo "Backend hash: $BACKEND_HASH"
|
||||||
|
|
||||||
|
echo "frontend_hash=$FRONTEND_HASH" >> $GITHUB_OUTPUT
|
||||||
|
echo "backend_hash=$BACKEND_HASH" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Short hashes for tags
|
||||||
|
if [ "$FRONTEND_HASH" = "no-frontend-changes" ]; then
|
||||||
|
echo "frontend_short=no-frontend" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "frontend_short=${FRONTEND_HASH:0:8}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$BACKEND_HASH" = "no-backend-changes" ]; then
|
||||||
|
echo "backend_short=no-backend" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "backend_short=${BACKEND_HASH:0:8}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check if frontend image exists
|
||||||
|
id: check-frontend
|
||||||
|
run: |
|
||||||
|
if docker manifest inspect ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }} >/dev/null 2>&1; then
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Frontend image already exists, skipping build"
|
||||||
|
else
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "Frontend image needs to be built"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check if backend image exists
|
||||||
|
id: check-backend
|
||||||
|
run: |
|
||||||
|
if docker manifest inspect ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }} >/dev/null 2>&1; then
|
||||||
|
echo "exists=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "Backend image already exists, skipping build"
|
||||||
|
else
|
||||||
|
echo "exists=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "Backend image needs to be built"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build and push V2 frontend image
|
||||||
|
if: steps.check-frontend.outputs.exists == 'false'
|
||||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/monolith/Dockerfile
|
file: ./docker/frontend/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }}
|
||||||
|
build-args: VERSION_TAG=v2-alpha
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Build and push V2 backend image
|
||||||
|
if: steps.check-backend.outputs.exists == 'false'
|
||||||
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/backend/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }}
|
||||||
build-args: VERSION_TAG=v2-alpha
|
build-args: VERSION_TAG=v2-alpha
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
@ -233,16 +292,17 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Use same port strategy as regular PRs - just the PR number
|
# Use same port strategy as regular PRs - just the PR number
|
||||||
V2_PORT=${{ needs.check-pr.outputs.pr_number }}
|
V2_PORT=${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
BACKEND_PORT=$((V2_PORT + 10000)) # Backend on higher port to avoid conflicts
|
||||||
|
|
||||||
# Create docker-compose for V2 monolith
|
# Create docker-compose for V2 with separate frontend and backend
|
||||||
cat > docker-compose.yml << EOF
|
cat > docker-compose.yml << EOF
|
||||||
version: '3.3'
|
version: '3.3'
|
||||||
services:
|
services:
|
||||||
stirling-pdf-v2:
|
stirling-pdf-v2-backend:
|
||||||
container_name: stirling-pdf-v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
container_name: stirling-pdf-v2-backend-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-pr-${{ needs.check-pr.outputs.pr_number }}
|
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }}
|
||||||
ports:
|
ports:
|
||||||
- "${V2_PORT}:80" # Frontend port (same as regular PRs)
|
- "${BACKEND_PORT}:8080" # Backend API port
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/data:/usr/share/tessdata:rw
|
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/data:/usr/share/tessdata:rw
|
||||||
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/config:/configs:rw
|
- /stirling/V2-PR-${{ needs.check-pr.outputs.pr_number }}/config:/configs:rw
|
||||||
@ -258,6 +318,17 @@ jobs:
|
|||||||
METRICS_ENABLED: "true"
|
METRICS_ENABLED: "true"
|
||||||
SYSTEM_GOOGLEVISIBILITY: "false"
|
SYSTEM_GOOGLEVISIBILITY: "false"
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
|
|
||||||
|
stirling-pdf-v2-frontend:
|
||||||
|
container_name: stirling-pdf-v2-frontend-pr-${{ needs.check-pr.outputs.pr_number }}
|
||||||
|
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }}
|
||||||
|
ports:
|
||||||
|
- "${V2_PORT}:80" # Frontend port (same as regular PRs)
|
||||||
|
environment:
|
||||||
|
VITE_API_BASE_URL: "http://${{ secrets.VPS_HOST }}:${BACKEND_PORT}"
|
||||||
|
depends_on:
|
||||||
|
- stirling-pdf-v2-backend
|
||||||
|
restart: on-failure:5
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Deploy to VPS
|
# Deploy to VPS
|
||||||
@ -280,6 +351,9 @@ jobs:
|
|||||||
|
|
||||||
# Clean up unused Docker resources to save space
|
# Clean up unused Docker resources to save space
|
||||||
docker system prune -af --volumes
|
docker system prune -af --volumes
|
||||||
|
|
||||||
|
# Clean up old backend/frontend images (older than 2 weeks)
|
||||||
|
docker image prune -af --filter "until=336h" --filter "label!=keep=true"
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
# Set port for output
|
# Set port for output
|
||||||
@ -325,3 +399,102 @@ jobs:
|
|||||||
body: commentBody
|
body: commentBody
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cleanup-v2-deployment:
|
||||||
|
if: github.event.action == 'closed'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Setup GitHub App Bot
|
||||||
|
if: github.actor != 'dependabot[bot]'
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Clean up V2 deployment comments
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = ${{ github.event.pull_request.number }};
|
||||||
|
|
||||||
|
// Find and delete V2 deployment comments
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
const v2Comments = comments.filter(c =>
|
||||||
|
c.body?.includes("## 🚀 V2 Auto-Deployment Complete!") &&
|
||||||
|
c.user?.type === "Bot"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const comment of v2Comments) {
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
comment_id: comment.id
|
||||||
|
});
|
||||||
|
console.log(`Deleted V2 deployment comment (ID: ${comment.id})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Set up SSH
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh/
|
||||||
|
echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key
|
||||||
|
sudo chmod 600 ../private.key
|
||||||
|
|
||||||
|
- name: Cleanup V2 deployment
|
||||||
|
run: |
|
||||||
|
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'ENDSSH'
|
||||||
|
if [ -d "/stirling/V2-PR-${{ github.event.pull_request.number }}" ]; then
|
||||||
|
echo "Found V2 PR directory, proceeding with cleanup..."
|
||||||
|
|
||||||
|
# Stop and remove V2 containers
|
||||||
|
cd /stirling/V2-PR-${{ github.event.pull_request.number }}
|
||||||
|
docker-compose down || true
|
||||||
|
|
||||||
|
# Go back to root before removal
|
||||||
|
cd /
|
||||||
|
|
||||||
|
# Remove V2 PR-specific directories
|
||||||
|
rm -rf /stirling/V2-PR-${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
# Clean up V2 containers by name (in case compose cleanup missed them)
|
||||||
|
docker rm -f stirling-pdf-v2-frontend-pr-${{ github.event.pull_request.number }} || true
|
||||||
|
docker rm -f stirling-pdf-v2-backend-pr-${{ github.event.pull_request.number }} || true
|
||||||
|
|
||||||
|
echo "V2 cleanup completed"
|
||||||
|
else
|
||||||
|
echo "V2 PR directory not found, nothing to clean up"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up old unused images (older than 2 weeks) but keep recent ones for reuse
|
||||||
|
docker image prune -af --filter "until=336h" --filter "label!=keep=true"
|
||||||
|
|
||||||
|
# Note: We don't remove the commit-based images since they can be reused across PRs
|
||||||
|
# Only remove PR-specific containers and directories
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
|
- name: Cleanup temporary files
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
rm -f ../private.key
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
@ -2,9 +2,9 @@ name: Build repo
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ["main"]
|
branches: ["main", "V2", "V2-gha"]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: ["main"]
|
branches: ["main", "V2", "V2-gha"]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@ -114,6 +114,46 @@ jobs:
|
|||||||
name: openapi-docs
|
name: openapi-docs
|
||||||
path: ./SwaggerDoc.json
|
path: ./SwaggerDoc.json
|
||||||
|
|
||||||
|
frontend-validation:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: frontend/package-lock.json
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: |
|
||||||
|
cd frontend
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
- name: Build frontend
|
||||||
|
run: |
|
||||||
|
cd frontend
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
- name: Run frontend tests (if available)
|
||||||
|
run: |
|
||||||
|
cd frontend
|
||||||
|
npm test --passWithNoTests --watchAll=false || true
|
||||||
|
|
||||||
|
- name: Upload frontend build artifacts
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
|
with:
|
||||||
|
name: frontend-build
|
||||||
|
path: frontend/dist/
|
||||||
|
retention-days: 3
|
||||||
|
|
||||||
check-licence:
|
check-licence:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
217
.github/workflows/frontend-licenses-update.yml
vendored
Normal file
217
.github/workflows/frontend-licenses-update.yml
vendored
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
name: Frontend License Report Workflow
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- V2
|
||||||
|
paths:
|
||||||
|
- "frontend/package.json"
|
||||||
|
- "frontend/package-lock.json"
|
||||||
|
- "frontend/scripts/generate-licenses.js"
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- V2
|
||||||
|
paths:
|
||||||
|
- "frontend/package.json"
|
||||||
|
- "frontend/package-lock.json"
|
||||||
|
- "frontend/scripts/generate-licenses.js"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate-frontend-license-report:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
repository-projects: write # Required for enabling automerge
|
||||||
|
steps:
|
||||||
|
- name: Harden Runner
|
||||||
|
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
||||||
|
with:
|
||||||
|
egress-policy: audit
|
||||||
|
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup GitHub App Bot
|
||||||
|
id: setup-bot
|
||||||
|
uses: ./.github/actions/setup-bot
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: frontend/package-lock.json
|
||||||
|
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
working-directory: frontend
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Generate frontend license report
|
||||||
|
working-directory: frontend
|
||||||
|
run: npm run generate-licenses
|
||||||
|
|
||||||
|
- name: Check for license warnings
|
||||||
|
run: |
|
||||||
|
if [ -f "frontend/src/assets/license-warnings.json" ]; then
|
||||||
|
echo "LICENSE_WARNINGS_EXIST=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "LICENSE_WARNINGS_EXIST=false" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PR Event: Check licenses and comment on PR
|
||||||
|
- name: Delete previous license check comments
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = context.issue.number;
|
||||||
|
|
||||||
|
// Get all comments on the PR
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
per_page: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter for license check comments
|
||||||
|
const licenseComments = comments.filter(comment =>
|
||||||
|
comment.body.includes('## ✅ Frontend License Check Passed') ||
|
||||||
|
comment.body.includes('## ❌ Frontend License Check Failed')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete old license check comments
|
||||||
|
for (const comment of licenseComments) {
|
||||||
|
console.log(`Deleting old license check comment: ${comment.id}`);
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
comment_id: comment.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Comment on PR - License Check Results
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const { owner, repo } = context.repo;
|
||||||
|
const prNumber = context.issue.number;
|
||||||
|
const hasWarnings = process.env.LICENSE_WARNINGS_EXIST === 'true';
|
||||||
|
|
||||||
|
let commentBody;
|
||||||
|
|
||||||
|
if (hasWarnings) {
|
||||||
|
// Read warnings file to get specific issues
|
||||||
|
const fs = require('fs');
|
||||||
|
let warningDetails = '';
|
||||||
|
try {
|
||||||
|
const warnings = JSON.parse(fs.readFileSync('frontend/src/assets/license-warnings.json', 'utf8'));
|
||||||
|
warningDetails = warnings.warnings.map(w => `- ${w.message}`).join('\n');
|
||||||
|
} catch (e) {
|
||||||
|
warningDetails = 'Unable to read warning details';
|
||||||
|
}
|
||||||
|
|
||||||
|
commentBody = `## ❌ Frontend License Check Failed
|
||||||
|
|
||||||
|
The frontend license check has detected compatibility warnings that require review:
|
||||||
|
|
||||||
|
${warningDetails}
|
||||||
|
|
||||||
|
**Action Required:** Please review these licenses to ensure they are acceptable for your use case before merging.
|
||||||
|
|
||||||
|
_This check will fail the PR until license issues are resolved._`;
|
||||||
|
} else {
|
||||||
|
commentBody = `## ✅ Frontend License Check Passed
|
||||||
|
|
||||||
|
All frontend licenses have been validated and no compatibility warnings were detected.
|
||||||
|
|
||||||
|
The frontend license report has been updated successfully.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: prNumber,
|
||||||
|
body: commentBody
|
||||||
|
});
|
||||||
|
|
||||||
|
- name: Fail workflow if license warnings exist (PR only)
|
||||||
|
if: github.event_name == 'pull_request' && env.LICENSE_WARNINGS_EXIST == 'true'
|
||||||
|
run: |
|
||||||
|
echo "❌ License warnings detected. Failing the workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
# Push Event: Commit license files and create PR
|
||||||
|
- name: Commit changes (Push only)
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
run: |
|
||||||
|
git add frontend/src/assets/3rdPartyLicenses.json
|
||||||
|
# Note: Do NOT commit license-warnings.json - it's only for PR review
|
||||||
|
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Prepare PR body (Push only)
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
run: |
|
||||||
|
PR_BODY="Auto-generated by ${{ steps.setup-bot.outputs.app-slug }}[bot]
|
||||||
|
|
||||||
|
This PR updates the frontend license report based on changes to package.json dependencies."
|
||||||
|
|
||||||
|
if [ "${{ env.LICENSE_WARNINGS_EXIST }}" = "true" ]; then
|
||||||
|
PR_BODY="$PR_BODY
|
||||||
|
|
||||||
|
## ⚠️ License Compatibility Warnings
|
||||||
|
|
||||||
|
The following licenses may require review for corporate compatibility:
|
||||||
|
|
||||||
|
$(cat frontend/src/assets/license-warnings.json | jq -r '.warnings[].message')
|
||||||
|
|
||||||
|
Please review these licenses to ensure they are acceptable for your use case."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "PR_BODY<<EOF" >> $GITHUB_ENV
|
||||||
|
echo "$PR_BODY" >> $GITHUB_ENV
|
||||||
|
echo "EOF" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create Pull Request (Push only)
|
||||||
|
id: cpr
|
||||||
|
if: github.event_name == 'push' && env.CHANGES_DETECTED == 'true'
|
||||||
|
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||||
|
with:
|
||||||
|
token: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
commit-message: "Update Frontend 3rd Party Licenses"
|
||||||
|
committer: ${{ steps.setup-bot.outputs.committer }}
|
||||||
|
author: ${{ steps.setup-bot.outputs.committer }}
|
||||||
|
signoff: true
|
||||||
|
branch: update-frontend-3rd-party-licenses
|
||||||
|
base: V2
|
||||||
|
title: "Update Frontend 3rd Party Licenses"
|
||||||
|
body: ${{ env.PR_BODY }}
|
||||||
|
labels: Licenses,github-actions,frontend
|
||||||
|
draft: false
|
||||||
|
delete-branch: true
|
||||||
|
sign-commits: true
|
||||||
|
|
||||||
|
- name: Enable Pull Request Automerge (Push only)
|
||||||
|
if: github.event_name == 'push' && steps.cpr.outputs.pull-request-operation == 'created' && env.LICENSE_WARNINGS_EXIST == 'false'
|
||||||
|
run: gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.setup-bot.outputs.token }}
|
||||||
|
|
||||||
|
- name: Add review required label (Push only)
|
||||||
|
if: github.event_name == 'push' && steps.cpr.outputs.pull-request-operation == 'created' && env.LICENSE_WARNINGS_EXIST == 'true'
|
||||||
|
run: gh pr edit "${{ steps.cpr.outputs.pull-request-number }}" --add-label "license-review-required"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.setup-bot.outputs.token }}
|
@ -14,15 +14,10 @@ docker/
|
|||||||
│ ├── Dockerfile # React/Vite frontend with nginx
|
│ ├── Dockerfile # React/Vite frontend with nginx
|
||||||
│ ├── nginx.conf # Nginx configuration
|
│ ├── nginx.conf # Nginx configuration
|
||||||
│ └── entrypoint.sh # Dynamic backend URL setup
|
│ └── entrypoint.sh # Dynamic backend URL setup
|
||||||
├── monolith/ # Single container setup
|
|
||||||
│ ├── Dockerfile # Combined frontend + backend
|
|
||||||
│ ├── nginx-monolith.conf # Nginx config for monolith
|
|
||||||
│ └── start-monolith.sh # Startup script
|
|
||||||
└── compose/ # Docker Compose files
|
└── compose/ # Docker Compose files
|
||||||
├── docker-compose.yml # Standard setup
|
├── docker-compose.yml # Standard setup
|
||||||
├── docker-compose.ultra-lite.yml # Ultra-lite setup
|
├── docker-compose.ultra-lite.yml # Ultra-lite setup
|
||||||
├── docker-compose.fat.yml # Full-featured setup
|
└── docker-compose.fat.yml # Full-featured setup
|
||||||
└── docker-compose.monolith.yml # Single container setup
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -42,12 +37,6 @@ docker-compose -f docker/compose/docker-compose.ultra-lite.yml up --build
|
|||||||
docker-compose -f docker/compose/docker-compose.fat.yml up --build
|
docker-compose -f docker/compose/docker-compose.fat.yml up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Single Container (Monolith)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Single container with both frontend and backend
|
|
||||||
docker-compose -f docker/compose/docker-compose.monolith.yml up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Access Points
|
## Access Points
|
||||||
|
|
||||||
@ -57,7 +46,7 @@ docker-compose -f docker/compose/docker-compose.monolith.yml up --build
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
- **Backend URL**: Set `BACKEND_URL` environment variable for custom backend locations
|
- **Backend URL**: Set `VITE_API_BASE_URL` environment variable for custom backend locations
|
||||||
- **Custom Ports**: Modify port mappings in docker-compose files
|
- **Custom Ports**: Modify port mappings in docker-compose files
|
||||||
- **Memory Limits**: Adjust memory limits per variant (2G ultra-lite, 4G standard, 6G fat)
|
- **Memory Limits**: Adjust memory limits per variant (2G ultra-lite, 4G standard, 6G fat)
|
||||||
|
|
||||||
|
@ -1,11 +1,36 @@
|
|||||||
# Backend Dockerfile - Java Spring Boot with all dependencies
|
# Backend Dockerfile - Java Spring Boot with all dependencies and build stage
|
||||||
|
# Build the application
|
||||||
|
FROM gradle:8.14-jdk21 AS build
|
||||||
|
|
||||||
|
COPY build.gradle .
|
||||||
|
COPY settings.gradle .
|
||||||
|
COPY gradlew .
|
||||||
|
COPY gradle gradle/
|
||||||
|
COPY app/core/build.gradle core/.
|
||||||
|
COPY app/common/build.gradle common/.
|
||||||
|
COPY app/proprietary/build.gradle proprietary/.
|
||||||
|
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the entire project to the working directory
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application with DISABLE_ADDITIONAL_FEATURES=false
|
||||||
|
RUN DISABLE_ADDITIONAL_FEATURES=false \
|
||||||
|
STIRLING_PDF_DESKTOP_UI=false \
|
||||||
|
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
|
||||||
|
|
||||||
|
# Main stage
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts /scripts
|
COPY scripts /scripts
|
||||||
COPY pipeline /pipeline
|
COPY pipeline /pipeline
|
||||||
COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
COPY app/core/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||||
COPY app/core/build/libs/*.jar app.jar
|
# first /app directory is for the build stage, second is for the final image
|
||||||
|
COPY --from=build /app/app/core/build/libs/*.jar app.jar
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
|
|
||||||
@ -22,7 +47,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}"
|
|||||||
LABEL org.opencontainers.image.keywords="PDF, manipulation, backend, API, Spring Boot"
|
LABEL org.opencontainers.image.keywords="PDF, manipulation, backend, API, Spring Boot"
|
||||||
|
|
||||||
# Set Environment Variables
|
# Set Environment Variables
|
||||||
ENV DISABLE_ADDITIONAL_FEATURES=true \
|
ENV DISABLE_ADDITIONAL_FEATURES=false \
|
||||||
VERSION_TAG=$VERSION_TAG \
|
VERSION_TAG=$VERSION_TAG \
|
||||||
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
|
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
|
||||||
JAVA_CUSTOM_OPTS="" \
|
JAVA_CUSTOM_OPTS="" \
|
||||||
@ -50,7 +75,6 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
tini \
|
tini \
|
||||||
bash \
|
bash \
|
||||||
curl \
|
curl \
|
||||||
qpdf \
|
|
||||||
shadow \
|
shadow \
|
||||||
su-exec \
|
su-exec \
|
||||||
openssl \
|
openssl \
|
||||||
@ -63,11 +87,13 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
# pdftohtml
|
# pdftohtml
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
# OCR MY PDF (unpaper for descew and other advanced features)
|
# OCR MY PDF (unpaper for descew and other advanced features)
|
||||||
|
unpaper \
|
||||||
tesseract-ocr-data-eng \
|
tesseract-ocr-data-eng \
|
||||||
tesseract-ocr-data-chi_sim \
|
tesseract-ocr-data-chi_sim \
|
||||||
tesseract-ocr-data-deu \
|
tesseract-ocr-data-deu \
|
||||||
tesseract-ocr-data-fra \
|
tesseract-ocr-data-fra \
|
||||||
tesseract-ocr-data-por \
|
tesseract-ocr-data-por \
|
||||||
|
ocrmypdf \
|
||||||
# CV
|
# CV
|
||||||
py3-opencv \
|
py3-opencv \
|
||||||
python3 \
|
python3 \
|
||||||
|
@ -77,12 +77,13 @@ RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/a
|
|||||||
# pdftohtml
|
# pdftohtml
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
# OCR MY PDF (unpaper for descew and other advanced featues)
|
# OCR MY PDF (unpaper for descew and other advanced featues)
|
||||||
qpdf \
|
unpaper \
|
||||||
tesseract-ocr-data-eng \
|
tesseract-ocr-data-eng \
|
||||||
tesseract-ocr-data-chi_sim \
|
tesseract-ocr-data-chi_sim \
|
||||||
tesseract-ocr-data-deu \
|
tesseract-ocr-data-deu \
|
||||||
tesseract-ocr-data-fra \
|
tesseract-ocr-data-fra \
|
||||||
tesseract-ocr-data-por \
|
tesseract-ocr-data-por \
|
||||||
|
ocrmypdf \
|
||||||
font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra font-liberation font-linux-libertine \
|
font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra font-liberation font-linux-libertine \
|
||||||
# CV
|
# CV
|
||||||
py3-opencv \
|
py3-opencv \
|
||||||
|
@ -1,4 +1,28 @@
|
|||||||
# Backend ultra-lite Dockerfile - Java Spring Boot with minimal dependencies
|
# Backend ultra-lite Dockerfile - Java Spring Boot with minimal dependencies and build stage
|
||||||
|
# Build the application
|
||||||
|
FROM gradle:8.14-jdk21 AS build
|
||||||
|
|
||||||
|
COPY build.gradle .
|
||||||
|
COPY settings.gradle .
|
||||||
|
COPY gradlew .
|
||||||
|
COPY gradle gradle/
|
||||||
|
COPY app/core/build.gradle core/.
|
||||||
|
COPY app/common/build.gradle common/.
|
||||||
|
COPY app/proprietary/build.gradle proprietary/.
|
||||||
|
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the entire project to the working directory
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application with DISABLE_ADDITIONAL_FEATURES=true
|
||||||
|
RUN DISABLE_ADDITIONAL_FEATURES=true \
|
||||||
|
STIRLING_PDF_DESKTOP_UI=false \
|
||||||
|
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
|
||||||
|
|
||||||
|
# Main stage
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
||||||
|
|
||||||
ARG VERSION_TAG
|
ARG VERSION_TAG
|
||||||
@ -18,11 +42,10 @@ ENV DISABLE_ADDITIONAL_FEATURES=true \
|
|||||||
TMP=/tmp/stirling-pdf
|
TMP=/tmp/stirling-pdf
|
||||||
|
|
||||||
# Copy necessary files
|
# Copy necessary files
|
||||||
COPY scripts/download-security-jar.sh /scripts/download-security-jar.sh
|
|
||||||
COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
|
COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
|
||||||
COPY scripts/installFonts.sh /scripts/installFonts.sh
|
COPY scripts/installFonts.sh /scripts/installFonts.sh
|
||||||
COPY pipeline /pipeline
|
COPY pipeline /pipeline
|
||||||
COPY app/core/build/libs/*.jar app.jar
|
COPY --from=build /app/app/core/build/libs/*.jar app.jar
|
||||||
|
|
||||||
# Set up necessary directories and permissions
|
# Set up necessary directories and permissions
|
||||||
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
@ -43,8 +41,8 @@ services:
|
|||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ../../frontend
|
context: ../..
|
||||||
dockerfile: ../docker/frontend/Dockerfile
|
dockerfile: docker/frontend/Dockerfile
|
||||||
container_name: stirling-pdf-frontend-fat
|
container_name: stirling-pdf-frontend-fat
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
ports:
|
ports:
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
stirling-pdf-monolith:
|
|
||||||
build:
|
|
||||||
context: ../..
|
|
||||||
dockerfile: docker/monolith/Dockerfile
|
|
||||||
container_name: stirling-pdf-monolith
|
|
||||||
restart: on-failure:5
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:80/ && curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 15s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "3000:80" # Frontend access
|
|
||||||
- "8080:8080" # Direct backend access (for debugging)
|
|
||||||
volumes:
|
|
||||||
- ../../stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ../../stirling/latest/config:/configs:rw
|
|
||||||
- ../../stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "true"
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Single container Stirling-PDF
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Monolith
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
stirling-data:
|
|
||||||
stirling-config:
|
|
||||||
stirling-logs:
|
|
@ -1,5 +1,3 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
@ -38,8 +36,8 @@ services:
|
|||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ../../frontend
|
context: ../..
|
||||||
dockerfile: ../docker/frontend/Dockerfile
|
dockerfile: docker/frontend/Dockerfile
|
||||||
container_name: stirling-pdf-frontend-ultra-lite
|
container_name: stirling-pdf-frontend-ultra-lite
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
ports:
|
ports:
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
@ -41,8 +39,8 @@ services:
|
|||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ../../frontend
|
context: ../..
|
||||||
dockerfile: ../docker/frontend/Dockerfile
|
dockerfile: docker/frontend/Dockerfile
|
||||||
container_name: stirling-pdf-frontend
|
container_name: stirling-pdf-frontend
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
ports:
|
ports:
|
||||||
|
@ -4,13 +4,13 @@ FROM node:20-alpine AS build
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files
|
# Copy package files
|
||||||
COPY package*.json ./
|
COPY frontend/package*.json ./
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
# Copy source code
|
# Copy source code
|
||||||
COPY . .
|
COPY frontend .
|
||||||
|
|
||||||
# Build the application
|
# Build the application
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@ -22,8 +22,8 @@ FROM nginx:alpine
|
|||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
# Copy nginx configuration and entrypoint
|
# Copy nginx configuration and entrypoint
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY docker/frontend/nginx.conf /etc/nginx/nginx.conf
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY docker/frontend/entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
# Make entrypoint executable
|
# Make entrypoint executable
|
||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
@ -32,7 +32,7 @@ RUN chmod +x /entrypoint.sh
|
|||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
# Environment variables for flexibility
|
# Environment variables for flexibility
|
||||||
ENV BACKEND_URL=http://backend:8080
|
ENV VITE_API_BASE_URL=http://backend:8080
|
||||||
|
|
||||||
# Use custom entrypoint
|
# Use custom entrypoint
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
@ -1,10 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Set default backend URL if not provided
|
# Set default backend URL if not provided
|
||||||
BACKEND_URL=${BACKEND_URL:-"http://backend:8080"}
|
VITE_API_BASE_URL=${VITE_API_BASE_URL:-"http://backend:8080"}
|
||||||
|
|
||||||
# Replace the placeholder in nginx.conf with the actual backend URL
|
# Replace the placeholder in nginx.conf with the actual backend URL
|
||||||
sed -i "s|\${BACKEND_URL}|${BACKEND_URL}|g" /etc/nginx/nginx.conf
|
sed -i "s|\${VITE_API_BASE_URL}|${VITE_API_BASE_URL}|g" /etc/nginx/nginx.conf
|
||||||
|
|
||||||
# Start nginx
|
# Start nginx
|
||||||
exec nginx -g "daemon off;"
|
exec nginx -g "daemon off;"
|
@ -17,6 +17,9 @@ http {
|
|||||||
server_name _;
|
server_name _;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html index.htm;
|
index index.html index.htm;
|
||||||
|
|
||||||
|
# Global settings for file uploads
|
||||||
|
client_max_body_size 100m;
|
||||||
|
|
||||||
# Handle client-side routing - support subpaths
|
# Handle client-side routing - support subpaths
|
||||||
location / {
|
location / {
|
||||||
@ -25,13 +28,28 @@ http {
|
|||||||
|
|
||||||
# Proxy API calls to backend
|
# Proxy API calls to backend
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_pass ${BACKEND_URL}/api/;
|
proxy_pass ${VITE_API_BASE_URL}/api/;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
proxy_set_header X-Forwarded-Port $server_port;
|
proxy_set_header X-Forwarded-Port $server_port;
|
||||||
|
|
||||||
|
# Additional headers for proper API proxying
|
||||||
|
proxy_set_header Connection '';
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_cache off;
|
||||||
|
|
||||||
|
# Timeout settings for large file uploads
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
|
||||||
|
# Request size limits for file uploads
|
||||||
|
client_max_body_size 100m;
|
||||||
|
proxy_request_buffering off;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cache static assets
|
# Cache static assets
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
# Monolith Dockerfile - Frontend + Backend in same container
|
|
||||||
# Build frontend
|
|
||||||
FROM node:20-alpine AS frontend-build
|
|
||||||
|
|
||||||
WORKDIR /app/frontend
|
|
||||||
|
|
||||||
# Copy frontend package files
|
|
||||||
COPY frontend/package*.json ./
|
|
||||||
|
|
||||||
# Install frontend dependencies
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copy frontend source
|
|
||||||
COPY frontend/ ./
|
|
||||||
|
|
||||||
# Build frontend
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Main stage - Backend with frontend files
|
|
||||||
FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be023728e11715
|
|
||||||
|
|
||||||
# Copy necessary files
|
|
||||||
COPY scripts /scripts
|
|
||||||
COPY pipeline /pipeline
|
|
||||||
COPY stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
|
||||||
COPY stirling-pdf/build/libs/*.jar app.jar
|
|
||||||
|
|
||||||
# Copy built frontend files
|
|
||||||
COPY --from=frontend-build /app/frontend/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
ARG VERSION_TAG
|
|
||||||
|
|
||||||
LABEL org.opencontainers.image.title="Stirling-PDF Monolith"
|
|
||||||
LABEL org.opencontainers.image.description="Single container with both frontend and backend for Stirling-PDF"
|
|
||||||
LABEL org.opencontainers.image.source="https://github.com/Stirling-Tools/Stirling-PDF"
|
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
|
||||||
LABEL org.opencontainers.image.vendor="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.url="https://www.stirlingpdf.com"
|
|
||||||
LABEL org.opencontainers.image.documentation="https://docs.stirlingpdf.com"
|
|
||||||
LABEL maintainer="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.authors="Stirling-Tools"
|
|
||||||
LABEL org.opencontainers.image.version="${VERSION_TAG}"
|
|
||||||
LABEL org.opencontainers.image.keywords="PDF, manipulation, monolith, single-container"
|
|
||||||
|
|
||||||
# Set Environment Variables
|
|
||||||
ENV DISABLE_ADDITIONAL_FEATURES=true \
|
|
||||||
VERSION_TAG=$VERSION_TAG \
|
|
||||||
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
|
|
||||||
JAVA_CUSTOM_OPTS="" \
|
|
||||||
HOME=/home/stirlingpdfuser \
|
|
||||||
PUID=1000 \
|
|
||||||
PGID=1000 \
|
|
||||||
UMASK=022 \
|
|
||||||
PYTHONPATH=/usr/lib/libreoffice/program:/opt/venv/lib/python3.12/site-packages \
|
|
||||||
UNO_PATH=/usr/lib/libreoffice/program \
|
|
||||||
URE_BOOTSTRAP=file:///usr/lib/libreoffice/program/fundamentalrc \
|
|
||||||
PATH=$PATH:/opt/venv/bin \
|
|
||||||
STIRLING_TEMPFILES_DIRECTORY=/tmp/stirling-pdf \
|
|
||||||
TMPDIR=/tmp/stirling-pdf \
|
|
||||||
TEMP=/tmp/stirling-pdf \
|
|
||||||
TMP=/tmp/stirling-pdf
|
|
||||||
|
|
||||||
# Install nginx and all dependencies
|
|
||||||
RUN echo "@main https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
|
||||||
echo "@community https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
|
||||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
|
|
||||||
apk upgrade --no-cache -a && \
|
|
||||||
apk add --no-cache \
|
|
||||||
ca-certificates \
|
|
||||||
tzdata \
|
|
||||||
tini \
|
|
||||||
bash \
|
|
||||||
curl \
|
|
||||||
qpdf \
|
|
||||||
shadow \
|
|
||||||
su-exec \
|
|
||||||
openssl \
|
|
||||||
openssl-dev \
|
|
||||||
openjdk21-jre \
|
|
||||||
nginx \
|
|
||||||
# Doc conversion
|
|
||||||
gcompat \
|
|
||||||
libc6-compat \
|
|
||||||
libreoffice \
|
|
||||||
# pdftohtml
|
|
||||||
poppler-utils \
|
|
||||||
# OCR MY PDF (unpaper for descew and other advanced features)
|
|
||||||
tesseract-ocr-data-eng \
|
|
||||||
tesseract-ocr-data-chi_sim \
|
|
||||||
tesseract-ocr-data-deu \
|
|
||||||
tesseract-ocr-data-fra \
|
|
||||||
tesseract-ocr-data-por \
|
|
||||||
# CV
|
|
||||||
py3-opencv \
|
|
||||||
python3 \
|
|
||||||
py3-pip \
|
|
||||||
py3-pillow@testing \
|
|
||||||
py3-pdf2image@testing && \
|
|
||||||
python3 -m venv /opt/venv && \
|
|
||||||
/opt/venv/bin/pip install --upgrade pip setuptools && \
|
|
||||||
/opt/venv/bin/pip install --no-cache-dir --upgrade unoserver weasyprint && \
|
|
||||||
ln -s /usr/lib/libreoffice/program/uno.py /opt/venv/lib/python3.12/site-packages/ && \
|
|
||||||
ln -s /usr/lib/libreoffice/program/unohelper.py /opt/venv/lib/python3.12/site-packages/ && \
|
|
||||||
ln -s /usr/lib/libreoffice/program /opt/venv/lib/python3.12/site-packages/LibreOffice && \
|
|
||||||
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
|
||||||
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders /tmp/stirling-pdf && \
|
|
||||||
fc-cache -f -v && \
|
|
||||||
chmod +x /scripts/* && \
|
|
||||||
chmod +x /scripts/init.sh && \
|
|
||||||
# User permissions
|
|
||||||
addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
|
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline /tmp/stirling-pdf && \
|
|
||||||
chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
|
|
||||||
chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/nginx/html
|
|
||||||
|
|
||||||
# Copy nginx configuration for monolith
|
|
||||||
COPY docker/monolith/nginx-monolith.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
# Copy startup script
|
|
||||||
COPY docker/monolith/start-monolith.sh /start-monolith.sh
|
|
||||||
RUN chmod +x /start-monolith.sh
|
|
||||||
|
|
||||||
# Expose both ports
|
|
||||||
EXPOSE 80 8080
|
|
||||||
|
|
||||||
# Set user and run command
|
|
||||||
ENTRYPOINT ["tini", "--"]
|
|
||||||
CMD ["/start-monolith.sh"]
|
|
@ -1,49 +0,0 @@
|
|||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
# Gzip compression
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name _;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html index.htm;
|
|
||||||
|
|
||||||
# Handle client-side routing - support subpaths
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Proxy API calls to backend running on same container
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:8080/api/;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Port $server_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Cache static assets
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Security headers
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
|
||||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Start the Java backend in the background
|
|
||||||
echo "Starting Java backend..."
|
|
||||||
su-exec stirlingpdfuser:stirlingpdfgroup bash -c "
|
|
||||||
cd /home/stirlingpdfuser && \
|
|
||||||
java -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/tmp/stirling-pdf -jar /app.jar &
|
|
||||||
/opt/venv/bin/unoserver --port 2003 --interface 127.0.0.1 &
|
|
||||||
"
|
|
||||||
|
|
||||||
# Wait for backend to start
|
|
||||||
echo "Waiting for backend to start..."
|
|
||||||
until curl -f http://localhost:8080/api/v1/info/status >/dev/null 2>&1; do
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Backend started, starting nginx..."
|
|
||||||
|
|
||||||
# Start nginx in the foreground
|
|
||||||
nginx -g "daemon off;"
|
|
@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Fat-Disable-Endpoints
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-fat
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
- ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with all Endpoints Disabled
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,64 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security-Fat-Postgres
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-fat-postgres
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
healthcheck:
|
|
||||||
test: [ "CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'" ]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with Security and PostgreSQL
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat-PostgreSQL
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SYSTEM_DATASOURCE_ENABLECUSTOMDATABASE: "true"
|
|
||||||
SYSTEM_DATASOURCE_CUSTOMDATABASEURL: "jdbc:postgresql://db:5432/stirling_pdf"
|
|
||||||
SYSTEM_DATASOURCE_USERNAME: "admin"
|
|
||||||
SYSTEM_DATASOURCE_PASSWORD: "stirling"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: 'postgres:17.2-alpine'
|
|
||||||
restart: on-failure:5
|
|
||||||
container_name: db
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: "stirling_pdf"
|
|
||||||
POSTGRES_USER: "admin"
|
|
||||||
POSTGRES_PASSWORD: "stirling"
|
|
||||||
shm_size: "512mb"
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512m
|
|
||||||
cpus: "0.5"
|
|
||||||
healthcheck:
|
|
||||||
test: [ "CMD-SHELL", "pg_isready -U admin stirling_pdf" ]
|
|
||||||
interval: 1s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/pgdata
|
|
@ -1,34 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security-Fat
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-fat
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,42 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "true"
|
|
||||||
SECURITY_OAUTH2_ENABLED: "true"
|
|
||||||
SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Stirling-PDF
|
|
||||||
SECURITY_OAUTH2_ISSUER: "https://accounts.google.com" # Change with any other provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
|
|
||||||
SECURITY_OAUTH2_CLIENTID: "<YOUR CLIENT ID>.apps.googleusercontent.com" # Client ID from your provider
|
|
||||||
SECURITY_OAUTH2_CLIENTSECRET: "<YOUR CLIENT SECRET>" # Client Secret from your provider
|
|
||||||
SECURITY_OAUTH2_SCOPES: "openid,profile,email" # Expected OAuth2 Scope
|
|
||||||
SECURITY_OAUTH2_USEASUSERNAME: "email" # Default is 'email'; custom fields can be used as the username
|
|
||||||
SECURITY_OAUTH2_PROVIDER: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,34 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "true"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,31 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Ultra-Lite-Security
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-ultra-lite
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 1G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "true"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF-Lite
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Lite Latest with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF-Lite Latest
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,31 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
SECURITY_ENABLELOGIN: "false"
|
|
||||||
LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SHOW_SURVEY: "true"
|
|
||||||
restart: on-failure:5
|
|
@ -1,34 +0,0 @@
|
|||||||
services:
|
|
||||||
stirling-pdf:
|
|
||||||
container_name: Stirling-PDF-Security-Fat-with-login
|
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-fat
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 4G
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -f -H 'X-API-KEY: 123456789' http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 16
|
|
||||||
ports:
|
|
||||||
- 8080:8080
|
|
||||||
volumes:
|
|
||||||
- ./stirling/latest/data:/usr/share/tessdata:rw
|
|
||||||
- ./stirling/latest/config:/configs:rw
|
|
||||||
- ./stirling/latest/logs:/logs:rw
|
|
||||||
environment:
|
|
||||||
DISABLE_ADDITIONAL_FEATURES: "false"
|
|
||||||
SECURITY_ENABLELOGIN: "true"
|
|
||||||
PUID: 1002
|
|
||||||
PGID: 1002
|
|
||||||
UMASK: "022"
|
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
|
||||||
UI_APPNAME: Stirling-PDF
|
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with Security
|
|
||||||
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat
|
|
||||||
SYSTEM_MAXFILESIZE: "100"
|
|
||||||
METRICS_ENABLED: "true"
|
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
|
||||||
SECURITY_CUSTOMGLOBALAPIKEY: "123456789"
|
|
||||||
restart: on-failure:5
|
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||||
|
|
||||||
|
## Docker Setup
|
||||||
|
|
||||||
|
For Docker deployments and configuration, see the [Docker README](../docker/README.md).
|
||||||
|
|
||||||
## Available Scripts
|
## Available Scripts
|
||||||
|
|
||||||
In the project directory, you can run:
|
In the project directory, you can run:
|
||||||
|
422
frontend/package-lock.json
generated
422
frontend/package-lock.json
generated
@ -7,6 +7,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
"license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
@ -42,6 +43,7 @@
|
|||||||
"@types/react": "^19.1.4",
|
"@types/react": "^19.1.4",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"@vitejs/plugin-react": "^4.5.0",
|
"@vitejs/plugin-react": "^4.5.0",
|
||||||
|
"license-checker": "^25.0.1",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"postcss-cli": "^11.0.1",
|
"postcss-cli": "^11.0.1",
|
||||||
"postcss-preset-mantine": "^1.17.0",
|
"postcss-preset-mantine": "^1.17.0",
|
||||||
@ -2480,8 +2482,8 @@
|
|||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||||
"license": "ISC",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
@ -2565,6 +2567,21 @@
|
|||||||
"dequal": "^2.0.3"
|
"dequal": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/array-find-index": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/asap": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@ -2647,8 +2664,8 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"license": "MIT",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
@ -2667,8 +2684,8 @@
|
|||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -2919,8 +2936,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
"license": "MIT",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/console-control-strings": {
|
"node_modules/console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@ -3024,6 +3041,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/debuglog": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==",
|
||||||
|
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/decompress-response": {
|
"node_modules/decompress-response": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
|
||||||
@ -3087,6 +3114,16 @@
|
|||||||
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
|
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/dezalgo": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asap": "^2.0.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dom-accessibility-api": {
|
"node_modules/dom-accessibility-api": {
|
||||||
"version": "0.5.16",
|
"version": "0.5.16",
|
||||||
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
||||||
@ -3408,8 +3445,8 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||||
"license": "ISC",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
@ -3528,8 +3565,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@ -3642,6 +3679,12 @@
|
|||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/hosted-git-info": {
|
||||||
|
"version": "2.8.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||||
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/html-parse-stringify": {
|
"node_modules/html-parse-stringify": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
||||||
@ -3745,8 +3788,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||||
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
|
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"once": "^1.3.0",
|
"once": "^1.3.0",
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
@ -3937,6 +3980,141 @@
|
|||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/license-checker": {
|
||||||
|
"version": "25.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz",
|
||||||
|
"integrity": "sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"debug": "^3.1.0",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"nopt": "^4.0.1",
|
||||||
|
"read-installed": "~4.0.3",
|
||||||
|
"semver": "^5.5.0",
|
||||||
|
"spdx-correct": "^3.0.0",
|
||||||
|
"spdx-expression-parse": "^3.0.0",
|
||||||
|
"spdx-satisfies": "^4.0.0",
|
||||||
|
"treeify": "^1.1.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"license-checker": "bin/license-checker"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/debug": {
|
||||||
|
"version": "3.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/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,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/mkdirp": {
|
||||||
|
"version": "0.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||||
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "bin/cmd.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/nopt": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"abbrev": "1",
|
||||||
|
"osenv": "^0.1.4"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nopt": "bin/nopt.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/license-checker/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,
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lie": {
|
"node_modules/lie": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||||
@ -4331,8 +4509,8 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@ -4340,6 +4518,15 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
@ -4493,6 +4680,27 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/normalize-package-data": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"hosted-git-info": "^2.1.4",
|
||||||
|
"resolve": "^1.10.0",
|
||||||
|
"semver": "2 || 3 || 4 || 5",
|
||||||
|
"validate-npm-package-license": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-package-data/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
@ -4512,6 +4720,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/npm-normalize-package-bin": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/npmlog": {
|
"node_modules/npmlog": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
||||||
@ -4539,12 +4753,41 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/os-homedir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/os-tmpdir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/osenv": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||||
|
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||||
|
"deprecated": "This package is no longer supported.",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"os-homedir": "^1.0.0",
|
||||||
|
"os-tmpdir": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pako": {
|
"node_modules/pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
@ -4584,8 +4827,8 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -5288,6 +5531,46 @@
|
|||||||
"pify": "^2.3.0"
|
"pify": "^2.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/read-installed": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ==",
|
||||||
|
"deprecated": "This package is no longer supported.",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debuglog": "^1.0.1",
|
||||||
|
"read-package-json": "^2.0.0",
|
||||||
|
"readdir-scoped-modules": "^1.0.0",
|
||||||
|
"semver": "2 || 3 || 4 || 5",
|
||||||
|
"slide": "~1.1.3",
|
||||||
|
"util-extend": "^1.0.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/read-installed/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/read-package-json": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==",
|
||||||
|
"deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.1",
|
||||||
|
"json-parse-even-better-errors": "^2.3.0",
|
||||||
|
"normalize-package-data": "^2.0.0",
|
||||||
|
"npm-normalize-package-bin": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readable-stream": {
|
"node_modules/readable-stream": {
|
||||||
"version": "3.6.2",
|
"version": "3.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
@ -5303,6 +5586,19 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readdir-scoped-modules": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
|
||||||
|
"deprecated": "This functionality has been moved to @npmcli/fs",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"debuglog": "^1.0.1",
|
||||||
|
"dezalgo": "^1.0.0",
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"once": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
@ -5558,6 +5854,15 @@
|
|||||||
"simple-concat": "^1.0.0"
|
"simple-concat": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/slide": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.5.7",
|
"version": "0.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
@ -5576,6 +5881,66 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/spdx-compare": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"array-find-index": "^1.0.2",
|
||||||
|
"spdx-expression-parse": "^3.0.0",
|
||||||
|
"spdx-ranges": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-correct": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-expression-parse": "^3.0.0",
|
||||||
|
"spdx-license-ids": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-exceptions": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/spdx-expression-parse": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-exceptions": "^2.1.0",
|
||||||
|
"spdx-license-ids": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-license-ids": {
|
||||||
|
"version": "3.0.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz",
|
||||||
|
"integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/spdx-ranges": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/spdx-satisfies": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-compare": "^1.0.0",
|
||||||
|
"spdx-expression-parse": "^3.0.0",
|
||||||
|
"spdx-ranges": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
@ -5814,6 +6179,15 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/treeify": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.8.1",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
@ -5980,6 +6354,22 @@
|
|||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/util-extend": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/validate-npm-package-license": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-correct": "^3.0.0",
|
||||||
|
"spdx-expression-parse": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.3.5",
|
"version": "6.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
|
||||||
@ -6129,8 +6519,8 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"name": "frontend",
|
"name": "frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE",
|
||||||
"proxy": "http://localhost:8080",
|
"proxy": "http://localhost:8080",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
@ -38,7 +39,8 @@
|
|||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"tauri-dev": "tauri dev --no-watch",
|
"tauri-dev": "tauri dev --no-watch",
|
||||||
"tauri-build": "tauri build"
|
"tauri-build": "tauri build",
|
||||||
|
"generate-licenses": "node scripts/generate-licenses.js"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
@ -63,6 +65,7 @@
|
|||||||
"@types/react": "^19.1.4",
|
"@types/react": "^19.1.4",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"@vitejs/plugin-react": "^4.5.0",
|
"@vitejs/plugin-react": "^4.5.0",
|
||||||
|
"license-checker": "^25.0.1",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"postcss-cli": "^11.0.1",
|
"postcss-cli": "^11.0.1",
|
||||||
"postcss-preset-mantine": "^1.17.0",
|
"postcss-preset-mantine": "^1.17.0",
|
||||||
|
415
frontend/scripts/generate-licenses.js
Normal file
415
frontend/scripts/generate-licenses.js
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate 3rd party licenses for frontend dependencies
|
||||||
|
* This script creates a JSON file similar to the Java backend's 3rdPartyLicenses.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
const OUTPUT_FILE = path.join(__dirname, '..', 'src', 'assets', '3rdPartyLicenses.json');
|
||||||
|
const PACKAGE_JSON = path.join(__dirname, '..', 'package.json');
|
||||||
|
|
||||||
|
// Ensure the output directory exists
|
||||||
|
const outputDir = path.dirname(OUTPUT_FILE);
|
||||||
|
if (!fs.existsSync(outputDir)) {
|
||||||
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 Generating frontend license report...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Install license-checker if not present
|
||||||
|
try {
|
||||||
|
require.resolve('license-checker');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('📦 Installing license-checker...');
|
||||||
|
execSync('npm install --save-dev license-checker', { stdio: 'inherit' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate license report using license-checker (more reliable)
|
||||||
|
const licenseReport = execSync('npx license-checker --production --json', {
|
||||||
|
encoding: 'utf8',
|
||||||
|
cwd: path.dirname(PACKAGE_JSON)
|
||||||
|
});
|
||||||
|
|
||||||
|
let licenseData;
|
||||||
|
try {
|
||||||
|
licenseData = JSON.parse(licenseReport);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('❌ Failed to parse license data:', parseError.message);
|
||||||
|
console.error('Raw output:', licenseReport.substring(0, 500) + '...');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!licenseData || typeof licenseData !== 'object') {
|
||||||
|
console.error('❌ Invalid license data structure');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert license-checker format to array
|
||||||
|
const licenseArray = Object.entries(licenseData).map(([key, value]) => {
|
||||||
|
let name, version;
|
||||||
|
|
||||||
|
// Handle scoped packages like @mantine/core@1.0.0
|
||||||
|
if (key.startsWith('@')) {
|
||||||
|
const parts = key.split('@');
|
||||||
|
name = `@${parts[1]}`;
|
||||||
|
version = parts[2];
|
||||||
|
} else {
|
||||||
|
// Handle regular packages like react@18.0.0
|
||||||
|
const lastAtIndex = key.lastIndexOf('@');
|
||||||
|
name = key.substring(0, lastAtIndex);
|
||||||
|
version = key.substring(lastAtIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize license types for edge cases
|
||||||
|
let licenseType = value.licenses;
|
||||||
|
|
||||||
|
// Handle missing or null licenses
|
||||||
|
if (!licenseType || licenseType === null || licenseType === undefined) {
|
||||||
|
licenseType = 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle empty string licenses
|
||||||
|
if (licenseType === '') {
|
||||||
|
licenseType = 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle array licenses (rare but possible)
|
||||||
|
if (Array.isArray(licenseType)) {
|
||||||
|
licenseType = licenseType.join(' AND ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle object licenses (fallback)
|
||||||
|
if (typeof licenseType === 'object' && licenseType !== null) {
|
||||||
|
licenseType = 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
version: version || value.version || 'unknown',
|
||||||
|
licenseType: licenseType,
|
||||||
|
repository: value.repository,
|
||||||
|
url: value.url,
|
||||||
|
link: value.licenseUrl
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Transform to match Java backend format
|
||||||
|
const transformedData = {
|
||||||
|
dependencies: licenseArray.map(dep => {
|
||||||
|
const licenseType = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : (dep.licenseType || 'Unknown');
|
||||||
|
const licenseUrl = dep.link || getLicenseUrl(licenseType);
|
||||||
|
|
||||||
|
return {
|
||||||
|
moduleName: dep.name,
|
||||||
|
moduleUrl: dep.repository || dep.url || `https://www.npmjs.com/package/${dep.name}`,
|
||||||
|
moduleVersion: dep.version,
|
||||||
|
moduleLicense: licenseType,
|
||||||
|
moduleLicenseUrl: licenseUrl
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// Log summary of license types found
|
||||||
|
const licenseSummary = licenseArray.reduce((acc, dep) => {
|
||||||
|
const license = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : (dep.licenseType || 'Unknown');
|
||||||
|
acc[license] = (acc[license] || 0) + 1;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
console.log('📊 License types found:');
|
||||||
|
Object.entries(licenseSummary).forEach(([license, count]) => {
|
||||||
|
console.log(` ${license}: ${count} packages`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Log any complex or unusual license formats for debugging
|
||||||
|
const complexLicenses = licenseArray.filter(dep =>
|
||||||
|
dep.licenseType && (
|
||||||
|
dep.licenseType.includes('AND') ||
|
||||||
|
dep.licenseType.includes('OR') ||
|
||||||
|
dep.licenseType === 'Unknown' ||
|
||||||
|
dep.licenseType.includes('SEE LICENSE')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (complexLicenses.length > 0) {
|
||||||
|
console.log('\n🔍 Complex/Edge case licenses detected:');
|
||||||
|
complexLicenses.forEach(dep => {
|
||||||
|
console.log(` ${dep.name}@${dep.version}: "${dep.licenseType}"`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for potentially problematic licenses
|
||||||
|
const problematicLicenses = checkLicenseCompatibility(licenseSummary, licenseArray);
|
||||||
|
if (problematicLicenses.length > 0) {
|
||||||
|
console.log('\n⚠️ License compatibility warnings:');
|
||||||
|
problematicLicenses.forEach(warning => {
|
||||||
|
console.log(` ${warning.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write license warnings to a separate file for CI/CD
|
||||||
|
const warningsFile = path.join(__dirname, '..', 'src', 'assets', 'license-warnings.json');
|
||||||
|
fs.writeFileSync(warningsFile, JSON.stringify({
|
||||||
|
warnings: problematicLicenses,
|
||||||
|
generated: new Date().toISOString()
|
||||||
|
}, null, 2));
|
||||||
|
console.log(`⚠️ License warnings saved to: ${warningsFile}`);
|
||||||
|
} else {
|
||||||
|
console.log('\n✅ All licenses appear to be corporate-friendly');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to file
|
||||||
|
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(transformedData, null, 4));
|
||||||
|
|
||||||
|
console.log(`✅ License report generated successfully!`);
|
||||||
|
console.log(`📄 Found ${transformedData.dependencies.length} dependencies`);
|
||||||
|
console.log(`💾 Saved to: ${OUTPUT_FILE}`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error generating license report:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get standard license URLs for common licenses
|
||||||
|
*/
|
||||||
|
function getLicenseUrl(licenseType) {
|
||||||
|
if (!licenseType || licenseType === 'Unknown') return '';
|
||||||
|
|
||||||
|
const licenseUrls = {
|
||||||
|
'MIT': 'https://opensource.org/licenses/MIT',
|
||||||
|
'Apache-2.0': 'https://www.apache.org/licenses/LICENSE-2.0',
|
||||||
|
'Apache License 2.0': 'https://www.apache.org/licenses/LICENSE-2.0',
|
||||||
|
'BSD-3-Clause': 'https://opensource.org/licenses/BSD-3-Clause',
|
||||||
|
'BSD-2-Clause': 'https://opensource.org/licenses/BSD-2-Clause',
|
||||||
|
'BSD': 'https://opensource.org/licenses/BSD-3-Clause',
|
||||||
|
'GPL-3.0': 'https://www.gnu.org/licenses/gpl-3.0.html',
|
||||||
|
'GPL-2.0': 'https://www.gnu.org/licenses/gpl-2.0.html',
|
||||||
|
'LGPL-2.1': 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html',
|
||||||
|
'LGPL-3.0': 'https://www.gnu.org/licenses/lgpl-3.0.html',
|
||||||
|
'ISC': 'https://opensource.org/licenses/ISC',
|
||||||
|
'CC0-1.0': 'https://creativecommons.org/publicdomain/zero/1.0/',
|
||||||
|
'Unlicense': 'https://unlicense.org/',
|
||||||
|
'MPL-2.0': 'https://www.mozilla.org/en-US/MPL/2.0/',
|
||||||
|
'WTFPL': 'http://www.wtfpl.net/',
|
||||||
|
'Zlib': 'https://opensource.org/licenses/Zlib',
|
||||||
|
'Artistic-2.0': 'https://opensource.org/licenses/Artistic-2.0',
|
||||||
|
'EPL-1.0': 'https://www.eclipse.org/legal/epl-v10.html',
|
||||||
|
'EPL-2.0': 'https://www.eclipse.org/legal/epl-2.0/',
|
||||||
|
'CDDL-1.0': 'https://opensource.org/licenses/CDDL-1.0',
|
||||||
|
'Ruby': 'https://www.ruby-lang.org/en/about/license.txt',
|
||||||
|
'Python-2.0': 'https://www.python.org/download/releases/2.0/license/',
|
||||||
|
'Public Domain': 'https://creativecommons.org/publicdomain/zero/1.0/',
|
||||||
|
'UNLICENSED': ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try exact match first
|
||||||
|
if (licenseUrls[licenseType]) {
|
||||||
|
return licenseUrls[licenseType];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try case-insensitive match
|
||||||
|
const lowerType = licenseType.toLowerCase();
|
||||||
|
for (const [key, url] of Object.entries(licenseUrls)) {
|
||||||
|
if (key.toLowerCase() === lowerType) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle complex SPDX expressions like "(MIT AND Zlib)" or "(MIT OR CC0-1.0)"
|
||||||
|
if (licenseType.includes('AND') || licenseType.includes('OR')) {
|
||||||
|
// Extract the first license from compound expressions for URL
|
||||||
|
const match = licenseType.match(/\(?\s*([A-Za-z0-9\-\.]+)/);
|
||||||
|
if (match && licenseUrls[match[1]]) {
|
||||||
|
return licenseUrls[match[1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For non-standard licenses, return empty string (will use package link if available)
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for potentially problematic licenses that may not be MIT/corporate compatible
|
||||||
|
*/
|
||||||
|
function checkLicenseCompatibility(licenseSummary, licenseArray) {
|
||||||
|
const warnings = [];
|
||||||
|
|
||||||
|
// Define problematic license patterns
|
||||||
|
const problematicLicenses = {
|
||||||
|
// Copyleft licenses
|
||||||
|
'GPL-2.0': 'Strong copyleft license - requires derivative works to be GPL',
|
||||||
|
'GPL-3.0': 'Strong copyleft license - requires derivative works to be GPL',
|
||||||
|
'LGPL-2.1': 'Weak copyleft license - may require source disclosure for modifications',
|
||||||
|
'LGPL-3.0': 'Weak copyleft license - may require source disclosure for modifications',
|
||||||
|
'AGPL-3.0': 'Network copyleft license - requires source disclosure for network use',
|
||||||
|
'AGPL-1.0': 'Network copyleft license - requires source disclosure for network use',
|
||||||
|
|
||||||
|
// Other potentially problematic licenses
|
||||||
|
'WTFPL': 'Potentially problematic license - legal uncertainty',
|
||||||
|
'CC-BY-SA-4.0': 'ShareAlike license - requires derivative works to use same license',
|
||||||
|
'CC-BY-SA-3.0': 'ShareAlike license - requires derivative works to use same license',
|
||||||
|
'CC-BY-NC-4.0': 'Non-commercial license - prohibits commercial use',
|
||||||
|
'CC-BY-NC-3.0': 'Non-commercial license - prohibits commercial use',
|
||||||
|
'OSL-3.0': 'Copyleft license - requires derivative works to be OSL',
|
||||||
|
'EPL-1.0': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'EPL-2.0': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'CDDL-1.0': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'CDDL-1.1': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'CPL-1.0': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'MPL-1.1': 'Weak copyleft license - may require source disclosure',
|
||||||
|
'EUPL-1.1': 'Copyleft license - requires derivative works to be EUPL',
|
||||||
|
'EUPL-1.2': 'Copyleft license - requires derivative works to be EUPL',
|
||||||
|
'UNLICENSED': 'No license specified - usage rights unclear',
|
||||||
|
'Unknown': 'License not detected - manual review required'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Known good licenses (no warnings needed)
|
||||||
|
const goodLicenses = new Set([
|
||||||
|
'MIT', 'Apache-2.0', 'Apache License 2.0', 'BSD-2-Clause', 'BSD-3-Clause', 'BSD',
|
||||||
|
'ISC', 'CC0-1.0', 'Public Domain', 'Unlicense', '0BSD', 'BlueOak-1.0.0',
|
||||||
|
'Zlib', 'Artistic-2.0', 'Python-2.0', 'Ruby', 'MPL-2.0', 'CC-BY-4.0',
|
||||||
|
'SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Helper function to normalize license names for comparison
|
||||||
|
function normalizeLicense(license) {
|
||||||
|
return license
|
||||||
|
.replace(/-or-later$/, '') // Remove -or-later suffix
|
||||||
|
.replace(/\+$/, '') // Remove + suffix
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each license type
|
||||||
|
Object.entries(licenseSummary).forEach(([license, count]) => {
|
||||||
|
// Skip known good licenses
|
||||||
|
if (goodLicenses.has(license)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this license only affects our own packages
|
||||||
|
const affectedPackages = licenseArray.filter(dep => {
|
||||||
|
const depLicense = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : dep.licenseType;
|
||||||
|
return depLicense === license;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isOnlyOurPackages = affectedPackages.every(dep =>
|
||||||
|
dep.name === 'frontend' ||
|
||||||
|
dep.name.toLowerCase().includes('stirling-pdf') ||
|
||||||
|
dep.name.toLowerCase().includes('stirling_pdf') ||
|
||||||
|
dep.name.toLowerCase().includes('stirlingpdf')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isOnlyOurPackages && (license === 'UNLICENSED' || license.startsWith('SEE LICENSE IN'))) {
|
||||||
|
return; // Skip warnings for our own Stirling-PDF packages
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for compound licenses like "(MIT AND Zlib)" or "(MIT OR CC0-1.0)"
|
||||||
|
if (license.includes('AND') || license.includes('OR')) {
|
||||||
|
// For OR licenses, check if there's at least one acceptable license option
|
||||||
|
if (license.includes('OR')) {
|
||||||
|
// Extract license components from OR expression
|
||||||
|
const orComponents = license
|
||||||
|
.replace(/[()]/g, '') // Remove parentheses
|
||||||
|
.split(' OR ')
|
||||||
|
.map(component => component.trim());
|
||||||
|
|
||||||
|
// Check if any component is in the goodLicenses set (with normalization)
|
||||||
|
const hasGoodLicense = orComponents.some(component => {
|
||||||
|
const normalized = normalizeLicense(component);
|
||||||
|
return goodLicenses.has(component) || goodLicenses.has(normalized);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasGoodLicense) {
|
||||||
|
return; // Skip warning - can use the good license option
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For AND licenses or OR licenses with no good options, check for problematic components
|
||||||
|
const hasProblematicComponent = Object.keys(problematicLicenses).some(problematic =>
|
||||||
|
license.includes(problematic)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasProblematicComponent) {
|
||||||
|
const affectedPackages = licenseArray
|
||||||
|
.filter(dep => {
|
||||||
|
const depLicense = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : dep.licenseType;
|
||||||
|
return depLicense === license;
|
||||||
|
})
|
||||||
|
.map(dep => ({
|
||||||
|
name: dep.name,
|
||||||
|
version: dep.version,
|
||||||
|
url: dep.repository || dep.url || `https://www.npmjs.com/package/${dep.name}`
|
||||||
|
}));
|
||||||
|
|
||||||
|
const licenseType = license.includes('AND') ? 'AND' : 'OR';
|
||||||
|
const reason = licenseType === 'AND'
|
||||||
|
? 'Compound license with AND requirement - all components must be compatible'
|
||||||
|
: 'Compound license with potentially problematic components and no good fallback options';
|
||||||
|
|
||||||
|
warnings.push({
|
||||||
|
message: `📋 This PR contains ${count} package${count > 1 ? 's' : ''} with compound license "${license}" - manual review recommended`,
|
||||||
|
licenseType: license,
|
||||||
|
licenseUrl: '',
|
||||||
|
reason: reason,
|
||||||
|
packageCount: count,
|
||||||
|
affectedDependencies: affectedPackages
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for exact matches with problematic licenses
|
||||||
|
if (problematicLicenses[license]) {
|
||||||
|
const affectedPackages = licenseArray
|
||||||
|
.filter(dep => {
|
||||||
|
const depLicense = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : dep.licenseType;
|
||||||
|
return depLicense === license;
|
||||||
|
})
|
||||||
|
.map(dep => ({
|
||||||
|
name: dep.name,
|
||||||
|
version: dep.version,
|
||||||
|
url: dep.repository || dep.url || `https://www.npmjs.com/package/${dep.name}`
|
||||||
|
}));
|
||||||
|
|
||||||
|
const packageList = affectedPackages.map(pkg => pkg.name).slice(0, 5).join(', ') + (affectedPackages.length > 5 ? `, and ${affectedPackages.length - 5} more` : '');
|
||||||
|
const licenseUrl = getLicenseUrl(license) || 'https://opensource.org/licenses';
|
||||||
|
|
||||||
|
warnings.push({
|
||||||
|
message: `⚠️ This PR contains ${count} package${count > 1 ? 's' : ''} with license type [${license}](${licenseUrl}) - ${problematicLicenses[license]}. Affected packages: ${packageList}`,
|
||||||
|
licenseType: license,
|
||||||
|
licenseUrl: licenseUrl,
|
||||||
|
reason: problematicLicenses[license],
|
||||||
|
packageCount: count,
|
||||||
|
affectedDependencies: affectedPackages
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Unknown license type - flag for manual review
|
||||||
|
const affectedPackages = licenseArray
|
||||||
|
.filter(dep => {
|
||||||
|
const depLicense = Array.isArray(dep.licenseType) ? dep.licenseType.join(', ') : dep.licenseType;
|
||||||
|
return depLicense === license;
|
||||||
|
})
|
||||||
|
.map(dep => ({
|
||||||
|
name: dep.name,
|
||||||
|
version: dep.version,
|
||||||
|
url: dep.repository || dep.url || `https://www.npmjs.com/package/${dep.name}`
|
||||||
|
}));
|
||||||
|
|
||||||
|
warnings.push({
|
||||||
|
message: `❓ This PR contains ${count} package${count > 1 ? 's' : ''} with unknown license type "${license}" - manual review required`,
|
||||||
|
licenseType: license,
|
||||||
|
licenseUrl: '',
|
||||||
|
reason: 'Unknown license type',
|
||||||
|
packageCount: count,
|
||||||
|
affectedDependencies: affectedPackages
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return warnings;
|
||||||
|
}
|
@ -21,7 +21,7 @@ import { pdfExportService } from "../../services/pdfExportService";
|
|||||||
import { useThumbnailGeneration } from "../../hooks/useThumbnailGeneration";
|
import { useThumbnailGeneration } from "../../hooks/useThumbnailGeneration";
|
||||||
import { calculateScaleFromFileSize } from "../../utils/thumbnailUtils";
|
import { calculateScaleFromFileSize } from "../../utils/thumbnailUtils";
|
||||||
import { fileStorage } from "../../services/fileStorage";
|
import { fileStorage } from "../../services/fileStorage";
|
||||||
import './pageEditor.module.css';
|
import './PageEditor.module.css';
|
||||||
import PageThumbnail from './PageThumbnail';
|
import PageThumbnail from './PageThumbnail';
|
||||||
import BulkSelectionPanel from './BulkSelectionPanel';
|
import BulkSelectionPanel from './BulkSelectionPanel';
|
||||||
import DragDropGrid from './DragDropGrid';
|
import DragDropGrid from './DragDropGrid';
|
||||||
|
@ -19,9 +19,8 @@ if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" && "$FAT_DOCKER" != "true"
|
|||||||
#apk add --no-cache calibre@testing
|
#apk add --no-cache calibre@testing
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$FAT_DOCKER" != "true" ]]; then
|
# Security jar is now built into the application jar during Docker build
|
||||||
/scripts/download-security-jar.sh
|
# No need to download it separately
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$LANGS" ]]; then
|
if [[ -n "$LANGS" ]]; then
|
||||||
/scripts/installFonts.sh $LANGS
|
/scripts/installFonts.sh $LANGS
|
||||||
|
63
testing/compose/docker-compose-security-with-login.yml
Normal file
63
testing/compose/docker-compose-security-with-login.yml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile
|
||||||
|
container_name: Stirling-PDF-Security-with-login
|
||||||
|
restart: on-failure:5
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- ../../stirling/latest/data:/usr/share/tessdata:rw
|
||||||
|
- ../../stirling/latest/config:/configs:rw
|
||||||
|
- ../../stirling/latest/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
|
DOCKER_ENABLE_SECURITY: "true"
|
||||||
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
SECURITY_INITIALLOGIN_USERNAME: "admin"
|
||||||
|
SECURITY_INITIALLOGIN_PASSWORD: "stirling"
|
||||||
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
|
UI_APPNAME: Stirling-PDF
|
||||||
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security and Login
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
||||||
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
|
SECURITY_CUSTOMGLOBALAPIKEY: "123456789"
|
||||||
|
SHOW_SURVEY: "true"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend-security-login
|
||||||
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
stirling-data:
|
||||||
|
stirling-config:
|
||||||
|
stirling-logs:
|
59
testing/compose/docker-compose-security.yml
Normal file
59
testing/compose/docker-compose-security.yml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
services:
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile
|
||||||
|
container_name: Stirling-PDF-Security
|
||||||
|
restart: on-failure:5
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- ../../stirling/latest/data:/usr/share/tessdata:rw
|
||||||
|
- ../../stirling/latest/config:/configs:rw
|
||||||
|
- ../../stirling/latest/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "false"
|
||||||
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
|
UI_APPNAME: Stirling-PDF
|
||||||
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Latest
|
||||||
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
|
SHOW_SURVEY: "true"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend-security
|
||||||
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
stirling-data:
|
||||||
|
stirling-config:
|
||||||
|
stirling-logs:
|
@ -1,11 +1,14 @@
|
|||||||
services:
|
services:
|
||||||
stirling-pdf:
|
backend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/backend/Dockerfile.ultra-lite
|
||||||
container_name: Stirling-PDF-Ultra-Lite
|
container_name: Stirling-PDF-Ultra-Lite
|
||||||
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-ultra-lite
|
restart: on-failure:5
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 1G
|
memory: 2G
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -qv 'Please sign in'"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
@ -14,10 +17,12 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./stirling/latest/config:/configs:rw
|
- ../../stirling/latest/config:/configs:rw
|
||||||
- ./stirling/latest/logs:/logs:rw
|
- ../../stirling/latest/logs:/logs:rw
|
||||||
environment:
|
environment:
|
||||||
|
DISABLE_ADDITIONAL_FEATURES: "true"
|
||||||
SECURITY_ENABLELOGIN: "false"
|
SECURITY_ENABLELOGIN: "false"
|
||||||
|
ENDPOINTS_GROUPS_TO_REMOVE: "CLI"
|
||||||
SYSTEM_DEFAULTLOCALE: en-US
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
UI_APPNAME: Stirling-PDF-Ultra-lite
|
UI_APPNAME: Stirling-PDF-Ultra-lite
|
||||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Ultra-lite Latest
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF-Ultra-lite Latest
|
||||||
@ -26,4 +31,29 @@ services:
|
|||||||
METRICS_ENABLED: "true"
|
METRICS_ENABLED: "true"
|
||||||
SYSTEM_GOOGLEVISIBILITY: "true"
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
SHOW_SURVEY: "true"
|
SHOW_SURVEY: "true"
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: docker/frontend/Dockerfile
|
||||||
|
container_name: stirling-pdf-frontend-ultra-lite
|
||||||
restart: on-failure:5
|
restart: on-failure:5
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
BACKEND_URL: http://backend:8080
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
networks:
|
||||||
|
- stirling-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stirling-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
stirling-data:
|
||||||
|
stirling-config:
|
||||||
|
stirling-logs:
|
125
testing/test.sh
125
testing/test.sh
@ -225,8 +225,8 @@ test_compose() {
|
|||||||
|
|
||||||
echo "Testing $compose_file configuration..."
|
echo "Testing $compose_file configuration..."
|
||||||
|
|
||||||
# Start up the Docker Compose service
|
# Start up the Docker Compose service with forced rebuild
|
||||||
docker-compose -f "$compose_file" up -d
|
docker-compose -f "$compose_file" up -d --build
|
||||||
|
|
||||||
# Wait for the service to become healthy
|
# Wait for the service to become healthy
|
||||||
if check_health "$service_name" "$compose_file"; then
|
if check_health "$service_name" "$compose_file"; then
|
||||||
@ -276,22 +276,27 @@ main() {
|
|||||||
EXPECTED_VERSION=$(get_expected_version)
|
EXPECTED_VERSION=$(get_expected_version)
|
||||||
echo "Expected version: $EXPECTED_VERSION"
|
echo "Expected version: $EXPECTED_VERSION"
|
||||||
|
|
||||||
# Building Docker images
|
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
|
|
||||||
docker build --build-arg VERSION_TAG=alpha -t docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
|
|
||||||
|
|
||||||
# Test each configuration
|
# Test each configuration
|
||||||
run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml"
|
run_tests "Stirling-PDF-Ultra-Lite" "./testing/compose/docker-compose-ultra-lite.yml"
|
||||||
|
|
||||||
echo "Testing webpage accessibility..."
|
echo "Testing basic frontend homepage accessibility..."
|
||||||
cd "testing"
|
if curl -f http://localhost:3000 > /dev/null 2>&1; then
|
||||||
if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
|
passed_tests+=("Frontend-Homepage-Accessibility-lite")
|
||||||
passed_tests+=("Webpage-Accessibility-lite")
|
echo "Frontend homepage accessibility check passed"
|
||||||
else
|
else
|
||||||
failed_tests+=("Webpage-Accessibility-lite")
|
failed_tests+=("Frontend-Homepage-Accessibility-lite")
|
||||||
echo "Webpage accessibility lite tests failed"
|
echo "Frontend homepage accessibility check failed"
|
||||||
fi
|
fi
|
||||||
cd "$PROJECT_ROOT"
|
|
||||||
|
# echo "Testing webpage accessibility..."
|
||||||
|
# cd "testing"
|
||||||
|
# if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
|
||||||
|
# passed_tests+=("Webpage-Accessibility-lite")
|
||||||
|
# else
|
||||||
|
# failed_tests+=("Webpage-Accessibility-lite")
|
||||||
|
# echo "Webpage accessibility lite tests failed"
|
||||||
|
# fi
|
||||||
|
# cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
echo "Testing version verification..."
|
echo "Testing version verification..."
|
||||||
if verify_app_version "Stirling-PDF-Ultra-Lite" "http://localhost:8080"; then
|
if verify_app_version "Stirling-PDF-Ultra-Lite" "http://localhost:8080"; then
|
||||||
@ -302,10 +307,11 @@ main() {
|
|||||||
echo "Version verification failed for Stirling-PDF-Ultra-Lite"
|
echo "Version verification failed for Stirling-PDF-Ultra-Lite"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
|
docker-compose -f "./testing/compose/docker-compose-ultra-lite.yml" down
|
||||||
|
|
||||||
# run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
|
# Clean up any generated config files
|
||||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
|
echo "Cleaning up generated config files..."
|
||||||
|
rm -rf "$PROJECT_ROOT/stirling/" 2>/dev/null || true
|
||||||
|
|
||||||
export DISABLE_ADDITIONAL_FEATURES=false
|
export DISABLE_ADDITIONAL_FEATURES=false
|
||||||
# Run the gradlew build command and check if it fails
|
# Run the gradlew build command and check if it fails
|
||||||
@ -319,43 +325,44 @@ main() {
|
|||||||
EXPECTED_VERSION=$(get_expected_version)
|
EXPECTED_VERSION=$(get_expected_version)
|
||||||
echo "Expected version with security enabled: $EXPECTED_VERSION"
|
echo "Expected version with security enabled: $EXPECTED_VERSION"
|
||||||
|
|
||||||
# Building Docker images with security enabled
|
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
|
|
||||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
|
|
||||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
|
|
||||||
|
|
||||||
|
|
||||||
# Test each configuration with security
|
# Test each configuration with security
|
||||||
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
|
run_tests "Stirling-PDF-Security" "./testing/compose/docker-compose-security.yml"
|
||||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
|
|
||||||
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
|
|
||||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
|
|
||||||
|
|
||||||
|
echo "Testing basic frontend homepage accessibility..."
|
||||||
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
|
if curl -f http://localhost:3000 > /dev/null 2>&1; then
|
||||||
|
passed_tests+=("Frontend-Homepage-Accessibility-full")
|
||||||
echo "Testing webpage accessibility..."
|
echo "Frontend homepage accessibility check passed"
|
||||||
cd "testing"
|
|
||||||
if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
|
|
||||||
passed_tests+=("Webpage-Accessibility-full")
|
|
||||||
else
|
else
|
||||||
failed_tests+=("Webpage-Accessibility-full")
|
failed_tests+=("Frontend-Homepage-Accessibility-full")
|
||||||
echo "Webpage accessibility full tests failed"
|
echo "Frontend homepage accessibility check failed"
|
||||||
fi
|
fi
|
||||||
cd "$PROJECT_ROOT"
|
|
||||||
|
# echo "Testing webpage accessibility..."
|
||||||
|
# cd "testing"
|
||||||
|
# if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
|
||||||
|
# passed_tests+=("Webpage-Accessibility-full")
|
||||||
|
# else
|
||||||
|
# failed_tests+=("Webpage-Accessibility-full")
|
||||||
|
# echo "Webpage accessibility full tests failed"
|
||||||
|
# fi
|
||||||
|
# cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
echo "Testing version verification..."
|
echo "Testing version verification..."
|
||||||
if verify_app_version "Stirling-PDF-Security-Fat" "http://localhost:8080"; then
|
if verify_app_version "Stirling-PDF-Security" "http://localhost:8080"; then
|
||||||
passed_tests+=("Stirling-PDF-Security-Fat-Version-Check")
|
passed_tests+=("Stirling-PDF-Security-Version-Check")
|
||||||
echo "Version verification passed for Stirling-PDF-Security-Fat"
|
echo "Version verification passed for Stirling-PDF-Security"
|
||||||
else
|
else
|
||||||
failed_tests+=("Stirling-PDF-Security-Fat-Version-Check")
|
failed_tests+=("Stirling-PDF-Security-Version-Check")
|
||||||
echo "Version verification failed for Stirling-PDF-Security-Fat"
|
echo "Version verification failed for Stirling-PDF-Security"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
|
docker-compose -f "./testing/compose/docker-compose-security.yml" down
|
||||||
|
|
||||||
|
# Clean up any generated config files
|
||||||
|
echo "Cleaning up generated config files..."
|
||||||
|
rm -rf "$PROJECT_ROOT/stirling/" 2>/dev/null || true
|
||||||
|
|
||||||
run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml"
|
run_tests "Stirling-PDF-Security-with-login" "./testing/compose/docker-compose-security-with-login.yml"
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
# Create directory for file snapshots if it doesn't exist
|
# Create directory for file snapshots if it doesn't exist
|
||||||
@ -368,7 +375,7 @@ main() {
|
|||||||
DIFF_FILE="$SNAPSHOT_DIR/files_diff.txt"
|
DIFF_FILE="$SNAPSHOT_DIR/files_diff.txt"
|
||||||
|
|
||||||
# Define container name variable for consistency
|
# Define container name variable for consistency
|
||||||
CONTAINER_NAME="Stirling-PDF-Security-Fat-with-login"
|
CONTAINER_NAME="Stirling-PDF-Security-with-login"
|
||||||
|
|
||||||
capture_file_list "$CONTAINER_NAME" "$BEFORE_FILE"
|
capture_file_list "$CONTAINER_NAME" "$BEFORE_FILE"
|
||||||
|
|
||||||
@ -409,28 +416,12 @@ main() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker-compose -f "./exampleYmlFiles/test_cicd.yml" down
|
docker-compose -f "./testing/compose/docker-compose-security-with-login.yml" down
|
||||||
|
|
||||||
|
# Clean up any generated config files
|
||||||
|
echo "Cleaning up generated config files..."
|
||||||
|
rm -rf "$PROJECT_ROOT/stirling/" 2>/dev/null || true
|
||||||
|
|
||||||
run_tests "Stirling-PDF-Fat-Disable-Endpoints" "./exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml"
|
|
||||||
|
|
||||||
echo "Testing disabled endpoints..."
|
|
||||||
if ./testing/test_disabledEndpoints.sh -f ./testing/endpoints.txt -b http://localhost:8080; then
|
|
||||||
passed_tests+=("Disabled-Endpoints")
|
|
||||||
else
|
|
||||||
failed_tests+=("Disabled-Endpoints")
|
|
||||||
echo "Disabled Endpoints tests failed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Testing version verification..."
|
|
||||||
if verify_app_version "Stirling-PDF-Fat-Disable-Endpoints" "http://localhost:8080"; then
|
|
||||||
passed_tests+=("Stirling-PDF-Fat-Disable-Endpoints-Version-Check")
|
|
||||||
echo "Version verification passed for Stirling-PDF-Fat-Disable-Endpoints"
|
|
||||||
else
|
|
||||||
failed_tests+=("Stirling-PDF-Fat-Disable-Endpoints-Version-Check")
|
|
||||||
echo "Version verification failed for Stirling-PDF-Fat-Disable-Endpoints"
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-endpoints-disabled.yml" down
|
|
||||||
|
|
||||||
# Report results
|
# Report results
|
||||||
echo "All tests completed in $SECONDS seconds."
|
echo "All tests completed in $SECONDS seconds."
|
||||||
|
@ -51,29 +51,33 @@ build_and_test() {
|
|||||||
local dockerfile_name="./Dockerfile"
|
local dockerfile_name="./Dockerfile"
|
||||||
local image_base="stirlingtools/stirling-pdf"
|
local image_base="stirlingtools/stirling-pdf"
|
||||||
local security_suffix=""
|
local security_suffix=""
|
||||||
local docker_compose_base="./exampleYmlFiles/docker-compose-latest"
|
local docker_compose_base="./testing/compose/docker-compose"
|
||||||
local compose_suffix=".yml"
|
local compose_suffix=".yml"
|
||||||
local service_name_base="Stirling-PDF"
|
local service_name_base="Stirling-PDF"
|
||||||
|
|
||||||
if [ "$enable_security" == "true" ]; then
|
|
||||||
security_suffix="-Security"
|
|
||||||
docker_compose_base+="-security" # Append to base name for Docker Compose files with security
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$build_type" in
|
case "$build_type" in
|
||||||
full)
|
full)
|
||||||
dockerfile_name="./Dockerfile"
|
dockerfile_name="./docker/backend/Dockerfile"
|
||||||
|
if [ "$enable_security" == "true" ]; then
|
||||||
|
compose_file="${docker_compose_base}-fat-security${compose_suffix}"
|
||||||
|
service_name="Stirling-PDF-Security-Fat"
|
||||||
|
else
|
||||||
|
compose_file="${docker_compose_base}-fat${compose_suffix}"
|
||||||
|
service_name="stirling-pdf-backend-fat"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
ultra-lite)
|
ultra-lite)
|
||||||
dockerfile_name="./Dockerfile.ultra-lite"
|
dockerfile_name="./docker/backend/Dockerfile.ultra-lite"
|
||||||
|
if [ "$enable_security" == "true" ]; then
|
||||||
|
compose_file="${docker_compose_base}-ultra-lite-security${compose_suffix}"
|
||||||
|
service_name="stirling-pdf-backend-ultra-lite-security"
|
||||||
|
else
|
||||||
|
compose_file="${docker_compose_base}-ultra-lite${compose_suffix}"
|
||||||
|
service_name="Stirling-PDF-Ultra-Lite"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Dynamic image tag and service name based on build type and security
|
|
||||||
local image_tag="${image_base}:latest${build_type}${security_suffix}"
|
|
||||||
local service_name="${service_name_base}${build_type^}${security_suffix}"
|
|
||||||
local compose_file="${docker_compose_base}${build_type}${compose_suffix}"
|
|
||||||
|
|
||||||
# Gradle build with or without security
|
# Gradle build with or without security
|
||||||
echo "Running ./gradlew clean build with security=$enable_security..."
|
echo "Running ./gradlew clean build with security=$enable_security..."
|
||||||
./gradlew clean build
|
./gradlew clean build
|
||||||
@ -83,10 +87,6 @@ build_and_test() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Building Docker image
|
|
||||||
echo "Building Docker image $image_tag with Dockerfile $dockerfile_name..."
|
|
||||||
docker build --build-arg VERSION_TAG=$version_tag -t $image_tag -f $dockerfile_name .
|
|
||||||
|
|
||||||
if [ "$run_compose" == "true" ]; then
|
if [ "$run_compose" == "true" ]; then
|
||||||
echo "Running Docker Compose for $build_type with security=$enable_security..."
|
echo "Running Docker Compose for $build_type with security=$enable_security..."
|
||||||
docker-compose -f "$compose_file" up -d
|
docker-compose -f "$compose_file" up -d
|
||||||
|
Loading…
x
Reference in New Issue
Block a user