diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ba84ec..b94f64c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,9 @@ "username": "opendatarepository", "database": "opendatarepository" } + ], + "basedpyright.analysis.extraPaths": [ + "./modules/odr_api/", + "./modules/odr_core/" ] } diff --git a/Taskfile.yml b/Taskfile.yml index 0e47f3a..87454ef 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -23,13 +23,6 @@ tasks: cmds: - task --list - echo-project-root: - desc: Echo the project root directory. Helps ensure environment is set up and tasks will run. - cmds: - - echo USER WD {{.USER_WORKING_DIR}} - - echo USER_WORKING_DIRECTORY ${ROOT_DIR} - - echo ROOT ${ROOT_DIR} - setup: desc: Setup the project cmds: @@ -109,3 +102,10 @@ tasks: desc: Stop all running containers cmds: - docker compose down + dev: + desc: Start development environment with odr-api in watch mode and databases headless + cmds: + - docker compose up -d postgres pgadmin + - | + docker compose up --watch odr-api --build & + docker compose up --watch odr-frontend --build diff --git a/docker-compose.yml b/docker-compose.yml index 6017dff..25b9ad1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,12 @@ services: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_HOST_AUTH_METHOD: trust + POSTGRES_PORT: 35432 volumes: - postgres_data:/var/lib/postgresql/data ports: - - "${POSTGRES_PORT:-35432}:5432" + - 35432:5432 networks: - omi-network @@ -19,6 +21,15 @@ services: PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-admin@example.com} PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} PGADMIN_LISTEN_ADDRESS: 0.0.0.0 + PGADMIN_CONFIG_SERVER_MODE: "False" + PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False" + entrypoint: /bin/sh -c "chmod 600 /pgpass; /entrypoint.sh;" + user: root + configs: + - source: servers.json + target: /pgadmin4/servers.json + - source: pgpass + target: /pgpass volumes: - pgadmin_data:/var/lib/pgadmin ports: @@ -40,12 +51,67 @@ services: - omi-network depends_on: - postgres + develop: + watch: + - action: sync + path: ./modules/odr_core + target: /app/modules/odr_core + - action: sync + path: ./modules/odr_api + target: /app/modules/odr_api + - action: sync + path: ./modules/odr_monitoring + target: /app/modules/odr_monitoring + + odr-frontend: + build: + context: ./modules/odr_frontend + dockerfile: docker/Dockerfile.frontend.dev + volumes: + - ./modules/odr_frontend:/app + - odr_frontend_node_modules:/app/node_modules + - odr_frontend_pnpm_store:/app/.pnpm-store + ports: + - "5173:5173" + environment: + NODE_ENV: development + API_SERVICE_URL: http://odr-api:31100/api/v1 + env_file: + - ./modules/odr_frontend/.env + networks: + - omi-network + develop: + watch: + - action: sync + path: ./modules/odr_frontend + target: /app + ignore: + - node_modules/ + - .pnpm-store/ volumes: postgres_data: pgadmin_data: + odr_frontend_node_modules: + odr_frontend_pnpm_store: networks: omi-network: external: true driver: bridge + +configs: + pgpass: + content: postgres:35432:${POSTGRES_DB}:${POSTGRES_USER}:${POSTGRES_PASSWORD} + servers.json: + content: | + {"Servers": {"1": { + "Group": "Servers", + "Name": "Open Data Repository", + "Host": "postgres", + "Port": 35432, + "MaintenanceDB": "postgres", + "Username": "${POSTGRES_USER}", + "PassFile": "/pgpass", + "SSLMode": "prefer" + }}} diff --git a/modules/odr_api/docker/Dockerfile.api b/modules/odr_api/docker/Dockerfile.api index fed2068..87be252 100644 --- a/modules/odr_api/docker/Dockerfile.api +++ b/modules/odr_api/docker/Dockerfile.api @@ -20,6 +20,9 @@ RUN pip install --no-cache-dir -r requirements.txt COPY modules/odr_core /app/modules/odr_core RUN pip install --no-cache-dir -e /app/modules/odr_core +COPY modules/odr_monitoring /app/modules/odr_monitoring +RUN pip install --no-cache-dir -e /app/modules/odr_monitoring + COPY modules/odr_api /app RUN pip install --no-cache-dir . @@ -31,4 +34,4 @@ EXPOSE 31100 # Set the entrypoint # CMD ["tail", "-f", "/dev/null"] ENTRYPOINT ["uvicorn"] -CMD ["odr_api.app:app", "--host", "0.0.0.0", "--port", "31100"] +CMD ["odr_api.app:app", "--host", "0.0.0.0", "--port", "31100", "--reload"] diff --git a/modules/odr_api/scripts/run_server.ps1 b/modules/odr_api/scripts/run_server.ps1 index 4a6dc47..5e00ec2 100755 --- a/modules/odr_api/scripts/run_server.ps1 +++ b/modules/odr_api/scripts/run_server.ps1 @@ -1,4 +1,4 @@ +# Run the FastAPI server with uvicorn -# Run the FastAPI server with multiple workers and log output to a file - -./venv/Scripts/python ./modules/odr_api/odr_api/main.py +$env:PYTHONPATH = "." +./venv/Scripts/uvicorn.exe odr_api.app:app --host 0.0.0.0 --port 31100 diff --git a/modules/odr_core/odr_core/config.py b/modules/odr_core/odr_core/config.py index 76c51ad..3d7646a 100644 --- a/modules/odr_core/odr_core/config.py +++ b/modules/odr_core/odr_core/config.py @@ -51,7 +51,9 @@ class Config: def get_db_url(self): db_name = self.TEST_POSTGRES_DB if self.TEST else self.POSTGRES_DB - return f"postgresql://{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}@{self.POSTGRES_HOST}:{self.POSTGRES_PORT}/{db_name}" + + conn_str = f"postgresql://{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}@{self.POSTGRES_HOST}:{self.POSTGRES_PORT}/{db_name}" + return conn_str settings = Settings() diff --git a/modules/odr_core/odr_core/database.py b/modules/odr_core/odr_core/database.py index 7e6be6d..0f29db1 100644 --- a/modules/odr_core/odr_core/database.py +++ b/modules/odr_core/odr_core/database.py @@ -3,6 +3,8 @@ from odr_core.config import settings # Create SQLAlchemy engine +url = settings.get_db_url() + engine = create_engine(settings.get_db_url()) # Create SessionLocal class diff --git a/modules/odr_database/docker/postgres-compose.yml b/modules/odr_database/docker/postgres-compose.yml deleted file mode 100644 index 09ac846..0000000 --- a/modules/odr_database/docker/postgres-compose.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: omi-postgres -services: - postgres: - image: pgvector/pgvector:pg16 - environment: - POSTGRES_DB: ${POSTGRES_DB} - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_HOST_AUTH_METHOD: trust - volumes: - - postgres_data:/var/lib/postgresql/data - ports: - - "${POSTGRES_PORT:-35432}:5432" - networks: - - omi-network - - pgadmin: - image: dpage/pgadmin4 - environment: - PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-admin@example.com} - PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin} - PGADMIN_LISTEN_ADDRESS: 0.0.0.0 - PGADMIN_CONFIG_SERVER_MODE: "False" - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False" - entrypoint: /bin/sh -c "chmod 600 /pgpass; /entrypoint.sh;" - user: root - configs: - - source: servers.json - target: /pgadmin4/servers.json - - source: pgpass - target: /pgpass - volumes: - - pgadmin_data:/var/lib/pgadmin - ports: - - "${PGADMIN_PORT:-35050}:80" - networks: - - omi-network - depends_on: - - postgres - -volumes: - postgres_data: - pgadmin_data: - -networks: - omi-network: - external: true - driver: bridge - -configs: - pgpass: - content: postgres:5432:${POSTGRES_DB}:${POSTGRES_USER}:${POSTGRES_PASSWORD} - servers.json: - content: | - {"Servers": {"1": { - "Group": "Servers", - "Name": "Open Data Repository", - "Host": "postgres", - "Port": 5432, - "MaintenanceDB": "postgres", - "Username": "${POSTGRES_USER}", - "PassFile": "/pgpass", - "SSLMode": "prefer" - }}} diff --git a/modules/odr_datamodel/Taskfile.yml b/modules/odr_datamodel/Taskfile.yml index f0198c6..7a1e60c 100644 --- a/modules/odr_datamodel/Taskfile.yml +++ b/modules/odr_datamodel/Taskfile.yml @@ -6,6 +6,9 @@ tasks: desc: Migrate the database cmds: - alembic -c ./modules/odr_datamodel/alembic.ini upgrade head + env: + POSTGRES_HOST: localhost + POSTGRES_PORT: 35432 revision: desc: Create a new revision, e.g. task data:revision -- "Add new column" diff --git a/modules/odr_frontend/.dockerignore b/modules/odr_frontend/.dockerignore new file mode 100644 index 0000000..c7c17af --- /dev/null +++ b/modules/odr_frontend/.dockerignore @@ -0,0 +1,5 @@ +.git +.gitignore +npm-debug.log +./docker/Dockerfile* +.dockerignore diff --git a/modules/odr_frontend/docker/Dockerfile.frontend.dev b/modules/odr_frontend/docker/Dockerfile.frontend.dev new file mode 100644 index 0000000..4f3e5ed --- /dev/null +++ b/modules/odr_frontend/docker/Dockerfile.frontend.dev @@ -0,0 +1,21 @@ +FROM node:22-alpine + +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm + +# Copy package.json and pnpm-lock.yaml (if you have one) +COPY package.json pnpm-lock.yaml* ./ + +# Copy the entrypoint script +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +COPY template.env /app/.env + +EXPOSE 5173 + +ENTRYPOINT ["/entrypoint.sh"] + +CMD ["pnpm", "run", "dev", "--", "--host", "0.0.0.0"] diff --git a/modules/odr_frontend/docker/Dockerfile.frontend.prod b/modules/odr_frontend/docker/Dockerfile.frontend.prod new file mode 100644 index 0000000..422f8a2 --- /dev/null +++ b/modules/odr_frontend/docker/Dockerfile.frontend.prod @@ -0,0 +1,41 @@ +# Build stage +### STUB : Not verified #### +FROM node:22-alpine AS builder + +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm + +# Copy package.json and pnpm-lock.yaml (if you have one) +COPY package.json pnpm-lock.yaml* ./ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Copy the rest of the application code +COPY . . + +# Build the application +RUN pnpm run build + +# Production stage +FROM node:22-alpine + +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm + +# Copy built assets from the builder stage +COPY --from=builder /app/build ./build +COPY --from=builder /app/package.json . + +# Install only production dependencies +RUN pnpm install --prod + +# Expose the application port +EXPOSE 3000 + +# Start the application +CMD ["node", "build"] diff --git a/modules/odr_frontend/docker/entrypoint.sh b/modules/odr_frontend/docker/entrypoint.sh new file mode 100644 index 0000000..9799c33 --- /dev/null +++ b/modules/odr_frontend/docker/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +echo "Installing dependencies..." +pnpm install + + +exec "$@" diff --git a/modules/odr_frontend/package.json b/modules/odr_frontend/package.json index 9245ec3..46ec1e7 100644 --- a/modules/odr_frontend/package.json +++ b/modules/odr_frontend/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "scripts": { - "dev": "vite dev", + "dev": "vite dev --host 0.0.0.0", "build": "vite build", "preview": "vite preview", "test": "npm run test:integration && npm run test:unit", @@ -25,6 +25,7 @@ "@tailwindcss/typography": "0.5.14", "@types/eslint": "^9.6.0", "@types/node": "22.2.0", + "dotenv": "^16.0.3", "autoprefixer": "10.4.20", "eslint": "^9.0.0", "eslint-config-prettier": "^9.1.0", @@ -35,12 +36,14 @@ "prettier-plugin-svelte": "^3.1.2", "svelte": "^4.2.7", "svelte-check": "^3.6.0", + "sveltekit-superforms": "^2.17.0", "tailwindcss": "3.4.10", "typescript": "^5.0.0", "typescript-eslint": "^8.0.0", "vite": "^5.0.3", "vite-plugin-tailwind-purgecss": "0.3.3", - "vitest": "^2.0.0" + "vitest": "^2.0.0", + "zod": "^3.23.8" }, "type": "module", "dependencies": { diff --git a/modules/odr_frontend/pnpm-lock.yaml b/modules/odr_frontend/pnpm-lock.yaml index b33e0c3..be565e6 100644 --- a/modules/odr_frontend/pnpm-lock.yaml +++ b/modules/odr_frontend/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: autoprefixer: specifier: 10.4.20 version: 10.4.20(postcss@8.4.41) + dotenv: + specifier: ^16.0.3 + version: 16.4.5 eslint: specifier: ^9.0.0 version: 9.9.0(jiti@1.21.6) @@ -75,6 +78,9 @@ importers: svelte-check: specifier: ^3.6.0 version: 3.8.5(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(svelte@4.2.18) + sveltekit-superforms: + specifier: ^2.17.0 + version: 2.17.0(@sveltejs/kit@2.5.22(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18) tailwindcss: specifier: 3.4.10 version: 3.4.10 @@ -93,6 +99,9 @@ importers: vitest: specifier: ^2.0.0 version: 2.0.5(@types/node@22.2.0) + zod: + specifier: ^3.23.8 + version: 3.23.8 packages: @@ -104,6 +113,16 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@ark/schema@0.2.0': + resolution: {integrity: sha512-IkNWCSHdjaoemMXpps4uFHEAQzwJPbTAS8K2vcQpk90sa+eNBuPSVyB/81/Qyl1VYW0iX3ceGC5NL/OznQv1jg==} + + '@ark/util@0.1.0': + resolution: {integrity: sha512-qCLYICQoCy3kEKDVwirQp8qvxhY7NJd8BhhoHaj1l3wCFAk9NUbcDsxAkPStZEMdPI/d7NcbGJe8SWZuRG2twQ==} + + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + engines: {node: '>=6.9.0'} + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -268,6 +287,9 @@ packages: resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/schemasafe@1.3.0': + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + '@floating-ui/core@1.6.7': resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==} @@ -277,6 +299,16 @@ packages: '@floating-ui/utils@0.2.7': resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==} + '@gcornut/valibot-json-schema@0.31.0': + resolution: {integrity: sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g==} + hasBin: true + + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -331,6 +363,10 @@ packages: '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + '@poppinss/macroable@1.0.2': + resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} + engines: {node: '>=18.16.0'} + '@rollup/rollup-android-arm-eabi@4.20.0': resolution: {integrity: sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==} cpu: [arm] @@ -411,6 +447,18 @@ packages: cpu: [x64] os: [win32] + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + + '@sinclair/typebox@0.32.35': + resolution: {integrity: sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA==} + '@skeletonlabs/skeleton@2.10.2': resolution: {integrity: sha512-TV2yWjvHpmtaF1F5luB8n7UbjKZcsrJMMiiJQHbZvqXjBWvudAcL8zywhE/NFKW5rYU//MtgOODdMZPZxvKu6w==} peerDependencies: @@ -421,6 +469,9 @@ packages: peerDependencies: tailwindcss: '>=3.0.0' + '@sodaru/yup-to-json-schema@2.0.1': + resolution: {integrity: sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==} + '@sveltejs/adapter-auto@3.2.4': resolution: {integrity: sha512-a64AKYbfTUrVwU0xslzv1Jf3M8bj0IwhptaXmhgIkjXspBXhD0od9JiItQHchijpLMGdEDcYBlvqySkEawv6mQ==} peerDependencies: @@ -478,6 +529,9 @@ packages: '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} + '@types/validator@13.12.1': + resolution: {integrity: sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==} + '@typescript-eslint/eslint-plugin@8.1.0': resolution: {integrity: sha512-LlNBaHFCEBPHyD4pZXb35mzjGkuGKXU5eeCA1SxvHfiRES0E82dOounfVpL4DCqYvJEKab0bZIA0gCRpdLKkCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -535,6 +589,14 @@ packages: resolution: {integrity: sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vinejs/compiler@2.5.0': + resolution: {integrity: sha512-hg4ekaB5Y2zh+IWzBiC/WCDWrIfpVnKu/ubUvelKlidc/VbulsexoFRw5kJGHZenPVI5YzNnDeTdYSALkTV7jQ==} + engines: {node: '>=18.0.0'} + + '@vinejs/vine@1.8.0': + resolution: {integrity: sha512-Qq3XxbA26jzqS9ICifkqzT399lMQZ2fWtqeV3luI2as+UIK7qDifJFU2Q4W3q3IB5VXoWxgwAZSZEO0em9I/qQ==} + engines: {node: '>=18.16.0'} + '@vitest/expect@2.0.5': resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} @@ -598,6 +660,9 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + arktype@2.0.0-beta.0: + resolution: {integrity: sha512-fE3ssMiXjr/bLqFPzlDhRlXngdyHQreu7p7i8+dtcY1CA+f8WrVUcue6JxywhnqEJXPG4HOcIwQcC+q4VfeUMQ==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -643,6 +708,9 @@ packages: resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} engines: {node: '>=8.0.0'} + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -655,6 +723,10 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + caniuse-lite@1.0.30001651: resolution: {integrity: sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==} @@ -716,6 +788,9 @@ packages: engines: {node: '>=4'} hasBin: true + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debug@4.3.6: resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} @@ -764,6 +839,10 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -783,6 +862,12 @@ packages: es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + esbuild-runner@2.2.2: + resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} + hasBin: true + peerDependencies: + esbuild: '*' + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -1066,6 +1151,9 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -1073,12 +1161,19 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + just-clone@6.2.0: + resolution: {integrity: sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1132,6 +1227,9 @@ packages: mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + memoize-weak@1.0.2: + resolution: {integrity: sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1206,6 +1304,10 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1396,6 +1498,9 @@ packages: engines: {node: '>=14'} hasBin: true + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1417,6 +1522,9 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1488,6 +1596,13 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -1527,6 +1642,10 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + superstruct@2.0.2: + resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} + engines: {node: '>=14.0.0'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1597,6 +1716,12 @@ packages: resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} engines: {node: '>=16'} + sveltekit-superforms@2.17.0: + resolution: {integrity: sha512-QrX8pkcmE0XoeVU42zMhsah4FoDrgtPc/4cZEr38rDlgU+DE0xNc5J0E7z1456sUJNbFjaB0+HZwwAkX0vYqaA==} + peerDependencies: + '@sveltejs/kit': 1.x || 2.x + svelte: 3.x || 4.x || >=5.0.0-next.51 + tailwindcss@3.4.10: resolution: {integrity: sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==} engines: {node: '>=14.0.0'} @@ -1612,6 +1737,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} @@ -1634,23 +1762,40 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' + ts-deepmerge@7.0.1: + resolution: {integrity: sha512-JBFCmNenZdUCc+TRNCtXVM6N8y/nDQHAcpj5BlwXG/gnogjam1NunulB9ia68mnqYI446giMfpqeBFFkOleh+g==} + engines: {node: '>=14.13.1'} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + typescript-eslint@8.1.0: resolution: {integrity: sha512-prB2U3jXPJLpo1iVLN338Lvolh6OrcCZO+9Yv6AR+tvegPPptYCDBIHiEEUdqRi8gAv2bXNKfMUrgAd2ejn/ow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1680,6 +1825,16 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + valibot@0.31.1: + resolution: {integrity: sha512-2YYIhPrnVSz/gfT2/iXVTrSj92HwchCt9Cga/6hX4B26iCz9zkIsGTS0HjDYTZfTi1Un0X6aRvhBi1cfqs/i0Q==} + + valibot@0.35.0: + resolution: {integrity: sha512-+i2aCRkReTrd5KBN/dW2BrPOvFnU5LXTV2xjZnjnqUIO8YUx6P2+MgRrkwF2FhkexgyKq/NIZdPdknhHf5A/Ww==} + + validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + vite-node@2.0.5: resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -1793,6 +1948,17 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yup@1.4.0: + resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} + + zod-to-json-schema@3.23.2: + resolution: {integrity: sha512-uSt90Gzc/tUfyNqxnjlfBs8W6WSGpNBv0rVsNxP/BVSMHMKGdthPYff4xtCHYloJGM0CFxFsb3NbC0eqPhfImw==} + peerDependencies: + zod: ^3.23.3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + snapshots: '@alloc/quick-lru@5.2.0': {} @@ -1802,6 +1968,19 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@ark/schema@0.2.0': + dependencies: + '@ark/util': 0.1.0 + optional: true + + '@ark/util@0.1.0': + optional: true + + '@babel/runtime@7.25.6': + dependencies: + regenerator-runtime: 0.14.1 + optional: true + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -1904,6 +2083,9 @@ snapshots: '@eslint/object-schema@2.1.4': {} + '@exodus/schemasafe@1.3.0': + optional: true + '@floating-ui/core@1.6.7': dependencies: '@floating-ui/utils': 0.2.7 @@ -1915,6 +2097,23 @@ snapshots: '@floating-ui/utils@0.2.7': {} + '@gcornut/valibot-json-schema@0.31.0': + dependencies: + valibot: 0.31.1 + optionalDependencies: + '@types/json-schema': 7.0.15 + esbuild: 0.21.5 + esbuild-runner: 2.2.2(esbuild@0.21.5) + optional: true + + '@hapi/hoek@9.3.0': + optional: true + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + optional: true + '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.3.0': {} @@ -1966,6 +2165,9 @@ snapshots: '@polka/url@1.0.0-next.25': {} + '@poppinss/macroable@1.0.2': + optional: true + '@rollup/rollup-android-arm-eabi@4.20.0': optional: true @@ -2014,6 +2216,20 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.20.0': optional: true + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + optional: true + + '@sideway/formula@3.0.1': + optional: true + + '@sideway/pinpoint@2.0.0': + optional: true + + '@sinclair/typebox@0.32.35': + optional: true + '@skeletonlabs/skeleton@2.10.2(svelte@4.2.18)': dependencies: esm-env: 1.0.0 @@ -2023,6 +2239,9 @@ snapshots: dependencies: tailwindcss: 3.4.10 + '@sodaru/yup-to-json-schema@2.0.1': + optional: true + '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.22(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))': dependencies: '@sveltejs/kit': 2.5.22(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)) @@ -2099,6 +2318,9 @@ snapshots: '@types/pug@2.0.10': {} + '@types/validator@13.12.1': + optional: true + '@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -2180,6 +2402,21 @@ snapshots: '@typescript-eslint/types': 8.1.0 eslint-visitor-keys: 3.4.3 + '@vinejs/compiler@2.5.0': + optional: true + + '@vinejs/vine@1.8.0': + dependencies: + '@poppinss/macroable': 1.0.2 + '@types/validator': 13.12.1 + '@vinejs/compiler': 2.5.0 + camelcase: 8.0.0 + dayjs: 1.11.13 + dlv: 1.1.3 + normalize-url: 8.0.1 + validator: 13.12.0 + optional: true + '@vitest/expect@2.0.5': dependencies: '@vitest/spy': 2.0.5 @@ -2251,6 +2488,12 @@ snapshots: dependencies: dequal: 2.0.3 + arktype@2.0.0-beta.0: + dependencies: + '@ark/schema': 0.2.0 + '@ark/util': 0.1.0 + optional: true + array-union@2.1.0: {} assertion-error@2.0.1: {} @@ -2293,12 +2536,18 @@ snapshots: buffer-crc32@1.0.0: {} + buffer-from@1.1.2: + optional: true + cac@6.7.14: {} callsites@3.1.0: {} camelcase-css@2.0.1: {} + camelcase@8.0.0: + optional: true + caniuse-lite@1.0.30001651: {} chai@5.1.1: @@ -2365,6 +2614,9 @@ snapshots: cssesc@3.0.0: {} + dayjs@1.11.13: + optional: true + debug@4.3.6: dependencies: ms: 2.1.2 @@ -2395,6 +2647,8 @@ snapshots: dependencies: domelementtype: 2.3.0 + dotenv@16.4.5: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.6: {} @@ -2407,6 +2661,13 @@ snapshots: es6-promise@3.3.1: {} + esbuild-runner@2.2.2(esbuild@0.21.5): + dependencies: + esbuild: 0.21.5 + source-map-support: 0.5.21 + tslib: 2.4.0 + optional: true + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -2732,16 +2993,33 @@ snapshots: jiti@1.21.6: {} + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + optional: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 json-buffer@3.0.1: {} + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.25.6 + ts-algebra: 2.0.0 + optional: true + json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} + just-clone@6.2.0: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -2785,6 +3063,8 @@ snapshots: mdn-data@2.0.30: {} + memoize-weak@1.0.2: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -2838,6 +3118,9 @@ snapshots: normalize-range@0.1.2: {} + normalize-url@8.0.1: + optional: true + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -2995,6 +3278,9 @@ snapshots: prettier@3.3.3: {} + property-expr@2.0.6: + optional: true + punycode@2.3.1: {} purgecss-from-html@6.0.0: @@ -3019,6 +3305,9 @@ snapshots: dependencies: picomatch: 2.3.1 + regenerator-runtime@0.14.1: + optional: true + resolve-from@4.0.0: {} resolve@1.22.8: @@ -3101,6 +3390,15 @@ snapshots: source-map-js@1.2.0: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + optional: true + + source-map@0.6.1: + optional: true + stackback@0.0.2: {} std-env@3.7.0: {} @@ -3143,6 +3441,9 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 + superstruct@2.0.2: + optional: true + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -3213,6 +3514,29 @@ snapshots: magic-string: 0.30.11 periscopic: 3.1.0 + sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.22(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18): + dependencies: + '@sveltejs/kit': 2.5.22(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)))(svelte@4.2.18)(vite@5.4.0(@types/node@22.2.0)) + devalue: 5.0.0 + just-clone: 6.2.0 + memoize-weak: 1.0.2 + svelte: 4.2.18 + ts-deepmerge: 7.0.1 + optionalDependencies: + '@exodus/schemasafe': 1.3.0 + '@gcornut/valibot-json-schema': 0.31.0 + '@sinclair/typebox': 0.32.35 + '@sodaru/yup-to-json-schema': 2.0.1 + '@vinejs/vine': 1.8.0 + arktype: 2.0.0-beta.0 + joi: 17.13.3 + json-schema-to-ts: 3.1.1 + superstruct: 2.0.2 + valibot: 0.35.0 + yup: 1.4.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.2(zod@3.23.8) + tailwindcss@3.4.10: dependencies: '@alloc/quick-lru': 5.2.0 @@ -3250,6 +3574,9 @@ snapshots: dependencies: any-promise: 1.3.0 + tiny-case@1.0.3: + optional: true + tiny-glob@0.2.9: dependencies: globalyzer: 0.1.0 @@ -3267,18 +3594,32 @@ snapshots: dependencies: is-number: 7.0.0 + toposort@2.0.2: + optional: true + totalist@3.0.1: {} + ts-algebra@2.0.0: + optional: true + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: typescript: 5.5.4 + ts-deepmerge@7.0.1: {} + ts-interface-checker@0.1.13: {} + tslib@2.4.0: + optional: true + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 + type-fest@2.19.0: + optional: true + typescript-eslint@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4): dependencies: '@typescript-eslint/eslint-plugin': 8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4) @@ -3306,6 +3647,15 @@ snapshots: util-deprecate@1.0.2: {} + valibot@0.31.1: + optional: true + + valibot@0.35.0: + optional: true + + validator@13.12.0: + optional: true + vite-node@2.0.5(@types/node@22.2.0): dependencies: cac: 6.7.14 @@ -3410,3 +3760,18 @@ snapshots: yaml@2.5.0: {} yocto-queue@0.1.0: {} + + yup@1.4.0: + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + optional: true + + zod-to-json-schema@3.23.2(zod@3.23.8): + dependencies: + zod: 3.23.8 + optional: true + + zod@3.23.8: {} diff --git a/modules/odr_frontend/src/hooks.server.ts b/modules/odr_frontend/src/hooks.server.ts index 82c4e12..895863f 100644 --- a/modules/odr_frontend/src/hooks.server.ts +++ b/modules/odr_frontend/src/hooks.server.ts @@ -1,4 +1,5 @@ import { redirect, type Cookies } from '@sveltejs/kit'; +import { API_URL } from '$lib/server/env'; interface User { username: string; @@ -11,8 +12,22 @@ interface User { user_type: 'user' | 'bot'; } +async function checkApiHealth() { + try { + const response = await fetch(`${API_URL}/health`); + if (response.ok) { + console.log('API health check successful'); + } else { + console.error('API health check failed:', response.status, await response.text()); + } + } catch (error) { + console.error('API health check error:', error); + } +} + /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { + await checkApiHealth(); const { route, cookies, locals } = event; const sessionCookie = cookies.get('session'); @@ -50,7 +65,7 @@ export async function handle({ event, resolve }) { const validateTokenFunction = async (cookies: Cookies): Promise => { const currentToken = cookies.get('session'); - const req = await fetch('http://localhost:31100/api/v1/users/me', { + const req = await fetch(`${API_URL}/users/me`, { headers: { Cookie: `session=${currentToken}` } diff --git a/modules/odr_frontend/src/lib/server/env.ts b/modules/odr_frontend/src/lib/server/env.ts new file mode 100644 index 0000000..f49270e --- /dev/null +++ b/modules/odr_frontend/src/lib/server/env.ts @@ -0,0 +1,20 @@ +import * as dotenv from "dotenv"; +dotenv.config(); + +function getEnvironmentVariable(environmentVariable: string): string { + const validEnvironmentVariable = process.env[environmentVariable]; + if (!validEnvironmentVariable) { + throw new Error(`Couldn't find environment variable: ${environmentVariable}`); + } + return validEnvironmentVariable; +} + +export const ENV = { + PUBLIC_API_BASE_URL: getEnvironmentVariable("PUBLIC_API_BASE_URL"), + API_SERVICE_URL: getEnvironmentVariable("API_SERVICE_URL"), +}; + +export const API_URL = ENV.API_SERVICE_URL || ENV.PUBLIC_API_BASE_URL; + +console.log("Environment variables:", ENV); +console.log("Using API URL:", API_URL); diff --git a/modules/odr_frontend/src/routes/auth/login/+page.server.ts b/modules/odr_frontend/src/routes/auth/login/+page.server.ts index 9144b5c..f5289f8 100644 --- a/modules/odr_frontend/src/routes/auth/login/+page.server.ts +++ b/modules/odr_frontend/src/routes/auth/login/+page.server.ts @@ -1,5 +1,5 @@ import { redirect } from '@sveltejs/kit'; - +import { ENV } from '$lib/server/env'; /** @type {import('./$types').Actions} */ export const actions = { default: async (event) => { @@ -15,7 +15,7 @@ export const actions = { }; } - const loginRequest = await fetch('http://localhost:31100/api/v1/auth/login', { + const loginRequest = await fetch(`${ENV.API_SERVICE_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/modules/odr_frontend/src/routes/auth/register/+page.server.ts b/modules/odr_frontend/src/routes/auth/register/+page.server.ts index 85c3ecb..ed464cf 100644 --- a/modules/odr_frontend/src/routes/auth/register/+page.server.ts +++ b/modules/odr_frontend/src/routes/auth/register/+page.server.ts @@ -1,4 +1,6 @@ /** @type {import('./$types').Actions} */ +import { ENV } from '$lib/server/env'; + export const actions = { default: async (event) => { console.log('Registering new user...'); @@ -33,7 +35,7 @@ export const actions = { } else { console.info('Creating new user...'); //Use the python endpoint to create a new user - const req = await fetch('http://localhost:31100/api/v1/users/', { + const req = await fetch(`${ENV.API_SERVICE_URL}/users/`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -47,7 +49,7 @@ export const actions = { const res: Record = await req.json(); if (req.status === 200 && res?.username === body.get('username')) { console.log('User created successfully'); - const tokenReq = await fetch('http://localhost:31100/api/v1/auth/login', { + const tokenReq = await fetch(`${ENV.API_SERVICE_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/modules/odr_frontend/template.env b/modules/odr_frontend/template.env new file mode 100644 index 0000000..e9a150a --- /dev/null +++ b/modules/odr_frontend/template.env @@ -0,0 +1,2 @@ +PUBLIC_API_BASE_URL=http://localhost:31100 +API_SERVICE_URL=http://odr-api:31100