From 0d68b143554b290fe0b2f4718282eec659abc40c Mon Sep 17 00:00:00 2001 From: Rory Byrne Date: Sat, 17 Jan 2026 03:02:35 +0000 Subject: [PATCH 01/10] feat: integrate web UI into monorepo with Docker Compose deployment Restructure repository into a monorepo with server/ and web/ directories, enabling single-command deployment of the complete OSA stack. Changes: - Move Python backend into server/ directory - Add webapp as web/ directory (Next.js frontend) - Create docker-compose.yml for production deployment - Create docker-compose.dev.yml for hot-reload development - Add multi-stage Dockerfiles for both services - Configure health checks and service dependencies - Update CI workflow for monorepo with path filtering - Add root Justfile for orchestration commands - Update documentation with deployment instructions Closes #25 --- .env.example | 44 + .github/workflows/ci.yml | 116 +- .gitignore | 24 + .pre-commit-config.yaml | 4 +- Justfile | 193 +- README.md | 191 +- docker-compose.dev.yml | 39 + docker-compose.yml | 55 + .python-version => server/.python-version | 0 server/Dockerfile | 69 + server/Justfile | 87 + server/README.md | 33 + alembic.ini => server/alembic.ini | 0 server/entrypoint.sh | 10 + {migrations => server/migrations}/README | 0 {migrations => server/migrations}/env.py | 14 + .../migrations}/script.py.mako | 0 .../versions/0d9fbacf8e58_initial_tables.py | 0 {osa => server/osa}/__init__.py | 0 {osa => server/osa}/application/__init__.py | 0 .../osa}/application/api/__init__.py | 0 .../osa}/application/api/rest/__init__.py | 0 .../osa}/application/api/rest/app.py | 0 .../osa}/application/api/v1/__init__.py | 0 .../osa}/application/api/v1/errors.py | 0 .../application/api/v1/routes/__init__.py | 0 .../osa}/application/api/v1/routes/events.py | 0 .../osa}/application/api/v1/routes/health.py | 0 .../osa}/application/api/v1/routes/search.py | 0 .../osa}/application/api/v1/routes/stats.py | 0 .../application/api/v1/routes/validation.py | 0 {osa => server/osa}/application/di.py | 0 .../osa}/application/event/__init__.py | 0 .../osa}/application/event/server_started.py | 0 {osa => server/osa}/cli/__init__.py | 0 {osa => server/osa}/cli/commands/__init__.py | 0 {osa => server/osa}/cli/commands/admin.py | 0 {osa => server/osa}/cli/commands/events.py | 0 {osa => server/osa}/cli/commands/local.py | 0 {osa => server/osa}/cli/commands/search.py | 0 {osa => server/osa}/cli/commands/show.py | 0 {osa => server/osa}/cli/commands/stats.py | 0 {osa => server/osa}/cli/console.py | 0 {osa => server/osa}/cli/main.py | 0 {osa => server/osa}/cli/models.py | 0 {osa => server/osa}/cli/util/__init__.py | 0 {osa => server/osa}/cli/util/daemon.py | 0 {osa => server/osa}/cli/util/paths.py | 0 {osa => server/osa}/cli/util/search_cache.py | 0 {osa => server/osa}/cli/util/server_state.py | 0 {osa => server/osa}/config.py | 0 {osa => server/osa}/domain/__init__.py | 0 {osa => server/osa}/domain/auth/__init__.py | 0 .../osa}/domain/auth/adapter/__init__.py | 0 .../osa}/domain/auth/command/__init__.py | 0 .../osa}/domain/auth/event/__init__.py | 0 .../osa}/domain/auth/model/__init__.py | 0 .../osa}/domain/auth/port/__init__.py | 0 .../osa}/domain/auth/query/__init__.py | 0 .../osa}/domain/auth/service/__init__.py | 0 .../osa}/domain/curation/__init__.py | 0 .../osa}/domain/curation/adapter/__init__.py | 0 .../osa}/domain/curation/command/__init__.py | 0 .../osa}/domain/curation/event/__init__.py | 0 .../curation/event/deposition_approved.py | 0 .../osa}/domain/curation/listener/__init__.py | 0 .../listener/auto_approve_curation_tool.py | 0 .../osa}/domain/curation/model/__init__.py | 0 .../osa}/domain/curation/port/__init__.py | 0 .../osa}/domain/curation/query/__init__.py | 0 .../osa}/domain/curation/service/__init__.py | 0 .../osa}/domain/deposition/__init__.py | 0 .../domain/deposition/adapter/__init__.py | 0 .../domain/deposition/command/__init__.py | 0 .../osa}/domain/deposition/command/create.py | 0 .../domain/deposition/command/delete_files.py | 0 .../osa}/domain/deposition/command/submit.py | 0 .../osa}/domain/deposition/command/update.py | 0 .../osa}/domain/deposition/command/upload.py | 0 .../osa}/domain/deposition/event/__init__.py | 0 .../osa}/domain/deposition/event/submitted.py | 0 .../osa}/domain/deposition/model/__init__.py | 0 .../osa}/domain/deposition/model/aggregate.py | 0 .../osa}/domain/deposition/model/entity.py | 0 .../osa}/domain/deposition/model/value.py | 0 .../osa}/domain/deposition/port/__init__.py | 0 .../osa}/domain/deposition/port/repository.py | 0 .../osa}/domain/deposition/port/storage.py | 0 .../osa}/domain/deposition/query/__init__.py | 0 .../domain/deposition/service/__init__.py | 0 .../domain/deposition/service/deposition.py | 0 .../domain/deposition/util/di/__init__.py | 0 .../domain/deposition/util/di/provider.py | 0 {osa => server/osa}/domain/export/__init__.py | 0 .../osa}/domain/export/adapter/__init__.py | 0 .../osa}/domain/export/command/__init__.py | 0 .../osa}/domain/export/event/__init__.py | 0 .../osa}/domain/export/model/__init__.py | 0 .../osa}/domain/export/port/__init__.py | 0 .../osa}/domain/export/query/__init__.py | 0 .../osa}/domain/export/service/__init__.py | 0 {osa => server/osa}/domain/index/__init__.py | 0 .../osa}/domain/index/listener/__init__.py | 0 .../domain/index/listener/index_projector.py | 0 .../osa}/domain/index/model/__init__.py | 0 .../osa}/domain/index/model/registry.py | 0 .../osa}/domain/index/service/__init__.py | 0 .../osa}/domain/index/service/index.py | 0 {osa => server/osa}/domain/record/__init__.py | 0 .../osa}/domain/record/adapter/__init__.py | 0 .../osa}/domain/record/command/__init__.py | 0 .../osa}/domain/record/event/__init__.py | 0 .../domain/record/event/record_published.py | 0 .../osa}/domain/record/listener/__init__.py | 0 .../listener/record_creation_listener.py | 0 .../osa}/domain/record/model/__init__.py | 0 .../osa}/domain/record/model/aggregate.py | 0 .../osa}/domain/record/model/value.py | 0 .../osa}/domain/record/port/__init__.py | 0 .../osa}/domain/record/port/repository.py | 0 .../osa}/domain/record/query/__init__.py | 0 .../osa}/domain/record/service/__init__.py | 0 .../osa}/domain/record/service/record.py | 0 {osa => server/osa}/domain/schema/__init__.py | 0 .../osa}/domain/schema/adapter/__init__.py | 0 .../osa}/domain/schema/command/__init__.py | 0 .../osa}/domain/schema/event/__init__.py | 0 .../osa}/domain/schema/model/__init__.py | 0 .../osa}/domain/schema/port/__init__.py | 0 .../osa}/domain/schema/query/__init__.py | 0 .../osa}/domain/schema/service/__init__.py | 0 {osa => server/osa}/domain/search/__init__.py | 0 .../osa}/domain/search/adapter/__init__.py | 0 .../osa}/domain/search/command/__init__.py | 0 .../osa}/domain/search/event/__init__.py | 0 .../osa}/domain/search/model/__init__.py | 0 .../osa}/domain/search/port/__init__.py | 0 .../osa}/domain/search/query/__init__.py | 0 .../osa}/domain/search/service/__init__.py | 0 {osa => server/osa}/domain/shared/__init__.py | 0 {osa => server/osa}/domain/shared/adapter.py | 0 {osa => server/osa}/domain/shared/command.py | 0 {osa => server/osa}/domain/shared/dto.py | 0 {osa => server/osa}/domain/shared/error.py | 0 {osa => server/osa}/domain/shared/event.py | 0 .../osa}/domain/shared/event_log.py | 0 .../osa}/domain/shared/model/__init__.py | 0 .../osa}/domain/shared/model/aggregate.py | 0 .../osa}/domain/shared/model/entity.py | 0 .../osa}/domain/shared/model/srn.py | 0 .../osa}/domain/shared/model/value.py | 0 {osa => server/osa}/domain/shared/outbox.py | 0 .../osa}/domain/shared/port/__init__.py | 0 .../osa}/domain/shared/port/base.py | 0 .../domain/shared/port/event_repository.py | 0 {osa => server/osa}/domain/shared/query.py | 0 {osa => server/osa}/domain/shared/service.py | 0 {osa => server/osa}/domain/source/__init__.py | 0 .../osa}/domain/source/event/__init__.py | 0 .../domain/source/event/source_requested.py | 0 .../source/event/source_run_completed.py | 0 .../osa}/domain/source/listener/__init__.py | 0 .../listener/initial_source_listener.py | 0 .../domain/source/listener/source_listener.py | 0 .../osa}/domain/source/model/__init__.py | 0 .../osa}/domain/source/model/registry.py | 0 .../osa}/domain/source/schedule/__init__.py | 0 .../domain/source/schedule/source_schedule.py | 0 .../osa}/domain/source/service/__init__.py | 0 .../osa}/domain/source/service/source.py | 0 .../osa}/domain/validation/__init__.py | 0 .../domain/validation/adapter/__init__.py | 0 .../domain/validation/command/__init__.py | 0 .../osa}/domain/validation/event/__init__.py | 0 .../validation/event/validation_completed.py | 0 .../validation/event/validation_started.py | 0 .../osa}/domain/validation/handler.py | 0 .../domain/validation/listener/__init__.py | 0 .../listener/validation_listener.py | 0 .../osa}/domain/validation/model/__init__.py | 0 .../osa}/domain/validation/model/entity.py | 0 .../osa}/domain/validation/model/value.py | 0 .../osa}/domain/validation/port/__init__.py | 0 .../osa}/domain/validation/port/repository.py | 0 .../osa}/domain/validation/port/runner.py | 0 .../osa}/domain/validation/query/__init__.py | 0 .../domain/validation/service/__init__.py | 0 .../domain/validation/service/validation.py | 0 .../domain/validation/util/di/__init__.py | 0 .../domain/validation/util/di/provider.py | 0 .../osa}/infrastructure/__init__.py | 0 .../osa}/infrastructure/event/__init__.py | 0 .../osa}/infrastructure/event/di.py | 0 .../osa}/infrastructure/event/worker.py | 0 .../osa}/infrastructure/index/__init__.py | 0 .../osa}/infrastructure/index/di.py | 0 .../infrastructure/index/vector/__init__.py | 0 .../infrastructure/index/vector/backend.py | 0 .../infrastructure/index/vector/config.py | 0 .../osa}/infrastructure/messaging/__init__.py | 0 .../osa}/infrastructure/oci/__init__.py | 0 {osa => server/osa}/infrastructure/oci/di.py | 0 .../osa}/infrastructure/oci/runner.py | 0 .../infrastructure/persistence/__init__.py | 0 .../persistence/adapter/__init__.py | 0 .../persistence/adapter/storage.py | 0 .../infrastructure/persistence/database.py | 0 .../osa}/infrastructure/persistence/di.py | 0 .../persistence/mappers/deposition.py | 0 .../persistence/mappers/record.py | 0 .../persistence/mappers/validation.py | 0 .../infrastructure/persistence/migrate.py | 0 .../persistence/repository/deposition.py | 0 .../persistence/repository/event.py | 0 .../persistence/repository/record.py | 0 .../persistence/repository/validation.py | 0 .../osa}/infrastructure/persistence/tables.py | 0 .../osa}/infrastructure/source/__init__.py | 0 .../osa}/infrastructure/source/di.py | 0 .../osa}/infrastructure/source/discovery.py | 0 {osa => server/osa}/sdk/__init__.py | 0 {osa => server/osa}/sdk/index/__init__.py | 0 {osa => server/osa}/sdk/index/backend.py | 0 {osa => server/osa}/sdk/index/config.py | 0 {osa => server/osa}/sdk/index/result.py | 0 {osa => server/osa}/sdk/source/__init__.py | 0 {osa => server/osa}/sdk/source/config.py | 0 {osa => server/osa}/sdk/source/record.py | 0 {osa => server/osa}/sdk/source/source.py | 0 {osa => server/osa}/util/__init__.py | 0 {osa => server/osa}/util/di/__init__.py | 0 {osa => server/osa}/util/di/base.py | 0 {osa => server/osa}/util/di/container.py | 0 {osa => server/osa}/util/di/fastapi.py | 0 {osa => server/osa}/util/di/scope.py | 0 pyproject.toml => server/pyproject.toml | 2 + {sources => server/sources}/__init__.py | 0 .../sources}/geo_entrez/__init__.py | 0 .../sources}/geo_entrez/config.py | 0 .../sources}/geo_entrez/source.py | 0 {tests => server/tests}/conftest.py | 0 .../tests}/integration/__init__.py | 0 .../integration/infrastructure/__init__.py | 0 .../infrastructure/source/__init__.py | 0 .../tests}/test_sources/__init__.py | 0 .../test_sources/geo_entrez/__init__.py | 0 .../test_sources/geo_entrez/test_source.py | 0 {tests => server/tests}/unit/cli/__init__.py | 0 .../tests}/unit/cli/util/__init__.py | 0 .../tests}/unit/cli/util/test_paths.py | 0 .../tests}/unit/config/__init__.py | 0 .../tests}/unit/config/test_paths_config.py | 0 .../tests}/unit/domain/index/__init__.py | 0 .../unit/domain/index/test_index_service.py | 0 .../tests}/unit/domain/record/__init__.py | 0 .../unit/domain/record/test_record_service.py | 0 .../tests}/unit/domain/shared/test_srn.py | 0 .../tests}/unit/domain/source/__init__.py | 0 .../unit/domain/source/test_source_service.py | 0 .../tests}/unit/domain/validation/__init__.py | 0 .../index/test_vector_config.py | 0 uv.lock => server/uv.lock | 66 + web/.gitignore | 41 + web/Dockerfile | 51 + web/README.md | 36 + web/eslint.config.mjs | 18 + web/next.config.ts | 18 + web/package.json | 27 + web/pnpm-lock.yaml | 4017 +++++++++++++++++ web/postcss.config.mjs | 7 + web/public/osa_logo.png | Bin 0 -> 10538 bytes web/public/osa_logo.svg | 3 + web/src/app/apple-icon.png | Bin 0 -> 10538 bytes web/src/app/error.module.css | 6 + web/src/app/error.tsx | 21 + web/src/app/globals.css | 60 + web/src/app/icon.svg | 3 + web/src/app/layout.tsx | 47 + web/src/app/page.tsx | 9 + web/src/app/record/[srn]/error.module.css | 6 + web/src/app/record/[srn]/error.tsx | 21 + web/src/app/record/[srn]/loading.module.css | 6 + web/src/app/record/[srn]/loading.tsx | 10 + web/src/app/record/[srn]/not-found.module.css | 65 + web/src/app/record/[srn]/not-found.tsx | 37 + web/src/app/record/[srn]/page.module.css | 67 + web/src/app/record/[srn]/page.tsx | 47 + web/src/app/search/error.module.css | 6 + web/src/app/search/error.tsx | 21 + web/src/app/search/loading.module.css | 6 + web/src/app/search/loading.tsx | 10 + web/src/app/search/page.module.css | 24 + web/src/app/search/page.tsx | 48 + web/src/components/layout/Footer.module.css | 117 + web/src/components/layout/Footer.tsx | 78 + web/src/components/layout/Header.module.css | 53 + web/src/components/layout/Header.tsx | 22 + .../components/record/RecordDetail.module.css | 145 + web/src/components/record/RecordDetail.tsx | 84 + .../components/search/SearchHero.module.css | 98 + web/src/components/search/SearchHero.tsx | 40 + .../components/search/SearchHit.module.css | 98 + web/src/components/search/SearchHit.tsx | 53 + .../components/search/SearchInput.module.css | 112 + web/src/components/search/SearchInput.tsx | 96 + .../search/SearchResults.module.css | 43 + web/src/components/search/SearchResults.tsx | 74 + web/src/components/ui/BackButton.module.css | 14 + web/src/components/ui/BackButton.tsx | 27 + web/src/components/ui/EmptyState.module.css | 27 + web/src/components/ui/EmptyState.tsx | 17 + web/src/components/ui/ErrorMessage.module.css | 36 + web/src/components/ui/ErrorMessage.tsx | 27 + .../components/ui/LoadingSpinner.module.css | 39 + web/src/components/ui/LoadingSpinner.tsx | 15 + web/src/types/api.ts | 83 + web/src/types/index.ts | 20 + web/src/types/record.ts | 62 + web/tsconfig.json | 34 + 319 files changed, 7007 insertions(+), 192 deletions(-) create mode 100644 .env.example create mode 100644 docker-compose.dev.yml create mode 100644 docker-compose.yml rename .python-version => server/.python-version (100%) create mode 100644 server/Dockerfile create mode 100644 server/Justfile create mode 100644 server/README.md rename alembic.ini => server/alembic.ini (100%) create mode 100644 server/entrypoint.sh rename {migrations => server/migrations}/README (100%) rename {migrations => server/migrations}/env.py (75%) rename {migrations => server/migrations}/script.py.mako (100%) rename {migrations => server/migrations}/versions/0d9fbacf8e58_initial_tables.py (100%) rename {osa => server/osa}/__init__.py (100%) rename {osa => server/osa}/application/__init__.py (100%) rename {osa => server/osa}/application/api/__init__.py (100%) rename {osa => server/osa}/application/api/rest/__init__.py (100%) rename {osa => server/osa}/application/api/rest/app.py (100%) rename {osa => server/osa}/application/api/v1/__init__.py (100%) rename {osa => server/osa}/application/api/v1/errors.py (100%) rename {osa => server/osa}/application/api/v1/routes/__init__.py (100%) rename {osa => server/osa}/application/api/v1/routes/events.py (100%) rename {osa => server/osa}/application/api/v1/routes/health.py (100%) rename {osa => server/osa}/application/api/v1/routes/search.py (100%) rename {osa => server/osa}/application/api/v1/routes/stats.py (100%) rename {osa => server/osa}/application/api/v1/routes/validation.py (100%) rename {osa => server/osa}/application/di.py (100%) rename {osa => server/osa}/application/event/__init__.py (100%) rename {osa => server/osa}/application/event/server_started.py (100%) rename {osa => server/osa}/cli/__init__.py (100%) rename {osa => server/osa}/cli/commands/__init__.py (100%) rename {osa => server/osa}/cli/commands/admin.py (100%) rename {osa => server/osa}/cli/commands/events.py (100%) rename {osa => server/osa}/cli/commands/local.py (100%) rename {osa => server/osa}/cli/commands/search.py (100%) rename {osa => server/osa}/cli/commands/show.py (100%) rename {osa => server/osa}/cli/commands/stats.py (100%) rename {osa => server/osa}/cli/console.py (100%) rename {osa => server/osa}/cli/main.py (100%) rename {osa => server/osa}/cli/models.py (100%) rename {osa => server/osa}/cli/util/__init__.py (100%) rename {osa => server/osa}/cli/util/daemon.py (100%) rename {osa => server/osa}/cli/util/paths.py (100%) rename {osa => server/osa}/cli/util/search_cache.py (100%) rename {osa => server/osa}/cli/util/server_state.py (100%) rename {osa => server/osa}/config.py (100%) rename {osa => server/osa}/domain/__init__.py (100%) rename {osa => server/osa}/domain/auth/__init__.py (100%) rename {osa => server/osa}/domain/auth/adapter/__init__.py (100%) rename {osa => server/osa}/domain/auth/command/__init__.py (100%) rename {osa => server/osa}/domain/auth/event/__init__.py (100%) rename {osa => server/osa}/domain/auth/model/__init__.py (100%) rename {osa => server/osa}/domain/auth/port/__init__.py (100%) rename {osa => server/osa}/domain/auth/query/__init__.py (100%) rename {osa => server/osa}/domain/auth/service/__init__.py (100%) rename {osa => server/osa}/domain/curation/__init__.py (100%) rename {osa => server/osa}/domain/curation/adapter/__init__.py (100%) rename {osa => server/osa}/domain/curation/command/__init__.py (100%) rename {osa => server/osa}/domain/curation/event/__init__.py (100%) rename {osa => server/osa}/domain/curation/event/deposition_approved.py (100%) rename {osa => server/osa}/domain/curation/listener/__init__.py (100%) rename {osa => server/osa}/domain/curation/listener/auto_approve_curation_tool.py (100%) rename {osa => server/osa}/domain/curation/model/__init__.py (100%) rename {osa => server/osa}/domain/curation/port/__init__.py (100%) rename {osa => server/osa}/domain/curation/query/__init__.py (100%) rename {osa => server/osa}/domain/curation/service/__init__.py (100%) rename {osa => server/osa}/domain/deposition/__init__.py (100%) rename {osa => server/osa}/domain/deposition/adapter/__init__.py (100%) rename {osa => server/osa}/domain/deposition/command/__init__.py (100%) rename {osa => server/osa}/domain/deposition/command/create.py (100%) rename {osa => server/osa}/domain/deposition/command/delete_files.py (100%) rename {osa => server/osa}/domain/deposition/command/submit.py (100%) rename {osa => server/osa}/domain/deposition/command/update.py (100%) rename {osa => server/osa}/domain/deposition/command/upload.py (100%) rename {osa => server/osa}/domain/deposition/event/__init__.py (100%) rename {osa => server/osa}/domain/deposition/event/submitted.py (100%) rename {osa => server/osa}/domain/deposition/model/__init__.py (100%) rename {osa => server/osa}/domain/deposition/model/aggregate.py (100%) rename {osa => server/osa}/domain/deposition/model/entity.py (100%) rename {osa => server/osa}/domain/deposition/model/value.py (100%) rename {osa => server/osa}/domain/deposition/port/__init__.py (100%) rename {osa => server/osa}/domain/deposition/port/repository.py (100%) rename {osa => server/osa}/domain/deposition/port/storage.py (100%) rename {osa => server/osa}/domain/deposition/query/__init__.py (100%) rename {osa => server/osa}/domain/deposition/service/__init__.py (100%) rename {osa => server/osa}/domain/deposition/service/deposition.py (100%) rename {osa => server/osa}/domain/deposition/util/di/__init__.py (100%) rename {osa => server/osa}/domain/deposition/util/di/provider.py (100%) rename {osa => server/osa}/domain/export/__init__.py (100%) rename {osa => server/osa}/domain/export/adapter/__init__.py (100%) rename {osa => server/osa}/domain/export/command/__init__.py (100%) rename {osa => server/osa}/domain/export/event/__init__.py (100%) rename {osa => server/osa}/domain/export/model/__init__.py (100%) rename {osa => server/osa}/domain/export/port/__init__.py (100%) rename {osa => server/osa}/domain/export/query/__init__.py (100%) rename {osa => server/osa}/domain/export/service/__init__.py (100%) rename {osa => server/osa}/domain/index/__init__.py (100%) rename {osa => server/osa}/domain/index/listener/__init__.py (100%) rename {osa => server/osa}/domain/index/listener/index_projector.py (100%) rename {osa => server/osa}/domain/index/model/__init__.py (100%) rename {osa => server/osa}/domain/index/model/registry.py (100%) rename {osa => server/osa}/domain/index/service/__init__.py (100%) rename {osa => server/osa}/domain/index/service/index.py (100%) rename {osa => server/osa}/domain/record/__init__.py (100%) rename {osa => server/osa}/domain/record/adapter/__init__.py (100%) rename {osa => server/osa}/domain/record/command/__init__.py (100%) rename {osa => server/osa}/domain/record/event/__init__.py (100%) rename {osa => server/osa}/domain/record/event/record_published.py (100%) rename {osa => server/osa}/domain/record/listener/__init__.py (100%) rename {osa => server/osa}/domain/record/listener/record_creation_listener.py (100%) rename {osa => server/osa}/domain/record/model/__init__.py (100%) rename {osa => server/osa}/domain/record/model/aggregate.py (100%) rename {osa => server/osa}/domain/record/model/value.py (100%) rename {osa => server/osa}/domain/record/port/__init__.py (100%) rename {osa => server/osa}/domain/record/port/repository.py (100%) rename {osa => server/osa}/domain/record/query/__init__.py (100%) rename {osa => server/osa}/domain/record/service/__init__.py (100%) rename {osa => server/osa}/domain/record/service/record.py (100%) rename {osa => server/osa}/domain/schema/__init__.py (100%) rename {osa => server/osa}/domain/schema/adapter/__init__.py (100%) rename {osa => server/osa}/domain/schema/command/__init__.py (100%) rename {osa => server/osa}/domain/schema/event/__init__.py (100%) rename {osa => server/osa}/domain/schema/model/__init__.py (100%) rename {osa => server/osa}/domain/schema/port/__init__.py (100%) rename {osa => server/osa}/domain/schema/query/__init__.py (100%) rename {osa => server/osa}/domain/schema/service/__init__.py (100%) rename {osa => server/osa}/domain/search/__init__.py (100%) rename {osa => server/osa}/domain/search/adapter/__init__.py (100%) rename {osa => server/osa}/domain/search/command/__init__.py (100%) rename {osa => server/osa}/domain/search/event/__init__.py (100%) rename {osa => server/osa}/domain/search/model/__init__.py (100%) rename {osa => server/osa}/domain/search/port/__init__.py (100%) rename {osa => server/osa}/domain/search/query/__init__.py (100%) rename {osa => server/osa}/domain/search/service/__init__.py (100%) rename {osa => server/osa}/domain/shared/__init__.py (100%) rename {osa => server/osa}/domain/shared/adapter.py (100%) rename {osa => server/osa}/domain/shared/command.py (100%) rename {osa => server/osa}/domain/shared/dto.py (100%) rename {osa => server/osa}/domain/shared/error.py (100%) rename {osa => server/osa}/domain/shared/event.py (100%) rename {osa => server/osa}/domain/shared/event_log.py (100%) rename {osa => server/osa}/domain/shared/model/__init__.py (100%) rename {osa => server/osa}/domain/shared/model/aggregate.py (100%) rename {osa => server/osa}/domain/shared/model/entity.py (100%) rename {osa => server/osa}/domain/shared/model/srn.py (100%) rename {osa => server/osa}/domain/shared/model/value.py (100%) rename {osa => server/osa}/domain/shared/outbox.py (100%) rename {osa => server/osa}/domain/shared/port/__init__.py (100%) rename {osa => server/osa}/domain/shared/port/base.py (100%) rename {osa => server/osa}/domain/shared/port/event_repository.py (100%) rename {osa => server/osa}/domain/shared/query.py (100%) rename {osa => server/osa}/domain/shared/service.py (100%) rename {osa => server/osa}/domain/source/__init__.py (100%) rename {osa => server/osa}/domain/source/event/__init__.py (100%) rename {osa => server/osa}/domain/source/event/source_requested.py (100%) rename {osa => server/osa}/domain/source/event/source_run_completed.py (100%) rename {osa => server/osa}/domain/source/listener/__init__.py (100%) rename {osa => server/osa}/domain/source/listener/initial_source_listener.py (100%) rename {osa => server/osa}/domain/source/listener/source_listener.py (100%) rename {osa => server/osa}/domain/source/model/__init__.py (100%) rename {osa => server/osa}/domain/source/model/registry.py (100%) rename {osa => server/osa}/domain/source/schedule/__init__.py (100%) rename {osa => server/osa}/domain/source/schedule/source_schedule.py (100%) rename {osa => server/osa}/domain/source/service/__init__.py (100%) rename {osa => server/osa}/domain/source/service/source.py (100%) rename {osa => server/osa}/domain/validation/__init__.py (100%) rename {osa => server/osa}/domain/validation/adapter/__init__.py (100%) rename {osa => server/osa}/domain/validation/command/__init__.py (100%) rename {osa => server/osa}/domain/validation/event/__init__.py (100%) rename {osa => server/osa}/domain/validation/event/validation_completed.py (100%) rename {osa => server/osa}/domain/validation/event/validation_started.py (100%) rename {osa => server/osa}/domain/validation/handler.py (100%) rename {osa => server/osa}/domain/validation/listener/__init__.py (100%) rename {osa => server/osa}/domain/validation/listener/validation_listener.py (100%) rename {osa => server/osa}/domain/validation/model/__init__.py (100%) rename {osa => server/osa}/domain/validation/model/entity.py (100%) rename {osa => server/osa}/domain/validation/model/value.py (100%) rename {osa => server/osa}/domain/validation/port/__init__.py (100%) rename {osa => server/osa}/domain/validation/port/repository.py (100%) rename {osa => server/osa}/domain/validation/port/runner.py (100%) rename {osa => server/osa}/domain/validation/query/__init__.py (100%) rename {osa => server/osa}/domain/validation/service/__init__.py (100%) rename {osa => server/osa}/domain/validation/service/validation.py (100%) rename {osa => server/osa}/domain/validation/util/di/__init__.py (100%) rename {osa => server/osa}/domain/validation/util/di/provider.py (100%) rename {osa => server/osa}/infrastructure/__init__.py (100%) rename {osa => server/osa}/infrastructure/event/__init__.py (100%) rename {osa => server/osa}/infrastructure/event/di.py (100%) rename {osa => server/osa}/infrastructure/event/worker.py (100%) rename {osa => server/osa}/infrastructure/index/__init__.py (100%) rename {osa => server/osa}/infrastructure/index/di.py (100%) rename {osa => server/osa}/infrastructure/index/vector/__init__.py (100%) rename {osa => server/osa}/infrastructure/index/vector/backend.py (100%) rename {osa => server/osa}/infrastructure/index/vector/config.py (100%) rename {osa => server/osa}/infrastructure/messaging/__init__.py (100%) rename {osa => server/osa}/infrastructure/oci/__init__.py (100%) rename {osa => server/osa}/infrastructure/oci/di.py (100%) rename {osa => server/osa}/infrastructure/oci/runner.py (100%) rename {osa => server/osa}/infrastructure/persistence/__init__.py (100%) rename {osa => server/osa}/infrastructure/persistence/adapter/__init__.py (100%) rename {osa => server/osa}/infrastructure/persistence/adapter/storage.py (100%) rename {osa => server/osa}/infrastructure/persistence/database.py (100%) rename {osa => server/osa}/infrastructure/persistence/di.py (100%) rename {osa => server/osa}/infrastructure/persistence/mappers/deposition.py (100%) rename {osa => server/osa}/infrastructure/persistence/mappers/record.py (100%) rename {osa => server/osa}/infrastructure/persistence/mappers/validation.py (100%) rename {osa => server/osa}/infrastructure/persistence/migrate.py (100%) rename {osa => server/osa}/infrastructure/persistence/repository/deposition.py (100%) rename {osa => server/osa}/infrastructure/persistence/repository/event.py (100%) rename {osa => server/osa}/infrastructure/persistence/repository/record.py (100%) rename {osa => server/osa}/infrastructure/persistence/repository/validation.py (100%) rename {osa => server/osa}/infrastructure/persistence/tables.py (100%) rename {osa => server/osa}/infrastructure/source/__init__.py (100%) rename {osa => server/osa}/infrastructure/source/di.py (100%) rename {osa => server/osa}/infrastructure/source/discovery.py (100%) rename {osa => server/osa}/sdk/__init__.py (100%) rename {osa => server/osa}/sdk/index/__init__.py (100%) rename {osa => server/osa}/sdk/index/backend.py (100%) rename {osa => server/osa}/sdk/index/config.py (100%) rename {osa => server/osa}/sdk/index/result.py (100%) rename {osa => server/osa}/sdk/source/__init__.py (100%) rename {osa => server/osa}/sdk/source/config.py (100%) rename {osa => server/osa}/sdk/source/record.py (100%) rename {osa => server/osa}/sdk/source/source.py (100%) rename {osa => server/osa}/util/__init__.py (100%) rename {osa => server/osa}/util/di/__init__.py (100%) rename {osa => server/osa}/util/di/base.py (100%) rename {osa => server/osa}/util/di/container.py (100%) rename {osa => server/osa}/util/di/fastapi.py (100%) rename {osa => server/osa}/util/di/scope.py (100%) rename pyproject.toml => server/pyproject.toml (95%) rename {sources => server/sources}/__init__.py (100%) rename {sources => server/sources}/geo_entrez/__init__.py (100%) rename {sources => server/sources}/geo_entrez/config.py (100%) rename {sources => server/sources}/geo_entrez/source.py (100%) rename {tests => server/tests}/conftest.py (100%) rename {tests => server/tests}/integration/__init__.py (100%) rename {tests => server/tests}/integration/infrastructure/__init__.py (100%) rename {tests => server/tests}/integration/infrastructure/source/__init__.py (100%) rename {tests => server/tests}/test_sources/__init__.py (100%) rename {tests => server/tests}/test_sources/geo_entrez/__init__.py (100%) rename {tests => server/tests}/test_sources/geo_entrez/test_source.py (100%) rename {tests => server/tests}/unit/cli/__init__.py (100%) rename {tests => server/tests}/unit/cli/util/__init__.py (100%) rename {tests => server/tests}/unit/cli/util/test_paths.py (100%) rename {tests => server/tests}/unit/config/__init__.py (100%) rename {tests => server/tests}/unit/config/test_paths_config.py (100%) rename {tests => server/tests}/unit/domain/index/__init__.py (100%) rename {tests => server/tests}/unit/domain/index/test_index_service.py (100%) rename {tests => server/tests}/unit/domain/record/__init__.py (100%) rename {tests => server/tests}/unit/domain/record/test_record_service.py (100%) rename {tests => server/tests}/unit/domain/shared/test_srn.py (100%) rename {tests => server/tests}/unit/domain/source/__init__.py (100%) rename {tests => server/tests}/unit/domain/source/test_source_service.py (100%) rename {tests => server/tests}/unit/domain/validation/__init__.py (100%) rename {tests => server/tests}/unit/infrastructure/index/test_vector_config.py (100%) rename uv.lock => server/uv.lock (97%) create mode 100644 web/.gitignore create mode 100644 web/Dockerfile create mode 100644 web/README.md create mode 100644 web/eslint.config.mjs create mode 100644 web/next.config.ts create mode 100644 web/package.json create mode 100644 web/pnpm-lock.yaml create mode 100644 web/postcss.config.mjs create mode 100644 web/public/osa_logo.png create mode 100644 web/public/osa_logo.svg create mode 100644 web/src/app/apple-icon.png create mode 100644 web/src/app/error.module.css create mode 100644 web/src/app/error.tsx create mode 100644 web/src/app/globals.css create mode 100644 web/src/app/icon.svg create mode 100644 web/src/app/layout.tsx create mode 100644 web/src/app/page.tsx create mode 100644 web/src/app/record/[srn]/error.module.css create mode 100644 web/src/app/record/[srn]/error.tsx create mode 100644 web/src/app/record/[srn]/loading.module.css create mode 100644 web/src/app/record/[srn]/loading.tsx create mode 100644 web/src/app/record/[srn]/not-found.module.css create mode 100644 web/src/app/record/[srn]/not-found.tsx create mode 100644 web/src/app/record/[srn]/page.module.css create mode 100644 web/src/app/record/[srn]/page.tsx create mode 100644 web/src/app/search/error.module.css create mode 100644 web/src/app/search/error.tsx create mode 100644 web/src/app/search/loading.module.css create mode 100644 web/src/app/search/loading.tsx create mode 100644 web/src/app/search/page.module.css create mode 100644 web/src/app/search/page.tsx create mode 100644 web/src/components/layout/Footer.module.css create mode 100644 web/src/components/layout/Footer.tsx create mode 100644 web/src/components/layout/Header.module.css create mode 100644 web/src/components/layout/Header.tsx create mode 100644 web/src/components/record/RecordDetail.module.css create mode 100644 web/src/components/record/RecordDetail.tsx create mode 100644 web/src/components/search/SearchHero.module.css create mode 100644 web/src/components/search/SearchHero.tsx create mode 100644 web/src/components/search/SearchHit.module.css create mode 100644 web/src/components/search/SearchHit.tsx create mode 100644 web/src/components/search/SearchInput.module.css create mode 100644 web/src/components/search/SearchInput.tsx create mode 100644 web/src/components/search/SearchResults.module.css create mode 100644 web/src/components/search/SearchResults.tsx create mode 100644 web/src/components/ui/BackButton.module.css create mode 100644 web/src/components/ui/BackButton.tsx create mode 100644 web/src/components/ui/EmptyState.module.css create mode 100644 web/src/components/ui/EmptyState.tsx create mode 100644 web/src/components/ui/ErrorMessage.module.css create mode 100644 web/src/components/ui/ErrorMessage.tsx create mode 100644 web/src/components/ui/LoadingSpinner.module.css create mode 100644 web/src/components/ui/LoadingSpinner.tsx create mode 100644 web/src/types/api.ts create mode 100644 web/src/types/index.ts create mode 100644 web/src/types/record.ts create mode 100644 web/tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..17b6265 --- /dev/null +++ b/.env.example @@ -0,0 +1,44 @@ +# OSA Environment Configuration +# Copy to .env and customize values + +# ============================================================================= +# Database Configuration +# ============================================================================= +# PostgreSQL credentials used by all services +POSTGRES_USER=postgres +POSTGRES_PASSWORD=osa +POSTGRES_DB=osa +POSTGRES_HOST=db +POSTGRES_PORT=5432 + +# ============================================================================= +# API Server Configuration +# ============================================================================= +# Host and port for the FastAPI backend +API_HOST=0.0.0.0 +API_PORT=8000 + +# Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) +LOG_LEVEL=INFO + +# Data directory for OSA storage (inside container) +OSA_DATA_DIR=/data + +# ============================================================================= +# Web Interface Configuration +# ============================================================================= +# External port to access the web interface (maps to container port 3000) +# Change this if port 8080 is already in use +WEB_PORT=8080 + +# Backend API URL (used by the web container for SSR) +# In Docker, this should use the service name 'server' +API_URL=http://server:8000 + +# ============================================================================= +# Development Settings (optional) +# ============================================================================= +# These are only used in development mode (docker-compose.dev.yml) + +# Force polling for file changes (required for some systems like WSL2) +# WATCHFILES_FORCE_POLLING=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b01995..e40dab2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,16 +8,39 @@ on: env: PYTHON_VERSION: "3.13" + NODE_VERSION: "22" jobs: - lint: - name: Lint & Format + # Detect which paths changed + changes: + name: Detect Changes runs-on: ubuntu-latest + outputs: + server: ${{ steps.filter.outputs.server }} + web: ${{ steps.filter.outputs.web }} steps: - uses: actions/checkout@v4 - - name: Install just - uses: extractions/setup-just@v2 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + server: + - 'server/**' + web: + - 'web/**' + + # Server (Python backend) checks + server-lint: + name: Server - Lint & Format + needs: changes + if: needs.changes.outputs.server == 'true' || github.event_name == 'push' + runs-on: ubuntu-latest + defaults: + run: + working-directory: server + steps: + - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v4 @@ -36,15 +59,17 @@ jobs: - name: Check linting run: uv run ruff check . - typecheck: - name: Type Check + server-typecheck: + name: Server - Type Check + needs: changes + if: needs.changes.outputs.server == 'true' || github.event_name == 'push' runs-on: ubuntu-latest + defaults: + run: + working-directory: server steps: - uses: actions/checkout@v4 - - name: Install just - uses: extractions/setup-just@v2 - - name: Install uv uses: astral-sh/setup-uv@v4 with: @@ -59,18 +84,20 @@ jobs: - name: Run type checker run: uv run ty check osa - test: - name: Test + server-test: + name: Server - Test + needs: changes + if: needs.changes.outputs.server == 'true' || github.event_name == 'push' runs-on: ubuntu-latest + defaults: + run: + working-directory: server permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v4 - - name: Install just - uses: extractions/setup-just@v2 - - name: Install uv uses: astral-sh/setup-uv@v4 with: @@ -90,7 +117,7 @@ jobs: - name: Code Coverage Summary uses: irongut/CodeCoverageSummary@v1.3.0 with: - filename: coverage.xml + filename: server/coverage.xml badge: true format: markdown output: both @@ -100,3 +127,62 @@ jobs: if: github.event_name == 'pull_request' with: path: code-coverage-results.md + + # Web (Next.js frontend) checks + web-lint: + name: Web - Lint + needs: changes + if: needs.changes.outputs.web == 'true' || github.event_name == 'push' + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: latest + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + cache-dependency-path: web/pnpm-lock.yaml + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run linter + run: pnpm lint + + web-build: + name: Web - Build + needs: changes + if: needs.changes.outputs.web == 'true' || github.event_name == 'push' + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: latest + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + cache-dependency-path: web/pnpm-lock.yaml + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm build diff --git a/.gitignore b/.gitignore index 42f20c5..0bacab6 100644 --- a/.gitignore +++ b/.gitignore @@ -214,3 +214,27 @@ __marimo__/ # Streamlit .streamlit/secrets.toml + +# Monorepo - Server specific +server/.venv/ +server/.coverage +server/.coverage.* +server/coverage.xml +server/htmlcov/ +server/.pytest_cache/ +server/.ruff_cache/ +server/__pycache__/ +server/*.egg-info/ + +# Monorepo - Web specific +web/node_modules/ +web/.next/ +web/.env.local +web/.turbo/ + +# Docker +.docker/ + +# Environment +.env +!.env.example diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3a0da0e..cc180ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,14 +23,14 @@ repos: hooks: - id: ty-check name: ty type check - entry: uv run ty check osa + entry: env -u VIRTUAL_ENV uv run --directory server ty check osa language: system types: [python] pass_filenames: false - id: unit-tests name: unit tests - entry: uv run pytest tests/unit -q --tb=short + entry: env -u VIRTUAL_ENV uv run --directory server pytest tests/unit -q --tb=short language: system types: [python] pass_filenames: false diff --git a/Justfile b/Justfile index ba4f56f..919c7d2 100644 --- a/Justfile +++ b/Justfile @@ -1,142 +1,119 @@ -# Import deployment commands -# mod local 'deployment/local/local.just' +# OSA Monorepo Justfile +# Production deployment and development orchestration commands default: @just --list -# === PostgreSQL (Docker) === +# === Production Deployment === -# Start PostgreSQL in Docker -db-up: - @just local up - -# Stop PostgreSQL -db-down: - @just local down - -# View PostgreSQL logs -db-logs: - @just local logs - -# Connect to PostgreSQL with psql -db-connect: - @just local db-connect +# Start all services in production mode +up: + docker compose up -d -# Reset database (WARNING: deletes all data) -db-wipe: - @just local wipe +# Start all services with logs visible +up-attached: + docker compose up -# === Migrations (Local) === +# Stop all services +down: + docker compose down -# Run migrations against Docker PostgreSQL -migrate: - uv run alembic upgrade head +# View logs from all services +logs: + docker compose logs -f -# Create new migration -migration name: - uv run alembic revision -m "{{name}}" +# View logs from a specific service +logs-service service: + docker compose logs -f {{service}} -# Show current migration version -migrate-status: - uv run alembic current +# View server logs +server-logs: + docker compose logs -f server -# Show migration history -migrate-history: - uv run alembic history +# View last N lines of server logs (default: 100) +server-logs-tail lines="100": + docker compose logs --tail {{lines}} server -# Rollback one migration -migrate-down: - uv run alembic downgrade -1 +# View server logs with timestamps +server-logs-time: + docker compose logs -f -t server -# === CLI (Local) === +# View server logs since a time (e.g., "10m", "1h", "2024-01-01") +server-logs-since since: + docker compose logs -f --since {{since}} server -# Run any osa CLI command -cli *ARGS: - uv run osa {{ARGS}} +# Shell into the server container +server-shell: + docker compose exec server bash -# Initialize a field -init FIELD: - uv run osa field init {{FIELD}} +# Restart just the server +server-restart: + docker compose restart server -# Wipe all local OSA data (database, vectors, cache) -wipe: - uv run osa local clean --force +# Restart all services +restart: + docker compose restart -# === Complete Workflow === +# Rebuild and restart services +rebuild: + docker compose up -d --build -# Set up everything for first time (start DB + run migrations) -setup: - @echo "Starting PostgreSQL..." - @just db-up - @echo "Waiting for PostgreSQL to be ready..." - @sleep 3 - @echo "Running migrations..." - @just migrate - @echo "Setup complete! Database is ready." +# === Development Mode === -# Aliases for common commands -up: db-up -down: db-down +# Start full-stack development with hot-reload +dev: + docker compose -f docker-compose.yml -f docker-compose.dev.yml up -# Testing commands -test kind="unit": - @TEST=1 uv run pytest "tests/{{kind}}" -v --tb=short +# Start development in background +dev-detached: + docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d -test-s kind="unit": - @TEST=1 uv run pytest -s -o log_cli=True -o log_cli_level=DEBUG "tests/{{kind}}" +# Stop development environment +dev-down: + docker compose -f docker-compose.yml -f docker-compose.dev.yml down -test-unit: - @TEST=1 uv run pytest tests/unit +# === Individual Service Development === -[working-directory: 'deployment/local'] -test-e2e: - docker compose --profile test-e2e up --build --abort-on-container-exit test-e2e +# Run server independently (requires database) +server-dev: + cd server && just dev -[working-directory: 'deployment/local'] -test-integration: - docker compose --profile test up --build --abort-on-container-exit test +# Run web frontend independently +web-dev: + cd web && pnpm dev -# Code quality commands -fix thing="osa": - uv run ruff format {{thing}} - uv run ruff check --fix {{thing}} +# Build web frontend for production +web-build: + cd web && pnpm build -lint thing="osa": - uv run ruff check {{thing}} - uv run ty check {{thing}} +# Lint web frontend code +web-lint: + cd web && pnpm lint -# Docker commands (standalone) -docker-build: - docker build -t osa-api:latest . +# === Database === -docker-run PORT="8000": - docker run -p {{PORT}}:8000 --env-file .env osa-api:latest - -docker-serve PORT="8000": - just docker-build && docker run -p {{PORT}}:8000 --env-file .env osa-api:latest - -docker-shell docker-build: - docker run -it --rm osa-api:latest bash +# Start only the database +db-up: + docker compose up -d db -docker-stop: - docker stop osa-api && docker rm osa-api || true +# Stop the database +db-down: + docker compose stop db -# Run database migrations locally -db-migrate: - uv run alembic upgrade head +# View database logs +db-logs: + docker compose logs -f db -# Create new migration -db-migration name: - uv run alembic revision -m "{{name}}" +# Connect to PostgreSQL +db-connect: + docker compose exec db psql -U postgres -d osa -# Show migration history -db-history: - uv run alembic history +# === Maintenance === -# Show current migration version -db-current: - uv run alembic current +# Clean up Docker resources (volumes, images, etc.) +clean: + docker compose down -v --rmi local -# Downgrade migration -db-downgrade: - uv run alembic downgrade -1 +# Show service status +status: + docker compose ps diff --git a/README.md b/README.md index e71890c..8443906 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@

Quick Start • - Templates • - Usage • - Development + Development • + Structure • + Troubleshooting

--- @@ -21,107 +21,164 @@ OSA makes it easy to stand up [PDB](https://www.rcsb.org/)-level data infrastruc ## Quick Start -**Requirements:** Python 3.13+, [uv](https://docs.astral.sh/uv/) +### Self-Hosted Deployment + +Deploy the complete OSA stack with a single command: + +**Requirements:** Docker Desktop 4.x+ or Docker Engine 24.x+ ```bash -# Clone and install -git clone https://github.com/opendatabank/osa.git -cd osa -uv sync -source .venv/bin/activate +git clone https://github.com/opensciencearchive/server.git +cd server +docker compose up +``` -# Initialize with the GEO template -osa init geo +Access the web interface at `http://localhost:8080` -# NOTE: update the config.yaml with your NCBI API key and increase the record ingestion limit +### Environment Configuration -# Start the server -osa server start +Copy and customize the environment template: -# Search datasets using natural language -osa search vector "single cell RNA-seq alzheimer's disease" +```bash +cp .env.example .env ``` -## Templates +Key variables: -OSA ships with pre-configured templates for different domains: +| Variable | Default | Description | +|----------|---------|-------------| +| `POSTGRES_PASSWORD` | `osa` | Database password | +| `WEB_PORT` | `8080` | External port for web interface | +| `LOG_LEVEL` | `INFO` | Application log level | -| Template | Description | -|----------|-------------| -| **geo** | [NCBI GEO](https://www.ncbi.nlm.nih.gov/geo/) integration with vector search. Natural language search over gene expression datasets. | -| **minimal** | Blank configuration for building your own archive. | +## Development + +### Full-Stack Development + +Start all services with hot-reload enabled: ```bash -# See available templates -osa init +just dev +``` -# Initialize with a specific template -osa init geo -osa init minimal +Or using docker compose directly: + +```bash +docker compose -f docker-compose.yml -f docker-compose.dev.yml up ``` -More templates coming soon. Contributions welcome. +**What's running:** +- Web UI: http://localhost:3000 (hot-reload) +- API Server: http://localhost:8000 (auto-restart on changes) +- PostgreSQL: localhost:5432 + +### Individual Service Development + +**Frontend only:** -## Usage +```bash +just web-dev +# Or: cd web && pnpm dev +``` -### CLI Commands +**Backend only:** ```bash -# Search for datasets -osa search vector "breast cancer tumor microenvironment" +just server-dev +# Or: cd server && just dev +``` + +### Available Commands -# View details of a result (by number from search) -osa show 1 +| Command | Description | +|---------|-------------| +| `just up` | Start production deployment | +| `just down` | Stop all services | +| `just logs` | View service logs | +| `just dev` | Full-stack development with hot-reload | +| `just web-dev` | Frontend development server | +| `just web-build` | Production build of frontend | +| `just web-lint` | Lint frontend code | +| `just server-dev` | Backend development server | +| `just status` | Show service status | -# Check system stats -osa stats +## Project Structure -# Server management -osa server status -osa server logs --follow -osa server stop ``` +osa/ +├── server/ # Python backend (FastAPI) +│ ├── osa/ # Application code +│ ├── tests/ # Test suite +│ ├── migrations/ # Database migrations +│ ├── sources/ # Data source plugins +│ ├── Dockerfile +│ ├── pyproject.toml +│ └── Justfile # Server-specific commands +├── web/ # Next.js frontend +│ ├── src/ # Application code +│ ├── public/ # Static assets +│ ├── Dockerfile +│ └── package.json +├── docker-compose.yml # Production orchestration +├── docker-compose.dev.yml # Development overrides +├── Justfile # Root orchestration commands +└── .env.example # Environment template +``` + +## Troubleshooting -### Configuration +### Port conflicts -Configuration lives in `~/.config/osa/config.yaml`. Data is stored in `~/.local/share/osa/`. +If port 8080 is already in use: -#### GEO Template Setup +```bash +# Option 1: Change the port in .env +echo "WEB_PORT=3001" >> .env +docker compose up -After running `osa init geo`, edit your config file to: +# Option 2: Stop the conflicting service +lsof -i :8080 +``` -1. **Add your NCBI API key** (recommended for faster ingestion): - - Get a free API key at https://account.ncbi.nlm.nih.gov/settings/ - - Without an API key, NCBI limits you to 3 requests/second - - With an API key, you get 10 requests/second +### Database connection issues -2. **Increase the initial ingestion limit** for a more complete dataset: +Ensure the database container is healthy before starting other services: -```yaml -ingestors: - - ingestor: geo-entrez - config: - email: your@email.com - api_key: your_ncbi_api_key_here # Optional but recommended - initial_run: - enabled: true - limit: 10000 # Increase from default 50 for fuller dataset +```bash +docker compose ps ``` -The GEO template uses the full GSE dataset (~250,000 series). Initial ingestion of 10,000 records takes roughly 20-30 minutes with an API key. +The `db` service should show `healthy` status. If not: -## Development +```bash +# Check database logs +docker compose logs db + +# Restart just the database +docker compose restart db +``` + +### Container build failures + +If builds fail, try cleaning and rebuilding: ```bash -# Install dev dependencies -uv sync --group dev +# Clean up Docker resources +just clean -# Run tests -uv run pytest +# Rebuild from scratch +docker compose build --no-cache +docker compose up +``` -# Type checking & linting -uv run pyright -uv run ruff check +### Hot-reload not working + +For WSL2 users, hot-reload should work automatically (WATCHFILES_FORCE_POLLING is enabled). If it doesn't: + +```bash +# Restart the dev environment +docker compose -f docker-compose.yml -f docker-compose.dev.yml down +docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build ``` ## License diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..aebdfb6 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,39 @@ +# Development overrides for docker-compose.yml +# Usage: docker compose -f docker-compose.yml -f docker-compose.dev.yml up + +services: + server: + build: + context: ./server + dockerfile: Dockerfile + target: builder + volumes: + - ./server:/app + - /app/.venv + environment: + OSA_DATABASE__URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-osa}@db:5432/${POSTGRES_DB:-osa} + OSA_DATA_DIR: /data + OSA_LOGGING__LEVEL: ${LOG_LEVEL:-DEBUG} + WATCHFILES_FORCE_POLLING: "true" + command: uvicorn osa.application.api.rest.app:app --host 0.0.0.0 --port 8000 --reload + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8000/api/v1/health"] + interval: 10s + timeout: 5s + start_period: 30s + retries: 3 + + web: + build: + context: ./web + dockerfile: Dockerfile + target: deps + volumes: + - ./web:/app + - /app/node_modules + - /app/.next + environment: + API_URL: http://server:8000 + ports: + - "3000:3000" + command: pnpm dev diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..98aebe3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,55 @@ +services: + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-osa} + POSTGRES_DB: ${POSTGRES_DB:-osa} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] + interval: 3s + timeout: 10s + retries: 5 + restart: unless-stopped + + server: + build: + context: ./server + dockerfile: Dockerfile + environment: + OSA_DATABASE__URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-osa}@db:5432/${POSTGRES_DB:-osa} + OSA_DATA_DIR: /data + OSA_LOGGING__LEVEL: ${LOG_LEVEL:-INFO} + depends_on: + db: + condition: service_healthy + volumes: + - server_data:/data + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8000/api/v1/health"] + interval: 30s + timeout: 10s + start_period: 10s + retries: 3 + restart: unless-stopped + + web: + build: + context: ./web + dockerfile: Dockerfile + args: + API_URL: http://server:8000 + environment: + API_URL: http://server:8000 + ports: + - "${WEB_PORT:-8080}:3000" + depends_on: + server: + condition: service_healthy + restart: unless-stopped + +volumes: + postgres_data: + server_data: diff --git a/.python-version b/server/.python-version similarity index 100% rename from .python-version rename to server/.python-version diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..cca71b5 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,69 @@ +# syntax=docker/dockerfile:1 + +# Stage 1: Builder +FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder + +WORKDIR /app + +# Enable bytecode compilation for faster startup +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install dependencies first (better caching) +COPY pyproject.toml uv.lock ./ +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-install-project --no-dev + +# Copy application code +COPY osa/ ./osa/ +COPY sources/ ./sources/ +COPY migrations/ ./migrations/ +COPY alembic.ini ./ +COPY entrypoint.sh ./ +COPY README.md ./ + +# Install the project +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Stage 2: Runtime +FROM python:3.13-slim-bookworm AS runtime + +# Install curl for health checks +RUN apt-get update && apt-get install -y --no-install-recommends curl && \ + rm -rf /var/lib/apt/lists/* + +# Create non-root user +RUN useradd --create-home --shell /bin/bash appuser + +WORKDIR /app + +# Copy the virtual environment from builder +COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv +COPY --from=builder --chown=appuser:appuser /app/osa /app/osa +COPY --from=builder --chown=appuser:appuser /app/sources /app/sources +COPY --from=builder --chown=appuser:appuser /app/migrations /app/migrations +COPY --from=builder --chown=appuser:appuser /app/alembic.ini /app/alembic.ini + +# Ensure the virtualenv is used +ENV PATH="/app/.venv/bin:$PATH" + +# Create data directory +RUN mkdir -p /data && chown appuser:appuser /data +ENV OSA_DATA_DIR=/data + +COPY --from=builder --chown=appuser:appuser /app/entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + +USER appuser + +EXPOSE 8000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl --fail http://localhost:8000/api/v1/health || exit 1 + +ENTRYPOINT ["/app/entrypoint.sh"] +CMD ["uvicorn", "osa.application.api.rest.app:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/server/Justfile b/server/Justfile new file mode 100644 index 0000000..afeadd5 --- /dev/null +++ b/server/Justfile @@ -0,0 +1,87 @@ +# Server Justfile +# Development commands for the Python backend + +default: + @just --list + +# === Development === + +# Run development server with hot-reload +dev: + uv run uvicorn osa.application.api.rest.app:app --reload --host 0.0.0.0 --port 8000 + +# Run with debug logging +dev-debug: + LOG_LEVEL=DEBUG uv run uvicorn osa.application.api.rest.app:app --reload --host 0.0.0.0 --port 8000 + +# === Testing === + +# Run all tests +test: + @TEST=1 uv run pytest tests -v --tb=short + +# Run unit tests +test-unit: + @TEST=1 uv run pytest tests/unit -v --tb=short + +# Run tests with verbose logging +test-s kind="unit": + @TEST=1 uv run pytest -s -o log_cli=True -o log_cli_level=DEBUG "tests/{{kind}}" + +# Run tests with coverage +test-cov: + @TEST=1 uv run pytest tests/unit --cov=osa --cov-report=term-missing + +# === Code Quality === + +# Run linter and type checker +lint: + uv run ruff check osa + uv run ty check osa + +# Fix formatting and lint issues +fix: + uv run ruff format osa + uv run ruff check --fix osa + +# Format code +format: + uv run ruff format osa + +# === Database === + +# Run migrations +migrate: + uv run alembic upgrade head + +# Create new migration +migration name: + uv run alembic revision -m "{{name}}" + +# Show current migration version +migrate-status: + uv run alembic current + +# Show migration history +migrate-history: + uv run alembic history + +# Rollback one migration +migrate-down: + uv run alembic downgrade -1 + +# === CLI === + +# Run any osa CLI command +cli *ARGS: + uv run osa {{ARGS}} + +# === Dependencies === + +# Install/sync dependencies +install: + uv sync + +# Update dependencies +update: + uv sync --upgrade diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..a670bb0 --- /dev/null +++ b/server/README.md @@ -0,0 +1,33 @@ +# OSA Server + +Python backend for Open Science Archive, built with FastAPI. + +## Development + +```bash +# Install dependencies +uv sync + +# Run development server +just dev + +# Run tests +just test + +# Lint and type check +just lint +``` + +## Structure + +``` +server/ +├── osa/ # Application code +├── tests/ # Test suite +├── migrations/ # Database migrations (Alembic) +├── sources/ # Data source plugins +├── Dockerfile # Container build +└── Justfile # Development commands +``` + +See the [root README](../README.md) for full documentation. diff --git a/alembic.ini b/server/alembic.ini similarity index 100% rename from alembic.ini rename to server/alembic.ini diff --git a/server/entrypoint.sh b/server/entrypoint.sh new file mode 100644 index 0000000..555cf8f --- /dev/null +++ b/server/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e + +# Run database migrations +echo "Running database migrations..." +alembic upgrade head + +# Start the application +echo "Starting application..." +exec "$@" diff --git a/migrations/README b/server/migrations/README similarity index 100% rename from migrations/README rename to server/migrations/README diff --git a/migrations/env.py b/server/migrations/env.py similarity index 75% rename from migrations/env.py rename to server/migrations/env.py index 9b9fc57..61a5b48 100644 --- a/migrations/env.py +++ b/server/migrations/env.py @@ -1,3 +1,4 @@ +import os from logging.config import fileConfig from sqlalchemy import engine_from_config, pool @@ -8,6 +9,19 @@ # access to the values within the .ini file in use. config = context.config +# Override sqlalchemy.url from environment variable if set +# Uses OSA_DATABASE__URL (same as the app) for consistency +# Convert async driver (asyncpg) to sync driver (psycopg2) for alembic +database_url = os.environ.get("OSA_DATABASE__URL") +print(f"[alembic env.py] OSA_DATABASE__URL = {database_url}") +if database_url: + # Alembic runs synchronously, so convert asyncpg to psycopg2 + sync_url = database_url.replace("postgresql+asyncpg://", "postgresql+psycopg2://") + print(f"[alembic env.py] Using sync URL: {sync_url}") + config.set_main_option("sqlalchemy.url", sync_url) +else: + print("[alembic env.py] Falling back to alembic.ini URL") + # Interpret the config file for Python logging. # This line sets up loggers basically. if config.config_file_name is not None: diff --git a/migrations/script.py.mako b/server/migrations/script.py.mako similarity index 100% rename from migrations/script.py.mako rename to server/migrations/script.py.mako diff --git a/migrations/versions/0d9fbacf8e58_initial_tables.py b/server/migrations/versions/0d9fbacf8e58_initial_tables.py similarity index 100% rename from migrations/versions/0d9fbacf8e58_initial_tables.py rename to server/migrations/versions/0d9fbacf8e58_initial_tables.py diff --git a/osa/__init__.py b/server/osa/__init__.py similarity index 100% rename from osa/__init__.py rename to server/osa/__init__.py diff --git a/osa/application/__init__.py b/server/osa/application/__init__.py similarity index 100% rename from osa/application/__init__.py rename to server/osa/application/__init__.py diff --git a/osa/application/api/__init__.py b/server/osa/application/api/__init__.py similarity index 100% rename from osa/application/api/__init__.py rename to server/osa/application/api/__init__.py diff --git a/osa/application/api/rest/__init__.py b/server/osa/application/api/rest/__init__.py similarity index 100% rename from osa/application/api/rest/__init__.py rename to server/osa/application/api/rest/__init__.py diff --git a/osa/application/api/rest/app.py b/server/osa/application/api/rest/app.py similarity index 100% rename from osa/application/api/rest/app.py rename to server/osa/application/api/rest/app.py diff --git a/osa/application/api/v1/__init__.py b/server/osa/application/api/v1/__init__.py similarity index 100% rename from osa/application/api/v1/__init__.py rename to server/osa/application/api/v1/__init__.py diff --git a/osa/application/api/v1/errors.py b/server/osa/application/api/v1/errors.py similarity index 100% rename from osa/application/api/v1/errors.py rename to server/osa/application/api/v1/errors.py diff --git a/osa/application/api/v1/routes/__init__.py b/server/osa/application/api/v1/routes/__init__.py similarity index 100% rename from osa/application/api/v1/routes/__init__.py rename to server/osa/application/api/v1/routes/__init__.py diff --git a/osa/application/api/v1/routes/events.py b/server/osa/application/api/v1/routes/events.py similarity index 100% rename from osa/application/api/v1/routes/events.py rename to server/osa/application/api/v1/routes/events.py diff --git a/osa/application/api/v1/routes/health.py b/server/osa/application/api/v1/routes/health.py similarity index 100% rename from osa/application/api/v1/routes/health.py rename to server/osa/application/api/v1/routes/health.py diff --git a/osa/application/api/v1/routes/search.py b/server/osa/application/api/v1/routes/search.py similarity index 100% rename from osa/application/api/v1/routes/search.py rename to server/osa/application/api/v1/routes/search.py diff --git a/osa/application/api/v1/routes/stats.py b/server/osa/application/api/v1/routes/stats.py similarity index 100% rename from osa/application/api/v1/routes/stats.py rename to server/osa/application/api/v1/routes/stats.py diff --git a/osa/application/api/v1/routes/validation.py b/server/osa/application/api/v1/routes/validation.py similarity index 100% rename from osa/application/api/v1/routes/validation.py rename to server/osa/application/api/v1/routes/validation.py diff --git a/osa/application/di.py b/server/osa/application/di.py similarity index 100% rename from osa/application/di.py rename to server/osa/application/di.py diff --git a/osa/application/event/__init__.py b/server/osa/application/event/__init__.py similarity index 100% rename from osa/application/event/__init__.py rename to server/osa/application/event/__init__.py diff --git a/osa/application/event/server_started.py b/server/osa/application/event/server_started.py similarity index 100% rename from osa/application/event/server_started.py rename to server/osa/application/event/server_started.py diff --git a/osa/cli/__init__.py b/server/osa/cli/__init__.py similarity index 100% rename from osa/cli/__init__.py rename to server/osa/cli/__init__.py diff --git a/osa/cli/commands/__init__.py b/server/osa/cli/commands/__init__.py similarity index 100% rename from osa/cli/commands/__init__.py rename to server/osa/cli/commands/__init__.py diff --git a/osa/cli/commands/admin.py b/server/osa/cli/commands/admin.py similarity index 100% rename from osa/cli/commands/admin.py rename to server/osa/cli/commands/admin.py diff --git a/osa/cli/commands/events.py b/server/osa/cli/commands/events.py similarity index 100% rename from osa/cli/commands/events.py rename to server/osa/cli/commands/events.py diff --git a/osa/cli/commands/local.py b/server/osa/cli/commands/local.py similarity index 100% rename from osa/cli/commands/local.py rename to server/osa/cli/commands/local.py diff --git a/osa/cli/commands/search.py b/server/osa/cli/commands/search.py similarity index 100% rename from osa/cli/commands/search.py rename to server/osa/cli/commands/search.py diff --git a/osa/cli/commands/show.py b/server/osa/cli/commands/show.py similarity index 100% rename from osa/cli/commands/show.py rename to server/osa/cli/commands/show.py diff --git a/osa/cli/commands/stats.py b/server/osa/cli/commands/stats.py similarity index 100% rename from osa/cli/commands/stats.py rename to server/osa/cli/commands/stats.py diff --git a/osa/cli/console.py b/server/osa/cli/console.py similarity index 100% rename from osa/cli/console.py rename to server/osa/cli/console.py diff --git a/osa/cli/main.py b/server/osa/cli/main.py similarity index 100% rename from osa/cli/main.py rename to server/osa/cli/main.py diff --git a/osa/cli/models.py b/server/osa/cli/models.py similarity index 100% rename from osa/cli/models.py rename to server/osa/cli/models.py diff --git a/osa/cli/util/__init__.py b/server/osa/cli/util/__init__.py similarity index 100% rename from osa/cli/util/__init__.py rename to server/osa/cli/util/__init__.py diff --git a/osa/cli/util/daemon.py b/server/osa/cli/util/daemon.py similarity index 100% rename from osa/cli/util/daemon.py rename to server/osa/cli/util/daemon.py diff --git a/osa/cli/util/paths.py b/server/osa/cli/util/paths.py similarity index 100% rename from osa/cli/util/paths.py rename to server/osa/cli/util/paths.py diff --git a/osa/cli/util/search_cache.py b/server/osa/cli/util/search_cache.py similarity index 100% rename from osa/cli/util/search_cache.py rename to server/osa/cli/util/search_cache.py diff --git a/osa/cli/util/server_state.py b/server/osa/cli/util/server_state.py similarity index 100% rename from osa/cli/util/server_state.py rename to server/osa/cli/util/server_state.py diff --git a/osa/config.py b/server/osa/config.py similarity index 100% rename from osa/config.py rename to server/osa/config.py diff --git a/osa/domain/__init__.py b/server/osa/domain/__init__.py similarity index 100% rename from osa/domain/__init__.py rename to server/osa/domain/__init__.py diff --git a/osa/domain/auth/__init__.py b/server/osa/domain/auth/__init__.py similarity index 100% rename from osa/domain/auth/__init__.py rename to server/osa/domain/auth/__init__.py diff --git a/osa/domain/auth/adapter/__init__.py b/server/osa/domain/auth/adapter/__init__.py similarity index 100% rename from osa/domain/auth/adapter/__init__.py rename to server/osa/domain/auth/adapter/__init__.py diff --git a/osa/domain/auth/command/__init__.py b/server/osa/domain/auth/command/__init__.py similarity index 100% rename from osa/domain/auth/command/__init__.py rename to server/osa/domain/auth/command/__init__.py diff --git a/osa/domain/auth/event/__init__.py b/server/osa/domain/auth/event/__init__.py similarity index 100% rename from osa/domain/auth/event/__init__.py rename to server/osa/domain/auth/event/__init__.py diff --git a/osa/domain/auth/model/__init__.py b/server/osa/domain/auth/model/__init__.py similarity index 100% rename from osa/domain/auth/model/__init__.py rename to server/osa/domain/auth/model/__init__.py diff --git a/osa/domain/auth/port/__init__.py b/server/osa/domain/auth/port/__init__.py similarity index 100% rename from osa/domain/auth/port/__init__.py rename to server/osa/domain/auth/port/__init__.py diff --git a/osa/domain/auth/query/__init__.py b/server/osa/domain/auth/query/__init__.py similarity index 100% rename from osa/domain/auth/query/__init__.py rename to server/osa/domain/auth/query/__init__.py diff --git a/osa/domain/auth/service/__init__.py b/server/osa/domain/auth/service/__init__.py similarity index 100% rename from osa/domain/auth/service/__init__.py rename to server/osa/domain/auth/service/__init__.py diff --git a/osa/domain/curation/__init__.py b/server/osa/domain/curation/__init__.py similarity index 100% rename from osa/domain/curation/__init__.py rename to server/osa/domain/curation/__init__.py diff --git a/osa/domain/curation/adapter/__init__.py b/server/osa/domain/curation/adapter/__init__.py similarity index 100% rename from osa/domain/curation/adapter/__init__.py rename to server/osa/domain/curation/adapter/__init__.py diff --git a/osa/domain/curation/command/__init__.py b/server/osa/domain/curation/command/__init__.py similarity index 100% rename from osa/domain/curation/command/__init__.py rename to server/osa/domain/curation/command/__init__.py diff --git a/osa/domain/curation/event/__init__.py b/server/osa/domain/curation/event/__init__.py similarity index 100% rename from osa/domain/curation/event/__init__.py rename to server/osa/domain/curation/event/__init__.py diff --git a/osa/domain/curation/event/deposition_approved.py b/server/osa/domain/curation/event/deposition_approved.py similarity index 100% rename from osa/domain/curation/event/deposition_approved.py rename to server/osa/domain/curation/event/deposition_approved.py diff --git a/osa/domain/curation/listener/__init__.py b/server/osa/domain/curation/listener/__init__.py similarity index 100% rename from osa/domain/curation/listener/__init__.py rename to server/osa/domain/curation/listener/__init__.py diff --git a/osa/domain/curation/listener/auto_approve_curation_tool.py b/server/osa/domain/curation/listener/auto_approve_curation_tool.py similarity index 100% rename from osa/domain/curation/listener/auto_approve_curation_tool.py rename to server/osa/domain/curation/listener/auto_approve_curation_tool.py diff --git a/osa/domain/curation/model/__init__.py b/server/osa/domain/curation/model/__init__.py similarity index 100% rename from osa/domain/curation/model/__init__.py rename to server/osa/domain/curation/model/__init__.py diff --git a/osa/domain/curation/port/__init__.py b/server/osa/domain/curation/port/__init__.py similarity index 100% rename from osa/domain/curation/port/__init__.py rename to server/osa/domain/curation/port/__init__.py diff --git a/osa/domain/curation/query/__init__.py b/server/osa/domain/curation/query/__init__.py similarity index 100% rename from osa/domain/curation/query/__init__.py rename to server/osa/domain/curation/query/__init__.py diff --git a/osa/domain/curation/service/__init__.py b/server/osa/domain/curation/service/__init__.py similarity index 100% rename from osa/domain/curation/service/__init__.py rename to server/osa/domain/curation/service/__init__.py diff --git a/osa/domain/deposition/__init__.py b/server/osa/domain/deposition/__init__.py similarity index 100% rename from osa/domain/deposition/__init__.py rename to server/osa/domain/deposition/__init__.py diff --git a/osa/domain/deposition/adapter/__init__.py b/server/osa/domain/deposition/adapter/__init__.py similarity index 100% rename from osa/domain/deposition/adapter/__init__.py rename to server/osa/domain/deposition/adapter/__init__.py diff --git a/osa/domain/deposition/command/__init__.py b/server/osa/domain/deposition/command/__init__.py similarity index 100% rename from osa/domain/deposition/command/__init__.py rename to server/osa/domain/deposition/command/__init__.py diff --git a/osa/domain/deposition/command/create.py b/server/osa/domain/deposition/command/create.py similarity index 100% rename from osa/domain/deposition/command/create.py rename to server/osa/domain/deposition/command/create.py diff --git a/osa/domain/deposition/command/delete_files.py b/server/osa/domain/deposition/command/delete_files.py similarity index 100% rename from osa/domain/deposition/command/delete_files.py rename to server/osa/domain/deposition/command/delete_files.py diff --git a/osa/domain/deposition/command/submit.py b/server/osa/domain/deposition/command/submit.py similarity index 100% rename from osa/domain/deposition/command/submit.py rename to server/osa/domain/deposition/command/submit.py diff --git a/osa/domain/deposition/command/update.py b/server/osa/domain/deposition/command/update.py similarity index 100% rename from osa/domain/deposition/command/update.py rename to server/osa/domain/deposition/command/update.py diff --git a/osa/domain/deposition/command/upload.py b/server/osa/domain/deposition/command/upload.py similarity index 100% rename from osa/domain/deposition/command/upload.py rename to server/osa/domain/deposition/command/upload.py diff --git a/osa/domain/deposition/event/__init__.py b/server/osa/domain/deposition/event/__init__.py similarity index 100% rename from osa/domain/deposition/event/__init__.py rename to server/osa/domain/deposition/event/__init__.py diff --git a/osa/domain/deposition/event/submitted.py b/server/osa/domain/deposition/event/submitted.py similarity index 100% rename from osa/domain/deposition/event/submitted.py rename to server/osa/domain/deposition/event/submitted.py diff --git a/osa/domain/deposition/model/__init__.py b/server/osa/domain/deposition/model/__init__.py similarity index 100% rename from osa/domain/deposition/model/__init__.py rename to server/osa/domain/deposition/model/__init__.py diff --git a/osa/domain/deposition/model/aggregate.py b/server/osa/domain/deposition/model/aggregate.py similarity index 100% rename from osa/domain/deposition/model/aggregate.py rename to server/osa/domain/deposition/model/aggregate.py diff --git a/osa/domain/deposition/model/entity.py b/server/osa/domain/deposition/model/entity.py similarity index 100% rename from osa/domain/deposition/model/entity.py rename to server/osa/domain/deposition/model/entity.py diff --git a/osa/domain/deposition/model/value.py b/server/osa/domain/deposition/model/value.py similarity index 100% rename from osa/domain/deposition/model/value.py rename to server/osa/domain/deposition/model/value.py diff --git a/osa/domain/deposition/port/__init__.py b/server/osa/domain/deposition/port/__init__.py similarity index 100% rename from osa/domain/deposition/port/__init__.py rename to server/osa/domain/deposition/port/__init__.py diff --git a/osa/domain/deposition/port/repository.py b/server/osa/domain/deposition/port/repository.py similarity index 100% rename from osa/domain/deposition/port/repository.py rename to server/osa/domain/deposition/port/repository.py diff --git a/osa/domain/deposition/port/storage.py b/server/osa/domain/deposition/port/storage.py similarity index 100% rename from osa/domain/deposition/port/storage.py rename to server/osa/domain/deposition/port/storage.py diff --git a/osa/domain/deposition/query/__init__.py b/server/osa/domain/deposition/query/__init__.py similarity index 100% rename from osa/domain/deposition/query/__init__.py rename to server/osa/domain/deposition/query/__init__.py diff --git a/osa/domain/deposition/service/__init__.py b/server/osa/domain/deposition/service/__init__.py similarity index 100% rename from osa/domain/deposition/service/__init__.py rename to server/osa/domain/deposition/service/__init__.py diff --git a/osa/domain/deposition/service/deposition.py b/server/osa/domain/deposition/service/deposition.py similarity index 100% rename from osa/domain/deposition/service/deposition.py rename to server/osa/domain/deposition/service/deposition.py diff --git a/osa/domain/deposition/util/di/__init__.py b/server/osa/domain/deposition/util/di/__init__.py similarity index 100% rename from osa/domain/deposition/util/di/__init__.py rename to server/osa/domain/deposition/util/di/__init__.py diff --git a/osa/domain/deposition/util/di/provider.py b/server/osa/domain/deposition/util/di/provider.py similarity index 100% rename from osa/domain/deposition/util/di/provider.py rename to server/osa/domain/deposition/util/di/provider.py diff --git a/osa/domain/export/__init__.py b/server/osa/domain/export/__init__.py similarity index 100% rename from osa/domain/export/__init__.py rename to server/osa/domain/export/__init__.py diff --git a/osa/domain/export/adapter/__init__.py b/server/osa/domain/export/adapter/__init__.py similarity index 100% rename from osa/domain/export/adapter/__init__.py rename to server/osa/domain/export/adapter/__init__.py diff --git a/osa/domain/export/command/__init__.py b/server/osa/domain/export/command/__init__.py similarity index 100% rename from osa/domain/export/command/__init__.py rename to server/osa/domain/export/command/__init__.py diff --git a/osa/domain/export/event/__init__.py b/server/osa/domain/export/event/__init__.py similarity index 100% rename from osa/domain/export/event/__init__.py rename to server/osa/domain/export/event/__init__.py diff --git a/osa/domain/export/model/__init__.py b/server/osa/domain/export/model/__init__.py similarity index 100% rename from osa/domain/export/model/__init__.py rename to server/osa/domain/export/model/__init__.py diff --git a/osa/domain/export/port/__init__.py b/server/osa/domain/export/port/__init__.py similarity index 100% rename from osa/domain/export/port/__init__.py rename to server/osa/domain/export/port/__init__.py diff --git a/osa/domain/export/query/__init__.py b/server/osa/domain/export/query/__init__.py similarity index 100% rename from osa/domain/export/query/__init__.py rename to server/osa/domain/export/query/__init__.py diff --git a/osa/domain/export/service/__init__.py b/server/osa/domain/export/service/__init__.py similarity index 100% rename from osa/domain/export/service/__init__.py rename to server/osa/domain/export/service/__init__.py diff --git a/osa/domain/index/__init__.py b/server/osa/domain/index/__init__.py similarity index 100% rename from osa/domain/index/__init__.py rename to server/osa/domain/index/__init__.py diff --git a/osa/domain/index/listener/__init__.py b/server/osa/domain/index/listener/__init__.py similarity index 100% rename from osa/domain/index/listener/__init__.py rename to server/osa/domain/index/listener/__init__.py diff --git a/osa/domain/index/listener/index_projector.py b/server/osa/domain/index/listener/index_projector.py similarity index 100% rename from osa/domain/index/listener/index_projector.py rename to server/osa/domain/index/listener/index_projector.py diff --git a/osa/domain/index/model/__init__.py b/server/osa/domain/index/model/__init__.py similarity index 100% rename from osa/domain/index/model/__init__.py rename to server/osa/domain/index/model/__init__.py diff --git a/osa/domain/index/model/registry.py b/server/osa/domain/index/model/registry.py similarity index 100% rename from osa/domain/index/model/registry.py rename to server/osa/domain/index/model/registry.py diff --git a/osa/domain/index/service/__init__.py b/server/osa/domain/index/service/__init__.py similarity index 100% rename from osa/domain/index/service/__init__.py rename to server/osa/domain/index/service/__init__.py diff --git a/osa/domain/index/service/index.py b/server/osa/domain/index/service/index.py similarity index 100% rename from osa/domain/index/service/index.py rename to server/osa/domain/index/service/index.py diff --git a/osa/domain/record/__init__.py b/server/osa/domain/record/__init__.py similarity index 100% rename from osa/domain/record/__init__.py rename to server/osa/domain/record/__init__.py diff --git a/osa/domain/record/adapter/__init__.py b/server/osa/domain/record/adapter/__init__.py similarity index 100% rename from osa/domain/record/adapter/__init__.py rename to server/osa/domain/record/adapter/__init__.py diff --git a/osa/domain/record/command/__init__.py b/server/osa/domain/record/command/__init__.py similarity index 100% rename from osa/domain/record/command/__init__.py rename to server/osa/domain/record/command/__init__.py diff --git a/osa/domain/record/event/__init__.py b/server/osa/domain/record/event/__init__.py similarity index 100% rename from osa/domain/record/event/__init__.py rename to server/osa/domain/record/event/__init__.py diff --git a/osa/domain/record/event/record_published.py b/server/osa/domain/record/event/record_published.py similarity index 100% rename from osa/domain/record/event/record_published.py rename to server/osa/domain/record/event/record_published.py diff --git a/osa/domain/record/listener/__init__.py b/server/osa/domain/record/listener/__init__.py similarity index 100% rename from osa/domain/record/listener/__init__.py rename to server/osa/domain/record/listener/__init__.py diff --git a/osa/domain/record/listener/record_creation_listener.py b/server/osa/domain/record/listener/record_creation_listener.py similarity index 100% rename from osa/domain/record/listener/record_creation_listener.py rename to server/osa/domain/record/listener/record_creation_listener.py diff --git a/osa/domain/record/model/__init__.py b/server/osa/domain/record/model/__init__.py similarity index 100% rename from osa/domain/record/model/__init__.py rename to server/osa/domain/record/model/__init__.py diff --git a/osa/domain/record/model/aggregate.py b/server/osa/domain/record/model/aggregate.py similarity index 100% rename from osa/domain/record/model/aggregate.py rename to server/osa/domain/record/model/aggregate.py diff --git a/osa/domain/record/model/value.py b/server/osa/domain/record/model/value.py similarity index 100% rename from osa/domain/record/model/value.py rename to server/osa/domain/record/model/value.py diff --git a/osa/domain/record/port/__init__.py b/server/osa/domain/record/port/__init__.py similarity index 100% rename from osa/domain/record/port/__init__.py rename to server/osa/domain/record/port/__init__.py diff --git a/osa/domain/record/port/repository.py b/server/osa/domain/record/port/repository.py similarity index 100% rename from osa/domain/record/port/repository.py rename to server/osa/domain/record/port/repository.py diff --git a/osa/domain/record/query/__init__.py b/server/osa/domain/record/query/__init__.py similarity index 100% rename from osa/domain/record/query/__init__.py rename to server/osa/domain/record/query/__init__.py diff --git a/osa/domain/record/service/__init__.py b/server/osa/domain/record/service/__init__.py similarity index 100% rename from osa/domain/record/service/__init__.py rename to server/osa/domain/record/service/__init__.py diff --git a/osa/domain/record/service/record.py b/server/osa/domain/record/service/record.py similarity index 100% rename from osa/domain/record/service/record.py rename to server/osa/domain/record/service/record.py diff --git a/osa/domain/schema/__init__.py b/server/osa/domain/schema/__init__.py similarity index 100% rename from osa/domain/schema/__init__.py rename to server/osa/domain/schema/__init__.py diff --git a/osa/domain/schema/adapter/__init__.py b/server/osa/domain/schema/adapter/__init__.py similarity index 100% rename from osa/domain/schema/adapter/__init__.py rename to server/osa/domain/schema/adapter/__init__.py diff --git a/osa/domain/schema/command/__init__.py b/server/osa/domain/schema/command/__init__.py similarity index 100% rename from osa/domain/schema/command/__init__.py rename to server/osa/domain/schema/command/__init__.py diff --git a/osa/domain/schema/event/__init__.py b/server/osa/domain/schema/event/__init__.py similarity index 100% rename from osa/domain/schema/event/__init__.py rename to server/osa/domain/schema/event/__init__.py diff --git a/osa/domain/schema/model/__init__.py b/server/osa/domain/schema/model/__init__.py similarity index 100% rename from osa/domain/schema/model/__init__.py rename to server/osa/domain/schema/model/__init__.py diff --git a/osa/domain/schema/port/__init__.py b/server/osa/domain/schema/port/__init__.py similarity index 100% rename from osa/domain/schema/port/__init__.py rename to server/osa/domain/schema/port/__init__.py diff --git a/osa/domain/schema/query/__init__.py b/server/osa/domain/schema/query/__init__.py similarity index 100% rename from osa/domain/schema/query/__init__.py rename to server/osa/domain/schema/query/__init__.py diff --git a/osa/domain/schema/service/__init__.py b/server/osa/domain/schema/service/__init__.py similarity index 100% rename from osa/domain/schema/service/__init__.py rename to server/osa/domain/schema/service/__init__.py diff --git a/osa/domain/search/__init__.py b/server/osa/domain/search/__init__.py similarity index 100% rename from osa/domain/search/__init__.py rename to server/osa/domain/search/__init__.py diff --git a/osa/domain/search/adapter/__init__.py b/server/osa/domain/search/adapter/__init__.py similarity index 100% rename from osa/domain/search/adapter/__init__.py rename to server/osa/domain/search/adapter/__init__.py diff --git a/osa/domain/search/command/__init__.py b/server/osa/domain/search/command/__init__.py similarity index 100% rename from osa/domain/search/command/__init__.py rename to server/osa/domain/search/command/__init__.py diff --git a/osa/domain/search/event/__init__.py b/server/osa/domain/search/event/__init__.py similarity index 100% rename from osa/domain/search/event/__init__.py rename to server/osa/domain/search/event/__init__.py diff --git a/osa/domain/search/model/__init__.py b/server/osa/domain/search/model/__init__.py similarity index 100% rename from osa/domain/search/model/__init__.py rename to server/osa/domain/search/model/__init__.py diff --git a/osa/domain/search/port/__init__.py b/server/osa/domain/search/port/__init__.py similarity index 100% rename from osa/domain/search/port/__init__.py rename to server/osa/domain/search/port/__init__.py diff --git a/osa/domain/search/query/__init__.py b/server/osa/domain/search/query/__init__.py similarity index 100% rename from osa/domain/search/query/__init__.py rename to server/osa/domain/search/query/__init__.py diff --git a/osa/domain/search/service/__init__.py b/server/osa/domain/search/service/__init__.py similarity index 100% rename from osa/domain/search/service/__init__.py rename to server/osa/domain/search/service/__init__.py diff --git a/osa/domain/shared/__init__.py b/server/osa/domain/shared/__init__.py similarity index 100% rename from osa/domain/shared/__init__.py rename to server/osa/domain/shared/__init__.py diff --git a/osa/domain/shared/adapter.py b/server/osa/domain/shared/adapter.py similarity index 100% rename from osa/domain/shared/adapter.py rename to server/osa/domain/shared/adapter.py diff --git a/osa/domain/shared/command.py b/server/osa/domain/shared/command.py similarity index 100% rename from osa/domain/shared/command.py rename to server/osa/domain/shared/command.py diff --git a/osa/domain/shared/dto.py b/server/osa/domain/shared/dto.py similarity index 100% rename from osa/domain/shared/dto.py rename to server/osa/domain/shared/dto.py diff --git a/osa/domain/shared/error.py b/server/osa/domain/shared/error.py similarity index 100% rename from osa/domain/shared/error.py rename to server/osa/domain/shared/error.py diff --git a/osa/domain/shared/event.py b/server/osa/domain/shared/event.py similarity index 100% rename from osa/domain/shared/event.py rename to server/osa/domain/shared/event.py diff --git a/osa/domain/shared/event_log.py b/server/osa/domain/shared/event_log.py similarity index 100% rename from osa/domain/shared/event_log.py rename to server/osa/domain/shared/event_log.py diff --git a/osa/domain/shared/model/__init__.py b/server/osa/domain/shared/model/__init__.py similarity index 100% rename from osa/domain/shared/model/__init__.py rename to server/osa/domain/shared/model/__init__.py diff --git a/osa/domain/shared/model/aggregate.py b/server/osa/domain/shared/model/aggregate.py similarity index 100% rename from osa/domain/shared/model/aggregate.py rename to server/osa/domain/shared/model/aggregate.py diff --git a/osa/domain/shared/model/entity.py b/server/osa/domain/shared/model/entity.py similarity index 100% rename from osa/domain/shared/model/entity.py rename to server/osa/domain/shared/model/entity.py diff --git a/osa/domain/shared/model/srn.py b/server/osa/domain/shared/model/srn.py similarity index 100% rename from osa/domain/shared/model/srn.py rename to server/osa/domain/shared/model/srn.py diff --git a/osa/domain/shared/model/value.py b/server/osa/domain/shared/model/value.py similarity index 100% rename from osa/domain/shared/model/value.py rename to server/osa/domain/shared/model/value.py diff --git a/osa/domain/shared/outbox.py b/server/osa/domain/shared/outbox.py similarity index 100% rename from osa/domain/shared/outbox.py rename to server/osa/domain/shared/outbox.py diff --git a/osa/domain/shared/port/__init__.py b/server/osa/domain/shared/port/__init__.py similarity index 100% rename from osa/domain/shared/port/__init__.py rename to server/osa/domain/shared/port/__init__.py diff --git a/osa/domain/shared/port/base.py b/server/osa/domain/shared/port/base.py similarity index 100% rename from osa/domain/shared/port/base.py rename to server/osa/domain/shared/port/base.py diff --git a/osa/domain/shared/port/event_repository.py b/server/osa/domain/shared/port/event_repository.py similarity index 100% rename from osa/domain/shared/port/event_repository.py rename to server/osa/domain/shared/port/event_repository.py diff --git a/osa/domain/shared/query.py b/server/osa/domain/shared/query.py similarity index 100% rename from osa/domain/shared/query.py rename to server/osa/domain/shared/query.py diff --git a/osa/domain/shared/service.py b/server/osa/domain/shared/service.py similarity index 100% rename from osa/domain/shared/service.py rename to server/osa/domain/shared/service.py diff --git a/osa/domain/source/__init__.py b/server/osa/domain/source/__init__.py similarity index 100% rename from osa/domain/source/__init__.py rename to server/osa/domain/source/__init__.py diff --git a/osa/domain/source/event/__init__.py b/server/osa/domain/source/event/__init__.py similarity index 100% rename from osa/domain/source/event/__init__.py rename to server/osa/domain/source/event/__init__.py diff --git a/osa/domain/source/event/source_requested.py b/server/osa/domain/source/event/source_requested.py similarity index 100% rename from osa/domain/source/event/source_requested.py rename to server/osa/domain/source/event/source_requested.py diff --git a/osa/domain/source/event/source_run_completed.py b/server/osa/domain/source/event/source_run_completed.py similarity index 100% rename from osa/domain/source/event/source_run_completed.py rename to server/osa/domain/source/event/source_run_completed.py diff --git a/osa/domain/source/listener/__init__.py b/server/osa/domain/source/listener/__init__.py similarity index 100% rename from osa/domain/source/listener/__init__.py rename to server/osa/domain/source/listener/__init__.py diff --git a/osa/domain/source/listener/initial_source_listener.py b/server/osa/domain/source/listener/initial_source_listener.py similarity index 100% rename from osa/domain/source/listener/initial_source_listener.py rename to server/osa/domain/source/listener/initial_source_listener.py diff --git a/osa/domain/source/listener/source_listener.py b/server/osa/domain/source/listener/source_listener.py similarity index 100% rename from osa/domain/source/listener/source_listener.py rename to server/osa/domain/source/listener/source_listener.py diff --git a/osa/domain/source/model/__init__.py b/server/osa/domain/source/model/__init__.py similarity index 100% rename from osa/domain/source/model/__init__.py rename to server/osa/domain/source/model/__init__.py diff --git a/osa/domain/source/model/registry.py b/server/osa/domain/source/model/registry.py similarity index 100% rename from osa/domain/source/model/registry.py rename to server/osa/domain/source/model/registry.py diff --git a/osa/domain/source/schedule/__init__.py b/server/osa/domain/source/schedule/__init__.py similarity index 100% rename from osa/domain/source/schedule/__init__.py rename to server/osa/domain/source/schedule/__init__.py diff --git a/osa/domain/source/schedule/source_schedule.py b/server/osa/domain/source/schedule/source_schedule.py similarity index 100% rename from osa/domain/source/schedule/source_schedule.py rename to server/osa/domain/source/schedule/source_schedule.py diff --git a/osa/domain/source/service/__init__.py b/server/osa/domain/source/service/__init__.py similarity index 100% rename from osa/domain/source/service/__init__.py rename to server/osa/domain/source/service/__init__.py diff --git a/osa/domain/source/service/source.py b/server/osa/domain/source/service/source.py similarity index 100% rename from osa/domain/source/service/source.py rename to server/osa/domain/source/service/source.py diff --git a/osa/domain/validation/__init__.py b/server/osa/domain/validation/__init__.py similarity index 100% rename from osa/domain/validation/__init__.py rename to server/osa/domain/validation/__init__.py diff --git a/osa/domain/validation/adapter/__init__.py b/server/osa/domain/validation/adapter/__init__.py similarity index 100% rename from osa/domain/validation/adapter/__init__.py rename to server/osa/domain/validation/adapter/__init__.py diff --git a/osa/domain/validation/command/__init__.py b/server/osa/domain/validation/command/__init__.py similarity index 100% rename from osa/domain/validation/command/__init__.py rename to server/osa/domain/validation/command/__init__.py diff --git a/osa/domain/validation/event/__init__.py b/server/osa/domain/validation/event/__init__.py similarity index 100% rename from osa/domain/validation/event/__init__.py rename to server/osa/domain/validation/event/__init__.py diff --git a/osa/domain/validation/event/validation_completed.py b/server/osa/domain/validation/event/validation_completed.py similarity index 100% rename from osa/domain/validation/event/validation_completed.py rename to server/osa/domain/validation/event/validation_completed.py diff --git a/osa/domain/validation/event/validation_started.py b/server/osa/domain/validation/event/validation_started.py similarity index 100% rename from osa/domain/validation/event/validation_started.py rename to server/osa/domain/validation/event/validation_started.py diff --git a/osa/domain/validation/handler.py b/server/osa/domain/validation/handler.py similarity index 100% rename from osa/domain/validation/handler.py rename to server/osa/domain/validation/handler.py diff --git a/osa/domain/validation/listener/__init__.py b/server/osa/domain/validation/listener/__init__.py similarity index 100% rename from osa/domain/validation/listener/__init__.py rename to server/osa/domain/validation/listener/__init__.py diff --git a/osa/domain/validation/listener/validation_listener.py b/server/osa/domain/validation/listener/validation_listener.py similarity index 100% rename from osa/domain/validation/listener/validation_listener.py rename to server/osa/domain/validation/listener/validation_listener.py diff --git a/osa/domain/validation/model/__init__.py b/server/osa/domain/validation/model/__init__.py similarity index 100% rename from osa/domain/validation/model/__init__.py rename to server/osa/domain/validation/model/__init__.py diff --git a/osa/domain/validation/model/entity.py b/server/osa/domain/validation/model/entity.py similarity index 100% rename from osa/domain/validation/model/entity.py rename to server/osa/domain/validation/model/entity.py diff --git a/osa/domain/validation/model/value.py b/server/osa/domain/validation/model/value.py similarity index 100% rename from osa/domain/validation/model/value.py rename to server/osa/domain/validation/model/value.py diff --git a/osa/domain/validation/port/__init__.py b/server/osa/domain/validation/port/__init__.py similarity index 100% rename from osa/domain/validation/port/__init__.py rename to server/osa/domain/validation/port/__init__.py diff --git a/osa/domain/validation/port/repository.py b/server/osa/domain/validation/port/repository.py similarity index 100% rename from osa/domain/validation/port/repository.py rename to server/osa/domain/validation/port/repository.py diff --git a/osa/domain/validation/port/runner.py b/server/osa/domain/validation/port/runner.py similarity index 100% rename from osa/domain/validation/port/runner.py rename to server/osa/domain/validation/port/runner.py diff --git a/osa/domain/validation/query/__init__.py b/server/osa/domain/validation/query/__init__.py similarity index 100% rename from osa/domain/validation/query/__init__.py rename to server/osa/domain/validation/query/__init__.py diff --git a/osa/domain/validation/service/__init__.py b/server/osa/domain/validation/service/__init__.py similarity index 100% rename from osa/domain/validation/service/__init__.py rename to server/osa/domain/validation/service/__init__.py diff --git a/osa/domain/validation/service/validation.py b/server/osa/domain/validation/service/validation.py similarity index 100% rename from osa/domain/validation/service/validation.py rename to server/osa/domain/validation/service/validation.py diff --git a/osa/domain/validation/util/di/__init__.py b/server/osa/domain/validation/util/di/__init__.py similarity index 100% rename from osa/domain/validation/util/di/__init__.py rename to server/osa/domain/validation/util/di/__init__.py diff --git a/osa/domain/validation/util/di/provider.py b/server/osa/domain/validation/util/di/provider.py similarity index 100% rename from osa/domain/validation/util/di/provider.py rename to server/osa/domain/validation/util/di/provider.py diff --git a/osa/infrastructure/__init__.py b/server/osa/infrastructure/__init__.py similarity index 100% rename from osa/infrastructure/__init__.py rename to server/osa/infrastructure/__init__.py diff --git a/osa/infrastructure/event/__init__.py b/server/osa/infrastructure/event/__init__.py similarity index 100% rename from osa/infrastructure/event/__init__.py rename to server/osa/infrastructure/event/__init__.py diff --git a/osa/infrastructure/event/di.py b/server/osa/infrastructure/event/di.py similarity index 100% rename from osa/infrastructure/event/di.py rename to server/osa/infrastructure/event/di.py diff --git a/osa/infrastructure/event/worker.py b/server/osa/infrastructure/event/worker.py similarity index 100% rename from osa/infrastructure/event/worker.py rename to server/osa/infrastructure/event/worker.py diff --git a/osa/infrastructure/index/__init__.py b/server/osa/infrastructure/index/__init__.py similarity index 100% rename from osa/infrastructure/index/__init__.py rename to server/osa/infrastructure/index/__init__.py diff --git a/osa/infrastructure/index/di.py b/server/osa/infrastructure/index/di.py similarity index 100% rename from osa/infrastructure/index/di.py rename to server/osa/infrastructure/index/di.py diff --git a/osa/infrastructure/index/vector/__init__.py b/server/osa/infrastructure/index/vector/__init__.py similarity index 100% rename from osa/infrastructure/index/vector/__init__.py rename to server/osa/infrastructure/index/vector/__init__.py diff --git a/osa/infrastructure/index/vector/backend.py b/server/osa/infrastructure/index/vector/backend.py similarity index 100% rename from osa/infrastructure/index/vector/backend.py rename to server/osa/infrastructure/index/vector/backend.py diff --git a/osa/infrastructure/index/vector/config.py b/server/osa/infrastructure/index/vector/config.py similarity index 100% rename from osa/infrastructure/index/vector/config.py rename to server/osa/infrastructure/index/vector/config.py diff --git a/osa/infrastructure/messaging/__init__.py b/server/osa/infrastructure/messaging/__init__.py similarity index 100% rename from osa/infrastructure/messaging/__init__.py rename to server/osa/infrastructure/messaging/__init__.py diff --git a/osa/infrastructure/oci/__init__.py b/server/osa/infrastructure/oci/__init__.py similarity index 100% rename from osa/infrastructure/oci/__init__.py rename to server/osa/infrastructure/oci/__init__.py diff --git a/osa/infrastructure/oci/di.py b/server/osa/infrastructure/oci/di.py similarity index 100% rename from osa/infrastructure/oci/di.py rename to server/osa/infrastructure/oci/di.py diff --git a/osa/infrastructure/oci/runner.py b/server/osa/infrastructure/oci/runner.py similarity index 100% rename from osa/infrastructure/oci/runner.py rename to server/osa/infrastructure/oci/runner.py diff --git a/osa/infrastructure/persistence/__init__.py b/server/osa/infrastructure/persistence/__init__.py similarity index 100% rename from osa/infrastructure/persistence/__init__.py rename to server/osa/infrastructure/persistence/__init__.py diff --git a/osa/infrastructure/persistence/adapter/__init__.py b/server/osa/infrastructure/persistence/adapter/__init__.py similarity index 100% rename from osa/infrastructure/persistence/adapter/__init__.py rename to server/osa/infrastructure/persistence/adapter/__init__.py diff --git a/osa/infrastructure/persistence/adapter/storage.py b/server/osa/infrastructure/persistence/adapter/storage.py similarity index 100% rename from osa/infrastructure/persistence/adapter/storage.py rename to server/osa/infrastructure/persistence/adapter/storage.py diff --git a/osa/infrastructure/persistence/database.py b/server/osa/infrastructure/persistence/database.py similarity index 100% rename from osa/infrastructure/persistence/database.py rename to server/osa/infrastructure/persistence/database.py diff --git a/osa/infrastructure/persistence/di.py b/server/osa/infrastructure/persistence/di.py similarity index 100% rename from osa/infrastructure/persistence/di.py rename to server/osa/infrastructure/persistence/di.py diff --git a/osa/infrastructure/persistence/mappers/deposition.py b/server/osa/infrastructure/persistence/mappers/deposition.py similarity index 100% rename from osa/infrastructure/persistence/mappers/deposition.py rename to server/osa/infrastructure/persistence/mappers/deposition.py diff --git a/osa/infrastructure/persistence/mappers/record.py b/server/osa/infrastructure/persistence/mappers/record.py similarity index 100% rename from osa/infrastructure/persistence/mappers/record.py rename to server/osa/infrastructure/persistence/mappers/record.py diff --git a/osa/infrastructure/persistence/mappers/validation.py b/server/osa/infrastructure/persistence/mappers/validation.py similarity index 100% rename from osa/infrastructure/persistence/mappers/validation.py rename to server/osa/infrastructure/persistence/mappers/validation.py diff --git a/osa/infrastructure/persistence/migrate.py b/server/osa/infrastructure/persistence/migrate.py similarity index 100% rename from osa/infrastructure/persistence/migrate.py rename to server/osa/infrastructure/persistence/migrate.py diff --git a/osa/infrastructure/persistence/repository/deposition.py b/server/osa/infrastructure/persistence/repository/deposition.py similarity index 100% rename from osa/infrastructure/persistence/repository/deposition.py rename to server/osa/infrastructure/persistence/repository/deposition.py diff --git a/osa/infrastructure/persistence/repository/event.py b/server/osa/infrastructure/persistence/repository/event.py similarity index 100% rename from osa/infrastructure/persistence/repository/event.py rename to server/osa/infrastructure/persistence/repository/event.py diff --git a/osa/infrastructure/persistence/repository/record.py b/server/osa/infrastructure/persistence/repository/record.py similarity index 100% rename from osa/infrastructure/persistence/repository/record.py rename to server/osa/infrastructure/persistence/repository/record.py diff --git a/osa/infrastructure/persistence/repository/validation.py b/server/osa/infrastructure/persistence/repository/validation.py similarity index 100% rename from osa/infrastructure/persistence/repository/validation.py rename to server/osa/infrastructure/persistence/repository/validation.py diff --git a/osa/infrastructure/persistence/tables.py b/server/osa/infrastructure/persistence/tables.py similarity index 100% rename from osa/infrastructure/persistence/tables.py rename to server/osa/infrastructure/persistence/tables.py diff --git a/osa/infrastructure/source/__init__.py b/server/osa/infrastructure/source/__init__.py similarity index 100% rename from osa/infrastructure/source/__init__.py rename to server/osa/infrastructure/source/__init__.py diff --git a/osa/infrastructure/source/di.py b/server/osa/infrastructure/source/di.py similarity index 100% rename from osa/infrastructure/source/di.py rename to server/osa/infrastructure/source/di.py diff --git a/osa/infrastructure/source/discovery.py b/server/osa/infrastructure/source/discovery.py similarity index 100% rename from osa/infrastructure/source/discovery.py rename to server/osa/infrastructure/source/discovery.py diff --git a/osa/sdk/__init__.py b/server/osa/sdk/__init__.py similarity index 100% rename from osa/sdk/__init__.py rename to server/osa/sdk/__init__.py diff --git a/osa/sdk/index/__init__.py b/server/osa/sdk/index/__init__.py similarity index 100% rename from osa/sdk/index/__init__.py rename to server/osa/sdk/index/__init__.py diff --git a/osa/sdk/index/backend.py b/server/osa/sdk/index/backend.py similarity index 100% rename from osa/sdk/index/backend.py rename to server/osa/sdk/index/backend.py diff --git a/osa/sdk/index/config.py b/server/osa/sdk/index/config.py similarity index 100% rename from osa/sdk/index/config.py rename to server/osa/sdk/index/config.py diff --git a/osa/sdk/index/result.py b/server/osa/sdk/index/result.py similarity index 100% rename from osa/sdk/index/result.py rename to server/osa/sdk/index/result.py diff --git a/osa/sdk/source/__init__.py b/server/osa/sdk/source/__init__.py similarity index 100% rename from osa/sdk/source/__init__.py rename to server/osa/sdk/source/__init__.py diff --git a/osa/sdk/source/config.py b/server/osa/sdk/source/config.py similarity index 100% rename from osa/sdk/source/config.py rename to server/osa/sdk/source/config.py diff --git a/osa/sdk/source/record.py b/server/osa/sdk/source/record.py similarity index 100% rename from osa/sdk/source/record.py rename to server/osa/sdk/source/record.py diff --git a/osa/sdk/source/source.py b/server/osa/sdk/source/source.py similarity index 100% rename from osa/sdk/source/source.py rename to server/osa/sdk/source/source.py diff --git a/osa/util/__init__.py b/server/osa/util/__init__.py similarity index 100% rename from osa/util/__init__.py rename to server/osa/util/__init__.py diff --git a/osa/util/di/__init__.py b/server/osa/util/di/__init__.py similarity index 100% rename from osa/util/di/__init__.py rename to server/osa/util/di/__init__.py diff --git a/osa/util/di/base.py b/server/osa/util/di/base.py similarity index 100% rename from osa/util/di/base.py rename to server/osa/util/di/base.py diff --git a/osa/util/di/container.py b/server/osa/util/di/container.py similarity index 100% rename from osa/util/di/container.py rename to server/osa/util/di/container.py diff --git a/osa/util/di/fastapi.py b/server/osa/util/di/fastapi.py similarity index 100% rename from osa/util/di/fastapi.py rename to server/osa/util/di/fastapi.py diff --git a/osa/util/di/scope.py b/server/osa/util/di/scope.py similarity index 100% rename from osa/util/di/scope.py rename to server/osa/util/di/scope.py diff --git a/pyproject.toml b/server/pyproject.toml similarity index 95% rename from pyproject.toml rename to server/pyproject.toml index 83b649b..8e33de0 100644 --- a/pyproject.toml +++ b/server/pyproject.toml @@ -26,6 +26,8 @@ dependencies = [ "aiosqlite>=0.22.0", "greenlet>=3.2.4", "rich>=14.2.0", + "asyncpg>=0.31.0", + "psycopg2-binary>=2.9.11", ] [project.scripts] diff --git a/sources/__init__.py b/server/sources/__init__.py similarity index 100% rename from sources/__init__.py rename to server/sources/__init__.py diff --git a/sources/geo_entrez/__init__.py b/server/sources/geo_entrez/__init__.py similarity index 100% rename from sources/geo_entrez/__init__.py rename to server/sources/geo_entrez/__init__.py diff --git a/sources/geo_entrez/config.py b/server/sources/geo_entrez/config.py similarity index 100% rename from sources/geo_entrez/config.py rename to server/sources/geo_entrez/config.py diff --git a/sources/geo_entrez/source.py b/server/sources/geo_entrez/source.py similarity index 100% rename from sources/geo_entrez/source.py rename to server/sources/geo_entrez/source.py diff --git a/tests/conftest.py b/server/tests/conftest.py similarity index 100% rename from tests/conftest.py rename to server/tests/conftest.py diff --git a/tests/integration/__init__.py b/server/tests/integration/__init__.py similarity index 100% rename from tests/integration/__init__.py rename to server/tests/integration/__init__.py diff --git a/tests/integration/infrastructure/__init__.py b/server/tests/integration/infrastructure/__init__.py similarity index 100% rename from tests/integration/infrastructure/__init__.py rename to server/tests/integration/infrastructure/__init__.py diff --git a/tests/integration/infrastructure/source/__init__.py b/server/tests/integration/infrastructure/source/__init__.py similarity index 100% rename from tests/integration/infrastructure/source/__init__.py rename to server/tests/integration/infrastructure/source/__init__.py diff --git a/tests/test_sources/__init__.py b/server/tests/test_sources/__init__.py similarity index 100% rename from tests/test_sources/__init__.py rename to server/tests/test_sources/__init__.py diff --git a/tests/test_sources/geo_entrez/__init__.py b/server/tests/test_sources/geo_entrez/__init__.py similarity index 100% rename from tests/test_sources/geo_entrez/__init__.py rename to server/tests/test_sources/geo_entrez/__init__.py diff --git a/tests/test_sources/geo_entrez/test_source.py b/server/tests/test_sources/geo_entrez/test_source.py similarity index 100% rename from tests/test_sources/geo_entrez/test_source.py rename to server/tests/test_sources/geo_entrez/test_source.py diff --git a/tests/unit/cli/__init__.py b/server/tests/unit/cli/__init__.py similarity index 100% rename from tests/unit/cli/__init__.py rename to server/tests/unit/cli/__init__.py diff --git a/tests/unit/cli/util/__init__.py b/server/tests/unit/cli/util/__init__.py similarity index 100% rename from tests/unit/cli/util/__init__.py rename to server/tests/unit/cli/util/__init__.py diff --git a/tests/unit/cli/util/test_paths.py b/server/tests/unit/cli/util/test_paths.py similarity index 100% rename from tests/unit/cli/util/test_paths.py rename to server/tests/unit/cli/util/test_paths.py diff --git a/tests/unit/config/__init__.py b/server/tests/unit/config/__init__.py similarity index 100% rename from tests/unit/config/__init__.py rename to server/tests/unit/config/__init__.py diff --git a/tests/unit/config/test_paths_config.py b/server/tests/unit/config/test_paths_config.py similarity index 100% rename from tests/unit/config/test_paths_config.py rename to server/tests/unit/config/test_paths_config.py diff --git a/tests/unit/domain/index/__init__.py b/server/tests/unit/domain/index/__init__.py similarity index 100% rename from tests/unit/domain/index/__init__.py rename to server/tests/unit/domain/index/__init__.py diff --git a/tests/unit/domain/index/test_index_service.py b/server/tests/unit/domain/index/test_index_service.py similarity index 100% rename from tests/unit/domain/index/test_index_service.py rename to server/tests/unit/domain/index/test_index_service.py diff --git a/tests/unit/domain/record/__init__.py b/server/tests/unit/domain/record/__init__.py similarity index 100% rename from tests/unit/domain/record/__init__.py rename to server/tests/unit/domain/record/__init__.py diff --git a/tests/unit/domain/record/test_record_service.py b/server/tests/unit/domain/record/test_record_service.py similarity index 100% rename from tests/unit/domain/record/test_record_service.py rename to server/tests/unit/domain/record/test_record_service.py diff --git a/tests/unit/domain/shared/test_srn.py b/server/tests/unit/domain/shared/test_srn.py similarity index 100% rename from tests/unit/domain/shared/test_srn.py rename to server/tests/unit/domain/shared/test_srn.py diff --git a/tests/unit/domain/source/__init__.py b/server/tests/unit/domain/source/__init__.py similarity index 100% rename from tests/unit/domain/source/__init__.py rename to server/tests/unit/domain/source/__init__.py diff --git a/tests/unit/domain/source/test_source_service.py b/server/tests/unit/domain/source/test_source_service.py similarity index 100% rename from tests/unit/domain/source/test_source_service.py rename to server/tests/unit/domain/source/test_source_service.py diff --git a/tests/unit/domain/validation/__init__.py b/server/tests/unit/domain/validation/__init__.py similarity index 100% rename from tests/unit/domain/validation/__init__.py rename to server/tests/unit/domain/validation/__init__.py diff --git a/tests/unit/infrastructure/index/test_vector_config.py b/server/tests/unit/infrastructure/index/test_vector_config.py similarity index 100% rename from tests/unit/infrastructure/index/test_vector_config.py rename to server/tests/unit/infrastructure/index/test_vector_config.py diff --git a/uv.lock b/server/uv.lock similarity index 97% rename from uv.lock rename to server/uv.lock index 5becc7e..76a461b 100644 --- a/uv.lock +++ b/server/uv.lock @@ -181,6 +181,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096, upload-time = "2025-11-19T15:32:19.004Z" }, ] +[[package]] +name = "asyncpg" +version = "0.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cc/d18065ce2380d80b1bcce927c24a2642efd38918e33fd724bc4bca904877/asyncpg-0.31.0.tar.gz", hash = "sha256:c989386c83940bfbd787180f2b1519415e2d3d6277a70d9d0f0145ac73500735", size = 993667, upload-time = "2025-11-24T23:27:00.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/11/97b5c2af72a5d0b9bc3fa30cd4b9ce22284a9a943a150fdc768763caf035/asyncpg-0.31.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c204fab1b91e08b0f47e90a75d1b3c62174dab21f670ad6c5d0f243a228f015b", size = 661111, upload-time = "2025-11-24T23:26:04.467Z" }, + { url = "https://files.pythonhosted.org/packages/1b/71/157d611c791a5e2d0423f09f027bd499935f0906e0c2a416ce712ba51ef3/asyncpg-0.31.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:54a64f91839ba59008eccf7aad2e93d6e3de688d796f35803235ea1c4898ae1e", size = 636928, upload-time = "2025-11-24T23:26:05.944Z" }, + { url = "https://files.pythonhosted.org/packages/2e/fc/9e3486fb2bbe69d4a867c0b76d68542650a7ff1574ca40e84c3111bb0c6e/asyncpg-0.31.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0e0822b1038dc7253b337b0f3f676cadc4ac31b126c5d42691c39691962e403", size = 3424067, upload-time = "2025-11-24T23:26:07.957Z" }, + { url = "https://files.pythonhosted.org/packages/12/c6/8c9d076f73f07f995013c791e018a1cd5f31823c2a3187fc8581706aa00f/asyncpg-0.31.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bef056aa502ee34204c161c72ca1f3c274917596877f825968368b2c33f585f4", size = 3518156, upload-time = "2025-11-24T23:26:09.591Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3b/60683a0baf50fbc546499cfb53132cb6835b92b529a05f6a81471ab60d0c/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0bfbcc5b7ffcd9b75ab1558f00db2ae07db9c80637ad1b2469c43df79d7a5ae2", size = 3319636, upload-time = "2025-11-24T23:26:11.168Z" }, + { url = "https://files.pythonhosted.org/packages/50/dc/8487df0f69bd398a61e1792b3cba0e47477f214eff085ba0efa7eac9ce87/asyncpg-0.31.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22bc525ebbdc24d1261ecbf6f504998244d4e3be1721784b5f64664d61fbe602", size = 3472079, upload-time = "2025-11-24T23:26:13.164Z" }, + { url = "https://files.pythonhosted.org/packages/13/a1/c5bbeeb8531c05c89135cb8b28575ac2fac618bcb60119ee9696c3faf71c/asyncpg-0.31.0-cp313-cp313-win32.whl", hash = "sha256:f890de5e1e4f7e14023619399a471ce4b71f5418cd67a51853b9910fdfa73696", size = 527606, upload-time = "2025-11-24T23:26:14.78Z" }, + { url = "https://files.pythonhosted.org/packages/91/66/b25ccb84a246b470eb943b0107c07edcae51804912b824054b3413995a10/asyncpg-0.31.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc5f2fa9916f292e5c5c8b2ac2813763bcd7f58e130055b4ad8a0531314201ab", size = 596569, upload-time = "2025-11-24T23:26:16.189Z" }, + { url = "https://files.pythonhosted.org/packages/3c/36/e9450d62e84a13aea6580c83a47a437f26c7ca6fa0f0fd40b6670793ea30/asyncpg-0.31.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f6b56b91bb0ffc328c4e3ed113136cddd9deefdf5f79ab448598b9772831df44", size = 660867, upload-time = "2025-11-24T23:26:17.631Z" }, + { url = "https://files.pythonhosted.org/packages/82/4b/1d0a2b33b3102d210439338e1beea616a6122267c0df459ff0265cd5807a/asyncpg-0.31.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:334dec28cf20d7f5bb9e45b39546ddf247f8042a690bff9b9573d00086e69cb5", size = 638349, upload-time = "2025-11-24T23:26:19.689Z" }, + { url = "https://files.pythonhosted.org/packages/41/aa/e7f7ac9a7974f08eff9183e392b2d62516f90412686532d27e196c0f0eeb/asyncpg-0.31.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98cc158c53f46de7bb677fd20c417e264fc02b36d901cc2a43bd6cb0dc6dbfd2", size = 3410428, upload-time = "2025-11-24T23:26:21.275Z" }, + { url = "https://files.pythonhosted.org/packages/6f/de/bf1b60de3dede5c2731e6788617a512bc0ebd9693eac297ee74086f101d7/asyncpg-0.31.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9322b563e2661a52e3cdbc93eed3be7748b289f792e0011cb2720d278b366ce2", size = 3471678, upload-time = "2025-11-24T23:26:23.627Z" }, + { url = "https://files.pythonhosted.org/packages/46/78/fc3ade003e22d8bd53aaf8f75f4be48f0b460fa73738f0391b9c856a9147/asyncpg-0.31.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19857a358fc811d82227449b7ca40afb46e75b33eb8897240c3839dd8b744218", size = 3313505, upload-time = "2025-11-24T23:26:25.235Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e9/73eb8a6789e927816f4705291be21f2225687bfa97321e40cd23055e903a/asyncpg-0.31.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ba5f8886e850882ff2c2ace5732300e99193823e8107e2c53ef01c1ebfa1e85d", size = 3434744, upload-time = "2025-11-24T23:26:26.944Z" }, + { url = "https://files.pythonhosted.org/packages/08/4b/f10b880534413c65c5b5862f79b8e81553a8f364e5238832ad4c0af71b7f/asyncpg-0.31.0-cp314-cp314-win32.whl", hash = "sha256:cea3a0b2a14f95834cee29432e4ddc399b95700eb1d51bbc5bfee8f31fa07b2b", size = 532251, upload-time = "2025-11-24T23:26:28.404Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2d/7aa40750b7a19efa5d66e67fc06008ca0f27ba1bd082e457ad82f59aba49/asyncpg-0.31.0-cp314-cp314-win_amd64.whl", hash = "sha256:04d19392716af6b029411a0264d92093b6e5e8285ae97a39957b9a9c14ea72be", size = 604901, upload-time = "2025-11-24T23:26:30.34Z" }, + { url = "https://files.pythonhosted.org/packages/ce/fe/b9dfe349b83b9dee28cc42360d2c86b2cdce4cb551a2c2d27e156bcac84d/asyncpg-0.31.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bdb957706da132e982cc6856bb2f7b740603472b54c3ebc77fe60ea3e57e1bd2", size = 702280, upload-time = "2025-11-24T23:26:32Z" }, + { url = "https://files.pythonhosted.org/packages/6a/81/e6be6e37e560bd91e6c23ea8a6138a04fd057b08cf63d3c5055c98e81c1d/asyncpg-0.31.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6d11b198111a72f47154fa03b85799f9be63701e068b43f84ac25da0bda9cb31", size = 682931, upload-time = "2025-11-24T23:26:33.572Z" }, + { url = "https://files.pythonhosted.org/packages/a6/45/6009040da85a1648dd5bc75b3b0a062081c483e75a1a29041ae63a0bf0dc/asyncpg-0.31.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18c83b03bc0d1b23e6230f5bf8d4f217dc9bc08644ce0502a9d91dc9e634a9c7", size = 3581608, upload-time = "2025-11-24T23:26:35.638Z" }, + { url = "https://files.pythonhosted.org/packages/7e/06/2e3d4d7608b0b2b3adbee0d0bd6a2d29ca0fc4d8a78f8277df04e2d1fd7b/asyncpg-0.31.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e009abc333464ff18b8f6fd146addffd9aaf63e79aa3bb40ab7a4c332d0c5e9e", size = 3498738, upload-time = "2025-11-24T23:26:37.275Z" }, + { url = "https://files.pythonhosted.org/packages/7d/aa/7d75ede780033141c51d83577ea23236ba7d3a23593929b32b49db8ed36e/asyncpg-0.31.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3b1fbcb0e396a5ca435a8826a87e5c2c2cc0c8c68eb6fadf82168056b0e53a8c", size = 3401026, upload-time = "2025-11-24T23:26:39.423Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7a/15e37d45e7f7c94facc1e9148c0e455e8f33c08f0b8a0b1deb2c5171771b/asyncpg-0.31.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8df714dba348efcc162d2adf02d213e5fab1bd9f557e1305633e851a61814a7a", size = 3429426, upload-time = "2025-11-24T23:26:41.032Z" }, + { url = "https://files.pythonhosted.org/packages/13/d5/71437c5f6ae5f307828710efbe62163974e71237d5d46ebd2869ea052d10/asyncpg-0.31.0-cp314-cp314t-win32.whl", hash = "sha256:1b41f1afb1033f2b44f3234993b15096ddc9cd71b21a42dbd87fc6a57b43d65d", size = 614495, upload-time = "2025-11-24T23:26:42.659Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d7/8fb3044eaef08a310acfe23dae9a8e2e07d305edc29a53497e52bc76eca7/asyncpg-0.31.0-cp314-cp314t-win_amd64.whl", hash = "sha256:bd4107bb7cdd0e9e65fae66a62afd3a249663b844fa34d479f6d5b3bef9c04c3", size = 706062, upload-time = "2025-11-24T23:26:44.086Z" }, +] + [[package]] name = "attrs" version = "25.4.0" @@ -1738,6 +1770,7 @@ dependencies = [ { name = "aiosqlite" }, { name = "alembic" }, { name = "apscheduler" }, + { name = "asyncpg" }, { name = "chromadb" }, { name = "cyclopts" }, { name = "dishka" }, @@ -1745,6 +1778,7 @@ dependencies = [ { name = "greenlet" }, { name = "httpx" }, { name = "logfire", extra = ["fastapi", "httpx"] }, + { name = "psycopg2-binary" }, { name = "pydantic", extra = ["email"] }, { name = "pydantic-settings" }, { name = "rich" }, @@ -1771,6 +1805,7 @@ requires-dist = [ { name = "aiosqlite", specifier = ">=0.22.0" }, { name = "alembic", specifier = ">=1.17.2" }, { name = "apscheduler", specifier = ">=4.0.0a6" }, + { name = "asyncpg", specifier = ">=0.31.0" }, { name = "chromadb", specifier = ">=1.3.7" }, { name = "cyclopts", specifier = ">=4.4.0" }, { name = "dishka", specifier = ">=1.7.2" }, @@ -1778,6 +1813,7 @@ requires-dist = [ { name = "greenlet", specifier = ">=3.2.4" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "logfire", extras = ["fastapi", "httpx"], specifier = ">=4.15.1" }, + { name = "psycopg2-binary", specifier = ">=2.9.11" }, { name = "pydantic", extras = ["email"], specifier = ">=2.12.4" }, { name = "pydantic-settings", specifier = ">=2.12.0" }, { name = "rich", specifier = ">=14.2.0" }, @@ -1950,6 +1986,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/b4/46310463b4f6ceef310f8348786f3cff181cea671578e3d9743ba61a459e/protobuf-6.33.1-py3-none-any.whl", hash = "sha256:d595a9fd694fdeb061a62fbe10eb039cc1e444df81ec9bb70c7fc59ebcb1eafa", size = 170477, upload-time = "2025-11-13T16:44:17.633Z" }, ] +[[package]] +name = "psycopg2-binary" +version = "2.9.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/6c/8767aaa597ba424643dc87348c6f1754dd9f48e80fdc1b9f7ca5c3a7c213/psycopg2-binary-2.9.11.tar.gz", hash = "sha256:b6aed9e096bf63f9e75edf2581aa9a7e7186d97ab5c177aa6c87797cd591236c", size = 379620, upload-time = "2025-10-10T11:14:48.041Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/a8/a2709681b3ac11b0b1786def10006b8995125ba268c9a54bea6f5ae8bd3e/psycopg2_binary-2.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b8fb3db325435d34235b044b199e56cdf9ff41223a4b9752e8576465170bb38c", size = 3756572, upload-time = "2025-10-10T11:12:32.873Z" }, + { url = "https://files.pythonhosted.org/packages/62/e1/c2b38d256d0dafd32713e9f31982a5b028f4a3651f446be70785f484f472/psycopg2_binary-2.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:366df99e710a2acd90efed3764bb1e28df6c675d33a7fb40df9b7281694432ee", size = 3864529, upload-time = "2025-10-10T11:12:36.791Z" }, + { url = "https://files.pythonhosted.org/packages/11/32/b2ffe8f3853c181e88f0a157c5fb4e383102238d73c52ac6d93a5c8bffe6/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c55b385daa2f92cb64b12ec4536c66954ac53654c7f15a203578da4e78105c0", size = 4411242, upload-time = "2025-10-10T11:12:42.388Z" }, + { url = "https://files.pythonhosted.org/packages/10/04/6ca7477e6160ae258dc96f67c371157776564679aefd247b66f4661501a2/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c0377174bf1dd416993d16edc15357f6eb17ac998244cca19bc67cdc0e2e5766", size = 4468258, upload-time = "2025-10-10T11:12:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/3c/7e/6a1a38f86412df101435809f225d57c1a021307dd0689f7a5e7fe83588b1/psycopg2_binary-2.9.11-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5c6ff3335ce08c75afaed19e08699e8aacf95d4a260b495a4a8545244fe2ceb3", size = 4166295, upload-time = "2025-10-10T11:12:52.525Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7d/c07374c501b45f3579a9eb761cbf2604ddef3d96ad48679112c2c5aa9c25/psycopg2_binary-2.9.11-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84011ba3109e06ac412f95399b704d3d6950e386b7994475b231cf61eec2fc1f", size = 3983133, upload-time = "2025-10-30T02:55:24.329Z" }, + { url = "https://files.pythonhosted.org/packages/82/56/993b7104cb8345ad7d4516538ccf8f0d0ac640b1ebd8c754a7b024e76878/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba34475ceb08cccbdd98f6b46916917ae6eeb92b5ae111df10b544c3a4621dc4", size = 3652383, upload-time = "2025-10-10T11:12:56.387Z" }, + { url = "https://files.pythonhosted.org/packages/2d/ac/eaeb6029362fd8d454a27374d84c6866c82c33bfc24587b4face5a8e43ef/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b31e90fdd0f968c2de3b26ab014314fe814225b6c324f770952f7d38abf17e3c", size = 3298168, upload-time = "2025-10-10T11:13:00.403Z" }, + { url = "https://files.pythonhosted.org/packages/2b/39/50c3facc66bded9ada5cbc0de867499a703dc6bca6be03070b4e3b65da6c/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d526864e0f67f74937a8fce859bd56c979f5e2ec57ca7c627f5f1071ef7fee60", size = 3044712, upload-time = "2025-10-30T02:55:27.975Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8e/b7de019a1f562f72ada81081a12823d3c1590bedc48d7d2559410a2763fe/psycopg2_binary-2.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04195548662fa544626c8ea0f06561eb6203f1984ba5b4562764fbeb4c3d14b1", size = 3347549, upload-time = "2025-10-10T11:13:03.971Z" }, + { url = "https://files.pythonhosted.org/packages/80/2d/1bb683f64737bbb1f86c82b7359db1eb2be4e2c0c13b947f80efefa7d3e5/psycopg2_binary-2.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:efff12b432179443f54e230fdf60de1f6cc726b6c832db8701227d089310e8aa", size = 2714215, upload-time = "2025-10-10T11:13:07.14Z" }, + { url = "https://files.pythonhosted.org/packages/64/12/93ef0098590cf51d9732b4f139533732565704f45bdc1ffa741b7c95fb54/psycopg2_binary-2.9.11-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:92e3b669236327083a2e33ccfa0d320dd01b9803b3e14dd986a4fc54aa00f4e1", size = 3756567, upload-time = "2025-10-10T11:13:11.885Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a9/9d55c614a891288f15ca4b5209b09f0f01e3124056924e17b81b9fa054cc/psycopg2_binary-2.9.11-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e0deeb03da539fa3577fcb0b3f2554a97f7e5477c246098dbb18091a4a01c16f", size = 3864755, upload-time = "2025-10-10T11:13:17.727Z" }, + { url = "https://files.pythonhosted.org/packages/13/1e/98874ce72fd29cbde93209977b196a2edae03f8490d1bd8158e7f1daf3a0/psycopg2_binary-2.9.11-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9b52a3f9bb540a3e4ec0f6ba6d31339727b2950c9772850d6545b7eae0b9d7c5", size = 4411646, upload-time = "2025-10-10T11:13:24.432Z" }, + { url = "https://files.pythonhosted.org/packages/5a/bd/a335ce6645334fb8d758cc358810defca14a1d19ffbc8a10bd38a2328565/psycopg2_binary-2.9.11-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:db4fd476874ccfdbb630a54426964959e58da4c61c9feba73e6094d51303d7d8", size = 4468701, upload-time = "2025-10-10T11:13:29.266Z" }, + { url = "https://files.pythonhosted.org/packages/44/d6/c8b4f53f34e295e45709b7568bf9b9407a612ea30387d35eb9fa84f269b4/psycopg2_binary-2.9.11-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:47f212c1d3be608a12937cc131bd85502954398aaa1320cb4c14421a0ffccf4c", size = 4166293, upload-time = "2025-10-10T11:13:33.336Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e0/f8cc36eadd1b716ab36bb290618a3292e009867e5c97ce4aba908cb99644/psycopg2_binary-2.9.11-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e35b7abae2b0adab776add56111df1735ccc71406e56203515e228a8dc07089f", size = 3983184, upload-time = "2025-10-30T02:55:32.483Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/2a8fe18a4e61cfb3417da67b6318e12691772c0696d79434184a511906dc/psycopg2_binary-2.9.11-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fcf21be3ce5f5659daefd2b3b3b6e4727b028221ddc94e6c1523425579664747", size = 3652650, upload-time = "2025-10-10T11:13:38.181Z" }, + { url = "https://files.pythonhosted.org/packages/76/36/03801461b31b29fe58d228c24388f999fe814dfc302856e0d17f97d7c54d/psycopg2_binary-2.9.11-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:9bd81e64e8de111237737b29d68039b9c813bdf520156af36d26819c9a979e5f", size = 3298663, upload-time = "2025-10-10T11:13:44.878Z" }, + { url = "https://files.pythonhosted.org/packages/97/77/21b0ea2e1a73aa5fa9222b2a6b8ba325c43c3a8d54272839c991f2345656/psycopg2_binary-2.9.11-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:32770a4d666fbdafab017086655bcddab791d7cb260a16679cc5a7338b64343b", size = 3044737, upload-time = "2025-10-30T02:55:35.69Z" }, + { url = "https://files.pythonhosted.org/packages/67/69/f36abe5f118c1dca6d3726ceae164b9356985805480731ac6712a63f24f0/psycopg2_binary-2.9.11-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3cb3a676873d7506825221045bd70e0427c905b9c8ee8d6acd70cfcbd6e576d", size = 3347643, upload-time = "2025-10-10T11:13:53.499Z" }, + { url = "https://files.pythonhosted.org/packages/e1/36/9c0c326fe3a4227953dfb29f5d0c8ae3b8eb8c1cd2967aa569f50cb3c61f/psycopg2_binary-2.9.11-cp314-cp314-win_amd64.whl", hash = "sha256:4012c9c954dfaccd28f94e84ab9f94e12df76b4afb22331b1f0d3154893a6316", size = 2803913, upload-time = "2025-10-10T11:13:57.058Z" }, +] + [[package]] name = "pyasn1" version = "0.6.1" diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/web/Dockerfile b/web/Dockerfile new file mode 100644 index 0000000..85a50bf --- /dev/null +++ b/web/Dockerfile @@ -0,0 +1,51 @@ +# syntax=docker/dockerfile:1 + +# Stage 1: Dependencies +FROM node:22-alpine AS deps + +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app + +COPY package.json pnpm-lock.yaml ./ +RUN --mount=type=cache,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile + +# Stage 2: Builder +FROM node:22-alpine AS builder + +RUN corepack enable && corepack prepare pnpm@latest --activate + +WORKDIR /app + +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Build with API_URL for rewrites (can be overridden at runtime for SSR) +ARG API_URL=http://server:8000 +ENV API_URL=${API_URL} + +RUN pnpm build + +# Stage 3: Runtime +FROM node:22-alpine AS runtime + +WORKDIR /app + +# Create non-root user +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 nextjs + +# Copy built standalone output +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +CMD ["node", "server.js"] diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/web/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/web/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/web/next.config.ts b/web/next.config.ts new file mode 100644 index 0000000..b94c6ab --- /dev/null +++ b/web/next.config.ts @@ -0,0 +1,18 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + + // Proxy API requests to the backend server + async rewrites() { + const apiUrl = process.env.API_URL || "http://localhost:8000"; + return [ + { + source: "/api/:path*", + destination: `${apiUrl}/:path*`, + }, + ]; + }, +}; + +export default nextConfig; diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..c2a5b65 --- /dev/null +++ b/web/package.json @@ -0,0 +1,27 @@ +{ + "name": "semantic-bio", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint" + }, + "dependencies": { + "@opensciencearchive/ui": "github:opensciencearchive/ui", + "next": "16.1.1", + "react": "19.2.3", + "react-dom": "19.2.3" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.1.1", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml new file mode 100644 index 0000000..690375d --- /dev/null +++ b/web/pnpm-lock.yaml @@ -0,0 +1,4017 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@opensciencearchive/ui': + specifier: github:opensciencearchive/ui + version: https://codeload.github.com/opensciencearchive/ui/tar.gz/b6aedd941e23a9e080bba98b2403c93d43bcc5b8 + next: + specifier: 16.1.1 + version: 16.1.1(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: + specifier: 19.2.3 + version: 19.2.3 + react-dom: + specifier: 19.2.3 + version: 19.2.3(react@19.2.3) + devDependencies: + '@tailwindcss/postcss': + specifier: ^4 + version: 4.1.18 + '@types/node': + specifier: ^20 + version: 20.19.27 + '@types/react': + specifier: ^19 + version: 19.2.7 + '@types/react-dom': + specifier: ^19 + version: 19.2.3(@types/react@19.2.7) + eslint: + specifier: ^9 + version: 9.39.2(jiti@2.6.1) + eslint-config-next: + specifier: 16.1.1 + version: 16.1.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + tailwindcss: + specifier: ^4 + version: 4.1.18 + typescript: + specifier: ^5 + version: 5.9.3 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@0.2.12': + resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + + '@next/env@16.1.1': + resolution: {integrity: sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==} + + '@next/eslint-plugin-next@16.1.1': + resolution: {integrity: sha512-Ovb/6TuLKbE1UiPcg0p39Ke3puyTCIKN9hGbNItmpQsp+WX3qrjO3WaMVSi6JHr9X1NrmthqIguVHodMJbh/dw==} + + '@next/swc-darwin-arm64@16.1.1': + resolution: {integrity: sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@16.1.1': + resolution: {integrity: sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@16.1.1': + resolution: {integrity: sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@16.1.1': + resolution: {integrity: sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@16.1.1': + resolution: {integrity: sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@16.1.1': + resolution: {integrity: sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@16.1.1': + resolution: {integrity: sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@16.1.1': + resolution: {integrity: sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + + '@opensciencearchive/ui@https://codeload.github.com/opensciencearchive/ui/tar.gz/b6aedd941e23a9e080bba98b2403c93d43bcc5b8': + resolution: {tarball: https://codeload.github.com/opensciencearchive/ui/tar.gz/b6aedd941e23a9e080bba98b2403c93d43bcc5b8} + version: 0.1.0 + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + + '@tailwindcss/node@4.1.18': + resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} + + '@tailwindcss/oxide-android-arm64@4.1.18': + resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.18': + resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.18': + resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.18': + resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.18': + resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.18': + resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.18': + resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.1.18': + resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/node@20.19.27': + resolution: {integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.7': + resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} + + '@typescript-eslint/eslint-plugin@8.51.0': + resolution: {integrity: sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.51.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.51.0': + resolution: {integrity: sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.51.0': + resolution: {integrity: sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.51.0': + resolution: {integrity: sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.51.0': + resolution: {integrity: sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.51.0': + resolution: {integrity: sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.51.0': + resolution: {integrity: sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.51.0': + resolution: {integrity: sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.51.0': + resolution: {integrity: sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.51.0': + resolution: {integrity: sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.11.1': + resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.11.1': + resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + cpu: [x64] + os: [win32] + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + baseline-browser-mapping@2.9.11: + resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} + hasBin: true + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001762: + resolution: {integrity: sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.267: + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enhanced-resolve@5.18.4: + resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} + engines: {node: '>=10.13.0'} + + es-abstract@1.24.1: + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.2.2: + resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-next@16.1.1: + resolution: {integrity: sha512-55nTpVWm3qeuxoQKLOjQVciKZJUphKrNM0fCcQHAIOGl6VFXgaqeMfv0aKJhs7QtcnlAPhNVqsqRfRjeKBPIUA==} + peerDependencies: + eslint: '>=9.0.0' + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.10.1: + resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + 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==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + next@16.1.1: + resolution: {integrity: sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==} + engines: {node: '>=20.9.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} + peerDependencies: + react: ^19.2.3 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} + engines: {node: '>=0.10.0'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwindcss@4.1.18: + resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typescript-eslint@8.51.0: + resolution: {integrity: sha512-jh8ZuM5oEh2PSdyQG9YAEM1TCGuWenLSuSUhf/irbVUNW9O5FhbFVONviN2TgMTBnUmyHv7E56rYnfLZK6TkiA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unrs-resolver@1.11.1: + resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@4.3.5: + resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.5': {} + + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + + '@babel/traverse@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@emnapi/core@1.8.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.8.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.3': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.2': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/colour@1.0.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.8.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@0.2.12': + dependencies: + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@next/env@16.1.1': {} + + '@next/eslint-plugin-next@16.1.1': + dependencies: + fast-glob: 3.3.1 + + '@next/swc-darwin-arm64@16.1.1': + optional: true + + '@next/swc-darwin-x64@16.1.1': + optional: true + + '@next/swc-linux-arm64-gnu@16.1.1': + optional: true + + '@next/swc-linux-arm64-musl@16.1.1': + optional: true + + '@next/swc-linux-x64-gnu@16.1.1': + optional: true + + '@next/swc-linux-x64-musl@16.1.1': + optional: true + + '@next/swc-win32-arm64-msvc@16.1.1': + optional: true + + '@next/swc-win32-x64-msvc@16.1.1': + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@nolyfill/is-core-module@1.0.39': {} + + '@opensciencearchive/ui@https://codeload.github.com/opensciencearchive/ui/tar.gz/b6aedd941e23a9e080bba98b2403c93d43bcc5b8': {} + + '@rtsao/scc@1.1.0': {} + + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.1.18': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.4 + jiti: 2.6.1 + lightningcss: 1.30.2 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.1.18 + + '@tailwindcss/oxide-android-arm64@4.1.18': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.18': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.18': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.18': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.18': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + optional: true + + '@tailwindcss/oxide@4.1.18': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-x64': 4.1.18 + '@tailwindcss/oxide-freebsd-x64': 4.1.18 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-x64-musl': 4.1.18 + '@tailwindcss/oxide-wasm32-wasi': 4.1.18 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 + + '@tailwindcss/postcss@4.1.18': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.1.18 + '@tailwindcss/oxide': 4.1.18 + postcss: 8.5.6 + tailwindcss: 4.1.18 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/node@20.19.27': + dependencies: + undici-types: 6.21.0 + + '@types/react-dom@19.2.3(@types/react@19.2.7)': + dependencies: + '@types/react': 19.2.7 + + '@types/react@19.2.7': + dependencies: + csstype: 3.2.3 + + '@typescript-eslint/eslint-plugin@8.51.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.51.0 + '@typescript-eslint/type-utils': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.51.0 + eslint: 9.39.2(jiti@2.6.1) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.51.0 + '@typescript-eslint/types': 8.51.0 + '@typescript-eslint/typescript-estree': 8.51.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.51.0 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.51.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.51.0(typescript@5.9.3) + '@typescript-eslint/types': 8.51.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.51.0': + dependencies: + '@typescript-eslint/types': 8.51.0 + '@typescript-eslint/visitor-keys': 8.51.0 + + '@typescript-eslint/tsconfig-utils@8.51.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.51.0 + '@typescript-eslint/typescript-estree': 8.51.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.51.0': {} + + '@typescript-eslint/typescript-estree@8.51.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.51.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.51.0(typescript@5.9.3) + '@typescript-eslint/types': 8.51.0 + '@typescript-eslint/visitor-keys': 8.51.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.3 + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.51.0 + '@typescript-eslint/types': 8.51.0 + '@typescript-eslint/typescript-estree': 8.51.0(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.51.0': + dependencies: + '@typescript-eslint/types': 8.51.0 + eslint-visitor-keys: 4.2.1 + + '@unrs/resolver-binding-android-arm-eabi@1.11.1': + optional: true + + '@unrs/resolver-binding-android-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.11.1': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.11.1': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.11.1': + dependencies: + '@napi-rs/wasm-runtime': 0.2.12 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + optional: true + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + ast-types-flow@0.0.8: {} + + async-function@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.11.0: {} + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + baseline-browser-mapping@2.9.11: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.11 + caniuse-lite: 1.0.30001762 + electron-to-chromium: 1.5.267 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001762: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + client-only@0.0.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + damerau-levenshtein@1.0.8: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + detect-libc@2.1.2: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.267: {} + + emoji-regex@9.2.2: {} + + enhanced-resolve@5.18.4: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + es-abstract@1.24.1: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.2: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-next@16.1.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@next/eslint-plugin-next': 16.1.1 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1)) + globals: 16.4.0 + typescript-eslint: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.3 + eslint: 9.39.2(jiti@2.6.1) + get-tsconfig: 4.13.0 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.2(jiti@2.6.1)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.11.0 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.39.2(jiti@2.6.1) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@babel/core': 7.28.5 + '@babel/parser': 7.28.5 + eslint: 9.39.2(jiti@2.6.1) + hermes-parser: 0.25.1 + zod: 4.3.5 + zod-validation-error: 4.0.2(zod@4.3.5) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.2 + eslint: 9.39.2(jiti@2.6.1) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.2(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.1: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + 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 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.4.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-bun-module@2.0.0: + dependencies: + semver: 7.7.3 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jiti@2.6.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.30.2: + optional: true + + lightningcss-darwin-arm64@1.30.2: + optional: true + + lightningcss-darwin-x64@1.30.2: + optional: true + + lightningcss-freebsd-x64@1.30.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.2: + optional: true + + lightningcss-linux-arm64-gnu@1.30.2: + optional: true + + lightningcss-linux-arm64-musl@1.30.2: + optional: true + + lightningcss-linux-x64-gnu@1.30.2: + optional: true + + lightningcss-linux-x64-musl@1.30.2: + optional: true + + lightningcss-win32-arm64-msvc@1.30.2: + optional: true + + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + napi-postinstall@0.3.4: {} + + natural-compare@1.4.0: {} + + next@16.1.1(@babel/core@7.28.5)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@next/env': 16.1.1 + '@swc/helpers': 0.5.15 + baseline-browser-mapping: 2.9.11 + caniuse-lite: 1.0.30001762 + postcss: 8.4.31 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3) + optionalDependencies: + '@next/swc-darwin-arm64': 16.1.1 + '@next/swc-darwin-x64': 16.1.1 + '@next/swc-linux-arm64-gnu': 16.1.1 + '@next/swc-linux-arm64-musl': 16.1.1 + '@next/swc-linux-x64-gnu': 16.1.1 + '@next/swc-linux-x64-musl': 16.1.1 + '@next/swc-win32-arm64-msvc': 16.1.1 + '@next/swc-win32-x64-msvc': 16.1.1 + sharp: 0.34.5 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + node-releases@2.0.27: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + possible-typed-array-names@1.1.0: {} + + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + react-dom@19.2.3(react@19.2.3): + dependencies: + react: 19.2.3 + scheduler: 0.27.0 + + react-is@16.13.1: {} + + react@19.2.3: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.7.3: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + sharp@0.34.5: + dependencies: + '@img/colour': 1.0.0 + detect-libc: 2.1.2 + semver: 7.7.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + source-map-js@1.2.1: {} + + stable-hash@0.0.5: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.1 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + strip-bom@3.0.0: {} + + strip-json-comments@3.1.1: {} + + styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.3): + dependencies: + client-only: 0.0.1 + react: 19.2.3 + optionalDependencies: + '@babel/core': 7.28.5 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwindcss@4.1.18: {} + + tapable@2.3.0: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript-eslint@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.51.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.51.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + typescript@5.9.3: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@6.21.0: {} + + unrs-resolver@1.11.1: + dependencies: + napi-postinstall: 0.3.4 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.11.1 + '@unrs/resolver-binding-android-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-arm64': 1.11.1 + '@unrs/resolver-binding-darwin-x64': 1.11.1 + '@unrs/resolver-binding-freebsd-x64': 1.11.1 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 + '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 + '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 + '@unrs/resolver-binding-linux-x64-musl': 1.11.1 + '@unrs/resolver-binding-wasm32-wasi': 1.11.1 + '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 + '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 + '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + zod-validation-error@4.0.2(zod@4.3.5): + dependencies: + zod: 4.3.5 + + zod@4.3.5: {} diff --git a/web/postcss.config.mjs b/web/postcss.config.mjs new file mode 100644 index 0000000..61e3684 --- /dev/null +++ b/web/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/web/public/osa_logo.png b/web/public/osa_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a198215ecb1d6fab771f2f8ee89704b3ea31616e GIT binary patch literal 10538 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 Gh5QfYMjS{0 literal 0 HcmV?d00001 diff --git a/web/public/osa_logo.svg b/web/public/osa_logo.svg new file mode 100644 index 0000000..52e2ee4 --- /dev/null +++ b/web/public/osa_logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/app/apple-icon.png b/web/src/app/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a198215ecb1d6fab771f2f8ee89704b3ea31616e GIT binary patch literal 10538 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 Gh5QfYMjS{0 literal 0 HcmV?d00001 diff --git a/web/src/app/error.module.css b/web/src/app/error.module.css new file mode 100644 index 0000000..cb6aa28 --- /dev/null +++ b/web/src/app/error.module.css @@ -0,0 +1,6 @@ +.main { + min-height: calc(100vh - 200px); + display: flex; + align-items: center; + justify-content: center; +} diff --git a/web/src/app/error.tsx b/web/src/app/error.tsx new file mode 100644 index 0000000..aa793de --- /dev/null +++ b/web/src/app/error.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { ErrorMessage } from '@/components/ui/ErrorMessage'; +import styles from './error.module.css'; + +interface ErrorProps { + error: Error; + reset: () => void; +} + +export default function GlobalError({ error, reset }: ErrorProps) { + return ( +
+ +
+ ); +} diff --git a/web/src/app/globals.css b/web/src/app/globals.css new file mode 100644 index 0000000..0ff2a50 --- /dev/null +++ b/web/src/app/globals.css @@ -0,0 +1,60 @@ +/* + * Semantic Bio — Global Styles + * Built on OSA Design System + */ + +/* OSA Design System - using direct paths to bypass exports resolution */ +@import '../../node_modules/@opensciencearchive/ui/ui/tokens/index.css'; +@import '../../node_modules/@opensciencearchive/ui/ui/base/reset.css'; +@import '../../node_modules/@opensciencearchive/ui/ui/base/elements.css'; + +/* App-specific variables */ +:root { + --content-width: 720px; + --content-width-wide: 960px; + --header-height: 60px; +} + +/* Base app styles */ +html { + font-family: var(--font-body); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + min-height: 100vh; + display: flex; + flex-direction: column; + background: var(--color-bg); + color: var(--color-text); +} + +/* Override link styles for app navigation */ +a { + text-decoration: none; + color: var(--color-accent); + transition: color var(--transition-fast); +} + +a:hover { + color: var(--color-accent-hover); +} + +/* Focus styles */ +:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 2px; +} + +/* Form element resets */ +button { + font-family: inherit; + cursor: pointer; + border: none; + background: none; +} + +input, textarea { + font-family: inherit; +} diff --git a/web/src/app/icon.svg b/web/src/app/icon.svg new file mode 100644 index 0000000..52e2ee4 --- /dev/null +++ b/web/src/app/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx new file mode 100644 index 0000000..943045a --- /dev/null +++ b/web/src/app/layout.tsx @@ -0,0 +1,47 @@ +import type { Metadata } from 'next'; +import { DM_Serif_Display, Inter, JetBrains_Mono } from 'next/font/google'; +import './globals.css'; +import { Header } from '@/components/layout/Header'; +import { Footer } from '@/components/layout/Footer'; + +const dmSerif = DM_Serif_Display({ + weight: ['400'], + style: ['normal', 'italic'], + subsets: ['latin'], + display: 'swap', + variable: '--font-display', +}); + +const inter = Inter({ + subsets: ['latin'], + display: 'swap', + variable: '--font-body', +}); + +const jetbrainsMono = JetBrains_Mono({ + subsets: ['latin'], + display: 'swap', + variable: '--font-mono', +}); + +export const metadata: Metadata = { + title: 'Semantic Bio — Search Biological Databases', + description: 'Semantic search over biological databases from Open Science Archive. Discover research datasets using natural language.', + keywords: ['biology', 'genomics', 'GEO', 'research', 'scientific data', 'semantic search'], +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + +
+ {children} +