diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
deleted file mode 100644
index 6950f36..0000000
--- a/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,47 +0,0 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the
-// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
-{
- "name": "Existing Docker Compose (Extend)",
-
- // Update the 'dockerComposeFile' list if you have more compose files or use different names.
- // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
- "dockerComposeFile": [
- "../docker-compose.yml",
- "docker-compose.yml"
- ],
-
- // The 'service' property is the name of the service for the container that VS Code should
- // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
- "service": "dev",
-
- // The optional 'workspaceFolder' property is the path VS Code should open by default when
- // connected. This is typically a file mount in .devcontainer/docker-compose.yml
- "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
- "features": {
- "ghcr.io/devcontainers/features/git:1": {},
- "ghcr.io/devcontainers/features/node:1": {},
- "ghcr.io/devcontainers/features/python:1": {},
- "ghcr.io/davzucky/devcontainers-features-wolfi/docker-outside-of-docker:1": {}
- }
-
- // Features to add to the dev container. More info: https://containers.dev/features.
- // "features": {},
-
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
- // "forwardPorts": [],
-
- // Uncomment the next line if you want start specific services in your Docker Compose config.
- // "runServices": [],
-
- // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
- // "shutdownAction": "none",
-
- // Uncomment the next line to run commands after the container is created.
- // "postCreateCommand": "cat /etc/os-release",
-
- // Configure tool-specific properties.
- // "customizations": {},
-
- // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
- // "remoteUser": "devcontainer"
-}
diff --git a/.devcontainer/docker-compose.extend.yml b/.devcontainer/docker-compose.extend.yml
deleted file mode 100644
index 68d7cd4..0000000
--- a/.devcontainer/docker-compose.extend.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-services:
- app:
- cap_add:
- - SYS_PTRACE
- command: sleep infinity
- init: true
- security_opt:
- - seccomp:unconfined
-version: '3.8'
diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
deleted file mode 100644
index 2c1188e..0000000
--- a/.devcontainer/docker-compose.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-version: '3.8'
-services:
- # Update this to the name of the service you want to work with in your docker-compose.yml file
- dev:
- # Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
- # folder. Note that the path of the Dockerfile and context is relative to the *primary*
- # docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
- # array). The sample below assumes your primary file is in the root of your project.
- #
- # build:
- # context: .
- # dockerfile: .devcontainer/Dockerfile
-
- volumes:
- # Update this to wherever you want VS Code to mount the folder of your project
- - ..:/workspaces:cached
-
- # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
- # cap_add:
- # - SYS_PTRACE
- # security_opt:
- # - seccomp:unconfined
-
- # Overrides default command so things don't shut down after the process ends.
- command: sleep infinity
-
diff --git a/.eslintrc.json b/.eslintrc.json
index 3722418..015e65d 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,3 +1,6 @@
{
- "extends": ["next/core-web-vitals", "next/typescript"]
+ "extends": ["next/core-web-vitals"],
+ "rules": {
+ "react/no-unescaped-entities": "off"
+ }
}
diff --git a/Dockerfile b/Dockerfile
index 7cb033f..82710d8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,93 +1,46 @@
-# syntax=docker/dockerfile:1.4
-ARG NODE_VERSION=20
-
-# Base development image
-FROM node:${NODE_VERSION}-slim AS base
-
-# Install Python and basic build dependencies
-RUN apt-get update && apt-get install -y \
- python3 \
- python3-pip \
- git \
- curl \
- build-essential \
- procps \
- && rm -rf /var/lib/apt/lists/*
-
-# Create cache directories
-RUN mkdir -p /root/.npm
-RUN mkdir -p /root/.pip
-
-# Set working directory
-WORKDIR /app
-
-# Development stage
-FROM base AS dev
-
-# Install development tools
-RUN apt-get update && apt-get install -y \
- vim \
- ssh \
- && rm -rf /var/lib/apt/lists/*
-
-# Create a non-root user for development
-ARG USERNAME=node
-ARG USER_UID=1000
-ARG USER_GID=$USER_UID
-
-# Create the user (skip if already exists)
-RUN (groupadd --gid $USER_GID $USERNAME || true) \
- && (useradd --uid $USER_UID --gid $USER_GID -m $USERNAME || true) \
- && apt-get update \
- && apt-get install -y sudo \
- && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
- && chmod 0440 /etc/sudoers.d/$USERNAME
-
-# Set npm config
-RUN npm config set cache /root/.npm \
- && npm config set prefer-offline true \
- && npm config set package-lock true
-
-# Copy package files
-COPY package*.json ./
-COPY .npmrc ./
-COPY requirements.txt ./
-
-# Install Node.js dependencies with cache
-RUN --mount=type=cache,target=/root/.npm \
- npm ci
-
-# Install Python dependencies with cache (skip if no real dependencies)
-RUN --mount=type=cache,target=/root/.cache/pip \
- pip3 install --break-system-packages -r requirements.txt || echo "No Python dependencies to install"
-
-# Switch to non-root user
-USER $USERNAME
-
-# Set the default command for development
-CMD ["npm", "run", "dev"]
-
-# Production stage
-FROM base AS prod
-
-# Copy package files
-COPY package*.json ./
-COPY .npmrc ./
-COPY requirements.txt ./
-
-# Install production dependencies
-RUN --mount=type=cache,target=/root/.npm \
- npm ci --only=production
-
-# Install Python production dependencies (skip if no real dependencies)
-RUN --mount=type=cache,target=/root/.cache/pip \
- pip3 install --break-system-packages -r requirements.txt || echo "No Python dependencies to install"
-
-# Copy application code
-COPY . .
-
-# Build the application
-RUN npm run build
-
-# Production command
-CMD ["npm", "start"]
\ No newline at end of file
+# Production Dockerfile for Next.js frontend
+FROM node:20-alpine AS builder
+
+WORKDIR /app
+
+# Copy package files
+COPY package*.json ./
+COPY .npmrc ./
+
+# Install dependencies
+RUN npm ci
+
+# Copy source code
+COPY . .
+
+# Build the application
+ENV NEXT_TELEMETRY_DISABLED=1
+RUN npm run build
+
+# Production stage
+FROM node:20-alpine AS runner
+
+WORKDIR /app
+
+# Copy necessary files from builder
+COPY --from=builder /app/package*.json ./
+COPY --from=builder /app/.next/standalone ./
+COPY --from=builder /app/.next/static ./.next/static
+COPY --from=builder /app/public ./public
+
+# Install only production dependencies
+RUN npm ci --omit=dev
+
+# Create non-root user
+RUN addgroup --gid 1001 nodejs && \
+ adduser -D -u 1001 -G nodejs nextjs && \
+ chown -R nextjs:nodejs /app
+
+USER nextjs
+
+EXPOSE 8089
+
+ENV PORT=8089
+ENV HOSTNAME=0.0.0.0
+
+CMD ["node", "server.js"]
diff --git a/app/about/page.tsx b/app/about/page.tsx
new file mode 100644
index 0000000..3fbd1a5
--- /dev/null
+++ b/app/about/page.tsx
@@ -0,0 +1,109 @@
+import React from 'react';
+import Link from 'next/link';
+import { Eye, Mail, Users, Heart, ExternalLink } from 'lucide-react';
+
+export default function AboutPage() {
+ return (
+
+ {/* Mission */}
+
+
+
+ About CCFW
+
+
Cape Coral Friends of Wildlife
+
+ Cape Coral Friends of Wildlife (CCFW) is a nonprofit organization dedicated to protecting, monitoring, and advocating for native wildlife in Cape Coral and Southwest Florida.
+
+
+ Founded by passionate local residents, we've grown into a community of hundreds of volunteers who monitor owl burrows, restore habitat, educate the public, and run the wildlife cameras you're watching right now.
+
+
+
+
+
+ {[
+ { icon: Users, value: '500+', label: 'Active Volunteers' },
+ { icon: Eye, value: '2,000+', label: 'Burrows Monitored' },
+ { icon: Heart, value: '25+', label: 'Years of Conservation' },
+ ].map(({ icon: Icon, value, label }) => (
+
+ ))}
+
+
+
+ {/* Mission panels */}
+
+ {[
+ {
+ title: 'Monitor',
+ desc: 'Our volunteers walk hundreds of miles each year counting and mapping active burrowing owl burrows across Cape Coral.',
+ },
+ {
+ title: 'Educate',
+ desc: 'We visit schools, community events, and host public walks to help residents understand and appreciate their wild neighbors.',
+ },
+ {
+ title: 'Protect',
+ desc: 'We advocate for wildlife-friendly development policies, acquire land for habitat, and work with the city on conservation ordinances.',
+ },
+ ].map(({ title, desc }) => (
+
+ ))}
+
+
+ {/* Contact */}
+
+ Get in Touch
+
+
+
+
+ Whether you want to volunteer, report an injured owl, ask about conservation programs, or partner with us — we'd love to hear from you.
+
+
+
+
+
+ );
+}
diff --git a/app/components/DonationCard.tsx b/app/components/DonationCard.tsx
new file mode 100644
index 0000000..9b5b385
--- /dev/null
+++ b/app/components/DonationCard.tsx
@@ -0,0 +1,84 @@
+'use client';
+import React, { useState } from 'react';
+import { Heart, CheckCircle } from 'lucide-react';
+import type { Campaign } from '@/lib/api';
+
+const AMOUNTS = [10, 25, 50, 100, 250];
+
+export default function DonationCard({ campaign }: { campaign: Campaign }) {
+ const [selected, setSelected] = useState(25);
+ const [custom, setCustom] = useState('');
+ const [donated, setDonated] = useState(false);
+ const pct = Math.min(100, Math.round((campaign.raised / campaign.goal) * 100));
+
+ const handleDonate = () => {
+ // Stripe would go here
+ setDonated(true);
+ setTimeout(() => setDonated(false), 3000);
+ };
+
+ return (
+
+
+
{campaign.title}
+
{campaign.description}
+
+
+ {/* Progress */}
+
+
+ ${campaign.raised.toLocaleString()} raised
+ Goal: ${campaign.goal.toLocaleString()}
+
+
+
{pct}% complete
+
+
+ {/* Amount selector */}
+
+
+ {AMOUNTS.map((amt) => (
+ { setSelected(amt); setCustom(''); }}
+ className={`py-2 rounded-lg text-sm font-bold transition-all ${
+ selected === amt && !custom
+ ? 'bg-gold text-deepGreen shadow-lg shadow-gold/20'
+ : 'bg-black/40 text-stone-300 hover:bg-white/10'
+ }`}
+ >
+ ${amt}
+
+ ))}
+
+
{ setCustom(e.target.value); setSelected(0); }}
+ placeholder="Custom amount"
+ className="w-full bg-black/40 border border-white/10 rounded-lg px-4 py-2.5 text-sm text-white placeholder:text-stone-600 focus:outline-none focus:border-teal/50"
+ />
+
+
+
+ {donated ? (
+ <> Thank you!>
+ ) : (
+ <> Donate ${custom || selected}>
+ )}
+
+
+ );
+}
diff --git a/app/components/DonationPanel.tsx b/app/components/DonationPanel.tsx
deleted file mode 100644
index e799164..0000000
--- a/app/components/DonationPanel.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-"use client";
-
-import React, { useState } from 'react';
-
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-
-interface DonationPanelProps {
- id: string;
-}
-
-const DonationPanel: React.FC = ({ id }) => {
- const [amount, setAmount] = useState(25);
- const [donated, setDonated] = useState(false);
- const [donationInProgress, setDonationInProgress] = useState(false);
-
- const handleAmountChange = (e: React.ChangeEvent) => {
- const value = parseInt(e.target.value);
- if (!isNaN(value)) {
- setAmount(value);
- } else {
- setAmount(0);
- }
- };
-
- const handleDonate = () => {
- if (amount > 0) {
- setDonationInProgress(true);
- // Simulate API call
- setTimeout(() => {
- setDonated(true);
- setDonationInProgress(false);
- }, 1500);
- }
- };
-
- const predefinedAmounts = [10, 25, 50, 100];
-
- return (
-
-
- Support Wildlife
-
- Help protect the wildlife featured in Livestream {id}
-
-
-
- {!donated ? (
-
-
Your donation helps protect and preserve the habitats of these amazing creatures.
-
-
- {predefinedAmounts.map((presetAmount) => (
- setAmount(presetAmount)}
- >
- ${presetAmount}
-
- ))}
-
-
-
-
-
-
-
100% of donations go directly to CCFW conservation efforts
-
-
-
- {donationInProgress ? (
- <>
- Donate Now
-
-
-
-
-
-
- >
- ) : (
- `Donate $${amount}`
- )}
-
-
- ) : (
-
-
-
Thank You!
-
Your donation of ${amount} will help protect Florida wildlife.
-
- Cape Coral Friends of Wildlife is a 501(c)(3) non-profit organization.
- All donations are tax-deductible.
-
-
setDonated(false)} variant="outline" className="border-ccfw-teal/30 text-ccfw-teal mt-4 hover:bg-ccfw-teal/10">
- Make Another Donation
-
-
- )}
-
-
- );
-};
-
-export default DonationPanel;
diff --git a/app/components/EventCard.tsx b/app/components/EventCard.tsx
new file mode 100644
index 0000000..a650fdd
--- /dev/null
+++ b/app/components/EventCard.tsx
@@ -0,0 +1,77 @@
+'use client';
+import React, { useState } from 'react';
+import { Calendar, MapPin, Users, CheckCircle } from 'lucide-react';
+import { format } from 'date-fns';
+import type { Event } from '@/lib/api';
+import { api } from '@/lib/api';
+
+export default function EventCard({ event }: { event: Event }) {
+ const [rsvpd, setRsvpd] = useState(false);
+ const [email, setEmail] = useState('');
+ const [showEmail, setShowEmail] = useState(false);
+ const date = new Date(event.date);
+
+ const handleRsvp = async () => {
+ if (!email) { setShowEmail(true); return; }
+ try {
+ await api.rsvpEvent(event.id, email);
+ setRsvpd(true);
+ } catch {
+ setRsvpd(true); // optimistic
+ }
+ };
+
+ return (
+
+ {/* Date block */}
+
+ {format(date, 'MMM')}
+ {format(date, 'd')}
+
+
+ {/* Content */}
+
+
{event.title}
+
+
+
+ {format(date, 'EEEE, MMMM d, yyyy')} at {format(date, 'h:mm a')}
+
+
+
+ {event.location}
+
+
+
+ {event.rsvpCount} registered{event.capacity ? ` / ${event.capacity} max` : ''}
+
+
+
{event.description}
+
+ {/* RSVP */}
+
+ {showEmail && !rsvpd && (
+ setEmail(e.target.value)}
+ placeholder="your@email.com"
+ className="flex-1 bg-black/40 border border-white/10 rounded-lg px-4 py-2 text-sm text-white placeholder:text-stone-600 focus:outline-none focus:border-teal/50"
+ />
+ )}
+
+ {rsvpd ? <> Registered!> : 'Register'}
+
+
+
+
+ );
+}
diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx
new file mode 100644
index 0000000..83e453d
--- /dev/null
+++ b/app/components/Footer.tsx
@@ -0,0 +1,72 @@
+import React from 'react';
+import Link from 'next/link';
+import { Eye, Facebook, Instagram, Youtube, Mail } from 'lucide-react';
+
+export default function Footer() {
+ return (
+
+ );
+}
diff --git a/app/components/LiveStream.tsx b/app/components/LiveStream.tsx
deleted file mode 100644
index a05c5f0..0000000
--- a/app/components/LiveStream.tsx
+++ /dev/null
@@ -1,193 +0,0 @@
-"use client";
-
-import React from 'react';
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-
-interface LiveStreamProps {
- id: string;
-}
-
-// Define burrowing owl info based on stream ID
-const getStreamInfo = (id: string) => {
- switch (id) {
- case "1":
- return {
- title: "Cape Coral Burrowing Owl",
- location: "Cape Coral, FL",
- fact: "The burrowing owl is the official city bird of Cape Coral. These unique owls nest underground and are active during the day."
- };
- case "2":
- return {
- title: "Burrowing Owl Habitat",
- location: "Cape Coral, FL",
- fact: "Burrowing owls prefer open areas with low vegetation and create underground burrows that provide shelter for many wildlife species."
- };
- case "3":
- return {
- title: "Owl Burrow Monitoring",
- location: "Cape Coral, FL",
- fact: "CCFW volunteers maintain over 2,500 burrows throughout Cape Coral to protect these threatened ground-dwelling owls."
- };
- default:
- return {
- title: `Burrowing Owl Cam ${id}`,
- location: "Cape Coral, FL",
- fact: "Burrowing owls are Florida's smallest owl species and are known for their distinctive long legs and daytime activity."
- };
- }
-};
-
-// Client-side component for dynamic time to avoid hydration errors
-const ClientTimeDisplay: React.FC = () => {
- const [currentTime, setCurrentTime] = React.useState('');
-
- React.useEffect(() => {
- setCurrentTime(new Date().toLocaleDateString() + ' • ' + new Date().toLocaleTimeString());
- }, []);
-
- return {currentTime} ;
-};
-
-const LiveStream: React.FC = ({ id }) => {
- // This would be determined by your backend in a real app
- const isLive = id !== "3"; // Let's assume stream #3 is offline for testing
-
- const streamInfo = getStreamInfo(id);
- // Use a fixed viewer count to avoid hydration errors
- const viewerCount = isLive ? (id === "1" ? 128 : id === "2" ? 86 : 75) : 0;
-
- return (
-
-
-
-
{streamInfo.title}
-
-
-
{isLive ? 'LIVE' : 'OFFLINE'}
-
-
-
-
-
- {isLive ? (
- <>
-
-
- {/* Overlay for wildlife stream info */}
-
-
-
-
CCFW Wildlife Stream
-
-
- HD
-
-
-
-
-
-
{streamInfo.location} • Cape Coral Friends of Wildlife
-
HD Video • Live from Florida
-
-
-
-
-
-
-
-
- {viewerCount}
-
-
- {/* Stream controls overlay */}
-
-
-
-
- Powered by CCFW
-
-
-
- >
- ) : (
-
-
-
-
-
-
-
-
-
Stream currently offline
-
Will return soon. Check back later.
-
-
-
-
-
- )}
-
-
-
- {/* Wildlife fact */}
-
-
-
-
-
-
- Wildlife Fact: {streamInfo.fact}
-
-
-
-
-
- );
-};
-
-export default LiveStream;
diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx
new file mode 100644
index 0000000..10723c6
--- /dev/null
+++ b/app/components/Navbar.tsx
@@ -0,0 +1,117 @@
+'use client';
+import React, { useState, useEffect } from 'react';
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+import { Menu, X, Eye, Tv2, TreePine, Heart, Calendar, Info } from 'lucide-react';
+
+const links = [
+ { href: '/streams', label: 'Live Cams', icon: Tv2 },
+ { href: '/wildlife', label: 'Wildlife', icon: TreePine },
+ { href: '/events', label: 'Events', icon: Calendar },
+ { href: '/donate', label: 'Donate', icon: Heart },
+ { href: '/about', label: 'About', icon: Info },
+];
+
+export default function Navbar() {
+ const [open, setOpen] = useState(false);
+ const [scrolled, setScrolled] = useState(false);
+ const pathname = usePathname();
+
+ useEffect(() => {
+ const handler = () => setScrolled(window.scrollY > 40);
+ window.addEventListener('scroll', handler);
+ return () => window.removeEventListener('scroll', handler);
+ }, []);
+
+ return (
+
+
+ {/* Logo */}
+
+
+
+
+
+ Owl Stream
+ CCFW
+
+
+
+ {/* Desktop Nav */}
+
+ {links.map(({ href, label }) => {
+ const active = pathname === href || pathname.startsWith(href + '/');
+ return (
+
+ {label}
+
+ );
+ })}
+
+
+ {/* Donate CTA (desktop) */}
+
+
+ Support CCFW
+
+
+ {/* Mobile hamburger */}
+
setOpen(!open)}
+ aria-label="Toggle menu"
+ >
+ {open ? : }
+
+
+
+ {/* Mobile Menu */}
+ {open && (
+
+ {links.map(({ href, label, icon: Icon }) => {
+ const active = pathname === href;
+ return (
+
setOpen(false)}
+ className={`flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all ${
+ active ? 'bg-teal/20 text-teal' : 'text-stone-300 hover:bg-white/5 hover:text-white'
+ }`}
+ >
+
+ {label}
+
+ );
+ })}
+
+ setOpen(false)}
+ className="flex items-center justify-center gap-2 w-full py-3 rounded-xl bg-gold text-deepGreen font-bold text-sm"
+ >
+ Support CCFW
+
+
+
+ )}
+
+ );
+}
diff --git a/app/components/OwlInfo.tsx b/app/components/OwlInfo.tsx
deleted file mode 100644
index f60dd6f..0000000
--- a/app/components/OwlInfo.tsx
+++ /dev/null
@@ -1,182 +0,0 @@
-"use client";
-
-import React, { useState } from 'react';
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-
-interface OwlInfoProps {
- id: string;
-}
-
-const OwlInfo: React.FC = ({ id }) => {
- const [activeTab, setActiveTab] = useState<'facts' | 'habitat' | 'conservation'>('facts');
-
- // Get burrowing owl data based on stream ID
- const getWildlifeData = () => {
- switch (id) {
- case "1":
- return {
- species: "Burrowing Owl",
- scientificName: "Athene cunicularia",
- location: "Cape Coral, FL",
- facts: [
- "Burrowing owls are small, long-legged owls that nest underground in burrows",
- "Unlike most owls, they are active during the day (diurnal)",
- "They stand about 9 inches tall and have bright yellow eyes",
- "The City of Cape Coral has designated the burrowing owl as its official city bird"
- ],
- habitat: "Cape Coral has the largest population of burrowing owls in Florida. They prefer open areas with low vegetation such as prairies, grasslands, and open areas of urban development. CCFW volunteers maintain over 2,500 burrows throughout Cape Coral.",
- conservation: "Burrowing owls are listed as a state-threatened species in Florida. Development of their habitats is the biggest threat to their survival. CCFW works to protect and maintain burrows, educate the public, and collaborate with local authorities to ensure these birds have safe places to nest.",
- ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
- };
- case "2":
- return {
- species: "Burrowing Owl",
- scientificName: "Athene cunicularia",
- location: "Cape Coral, FL",
- facts: [
- "Burrowing owls create underground burrows that can be up to 30 feet long",
- "They often use burrows created by other animals like prairie dogs or armadillos",
- "These owls are known for their distinctive 'bobblehead' behavior when curious",
- "They can live up to 9 years in the wild with proper habitat protection"
- ],
- habitat: "Burrowing owls prefer open, grassy areas with sparse vegetation. They are commonly found in prairies, agricultural fields, and urban areas with suitable open spaces. The owls dig their own burrows or modify existing ones.",
- conservation: "Habitat loss from urban development is the primary threat to burrowing owls. CCFW's burrow maintenance program helps protect existing burrows and creates artificial burrows to support the owl population in Cape Coral.",
- ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
- };
- case "3":
- return {
- species: "Burrowing Owl",
- scientificName: "Athene cunicularia",
- location: "Cape Coral, FL",
- facts: [
- "Burrowing owls are Florida's smallest owl species",
- "They have long legs adapted for walking and running on the ground",
- "Their diet consists mainly of insects, small mammals, and reptiles",
- "They are the only owl species that nests exclusively underground"
- ],
- habitat: "These unique owls inhabit open grasslands, pastures, and urban areas with low vegetation. They are particularly well-adapted to the Florida landscape and have thrived in areas where other wildlife has declined.",
- conservation: "CCFW volunteers monitor and maintain over 2,500 burrows in Cape Coral. The organization's educational programs help the community understand the importance of protecting these threatened birds and their habitats.",
- ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
- };
- default:
- return {
- species: "Burrowing Owl",
- scientificName: "Athene cunicularia",
- location: "Cape Coral, FL",
- facts: [
- "Burrowing owls are the official city bird of Cape Coral",
- "They are diurnal, meaning they are active during the day",
- "These owls have distinctive long legs and bright yellow eyes",
- "CCFW maintains over 2,500 burrows to protect this threatened species"
- ],
- habitat: "Cape Coral provides ideal habitat for burrowing owls with its mix of urban development and open spaces. The city has the largest population of burrowing owls in Florida due to successful conservation efforts.",
- conservation: "Cape Coral Friends of Wildlife works tirelessly to protect burrowing owls through habitat preservation, burrow maintenance, public education, and collaboration with local authorities.",
- ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
- };
- }
- };
-
- const wildlifeData = getWildlifeData();
-
- return (
-
-
- About {wildlifeData.species}
-
- {wildlifeData.scientificName && (
- <>{wildlifeData.scientificName} • >
- )}
- {wildlifeData.location}
-
-
-
-
- setActiveTab('facts')}
- >
- Facts
-
- setActiveTab('habitat')}
- >
- Habitat
-
- setActiveTab('conservation')}
- >
- Conservation
-
-
-
-
- {activeTab === 'facts' && (
-
-
- {wildlifeData.facts.map((fact, index) => (
- {fact}
- ))}
-
-
- )}
-
- {activeTab === 'habitat' && (
-
-
{wildlifeData.habitat}
-
- )}
-
- {activeTab === 'conservation' && (
-
-
{wildlifeData.conservation}
-
-
-
- )}
-
-
-
-
-
- );
-};
-
-export default OwlInfo;
diff --git a/app/components/StatsBar.tsx b/app/components/StatsBar.tsx
new file mode 100644
index 0000000..09f877d
--- /dev/null
+++ b/app/components/StatsBar.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { Eye, Home, Clock, Tv2 } from 'lucide-react';
+import type { Stat } from '@/lib/api';
+
+const items = [
+ { key: 'owlCount', label: 'Owls Tracked', icon: Eye, unit: '' },
+ { key: 'burrowCount', label: 'Active Burrows', icon: Home, unit: '' },
+ { key: 'volunteerHours', label: 'Volunteer Hours', icon: Clock, unit: 'hrs' },
+ { key: 'activeStreams', label: 'Live Cams', icon: Tv2, unit: '' },
+] as const;
+
+export default function StatsBar({ stats }: { stats: Stat }) {
+ return (
+
+ {items.map(({ key, label, icon: Icon, unit }) => (
+
+
+
+ {stats[key].toLocaleString()}{unit}
+
+
{label}
+
+ ))}
+
+ );
+}
diff --git a/app/components/StreamCard.tsx b/app/components/StreamCard.tsx
new file mode 100644
index 0000000..7c54673
--- /dev/null
+++ b/app/components/StreamCard.tsx
@@ -0,0 +1,62 @@
+import React from 'react';
+import Link from 'next/link';
+import { Radio, Users, MapPin } from 'lucide-react';
+import type { Stream } from '@/lib/api';
+
+export default function StreamCard({ stream }: { stream: Stream }) {
+ return (
+
+
+ {/* Thumbnail area */}
+
+ {stream.thumbnailUrl ? (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ ) : (
+
+
+
+ )}
+
+ {/* Status badge */}
+
+ {stream.status === 'live' && }
+ {stream.status === 'live' ? 'Live' : 'Offline'}
+
+
+ {/* Viewer count */}
+ {stream.viewerCount > 0 && (
+
+
+ {stream.viewerCount.toLocaleString()}
+
+ )}
+
+
+ {/* Info */}
+
+
+ {stream.name}
+
+ {stream.location && (
+
+
+ {stream.location}
+
+ )}
+ {stream.description && (
+
{stream.description}
+ )}
+
+
+
+ );
+}
diff --git a/app/components/WildlifeCard.tsx b/app/components/WildlifeCard.tsx
new file mode 100644
index 0000000..c45819c
--- /dev/null
+++ b/app/components/WildlifeCard.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import { Shield } from 'lucide-react';
+import type { Wildlife } from '@/lib/api';
+
+const statusColor: Record = {
+ 'Threatened': 'bg-red-500/20 text-red-400 border-red-500/30',
+ 'Protected': 'bg-amber-500/20 text-amber-400 border-amber-500/30',
+ 'Least Concern': 'bg-emerald-500/20 text-emerald-400 border-emerald-500/30',
+ 'Endangered': 'bg-red-700/30 text-red-300 border-red-600/30',
+};
+
+export default function WildlifeCard({ species }: { species: Wildlife }) {
+ const colors = statusColor[species.status] ?? 'bg-stone-500/20 text-stone-400 border-stone-500/30';
+ return (
+
+ {/* Image */}
+
+ {species.imageUrl ? (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ ) : (
+
🦉
+ )}
+
+
+ {/* Status */}
+
+
+ {species.status}
+
+
+
{species.name}
+
{species.scientificName}
+
+
{species.description}
+
+
+ Habitat: {species.habitat}
+
+
+
+
+ );
+}
diff --git a/app/donate/page.tsx b/app/donate/page.tsx
new file mode 100644
index 0000000..ff35666
--- /dev/null
+++ b/app/donate/page.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import { Heart, Shield, Camera, TreePine } from 'lucide-react';
+import { api, Campaign } from '@/lib/api';
+import DonationCard from '../components/DonationCard';
+
+const FALLBACK_CAMPAIGNS: Campaign[] = [
+ {
+ id: '1', title: 'Land Preservation Fund',
+ description: 'Help CCFW acquire and protect critical burrowing owl habitat before developers can build on it.',
+ goal: 50000, raised: 31250,
+ },
+ {
+ id: '2', title: 'Volunteer Equipment',
+ description: 'Fund field monitors, spotting scopes, GPS units, and protective gear for our volunteer teams.',
+ goal: 15000, raised: 9800,
+ },
+ {
+ id: '3', title: 'Camera Infrastructure',
+ description: 'Expand our network of wildlife cameras. Each camera streams 24/7 and reaches thousands of viewers.',
+ goal: 25000, raised: 14200,
+ },
+];
+
+const icons = [TreePine, Shield, Camera];
+
+async function getCampaigns(): Promise {
+ try { return await api.getCampaigns(); }
+ catch { return FALLBACK_CAMPAIGNS; }
+}
+
+export default async function DonatePage() {
+ const campaigns = await getCampaigns();
+
+ return (
+
+
+
+ Support Conservation
+
+ Help Protect Cape Coral Wildlife
+
+ Every dollar goes directly to protecting burrowing owls, gopher tortoises, and native Florida wildlife. CCFW is a 501(c)(3) nonprofit — your donation is tax deductible.
+
+
+
+ {/* Impact banner */}
+
+ {[
+ { icon: icons[0], title: 'Land Preserved', value: '150+ acres' },
+ { icon: icons[1], title: 'Burrows Monitored', value: '2,000+' },
+ { icon: icons[2], title: 'Live Cameras', value: '12 active' },
+ ].map(({ icon: Icon, title, value }) => (
+
+ ))}
+
+
+ {/* Campaign cards */}
+
+
Active Campaigns
+
+ {campaigns.map((c) => )}
+
+
+
+ {/* Trust signals */}
+
+
+
+
Secure & Tax-Deductible
+
+ Cape Coral Friends of Wildlife is a registered 501(c)(3) nonprofit organization. All donations are tax-deductible to the fullest extent permitted by law. We never sell your information. Payment processing powered by Stripe.
+
+
+
+
+ );
+}
diff --git a/app/events/page.tsx b/app/events/page.tsx
new file mode 100644
index 0000000..96f32c1
--- /dev/null
+++ b/app/events/page.tsx
@@ -0,0 +1,69 @@
+import React from 'react';
+import { Calendar } from 'lucide-react';
+import { api, Event } from '@/lib/api';
+import EventCard from '../components/EventCard';
+
+const FALLBACK_EVENTS: Event[] = [
+ {
+ id: '1',
+ title: 'Burrowing Owl Survey Walk',
+ date: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString(),
+ location: 'Rotary Park, Cape Coral',
+ description: 'Join CCFW volunteers for our monthly owl survey. Learn to identify burrows and record sighting data. All skill levels welcome.',
+ rsvpCount: 14,
+ capacity: 25,
+ },
+ {
+ id: '2',
+ title: 'Habitat Restoration Day',
+ date: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000).toISOString(),
+ location: 'Four Mile Cove, Cape Coral',
+ description: 'Help us plant native vegetation to restore burrowing owl habitat. Gloves and tools provided. Bring water and sunscreen.',
+ rsvpCount: 8,
+ capacity: 20,
+ },
+ {
+ id: '3',
+ title: 'Community Wildlife Photography Workshop',
+ date: new Date(Date.now() + 17 * 24 * 60 * 60 * 1000).toISOString(),
+ location: 'CCFW Conservation Center',
+ description: 'Professional wildlife photographer workshop covering camera settings, ethics of wildlife photography, and best spots in Cape Coral.',
+ rsvpCount: 22,
+ capacity: 30,
+ },
+];
+
+async function getEvents(): Promise {
+ try { return await api.getEvents(); }
+ catch { return FALLBACK_EVENTS; }
+}
+
+export default async function EventsPage() {
+ const events = await getEvents();
+
+ return (
+
+
+
+ Upcoming
+
+ CCFW Events
+
+ Get involved! CCFW hosts regular surveys, restoration days, and educational events for the Cape Coral community.
+
+
+
+
+ {events.length === 0 ? (
+
+
+
No upcoming events
+
Check back soon or follow us on social media.
+
+ ) : (
+ events.map((e) =>
)
+ )}
+
+
+ );
+}
diff --git a/app/globals.css b/app/globals.css
index 5d888c3..37f9d11 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,56 +1,31 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-:root {
- /* CCFW Colors */
- --background: 25 25 25;
- --foreground: 230 230 230;
- --muted: 50 50 50;
- --muted-foreground: 180 180 180;
-
- /* Teal/turquoise from CCFW site */
- --accent: 0 130 167;
- --accent-foreground: 255 255 255;
-
- /* CCFW Colors */
- --card: 233 230 223;
- --card-foreground: 51 51 51;
-
- /* Teal/turquoise from CCFW */
- --primary: 0 130 167;
- --primary-foreground: 255 255 255;
-
- /* CCFW Yellow/Gold */
- --secondary: 246 202 66;
- --secondary-foreground: 51 51 51;
-
- /* Coral red from CCFW site */
- --destructive: 255 133 106;
- --destructive-foreground: 255 255 255;
-
- /* CCFW Colors */
- --border: 204 204 204;
- --input: 233 230 223;
- --ring: 0 130 167;
-
- /* Additional CCFW colors */
- --ccfw-gold: 246 202 66;
- --ccfw-teal: 0 130 167;
- --ccfw-coral: 255 133 106;
- --ccfw-beige: 233 230 223;
- --ccfw-maroon: 88 40 67;
-}
-
-body {
- color: rgb(var(--foreground));
- background: rgb(var(--background));
-}
-
-@layer utilities {
- .neon-glow {
- text-shadow: 0 0 5px rgb(var(--accent) / 0.5),
- 0 0 10px rgb(var(--accent) / 0.5),
- 0 0 15px rgb(var(--accent) / 0.5);
- }
-}
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --deep-green: #0a1f1a;
+ --surface-green: #112920;
+ --gold: #c4a265;
+ --teal: #0082a7;
+}
+
+html, body {
+ background-color: #0a1f1a;
+ color: #e8e0d0;
+ font-family: system-ui, -apple-system, sans-serif;
+ margin: 0;
+}
+
+::-webkit-scrollbar {
+ width: 8px;
+}
+::-webkit-scrollbar-track {
+ background: #0a1f1a;
+}
+::-webkit-scrollbar-thumb {
+ background: #1e4a3c;
+ border-radius: 4px;
+}
+::-webkit-scrollbar-thumb:hover {
+ background: #0082a7;
+}
diff --git a/app/layout.tsx b/app/layout.tsx
index 17f967a..68794ea 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,19 +1,21 @@
-import type { Metadata } from "next";
-import "./globals.css";
+import type { Metadata } from 'next';
+import './globals.css';
+import Navbar from './components/Navbar';
+import Footer from './components/Footer';
export const metadata: Metadata = {
- title: "Cape Coral Burrowing Owl Livestream",
- description: "Live stream of burrowing owls in Cape Coral",
+ title: 'Owl Stream | Cape Coral Friends of Wildlife',
+ description: 'Live burrowing owl cams, wildlife conservation, and nature in Cape Coral, Florida.',
};
-export default function RootLayout({
- children,
-}: {
- children: React.ReactNode
-}) {
+export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
- {children}
+
+
+ {children}
+
+
- )
+ );
}
diff --git a/app/livestream/[id]/page.tsx b/app/livestream/[id]/page.tsx
deleted file mode 100644
index 96661bd..0000000
--- a/app/livestream/[id]/page.tsx
+++ /dev/null
@@ -1,184 +0,0 @@
-import React from 'react';
-import Link from 'next/link';
-import LiveStream from '@/app/components/LiveStream';
-import DonationPanel from '@/app/components/DonationPanel';
-import OwlInfo from '@/app/components/OwlInfo';
-import { Button } from "@/components/ui/button";
-import { Card, CardContent } from "@/components/ui/card";
-
-// This would come from an API or database in a real app
-const livestreamsData = [
- {
- id: "1",
- name: "Cape Coral Burrowing Owl",
- location: "Cape Coral, FL",
- status: "Live",
- viewers: 128,
- description: "Watch these unique ground-dwelling owls at their burrows in Cape Coral. These protected birds are the official city bird of Cape Coral!"
- },
- {
- id: "2",
- name: "Sanibel Island Osprey",
- location: "Sanibel Island, FL",
- status: "Live",
- viewers: 86,
- description: "Observe ospreys building nests and hunting for fish around Sanibel Island."
- },
- {
- id: "3",
- name: "Everglades Alligator",
- location: "Everglades National Park, FL",
- status: "Offline",
- viewers: 0,
- description: "Temporarily offline. Usually shows alligators in their natural habitat in the Everglades."
- },
-];
-
-export default function LivestreamPage({ params }: { params: { id: string } }) {
- // Find the stream data based on the ID
- const streamData = livestreamsData.find(stream => stream.id === params.id) || {
- id: params.id,
- name: `Wildlife Livestream ${params.id}`,
- location: "Florida",
- status: "Live",
- viewers: Math.floor(Math.random() * 100) + 50,
- description: "Experience the natural beauty of Florida's wildlife."
- };
-
- return (
-
-
-
-
-
-
-
-
-
- Back to all streams
-
-
-
{streamData.name}
-
{streamData.location}
-
-
-
-
{streamData.status}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
About this livestream
-
- This livestream is provided by Cape Coral Friends of Wildlife, a volunteer organization dedicated to the protection and preservation of local wildlife. These cameras help researchers monitor wildlife behavior while allowing the public to connect with nature.
-
-
-
- Learn more about our conservation efforts
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Get Involved
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/app/map/page.tsx b/app/map/page.tsx
new file mode 100644
index 0000000..b4015d0
--- /dev/null
+++ b/app/map/page.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import { Map } from 'lucide-react';
+
+export default function MapPage() {
+ return (
+
+
+
+ {/* Map placeholder — interactive Leaflet map requires client component */}
+
+
+
🗺️
+
+
Interactive Burrow Map
+
+ Leaflet map with burrow markers loading from{' '}
+ /api/burrows
+
+
+
+ {/* Decorative grid pattern */}
+
+
+
+ {/* Legend */}
+
+
+ );
+}
diff --git a/app/page.tsx b/app/page.tsx
index 4133674..03f4d97 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,640 +1,132 @@
-import React from 'react';
-import Link from 'next/link';
-import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-
-// This would typically come from an API or database
-const livestreams = [
- {
- id: 1,
- name: "Cape Coral Burrowing Owl",
- location: "Cape Coral, FL",
- status: "Live",
- viewers: 128,
- description: "Watch these unique ground-dwelling owls at their burrows in Cape Coral. These protected birds are the official city bird of Cape Coral!"
- },
- {
- id: 2,
- name: "Burrowing Owl Habitat",
- location: "Cape Coral, FL",
- status: "Live",
- viewers: 95,
- description: "Observe burrowing owls in their natural habitat. Watch them hunt, nest, and interact with their environment."
- },
- {
- id: 3,
- name: "Owl Burrow Monitoring",
- location: "Cape Coral, FL",
- status: "Live",
- viewers: 67,
- description: "Monitor active burrowing owl burrows and learn about CCFW's conservation efforts to protect these amazing birds."
- },
-];
-
-export default function Home() {
- return (
-
-
-
-
- {/* Logo and Brand */}
-
-
-
-
CCFW Livestreams
-
Cape Coral Friends of Wildlife
-
-
-
- {/* Navigation Actions */}
-
-
-
-
-
-
- {/* Hero Section */}
-
-
-
-
-
-
-
-
-
-
Live Wildlife Streams
-
-
- Cape Coral Friends of
-
- Wildlife Livestreams
-
-
-
- Dedicated to Protection, Preservation and Education
-
-
-
-
-
- Discover the fascinating world of burrowing owls , the official city bird of Cape Coral.
- These unique ground-dwelling owls are active during the day and nest underground in burrows throughout our community.
-
-
- Cape Coral Friends of Wildlife is dedicated to protecting these threatened birds through habitat preservation, burrow maintenance, and community education. With over 2,500 burrows maintained by our volunteers, we ensure these amazing owls thrive in our urban environment.
-
-
-
-
-
-
-
- Learn more about CCFW
-
-
-
-
-
-
-
-
- {/* Featured Owls Section */}
-
-
-
-
- {[
- {
- name: 'Burrowing Owl Facts',
- icon: '🦉',
- color: 'from-ccfw-teal to-ccfw-maroon',
- description: "Burrowing owls are small, long-legged owls that nest underground in burrows. Unlike most owls, they are active during the day and have bright yellow eyes. The City of Cape Coral has designated the burrowing owl as its official city bird."
- },
- {
- name: 'Owl Conservation',
- icon: '🌱',
- color: 'from-ccfw-maroon to-ccfw-teal',
- description: "CCFW volunteers maintain over 2,500 burrows throughout Cape Coral. These unique birds face threats from habitat loss and development. Our conservation efforts protect these amazing ground-dwelling owls."
- },
- {
- name: 'Owl Habitat',
- icon: '🏞️',
- color: 'from-ccfw-gold to-ccfw-coral',
- description: "Burrowing owls prefer open areas with low vegetation such as prairies, grasslands, and open areas of urban development. They create burrows that provide shelter for many other wildlife species as well."
- }
- ].map((owlFeature) => (
-
-
-
-
-
-
{owlFeature.icon}
-
-
- {owlFeature.name}
-
-
-
-
-
-
-
-
- {owlFeature.description}
-
-
-
- ))}
-
-
-
- {/* Live Cameras Section */}
-
-
-
-
-
-
-
-
Powered by
-
- CCFW
-
-
-
-
-
- {livestreams.map((stream) => (
-
- {/* Status Indicator */}
-
-
- {/* Background Gradient Overlay */}
-
-
- {/* Camera Preview Mockup */}
-
-
-
-
- {/* Quality Badge */}
-
- HD
-
-
-
-
-
- {stream.name}
-
-
-
-
-
- {stream.location}
-
-
-
-
-
- {stream.description}
-
-
- {/* Viewer Count & Quality */}
-
-
- {stream.status === 'Live' && (
-
-
-
-
-
{stream.viewers} viewers
-
- )}
-
-
-
-
- {/* Watch Button */}
-
-
- {stream.status === 'Live' ? (
- <>
-
-
-
-
- Watch Live
- >
- ) : (
- <>
-
-
-
- Offline
- >
- )}
-
-
-
-
- ))}
-
-
-
- {/* Support Our Mission Section */}
-
-
-
-
- {/* Content Section */}
-
-
-
-
-
Support Our Mission
-
-
- Cape Coral Friends of Wildlife is a volunteer organization founded in 2001. With over 500 members and an engaged group of volunteers, we work to preserve and enhance the habitats of protected wildlife.
-
-
- Your support helps us continue our conservation efforts and educational programs that benefit the unique wildlife of Southwest Florida.
-
-
-
- {/* Action Buttons */}
-
-
-
- {/* Stats Card */}
-
-
- {/* Background Glow */}
-
-
-
- {/* Header */}
-
-
-
-
-
-
Impact This Year
-
-
Volunteer Hours
-
-
- {/* Main Stat */}
-
-
- {/* CTA */}
-
-
-
-
-
-
-
-
- {/* Modern Footer */}
-
-
- );
-}
+import React from 'react';
+import Link from 'next/link';
+import { Tv2, Heart, ChevronRight, TreePine, Calendar } from 'lucide-react';
+import { api, Stream, Stat } from '@/lib/api';
+import StatsBar from './components/StatsBar';
+import StreamCard from './components/StreamCard';
+
+async function getData(): Promise<{ stats: Stat | null; streams: Stream[] }> {
+ try {
+ const [stats, streams] = await Promise.all([api.getStats(), api.getStreams()]);
+ return { stats, streams: streams.slice(0, 3) };
+ } catch {
+ return { stats: null, streams: [] };
+ }
+}
+
+export default async function Home() {
+ const { stats, streams } = await getData();
+
+ return (
+
+ {/* Hero */}
+
+ {/* Background gradient */}
+
+
+ {/* Decorative circles */}
+
+
+
+
+ {/* Live badge */}
+
+
+ Cameras Live Now
+
+
+
+ Watch Cape Coral's
+
+ Burrowing Owls
+
+ Live
+
+
+
+ Free, 24/7 wildlife cameras brought to you by Cape Coral Friends of Wildlife. Watch, learn, and help protect Florida's native species.
+
+
+
+
+ Watch Live Cams
+
+
+ Support the Mission
+
+
+
+
+
+ {/* Stats Bar */}
+ {stats && (
+
+ )}
+
+ {/* Latest Streams */}
+ {streams.length > 0 && (
+
+
+
+
Live Cameras
+
Watch our wildlife cams in real time
+
+
+ View all
+
+
+
+ {streams.map((s) => )}
+
+
+ )}
+
+ {/* Mission CTA grid */}
+
+ {[
+ {
+ icon: TreePine,
+ title: 'Wildlife Guide',
+ desc: 'Learn about burrowing owls, gopher tortoises, scrub-jays, and manatees.',
+ href: '/wildlife',
+ cta: 'Explore Species',
+ color: 'text-emerald-400',
+ },
+ {
+ icon: Heart,
+ title: 'Support CCFW',
+ desc: 'Your donation funds cameras, land preservation, and volunteer programs.',
+ href: '/donate',
+ cta: 'Donate Now',
+ color: 'text-gold',
+ },
+ {
+ icon: Calendar,
+ title: 'Upcoming Events',
+ desc: 'Join cleanups, educational walks, and community conservation events.',
+ href: '/events',
+ cta: 'See Events',
+ color: 'text-teal',
+ },
+ ].map(({ icon: Icon, title, desc, href, cta, color }) => (
+
+
+
{title}
+
{desc}
+
+ {cta}
+
+
+ ))}
+
+
+ );
+}
diff --git a/app/streams/[id]/VideoPlayer.tsx b/app/streams/[id]/VideoPlayer.tsx
new file mode 100644
index 0000000..b35f599
--- /dev/null
+++ b/app/streams/[id]/VideoPlayer.tsx
@@ -0,0 +1,58 @@
+'use client';
+import React, { useEffect, useRef } from 'react';
+import { Radio } from 'lucide-react';
+
+interface Props {
+ hlsUrl?: string;
+ thumbnailUrl?: string;
+}
+
+export default function VideoPlayer({ hlsUrl, thumbnailUrl }: Props) {
+ const videoRef = useRef(null);
+
+ useEffect(() => {
+ if (!hlsUrl || !videoRef.current) return;
+ const video = videoRef.current;
+
+ if (video.canPlayType('application/vnd.apple.mpegurl')) {
+ video.src = hlsUrl;
+ return;
+ }
+
+ import('hls.js').then(({ default: Hls }) => {
+ if (Hls.isSupported()) {
+ const hls = new Hls();
+ hls.loadSource(hlsUrl);
+ hls.attachMedia(video);
+ return () => hls.destroy();
+ }
+ });
+ }, [hlsUrl]);
+
+ if (!hlsUrl) {
+ return (
+
+
+
Stream offline — no source available
+ {thumbnailUrl && (
+ // eslint-disable-next-line @next/next/no-img-element
+
+ )}
+
+ );
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/app/streams/[id]/page.tsx b/app/streams/[id]/page.tsx
new file mode 100644
index 0000000..25597ae
--- /dev/null
+++ b/app/streams/[id]/page.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import { notFound } from 'next/navigation';
+import { MapPin, Users, ArrowLeft } from 'lucide-react';
+import Link from 'next/link';
+import { api, Campaign } from '@/lib/api';
+import VideoPlayer from './VideoPlayer';
+import DonationCard from '../../components/DonationCard';
+
+export default async function StreamDetailPage({ params }: { params: { id: string } }) {
+ let stream;
+ let campaigns: Campaign[] = [];
+ try {
+ [stream, campaigns] = await Promise.all([
+ api.getStream(params.id),
+ api.getCampaigns(),
+ ]);
+ } catch {
+ notFound();
+ }
+
+ return (
+
+ {/* Back */}
+
+
Back to all cameras
+
+
+ {/* Status bar */}
+
+
+ {stream.status === 'live' && }
+ {stream.status === 'live' ? 'Live' : 'Offline'}
+
+ {stream.location && (
+
+ {stream.location}
+
+ )}
+ {stream.viewerCount > 0 && (
+
+ {stream.viewerCount.toLocaleString()} watching
+
+ )}
+
+
+
+ {/* Main video + info */}
+
+
+
+
{stream.name}
+ {stream.description && (
+
{stream.description}
+ )}
+
+
+ {/* Wildlife facts panel */}
+
+
Burrowing Owl Facts
+
+ • Burrowing owls are the official city bird of Cape Coral, FL.
+ • Unlike most owls, they are active during the day and nest underground.
+ • They are a Species of Special Concern in Florida — development threatens their habitat.
+ • CCFW monitors over 2,000 active burrow sites across Cape Coral.
+
+
+
+
+ {/* Sidebar: Donate */}
+
+
+
Support the Cameras
+
+ These cameras run 24/7 thanks to donations from wildlife lovers like you.
+
+
+ {campaigns.slice(0, 1).map((c) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/app/streams/page.tsx b/app/streams/page.tsx
new file mode 100644
index 0000000..7172881
--- /dev/null
+++ b/app/streams/page.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { Radio } from 'lucide-react';
+import { api, Stream } from '@/lib/api';
+import StreamCard from '../components/StreamCard';
+
+async function getStreams(): Promise {
+ try { return await api.getStreams(); }
+ catch { return []; }
+}
+
+export default async function StreamsPage() {
+ const streams = await getStreams();
+ const live = streams.filter((s) => s.status === 'live');
+ const offline = streams.filter((s) => s.status !== 'live');
+
+ return (
+
+
+
+
+ {live.length} camera{live.length !== 1 ? 's' : ''} live now
+
+ Wildlife Cameras
+
+ Free, 24/7 livestreams from Cape Coral's burrowing owl habitats and wildlife areas.
+
+
+
+ {streams.length === 0 && (
+
+
+
No cameras available
+
Check back soon or ensure the backend is running.
+
+ )}
+
+ {live.length > 0 && (
+
+
+
+ Live Now
+
+
+ {live.map((s) => )}
+
+
+ )}
+
+ {offline.length > 0 && (
+
+ Offline Cameras
+
+ {offline.map((s) => )}
+
+
+ )}
+
+ );
+}
diff --git a/app/volunteer/page.tsx b/app/volunteer/page.tsx
new file mode 100644
index 0000000..abd5325
--- /dev/null
+++ b/app/volunteer/page.tsx
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Lock, Users, ClipboardList } from 'lucide-react';
+import Link from 'next/link';
+
+export default function VolunteerPage() {
+ return (
+
+
+
+ {/* Login gate notice */}
+
+
+
+
+
+
Volunteer Dashboard
+
+ The full volunteer dashboard (task assignments, hour logging, equipment checkout, and leaderboard) requires a CCFW volunteer account. Log in or register to access.
+
+
+
+
+
+ {/* Volunteer roles */}
+
+
Volunteer Opportunities
+
+ {[
+ {
+ icon: '🦉',
+ title: 'Owl Surveyor',
+ desc: 'Walk designated survey routes and record burrow activity on a monthly basis.',
+ commitment: '2–4 hrs/month',
+ },
+ {
+ icon: '🌿',
+ title: 'Habitat Restorer',
+ desc: 'Plant native vegetation, remove invasives, and restore critical burrowing owl habitat.',
+ commitment: '4 hrs/quarter',
+ },
+ {
+ icon: '📸',
+ title: 'Camera Monitor',
+ desc: 'Review footage from wildlife cameras, flag notable events, and maintain equipment.',
+ commitment: 'Remote, flexible',
+ },
+ ].map(({ icon, title, desc, commitment }) => (
+
+
{icon}
+
{title}
+
{desc}
+
+
+ {commitment}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/app/wildlife/page.tsx b/app/wildlife/page.tsx
new file mode 100644
index 0000000..91f15e5
--- /dev/null
+++ b/app/wildlife/page.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import { TreePine } from 'lucide-react';
+import { api, Wildlife } from '@/lib/api';
+import WildlifeCard from '../components/WildlifeCard';
+
+// Fallback data when API unavailable
+const FALLBACK: Wildlife[] = [
+ {
+ id: '1', name: 'Burrowing Owl', scientificName: 'Athene cunicularia',
+ status: 'Threatened',
+ description: 'Cape Coral\'s official city bird. These small ground-dwelling owls nest in burrows, are active during the day, and are a Species of Special Concern in Florida. CCFW monitors thousands of active burrow sites.',
+ habitat: 'Open grasslands, vacant lots, golf courses',
+ },
+ {
+ id: '2', name: 'Gopher Tortoise', scientificName: 'Gopherus polyphemus',
+ status: 'Threatened',
+ description: 'A keystone species whose burrows shelter over 350 other animal species. Their habitat is disappearing rapidly due to development. Florida law protects gopher tortoises and their burrows.',
+ habitat: 'Dry upland habitats, scrub, longleaf pine',
+ },
+ {
+ id: '3', name: 'Florida Scrub-Jay', scientificName: 'Aphelocoma coerulescens',
+ status: 'Threatened',
+ description: 'Florida\'s only endemic bird species, found nowhere else on Earth. These intelligent, cooperative-breeding birds require open, scrubby habitat that has declined by 90% over the past century.',
+ habitat: 'Florida scrub habitat',
+ },
+ {
+ id: '4', name: 'Florida Manatee', scientificName: 'Trichechus manatus latirostris',
+ status: 'Threatened',
+ description: 'Gentle marine mammals that frequent Southwest Florida\'s warm waters. Threats include boat strikes, cold stress, and habitat loss. Cape Coral\'s canals serve as critical manatee habitat.',
+ habitat: 'Coastal waterways, canals, springs',
+ },
+];
+
+async function getWildlife(): Promise {
+ try { return await api.getWildlife(); }
+ catch { return FALLBACK; }
+}
+
+export default async function WildlifePage() {
+ const species = await getWildlife();
+
+ return (
+
+
+
+ Native Species
+
+ Southwest Florida Wildlife
+
+ Cape Coral and Southwest Florida are home to remarkable native species. CCFW works to protect, monitor, and educate the community about these irreplaceable animals.
+
+
+
+
+ {species.map((s) => )}
+
+
+ {/* Conservation info panel */}
+
+
+
Why It Matters
+
+ Southwest Florida's rapid growth has put enormous pressure on wildlife habitat. Cape Coral, despite being one of the most densely populated cities in Florida, still harbors significant populations of protected species — but only because of active conservation efforts.
+
+
+ CCFW's work includes burrow monitoring, community education, habitat restoration, and advocacy to ensure these species have a future in Cape Coral.
+
+
+
+ {[
+ { num: '2,000+', label: 'Owl burrows monitored' },
+ { num: '25+', label: 'Years of conservation' },
+ { num: '100%', label: 'Volunteer powered' },
+ ].map(({ num, label }) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/backend/Dockerfile b/backend/Dockerfile
new file mode 100644
index 0000000..aa58add
--- /dev/null
+++ b/backend/Dockerfile
@@ -0,0 +1,39 @@
+FROM node:20-alpine AS builder
+
+WORKDIR /app
+
+COPY package.json package-lock.json* ./
+RUN npm ci
+
+COPY tsconfig.json ./
+COPY prisma ./prisma
+COPY src ./src
+
+RUN npx prisma generate
+RUN npm run build
+
+# --- Runtime stage ---
+FROM node:20-alpine AS runner
+
+# Install OpenSSL libraries required by Prisma
+RUN apk add --no-cache openssl libssl3
+
+RUN addgroup --gid 1001 appgroup && \
+ adduser -D -u 1001 -G appgroup appuser
+
+WORKDIR /app
+
+COPY package.json package-lock.json* ./
+RUN npm ci --omit=dev
+
+COPY --from=builder /app/dist ./dist
+COPY prisma ./prisma
+RUN npx prisma generate
+
+RUN chown -R appuser:appgroup /app
+
+USER appuser
+
+EXPOSE 3007
+
+CMD ["node", "dist/index.js"]
diff --git a/backend/node_modules/.bin/acorn b/backend/node_modules/.bin/acorn
new file mode 120000
index 0000000..cf76760
--- /dev/null
+++ b/backend/node_modules/.bin/acorn
@@ -0,0 +1 @@
+../acorn/bin/acorn
\ No newline at end of file
diff --git a/backend/node_modules/.bin/mime b/backend/node_modules/.bin/mime
new file mode 120000
index 0000000..fbb7ee0
--- /dev/null
+++ b/backend/node_modules/.bin/mime
@@ -0,0 +1 @@
+../mime/cli.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/mkdirp b/backend/node_modules/.bin/mkdirp
new file mode 120000
index 0000000..017896c
--- /dev/null
+++ b/backend/node_modules/.bin/mkdirp
@@ -0,0 +1 @@
+../mkdirp/bin/cmd.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/prisma b/backend/node_modules/.bin/prisma
new file mode 120000
index 0000000..af8b4c8
--- /dev/null
+++ b/backend/node_modules/.bin/prisma
@@ -0,0 +1 @@
+../prisma/build/index.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/resolve b/backend/node_modules/.bin/resolve
new file mode 120000
index 0000000..b6afda6
--- /dev/null
+++ b/backend/node_modules/.bin/resolve
@@ -0,0 +1 @@
+../resolve/bin/resolve
\ No newline at end of file
diff --git a/backend/node_modules/.bin/rimraf b/backend/node_modules/.bin/rimraf
new file mode 120000
index 0000000..4cd49a4
--- /dev/null
+++ b/backend/node_modules/.bin/rimraf
@@ -0,0 +1 @@
+../rimraf/bin.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/semver b/backend/node_modules/.bin/semver
new file mode 120000
index 0000000..5aaadf4
--- /dev/null
+++ b/backend/node_modules/.bin/semver
@@ -0,0 +1 @@
+../semver/bin/semver.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/tree-kill b/backend/node_modules/.bin/tree-kill
new file mode 120000
index 0000000..26dcd2c
--- /dev/null
+++ b/backend/node_modules/.bin/tree-kill
@@ -0,0 +1 @@
+../tree-kill/cli.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node b/backend/node_modules/.bin/ts-node
new file mode 120000
index 0000000..b3ff94b
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node
@@ -0,0 +1 @@
+../ts-node/dist/bin.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node-cwd b/backend/node_modules/.bin/ts-node-cwd
new file mode 120000
index 0000000..54984a4
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node-cwd
@@ -0,0 +1 @@
+../ts-node/dist/bin-cwd.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node-dev b/backend/node_modules/.bin/ts-node-dev
new file mode 120000
index 0000000..4683cb2
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node-dev
@@ -0,0 +1 @@
+../ts-node-dev/lib/bin.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node-esm b/backend/node_modules/.bin/ts-node-esm
new file mode 120000
index 0000000..a19d9ed
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node-esm
@@ -0,0 +1 @@
+../ts-node/dist/bin-esm.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node-script b/backend/node_modules/.bin/ts-node-script
new file mode 120000
index 0000000..edc40b3
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node-script
@@ -0,0 +1 @@
+../ts-node/dist/bin-script.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-node-transpile-only b/backend/node_modules/.bin/ts-node-transpile-only
new file mode 120000
index 0000000..173710d
--- /dev/null
+++ b/backend/node_modules/.bin/ts-node-transpile-only
@@ -0,0 +1 @@
+../ts-node/dist/bin-transpile.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/ts-script b/backend/node_modules/.bin/ts-script
new file mode 120000
index 0000000..7382912
--- /dev/null
+++ b/backend/node_modules/.bin/ts-script
@@ -0,0 +1 @@
+../ts-node/dist/bin-script-deprecated.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/tsc b/backend/node_modules/.bin/tsc
new file mode 120000
index 0000000..0863208
--- /dev/null
+++ b/backend/node_modules/.bin/tsc
@@ -0,0 +1 @@
+../typescript/bin/tsc
\ No newline at end of file
diff --git a/backend/node_modules/.bin/tsnd b/backend/node_modules/.bin/tsnd
new file mode 120000
index 0000000..4683cb2
--- /dev/null
+++ b/backend/node_modules/.bin/tsnd
@@ -0,0 +1 @@
+../ts-node-dev/lib/bin.js
\ No newline at end of file
diff --git a/backend/node_modules/.bin/tsserver b/backend/node_modules/.bin/tsserver
new file mode 120000
index 0000000..f8f8f1a
--- /dev/null
+++ b/backend/node_modules/.bin/tsserver
@@ -0,0 +1 @@
+../typescript/bin/tsserver
\ No newline at end of file
diff --git a/backend/node_modules/.package-lock.json b/backend/node_modules/.package-lock.json
new file mode 100644
index 0000000..14b8e40
--- /dev/null
+++ b/backend/node_modules/.package-lock.json
@@ -0,0 +1,1985 @@
+{
+ "name": "owl-stream-backend",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@prisma/client": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz",
+ "integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.13"
+ },
+ "peerDependencies": {
+ "prisma": "*"
+ },
+ "peerDependenciesMeta": {
+ "prisma": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@prisma/debug": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz",
+ "integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/engines": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz",
+ "integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/fetch-engine": "5.22.0",
+ "@prisma/get-platform": "5.22.0"
+ }
+ },
+ "node_modules/@prisma/engines-version": {
+ "version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz",
+ "integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/fetch-engine": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz",
+ "integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/get-platform": "5.22.0"
+ }
+ },
+ "node_modules/@prisma/get-platform": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz",
+ "integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
+ "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/bcryptjs": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
+ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.19",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.25",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
+ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "^1"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.19.8",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
+ "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jsonwebtoken": {
+ "version": "9.0.10",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
+ "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.33",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz",
+ "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
+ "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "<1"
+ }
+ },
+ "node_modules/@types/serve-static/node_modules/@types/send": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
+ "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/strip-json-comments": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
+ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.4",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
+ "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.14.0",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+ "license": "MIT"
+ },
+ "node_modules/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/diff": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
+ "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/dynamic-dedupe": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
+ "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "~0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "~6.14.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "~2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express-validator": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.3.1.tgz",
+ "integrity": "sha512-IGenaSf+DnWc69lKuqlRE9/i/2t5/16VpH5bXoqdxWz1aCpRvEdrBuu1y95i/iL5QP8ZYVATiwLFhwk3EDl5vg==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "validator": "~13.15.23"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "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",
+ "parseurl": "~1.3.3",
+ "statuses": "~2.0.2",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "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": "^4.0.1",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jsonwebtoken/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/jwa": {
+ "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",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "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": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT"
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prisma": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz",
+ "integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/engines": "5.22.0"
+ },
+ "bin": {
+ "prisma": "build/index.js"
+ },
+ "engines": {
+ "node": ">=16.13"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.3"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
+ "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "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": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "~2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "~2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.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.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "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/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tree-kill": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "tree-kill": "cli.js"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-node-dev": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
+ "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^3.5.1",
+ "dynamic-dedupe": "^0.3.0",
+ "minimist": "^1.2.6",
+ "mkdirp": "^1.0.4",
+ "resolve": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "source-map-support": "^0.5.12",
+ "tree-kill": "^1.2.2",
+ "ts-node": "^10.4.0",
+ "tsconfig": "^7.0.0"
+ },
+ "bin": {
+ "ts-node-dev": "lib/bin.js",
+ "tsnd": "lib/bin.js"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "*",
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tsconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
+ "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/strip-bom": "^3.0.0",
+ "@types/strip-json-comments": "0.0.30",
+ "strip-bom": "^3.0.0",
+ "strip-json-comments": "^2.0.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/validator": {
+ "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"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ }
+ }
+}
diff --git a/backend/node_modules/.prisma/client/default.d.ts b/backend/node_modules/.prisma/client/default.d.ts
new file mode 100644
index 0000000..bc20c6c
--- /dev/null
+++ b/backend/node_modules/.prisma/client/default.d.ts
@@ -0,0 +1 @@
+export * from "./index"
\ No newline at end of file
diff --git a/backend/node_modules/.prisma/client/default.js b/backend/node_modules/.prisma/client/default.js
new file mode 100644
index 0000000..fa52f0c
--- /dev/null
+++ b/backend/node_modules/.prisma/client/default.js
@@ -0,0 +1 @@
+module.exports = { ...require('.') }
\ No newline at end of file
diff --git a/backend/node_modules/.prisma/client/deno/edge.d.ts b/backend/node_modules/.prisma/client/deno/edge.d.ts
new file mode 100644
index 0000000..bca0a97
--- /dev/null
+++ b/backend/node_modules/.prisma/client/deno/edge.d.ts
@@ -0,0 +1,9 @@
+class PrismaClient {
+ constructor() {
+ throw new Error(
+ '@prisma/client/deno/edge did not initialize yet. Please run "prisma generate" and try to import it again.',
+ )
+ }
+}
+
+export { PrismaClient }
diff --git a/backend/node_modules/.prisma/client/edge.d.ts b/backend/node_modules/.prisma/client/edge.d.ts
new file mode 100644
index 0000000..274b8fa
--- /dev/null
+++ b/backend/node_modules/.prisma/client/edge.d.ts
@@ -0,0 +1 @@
+export * from "./default"
\ No newline at end of file
diff --git a/backend/node_modules/.prisma/client/edge.js b/backend/node_modules/.prisma/client/edge.js
new file mode 100644
index 0000000..fabdd49
--- /dev/null
+++ b/backend/node_modules/.prisma/client/edge.js
@@ -0,0 +1,310 @@
+
+Object.defineProperty(exports, "__esModule", { value: true });
+
+const {
+ PrismaClientKnownRequestError,
+ PrismaClientUnknownRequestError,
+ PrismaClientRustPanicError,
+ PrismaClientInitializationError,
+ PrismaClientValidationError,
+ NotFoundError,
+ getPrismaClient,
+ sqltag,
+ empty,
+ join,
+ raw,
+ skip,
+ Decimal,
+ Debug,
+ objectEnumValues,
+ makeStrictEnum,
+ Extensions,
+ warnOnce,
+ defineDmmfProperty,
+ Public,
+ getRuntime
+} = require('@prisma/client/runtime/edge.js')
+
+
+const Prisma = {}
+
+exports.Prisma = Prisma
+exports.$Enums = {}
+
+/**
+ * Prisma Client JS version: 5.22.0
+ * Query Engine version: 605197351a3c8bdd595af2d2a9bc3025bca48ea2
+ */
+Prisma.prismaVersion = {
+ client: "5.22.0",
+ engine: "605197351a3c8bdd595af2d2a9bc3025bca48ea2"
+}
+
+Prisma.PrismaClientKnownRequestError = PrismaClientKnownRequestError;
+Prisma.PrismaClientUnknownRequestError = PrismaClientUnknownRequestError
+Prisma.PrismaClientRustPanicError = PrismaClientRustPanicError
+Prisma.PrismaClientInitializationError = PrismaClientInitializationError
+Prisma.PrismaClientValidationError = PrismaClientValidationError
+Prisma.NotFoundError = NotFoundError
+Prisma.Decimal = Decimal
+
+/**
+ * Re-export of sql-template-tag
+ */
+Prisma.sql = sqltag
+Prisma.empty = empty
+Prisma.join = join
+Prisma.raw = raw
+Prisma.validator = Public.validator
+
+/**
+* Extensions
+*/
+Prisma.getExtensionContext = Extensions.getExtensionContext
+Prisma.defineExtension = Extensions.defineExtension
+
+/**
+ * Shorthand utilities for JSON filtering
+ */
+Prisma.DbNull = objectEnumValues.instances.DbNull
+Prisma.JsonNull = objectEnumValues.instances.JsonNull
+Prisma.AnyNull = objectEnumValues.instances.AnyNull
+
+Prisma.NullTypes = {
+ DbNull: objectEnumValues.classes.DbNull,
+ JsonNull: objectEnumValues.classes.JsonNull,
+ AnyNull: objectEnumValues.classes.AnyNull
+}
+
+
+
+
+
+/**
+ * Enums
+ */
+exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
+ ReadUncommitted: 'ReadUncommitted',
+ ReadCommitted: 'ReadCommitted',
+ RepeatableRead: 'RepeatableRead',
+ Serializable: 'Serializable'
+});
+
+exports.Prisma.UserScalarFieldEnum = {
+ id: 'id',
+ email: 'email',
+ name: 'name',
+ role: 'role',
+ password_hash: 'password_hash',
+ created_at: 'created_at'
+};
+
+exports.Prisma.BurrowScalarFieldEnum = {
+ id: 'id',
+ gps_lat: 'gps_lat',
+ gps_lng: 'gps_lng',
+ status: 'status',
+ location_description: 'location_description',
+ photos: 'photos',
+ assigned_volunteer_id: 'assigned_volunteer_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.DonationScalarFieldEnum = {
+ id: 'id',
+ donor_id: 'donor_id',
+ amount: 'amount',
+ campaign: 'campaign',
+ stripe_payment_id: 'stripe_payment_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.WildlifeSightingScalarFieldEnum = {
+ id: 'id',
+ reporter_id: 'reporter_id',
+ species: 'species',
+ gps_lat: 'gps_lat',
+ gps_lng: 'gps_lng',
+ photo_url: 'photo_url',
+ description: 'description',
+ verified: 'verified',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EventScalarFieldEnum = {
+ id: 'id',
+ title: 'title',
+ description: 'description',
+ date: 'date',
+ location: 'location',
+ max_attendees: 'max_attendees',
+ type: 'type',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EventRSVPScalarFieldEnum = {
+ event_id: 'event_id',
+ user_id: 'user_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.LivestreamSourceScalarFieldEnum = {
+ id: 'id',
+ name: 'name',
+ stream_url: 'stream_url',
+ camera_location: 'camera_location',
+ status: 'status',
+ thumbnail_url: 'thumbnail_url',
+ created_at: 'created_at'
+};
+
+exports.Prisma.VolunteerHourScalarFieldEnum = {
+ id: 'id',
+ volunteer_id: 'volunteer_id',
+ date: 'date',
+ hours: 'hours',
+ task_description: 'task_description',
+ verified_by: 'verified_by',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EquipmentItemScalarFieldEnum = {
+ id: 'id',
+ name: 'name',
+ description: 'description',
+ status: 'status',
+ checked_out_by: 'checked_out_by',
+ checked_out_at: 'checked_out_at',
+ created_at: 'created_at'
+};
+
+exports.Prisma.SortOrder = {
+ asc: 'asc',
+ desc: 'desc'
+};
+
+exports.Prisma.QueryMode = {
+ default: 'default',
+ insensitive: 'insensitive'
+};
+
+exports.Prisma.NullsOrder = {
+ first: 'first',
+ last: 'last'
+};
+exports.UserRole = exports.$Enums.UserRole = {
+ admin: 'admin',
+ volunteer: 'volunteer',
+ donor: 'donor',
+ public: 'public'
+};
+
+exports.BurrowStatus = exports.$Enums.BurrowStatus = {
+ active: 'active',
+ inactive: 'inactive',
+ destroyed: 'destroyed'
+};
+
+exports.DonationCampaign = exports.$Enums.DonationCampaign = {
+ land_preservation: 'land_preservation',
+ volunteer_equipment: 'volunteer_equipment',
+ general: 'general'
+};
+
+exports.EventType = exports.$Enums.EventType = {
+ cleanup: 'cleanup',
+ educational: 'educational',
+ fundraiser: 'fundraiser'
+};
+
+exports.StreamStatus = exports.$Enums.StreamStatus = {
+ live: 'live',
+ offline: 'offline'
+};
+
+exports.EquipmentStatus = exports.$Enums.EquipmentStatus = {
+ available: 'available',
+ checked_out: 'checked_out'
+};
+
+exports.Prisma.ModelName = {
+ User: 'User',
+ Burrow: 'Burrow',
+ Donation: 'Donation',
+ WildlifeSighting: 'WildlifeSighting',
+ Event: 'Event',
+ EventRSVP: 'EventRSVP',
+ LivestreamSource: 'LivestreamSource',
+ VolunteerHour: 'VolunteerHour',
+ EquipmentItem: 'EquipmentItem'
+};
+/**
+ * Create the Client
+ */
+const config = {
+ "generator": {
+ "name": "client",
+ "provider": {
+ "fromEnvVar": null,
+ "value": "prisma-client-js"
+ },
+ "output": {
+ "value": "/opt/owl-stream/backend/node_modules/@prisma/client",
+ "fromEnvVar": null
+ },
+ "config": {
+ "engineType": "library"
+ },
+ "binaryTargets": [
+ {
+ "fromEnvVar": null,
+ "value": "debian-openssl-3.0.x",
+ "native": true
+ }
+ ],
+ "previewFeatures": [],
+ "sourceFilePath": "/opt/owl-stream/backend/prisma/schema.prisma"
+ },
+ "relativeEnvPaths": {
+ "rootEnvPath": null
+ },
+ "relativePath": "../../../prisma",
+ "clientVersion": "5.22.0",
+ "engineVersion": "605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "datasourceNames": [
+ "db"
+ ],
+ "activeProvider": "postgresql",
+ "postinstall": false,
+ "inlineDatasources": {
+ "db": {
+ "url": {
+ "fromEnvVar": "DATABASE_URL",
+ "value": null
+ }
+ }
+ },
+ "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\n\nenum UserRole {\n admin\n volunteer\n donor\n public\n}\n\nenum BurrowStatus {\n active\n inactive\n destroyed\n}\n\nenum DonationCampaign {\n land_preservation\n volunteer_equipment\n general\n}\n\nenum EventType {\n cleanup\n educational\n fundraiser\n}\n\nenum StreamStatus {\n live\n offline\n}\n\nenum EquipmentStatus {\n available\n checked_out\n}\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n name String\n role UserRole @default(public)\n password_hash String\n created_at DateTime @default(now())\n\n burrows Burrow[] @relation(\"AssignedVolunteer\")\n donations Donation[]\n sightings WildlifeSighting[] @relation(\"SightingReporter\")\n event_rsvps EventRSVP[]\n volunteer_hours VolunteerHour[]\n equipment_items EquipmentItem[] @relation(\"CheckedOutBy\")\n verified_hours VolunteerHour[] @relation(\"VerifiedBy\")\n\n @@map(\"users\")\n}\n\nmodel Burrow {\n id String @id @default(cuid())\n gps_lat Float\n gps_lng Float\n status BurrowStatus @default(active)\n location_description String?\n photos String[] @default([])\n assigned_volunteer_id String?\n created_at DateTime @default(now())\n\n assigned_volunteer User? @relation(\"AssignedVolunteer\", fields: [assigned_volunteer_id], references: [id], onDelete: SetNull)\n\n @@map(\"burrows\")\n}\n\nmodel Donation {\n id String @id @default(cuid())\n donor_id String?\n amount Float\n campaign DonationCampaign @default(general)\n stripe_payment_id String?\n created_at DateTime @default(now())\n\n donor User? @relation(fields: [donor_id], references: [id], onDelete: SetNull)\n\n @@map(\"donations\")\n}\n\nmodel WildlifeSighting {\n id String @id @default(cuid())\n reporter_id String?\n species String\n gps_lat Float\n gps_lng Float\n photo_url String?\n description String?\n verified Boolean @default(false)\n created_at DateTime @default(now())\n\n reporter User? @relation(\"SightingReporter\", fields: [reporter_id], references: [id], onDelete: SetNull)\n\n @@map(\"wildlife_sightings\")\n}\n\nmodel Event {\n id String @id @default(cuid())\n title String\n description String?\n date DateTime\n location String\n max_attendees Int?\n type EventType\n created_at DateTime @default(now())\n\n rsvps EventRSVP[]\n\n @@map(\"events\")\n}\n\nmodel EventRSVP {\n event_id String\n user_id String\n created_at DateTime @default(now())\n\n event Event @relation(fields: [event_id], references: [id], onDelete: Cascade)\n user User @relation(fields: [user_id], references: [id], onDelete: Cascade)\n\n @@id([event_id, user_id])\n @@map(\"event_rsvps\")\n}\n\nmodel LivestreamSource {\n id String @id @default(cuid())\n name String\n stream_url String\n camera_location String\n status StreamStatus @default(offline)\n thumbnail_url String?\n created_at DateTime @default(now())\n\n @@map(\"livestream_sources\")\n}\n\nmodel VolunteerHour {\n id String @id @default(cuid())\n volunteer_id String\n date DateTime\n hours Float\n task_description String\n verified_by String?\n created_at DateTime @default(now())\n\n volunteer User @relation(fields: [volunteer_id], references: [id], onDelete: Cascade)\n verifier User? @relation(\"VerifiedBy\", fields: [verified_by], references: [id], onDelete: SetNull)\n\n @@map(\"volunteer_hours\")\n}\n\nmodel EquipmentItem {\n id String @id @default(cuid())\n name String\n description String?\n status EquipmentStatus @default(available)\n checked_out_by String?\n checked_out_at DateTime?\n created_at DateTime @default(now())\n\n checker User? @relation(\"CheckedOutBy\", fields: [checked_out_by], references: [id], onDelete: SetNull)\n\n @@map(\"equipment_items\")\n}\n",
+ "inlineSchemaHash": "3db747e2a5cdbee3412640a8a6a0b5c6660c177afd4f7b982bdbf2408a853a18",
+ "copyEngine": true
+}
+config.dirname = '/'
+
+config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"dbName\":\"users\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"UserRole\",\"default\":\"public\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password_hash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"burrows\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Burrow\",\"relationName\":\"AssignedVolunteer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"donations\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Donation\",\"relationName\":\"DonationToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sightings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"WildlifeSighting\",\"relationName\":\"SightingReporter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"event_rsvps\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EventRSVP\",\"relationName\":\"EventRSVPToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"volunteer_hours\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"VolunteerHour\",\"relationName\":\"UserToVolunteerHour\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"equipment_items\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EquipmentItem\",\"relationName\":\"CheckedOutBy\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"verified_hours\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"VolunteerHour\",\"relationName\":\"VerifiedBy\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Burrow\":{\"dbName\":\"burrows\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"gps_lat\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"gps_lng\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"BurrowStatus\",\"default\":\"active\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location_description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"photos\",\"kind\":\"scalar\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assigned_volunteer_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assigned_volunteer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"AssignedVolunteer\",\"relationFromFields\":[\"assigned_volunteer_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Donation\":{\"dbName\":\"donations\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"donor_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"amount\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"campaign\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DonationCampaign\",\"default\":\"general\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stripe_payment_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"donor\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"DonationToUser\",\"relationFromFields\":[\"donor_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"WildlifeSighting\":{\"dbName\":\"wildlife_sightings\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"reporter_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"species\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"gps_lat\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"gps_lng\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"photo_url\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"verified\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"reporter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"SightingReporter\",\"relationFromFields\":[\"reporter_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Event\":{\"dbName\":\"events\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"date\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"max_attendees\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EventType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"rsvps\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EventRSVP\",\"relationName\":\"EventToEventRSVP\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EventRSVP\":{\"dbName\":\"event_rsvps\",\"fields\":[{\"name\":\"event_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"event\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Event\",\"relationName\":\"EventToEventRSVP\",\"relationFromFields\":[\"event_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"EventRSVPToUser\",\"relationFromFields\":[\"user_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"event_id\",\"user_id\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"LivestreamSource\":{\"dbName\":\"livestream_sources\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stream_url\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"camera_location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"StreamStatus\",\"default\":\"offline\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"thumbnail_url\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"VolunteerHour\":{\"dbName\":\"volunteer_hours\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"volunteer_id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"date\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hours\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"task_description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"verified_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"volunteer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"UserToVolunteerHour\",\"relationFromFields\":[\"volunteer_id\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"verifier\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"VerifiedBy\",\"relationFromFields\":[\"verified_by\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EquipmentItem\":{\"dbName\":\"equipment_items\",\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":{\"name\":\"cuid\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"EquipmentStatus\",\"default\":\"available\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"checked_out_by\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"checked_out_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"created_at\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"checker\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"CheckedOutBy\",\"relationFromFields\":[\"checked_out_by\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"UserRole\":{\"values\":[{\"name\":\"admin\",\"dbName\":null},{\"name\":\"volunteer\",\"dbName\":null},{\"name\":\"donor\",\"dbName\":null},{\"name\":\"public\",\"dbName\":null}],\"dbName\":null},\"BurrowStatus\":{\"values\":[{\"name\":\"active\",\"dbName\":null},{\"name\":\"inactive\",\"dbName\":null},{\"name\":\"destroyed\",\"dbName\":null}],\"dbName\":null},\"DonationCampaign\":{\"values\":[{\"name\":\"land_preservation\",\"dbName\":null},{\"name\":\"volunteer_equipment\",\"dbName\":null},{\"name\":\"general\",\"dbName\":null}],\"dbName\":null},\"EventType\":{\"values\":[{\"name\":\"cleanup\",\"dbName\":null},{\"name\":\"educational\",\"dbName\":null},{\"name\":\"fundraiser\",\"dbName\":null}],\"dbName\":null},\"StreamStatus\":{\"values\":[{\"name\":\"live\",\"dbName\":null},{\"name\":\"offline\",\"dbName\":null}],\"dbName\":null},\"EquipmentStatus\":{\"values\":[{\"name\":\"available\",\"dbName\":null},{\"name\":\"checked_out\",\"dbName\":null}],\"dbName\":null}},\"types\":{}}")
+defineDmmfProperty(exports.Prisma, config.runtimeDataModel)
+config.engineWasm = undefined
+
+config.injectableEdgeEnv = () => ({
+ parsed: {
+ DATABASE_URL: typeof globalThis !== 'undefined' && globalThis['DATABASE_URL'] || typeof process !== 'undefined' && process.env && process.env.DATABASE_URL || undefined
+ }
+})
+
+if (typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined) {
+ Debug.enable(typeof globalThis !== 'undefined' && globalThis['DEBUG'] || typeof process !== 'undefined' && process.env && process.env.DEBUG || undefined)
+}
+
+const PrismaClient = getPrismaClient(config)
+exports.PrismaClient = PrismaClient
+Object.assign(exports, Prisma)
+
diff --git a/backend/node_modules/.prisma/client/index-browser.js b/backend/node_modules/.prisma/client/index-browser.js
new file mode 100644
index 0000000..692eb48
--- /dev/null
+++ b/backend/node_modules/.prisma/client/index-browser.js
@@ -0,0 +1,303 @@
+
+Object.defineProperty(exports, "__esModule", { value: true });
+
+const {
+ Decimal,
+ objectEnumValues,
+ makeStrictEnum,
+ Public,
+ getRuntime,
+ skip
+} = require('@prisma/client/runtime/index-browser.js')
+
+
+const Prisma = {}
+
+exports.Prisma = Prisma
+exports.$Enums = {}
+
+/**
+ * Prisma Client JS version: 5.22.0
+ * Query Engine version: 605197351a3c8bdd595af2d2a9bc3025bca48ea2
+ */
+Prisma.prismaVersion = {
+ client: "5.22.0",
+ engine: "605197351a3c8bdd595af2d2a9bc3025bca48ea2"
+}
+
+Prisma.PrismaClientKnownRequestError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)};
+Prisma.PrismaClientUnknownRequestError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.PrismaClientRustPanicError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.PrismaClientInitializationError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.PrismaClientValidationError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.NotFoundError = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`NotFoundError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.Decimal = Decimal
+
+/**
+ * Re-export of sql-template-tag
+ */
+Prisma.sql = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.empty = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.join = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.raw = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.validator = Public.validator
+
+/**
+* Extensions
+*/
+Prisma.getExtensionContext = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+Prisma.defineExtension = () => {
+ const runtimeName = getRuntime().prettyName;
+ throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
+In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
+)}
+
+/**
+ * Shorthand utilities for JSON filtering
+ */
+Prisma.DbNull = objectEnumValues.instances.DbNull
+Prisma.JsonNull = objectEnumValues.instances.JsonNull
+Prisma.AnyNull = objectEnumValues.instances.AnyNull
+
+Prisma.NullTypes = {
+ DbNull: objectEnumValues.classes.DbNull,
+ JsonNull: objectEnumValues.classes.JsonNull,
+ AnyNull: objectEnumValues.classes.AnyNull
+}
+
+
+
+/**
+ * Enums
+ */
+
+exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
+ ReadUncommitted: 'ReadUncommitted',
+ ReadCommitted: 'ReadCommitted',
+ RepeatableRead: 'RepeatableRead',
+ Serializable: 'Serializable'
+});
+
+exports.Prisma.UserScalarFieldEnum = {
+ id: 'id',
+ email: 'email',
+ name: 'name',
+ role: 'role',
+ password_hash: 'password_hash',
+ created_at: 'created_at'
+};
+
+exports.Prisma.BurrowScalarFieldEnum = {
+ id: 'id',
+ gps_lat: 'gps_lat',
+ gps_lng: 'gps_lng',
+ status: 'status',
+ location_description: 'location_description',
+ photos: 'photos',
+ assigned_volunteer_id: 'assigned_volunteer_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.DonationScalarFieldEnum = {
+ id: 'id',
+ donor_id: 'donor_id',
+ amount: 'amount',
+ campaign: 'campaign',
+ stripe_payment_id: 'stripe_payment_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.WildlifeSightingScalarFieldEnum = {
+ id: 'id',
+ reporter_id: 'reporter_id',
+ species: 'species',
+ gps_lat: 'gps_lat',
+ gps_lng: 'gps_lng',
+ photo_url: 'photo_url',
+ description: 'description',
+ verified: 'verified',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EventScalarFieldEnum = {
+ id: 'id',
+ title: 'title',
+ description: 'description',
+ date: 'date',
+ location: 'location',
+ max_attendees: 'max_attendees',
+ type: 'type',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EventRSVPScalarFieldEnum = {
+ event_id: 'event_id',
+ user_id: 'user_id',
+ created_at: 'created_at'
+};
+
+exports.Prisma.LivestreamSourceScalarFieldEnum = {
+ id: 'id',
+ name: 'name',
+ stream_url: 'stream_url',
+ camera_location: 'camera_location',
+ status: 'status',
+ thumbnail_url: 'thumbnail_url',
+ created_at: 'created_at'
+};
+
+exports.Prisma.VolunteerHourScalarFieldEnum = {
+ id: 'id',
+ volunteer_id: 'volunteer_id',
+ date: 'date',
+ hours: 'hours',
+ task_description: 'task_description',
+ verified_by: 'verified_by',
+ created_at: 'created_at'
+};
+
+exports.Prisma.EquipmentItemScalarFieldEnum = {
+ id: 'id',
+ name: 'name',
+ description: 'description',
+ status: 'status',
+ checked_out_by: 'checked_out_by',
+ checked_out_at: 'checked_out_at',
+ created_at: 'created_at'
+};
+
+exports.Prisma.SortOrder = {
+ asc: 'asc',
+ desc: 'desc'
+};
+
+exports.Prisma.QueryMode = {
+ default: 'default',
+ insensitive: 'insensitive'
+};
+
+exports.Prisma.NullsOrder = {
+ first: 'first',
+ last: 'last'
+};
+exports.UserRole = exports.$Enums.UserRole = {
+ admin: 'admin',
+ volunteer: 'volunteer',
+ donor: 'donor',
+ public: 'public'
+};
+
+exports.BurrowStatus = exports.$Enums.BurrowStatus = {
+ active: 'active',
+ inactive: 'inactive',
+ destroyed: 'destroyed'
+};
+
+exports.DonationCampaign = exports.$Enums.DonationCampaign = {
+ land_preservation: 'land_preservation',
+ volunteer_equipment: 'volunteer_equipment',
+ general: 'general'
+};
+
+exports.EventType = exports.$Enums.EventType = {
+ cleanup: 'cleanup',
+ educational: 'educational',
+ fundraiser: 'fundraiser'
+};
+
+exports.StreamStatus = exports.$Enums.StreamStatus = {
+ live: 'live',
+ offline: 'offline'
+};
+
+exports.EquipmentStatus = exports.$Enums.EquipmentStatus = {
+ available: 'available',
+ checked_out: 'checked_out'
+};
+
+exports.Prisma.ModelName = {
+ User: 'User',
+ Burrow: 'Burrow',
+ Donation: 'Donation',
+ WildlifeSighting: 'WildlifeSighting',
+ Event: 'Event',
+ EventRSVP: 'EventRSVP',
+ LivestreamSource: 'LivestreamSource',
+ VolunteerHour: 'VolunteerHour',
+ EquipmentItem: 'EquipmentItem'
+};
+
+/**
+ * This is a stub Prisma Client that will error at runtime if called.
+ */
+class PrismaClient {
+ constructor() {
+ return new Proxy(this, {
+ get(target, prop) {
+ let message
+ const runtime = getRuntime()
+ if (runtime.isEdge) {
+ message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
+- Use Prisma Accelerate: https://pris.ly/d/accelerate
+- Use Driver Adapters: https://pris.ly/d/driver-adapters
+`;
+ } else {
+ message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
+ }
+
+ message += `
+If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
+
+ throw new Error(message)
+ }
+ })
+ }
+}
+
+exports.PrismaClient = PrismaClient
+
+Object.assign(exports, Prisma)
diff --git a/backend/node_modules/.prisma/client/index.d.ts b/backend/node_modules/.prisma/client/index.d.ts
new file mode 100644
index 0000000..afcbc3d
--- /dev/null
+++ b/backend/node_modules/.prisma/client/index.d.ts
@@ -0,0 +1,15103 @@
+
+/**
+ * Client
+**/
+
+import * as runtime from '@prisma/client/runtime/library.js';
+import $Types = runtime.Types // general types
+import $Public = runtime.Types.Public
+import $Utils = runtime.Types.Utils
+import $Extensions = runtime.Types.Extensions
+import $Result = runtime.Types.Result
+
+export type PrismaPromise = $Public.PrismaPromise
+
+
+/**
+ * Model User
+ *
+ */
+export type User = $Result.DefaultSelection
+/**
+ * Model Burrow
+ *
+ */
+export type Burrow = $Result.DefaultSelection
+/**
+ * Model Donation
+ *
+ */
+export type Donation = $Result.DefaultSelection
+/**
+ * Model WildlifeSighting
+ *
+ */
+export type WildlifeSighting = $Result.DefaultSelection
+/**
+ * Model Event
+ *
+ */
+export type Event = $Result.DefaultSelection
+/**
+ * Model EventRSVP
+ *
+ */
+export type EventRSVP = $Result.DefaultSelection
+/**
+ * Model LivestreamSource
+ *
+ */
+export type LivestreamSource = $Result.DefaultSelection
+/**
+ * Model VolunteerHour
+ *
+ */
+export type VolunteerHour = $Result.DefaultSelection
+/**
+ * Model EquipmentItem
+ *
+ */
+export type EquipmentItem = $Result.DefaultSelection
+
+/**
+ * Enums
+ */
+export namespace $Enums {
+ export const UserRole: {
+ admin: 'admin',
+ volunteer: 'volunteer',
+ donor: 'donor',
+ public: 'public'
+};
+
+export type UserRole = (typeof UserRole)[keyof typeof UserRole]
+
+
+export const BurrowStatus: {
+ active: 'active',
+ inactive: 'inactive',
+ destroyed: 'destroyed'
+};
+
+export type BurrowStatus = (typeof BurrowStatus)[keyof typeof BurrowStatus]
+
+
+export const DonationCampaign: {
+ land_preservation: 'land_preservation',
+ volunteer_equipment: 'volunteer_equipment',
+ general: 'general'
+};
+
+export type DonationCampaign = (typeof DonationCampaign)[keyof typeof DonationCampaign]
+
+
+export const EventType: {
+ cleanup: 'cleanup',
+ educational: 'educational',
+ fundraiser: 'fundraiser'
+};
+
+export type EventType = (typeof EventType)[keyof typeof EventType]
+
+
+export const StreamStatus: {
+ live: 'live',
+ offline: 'offline'
+};
+
+export type StreamStatus = (typeof StreamStatus)[keyof typeof StreamStatus]
+
+
+export const EquipmentStatus: {
+ available: 'available',
+ checked_out: 'checked_out'
+};
+
+export type EquipmentStatus = (typeof EquipmentStatus)[keyof typeof EquipmentStatus]
+
+}
+
+export type UserRole = $Enums.UserRole
+
+export const UserRole: typeof $Enums.UserRole
+
+export type BurrowStatus = $Enums.BurrowStatus
+
+export const BurrowStatus: typeof $Enums.BurrowStatus
+
+export type DonationCampaign = $Enums.DonationCampaign
+
+export const DonationCampaign: typeof $Enums.DonationCampaign
+
+export type EventType = $Enums.EventType
+
+export const EventType: typeof $Enums.EventType
+
+export type StreamStatus = $Enums.StreamStatus
+
+export const StreamStatus: typeof $Enums.StreamStatus
+
+export type EquipmentStatus = $Enums.EquipmentStatus
+
+export const EquipmentStatus: typeof $Enums.EquipmentStatus
+
+/**
+ * ## Prisma Client ʲˢ
+ *
+ * Type-safe database client for TypeScript & Node.js
+ * @example
+ * ```
+ * const prisma = new PrismaClient()
+ * // Fetch zero or more Users
+ * const users = await prisma.user.findMany()
+ * ```
+ *
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client).
+ */
+export class PrismaClient<
+ ClientOptions extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions,
+ U = 'log' extends keyof ClientOptions ? ClientOptions['log'] extends Array ? Prisma.GetEvents : never : never,
+ ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs
+> {
+ [K: symbol]: { types: Prisma.TypeMap['other'] }
+
+ /**
+ * ## Prisma Client ʲˢ
+ *
+ * Type-safe database client for TypeScript & Node.js
+ * @example
+ * ```
+ * const prisma = new PrismaClient()
+ * // Fetch zero or more Users
+ * const users = await prisma.user.findMany()
+ * ```
+ *
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client).
+ */
+
+ constructor(optionsArg ?: Prisma.Subset);
+ $on(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): void;
+
+ /**
+ * Connect with the database
+ */
+ $connect(): $Utils.JsPromise;
+
+ /**
+ * Disconnect from the database
+ */
+ $disconnect(): $Utils.JsPromise;
+
+ /**
+ * Add a middleware
+ * @deprecated since 4.16.0. For new code, prefer client extensions instead.
+ * @see https://pris.ly/d/extensions
+ */
+ $use(cb: Prisma.Middleware): void
+
+/**
+ * Executes a prepared raw query and returns the number of affected rows.
+ * @example
+ * ```
+ * const result = await prisma.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`
+ * ```
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
+ */
+ $executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise;
+
+ /**
+ * Executes a raw query and returns the number of affected rows.
+ * Susceptible to SQL injections, see documentation.
+ * @example
+ * ```
+ * const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com')
+ * ```
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
+ */
+ $executeRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise;
+
+ /**
+ * Performs a prepared raw query and returns the `SELECT` data.
+ * @example
+ * ```
+ * const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`
+ * ```
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
+ */
+ $queryRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise;
+
+ /**
+ * Performs a raw query and returns the `SELECT` data.
+ * Susceptible to SQL injections, see documentation.
+ * @example
+ * ```
+ * const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com')
+ * ```
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access).
+ */
+ $queryRawUnsafe(query: string, ...values: any[]): Prisma.PrismaPromise;
+
+
+ /**
+ * Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole.
+ * @example
+ * ```
+ * const [george, bob, alice] = await prisma.$transaction([
+ * prisma.user.create({ data: { name: 'George' } }),
+ * prisma.user.create({ data: { name: 'Bob' } }),
+ * prisma.user.create({ data: { name: 'Alice' } }),
+ * ])
+ * ```
+ *
+ * Read more in our [docs](https://www.prisma.io/docs/concepts/components/prisma-client/transactions).
+ */
+ $transaction[]>(arg: [...P], options?: { isolationLevel?: Prisma.TransactionIsolationLevel }): $Utils.JsPromise>
+
+ $transaction(fn: (prisma: Omit) => $Utils.JsPromise, options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): $Utils.JsPromise
+
+
+ $extends: $Extensions.ExtendsHook<"extends", Prisma.TypeMapCb, ExtArgs>
+
+ /**
+ * `prisma.user`: Exposes CRUD operations for the **User** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more Users
+ * const users = await prisma.user.findMany()
+ * ```
+ */
+ get user(): Prisma.UserDelegate;
+
+ /**
+ * `prisma.burrow`: Exposes CRUD operations for the **Burrow** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more Burrows
+ * const burrows = await prisma.burrow.findMany()
+ * ```
+ */
+ get burrow(): Prisma.BurrowDelegate;
+
+ /**
+ * `prisma.donation`: Exposes CRUD operations for the **Donation** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more Donations
+ * const donations = await prisma.donation.findMany()
+ * ```
+ */
+ get donation(): Prisma.DonationDelegate;
+
+ /**
+ * `prisma.wildlifeSighting`: Exposes CRUD operations for the **WildlifeSighting** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more WildlifeSightings
+ * const wildlifeSightings = await prisma.wildlifeSighting.findMany()
+ * ```
+ */
+ get wildlifeSighting(): Prisma.WildlifeSightingDelegate;
+
+ /**
+ * `prisma.event`: Exposes CRUD operations for the **Event** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more Events
+ * const events = await prisma.event.findMany()
+ * ```
+ */
+ get event(): Prisma.EventDelegate;
+
+ /**
+ * `prisma.eventRSVP`: Exposes CRUD operations for the **EventRSVP** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more EventRSVPS
+ * const eventRSVPS = await prisma.eventRSVP.findMany()
+ * ```
+ */
+ get eventRSVP(): Prisma.EventRSVPDelegate;
+
+ /**
+ * `prisma.livestreamSource`: Exposes CRUD operations for the **LivestreamSource** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more LivestreamSources
+ * const livestreamSources = await prisma.livestreamSource.findMany()
+ * ```
+ */
+ get livestreamSource(): Prisma.LivestreamSourceDelegate;
+
+ /**
+ * `prisma.volunteerHour`: Exposes CRUD operations for the **VolunteerHour** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more VolunteerHours
+ * const volunteerHours = await prisma.volunteerHour.findMany()
+ * ```
+ */
+ get volunteerHour(): Prisma.VolunteerHourDelegate;
+
+ /**
+ * `prisma.equipmentItem`: Exposes CRUD operations for the **EquipmentItem** model.
+ * Example usage:
+ * ```ts
+ * // Fetch zero or more EquipmentItems
+ * const equipmentItems = await prisma.equipmentItem.findMany()
+ * ```
+ */
+ get equipmentItem(): Prisma.EquipmentItemDelegate;
+}
+
+export namespace Prisma {
+ export import DMMF = runtime.DMMF
+
+ export type PrismaPromise = $Public.PrismaPromise
+
+ /**
+ * Validator
+ */
+ export import validator = runtime.Public.validator
+
+ /**
+ * Prisma Errors
+ */
+ export import PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError
+ export import PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError
+ export import PrismaClientRustPanicError = runtime.PrismaClientRustPanicError
+ export import PrismaClientInitializationError = runtime.PrismaClientInitializationError
+ export import PrismaClientValidationError = runtime.PrismaClientValidationError
+ export import NotFoundError = runtime.NotFoundError
+
+ /**
+ * Re-export of sql-template-tag
+ */
+ export import sql = runtime.sqltag
+ export import empty = runtime.empty
+ export import join = runtime.join
+ export import raw = runtime.raw
+ export import Sql = runtime.Sql
+
+
+
+ /**
+ * Decimal.js
+ */
+ export import Decimal = runtime.Decimal
+
+ export type DecimalJsLike = runtime.DecimalJsLike
+
+ /**
+ * Metrics
+ */
+ export type Metrics = runtime.Metrics
+ export type Metric = runtime.Metric
+ export type MetricHistogram = runtime.MetricHistogram
+ export type MetricHistogramBucket = runtime.MetricHistogramBucket
+
+ /**
+ * Extensions
+ */
+ export import Extension = $Extensions.UserArgs
+ export import getExtensionContext = runtime.Extensions.getExtensionContext
+ export import Args = $Public.Args
+ export import Payload = $Public.Payload
+ export import Result = $Public.Result
+ export import Exact = $Public.Exact
+
+ /**
+ * Prisma Client JS version: 5.22.0
+ * Query Engine version: 605197351a3c8bdd595af2d2a9bc3025bca48ea2
+ */
+ export type PrismaVersion = {
+ client: string
+ }
+
+ export const prismaVersion: PrismaVersion
+
+ /**
+ * Utility Types
+ */
+
+
+ export import JsonObject = runtime.JsonObject
+ export import JsonArray = runtime.JsonArray
+ export import JsonValue = runtime.JsonValue
+ export import InputJsonObject = runtime.InputJsonObject
+ export import InputJsonArray = runtime.InputJsonArray
+ export import InputJsonValue = runtime.InputJsonValue
+
+ /**
+ * Types of the values used to represent different kinds of `null` values when working with JSON fields.
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ namespace NullTypes {
+ /**
+ * Type of `Prisma.DbNull`.
+ *
+ * You cannot use other instances of this class. Please use the `Prisma.DbNull` value.
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ class DbNull {
+ private DbNull: never
+ private constructor()
+ }
+
+ /**
+ * Type of `Prisma.JsonNull`.
+ *
+ * You cannot use other instances of this class. Please use the `Prisma.JsonNull` value.
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ class JsonNull {
+ private JsonNull: never
+ private constructor()
+ }
+
+ /**
+ * Type of `Prisma.AnyNull`.
+ *
+ * You cannot use other instances of this class. Please use the `Prisma.AnyNull` value.
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ class AnyNull {
+ private AnyNull: never
+ private constructor()
+ }
+ }
+
+ /**
+ * Helper for filtering JSON entries that have `null` on the database (empty on the db)
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ export const DbNull: NullTypes.DbNull
+
+ /**
+ * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ export const JsonNull: NullTypes.JsonNull
+
+ /**
+ * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
+ *
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
+ */
+ export const AnyNull: NullTypes.AnyNull
+
+ type SelectAndInclude = {
+ select: any
+ include: any
+ }
+
+ type SelectAndOmit = {
+ select: any
+ omit: any
+ }
+
+ /**
+ * Get the type of the value, that the Promise holds.
+ */
+ export type PromiseType> = T extends PromiseLike ? U : T;
+
+ /**
+ * Get the return type of a function which returns a Promise.
+ */
+ export type PromiseReturnType $Utils.JsPromise> = PromiseType>
+
+ /**
+ * From T, pick a set of properties whose keys are in the union K
+ */
+ type Prisma__Pick = {
+ [P in K]: T[P];
+ };
+
+
+ export type Enumerable = T | Array;
+
+ export type RequiredKeys = {
+ [K in keyof T]-?: {} extends Prisma__Pick ? never : K
+ }[keyof T]
+
+ export type TruthyKeys = keyof {
+ [K in keyof T as T[K] extends false | undefined | null ? never : K]: K
+ }
+
+ export type TrueKeys = TruthyKeys>>
+
+ /**
+ * Subset
+ * @desc From `T` pick properties that exist in `U`. Simple version of Intersection
+ */
+ export type Subset = {
+ [key in keyof T]: key extends keyof U ? T[key] : never;
+ };
+
+ /**
+ * SelectSubset
+ * @desc From `T` pick properties that exist in `U`. Simple version of Intersection.
+ * Additionally, it validates, if both select and include are present. If the case, it errors.
+ */
+ export type SelectSubset = {
+ [key in keyof T]: key extends keyof U ? T[key] : never
+ } &
+ (T extends SelectAndInclude
+ ? 'Please either choose `select` or `include`.'
+ : T extends SelectAndOmit
+ ? 'Please either choose `select` or `omit`.'
+ : {})
+
+ /**
+ * Subset + Intersection
+ * @desc From `T` pick properties that exist in `U` and intersect `K`
+ */
+ export type SubsetIntersection = {
+ [key in keyof T]: key extends keyof U ? T[key] : never
+ } &
+ K
+
+ type Without = { [P in Exclude]?: never };
+
+ /**
+ * XOR is needed to have a real mutually exclusive union type
+ * https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types
+ */
+ type XOR =
+ T extends object ?
+ U extends object ?
+ (Without & U) | (Without & T)
+ : U : T
+
+
+ /**
+ * Is T a Record?
+ */
+ type IsObject = T extends Array
+ ? False
+ : T extends Date
+ ? False
+ : T extends Uint8Array
+ ? False
+ : T extends BigInt
+ ? False
+ : T extends object
+ ? True
+ : False
+
+
+ /**
+ * If it's T[], return T
+ */
+ export type UnEnumerate = T extends Array ? U : T
+
+ /**
+ * From ts-toolbelt
+ */
+
+ type __Either = Omit &
+ {
+ // Merge all but K
+ [P in K]: Prisma__Pick // With K possibilities
+ }[K]
+
+ type EitherStrict = Strict<__Either>
+
+ type EitherLoose = ComputeRaw<__Either>
+
+ type _Either<
+ O extends object,
+ K extends Key,
+ strict extends Boolean
+ > = {
+ 1: EitherStrict
+ 0: EitherLoose
+ }[strict]
+
+ type Either<
+ O extends object,
+ K extends Key,
+ strict extends Boolean = 1
+ > = O extends unknown ? _Either : never
+
+ export type Union = any
+
+ type PatchUndefined = {
+ [K in keyof O]: O[K] extends undefined ? At : O[K]
+ } & {}
+
+ /** Helper Types for "Merge" **/
+ export type IntersectOf = (
+ U extends unknown ? (k: U) => void : never
+ ) extends (k: infer I) => void
+ ? I
+ : never
+
+ export type Overwrite = {
+ [K in keyof O]: K extends keyof O1 ? O1[K] : O[K];
+ } & {};
+
+ type _Merge = IntersectOf;
+ }>>;
+
+ type Key = string | number | symbol;
+ type AtBasic = K extends keyof O ? O[K] : never;
+ type AtStrict = O[K & keyof O];
+ type AtLoose = O extends unknown ? AtStrict : never;
+ export type At = {
+ 1: AtStrict;
+ 0: AtLoose;
+ }[strict];
+
+ export type ComputeRaw = A extends Function ? A : {
+ [K in keyof A]: A[K];
+ } & {};
+
+ export type OptionalFlat = {
+ [K in keyof O]?: O[K];
+ } & {};
+
+ type _Record = {
+ [P in K]: T;
+ };
+
+ // cause typescript not to expand types and preserve names
+ type NoExpand = T extends unknown ? T : never;
+
+ // this type assumes the passed object is entirely optional
+ type AtLeast = NoExpand<
+ O extends unknown
+ ? | (K extends keyof O ? { [P in K]: O[P] } & O : O)
+ | {[P in keyof O as P extends K ? K : never]-?: O[P]} & O
+ : never>;
+
+ type _Strict = U extends unknown ? U & OptionalFlat<_Record, keyof U>, never>> : never;
+
+ export type Strict = ComputeRaw<_Strict>;
+ /** End Helper Types for "Merge" **/
+
+ export type Merge = ComputeRaw<_Merge>>;
+
+ /**
+ A [[Boolean]]
+ */
+ export type Boolean = True | False
+
+ // /**
+ // 1
+ // */
+ export type True = 1
+
+ /**
+ 0
+ */
+ export type False = 0
+
+ export type Not = {
+ 0: 1
+ 1: 0
+ }[B]
+
+ export type Extends = [A1] extends [never]
+ ? 0 // anything `never` is false
+ : A1 extends A2
+ ? 1
+ : 0
+
+ export type Has = Not<
+ Extends, U1>
+ >
+
+ export type Or = {
+ 0: {
+ 0: 0
+ 1: 1
+ }
+ 1: {
+ 0: 1
+ 1: 1
+ }
+ }[B1][B2]
+
+ export type Keys = U extends unknown ? keyof U : never
+
+ type Cast = A extends B ? A : B;
+
+ export const type: unique symbol;
+
+
+
+ /**
+ * Used by group by
+ */
+
+ export type GetScalarType = O extends object ? {
+ [P in keyof T]: P extends keyof O
+ ? O[P]
+ : never
+ } : never
+
+ type FieldPaths<
+ T,
+ U = Omit
+ > = IsObject extends True ? U : T
+
+ type GetHavingFields = {
+ [K in keyof T]: Or<
+ Or, Extends<'AND', K>>,
+ Extends<'NOT', K>
+ > extends True
+ ? // infer is only needed to not hit TS limit
+ // based on the brilliant idea of Pierre-Antoine Mills
+ // https://github.com/microsoft/TypeScript/issues/30188#issuecomment-478938437
+ T[K] extends infer TK
+ ? GetHavingFields extends object ? Merge> : never>
+ : never
+ : {} extends FieldPaths
+ ? never
+ : K
+ }[keyof T]
+
+ /**
+ * Convert tuple to union
+ */
+ type _TupleToUnion = T extends (infer E)[] ? E : never
+ type TupleToUnion = _TupleToUnion
+ type MaybeTupleToUnion = T extends any[] ? TupleToUnion : T
+
+ /**
+ * Like `Pick`, but additionally can also accept an array of keys
+ */
+ type PickEnumerable | keyof T> = Prisma__Pick>
+
+ /**
+ * Exclude all keys with underscores
+ */
+ type ExcludeUnderscoreKeys = T extends `_${string}` ? never : T
+
+
+ export type FieldRef = runtime.FieldRef
+
+ type FieldRefInputType = Model extends never ? never : FieldRef
+
+
+ export const ModelName: {
+ User: 'User',
+ Burrow: 'Burrow',
+ Donation: 'Donation',
+ WildlifeSighting: 'WildlifeSighting',
+ Event: 'Event',
+ EventRSVP: 'EventRSVP',
+ LivestreamSource: 'LivestreamSource',
+ VolunteerHour: 'VolunteerHour',
+ EquipmentItem: 'EquipmentItem'
+ };
+
+ export type ModelName = (typeof ModelName)[keyof typeof ModelName]
+
+
+ export type Datasources = {
+ db?: Datasource
+ }
+
+ interface TypeMapCb extends $Utils.Fn<{extArgs: $Extensions.InternalArgs, clientOptions: PrismaClientOptions }, $Utils.Record> {
+ returns: Prisma.TypeMap
+ }
+
+ export type TypeMap = {
+ meta: {
+ modelProps: "user" | "burrow" | "donation" | "wildlifeSighting" | "event" | "eventRSVP" | "livestreamSource" | "volunteerHour" | "equipmentItem"
+ txIsolationLevel: Prisma.TransactionIsolationLevel
+ }
+ model: {
+ User: {
+ payload: Prisma.$UserPayload
+ fields: Prisma.UserFieldRefs
+ operations: {
+ findUnique: {
+ args: Prisma.UserFindUniqueArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findUniqueOrThrow: {
+ args: Prisma.UserFindUniqueOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findFirst: {
+ args: Prisma.UserFindFirstArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findFirstOrThrow: {
+ args: Prisma.UserFindFirstOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findMany: {
+ args: Prisma.UserFindManyArgs
+ result: $Utils.PayloadToResult[]
+ }
+ create: {
+ args: Prisma.UserCreateArgs
+ result: $Utils.PayloadToResult
+ }
+ createMany: {
+ args: Prisma.UserCreateManyArgs
+ result: BatchPayload
+ }
+ createManyAndReturn: {
+ args: Prisma.UserCreateManyAndReturnArgs
+ result: $Utils.PayloadToResult[]
+ }
+ delete: {
+ args: Prisma.UserDeleteArgs
+ result: $Utils.PayloadToResult
+ }
+ update: {
+ args: Prisma.UserUpdateArgs
+ result: $Utils.PayloadToResult
+ }
+ deleteMany: {
+ args: Prisma.UserDeleteManyArgs
+ result: BatchPayload
+ }
+ updateMany: {
+ args: Prisma.UserUpdateManyArgs
+ result: BatchPayload
+ }
+ upsert: {
+ args: Prisma.UserUpsertArgs
+ result: $Utils.PayloadToResult
+ }
+ aggregate: {
+ args: Prisma.UserAggregateArgs
+ result: $Utils.Optional
+ }
+ groupBy: {
+ args: Prisma.UserGroupByArgs
+ result: $Utils.Optional[]
+ }
+ count: {
+ args: Prisma.UserCountArgs
+ result: $Utils.Optional | number
+ }
+ }
+ }
+ Burrow: {
+ payload: Prisma.$BurrowPayload
+ fields: Prisma.BurrowFieldRefs
+ operations: {
+ findUnique: {
+ args: Prisma.BurrowFindUniqueArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findUniqueOrThrow: {
+ args: Prisma.BurrowFindUniqueOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findFirst: {
+ args: Prisma.BurrowFindFirstArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findFirstOrThrow: {
+ args: Prisma.BurrowFindFirstOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findMany: {
+ args: Prisma.BurrowFindManyArgs
+ result: $Utils.PayloadToResult[]
+ }
+ create: {
+ args: Prisma.BurrowCreateArgs
+ result: $Utils.PayloadToResult
+ }
+ createMany: {
+ args: Prisma.BurrowCreateManyArgs
+ result: BatchPayload
+ }
+ createManyAndReturn: {
+ args: Prisma.BurrowCreateManyAndReturnArgs
+ result: $Utils.PayloadToResult[]
+ }
+ delete: {
+ args: Prisma.BurrowDeleteArgs
+ result: $Utils.PayloadToResult
+ }
+ update: {
+ args: Prisma.BurrowUpdateArgs
+ result: $Utils.PayloadToResult
+ }
+ deleteMany: {
+ args: Prisma.BurrowDeleteManyArgs
+ result: BatchPayload
+ }
+ updateMany: {
+ args: Prisma.BurrowUpdateManyArgs
+ result: BatchPayload
+ }
+ upsert: {
+ args: Prisma.BurrowUpsertArgs
+ result: $Utils.PayloadToResult
+ }
+ aggregate: {
+ args: Prisma.BurrowAggregateArgs
+ result: $Utils.Optional
+ }
+ groupBy: {
+ args: Prisma.BurrowGroupByArgs
+ result: $Utils.Optional[]
+ }
+ count: {
+ args: Prisma.BurrowCountArgs
+ result: $Utils.Optional | number
+ }
+ }
+ }
+ Donation: {
+ payload: Prisma.$DonationPayload
+ fields: Prisma.DonationFieldRefs
+ operations: {
+ findUnique: {
+ args: Prisma.DonationFindUniqueArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findUniqueOrThrow: {
+ args: Prisma.DonationFindUniqueOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findFirst: {
+ args: Prisma.DonationFindFirstArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findFirstOrThrow: {
+ args: Prisma.DonationFindFirstOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findMany: {
+ args: Prisma.DonationFindManyArgs
+ result: $Utils.PayloadToResult[]
+ }
+ create: {
+ args: Prisma.DonationCreateArgs
+ result: $Utils.PayloadToResult
+ }
+ createMany: {
+ args: Prisma.DonationCreateManyArgs
+ result: BatchPayload
+ }
+ createManyAndReturn: {
+ args: Prisma.DonationCreateManyAndReturnArgs
+ result: $Utils.PayloadToResult[]
+ }
+ delete: {
+ args: Prisma.DonationDeleteArgs
+ result: $Utils.PayloadToResult
+ }
+ update: {
+ args: Prisma.DonationUpdateArgs
+ result: $Utils.PayloadToResult
+ }
+ deleteMany: {
+ args: Prisma.DonationDeleteManyArgs
+ result: BatchPayload
+ }
+ updateMany: {
+ args: Prisma.DonationUpdateManyArgs
+ result: BatchPayload
+ }
+ upsert: {
+ args: Prisma.DonationUpsertArgs
+ result: $Utils.PayloadToResult
+ }
+ aggregate: {
+ args: Prisma.DonationAggregateArgs
+ result: $Utils.Optional
+ }
+ groupBy: {
+ args: Prisma.DonationGroupByArgs
+ result: $Utils.Optional[]
+ }
+ count: {
+ args: Prisma.DonationCountArgs
+ result: $Utils.Optional | number
+ }
+ }
+ }
+ WildlifeSighting: {
+ payload: Prisma.$WildlifeSightingPayload
+ fields: Prisma.WildlifeSightingFieldRefs
+ operations: {
+ findUnique: {
+ args: Prisma.WildlifeSightingFindUniqueArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findUniqueOrThrow: {
+ args: Prisma.WildlifeSightingFindUniqueOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findFirst: {
+ args: Prisma.WildlifeSightingFindFirstArgs
+ result: $Utils.PayloadToResult | null
+ }
+ findFirstOrThrow: {
+ args: Prisma.WildlifeSightingFindFirstOrThrowArgs
+ result: $Utils.PayloadToResult
+ }
+ findMany: {
+ args: Prisma.WildlifeSightingFindManyArgs
+ result: $Utils.PayloadToResult[]
+ }
+ create: {
+ args: Prisma.WildlifeSightingCreateArgs
+ result: $Utils.PayloadToResult
+ }
+ createMany: {
+ args: Prisma.WildlifeSightingCreateManyArgs
+ result: BatchPayload
+ }
+ createManyAndReturn: {
+ args: Prisma.WildlifeSightingCreateManyAndReturnArgs
+ result: $Utils.PayloadToResult