diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
index 6a1c4550..482f3af1 100644
--- a/.github/workflows/docker-build.yml
+++ b/.github/workflows/docker-build.yml
@@ -1,13 +1,19 @@
name: Build and Push Docker Images
+# This workflow is triggered by:
+# - Push to main/develop branches (builds 'latest' or branch-tagged images)
+# - Version tags from Release Please (e.g., v1.2.0 -> builds versioned images)
+# - GitHub Releases (created by Release Please)
+# - Manual workflow dispatch
+
on:
push:
branches: [ main, develop ]
- tags: [ 'v*.*.*' ]
+ tags: [ 'v*.*.*' ] # Triggered by Release Please tags
pull_request:
branches: [ main ]
release:
- types: [ published ]
+ types: [ published ] # Triggered when Release Please creates a release
workflow_dispatch:
inputs:
push:
diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml
new file mode 100644
index 00000000..b5973685
--- /dev/null
+++ b/.github/workflows/release-please.yml
@@ -0,0 +1,71 @@
+name: Release Please
+
+on:
+ push:
+ branches: [main]
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ release-please:
+ runs-on: ubuntu-latest
+ outputs:
+ release_created: ${{ steps.release.outputs.release_created }}
+ tag_name: ${{ steps.release.outputs.tag_name }}
+ version: ${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}
+ steps:
+ - name: Run Release Please
+ uses: googleapis/release-please-action@v4
+ id: release
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ config-file: release-please-config.json
+ manifest-file: .release-please-manifest.json
+
+ - name: Output Release Info
+ if: ${{ steps.release.outputs.release_created }}
+ run: |
+ echo "## Release Created! " >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Tag:** ${{ steps.release.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
+ echo "**Version:** ${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Docker images will be built and tagged with this version." >> $GITHUB_STEP_SUMMARY
+
+ # Sync version to package.json files after release
+ sync-versions:
+ needs: release-please
+ if: ${{ needs.release-please.outputs.release_created }}
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: main
+
+ - name: Update package.json versions
+ run: |
+ VERSION="${{ needs.release-please.outputs.version }}"
+ echo "Updating package.json files to version $VERSION"
+
+ # Update backend package.json
+ cd backend
+ npm version $VERSION --no-git-tag-version --allow-same-version
+ cd ..
+
+ # Update frontend package.json
+ cd frontend
+ npm version $VERSION --no-git-tag-version --allow-same-version
+ cd ..
+
+ - name: Commit version updates
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git add backend/package.json frontend/package.json
+ git diff --staged --quiet || git commit -m "chore: sync package.json versions to ${{ needs.release-please.outputs.version }}"
+ git push
diff --git a/.gitignore b/.gitignore
index 86d5dea6..fd3844d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,6 +77,13 @@ certbot/
AGENTS.md
CLAUDE.md
+# Working/planning documents (not for release)
+BUGS_AND_FEATURES.md
+frontend/TEST_PLAN.md
+docs/REFACTORING_PLAN.md
+docs/test-*.md
+docs/feature-*.md
+
# Local artifacts from browser tooling
.playwright-mcp/
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
new file mode 100644
index 00000000..7e437931
--- /dev/null
+++ b/.release-please-manifest.json
@@ -0,0 +1,3 @@
+{
+ ".": "1.1.15"
+}
diff --git a/BUGS_AND_FEATURES.md b/BUGS_AND_FEATURES.md
deleted file mode 100644
index 76696a34..00000000
--- a/BUGS_AND_FEATURES.md
+++ /dev/null
@@ -1,1309 +0,0 @@
-# PicPeak Bug Report & Feature Requests
-
-> **Generated:** January 2, 2026
-> **Version:** Frontend v1.1.15 / Backend v1.1.15
-> **Priority Levels:** P0 (Critical), P1 (High), P2 (Medium), P3 (Low)
-
----
-
-## Table of Contents
-
-1. [BUG-001: Logo Customization Section Formatting Issues](#bug-001-logo-customization-section-formatting-issues)
-2. [BUG-002: Favicon Upload Section Missing Preview](#bug-002-favicon-upload-section-missing-preview)
-3. [FEATURE-003: Custom CSS Instructions Panel](#feature-003-custom-css-instructions-panel)
-4. [FEATURE-004: Custom CSS Integration with Theme Presets & Gallery Layouts](#feature-004-custom-css-integration-with-theme-presets--gallery-layouts)
-5. [BUG-005: Custom Layouts Not Showing in Event Creation](#bug-005-custom-layouts-not-showing-in-event-creation)
-6. [FEATURE-006: Apple Liquid Glass Design Custom CSS Templates](#feature-006-apple-liquid-glass-design-custom-css-templates)
-7. [BUG-007: Typography & Style Section Row Formatting](#bug-007-typography--style-section-row-formatting)
-
----
-
-## BUG-001: Logo Customization Section Formatting Issues
-
-### Priority: P1 (High)
-
-### Location
-- **Page:** `/admin/branding`
-- **Section:** Company Information → Logo Customization
-
-### Current Behavior
-1. The "Upload Logo" button appears as a plain text link instead of a proper button
-2. No preview thumbnail is displayed when a logo has been uploaded
-3. The layout doesn't show the currently uploaded logo image
-4. Button styling is inconsistent with other upload buttons (e.g., Favicon)
-
-### Expected Behavior
-1. "Upload Logo" should be a styled button matching the "Upload Favicon" button style
-2. When a logo is uploaded, a preview thumbnail should be displayed (similar to how other image uploads work)
-3. A "Remove Logo" or "Change Logo" option should appear when a logo exists
-4. The section should show:
- - Current logo preview (if uploaded)
- - Upload/Change button
- - Remove button (if logo exists)
- - File size/dimension info
-
-### Technical Analysis
-
-**Affected Component:** `frontend/src/pages/admin/BrandingPage.tsx` or similar
-
-**Proposed Solution:**
-```tsx
-// Logo preview section structure
-
- {currentLogo ? (
-
-

-
-
-
-
-
- ) : (
-
- )}
-
Recommended size: 200x60px, PNG or JPEG
-
-```
-
-### Screenshots
-- See: `.playwright-mcp/branding-logo-section.png`
-
----
-
-## BUG-002: Favicon Upload Section Missing Preview
-
-### Priority: P2 (Medium)
-
-### Location
-- **Page:** `/admin/branding`
-- **Section:** Company Information → Favicon
-
-### Current Behavior
-1. Only shows "Upload Favicon" button
-2. No preview of currently uploaded favicon
-3. No way to see or remove existing favicon
-
-### Expected Behavior
-1. Display current favicon preview (32x32px thumbnail)
-2. Show "Change Favicon" when one exists
-3. Provide "Remove Favicon" option
-4. Display file info (name, size) when uploaded
-
-### Technical Analysis
-
-**Proposed Solution:**
-```tsx
-
-
-
- {currentFavicon ? (
- <>
-

-
-
- >
- ) : (
-
- )}
-
-
PNG or ICO format, recommended size: 32x32px
-
-```
-
----
-
-## FEATURE-003: Custom CSS Instructions Panel
-
-### Priority: P2 (Medium)
-
-### Location
-- **Page:** `/admin/settings` → Custom CSS tab
-
-### Current Behavior
-- Simple textarea with minimal guidance
-- Only shows: "Advanced: Add custom CSS to further customize the appearance"
-- CSS variables are documented in comments within the template
-
-### Required Enhancement
-Add a collapsible instruction panel with comprehensive documentation:
-
-### Proposed Implementation
-
-```tsx
-
-
-
- CSS Documentation & Guide
-
-
-
- {/* Documentation content */}
-
-
-```
-
-### Documentation Content Structure
-
-#### 1. Available CSS Custom Properties
-```css
-/* Color Variables */
---gallery-bg: #ffffff; /* Main background color */
---gallery-bg-secondary: #f5f5f5; /* Secondary/card background */
---gallery-text: #171717; /* Primary text color */
---gallery-text-muted: #737373; /* Muted/secondary text */
---gallery-accent: #22c55e; /* Accent/highlight color */
---gallery-accent-hover: #16a34a; /* Accent hover state */
---gallery-border: #e5e5e5; /* Border color */
-
-/* Spacing & Layout */
---gallery-spacing: 16px; /* Base spacing unit */
---gallery-radius: 8px; /* Border radius */
---gallery-shadow: 0 1px 3px rgba(0,0,0,0.1); /* Box shadow */
-
-/* Typography */
---gallery-font-body: 'Inter', sans-serif;
---gallery-font-heading: 'Inter', sans-serif;
---gallery-font-size-base: 16px;
-```
-
-#### 2. Targetable CSS Classes
-```css
-/* Page Structure */
-.gallery-page { } /* Root gallery container */
-.gallery-header { } /* Header section */
-.gallery-content { } /* Main content area */
-.gallery-footer { } /* Footer section */
-
-/* Photo Grid */
-.photo-grid { } /* Grid container */
-.photo-card { } /* Individual photo card */
-.photo-card img { } /* Photo image */
-.photo-card-overlay { } /* Hover overlay */
-.photo-card-info { } /* Photo metadata */
-
-/* Lightbox */
-.lightbox-overlay { } /* Lightbox background */
-.lightbox-content { } /* Lightbox container */
-.lightbox-image { } /* Lightbox image */
-.lightbox-controls { } /* Navigation controls */
-
-/* Buttons & Interactions */
-.gallery-btn { } /* Primary buttons */
-.gallery-btn-secondary { } /* Secondary buttons */
-.gallery-link { } /* Links */
-
-/* Categories */
-.category-filter { } /* Category filter bar */
-.category-pill { } /* Category pill/tag */
-
-/* Masonry Layout */
-.masonry-grid { } /* Masonry container */
-.masonry-item { } /* Masonry item */
-
-/* Carousel Layout */
-.carousel-container { } /* Carousel wrapper */
-.carousel-slide { } /* Individual slide */
-.carousel-nav { } /* Navigation arrows */
-.carousel-dots { } /* Pagination dots */
-
-/* Timeline Layout */
-.timeline-container { } /* Timeline wrapper */
-.timeline-item { } /* Timeline entry */
-.timeline-date { } /* Date marker */
-
-/* Hero Layout */
-.hero-section { } /* Hero image area */
-.hero-image { } /* Featured image */
-.hero-content { } /* Hero text content */
-```
-
-#### 3. Layout-Specific Customization
-```css
-/* Grid Layout Customization */
-.gallery-page[data-layout="grid"] .photo-grid {
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
- gap: var(--gallery-spacing);
-}
-
-/* Masonry Layout Customization */
-.gallery-page[data-layout="masonry"] .masonry-grid {
- column-count: 4;
- column-gap: var(--gallery-spacing);
-}
-
-/* Carousel Layout Customization */
-.gallery-page[data-layout="carousel"] .carousel-container {
- height: 80vh;
-}
-
-/* Timeline Layout Customization */
-.gallery-page[data-layout="timeline"] .timeline-container {
- max-width: 1200px;
- margin: 0 auto;
-}
-```
-
-#### 4. Responsive Breakpoints
-```css
-/* Mobile: < 640px */
-@media (max-width: 639px) { }
-
-/* Tablet: 640px - 1023px */
-@media (min-width: 640px) and (max-width: 1023px) { }
-
-/* Desktop: >= 1024px */
-@media (min-width: 1024px) { }
-```
-
-#### 5. Animation Classes
-```css
-/* Available animations */
-.animate-fade { } /* Fade in */
-.animate-scale { } /* Scale up */
-.animate-slide { } /* Slide in */
-.animate-none { } /* No animation */
-```
-
----
-
-## FEATURE-004: Custom CSS Integration with Theme Presets & Gallery Layouts
-
-### Priority: P0 (Critical)
-
-### Location
-- **Page:** `/admin/settings` → Custom CSS tab
-- **Page:** `/admin/branding` → Gallery Theme section
-- **Page:** `/admin/events/new` → Theme & Style section
-
-### Current Behavior
-- Custom CSS templates exist but are isolated
-- Theme presets don't integrate with custom CSS
-- Users cannot define custom theme presets
-- Users cannot define custom gallery layouts
-- No way to use CSS variables from theme presets
-
-### Required Features
-
-#### 4.1 Custom Theme Preset Creation
-
-Users should be able to create custom theme presets that appear alongside built-in presets:
-
-```typescript
-interface CustomThemePreset {
- id: string;
- name: string;
- description: string;
- thumbnail?: string;
- // Inherits from base preset or standalone
- basePreset?: 'classic-grid' | 'elegant-wedding' | 'modern-masonry' | null;
- // CSS template reference
- cssTemplateId: 1 | 2 | 3;
- // Override variables
- variables: {
- primaryColor: string;
- accentColor: string;
- backgroundColor: string;
- textColor: string;
- fontBody: string;
- fontHeading: string;
- borderRadius: string;
- spacing: string;
- };
- // Layout settings
- layout: 'grid' | 'masonry' | 'carousel' | 'timeline' | 'hero' | 'mosaic' | 'custom';
- layoutSettings: {
- columns: { mobile: number; tablet: number; desktop: number };
- spacing: 'tight' | 'normal' | 'relaxed';
- animation: 'none' | 'fade' | 'scale' | 'slide';
- };
-}
-```
-
-#### 4.2 Custom Gallery Layout Definition
-
-Allow users to define custom layouts via CSS:
-
-```css
-/* Custom Layout 1: Magazine Style */
-.gallery-page[data-layout="custom-1"] .photo-grid {
- display: grid;
- grid-template-columns: 2fr 1fr 1fr;
- grid-template-rows: auto;
- gap: 8px;
-}
-
-.gallery-page[data-layout="custom-1"] .photo-card:first-child {
- grid-row: span 2;
-}
-
-/* Custom Layout 2: Polaroid Style */
-.gallery-page[data-layout="custom-2"] .photo-card {
- background: white;
- padding: 12px 12px 40px 12px;
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
- transform: rotate(var(--rotation, 0deg));
-}
-
-/* Custom Layout 3: Filmstrip */
-.gallery-page[data-layout="custom-3"] .photo-grid {
- display: flex;
- overflow-x: auto;
- gap: 4px;
- padding: 20px;
- background: #1a1a1a;
-}
-```
-
-#### 4.3 Variable Inheritance System
-
-Custom CSS should be able to reference theme preset variables:
-
-```css
-/* Access theme preset variables */
-.gallery-page {
- /* These come from the selected theme preset */
- background: var(--theme-bg, var(--gallery-bg));
- color: var(--theme-text, var(--gallery-text));
-
- /* Override specific elements */
- --gallery-accent: var(--theme-accent);
-}
-
-/* Conditional styling based on preset */
-.gallery-page[data-preset="elegant-wedding"] {
- /* Wedding-specific overrides */
-}
-
-.gallery-page[data-preset="custom"] {
- /* Full custom styling */
-}
-```
-
-### Database Schema Addition
-
-```sql
--- Custom theme presets table
-CREATE TABLE custom_theme_presets (
- id SERIAL PRIMARY KEY,
- name VARCHAR(100) NOT NULL,
- description TEXT,
- thumbnail_url VARCHAR(500),
- base_preset VARCHAR(50),
- css_template_id INTEGER REFERENCES css_templates(id),
- variables JSONB NOT NULL DEFAULT '{}',
- layout VARCHAR(50) NOT NULL DEFAULT 'grid',
- layout_settings JSONB NOT NULL DEFAULT '{}',
- is_enabled BOOLEAN DEFAULT true,
- sort_order INTEGER DEFAULT 0,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-);
-
--- Link events to custom presets
-ALTER TABLE events ADD COLUMN custom_preset_id INTEGER REFERENCES custom_theme_presets(id);
-```
-
-### UI Components Required
-
-1. **Theme Preset Builder** - Visual editor for creating custom presets
-2. **Layout Designer** - CSS grid/flexbox visual editor for custom layouts
-3. **Variable Picker** - Color/font/spacing picker that outputs CSS variables
-4. **Preview Synchronization** - Real-time preview of custom themes
-
----
-
-## BUG-005: Custom Layouts Not Showing in Event Creation
-
-### Priority: P1 (High)
-
-### Location
-- **Page:** `/admin/events/new` → Theme & Style → Gallery Layout
-
-### Current Behavior
-- Only shows 6 default layouts: grid, masonry, carousel, timeline, hero, mosaic
-- Custom CSS templates with enabled custom layouts don't appear
-- No "Custom 1", "Custom 2", "Custom 3" options visible
-
-### Expected Behavior
-When Custom CSS templates are enabled in Settings:
-1. Additional layout options should appear: "Custom 1", "Custom 2", "Custom 3"
-2. Only show custom layouts that have content (non-empty CSS)
-3. Display the template name as the layout name
-4. Show a preview thumbnail if available
-
-### Technical Analysis
-
-**Current Gallery Layout Options:**
-```typescript
-const GALLERY_LAYOUTS = [
- { value: 'grid', label: 'Grid', description: 'Classic grid layout...' },
- { value: 'masonry', label: 'Masonry', description: 'Pinterest-style...' },
- { value: 'carousel', label: 'Carousel', description: 'Full-screen slideshow...' },
- { value: 'timeline', label: 'Timeline', description: 'Photos organized by date' },
- { value: 'hero', label: 'Hero', description: 'Featured image with grid...' },
- { value: 'mosaic', label: 'Mosaic', description: 'Artistic layout...' },
-];
-```
-
-**Required Addition:**
-```typescript
-// Fetch enabled custom templates
-const { data: customTemplates } = useQuery({
- queryKey: ['customCssTemplates'],
- queryFn: () => settingsService.getCustomCssTemplates(),
-});
-
-// Filter to only enabled templates with content
-const enabledCustomLayouts = customTemplates
- ?.filter(t => t.enabled && t.content?.trim())
- .map((t, index) => ({
- value: `custom-${index + 1}`,
- label: t.name || `Custom ${index + 1}`,
- description: 'Custom CSS layout template',
- isCustom: true,
- }));
-
-const allLayouts = [...GALLERY_LAYOUTS, ...(enabledCustomLayouts || [])];
-```
-
-### API Endpoint Required
-
-```typescript
-// GET /api/admin/settings/custom-css-templates
-interface CustomCssTemplate {
- id: number;
- name: string;
- enabled: boolean;
- content: string;
- hasLayoutDefinition: boolean; // true if contains custom layout CSS
-}
-```
-
----
-
-## FEATURE-006: Apple Liquid Glass Design Custom CSS Templates
-
-### Priority: P2 (Medium)
-
-### Overview
-Create 2 premium custom CSS templates implementing Apple's "Liquid Glass" design language introduced at WWDC 2025. This design features translucent surfaces, dynamic light refraction effects, and sophisticated blur treatments.
-
-### References
-- [Apple's Liquid Glass UI design + CSS guide](https://dev.to/gruszdev/apples-liquid-glass-revolution-how-glassmorphism-is-shaping-ui-design-in-2025-with-css-code-1221)
-- [Recreating Apple's Liquid Glass Effect with Pure CSS](https://dev.to/kevinbism/recreating-apples-liquid-glass-effect-with-pure-css-3gpl)
-- [CSS-Tricks: Getting Clarity on Apple's Liquid Glass](https://css-tricks.com/getting-clarity-on-apples-liquid-glass/)
-- [Liquid Glass CSS Generator](https://liquidglassgen.com/)
-
-### Template 1: "Liquid Glass Light"
-
-A light-themed glassmorphism design with subtle transparency and soft shadows.
-
-```css
-/*
- * PicPeak Custom CSS Template: Liquid Glass Light
- * Inspired by Apple's iOS 26 Liquid Glass Design Language
- *
- * Features:
- * - Translucent frosted glass surfaces
- * - Dynamic light refraction effects
- * - Subtle specular highlights
- * - Soft depth shadows
- */
-
-/* ===== Base Theme Variables ===== */
-.gallery-page {
- --glass-bg: rgba(255, 255, 255, 0.7);
- --glass-bg-elevated: rgba(255, 255, 255, 0.85);
- --glass-border: rgba(255, 255, 255, 0.5);
- --glass-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
- --glass-blur: 20px;
- --glass-saturation: 180%;
-
- --gallery-bg: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
- --gallery-text: #1a1a2e;
- --gallery-text-muted: rgba(26, 26, 46, 0.7);
- --gallery-accent: #667eea;
- --gallery-accent-hover: #764ba2;
- --gallery-radius: 24px;
- --gallery-spacing: 20px;
-}
-
-/* ===== Page Background ===== */
-.gallery-page {
- background: var(--gallery-bg);
- min-height: 100vh;
- position: relative;
-}
-
-/* Animated gradient background */
-.gallery-page::before {
- content: '';
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background:
- radial-gradient(circle at 20% 80%, rgba(255, 255, 255, 0.3) 0%, transparent 50%),
- radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.2) 0%, transparent 40%);
- pointer-events: none;
- z-index: 0;
-}
-
-/* ===== Glass Card Base ===== */
-.glass-surface {
- background: var(--glass-bg);
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- box-shadow:
- var(--glass-shadow),
- inset 0 1px 1px rgba(255, 255, 255, 0.8),
- inset 0 -1px 1px rgba(0, 0, 0, 0.05);
-}
-
-/* Liquid shine effect */
-.glass-surface::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 50%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.4) 0%,
- rgba(255, 255, 255, 0.1) 50%,
- transparent 100%
- );
- border-radius: var(--gallery-radius) var(--gallery-radius) 0 0;
- pointer-events: none;
-}
-
-/* ===== Gallery Header ===== */
-.gallery-header {
- background: var(--glass-bg-elevated);
- backdrop-filter: blur(30px) saturate(200%);
- -webkit-backdrop-filter: blur(30px) saturate(200%);
- border-bottom: 1px solid var(--glass-border);
- padding: calc(var(--gallery-spacing) * 1.5);
- position: sticky;
- top: 0;
- z-index: 100;
-}
-
-.gallery-title {
- color: var(--gallery-text);
- font-weight: 700;
- font-size: 1.75rem;
- letter-spacing: -0.02em;
- text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5);
-}
-
-/* ===== Photo Grid ===== */
-.photo-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- gap: var(--gallery-spacing);
- padding: calc(var(--gallery-spacing) * 2);
- position: relative;
- z-index: 1;
-}
-
-/* ===== Photo Cards - Glass Style ===== */
-.photo-card {
- position: relative;
- background: var(--glass-bg);
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- overflow: hidden;
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
- box-shadow:
- 0 4px 16px rgba(0, 0, 0, 0.1),
- inset 0 1px 1px rgba(255, 255, 255, 0.6);
-}
-
-.photo-card::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 40%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.3) 0%,
- transparent 100%
- );
- pointer-events: none;
- z-index: 1;
- border-radius: var(--gallery-radius) var(--gallery-radius) 0 0;
-}
-
-.photo-card:hover {
- transform: translateY(-8px) scale(1.02);
- box-shadow:
- 0 20px 40px rgba(102, 126, 234, 0.3),
- 0 8px 16px rgba(0, 0, 0, 0.1),
- inset 0 1px 1px rgba(255, 255, 255, 0.8);
-}
-
-.photo-card img {
- width: 100%;
- height: 240px;
- object-fit: cover;
- transition: transform 0.4s ease;
-}
-
-.photo-card:hover img {
- transform: scale(1.05);
-}
-
-.photo-card-info {
- padding: var(--gallery-spacing);
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.1) 0%,
- rgba(255, 255, 255, 0.3) 100%
- );
-}
-
-/* ===== Buttons - Glass Style ===== */
-.gallery-btn {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: calc(var(--gallery-radius) / 2);
- padding: 12px 24px;
- color: var(--gallery-text);
- font-weight: 600;
- cursor: pointer;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
-}
-
-.gallery-btn::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 50%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.4) 0%,
- transparent 100%
- );
-}
-
-.gallery-btn:hover {
- background: var(--glass-bg-elevated);
- transform: translateY(-2px);
- box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
-}
-
-.gallery-btn-primary {
- background: linear-gradient(135deg, var(--gallery-accent) 0%, var(--gallery-accent-hover) 100%);
- color: white;
- border: none;
-}
-
-/* ===== Lightbox - Glass Style ===== */
-.lightbox-overlay {
- background: rgba(26, 26, 46, 0.8);
- backdrop-filter: blur(40px);
- -webkit-backdrop-filter: blur(40px);
-}
-
-.lightbox-content {
- background: var(--glass-bg);
- backdrop-filter: blur(20px);
- -webkit-backdrop-filter: blur(20px);
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- box-shadow: 0 24px 48px rgba(0, 0, 0, 0.2);
-}
-
-/* ===== Category Pills ===== */
-.category-pill {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: 9999px;
- padding: 8px 20px;
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--gallery-text);
- transition: all 0.3s ease;
-}
-
-.category-pill:hover,
-.category-pill.active {
- background: var(--gallery-accent);
- color: white;
- border-color: var(--gallery-accent);
-}
-
-/* ===== Responsive ===== */
-@media (max-width: 768px) {
- .gallery-page {
- --gallery-radius: 16px;
- --gallery-spacing: 12px;
- --glass-blur: 16px;
- }
-
- .photo-grid {
- grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
- }
-
- .photo-card img {
- height: 180px;
- }
-}
-
-/* ===== Accessibility: Reduce Motion ===== */
-@media (prefers-reduced-motion: reduce) {
- .photo-card,
- .gallery-btn {
- transition: none;
- }
-
- .photo-card:hover {
- transform: none;
- }
-}
-
-/* ===== Accessibility: Reduce Transparency ===== */
-@media (prefers-reduced-transparency: reduce) {
- .glass-surface,
- .photo-card,
- .gallery-btn {
- backdrop-filter: none;
- -webkit-backdrop-filter: none;
- background: rgba(255, 255, 255, 0.95);
- }
-}
-```
-
-### Template 2: "Liquid Glass Dark"
-
-A dark-themed glassmorphism design with deep translucency and neon accents.
-
-```css
-/*
- * PicPeak Custom CSS Template: Liquid Glass Dark
- * Inspired by Apple's iOS 26 Liquid Glass Design Language
- *
- * Features:
- * - Deep translucent dark surfaces
- * - Neon accent highlights
- * - Dramatic glass reflections
- * - Subtle animated gradients
- */
-
-/* ===== Base Theme Variables ===== */
-.gallery-page {
- --glass-bg: rgba(15, 15, 35, 0.7);
- --glass-bg-elevated: rgba(25, 25, 55, 0.85);
- --glass-border: rgba(255, 255, 255, 0.1);
- --glass-border-highlight: rgba(255, 255, 255, 0.2);
- --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
- --glass-blur: 24px;
- --glass-saturation: 150%;
-
- --gallery-bg: #0a0a1a;
- --gallery-text: #f0f0f5;
- --gallery-text-muted: rgba(240, 240, 245, 0.6);
- --gallery-accent: #00d4ff;
- --gallery-accent-secondary: #ff00e5;
- --gallery-accent-hover: #00ffea;
- --gallery-radius: 20px;
- --gallery-spacing: 20px;
-
- /* Neon glow variables */
- --neon-glow: 0 0 20px rgba(0, 212, 255, 0.5), 0 0 40px rgba(0, 212, 255, 0.2);
- --neon-glow-secondary: 0 0 20px rgba(255, 0, 229, 0.5), 0 0 40px rgba(255, 0, 229, 0.2);
-}
-
-/* ===== Page Background ===== */
-.gallery-page {
- background: var(--gallery-bg);
- min-height: 100vh;
- position: relative;
- overflow-x: hidden;
-}
-
-/* Animated mesh gradient background */
-.gallery-page::before {
- content: '';
- position: fixed;
- top: -50%;
- left: -50%;
- right: -50%;
- bottom: -50%;
- background:
- radial-gradient(circle at 30% 20%, rgba(0, 212, 255, 0.15) 0%, transparent 40%),
- radial-gradient(circle at 70% 80%, rgba(255, 0, 229, 0.1) 0%, transparent 40%),
- radial-gradient(circle at 50% 50%, rgba(100, 100, 255, 0.05) 0%, transparent 60%);
- animation: gradientShift 20s ease-in-out infinite;
- pointer-events: none;
- z-index: 0;
-}
-
-@keyframes gradientShift {
- 0%, 100% { transform: translate(0, 0) rotate(0deg); }
- 25% { transform: translate(2%, 2%) rotate(1deg); }
- 50% { transform: translate(-1%, 3%) rotate(-1deg); }
- 75% { transform: translate(3%, -2%) rotate(2deg); }
-}
-
-/* ===== Gallery Header ===== */
-.gallery-header {
- background: var(--glass-bg-elevated);
- backdrop-filter: blur(30px) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(30px) saturate(var(--glass-saturation));
- border-bottom: 1px solid var(--glass-border-highlight);
- padding: calc(var(--gallery-spacing) * 1.5);
- position: sticky;
- top: 0;
- z-index: 100;
- box-shadow:
- 0 4px 24px rgba(0, 0, 0, 0.3),
- inset 0 1px 0 rgba(255, 255, 255, 0.1);
-}
-
-.gallery-title {
- color: var(--gallery-text);
- font-weight: 700;
- font-size: 1.75rem;
- letter-spacing: -0.02em;
- background: linear-gradient(135deg, var(--gallery-text) 0%, var(--gallery-accent) 100%);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- background-clip: text;
-}
-
-/* ===== Photo Grid ===== */
-.photo-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- gap: var(--gallery-spacing);
- padding: calc(var(--gallery-spacing) * 2);
- position: relative;
- z-index: 1;
-}
-
-/* ===== Photo Cards - Dark Glass Style ===== */
-.photo-card {
- position: relative;
- background: var(--glass-bg);
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- overflow: hidden;
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
- box-shadow:
- 0 4px 24px rgba(0, 0, 0, 0.3),
- inset 0 1px 0 rgba(255, 255, 255, 0.05);
-}
-
-/* Top highlight reflection */
-.photo-card::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 1px;
- background: linear-gradient(
- 90deg,
- transparent 0%,
- rgba(255, 255, 255, 0.3) 50%,
- transparent 100%
- );
- z-index: 2;
-}
-
-/* Inner glow effect */
-.photo-card::after {
- content: '';
- position: absolute;
- inset: 0;
- border-radius: var(--gallery-radius);
- padding: 1px;
- background: linear-gradient(
- 135deg,
- rgba(0, 212, 255, 0) 0%,
- rgba(0, 212, 255, 0) 40%,
- rgba(0, 212, 255, 0.1) 100%
- );
- -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
- -webkit-mask-composite: xor;
- mask-composite: exclude;
- pointer-events: none;
- opacity: 0;
- transition: opacity 0.4s ease;
-}
-
-.photo-card:hover {
- transform: translateY(-8px) scale(1.02);
- border-color: var(--glass-border-highlight);
- box-shadow:
- 0 24px 48px rgba(0, 0, 0, 0.4),
- 0 0 0 1px rgba(0, 212, 255, 0.2),
- var(--neon-glow);
-}
-
-.photo-card:hover::after {
- opacity: 1;
-}
-
-.photo-card img {
- width: 100%;
- height: 240px;
- object-fit: cover;
- transition: transform 0.4s ease, filter 0.4s ease;
- filter: brightness(0.9);
-}
-
-.photo-card:hover img {
- transform: scale(1.05);
- filter: brightness(1);
-}
-
-.photo-card-info {
- padding: var(--gallery-spacing);
- background: linear-gradient(
- 180deg,
- rgba(0, 0, 0, 0.2) 0%,
- rgba(0, 0, 0, 0.4) 100%
- );
- color: var(--gallery-text);
-}
-
-.photo-card-info p {
- color: var(--gallery-text-muted);
- font-size: 0.875rem;
-}
-
-/* ===== Buttons - Neon Glass Style ===== */
-.gallery-btn {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: calc(var(--gallery-radius) / 2);
- padding: 12px 24px;
- color: var(--gallery-text);
- font-weight: 600;
- cursor: pointer;
- transition: all 0.3s ease;
- position: relative;
-}
-
-.gallery-btn:hover {
- border-color: var(--gallery-accent);
- box-shadow: var(--neon-glow);
- color: var(--gallery-accent);
-}
-
-.gallery-btn-primary {
- background: linear-gradient(135deg, var(--gallery-accent) 0%, var(--gallery-accent-secondary) 100%);
- color: white;
- border: none;
- box-shadow: var(--neon-glow);
-}
-
-.gallery-btn-primary:hover {
- box-shadow:
- 0 0 30px rgba(0, 212, 255, 0.6),
- 0 0 60px rgba(0, 212, 255, 0.3),
- 0 0 90px rgba(255, 0, 229, 0.2);
- transform: translateY(-2px);
-}
-
-/* ===== Lightbox - Dark Glass ===== */
-.lightbox-overlay {
- background: rgba(5, 5, 15, 0.9);
- backdrop-filter: blur(40px);
- -webkit-backdrop-filter: blur(40px);
-}
-
-.lightbox-content {
- background: var(--glass-bg-elevated);
- backdrop-filter: blur(24px);
- -webkit-backdrop-filter: blur(24px);
- border: 1px solid var(--glass-border-highlight);
- border-radius: var(--gallery-radius);
- box-shadow:
- 0 24px 80px rgba(0, 0, 0, 0.5),
- var(--neon-glow);
-}
-
-/* ===== Category Pills ===== */
-.category-pill {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: 9999px;
- padding: 8px 20px;
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--gallery-text-muted);
- transition: all 0.3s ease;
-}
-
-.category-pill:hover {
- border-color: var(--gallery-accent);
- color: var(--gallery-accent);
- box-shadow: var(--neon-glow);
-}
-
-.category-pill.active {
- background: linear-gradient(135deg, var(--gallery-accent) 0%, var(--gallery-accent-secondary) 100%);
- color: white;
- border-color: transparent;
- box-shadow: var(--neon-glow);
-}
-
-/* ===== Scrollbar Styling ===== */
-.gallery-page ::-webkit-scrollbar {
- width: 8px;
- height: 8px;
-}
-
-.gallery-page ::-webkit-scrollbar-track {
- background: var(--glass-bg);
- border-radius: 4px;
-}
-
-.gallery-page ::-webkit-scrollbar-thumb {
- background: linear-gradient(180deg, var(--gallery-accent) 0%, var(--gallery-accent-secondary) 100%);
- border-radius: 4px;
-}
-
-/* ===== Responsive ===== */
-@media (max-width: 768px) {
- .gallery-page {
- --gallery-radius: 16px;
- --gallery-spacing: 12px;
- --glass-blur: 16px;
- }
-
- .photo-grid {
- grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
- }
-
- .photo-card img {
- height: 180px;
- }
-
- /* Reduce animation complexity on mobile */
- .gallery-page::before {
- animation: none;
- }
-}
-
-/* ===== Accessibility: Reduce Motion ===== */
-@media (prefers-reduced-motion: reduce) {
- .gallery-page::before {
- animation: none;
- }
-
- .photo-card,
- .gallery-btn {
- transition: none;
- }
-
- .photo-card:hover {
- transform: none;
- }
-}
-
-/* ===== Accessibility: Reduce Transparency ===== */
-@media (prefers-reduced-transparency: reduce) {
- .photo-card,
- .gallery-btn,
- .gallery-header {
- backdrop-filter: none;
- -webkit-backdrop-filter: none;
- }
-
- .gallery-page {
- --glass-bg: rgba(20, 20, 40, 0.98);
- --glass-bg-elevated: rgba(30, 30, 60, 0.98);
- }
-}
-```
-
----
-
-## BUG-007: Typography & Style Section Row Formatting
-
-### Priority: P2 (Medium)
-
-### Location
-- **Page:** `/admin/events/new` → Theme & Style → Typography & Style section
-- **Page:** `/admin/branding` → Gallery Theme → Typography & Style section
-
-### Current Behavior
-The second row of Typography & Style section contains 4 dropdown fields crammed into one row:
-- Font Size
-- Border Radius
-- Shadow Style
-- Background
-
-These fields are truncated and show abbreviated text (e.g., "Nor", "Lar", "Sub") because they don't have enough horizontal space.
-
-### Expected Behavior
-Split the 4 fields into 2 rows of 2 fields each:
-- **Row 1:** Font Size, Border Radius
-- **Row 2:** Shadow Style, Background
-
-### Screenshots
-- See: `.playwright-mcp/typography-style-visible.png`
-
-### Technical Analysis
-
-**Current Code Structure (likely):**
-```tsx
-
-
-
-
-
-
-```
-
-**Proposed Fix:**
-```tsx
-{/* Row 1: Font Size & Border Radius */}
-
-
-
-
-
-
-
-
-
-{/* Row 2: Shadow Style & Background */}
-
-
-
-
-
-
-
-
-```
-
-### Files to Modify
-1. `frontend/src/pages/admin/EventCreatePage.tsx` (or similar)
-2. `frontend/src/pages/admin/BrandingPage.tsx`
-3. `frontend/src/components/admin/ThemeCustomizer.tsx` (if shared component)
-
----
-
-## Implementation Priority Order
-
-| Priority | Issue | Effort | Impact |
-|----------|-------|--------|--------|
-| P0 | FEATURE-004: Custom CSS + Theme Integration | High | Critical for customization |
-| P1 | BUG-001: Logo Upload Formatting | Medium | User experience |
-| P1 | BUG-005: Custom Layouts in Events | Medium | Feature completeness |
-| P2 | BUG-002: Favicon Preview | Low | User experience |
-| P2 | BUG-007: Typography Row Layout | Low | UI polish |
-| P2 | FEATURE-003: CSS Instructions | Medium | User guidance |
-| P2 | FEATURE-006: Liquid Glass Templates | Medium | Premium feature |
-
----
-
-## Testing Checklist
-
-### BUG-001 & BUG-002
-- [ ] Logo upload displays preview after upload
-- [ ] Logo can be changed/removed
-- [ ] Favicon upload displays preview
-- [ ] Favicon can be changed/removed
-- [ ] Button styling matches design system
-
-### FEATURE-003
-- [ ] Collapsible instructions panel works
-- [ ] All CSS variables documented
-- [ ] All CSS classes documented
-- [ ] Code examples copy correctly
-
-### FEATURE-004
-- [ ] Custom theme presets can be created
-- [ ] Custom presets appear in event creation
-- [ ] CSS variables from presets work in custom CSS
-- [ ] Custom layouts render correctly
-
-### BUG-005
-- [ ] Enabled custom templates show in layout selector
-- [ ] Only templates with content appear
-- [ ] Custom layouts apply correctly to galleries
-
-### FEATURE-006
-- [ ] Liquid Glass Light template renders correctly
-- [ ] Liquid Glass Dark template renders correctly
-- [ ] Animations respect prefers-reduced-motion
-- [ ] Transparency respects prefers-reduced-transparency
-- [ ] Mobile responsiveness works
-
-### BUG-007
-- [ ] Typography section shows 2 items per row
-- [ ] Dropdown labels fully visible
-- [ ] Responsive behavior maintained
-
----
-
-*Document generated for PicPeak development team*
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..8fe849c1
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,63 @@
+# Changelog
+
+All notable changes to PicPeak will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [1.2.0](https://github.com/the-luap/picpeak/compare/v1.1.15...v1.2.0) (2026-01-03)
+
+### Features
+
+* **Event Rename**: Safe event renaming with automatic slug updates, old URL redirects via `slug_redirects` table, and optional email notifications to clients
+* **Optional Event Fields**: Make customer name, email, and admin email fields optional via admin settings with "(optional)" labels in forms
+* **Photo Filtering**: Filter photos by rating, likes, favorites, and comments with a new PhotoFilterPanel component
+* **Photo Export**: Export filtered photo selections as ZIP, generate Capture One/Lightroom-compatible XMP sidecar files, or export metadata lists
+* **Custom CSS Templates**: 3 customizable CSS template slots with live preview, XSS-safe sanitization, and per-event template assignment
+* **Apple Liquid Glass Theme**: Starter CSS template inspired by iOS 26 / macOS Tahoe Liquid Glass design with glass morphism effects, Apple SF Pro fonts, and responsive layout
+* **Liquid Glass Dark Theme**: Neon-accented dark glass theme with animated gradient backgrounds
+* **Image Security Settings**: Per-event download protection with configurable protection levels (basic, standard, enhanced, maximum), canvas rendering, DevTools detection, and right-click prevention
+* **Automated Releases**: Release Please integration for automatic versioning, changelog generation, and GitHub releases that trigger Docker image builds
+
+### Bug Fixes
+
+* **Date Parsing**: Fix event date formatting in slugs (now uses YYYY-MM-DD format correctly)
+* **Search Placeholder**: Fix search field placeholder visibility in glass-styled sidebar
+* **Vite Proxy**: Fix Vite dev server proxy port configuration
+* **Photo Export Button**: Fix export button staying disabled when photos are selected
+* **Boolean Parsing**: Fix boolean parsing in publicSettings.js for optional fields
+* **Translation Keys**: Add missing `common.optional` translation key in locales
+
+### Security
+
+* Fix critical vulnerabilities and harden application security
+* Add CSS sanitizer utility blocking XSS vectors in custom templates
+* Implement secure gallery CSS endpoint for template delivery
+
+### Code Refactoring
+
+* Add Photo and Settings service layers for better code organization
+* Phase 1 code consolidation with service layer architecture
+* Modular settings page with feature-based tab components
+* Create photoFilterBuilder utility for query construction
+* Add eventRenameService for safe event operations
+
+### Documentation
+
+* Add comprehensive REFACTORING_PLAN.md for codebase improvement roadmap
+* Update README roadmap with implemented features (Download Protection, Gallery Templates, Filtering & Export)
+* Add test specification documents for all new features
+
+### Database Migrations
+
+* `049_add_slug_redirects.js` - Store old slugs for URL redirects after rename
+* `050_add_optional_event_fields_settings.js` - Settings for optional form fields
+* `051_add_photo_filter_indexes.js` - Performance indexes for photo filtering
+* `052_add_css_templates.js` - CSS template storage with 3 slots
+* `053_add_liquid_glass_templates.js` - Apple Liquid Glass and Dark theme starter templates
+
+---
+
+## [1.1.15] - Previous Release
+
+Initial stable release with core functionality.
diff --git a/README.md b/README.md
index 15875af4..4e802ae9 100644
--- a/README.md
+++ b/README.md
@@ -235,7 +235,6 @@ These features are currently in beta testing and may have limited functionality
| Feature | Description | Status |
|---------|-------------|--------|
-| **Download Protection** | Advanced image protection system with canvas rendering, invisible watermarking, and right-click prevention to protect your photos from unauthorized downloads | 🧪 Beta |
| **Simple Deployment Script** | One-click deployment script for quick server setup with automated configuration and dependency installation | 🧪 Beta |
### 📋 Future Enhancements
@@ -244,12 +243,13 @@ These features are currently in beta testing and may have limited functionality
|---------|-------------|----------|---------|
| **Backup & Restore** | Comprehensive backup system with S3/MinIO support, automated scheduling, and safe restore functionality | High | ✅ Implemented |
| **External Media Library (Reference Mode)** | Use an external folder library as a read‑only source with import and on‑demand thumbnail generation | High | ✅ Implemented |
-| **Gallery Templates** | Additional gallery layouts and themes (masonry, slideshow, story-style) for different event types | Medium | 🔄 Open |
+| **Download Protection** | Advanced image protection system with canvas rendering, invisible watermarking, right-click prevention, and DevTools detection to protect photos from unauthorized downloads | High | ✅ Implemented |
+| **Gallery Templates** | Multiple gallery layouts (grid, masonry, carousel, timeline, hero, mosaic) with custom CSS styling support. Includes starter templates like Apple Liquid Glass for complete visual customization | Medium | ✅ Implemented |
| **Face Recognition** | AI-powered face detection to help guests find their photos and create automatic person-based albums | Low | 🔄 Open |
| **Gallery Feedback** | Allow guests to like, rate, and comment on photos with admin notifications and moderation | Medium | ✅ Implemented |
| **Video Support** | Upload and display videos alongside photos in galleries with streaming support | Low | ✅ Implemented |
| **Multiple Administrators** | Support for multiple admin accounts with role-based permissions and activity tracking | Low | 📋 Planned |
-| **Filtering & Export Options** | Add filters to show only rated, liked, or marked photos and export filtered selections for Capture One or Lightroom workflows | Low | 🔄 Open |
+| **Filtering & Export Options** | Filter photos by likes, ratings, comments, or favorites. Search by filename. Sort by date, name, size, or rating. Export filtered selections as ZIP or generate Capture One/Lightroom-compatible file lists for professional workflows | Medium | ✅ Implemented |
**Status Legend:** ✅ Implemented | 🚧 In Progress | 🔄 Open | 📋 Planned
diff --git a/backend/migrations/core/053_add_liquid_glass_templates.js b/backend/migrations/core/053_add_liquid_glass_templates.js
index 2900eb0f..af19bdd0 100644
--- a/backend/migrations/core/053_add_liquid_glass_templates.js
+++ b/backend/migrations/core/053_add_liquid_glass_templates.js
@@ -1,296 +1,334 @@
/**
* Migration: Add Liquid Glass CSS Templates
* Updates template slots 2 and 3 with Apple-inspired Liquid Glass designs
- */
-
-const LIQUID_GLASS_LIGHT = `/*
- * PicPeak Custom CSS Template: Liquid Glass Light
- * Inspired by Apple's iOS 26 Liquid Glass Design Language
*
- * Features:
- * - Translucent frosted glass surfaces
- * - Dynamic light refraction effects
- * - Subtle specular highlights
- * - Soft depth shadows
+ * These are starter example templates for new installations.
+ * Users can edit or replace them as needed.
*/
-/* ===== Base Theme Variables ===== */
-.gallery-page {
- --glass-bg: rgba(255, 255, 255, 0.7);
- --glass-bg-elevated: rgba(255, 255, 255, 0.85);
- --glass-border: rgba(255, 255, 255, 0.5);
- --glass-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
- --glass-blur: 20px;
- --glass-saturation: 180%;
+const APPLE_LIQUID_GLASS = `/*
+ * PicPeak Custom CSS Template: Apple Liquid Glass
+ * Authentic iOS 26 / macOS Tahoe Liquid Glass Design
+ */
- --gallery-bg: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
+/* ===== Apple System Fonts ===== */
+.gallery-page,
+.gallery-page *,
+.gallery-sidebar,
+.gallery-sidebar * {
+ font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
+ "Helvetica Neue", Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/* ===== CSS Variables ===== */
+:root {
+ --glass-blur: 20px;
+ --glass-blur-heavy: 40px;
+ --glass-saturation: 180%;
+ --glass-bg: rgba(255, 255, 255, 0.08);
+ --glass-bg-medium: rgba(255, 255, 255, 0.18);
+ --glass-bg-solid: rgba(255, 255, 255, 0.25);
+ --glass-border: rgba(255, 255, 255, 0.2);
+ --glass-border-light: rgba(255, 255, 255, 0.4);
+ --glass-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
+ --glass-inset: inset 0 1px 1px rgba(255, 255, 255, 0.4),
+ inset 0 -1px 1px rgba(0, 0, 0, 0.05);
+ --gallery-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
--gallery-text: #1a1a2e;
- --gallery-text-muted: rgba(26, 26, 46, 0.7);
+ --gallery-text-light: #ffffff;
--gallery-accent: #667eea;
- --gallery-accent-hover: #764ba2;
- --gallery-radius: 24px;
- --gallery-spacing: 20px;
+ --gallery-radius: 20px;
+ --gallery-radius-sm: 12px;
}
/* ===== Page Background ===== */
.gallery-page {
- background: var(--gallery-bg);
+ background: var(--gallery-gradient) !important;
+ background-attachment: fixed !important;
min-height: 100vh;
- position: relative;
}
-/* Animated gradient background */
.gallery-page::before {
content: '';
position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
+ inset: 0;
background:
- radial-gradient(circle at 20% 80%, rgba(255, 255, 255, 0.3) 0%, transparent 50%),
- radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.2) 0%, transparent 40%);
+ radial-gradient(ellipse 600px 400px at 15% 85%, rgba(255, 255, 255, 0.2) 0%, transparent 50%),
+ radial-gradient(ellipse 500px 350px at 85% 15%, rgba(255, 255, 255, 0.15) 0%, transparent 45%);
pointer-events: none;
z-index: 0;
}
-/* ===== Glass Card Base ===== */
-.glass-surface {
- background: var(--glass-bg);
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- box-shadow:
- var(--glass-shadow),
- inset 0 1px 1px rgba(255, 255, 255, 0.8),
- inset 0 -1px 1px rgba(0, 0, 0, 0.05);
+/* ===== TOP BAR / HEADER - Liquid Glass ===== */
+.gallery-page .gallery-header,
+.gallery-page header {
+ background: var(--glass-bg-medium) !important;
+ backdrop-filter: blur(var(--glass-blur-heavy)) saturate(var(--glass-saturation)) !important;
+ -webkit-backdrop-filter: blur(var(--glass-blur-heavy)) saturate(var(--glass-saturation)) !important;
+ border-bottom: 1px solid var(--glass-border) !important;
+ box-shadow: var(--glass-shadow), var(--glass-inset) !important;
}
-/* Liquid shine effect */
-.glass-surface::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 50%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.4) 0%,
- rgba(255, 255, 255, 0.1) 50%,
- transparent 100%
- );
- border-radius: var(--gallery-radius) var(--gallery-radius) 0 0;
- pointer-events: none;
+.gallery-page .gallery-header > div {
+ background: transparent !important;
+ border: none !important;
}
-/* ===== Gallery Header ===== */
-.gallery-header {
- background: var(--glass-bg-elevated);
- backdrop-filter: blur(30px) saturate(200%);
- -webkit-backdrop-filter: blur(30px) saturate(200%);
- border-bottom: 1px solid var(--glass-border);
- padding: calc(var(--gallery-spacing) * 1.5);
- position: sticky;
- top: 0;
- z-index: 100;
+/* ===== SIDEBAR - Liquid Glass ===== */
+.gallery-sidebar {
+ background: var(--glass-bg-medium) !important;
+ backdrop-filter: blur(var(--glass-blur-heavy)) saturate(var(--glass-saturation)) !important;
+ -webkit-backdrop-filter: blur(var(--glass-blur-heavy)) saturate(var(--glass-saturation)) !important;
+ border-right: 1px solid var(--glass-border) !important;
+ box-shadow: 4px 0 32px rgba(31, 38, 135, 0.1), var(--glass-inset) !important;
}
-.gallery-title {
- color: var(--gallery-text);
- font-weight: 700;
- font-size: 1.75rem;
- letter-spacing: -0.02em;
- text-shadow: 0 1px 2px rgba(255, 255, 255, 0.5);
+.gallery-sidebar h2,
+.gallery-sidebar h3 {
+ color: var(--gallery-text) !important;
+ font-weight: 600 !important;
}
-/* ===== Photo Grid ===== */
-.photo-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- gap: var(--gallery-spacing);
- padding: calc(var(--gallery-spacing) * 2);
- position: relative;
- z-index: 1;
+/* ===== HERO LAYOUT - Transform to Glass Title Box ===== */
+/* Target the hero wrapper */
+.gallery-page .relative.-mt-6 {
+ margin-top: 0 !important;
}
-/* ===== Photo Cards - Glass Style ===== */
-.photo-card {
- position: relative;
- background: var(--glass-bg);
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation));
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- overflow: hidden;
- transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
- box-shadow:
- 0 4px 16px rgba(0, 0, 0, 0.1),
- inset 0 1px 1px rgba(255, 255, 255, 0.6);
+/* Target the hero section (first child with h-[60vh]) */
+.gallery-page .relative.-mt-6 > .relative:first-child {
+ height: auto !important;
+ min-height: auto !important;
+ margin: 0 !important;
+ padding: 2rem !important;
+ display: flex !important;
+ justify-content: center !important;
+ align-items: center !important;
+ background: transparent !important;
}
-.photo-card::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 40%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.3) 0%,
- transparent 100%
- );
- pointer-events: none;
- z-index: 1;
- border-radius: var(--gallery-radius) var(--gallery-radius) 0 0;
+/* Hide the hero background image */
+.gallery-page .relative.-mt-6 > .relative:first-child > img,
+.gallery-page .relative.-mt-6 > .relative:first-child > canvas {
+ display: none !important;
}
-.photo-card:hover {
- transform: translateY(-8px) scale(1.02);
- box-shadow:
- 0 20px 40px rgba(102, 126, 234, 0.3),
- 0 8px 16px rgba(0, 0, 0, 0.1),
- inset 0 1px 1px rgba(255, 255, 255, 0.8);
+/* Hide the dark overlay */
+.gallery-page .relative.-mt-6 > .relative:first-child > .absolute.inset-0.bg-black {
+ display: none !important;
}
-.photo-card img {
- width: 100%;
- height: 240px;
- object-fit: cover;
- transition: transform 0.4s ease;
+/* Style the content area as glass title box */
+.gallery-page .relative.-mt-6 > .relative:first-child > .absolute.inset-0.flex {
+ position: relative !important;
+ inset: auto !important;
+ background: var(--glass-bg-medium) !important;
+ backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ border: 1px solid var(--glass-border-light) !important;
+ border-radius: var(--gallery-radius) !important;
+ padding: 2rem 3rem !important;
+ box-shadow: var(--glass-shadow), var(--glass-inset) !important;
+ max-width: 600px !important;
+ width: auto !important;
}
-.photo-card:hover img {
- transform: scale(1.05);
+/* Hide logo in glass title box */
+.gallery-page .relative.-mt-6 > .relative:first-child .mb-6 {
+ display: none !important;
}
-.photo-card-info {
- padding: var(--gallery-spacing);
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.1) 0%,
- rgba(255, 255, 255, 0.3) 100%
- );
+/* Style title text */
+.gallery-page .relative.-mt-6 > .relative:first-child h1 {
+ color: var(--gallery-text) !important;
+ text-shadow: none !important;
+ font-weight: 700 !important;
+ font-size: 2.25rem !important;
+ margin-bottom: 0.75rem !important;
}
-/* ===== Buttons - Glass Style ===== */
-.gallery-btn {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: calc(var(--gallery-radius) / 2);
- padding: 12px 24px;
- color: var(--gallery-text);
- font-weight: 600;
- cursor: pointer;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
+/* Style date text */
+.gallery-page .relative.-mt-6 > .relative:first-child .text-white\\/90 {
+ color: var(--gallery-text) !important;
+ opacity: 0.8;
}
-.gallery-btn::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- height: 50%;
- background: linear-gradient(
- 180deg,
- rgba(255, 255, 255, 0.4) 0%,
- transparent 100%
- );
+/* Hide scroll down button */
+.gallery-page .relative.-mt-6 > .relative:first-child > .absolute.bottom-8,
+.gallery-page .relative.-mt-6 > .relative:first-child > button.absolute {
+ display: none !important;
}
-.gallery-btn:hover {
- background: var(--glass-bg-elevated);
- transform: translateY(-2px);
- box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
+/* ===== PHOTO GRID ===== */
+.gallery-page .photo-grid {
+ display: grid !important;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) !important;
+ gap: 1.25rem !important;
+ padding: 1rem !important;
}
-.gallery-btn-primary {
- background: linear-gradient(135deg, var(--gallery-accent) 0%, var(--gallery-accent-hover) 100%);
- color: white;
- border: none;
+/* ===== PHOTO CARDS - Liquid Glass ===== */
+.gallery-page .photo-card {
+ background: var(--glass-bg) !important;
+ backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ border: 1px solid var(--glass-border) !important;
+ border-radius: var(--gallery-radius) !important;
+ overflow: hidden !important;
+ transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1), var(--glass-inset) !important;
}
-/* ===== Lightbox - Glass Style ===== */
-.lightbox-overlay {
- background: rgba(26, 26, 46, 0.8);
- backdrop-filter: blur(40px);
- -webkit-backdrop-filter: blur(40px);
+.gallery-page .photo-card:hover {
+ transform: translateY(-6px) scale(1.02) !important;
+ box-shadow: 0 20px 40px rgba(102, 126, 234, 0.25),
+ 0 8px 16px rgba(0, 0, 0, 0.1),
+ var(--glass-inset) !important;
+ border-color: var(--glass-border-light) !important;
}
-.lightbox-content {
- background: var(--glass-bg);
- backdrop-filter: blur(20px);
- -webkit-backdrop-filter: blur(20px);
- border: 1px solid var(--glass-border);
- border-radius: var(--gallery-radius);
- box-shadow: 0 24px 48px rgba(0, 0, 0, 0.2);
+.gallery-page .photo-card img {
+ transition: transform 0.4s ease !important;
}
-/* ===== Category Pills ===== */
-.category-pill {
- background: var(--glass-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border: 1px solid var(--glass-border);
- border-radius: 9999px;
- padding: 8px 20px;
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--gallery-text);
- transition: all 0.3s ease;
+.gallery-page .photo-card:hover img {
+ transform: scale(1.05) !important;
}
-.category-pill:hover,
-.category-pill.active {
- background: var(--gallery-accent);
- color: white;
- border-color: var(--gallery-accent);
+/* ===== BUTTONS - Glass Pill Style ===== */
+.gallery-page button,
+.gallery-page [role="button"],
+.gallery-sidebar button {
+ background: var(--glass-bg) !important;
+ backdrop-filter: blur(12px) saturate(150%) !important;
+ -webkit-backdrop-filter: blur(12px) saturate(150%) !important;
+ border: 1px solid var(--glass-border) !important;
+ border-radius: 9999px !important;
+ color: var(--gallery-text) !important;
+ font-weight: 500 !important;
+ transition: all 0.3s ease !important;
}
-/* ===== Responsive ===== */
+.gallery-page button:hover,
+.gallery-page [role="button"]:hover,
+.gallery-sidebar button:hover {
+ background: var(--glass-bg-medium) !important;
+ transform: translateY(-1px);
+ box-shadow: 0 4px 16px rgba(102, 126, 234, 0.2) !important;
+}
+
+.gallery-page button[class*="bg-primary"],
+.gallery-page .gallery-btn-download {
+ background: linear-gradient(135deg, var(--gallery-accent) 0%, #764ba2 100%) !important;
+ color: white !important;
+ border: none !important;
+}
+
+/* ===== INPUT FIELDS ===== */
+.gallery-page input,
+.gallery-page select,
+.gallery-sidebar input,
+.gallery-sidebar select {
+ background: rgba(255, 255, 255, 0.25) !important;
+ backdrop-filter: blur(8px) !important;
+ -webkit-backdrop-filter: blur(8px) !important;
+ border: 1px solid var(--glass-border) !important;
+ border-radius: var(--gallery-radius-sm) !important;
+ color: var(--gallery-text) !important;
+}
+
+/* Input placeholder text - make it visible */
+.gallery-page input::placeholder,
+.gallery-sidebar input::placeholder {
+ color: rgba(26, 26, 46, 0.6) !important;
+ opacity: 1 !important;
+}
+
+/* Input focus state */
+.gallery-page input:focus,
+.gallery-sidebar input:focus {
+ background: rgba(255, 255, 255, 0.35) !important;
+ border-color: var(--glass-border-light) !important;
+ outline: none !important;
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2) !important;
+}
+
+/* ===== FOOTER ===== */
+.gallery-page .gallery-footer,
+.gallery-page footer {
+ background: var(--glass-bg) !important;
+ backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturation)) !important;
+ border-top: 1px solid var(--glass-border) !important;
+}
+
+/* ===== LIGHTBOX ===== */
+.gallery-page [class*="fixed"][class*="inset-0"][class*="z-50"] {
+ background: rgba(0, 0, 0, 0.7) !important;
+ backdrop-filter: blur(30px) !important;
+ -webkit-backdrop-filter: blur(30px) !important;
+}
+
+/* ===== SCROLLBAR ===== */
+.gallery-page ::-webkit-scrollbar,
+.gallery-sidebar ::-webkit-scrollbar {
+ width: 8px;
+}
+
+.gallery-page ::-webkit-scrollbar-track,
+.gallery-sidebar ::-webkit-scrollbar-track {
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.gallery-page ::-webkit-scrollbar-thumb,
+.gallery-sidebar ::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.3);
+ border-radius: 4px;
+}
+
+/* ===== RESPONSIVE ===== */
@media (max-width: 768px) {
- .gallery-page {
+ :root {
--gallery-radius: 16px;
- --gallery-spacing: 12px;
--glass-blur: 16px;
}
- .photo-grid {
- grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
+ .gallery-page .relative.-mt-6 > .relative:first-child > .absolute.inset-0.flex {
+ padding: 1.5rem 2rem !important;
+ max-width: 90% !important;
}
- .photo-card img {
- height: 180px;
+ .gallery-page .relative.-mt-6 > .relative:first-child h1 {
+ font-size: 1.5rem !important;
+ }
+
+ .gallery-page .photo-grid {
+ grid-template-columns: repeat(2, 1fr) !important;
+ gap: 0.75rem !important;
}
}
-/* ===== Accessibility: Reduce Motion ===== */
+/* ===== ACCESSIBILITY ===== */
@media (prefers-reduced-motion: reduce) {
- .photo-card,
- .gallery-btn {
- transition: none;
+ .gallery-page .photo-card,
+ .gallery-page button {
+ transition: none !important;
}
- .photo-card:hover {
- transform: none;
+ .gallery-page .photo-card:hover {
+ transform: none !important;
}
}
-/* ===== Accessibility: Reduce Transparency ===== */
@media (prefers-reduced-transparency: reduce) {
- .glass-surface,
- .photo-card,
- .gallery-btn {
- backdrop-filter: none;
- -webkit-backdrop-filter: none;
- background: rgba(255, 255, 255, 0.95);
+ .gallery-page .photo-card,
+ .gallery-page button,
+ .gallery-sidebar {
+ backdrop-filter: none !important;
+ -webkit-backdrop-filter: none !important;
+ background: rgba(255, 255, 255, 0.95) !important;
}
}`;
@@ -642,12 +680,12 @@ const LIQUID_GLASS_DARK = `/*
}`;
exports.up = async function(knex) {
- // Update template slot 2 with Liquid Glass Light
+ // Update template slot 2 with Apple Liquid Glass (Light)
await knex('css_templates')
.where({ slot_number: 2 })
.update({
- name: 'Liquid Glass Light',
- css_content: LIQUID_GLASS_LIGHT,
+ name: 'Apple Liquid Glass',
+ css_content: APPLE_LIQUID_GLASS,
is_enabled: true,
is_default: false,
updated_at: knex.fn.now()
@@ -689,5 +727,5 @@ exports.down = async function(knex) {
};
// Export templates for use elsewhere
-module.exports.LIQUID_GLASS_LIGHT = LIQUID_GLASS_LIGHT;
+module.exports.APPLE_LIQUID_GLASS = APPLE_LIQUID_GLASS;
module.exports.LIQUID_GLASS_DARK = LIQUID_GLASS_DARK;
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 5b858263..89d39dd4 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -258,66 +258,66 @@
}
},
"node_modules/@aws-sdk/client-s3": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.940.0.tgz",
- "integrity": "sha512-Wi4qnBT6shRRMXuuTgjMFTU5mu2KFWisgcigEMPptjPGUtJvBVi4PTGgS64qsLoUk/obqDAyOBOfEtRZ2ddC2w==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.962.0.tgz",
+ "integrity": "sha512-I2/1McBZCcM3PfM4ck8D6gnZR3K7+yl1fGkwTq/3ThEn9tdLjNwcdgTbPfxfX6LoecLrH9Ekoo+D9nmQ0T261w==",
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@aws-crypto/sha1-browser": "5.2.0",
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/credential-provider-node": "3.940.0",
- "@aws-sdk/middleware-bucket-endpoint": "3.936.0",
- "@aws-sdk/middleware-expect-continue": "3.936.0",
- "@aws-sdk/middleware-flexible-checksums": "3.940.0",
- "@aws-sdk/middleware-host-header": "3.936.0",
- "@aws-sdk/middleware-location-constraint": "3.936.0",
- "@aws-sdk/middleware-logger": "3.936.0",
- "@aws-sdk/middleware-recursion-detection": "3.936.0",
- "@aws-sdk/middleware-sdk-s3": "3.940.0",
- "@aws-sdk/middleware-ssec": "3.936.0",
- "@aws-sdk/middleware-user-agent": "3.940.0",
- "@aws-sdk/region-config-resolver": "3.936.0",
- "@aws-sdk/signature-v4-multi-region": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-endpoints": "3.936.0",
- "@aws-sdk/util-user-agent-browser": "3.936.0",
- "@aws-sdk/util-user-agent-node": "3.940.0",
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/core": "^3.18.5",
- "@smithy/eventstream-serde-browser": "^4.2.5",
- "@smithy/eventstream-serde-config-resolver": "^4.3.5",
- "@smithy/eventstream-serde-node": "^4.2.5",
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/hash-blob-browser": "^4.2.6",
- "@smithy/hash-node": "^4.2.5",
- "@smithy/hash-stream-node": "^4.2.5",
- "@smithy/invalid-dependency": "^4.2.5",
- "@smithy/md5-js": "^4.2.5",
- "@smithy/middleware-content-length": "^4.2.5",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/middleware-retry": "^4.4.12",
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/middleware-stack": "^4.2.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/credential-provider-node": "3.962.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.957.0",
+ "@aws-sdk/middleware-expect-continue": "3.957.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.957.0",
+ "@aws-sdk/middleware-host-header": "3.957.0",
+ "@aws-sdk/middleware-location-constraint": "3.957.0",
+ "@aws-sdk/middleware-logger": "3.957.0",
+ "@aws-sdk/middleware-recursion-detection": "3.957.0",
+ "@aws-sdk/middleware-sdk-s3": "3.957.0",
+ "@aws-sdk/middleware-ssec": "3.957.0",
+ "@aws-sdk/middleware-user-agent": "3.957.0",
+ "@aws-sdk/region-config-resolver": "3.957.0",
+ "@aws-sdk/signature-v4-multi-region": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-endpoints": "3.957.0",
+ "@aws-sdk/util-user-agent-browser": "3.957.0",
+ "@aws-sdk/util-user-agent-node": "3.957.0",
+ "@smithy/config-resolver": "^4.4.5",
+ "@smithy/core": "^3.20.0",
+ "@smithy/eventstream-serde-browser": "^4.2.7",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.7",
+ "@smithy/eventstream-serde-node": "^4.2.7",
+ "@smithy/fetch-http-handler": "^5.3.8",
+ "@smithy/hash-blob-browser": "^4.2.8",
+ "@smithy/hash-node": "^4.2.7",
+ "@smithy/hash-stream-node": "^4.2.7",
+ "@smithy/invalid-dependency": "^4.2.7",
+ "@smithy/md5-js": "^4.2.7",
+ "@smithy/middleware-content-length": "^4.2.7",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/middleware-retry": "^4.4.17",
+ "@smithy/middleware-serde": "^4.2.8",
+ "@smithy/middleware-stack": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/node-http-handler": "^4.4.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
"@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.11",
- "@smithy/util-defaults-mode-node": "^4.2.14",
- "@smithy/util-endpoints": "^3.2.5",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-retry": "^4.2.5",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/util-defaults-mode-browser": "^4.3.16",
+ "@smithy/util-defaults-mode-node": "^4.2.19",
+ "@smithy/util-endpoints": "^3.2.7",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-retry": "^4.2.7",
+ "@smithy/util-stream": "^4.5.8",
"@smithy/util-utf8": "^4.2.0",
- "@smithy/util-waiter": "^4.2.5",
+ "@smithy/util-waiter": "^4.2.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -325,47 +325,47 @@
}
},
"node_modules/@aws-sdk/client-sso": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.940.0.tgz",
- "integrity": "sha512-SdqJGWVhmIURvCSgkDditHRO+ozubwZk9aCX9MK8qxyOndhobCndW1ozl3hX9psvMAo9Q4bppjuqy/GHWpjB+A==",
+ "version": "3.958.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.958.0.tgz",
+ "integrity": "sha512-6qNCIeaMzKzfqasy2nNRuYnMuaMebCcCPP4J2CVGkA8QYMbIVKPlkn9bpB20Vxe6H/r3jtCCLQaOJjVTx/6dXg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/middleware-host-header": "3.936.0",
- "@aws-sdk/middleware-logger": "3.936.0",
- "@aws-sdk/middleware-recursion-detection": "3.936.0",
- "@aws-sdk/middleware-user-agent": "3.940.0",
- "@aws-sdk/region-config-resolver": "3.936.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-endpoints": "3.936.0",
- "@aws-sdk/util-user-agent-browser": "3.936.0",
- "@aws-sdk/util-user-agent-node": "3.940.0",
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/core": "^3.18.5",
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/hash-node": "^4.2.5",
- "@smithy/invalid-dependency": "^4.2.5",
- "@smithy/middleware-content-length": "^4.2.5",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/middleware-retry": "^4.4.12",
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/middleware-stack": "^4.2.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/middleware-host-header": "3.957.0",
+ "@aws-sdk/middleware-logger": "3.957.0",
+ "@aws-sdk/middleware-recursion-detection": "3.957.0",
+ "@aws-sdk/middleware-user-agent": "3.957.0",
+ "@aws-sdk/region-config-resolver": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-endpoints": "3.957.0",
+ "@aws-sdk/util-user-agent-browser": "3.957.0",
+ "@aws-sdk/util-user-agent-node": "3.957.0",
+ "@smithy/config-resolver": "^4.4.5",
+ "@smithy/core": "^3.20.0",
+ "@smithy/fetch-http-handler": "^5.3.8",
+ "@smithy/hash-node": "^4.2.7",
+ "@smithy/invalid-dependency": "^4.2.7",
+ "@smithy/middleware-content-length": "^4.2.7",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/middleware-retry": "^4.4.17",
+ "@smithy/middleware-serde": "^4.2.8",
+ "@smithy/middleware-stack": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/node-http-handler": "^4.4.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
"@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.11",
- "@smithy/util-defaults-mode-node": "^4.2.14",
- "@smithy/util-endpoints": "^3.2.5",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-retry": "^4.2.5",
+ "@smithy/util-defaults-mode-browser": "^4.3.16",
+ "@smithy/util-defaults-mode-node": "^4.2.19",
+ "@smithy/util-endpoints": "^3.2.7",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-retry": "^4.2.7",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -374,22 +374,22 @@
}
},
"node_modules/@aws-sdk/core": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.940.0.tgz",
- "integrity": "sha512-KsGD2FLaX5ngJao1mHxodIVU9VYd1E8810fcYiGwO1PFHDzf5BEkp6D9IdMeQwT8Q6JLYtiiT1Y/o3UCScnGoA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.957.0.tgz",
+ "integrity": "sha512-DrZgDnF1lQZv75a52nFWs6MExihJF2GZB6ETZRqr6jMwhrk2kbJPUtvgbifwcL7AYmVqHQDJBrR/MqkwwFCpiw==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/xml-builder": "3.930.0",
- "@smithy/core": "^3.18.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/signature-v4": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/xml-builder": "3.957.0",
+ "@smithy/core": "^3.20.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/signature-v4": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
"@smithy/util-base64": "^4.3.0",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-middleware": "^4.2.7",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -397,16 +397,29 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.940.0.tgz",
- "integrity": "sha512-/G3l5/wbZYP2XEQiOoIkRJmlv15f1P3MSd1a0gz27lHEMrOJOGq66rF1Ca4OJLzapWt3Fy9BPrZAepoAX11kMw==",
+ "node_modules/@aws-sdk/crc64-nvme": {
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.957.0.tgz",
+ "integrity": "sha512-qSwSfI+qBU9HDsd6/4fM9faCxYJx2yDuHtj+NVOQ6XYDWQzFab/hUdwuKZ77Pi6goLF1pBZhJ2azaC2w7LbnTA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.957.0.tgz",
+ "integrity": "sha512-475mkhGaWCr+Z52fOOVb/q2VHuNvqEDixlYIkeaO6xJ6t9qR0wpLt4hOQaR6zR1wfZV0SlE7d8RErdYq/PByog==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -414,20 +427,20 @@
}
},
"node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.940.0.tgz",
- "integrity": "sha512-dOrc03DHElNBD6N9Okt4U0zhrG4Wix5QUBSZPr5VN8SvmjD9dkrrxOkkJaMCl/bzrW7kbQEp7LuBdbxArMmOZQ==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.957.0.tgz",
+ "integrity": "sha512-8dS55QHRxXgJlHkEYaCGZIhieCs9NU1HU1BcqQ4RfUdSsfRdxxktqUKgCnBnOOn0oD3PPA8cQOCAVgIyRb3Rfw==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
- "@smithy/util-stream": "^4.5.6",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/fetch-http-handler": "^5.3.8",
+ "@smithy/node-http-handler": "^4.4.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/util-stream": "^4.5.8",
"tslib": "^2.6.2"
},
"engines": {
@@ -435,24 +448,24 @@
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.940.0.tgz",
- "integrity": "sha512-gn7PJQEzb/cnInNFTOaDoCN/hOKqMejNmLof1W5VW95Qk0TPO52lH8R4RmJPnRrwFMswOWswTOpR1roKNLIrcw==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.962.0.tgz",
+ "integrity": "sha512-h0kVnXLW2d3nxbcrR/Pfg3W/+YoCguasWz7/3nYzVqmdKarGrpJzaFdoZtLgvDSZ8VgWUC4lWOTcsDMV0UNqUQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/credential-provider-env": "3.940.0",
- "@aws-sdk/credential-provider-http": "3.940.0",
- "@aws-sdk/credential-provider-login": "3.940.0",
- "@aws-sdk/credential-provider-process": "3.940.0",
- "@aws-sdk/credential-provider-sso": "3.940.0",
- "@aws-sdk/credential-provider-web-identity": "3.940.0",
- "@aws-sdk/nested-clients": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/credential-provider-imds": "^4.2.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/credential-provider-env": "3.957.0",
+ "@aws-sdk/credential-provider-http": "3.957.0",
+ "@aws-sdk/credential-provider-login": "3.962.0",
+ "@aws-sdk/credential-provider-process": "3.957.0",
+ "@aws-sdk/credential-provider-sso": "3.958.0",
+ "@aws-sdk/credential-provider-web-identity": "3.958.0",
+ "@aws-sdk/nested-clients": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/credential-provider-imds": "^4.2.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -460,18 +473,18 @@
}
},
"node_modules/@aws-sdk/credential-provider-login": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.940.0.tgz",
- "integrity": "sha512-fOKC3VZkwa9T2l2VFKWRtfHQPQuISqqNl35ZhcXjWKVwRwl/o7THPMkqI4XwgT2noGa7LLYVbWMwnsgSsBqglg==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.962.0.tgz",
+ "integrity": "sha512-kHYH6Av2UifG3mPkpPUNRh/PuX6adaAcpmsclJdHdxlixMCRdh8GNeEihq480DC0GmfqdpoSf1w2CLmLLPIS6w==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/nested-clients": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/nested-clients": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -479,22 +492,22 @@
}
},
"node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.940.0.tgz",
- "integrity": "sha512-M8NFAvgvO6xZjiti5kztFiAYmSmSlG3eUfr4ZHSfXYZUA/KUdZU/D6xJyaLnU8cYRWBludb6K9XPKKVwKfqm4g==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.962.0.tgz",
+ "integrity": "sha512-CS78NsWRxLa+nWqeWBEYMZTLacMFIXs1C5WJuM9kD05LLiWL32ksljoPsvNN24Bc7rCSQIIMx/U3KGvkDVZMVg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/credential-provider-env": "3.940.0",
- "@aws-sdk/credential-provider-http": "3.940.0",
- "@aws-sdk/credential-provider-ini": "3.940.0",
- "@aws-sdk/credential-provider-process": "3.940.0",
- "@aws-sdk/credential-provider-sso": "3.940.0",
- "@aws-sdk/credential-provider-web-identity": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/credential-provider-imds": "^4.2.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/credential-provider-env": "3.957.0",
+ "@aws-sdk/credential-provider-http": "3.957.0",
+ "@aws-sdk/credential-provider-ini": "3.962.0",
+ "@aws-sdk/credential-provider-process": "3.957.0",
+ "@aws-sdk/credential-provider-sso": "3.958.0",
+ "@aws-sdk/credential-provider-web-identity": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/credential-provider-imds": "^4.2.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -502,16 +515,16 @@
}
},
"node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.940.0.tgz",
- "integrity": "sha512-pILBzt5/TYCqRsJb7vZlxmRIe0/T+FZPeml417EK75060ajDGnVJjHcuVdLVIeKoTKm9gmJc9l45gon6PbHyUQ==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.957.0.tgz",
+ "integrity": "sha512-/KIz9kadwbeLy6SKvT79W81Y+hb/8LMDyeloA2zhouE28hmne+hLn0wNCQXAAupFFlYOAtZR2NTBs7HBAReJlg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -519,18 +532,18 @@
}
},
"node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.940.0.tgz",
- "integrity": "sha512-q6JMHIkBlDCOMnA3RAzf8cGfup+8ukhhb50fNpghMs1SNBGhanmaMbZSgLigBRsPQW7fOk2l8jnzdVLS+BB9Uw==",
+ "version": "3.958.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.958.0.tgz",
+ "integrity": "sha512-CBYHJ5ufp8HC4q+o7IJejCUctJXWaksgpmoFpXerbjAso7/Fg7LLUu9inXVOxlHKLlvYekDXjIUBXDJS2WYdgg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/client-sso": "3.940.0",
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/token-providers": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/client-sso": "3.958.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/token-providers": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -538,17 +551,17 @@
}
},
"node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.940.0.tgz",
- "integrity": "sha512-9QLTIkDJHHaYL0nyymO41H8g3ui1yz6Y3GmAN1gYQa6plXisuFBnGAbmKVj7zNvjWaOKdF0dV3dd3AFKEDoJ/w==",
+ "version": "3.958.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.958.0.tgz",
+ "integrity": "sha512-dgnvwjMq5Y66WozzUzxNkCFap+umHUtqMMKlr8z/vl9NYMLem/WUbWNpFFOVFWquXikc+ewtpBMR4KEDXfZ+KA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/nested-clients": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/nested-clients": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -556,14 +569,14 @@
}
},
"node_modules/@aws-sdk/lib-storage": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.940.0.tgz",
- "integrity": "sha512-4pHgz9tuFJNSy/qoTbW5FqXPjoR4B18jB656UsE+TP5GWd7EPx7m4F0EUwIsD3OF5+KPiiyICi8zkxOs7erfQw==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.962.0.tgz",
+ "integrity": "sha512-Ai5gWRQkzsUMQ6NPoZZoiLXoQ6/yPRcR4oracIVjyWcu48TfBpsRgbqY/5zNOM55ag1wPX9TtJJGOhK3TNk45g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.2.5",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/smithy-client": "^4.9.8",
+ "@smithy/abort-controller": "^4.2.7",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/smithy-client": "^4.10.2",
"buffer": "5.6.0",
"events": "3.3.0",
"stream-browserify": "3.0.0",
@@ -573,20 +586,20 @@
"node": ">=18.0.0"
},
"peerDependencies": {
- "@aws-sdk/client-s3": "^3.940.0"
+ "@aws-sdk/client-s3": "^3.962.0"
}
},
"node_modules/@aws-sdk/middleware-bucket-endpoint": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.936.0.tgz",
- "integrity": "sha512-XLSVVfAorUxZh6dzF+HTOp4R1B5EQcdpGcPliWr0KUj2jukgjZEcqbBmjyMF/p9bmyQsONX80iURF1HLAlW0qg==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.957.0.tgz",
+ "integrity": "sha512-iczcn/QRIBSpvsdAS/rbzmoBpleX1JBjXvCynMbDceVLBIcVrwT1hXECrhtIC2cjh4HaLo9ClAbiOiWuqt+6MA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-arn-parser": "3.893.0",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-arn-parser": "3.957.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-config-provider": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -595,14 +608,14 @@
}
},
"node_modules/@aws-sdk/middleware-expect-continue": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.936.0.tgz",
- "integrity": "sha512-Eb4ELAC23bEQLJmUMYnPWcjD3FZIsmz2svDiXEcxRkQU9r7NRID7pM7C5NPH94wOfiCk0b2Y8rVyFXW0lGQwbA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.957.0.tgz",
+ "integrity": "sha512-AlbK3OeVNwZZil0wlClgeI/ISlOt/SPUxBsIns876IFaVu/Pj3DgImnYhpcJuFRek4r4XM51xzIaGQXM6GDHGg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -610,22 +623,23 @@
}
},
"node_modules/@aws-sdk/middleware-flexible-checksums": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.940.0.tgz",
- "integrity": "sha512-WdsxDAVj5qaa5ApAP+JbpCOMHFGSmzjs2Y2OBSbWPeR9Ew7t/Okj+kUub94QJPsgzhvU1/cqNejhsw5VxeFKSQ==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.957.0.tgz",
+ "integrity": "sha512-iJpeVR5V8se1hl2pt+k8bF/e9JO4KWgPCMjg8BtRspNtKIUGy7j6msYvbDixaKZaF2Veg9+HoYcOhwnZumjXSA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@aws-crypto/crc32c": "5.2.0",
"@aws-crypto/util": "5.2.0",
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/crc64-nvme": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
"@smithy/is-array-buffer": "^4.2.0",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-stream": "^4.5.8",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -634,14 +648,14 @@
}
},
"node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz",
- "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.957.0.tgz",
+ "integrity": "sha512-BBgKawVyfQZglEkNTuBBdC3azlyqNXsvvN4jPkWAiNYcY0x1BasaJFl+7u/HisfULstryweJq/dAvIZIxzlZaA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -649,13 +663,13 @@
}
},
"node_modules/@aws-sdk/middleware-location-constraint": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.936.0.tgz",
- "integrity": "sha512-SCMPenDtQMd9o5da9JzkHz838w3327iqXk3cbNnXWqnNRx6unyW8FL0DZ84gIY12kAyVHz5WEqlWuekc15ehfw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.957.0.tgz",
+ "integrity": "sha512-y8/W7TOQpmDJg/fPYlqAhwA4+I15LrS7TwgUEoxogtkD8gfur9wFMRLT8LCyc9o4NMEcAnK50hSb4+wB0qv6tQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -663,13 +677,13 @@
}
},
"node_modules/@aws-sdk/middleware-logger": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz",
- "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.957.0.tgz",
+ "integrity": "sha512-w1qfKrSKHf9b5a8O76yQ1t69u6NWuBjr5kBX+jRWFx/5mu6RLpqERXRpVJxfosbep7k3B+DSB5tZMZ82GKcJtQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -677,15 +691,15 @@
}
},
"node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz",
- "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.957.0.tgz",
+ "integrity": "sha512-D2H/WoxhAZNYX+IjkKTdOhOkWQaK0jjJrDBj56hKjU5c9ltQiaX/1PqJ4dfjHntEshJfu0w+E6XJ+/6A6ILBBA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@aws/lambda-invoke-store": "^0.2.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -693,23 +707,23 @@
}
},
"node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.940.0.tgz",
- "integrity": "sha512-JYkLjgS1wLoKHJ40G63+afM1ehmsPsjcmrHirKh8+kSCx4ip7+nL1e/twV4Zicxr8RJi9Y0Ahq5mDvneilDDKQ==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.957.0.tgz",
+ "integrity": "sha512-5B2qY2nR2LYpxoQP0xUum5A1UNvH2JQpLHDH1nWFNF/XetV7ipFHksMxPNhtJJ6ARaWhQIDXfOUj0jcnkJxXUg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-arn-parser": "3.893.0",
- "@smithy/core": "^3.18.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/signature-v4": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-arn-parser": "3.957.0",
+ "@smithy/core": "^3.20.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/signature-v4": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
"@smithy/util-config-provider": "^4.2.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-stream": "^4.5.8",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -718,13 +732,13 @@
}
},
"node_modules/@aws-sdk/middleware-ssec": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.936.0.tgz",
- "integrity": "sha512-/GLC9lZdVp05ozRik5KsuODR/N7j+W+2TbfdFL3iS+7un+gnP6hC8RDOZd6WhpZp7drXQ9guKiTAxkZQwzS8DA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.957.0.tgz",
+ "integrity": "sha512-qwkmrK0lizdjNt5qxl4tHYfASh8DFpHXM1iDVo+qHe+zuslfMqQEGRkzxS8tJq/I+8F0c6v3IKOveKJAfIvfqQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -732,17 +746,17 @@
}
},
"node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.940.0.tgz",
- "integrity": "sha512-nJbLrUj6fY+l2W2rIB9P4Qvpiy0tnTdg/dmixRxrU1z3e8wBdspJlyE+AZN4fuVbeL6rrRrO/zxQC1bB3cw5IA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.957.0.tgz",
+ "integrity": "sha512-50vcHu96XakQnIvlKJ1UoltrFODjsq2KvtTgHiPFteUS884lQnK5VC/8xd1Msz/1ONpLMzdCVproCQqhDTtMPQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-endpoints": "3.936.0",
- "@smithy/core": "^3.18.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-endpoints": "3.957.0",
+ "@smithy/core": "^3.20.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -750,47 +764,47 @@
}
},
"node_modules/@aws-sdk/nested-clients": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.940.0.tgz",
- "integrity": "sha512-x0mdv6DkjXqXEcQj3URbCltEzW6hoy/1uIL+i8gExP6YKrnhiZ7SzuB4gPls2UOpK5UqLiqXjhRLfBb1C9i4Dw==",
+ "version": "3.958.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.958.0.tgz",
+ "integrity": "sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/middleware-host-header": "3.936.0",
- "@aws-sdk/middleware-logger": "3.936.0",
- "@aws-sdk/middleware-recursion-detection": "3.936.0",
- "@aws-sdk/middleware-user-agent": "3.940.0",
- "@aws-sdk/region-config-resolver": "3.936.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-endpoints": "3.936.0",
- "@aws-sdk/util-user-agent-browser": "3.936.0",
- "@aws-sdk/util-user-agent-node": "3.940.0",
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/core": "^3.18.5",
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/hash-node": "^4.2.5",
- "@smithy/invalid-dependency": "^4.2.5",
- "@smithy/middleware-content-length": "^4.2.5",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/middleware-retry": "^4.4.12",
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/middleware-stack": "^4.2.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/middleware-host-header": "3.957.0",
+ "@aws-sdk/middleware-logger": "3.957.0",
+ "@aws-sdk/middleware-recursion-detection": "3.957.0",
+ "@aws-sdk/middleware-user-agent": "3.957.0",
+ "@aws-sdk/region-config-resolver": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-endpoints": "3.957.0",
+ "@aws-sdk/util-user-agent-browser": "3.957.0",
+ "@aws-sdk/util-user-agent-node": "3.957.0",
+ "@smithy/config-resolver": "^4.4.5",
+ "@smithy/core": "^3.20.0",
+ "@smithy/fetch-http-handler": "^5.3.8",
+ "@smithy/hash-node": "^4.2.7",
+ "@smithy/invalid-dependency": "^4.2.7",
+ "@smithy/middleware-content-length": "^4.2.7",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/middleware-retry": "^4.4.17",
+ "@smithy/middleware-serde": "^4.2.8",
+ "@smithy/middleware-stack": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/node-http-handler": "^4.4.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
"@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.11",
- "@smithy/util-defaults-mode-node": "^4.2.14",
- "@smithy/util-endpoints": "^3.2.5",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-retry": "^4.2.5",
+ "@smithy/util-defaults-mode-browser": "^4.3.16",
+ "@smithy/util-defaults-mode-node": "^4.2.19",
+ "@smithy/util-endpoints": "^3.2.7",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-retry": "^4.2.7",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -799,15 +813,15 @@
}
},
"node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz",
- "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.957.0.tgz",
+ "integrity": "sha512-V8iY3blh8l2iaOqXWW88HbkY5jDoWjH56jonprG/cpyqqCnprvpMUZWPWYJoI8rHRf2bqzZeql1slxG6EnKI7A==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/config-resolver": "^4.4.5",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -815,18 +829,18 @@
}
},
"node_modules/@aws-sdk/s3-request-presigner": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.940.0.tgz",
- "integrity": "sha512-TgTUDM2H7revReDfkVwVtIqxV3K0cJLdyuLDIkefVHRUNKwU1Vd5FB2TaFrs6STO0kx5pTckDCOLh0iy7nW5WQ==",
+ "version": "3.962.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.962.0.tgz",
+ "integrity": "sha512-tyxsGfLY4NSohLrJsFGXbE3j8jguWK+hdGaUQSD1gJPvmC0B82qOyJ7WBIJLWgTabU3fiF/I9EGXjzR2rKr8jQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/signature-v4-multi-region": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@aws-sdk/util-format-url": "3.936.0",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/signature-v4-multi-region": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@aws-sdk/util-format-url": "3.957.0",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -834,16 +848,16 @@
}
},
"node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.940.0.tgz",
- "integrity": "sha512-ugHZEoktD/bG6mdgmhzLDjMP2VrYRAUPRPF1DpCyiZexkH7DCU7XrSJyXMvkcf0DHV+URk0q2sLf/oqn1D2uYw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.957.0.tgz",
+ "integrity": "sha512-t6UfP1xMUigMMzHcb7vaZcjv7dA2DQkk9C/OAP1dKyrE0vb4lFGDaTApi17GN6Km9zFxJthEMUbBc7DL0hq1Bg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/signature-v4": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/middleware-sdk-s3": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/signature-v4": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -851,17 +865,17 @@
}
},
"node_modules/@aws-sdk/token-providers": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.940.0.tgz",
- "integrity": "sha512-k5qbRe/ZFjW9oWEdzLIa2twRVIEx7p/9rutofyrRysrtEnYh3HAWCngAnwbgKMoiwa806UzcTRx0TjyEpnKcCg==",
+ "version": "3.958.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.958.0.tgz",
+ "integrity": "sha512-UCj7lQXODduD1myNJQkV+LYcGYJ9iiMggR8ow8Hva1g3A/Na5imNXzz6O67k7DAee0TYpy+gkNw+SizC6min8Q==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.940.0",
- "@aws-sdk/nested-clients": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/core": "3.957.0",
+ "@aws-sdk/nested-clients": "3.958.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -869,12 +883,12 @@
}
},
"node_modules/@aws-sdk/types": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
- "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.957.0.tgz",
+ "integrity": "sha512-wzWC2Nrt859ABk6UCAVY/WYEbAd7FjkdrQL6m24+tfmWYDNRByTJ9uOgU/kw9zqLCAwb//CPvrJdhqjTznWXAg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -882,9 +896,9 @@
}
},
"node_modules/@aws-sdk/util-arn-parser": {
- "version": "3.893.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz",
- "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.957.0.tgz",
+ "integrity": "sha512-Aj6m+AyrhWyg8YQ4LDPg2/gIfGHCEcoQdBt5DeSFogN5k9mmJPOJ+IAmNSWmWRjpOxEy6eY813RNDI6qS97M0g==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -894,15 +908,15 @@
}
},
"node_modules/@aws-sdk/util-endpoints": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz",
- "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.957.0.tgz",
+ "integrity": "sha512-xwF9K24mZSxcxKS3UKQFeX/dPYkEps9wF1b+MGON7EvnbcucrJGyQyK1v1xFPn1aqXkBTFi+SZaMRx5E5YCVFw==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
- "@smithy/util-endpoints": "^3.2.5",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
+ "@smithy/util-endpoints": "^3.2.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -910,14 +924,14 @@
}
},
"node_modules/@aws-sdk/util-format-url": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.936.0.tgz",
- "integrity": "sha512-MS5eSEtDUFIAMHrJaMERiHAvDPdfxc/T869ZjDNFAIiZhyc037REw0aoTNeimNXDNy2txRNZJaAUn/kE4RwN+g==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.957.0.tgz",
+ "integrity": "sha512-Yyo/tlc0iGFGTPPkuxub1uRAv6XrnVnvSNjslZh5jIYA8GZoeEFPgJa3Qdu0GUS/YwoK8GOLnnaL9h/eH5LDJQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/querystring-builder": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/querystring-builder": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -925,9 +939,9 @@
}
},
"node_modules/@aws-sdk/util-locate-window": {
- "version": "3.893.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz",
- "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.957.0.tgz",
+ "integrity": "sha512-nhmgKHnNV9K+i9daumaIz8JTLsIIML9PE/HUks5liyrjUzenjW/aHoc7WJ9/Td/gPZtayxFnXQSJRb/fDlBuJw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -937,27 +951,27 @@
}
},
"node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.936.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz",
- "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.957.0.tgz",
+ "integrity": "sha512-exueuwxef0lUJRnGaVkNSC674eAiWU07ORhxBnevFFZEKisln+09Qrtw823iyv5I1N8T+wKfh95xvtWQrNKNQw==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/types": "3.936.0",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/types": "^4.11.0",
"bowser": "^2.11.0",
"tslib": "^2.6.2"
}
},
"node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.940.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.940.0.tgz",
- "integrity": "sha512-dlD/F+L/jN26I8Zg5x0oDGJiA+/WEQmnSE27fi5ydvYnpfQLwThtQo9SsNS47XSR/SOULaaoC9qx929rZuo74A==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.957.0.tgz",
+ "integrity": "sha512-ycbYCwqXk4gJGp0Oxkzf2KBeeGBdTxz559D41NJP8FlzSej1Gh7Rk40Zo6AyTfsNWkrl/kVi1t937OIzC5t+9Q==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/middleware-user-agent": "3.940.0",
- "@aws-sdk/types": "3.936.0",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@aws-sdk/middleware-user-agent": "3.957.0",
+ "@aws-sdk/types": "3.957.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -973,12 +987,12 @@
}
},
"node_modules/@aws-sdk/xml-builder": {
- "version": "3.930.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz",
- "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==",
+ "version": "3.957.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.957.0.tgz",
+ "integrity": "sha512-Ai5iiQqS8kJ5PjzMhWcLKN0G2yasAkvpnPlq2EnqlIMdB48HsizElt62qcktdxp4neRMyGkFq4NzgmDbXnhRiA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"fast-xml-parser": "5.2.5",
"tslib": "^2.6.2"
},
@@ -987,9 +1001,9 @@
}
},
"node_modules/@aws/lambda-invoke-store": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz",
- "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==",
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz",
+ "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==",
"license": "Apache-2.0",
"engines": {
"node": ">=18.0.0"
@@ -1532,9 +1546,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
- "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2860,12 +2874,12 @@
}
},
"node_modules/@smithy/abort-controller": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz",
- "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.7.tgz",
+ "integrity": "sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2898,16 +2912,16 @@
}
},
"node_modules/@smithy/config-resolver": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz",
- "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==",
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.5.tgz",
+ "integrity": "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-config-provider": "^4.2.0",
- "@smithy/util-endpoints": "^3.2.5",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-endpoints": "^3.2.7",
+ "@smithy/util-middleware": "^4.2.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -2915,18 +2929,18 @@
}
},
"node_modules/@smithy/core": {
- "version": "3.18.5",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.5.tgz",
- "integrity": "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw==",
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.20.0.tgz",
+ "integrity": "sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/middleware-serde": "^4.2.8",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-stream": "^4.5.8",
"@smithy/util-utf8": "^4.2.0",
"@smithy/uuid": "^1.1.0",
"tslib": "^2.6.2"
@@ -2936,15 +2950,15 @@
}
},
"node_modules/@smithy/credential-provider-imds": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz",
- "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.7.tgz",
+ "integrity": "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -2952,13 +2966,13 @@
}
},
"node_modules/@smithy/eventstream-codec": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.5.tgz",
- "integrity": "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.7.tgz",
+ "integrity": "sha512-DrpkEoM3j9cBBWhufqBwnbbn+3nf1N9FP6xuVJ+e220jbactKuQgaZwjwP5CP1t+O94brm2JgVMD2atMGX3xIQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"@smithy/util-hex-encoding": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -2967,13 +2981,13 @@
}
},
"node_modules/@smithy/eventstream-serde-browser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.5.tgz",
- "integrity": "sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.7.tgz",
+ "integrity": "sha512-ujzPk8seYoDBmABDE5YqlhQZAXLOrtxtJLrbhHMKjBoG5b4dK4i6/mEU+6/7yXIAkqOO8sJ6YxZl+h0QQ1IJ7g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/eventstream-serde-universal": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2981,12 +2995,12 @@
}
},
"node_modules/@smithy/eventstream-serde-config-resolver": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.5.tgz",
- "integrity": "sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.7.tgz",
+ "integrity": "sha512-x7BtAiIPSaNaWuzm24Q/mtSkv+BrISO/fmheiJ39PKRNH3RmH2Hph/bUKSOBOBC9unqfIYDhKTHwpyZycLGPVQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2994,13 +3008,13 @@
}
},
"node_modules/@smithy/eventstream-serde-node": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.5.tgz",
- "integrity": "sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.7.tgz",
+ "integrity": "sha512-roySCtHC5+pQq5lK4be1fZ/WR6s/AxnPaLfCODIPArtN2du8s5Ot4mKVK3pPtijL/L654ws592JHJ1PbZFF6+A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/eventstream-serde-universal": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3008,13 +3022,13 @@
}
},
"node_modules/@smithy/eventstream-serde-universal": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.5.tgz",
- "integrity": "sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.7.tgz",
+ "integrity": "sha512-QVD+g3+icFkThoy4r8wVFZMsIP08taHVKjE6Jpmz8h5CgX/kk6pTODq5cht0OMtcapUx+xrPzUTQdA+TmO0m1g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/eventstream-codec": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/eventstream-codec": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3022,14 +3036,14 @@
}
},
"node_modules/@smithy/fetch-http-handler": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz",
- "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==",
+ "version": "5.3.8",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.8.tgz",
+ "integrity": "sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/querystring-builder": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/querystring-builder": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-base64": "^4.3.0",
"tslib": "^2.6.2"
},
@@ -3038,14 +3052,14 @@
}
},
"node_modules/@smithy/hash-blob-browser": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.6.tgz",
- "integrity": "sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw==",
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.8.tgz",
+ "integrity": "sha512-07InZontqsM1ggTCPSRgI7d8DirqRrnpL7nIACT4PW0AWrgDiHhjGZzbAE5UtRSiU0NISGUYe7/rri9ZeWyDpw==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/chunked-blob-reader": "^5.2.0",
"@smithy/chunked-blob-reader-native": "^4.2.1",
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3053,12 +3067,12 @@
}
},
"node_modules/@smithy/hash-node": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz",
- "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.7.tgz",
+ "integrity": "sha512-PU/JWLTBCV1c8FtB8tEFnY4eV1tSfBc7bDBADHfn1K+uRbPgSJ9jnJp0hyjiFN2PMdPzxsf1Fdu0eo9fJ760Xw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"@smithy/util-buffer-from": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
@@ -3068,12 +3082,12 @@
}
},
"node_modules/@smithy/hash-stream-node": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.5.tgz",
- "integrity": "sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.7.tgz",
+ "integrity": "sha512-ZQVoAwNYnFMIbd4DUc517HuwNelJUY6YOzwqrbcAgCnVn+79/OK7UjwA93SPpdTOpKDVkLIzavWm/Ck7SmnDPQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -3082,12 +3096,12 @@
}
},
"node_modules/@smithy/invalid-dependency": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz",
- "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.7.tgz",
+ "integrity": "sha512-ncvgCr9a15nPlkhIUx3CU4d7E7WEuVJOV7fS7nnK2hLtPK9tYRBkMHQbhXU1VvvKeBm/O0x26OEoBq+ngFpOEQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3107,12 +3121,12 @@
}
},
"node_modules/@smithy/md5-js": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.5.tgz",
- "integrity": "sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.7.tgz",
+ "integrity": "sha512-Wv6JcUxtOLTnxvNjDnAiATUsk8gvA6EeS8zzHig07dotpByYsLot+m0AaQEniUBjx97AC41MQR4hW0baraD1Xw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -3121,13 +3135,13 @@
}
},
"node_modules/@smithy/middleware-content-length": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz",
- "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.7.tgz",
+ "integrity": "sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3135,18 +3149,18 @@
}
},
"node_modules/@smithy/middleware-endpoint": {
- "version": "4.3.12",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.12.tgz",
- "integrity": "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.1.tgz",
+ "integrity": "sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.18.5",
- "@smithy/middleware-serde": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
- "@smithy/url-parser": "^4.2.5",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/core": "^3.20.0",
+ "@smithy/middleware-serde": "^4.2.8",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/url-parser": "^4.2.7",
+ "@smithy/util-middleware": "^4.2.7",
"tslib": "^2.6.2"
},
"engines": {
@@ -3154,18 +3168,18 @@
}
},
"node_modules/@smithy/middleware-retry": {
- "version": "4.4.12",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.12.tgz",
- "integrity": "sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ==",
+ "version": "4.4.17",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.17.tgz",
+ "integrity": "sha512-MqbXK6Y9uq17h+4r0ogu/sBT6V/rdV+5NvYL7ZV444BKfQygYe8wAhDrVXagVebN6w2RE0Fm245l69mOsPGZzg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/service-error-classification": "^4.2.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
- "@smithy/util-middleware": "^4.2.5",
- "@smithy/util-retry": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/service-error-classification": "^4.2.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
+ "@smithy/util-middleware": "^4.2.7",
+ "@smithy/util-retry": "^4.2.7",
"@smithy/uuid": "^1.1.0",
"tslib": "^2.6.2"
},
@@ -3174,13 +3188,13 @@
}
},
"node_modules/@smithy/middleware-serde": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz",
- "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==",
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.8.tgz",
+ "integrity": "sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3188,12 +3202,12 @@
}
},
"node_modules/@smithy/middleware-stack": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz",
- "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.7.tgz",
+ "integrity": "sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3201,14 +3215,14 @@
}
},
"node_modules/@smithy/node-config-provider": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz",
- "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.7.tgz",
+ "integrity": "sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.2.5",
- "@smithy/shared-ini-file-loader": "^4.4.0",
- "@smithy/types": "^4.9.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/shared-ini-file-loader": "^4.4.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3216,15 +3230,15 @@
}
},
"node_modules/@smithy/node-http-handler": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz",
- "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==",
+ "version": "4.4.7",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.7.tgz",
+ "integrity": "sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/querystring-builder": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/abort-controller": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/querystring-builder": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3232,12 +3246,12 @@
}
},
"node_modules/@smithy/property-provider": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz",
- "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.7.tgz",
+ "integrity": "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3245,12 +3259,12 @@
}
},
"node_modules/@smithy/protocol-http": {
- "version": "5.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz",
- "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==",
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.7.tgz",
+ "integrity": "sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3258,12 +3272,12 @@
}
},
"node_modules/@smithy/querystring-builder": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz",
- "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.7.tgz",
+ "integrity": "sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"@smithy/util-uri-escape": "^4.2.0",
"tslib": "^2.6.2"
},
@@ -3272,12 +3286,12 @@
}
},
"node_modules/@smithy/querystring-parser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz",
- "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.7.tgz",
+ "integrity": "sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3285,24 +3299,24 @@
}
},
"node_modules/@smithy/service-error-classification": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz",
- "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.7.tgz",
+ "integrity": "sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0"
+ "@smithy/types": "^4.11.0"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz",
- "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.2.tgz",
+ "integrity": "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3310,16 +3324,16 @@
}
},
"node_modules/@smithy/signature-v4": {
- "version": "5.3.5",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz",
- "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==",
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.7.tgz",
+ "integrity": "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg==",
"license": "Apache-2.0",
"dependencies": {
"@smithy/is-array-buffer": "^4.2.0",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-hex-encoding": "^4.2.0",
- "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-middleware": "^4.2.7",
"@smithy/util-uri-escape": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
@@ -3329,17 +3343,17 @@
}
},
"node_modules/@smithy/smithy-client": {
- "version": "4.9.8",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.8.tgz",
- "integrity": "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA==",
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.2.tgz",
+ "integrity": "sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.18.5",
- "@smithy/middleware-endpoint": "^4.3.12",
- "@smithy/middleware-stack": "^4.2.5",
- "@smithy/protocol-http": "^5.3.5",
- "@smithy/types": "^4.9.0",
- "@smithy/util-stream": "^4.5.6",
+ "@smithy/core": "^3.20.0",
+ "@smithy/middleware-endpoint": "^4.4.1",
+ "@smithy/middleware-stack": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.7",
+ "@smithy/types": "^4.11.0",
+ "@smithy/util-stream": "^4.5.8",
"tslib": "^2.6.2"
},
"engines": {
@@ -3347,9 +3361,9 @@
}
},
"node_modules/@smithy/types": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz",
- "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.11.0.tgz",
+ "integrity": "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3359,13 +3373,13 @@
}
},
"node_modules/@smithy/url-parser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz",
- "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.7.tgz",
+ "integrity": "sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/querystring-parser": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/querystring-parser": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3436,14 +3450,14 @@
}
},
"node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.3.11",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.11.tgz",
- "integrity": "sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw==",
+ "version": "4.3.16",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.16.tgz",
+ "integrity": "sha512-/eiSP3mzY3TsvUOYMeL4EqUX6fgUOj2eUOU4rMMgVbq67TiRLyxT7Xsjxq0bW3OwuzK009qOwF0L2OgJqperAQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.2.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3451,17 +3465,17 @@
}
},
"node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.2.14",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.14.tgz",
- "integrity": "sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA==",
+ "version": "4.2.19",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.19.tgz",
+ "integrity": "sha512-3a4+4mhf6VycEJyHIQLypRbiwG6aJvbQAeRAVXydMmfweEPnLLabRbdyo/Pjw8Rew9vjsh5WCdhmDaHkQnhhhA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/config-resolver": "^4.4.3",
- "@smithy/credential-provider-imds": "^4.2.5",
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/property-provider": "^4.2.5",
- "@smithy/smithy-client": "^4.9.8",
- "@smithy/types": "^4.9.0",
+ "@smithy/config-resolver": "^4.4.5",
+ "@smithy/credential-provider-imds": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/property-provider": "^4.2.7",
+ "@smithy/smithy-client": "^4.10.2",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3469,13 +3483,13 @@
}
},
"node_modules/@smithy/util-endpoints": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz",
- "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==",
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.7.tgz",
+ "integrity": "sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.3.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/node-config-provider": "^4.3.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3495,12 +3509,12 @@
}
},
"node_modules/@smithy/util-middleware": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz",
- "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.7.tgz",
+ "integrity": "sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.9.0",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3508,13 +3522,13 @@
}
},
"node_modules/@smithy/util-retry": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz",
- "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.7.tgz",
+ "integrity": "sha512-SvDdsQyF5CIASa4EYVT02LukPHVzAgUA4kMAuZ97QJc2BpAqZfA4PINB8/KOoCXEw9tsuv/jQjMeaHFvxdLNGg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/service-error-classification": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/service-error-classification": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3522,14 +3536,14 @@
}
},
"node_modules/@smithy/util-stream": {
- "version": "4.5.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz",
- "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==",
+ "version": "4.5.8",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.8.tgz",
+ "integrity": "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/fetch-http-handler": "^5.3.6",
- "@smithy/node-http-handler": "^4.4.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/fetch-http-handler": "^5.3.8",
+ "@smithy/node-http-handler": "^4.4.7",
+ "@smithy/types": "^4.11.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-buffer-from": "^4.2.0",
"@smithy/util-hex-encoding": "^4.2.0",
@@ -3566,13 +3580,13 @@
}
},
"node_modules/@smithy/util-waiter": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz",
- "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==",
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.7.tgz",
+ "integrity": "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.2.5",
- "@smithy/types": "^4.9.0",
+ "@smithy/abort-controller": "^4.2.7",
+ "@smithy/types": "^4.11.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3740,9 +3754,9 @@
}
},
"node_modules/@types/node": {
- "version": "24.10.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
- "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
+ "version": "25.0.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
+ "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4266,9 +4280,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.8.31",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz",
- "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==",
+ "version": "2.9.11",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
+ "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4370,9 +4384,9 @@
}
},
"node_modules/bowser": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.0.tgz",
- "integrity": "sha512-yHAbSRuT6LTeKi6k2aS40csueHqgAsFEgmrOsfRyFpJnFv5O2hl9FYmWEUZ97gZ/dG17U4IQQcTx4YAFYPuWRQ==",
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz",
+ "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==",
"license": "MIT"
},
"node_modules/brace-expansion": {
@@ -4400,9 +4414,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.28.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
- "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
"dev": true,
"funding": [
{
@@ -4421,11 +4435,11 @@
"license": "MIT",
"peer": true,
"dependencies": {
- "baseline-browser-mapping": "^2.8.25",
- "caniuse-lite": "^1.0.30001754",
- "electron-to-chromium": "^1.5.249",
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
"node-releases": "^2.0.27",
- "update-browserslist-db": "^1.1.4"
+ "update-browserslist-db": "^1.2.0"
},
"bin": {
"browserslist": "cli.js"
@@ -4621,9 +4635,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001757",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
- "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
+ "version": "1.0.30001762",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz",
+ "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==",
"dev": true,
"funding": [
{
@@ -5115,9 +5129,9 @@
}
},
"node_modules/dedent": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz",
- "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
+ "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -5345,9 +5359,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
- "version": "1.5.262",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz",
- "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==",
+ "version": "1.5.267",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
+ "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
"dev": true,
"license": "ISC"
},
@@ -5385,6 +5399,30 @@
"node": ">= 0.8"
}
},
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
@@ -5621,9 +5659,9 @@
}
},
"node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -5883,9 +5921,9 @@
}
},
"node_modules/fastq": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
- "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5941,17 +5979,17 @@
}
},
"node_modules/finalhandler": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
- "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
- "on-finished": "2.4.1",
+ "on-finished": "~2.4.1",
"parseurl": "~1.3.3",
- "statuses": "2.0.1",
+ "statuses": "~2.0.2",
"unpipe": "~1.0.0"
},
"engines": {
@@ -6578,19 +6616,23 @@
"optional": true
},
"node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/http-proxy-agent": {
@@ -6693,9 +6735,9 @@
}
},
"node_modules/iconv-lite": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
- "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
+ "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -7768,12 +7810,12 @@
}
},
"node_modules/jsonwebtoken": {
- "version": "9.0.2",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
- "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
+ "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
"license": "MIT",
"dependencies": {
- "jws": "^3.2.2",
+ "jws": "^4.0.1",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
@@ -7802,9 +7844,9 @@
}
},
"node_modules/jwa": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
- "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "^1.0.1",
@@ -7813,12 +7855,12 @@
}
},
"node_modules/jws": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
- "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
"license": "MIT",
"dependencies": {
- "jwa": "^1.4.2",
+ "jwa": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
@@ -8810,9 +8852,9 @@
"license": "MIT"
},
"node_modules/nodemailer": {
- "version": "7.0.11",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.11.tgz",
- "integrity": "sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==",
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.12.tgz",
+ "integrity": "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
@@ -9227,10 +9269,10 @@
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
- "version": "11.2.2",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz",
- "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==",
- "license": "ISC",
+ "version": "11.2.4",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz",
+ "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==",
+ "license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
@@ -9472,9 +9514,9 @@
}
},
"node_modules/postgres-bytea": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
- "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
+ "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -9729,35 +9771,6 @@
"node": ">= 0.10"
}
},
- "node_modules/raw-body/node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/raw-body/node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -9783,9 +9796,9 @@
}
},
"node_modules/react": {
- "version": "19.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
- "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
+ "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
"peer": true,
"engines": {
@@ -10089,24 +10102,24 @@
}
},
"node_modules/send": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
- "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
"mime": "1.6.0",
"ms": "2.1.3",
- "on-finished": "2.4.1",
+ "on-finished": "~2.4.1",
"range-parser": "~1.2.1",
- "statuses": "2.0.1"
+ "statuses": "~2.0.2"
},
"engines": {
"node": ">= 0.8.0"
@@ -10127,25 +10140,16 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
- "node_modules/send/node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/serve-static": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
- "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
"license": "MIT",
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.19.0"
+ "send": "~0.19.1"
},
"engines": {
"node": ">= 0.8.0"
@@ -10601,9 +10605,9 @@
}
},
"node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -10774,9 +10778,9 @@
}
},
"node_modules/strnum": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz",
- "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz",
+ "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==",
"funding": [
{
"type": "github",
@@ -11203,9 +11207,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
- "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
"dev": true,
"funding": [
{
@@ -11287,9 +11291,9 @@
}
},
"node_modules/validator": {
- "version": "13.15.23",
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz",
- "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==",
+ "version": "13.15.26",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
+ "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
@@ -11387,9 +11391,9 @@
}
},
"node_modules/winston": {
- "version": "3.18.3",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz",
- "integrity": "sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==",
+ "version": "3.19.0",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz",
+ "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==",
"license": "MIT",
"dependencies": {
"@colors/colors": "^1.6.0",
diff --git a/backend/scripts/check-storage.js b/backend/scripts/check-storage.js
old mode 100755
new mode 100644
diff --git a/backend/scripts/cleanup-thumbnails.js b/backend/scripts/cleanup-thumbnails.js
old mode 100755
new mode 100644
diff --git a/backend/scripts/create-admin.js b/backend/scripts/create-admin.js
old mode 100755
new mode 100644
diff --git a/backend/scripts/migrate-upload-assets.js b/backend/scripts/migrate-upload-assets.js
old mode 100755
new mode 100644
diff --git a/backend/scripts/regenerate-thumbnails.js b/backend/scripts/regenerate-thumbnails.js
old mode 100755
new mode 100644
diff --git a/backend/scripts/reset-admin-password.js b/backend/scripts/reset-admin-password.js
old mode 100755
new mode 100644
diff --git a/backend/src/routes/adminEvents.js b/backend/src/routes/adminEvents.js
index 0b136d10..23b55341 100644
--- a/backend/src/routes/adminEvents.js
+++ b/backend/src/routes/adminEvents.js
@@ -533,7 +533,7 @@ router.put('/:id', adminAuth, [
body('welcome_message').optional({ nullable: true, checkFalsy: true }).trim(),
body('color_theme').optional({ nullable: true }),
body('allow_user_uploads').optional().isBoolean(),
- body('customer_name').optional().trim().notEmpty(),
+ body('customer_name').optional({ nullable: true, checkFalsy: true }).trim(),
body('customer_email').optional().isEmail().normalizeEmail(),
body('upload_category_id').optional().custom((value) => {
// Accept null, undefined, or integer values
@@ -554,6 +554,13 @@ router.put('/:id', adminAuth, [
body('source_mode').optional().isIn(['managed', 'reference']),
body('external_path').optional({ nullable: true }).isString().trim(),
body('require_password').optional().isBoolean(),
+ // Download protection settings
+ body('protection_level').optional().isIn(['basic', 'standard', 'enhanced', 'maximum']),
+ body('enable_devtools_protection').optional().isBoolean(),
+ body('use_canvas_rendering').optional().isBoolean(),
+ body('overlay_protection').optional().isBoolean(),
+ body('image_quality').optional().isInt({ min: 1, max: 100 }),
+ body('fragmentation_level').optional().isInt({ min: 1, max: 10 }),
body('password').optional().isString().custom((value, { req }) => {
if (value === undefined || value === null || value === '') {
return true;
diff --git a/backend/src/routes/adminImageSecurity.js b/backend/src/routes/adminImageSecurity.js
index 75d370f8..b0d58564 100644
--- a/backend/src/routes/adminImageSecurity.js
+++ b/backend/src/routes/adminImageSecurity.js
@@ -31,13 +31,15 @@ router.get('/settings', adminAuth, async (req, res) => {
const config = {};
settings.forEach(setting => {
- config[setting.setting_key] = JSON.parse(setting.setting_value);
+ // PostgreSQL JSON columns are already parsed by the driver
+ // Just use the value directly - no need to JSON.parse
+ config[setting.setting_key] = setting.setting_value;
});
res.json(config);
} catch (error) {
- logger.error('Error getting image security settings', { error: error.message });
- res.status(500).json({ error: 'Failed to get security settings' });
+ logger.error('Error getting image security settings', { error: error.message, stack: error.stack });
+ res.status(500).json({ error: 'Failed to get security settings', details: error.message });
}
});
diff --git a/backend/src/routes/gallery.js b/backend/src/routes/gallery.js
index 08e98c7e..4cc63c0f 100644
--- a/backend/src/routes/gallery.js
+++ b/backend/src/routes/gallery.js
@@ -110,7 +110,9 @@ router.get('/:slug/info', async (req, res) => {
'watermark_downloads',
'watermark_text',
'require_password',
- 'color_theme'
+ 'color_theme',
+ 'enable_devtools_protection',
+ 'use_canvas_rendering'
)
.first();
@@ -154,7 +156,9 @@ router.get('/:slug/info', async (req, res) => {
allow_downloads: !(event.allow_downloads === false || event.allow_downloads === 0 || event.allow_downloads === '0'),
disable_right_click: event.disable_right_click === true || event.disable_right_click === 1 || event.disable_right_click === '1',
watermark_downloads: event.watermark_downloads === true || event.watermark_downloads === 1 || event.watermark_downloads === '1',
- watermark_text: event.watermark_text
+ watermark_text: event.watermark_text,
+ enable_devtools_protection: event.enable_devtools_protection === true || event.enable_devtools_protection === 1 || event.enable_devtools_protection === '1',
+ use_canvas_rendering: event.use_canvas_rendering === true || event.use_canvas_rendering === 1 || event.use_canvas_rendering === '1'
});
} catch (error) {
console.error('Error fetching gallery info:', error);
@@ -315,6 +319,8 @@ router.get('/:slug/photos', verifyGalleryAccess, async (req, res) => {
disable_right_click: req.event.disable_right_click === true,
watermark_downloads: req.event.watermark_downloads === true,
watermark_text: req.event.watermark_text,
+ enable_devtools_protection: req.event.enable_devtools_protection === true,
+ use_canvas_rendering: req.event.use_canvas_rendering === true,
...protectionSettings
},
categories: categories,
@@ -397,19 +403,27 @@ router.get('/:slug/download/:photoId', verifyGalleryAccess, async (req, res) =>
return res.status(404).json({ error: 'Photo file not found' });
}
- // Get watermark settings
+ // Get watermark settings - apply if global setting OR event-level setting is enabled
const watermarkSettings = await watermarkService.getWatermarkSettings();
-
- if (watermarkSettings && watermarkSettings.enabled) {
+ const eventWatermarkEnabled = req.event.watermark_downloads === true || req.event.watermark_downloads === 1;
+ const shouldApplyWatermark = (watermarkSettings && watermarkSettings.enabled) || eventWatermarkEnabled;
+
+ if (shouldApplyWatermark) {
// Apply watermark and send
- const watermarkedBuffer = await watermarkService.applyWatermark(filePath, watermarkSettings);
-
+ // Use event watermark text if available, otherwise fall back to global settings
+ const effectiveSettings = {
+ ...watermarkSettings,
+ enabled: true,
+ text: req.event.watermark_text || watermarkSettings?.text || 'Protected'
+ };
+ const watermarkedBuffer = await watermarkService.applyWatermark(filePath, effectiveSettings);
+
res.set({
'Content-Type': photo.mime_type || 'image/jpeg',
'Content-Disposition': `attachment; filename="${photo.filename}"`,
'Content-Length': watermarkedBuffer.length
});
-
+
res.send(watermarkedBuffer);
} else {
// Send original file
@@ -468,9 +482,16 @@ router.get('/:slug/download-all', verifyGalleryAccess, async (req, res) => {
archive.pipe(res);
- // Get watermark settings
+ // Get watermark settings - apply if global setting OR event-level setting is enabled
const watermarkSettings = await watermarkService.getWatermarkSettings();
-
+ const eventWatermarkEnabled = req.event.watermark_downloads === true || req.event.watermark_downloads === 1;
+ const shouldApplyWatermark = (watermarkSettings && watermarkSettings.enabled) || eventWatermarkEnabled;
+ const effectiveSettings = shouldApplyWatermark ? {
+ ...watermarkSettings,
+ enabled: true,
+ text: req.event.watermark_text || watermarkSettings?.text || 'Protected'
+ } : null;
+
// Add photos to archive
for (const photo of photos) {
let filePath;
@@ -485,7 +506,7 @@ router.get('/:slug/download-all', verifyGalleryAccess, async (req, res) => {
});
continue;
}
-
+
// Determine the file name in the archive
let archiveName;
if (hasMultipleTypes) {
@@ -496,10 +517,10 @@ router.get('/:slug/download-all', verifyGalleryAccess, async (req, res) => {
// No folders, just the filename
archiveName = photo.filename;
}
-
- if (watermarkSettings && watermarkSettings.enabled) {
+
+ if (shouldApplyWatermark && effectiveSettings) {
try {
- const watermarkedBuffer = await watermarkService.applyWatermark(filePath, watermarkSettings);
+ const watermarkedBuffer = await watermarkService.applyWatermark(filePath, effectiveSettings);
archive.append(watermarkedBuffer, { name: archiveName });
} catch (watermarkError) {
logger.warn('Failed to watermark photo for bulk download, skipping original to avoid leak', {
@@ -586,15 +607,23 @@ router.post('/:slug/download-selected', verifyGalleryAccess, async (req, res) =>
});
archive.pipe(res);
- // Check watermark settings similar to download-all
+ // Check watermark settings - apply if global setting OR event-level setting is enabled
const watermarkSettings = await watermarkService.getWatermarkSettings();
+ const eventWatermarkEnabled = req.event.watermark_downloads === true || req.event.watermark_downloads === 1;
+ const shouldApplyWatermark = (watermarkSettings && watermarkSettings.enabled) || eventWatermarkEnabled;
+ const effectiveSettings = shouldApplyWatermark ? {
+ ...watermarkSettings,
+ enabled: true,
+ text: req.event.watermark_text || watermarkSettings?.text || 'Protected'
+ } : null;
+
for (const photo of photos) {
try {
const filePath = resolvePhotoFilePath(req.event, photo);
const name = photo.filename || `photo-${photo.id}.jpg`;
- if (watermarkSettings && watermarkSettings.enabled) {
+ if (shouldApplyWatermark && effectiveSettings) {
try {
- const watermarkedBuffer = await watermarkService.applyWatermark(filePath, watermarkSettings);
+ const watermarkedBuffer = await watermarkService.applyWatermark(filePath, effectiveSettings);
archive.append(watermarkedBuffer, { name });
} catch (watermarkError) {
logger.warn('Failed to watermark selected photo, skipping original to avoid leak', {
diff --git a/docs/REFACTORING_PLAN.md b/docs/REFACTORING_PLAN.md
deleted file mode 100644
index c7f055ff..00000000
--- a/docs/REFACTORING_PLAN.md
+++ /dev/null
@@ -1,1744 +0,0 @@
-# PicPeak Comprehensive Refactoring Plan
-
-> **Version**: 1.0
-> **Created**: January 2026
-> **Status**: Approved for Implementation
-> **Architecture Goal**: Clean Architecture with Domain-Driven Design principles
-
----
-
-## Table of Contents
-
-1. [Executive Summary](#executive-summary)
-2. [Current Architecture Analysis](#current-architecture-analysis)
-3. [Target Architecture Vision](#target-architecture-vision)
-4. [Phase 1: Code Duplication Elimination](#phase-1-code-duplication-elimination)
-5. [Phase 2: Backend Route & Service Refactoring](#phase-2-backend-route--service-refactoring)
-6. [Phase 3: Frontend Page Decomposition](#phase-3-frontend-page-decomposition)
-7. [Phase 4: Cross-Cutting Concerns](#phase-4-cross-cutting-concerns)
-8. [Testing Strategy](#testing-strategy)
-9. [Migration & Rollback Plan](#migration--rollback-plan)
-10. [Implementation Checklist](#implementation-checklist)
-
----
-
-## Executive Summary
-
-### Scope
-This refactoring addresses **20+ files** totaling over **15,000 lines of code** that have grown beyond maintainable sizes or contain duplicated logic. The goal is to achieve world-class architecture following Clean Architecture and SOLID principles.
-
-### Key Outcomes
-- **50%+ reduction** in average file size for targeted files
-- **Zero code duplication** for utility functions
-- **Clear separation of concerns** between routes, services, and domain logic
-- **Improved testability** with dependency injection and smaller units
-- **Better developer experience** with intuitive file organization
-
-### Risk Mitigation
-- All changes are backwards-compatible
-- Each phase can be deployed independently
-- Comprehensive test coverage required before each merge
-- Feature flags for gradual rollout where applicable
-
----
-
-## Current Architecture Analysis
-
-### Backend Issues
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ CURRENT STATE │
-├─────────────────────────────────────────────────────────────┤
-│ Routes (1000+ lines each) │
-│ ┌─────────────────┐ ┌─────────────────┐ │
-│ │ adminEvents.js │ │ adminSettings.js│ │
-│ │ 1,088 lines │ │ 1,056 lines │ │
-│ │ - HTTP handlers │ │ - HTTP handlers │ │
-│ │ - Business logic│ │ - Business logic│ │
-│ │ - DB queries │ │ - File uploads │ │
-│ │ - Validation │ │ - Validation │ │
-│ │ - Helpers │ │ - Multer config │ │
-│ └─────────────────┘ └─────────────────┘ │
-│ │
-│ Services (1000+ lines each) │
-│ ┌─────────────────┐ ┌─────────────────┐ │
-│ │ backupService │ │ restoreService │ │
-│ │ 1,120 lines │ │ 1,220 lines │ │
-│ │ - Scheduling │ │ - Validation │ │
-│ │ - Execution │ │ - Execution │ │
-│ │ - S3 upload │ │ - Rollback │ │
-│ │ - Notifications │ │ - Logging │ │
-│ └─────────────────┘ └─────────────────┘ │
-│ │
-│ PROBLEMS: │
-│ ✗ Business logic in route handlers │
-│ ✗ No service layer abstraction for events/photos │
-│ ✗ Duplicate utility functions across files │
-│ ✗ God objects with too many responsibilities │
-└─────────────────────────────────────────────────────────────┘
-```
-
-### Frontend Issues
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ CURRENT STATE │
-├─────────────────────────────────────────────────────────────┤
-│ Pages (1000+ lines each) │
-│ ┌─────────────────┐ ┌─────────────────┐ │
-│ │ SettingsPage │ │EventDetailsPage │ │
-│ │ 1,839 lines │ │ 1,479 lines │ │
-│ │ - 27 hooks │ │ - 33 hooks │ │
-│ │ - 8 tab sections│ │ - Photo grid │ │
-│ │ - All mutations │ │ - Event editing │ │
-│ │ - All queries │ │ - Theme config │ │
-│ └─────────────────┘ └─────────────────┘ │
-│ │
-│ Duplicate Files │
-│ ┌─────────────────┐ ┌─────────────────┐ │
-│ │CreateEventPage │ │ CMSPage.tsx │ │
-│ │CreateEventPage │ │ CMSPageEnhanced │ │
-│ │ Enhanced │ │ │ │
-│ └─────────────────┘ └─────────────────┘ │
-│ │
-│ PROBLEMS: │
-│ ✗ Mega-components with 20+ hooks │
-│ ✗ Multiple duplicate page implementations │
-│ ✗ No custom hooks for shared logic │
-│ ✗ Mixed concerns in single components │
-└─────────────────────────────────────────────────────────────┘
-```
-
-### Code Duplication Map
-
-| Function/Pattern | Locations | Lines Duplicated |
-|-----------------|-----------|------------------|
-| `parseBooleanInput` | 3 files | ~60 lines |
-| Auth routes | 3 versions | ~900 lines |
-| CreateEvent pages | 2 versions | ~1,400 lines |
-| CMS pages | 2 versions | ~1,100 lines |
-| Multer config | 4+ files | ~200 lines |
-
----
-
-## Target Architecture Vision
-
-### Backend Target Architecture
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ TARGET STATE │
-├─────────────────────────────────────────────────────────────┤
-│ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ ROUTES LAYER │ │
-│ │ (Thin controllers - HTTP handling only) │ │
-│ │ ~100-200 lines per file │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ SERVICES LAYER │ │
-│ │ (Business logic orchestration) │ │
-│ │ ~200-400 lines per file │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │EventService │ │PhotoService │ │SettingsServ │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ DOMAIN LAYER │ │
-│ │ (Pure business logic, no I/O) │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │ Validators │ │ Transformers│ │ Factories │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ INFRASTRUCTURE LAYER │ │
-│ │ (Database, File System, External APIs) │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │Repositories │ │ FileStorage │ │ S3Adapter │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ SHARED UTILITIES │ │
-│ │ (Pure functions, zero side effects) │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │ parsers.js │ │validators.js│ │formatters.js│ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │
-└─────────────────────────────────────────────────────────────┘
-```
-
-### Frontend Target Architecture
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ TARGET STATE │
-├─────────────────────────────────────────────────────────────┤
-│ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ PAGES │ │
-│ │ (Route components - composition only) │ │
-│ │ ~100-200 lines per file │ │
-│ │ ┌─────────────────────────────────────────────┐ │ │
-│ │ │ SettingsPage.tsx │ │ │
-│ │ │ │ │ │
-│ │ │ │ │ │
-│ │ │ │ │ │
-│ │ │ │ │ │
-│ │ │ ... │ │ │
-│ │ │ │ │ │
-│ │ └─────────────────────────────────────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ FEATURES │ │
-│ │ (Feature-specific components with hooks) │ │
-│ │ ~200-400 lines per file │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │ settings/ │ │ events/ │ │ photos/ │ │ │
-│ │ │ ├─ tabs/ │ │ ├─ editor/ │ │ ├─ grid/ │ │ │
-│ │ │ ├─ hooks/ │ │ ├─ viewer/ │ │ ├─ viewer/ │ │ │
-│ │ │ └─ index.ts │ │ └─ hooks/ │ │ └─ export/ │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ SHARED COMPONENTS │ │
-│ │ (Reusable UI primitives) │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │ common/ │ │ forms/ │ │ layout/ │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────────┐ │
-│ │ SHARED HOOKS │ │
-│ │ (Reusable stateful logic) │ │
-│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
-│ │ │useSettings │ │ usePhotos │ │ useEvents │ │ │
-│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
-│ └─────────────────────────────────────────────────────┘ │
-│ │
-└─────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Phase 1: Code Duplication Elimination
-
-> **Priority**: CRITICAL
-> **Estimated Effort**: 2-3 days
-> **Risk**: Low
-> **Dependencies**: None
-
-### 1.1 Extract Shared Parsers Utility
-
-**Problem**: `parseBooleanInput` function duplicated in 3 files
-
-**Files Affected**:
-- `backend/src/routes/adminEvents.js` (lines 61-81)
-- `backend/src/routes/events.js` (lines 14-34)
-- `frontend/src/pages/admin/SettingsPage.tsx` (lines 33-52, named `toBoolean`)
-
-**Solution**: Create unified parser utilities
-
-#### Backend Implementation
-
-**Create**: `backend/src/utils/parsers.js`
-
-```javascript
-/**
- * Shared Parser Utilities
- * Pure functions for parsing and transforming input values
- */
-
-/**
- * Parse any input value to boolean with configurable default
- * @param {*} value - Input value to parse
- * @param {boolean} defaultValue - Default if value is undefined/null
- * @returns {boolean}
- */
-const parseBooleanInput = (value, defaultValue = true) => {
- if (value === undefined || value === null) {
- return defaultValue;
- }
- if (typeof value === 'boolean') {
- return value;
- }
- if (typeof value === 'number') {
- if (Number.isNaN(value)) return defaultValue;
- return value !== 0;
- }
- if (typeof value === 'string') {
- const normalized = value.trim().toLowerCase();
- if (['false', '0', 'no', 'off', ''].includes(normalized)) {
- return false;
- }
- if (['true', '1', 'yes', 'on'].includes(normalized)) {
- return true;
- }
- }
- return defaultValue;
-};
-
-/**
- * Parse numeric input with validation
- * @param {*} value - Input value to parse
- * @param {number} defaultValue - Default if invalid
- * @param {Object} options - Min/max bounds
- * @returns {number}
- */
-const parseNumberInput = (value, defaultValue, { min, max } = {}) => {
- if (value === undefined || value === null || value === '') {
- return defaultValue;
- }
- const parsed = Number(value);
- if (!Number.isFinite(parsed)) {
- return defaultValue;
- }
- if (min !== undefined && parsed < min) return min;
- if (max !== undefined && parsed > max) return max;
- return parsed;
-};
-
-/**
- * Parse string input with trimming and null handling
- * @param {*} value - Input value
- * @param {string|null} defaultValue - Default if empty
- * @returns {string|null}
- */
-const parseStringInput = (value, defaultValue = null) => {
- if (value === undefined || value === null) {
- return defaultValue;
- }
- if (typeof value === 'string') {
- const trimmed = value.trim();
- return trimmed || defaultValue;
- }
- return String(value);
-};
-
-/**
- * Parse JSON string safely
- * @param {*} value - JSON string or already parsed value
- * @param {*} defaultValue - Default if parsing fails
- * @returns {*}
- */
-const parseJsonInput = (value, defaultValue = null) => {
- if (value === undefined || value === null) {
- return defaultValue;
- }
- if (typeof value !== 'string') {
- return value; // Already parsed
- }
- try {
- return JSON.parse(value);
- } catch {
- return defaultValue;
- }
-};
-
-module.exports = {
- parseBooleanInput,
- parseNumberInput,
- parseStringInput,
- parseJsonInput
-};
-```
-
-#### Frontend Implementation
-
-**Create**: `frontend/src/utils/parsers.ts`
-
-```typescript
-/**
- * Shared Parser Utilities for Frontend
- */
-
-/**
- * Parse any input value to boolean with configurable default
- */
-export const toBoolean = (value: unknown, defaultValue = false): boolean => {
- if (value === undefined || value === null) {
- return defaultValue;
- }
- if (typeof value === 'boolean') {
- return value;
- }
- if (typeof value === 'number') {
- if (Number.isNaN(value)) return defaultValue;
- return value !== 0;
- }
- if (typeof value === 'string') {
- const normalized = value.toLowerCase().trim();
- if (['true', '1', 'yes', 'on'].includes(normalized)) return true;
- if (['false', '0', 'no', 'off', ''].includes(normalized)) return false;
- }
- return defaultValue;
-};
-
-/**
- * Parse numeric input with validation
- */
-export const toNumber = (
- value: unknown,
- defaultValue: number,
- options?: { min?: number; max?: number }
-): number => {
- if (value === undefined || value === null || value === '') {
- return defaultValue;
- }
- const parsed = Number(value);
- if (!Number.isFinite(parsed)) {
- return defaultValue;
- }
- if (options?.min !== undefined && parsed < options.min) return options.min;
- if (options?.max !== undefined && parsed > options.max) return options.max;
- return parsed;
-};
-```
-
-#### Migration Steps
-
-1. Create new utility files
-2. Add comprehensive unit tests for all parser functions
-3. Update imports in affected files one at a time:
- - `adminEvents.js`: Replace inline function with import
- - `events.js`: Replace inline function with import
- - `SettingsPage.tsx`: Replace inline function with import
-4. Remove duplicate function definitions
-5. Run full test suite
-6. Deploy
-
----
-
-### 1.2 Consolidate Auth Routes
-
-**Problem**: Three versions of auth routes exist
-
-**Files**:
-- `backend/src/routes/auth.js` (136 lines) - Basic version
-- `backend/src/routes/auth-enhanced.js` (395 lines) - Enhanced v1
-- `backend/src/routes/auth-enhanced-v2.js` (393 lines) - Enhanced v2
-
-**Analysis Required**:
-```bash
-# Determine which version is actively used
-grep -r "auth-enhanced" backend/src/ --include="*.js"
-grep -r "auth.js" backend/src/ --include="*.js"
-```
-
-**Solution**: Consolidate into single `auth.js`
-
-#### Implementation Plan
-
-1. **Audit Current Usage**
- - Identify which auth file is mounted in `server.js`
- - Document all endpoints from each version
- - Create feature comparison matrix
-
-2. **Merge Strategy**
- ```
- auth.js (NEW - Consolidated)
- ├── All endpoints from auth-enhanced-v2.js (active version)
- ├── Any unique endpoints from other versions
- └── Deprecated endpoints marked for removal
- ```
-
-3. **Create Feature Flags** (if needed)
- ```javascript
- // config/features.js
- module.exports = {
- AUTH_USE_ENHANCED_TOKENS: true,
- AUTH_REQUIRE_EMAIL_VERIFICATION: false,
- };
- ```
-
-4. **Migration Steps**
- - Create new consolidated `auth.js`
- - Update `server.js` to use new auth routes
- - Keep old files temporarily with deprecation notices
- - Monitor for errors in production
- - Remove deprecated files after 2 weeks
-
----
-
-### 1.3 Consolidate CreateEvent Pages
-
-**Problem**: Two nearly identical event creation pages
-
-**Files**:
-- `frontend/src/pages/admin/CreateEventPage.tsx` (709 lines)
-- `frontend/src/pages/admin/CreateEventPageEnhanced.tsx` (709 lines)
-
-**Solution**: Single `CreateEventPage.tsx` with all features
-
-#### Difference Analysis
-
-| Feature | Standard | Enhanced |
-|---------|----------|----------|
-| Basic form fields | ✓ | ✓ |
-| Theme customizer | ✓ | ✓ |
-| Password generator | ✓ | ✓ |
-| Advanced validation | ? | ✓ |
-| Auto-save draft | ? | ✓ |
-
-#### Implementation Plan
-
-1. **Diff the files** to identify exact differences:
- ```bash
- diff -u CreateEventPage.tsx CreateEventPageEnhanced.tsx > event_pages_diff.txt
- ```
-
-2. **Merge enhanced features into standard page**
-
-3. **Extract shared logic into custom hooks**:
- ```typescript
- // hooks/useEventForm.ts
- export function useEventForm(initialData?: Partial) {
- // Form state management
- // Validation logic
- // Submit handlers
- }
-
- // hooks/useEventDraft.ts
- export function useEventDraft(eventData: Partial) {
- // Auto-save logic
- // Draft recovery
- }
- ```
-
-4. **Update router to use single page**
-
-5. **Delete duplicate file**
-
----
-
-### 1.4 Consolidate CMS Pages
-
-**Problem**: Two CMS page implementations
-
-**Files**:
-- `frontend/src/pages/admin/CMSPage.tsx` (538 lines)
-- `frontend/src/pages/admin/CMSPageEnhanced.tsx` (618 lines)
-
-**Enhanced Features**:
-- Auto-save functionality
-- Unsaved changes warning
-- Enhanced editor toolbar
-
-**Solution**: Single `CMSPage.tsx` with optional features
-
-#### Implementation Plan
-
-1. **Create feature-complete CMSPage.tsx**:
- ```typescript
- interface CMSPageProps {
- enableAutoSave?: boolean;
- enableUnsavedWarning?: boolean;
- }
-
- export const CMSPage: React.FC = ({
- enableAutoSave = true,
- enableUnsavedWarning = true
- }) => {
- // Merged implementation
- };
- ```
-
-2. **Extract reusable hooks**:
- ```typescript
- // hooks/useAutoSave.ts
- export function useAutoSave(
- data: T,
- saveFn: (data: T) => Promise,
- debounceMs = 2000
- ) { ... }
-
- // hooks/useUnsavedChanges.ts
- export function useUnsavedChanges(hasChanges: boolean) { ... }
- ```
-
-3. **Delete duplicate file**
-
----
-
-### 1.5 Extract Multer Configuration Factory
-
-**Problem**: Multer storage configuration duplicated across multiple route files
-
-**Files with Multer configs**:
-- `adminPhotos.js`
-- `adminSettings.js`
-- `adminEvents.js`
-- `protectedImages.js`
-
-**Solution**: Centralized multer configuration factory
-
-#### Implementation
-
-**Create**: `backend/src/config/multerConfig.js`
-
-```javascript
-const multer = require('multer');
-const path = require('path');
-const crypto = require('crypto');
-const fs = require('fs').promises;
-
-/**
- * Create disk storage configuration
- * @param {Object} options
- * @param {string} options.destination - Upload directory path
- * @param {Function} options.filenameGenerator - Custom filename generator
- */
-const createDiskStorage = ({ destination, filenameGenerator }) => {
- return multer.diskStorage({
- destination: async (req, file, cb) => {
- try {
- await fs.mkdir(destination, { recursive: true });
- cb(null, destination);
- } catch (error) {
- cb(error);
- }
- },
- filename: filenameGenerator || ((req, file, cb) => {
- const uniqueSuffix = `${Date.now()}-${crypto.randomBytes(6).toString('hex')}`;
- const ext = path.extname(file.originalname).toLowerCase();
- cb(null, `${uniqueSuffix}${ext}`);
- })
- });
-};
-
-/**
- * Create multer upload instance with standard limits
- * @param {Object} options
- * @param {multer.StorageEngine} options.storage - Multer storage engine
- * @param {number} options.maxFileSize - Max file size in bytes (default 50MB)
- * @param {string[]} options.allowedMimeTypes - Allowed MIME types
- * @param {number} options.maxFiles - Max files per request (default 100)
- */
-const createUpload = ({
- storage,
- maxFileSize = 50 * 1024 * 1024,
- allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'],
- maxFiles = 100
-}) => {
- return multer({
- storage,
- limits: {
- fileSize: maxFileSize,
- files: maxFiles
- },
- fileFilter: (req, file, cb) => {
- if (allowedMimeTypes.includes(file.mimetype)) {
- cb(null, true);
- } else {
- cb(new Error(`File type ${file.mimetype} not allowed`));
- }
- }
- });
-};
-
-/**
- * Pre-configured uploads for common use cases
- */
-const uploads = {
- photos: (storagePath) => createUpload({
- storage: createDiskStorage({ destination: storagePath }),
- allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp', 'video/mp4', 'video/webm', 'video/quicktime'],
- maxFiles: 500
- }),
-
- logos: (storagePath) => createUpload({
- storage: createDiskStorage({ destination: storagePath }),
- allowedMimeTypes: ['image/jpeg', 'image/png', 'image/svg+xml', 'image/webp'],
- maxFileSize: 5 * 1024 * 1024,
- maxFiles: 1
- }),
-
- general: (storagePath) => createUpload({
- storage: createDiskStorage({ destination: storagePath })
- })
-};
-
-module.exports = {
- createDiskStorage,
- createUpload,
- uploads
-};
-```
-
----
-
-## Phase 2: Backend Route & Service Refactoring
-
-> **Priority**: HIGH
-> **Estimated Effort**: 5-7 days
-> **Risk**: Medium
-> **Dependencies**: Phase 1 complete
-
-### 2.1 Create Event Service Layer
-
-**Current**: `adminEvents.js` (1,088 lines) with business logic in route handlers
-
-**Target**: Thin routes + dedicated EventService
-
-#### New File Structure
-
-```
-backend/src/
-├── routes/
-│ └── adminEvents.js # ~200 lines (HTTP only)
-├── services/
-│ └── events/
-│ ├── index.js # Public exports
-│ ├── eventService.js # Main service (~300 lines)
-│ ├── eventValidator.js # Validation logic (~100 lines)
-│ ├── eventMapper.js # Data transformation (~80 lines)
-│ └── eventRepository.js # Database queries (~150 lines)
-└── utils/
- └── parsers.js # Shared parsers
-```
-
-#### EventService Implementation
-
-**Create**: `backend/src/services/events/eventService.js`
-
-```javascript
-const { db, logActivity } = require('../../database/db');
-const eventRepository = require('./eventRepository');
-const eventValidator = require('./eventValidator');
-const eventMapper = require('./eventMapper');
-const { queueEmail } = require('../emailProcessor');
-const { buildShareLinkVariants } = require('../shareLinkService');
-const logger = require('../../utils/logger');
-
-class EventService {
- /**
- * Create a new event
- * @param {Object} eventData - Event creation data
- * @param {Object} admin - Admin user creating the event
- * @returns {Promise