diff --git a/.clinerules b/.clinerules index 53a9baa8..a9d47c95 100644 --- a/.clinerules +++ b/.clinerules @@ -4,8 +4,8 @@ ### Package Management - Use pnpm for package management (pnpm@10.6.4) -- Use Corepack for package manager versioning -- Bun is used for running scripts and tests +- Use Corepack for package manager version consistency +- Bun is used for running scripts and tests only - Save type errors and dependency installations until ready to address them ### Database @@ -22,15 +22,21 @@ ### Code Organization - Use service-based architecture -- Implement plugin system for extensibility +- Implement plugin system with module federation for extensibility - Follow clean architecture principles - Use TypeScript strict mode ### Monorepo Structure - Use Turborepo for build orchestration and caching -- Bun workspaces for dependency management +- pnpm workspaces for dependency management - Separate backend and frontend as distinct workspaces +### Build System +- Use RSPack for backend building +- Use RSBuild for frontend building +- Support for module federation +- Optimized for TypeScript + ## Project Preferences ### Code Style @@ -51,6 +57,18 @@ - Handle nested stringified JSON - Implement proper error handling for malformed JSON +### Deployment +- Deploy to Railway using Docker containers +- Use Kubernetes for orchestration +- Implement CI/CD with GitHub Actions +- Use environment-specific configurations + +### Security +- Implement proper database security measures +- Plan for Web3Auth integration in frontend +- Use secure headers and CORS policies +- Implement audit logging for sensitive operations + ## Critical Implementation Paths ### Content Flow @@ -60,8 +78,16 @@ 4. DistributionService โ†’ Distributor-specific transforms 5. Distribution to configured channels +### Recap Flow +1. Scheduler service creates jobs based on feed configuration +2. External scheduler triggers recap job via HTTP endpoint +3. Recap job fetches approved submissions since last run +4. ProcessorService applies batch transformations +5. Distribution to configured channels +6. Update last successful completion timestamp + ### Plugin System -1. PluginService loads plugins at runtime +1. PluginService loads plugins at runtime via module federation 2. Plugins register with appropriate service 3. Services use plugins based on configuration 4. Error handling and recovery for plugin failures @@ -71,21 +97,43 @@ 2. Transaction support with retry logic 3. Error handling and connection management 4. Type-safe queries with Drizzle ORM - -## Known Challenges - -### Testing Infrastructure -- Current testing approach relies too heavily on mocks -- Need to implement Docker-based testing infrastructure -- Need to refactor tests to use real database -- Need to implement component tests for key flows - -### PostgreSQL Migration -- Migration from SQLite to PostgreSQL in progress -- Need to update database service implementation -- Need to migrate existing data - -### Performance Optimization -- Need to optimize resource usage -- Need to implement performance monitoring -- Need to identify and address bottlenecks +5. Repository pattern for domain-specific operations +6. State tracking for external scheduled jobs + +## Current Focus Areas + +### Recap Scheduling System +- Implementing reliable recap generation for feeds +- Using external scheduler service for job management +- Tracking job state in the database for resilience +- Supporting both cron expressions and interval-based schedules +- Providing UI for managing recap configurations +- Handling process restarts and maintaining job consistency + +### Comprehensive Error Handling +- Implementing granular error types across the application +- Developing consistent error recovery mechanisms +- Enhancing error logging and monitoring +- Creating user-friendly error messages +- Implementing graceful degradation strategies + +### Configuration in Database +- Migrating from JSON-based configuration to database storage +- Implementing configuration versioning +- Creating admin interface for configuration management +- Ensuring backward compatibility +- Implementing validation and security measures + +### Test Coverage +- Expanding component tests for key flows +- Implementing integration tests for external services +- Adding E2E tests for critical user journeys +- Improving test infrastructure with Docker +- Implementing performance testing + +### Web3Auth Security +- Implementing secure authentication with Web3Auth +- Adding database protections for user data +- Creating proper access control mechanisms +- Implementing audit logging +- Ensuring compliance with security best practices diff --git a/.dockerignore b/.dockerignore index 0bffde13..05891ce4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ # dependencies node_modules +apps/**/node_modules .pnp **/.pnp.js **/.yarn/install-state.gz @@ -18,6 +19,7 @@ out # production build **/**/dist +apps/**/dist # misc **/.DS_Store @@ -81,4 +83,4 @@ frontend/**/*.sw? fly.toml # workspace -.github \ No newline at end of file +.github diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 935a7690..bf52d1b1 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - platform: [ linux/amd64 ] + platform: [linux/amd64] steps: - name: Checkout code @@ -43,4 +43,3 @@ jobs: platforms: ${{ matrix.platform }} push: true tags: ghcr.io/${{ env.REPO }}:${{ github.sha }} - diff --git a/.github/workflows/near-rewards.yml b/.github/workflows/near-rewards.yml index 75c55318..09853934 100644 --- a/.github/workflows/near-rewards.yml +++ b/.github/workflows/near-rewards.yml @@ -1,10 +1,10 @@ name: NEAR Protocol Rewards Tracking on: schedule: - - cron: '0 */12 * * *' # Every 12 hours - workflow_dispatch: # Manual trigger + - cron: "0 */12 * * *" # Every 12 hours + workflow_dispatch: # Manual trigger push: - branches: [ main ] # Start on main branch updates + branches: [main] # Start on main branch updates jobs: calculate-rewards: @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '18' + node-version: "18" - name: Calculate Rewards env: @@ -25,4 +25,4 @@ jobs: GITHUB_REPO: ${{ github.repository }} run: | npm install -g near-protocol-rewards@latest - near-protocol-rewards calculate \ No newline at end of file + near-protocol-rewards calculate diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..3fb4d30a --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,31 @@ +# name: Release + +# on: +# push: +# branches: +# - main + +# jobs: +# release: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# - uses: oven-sh/setup-bun@v2 +# - run: bun install +# - run: bun run build +# - name: Setup Node.js +# uses: actions/setup-node@v4 +# with: +# node-version: "lts/*" +# registry-url: 'https://registry.npmjs.org' +# - name: Publish +# env: +# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +# run: | +# for pkg in packages/*; do +# if [ -f "$pkg/package.json" ]; then +# cd $pkg +# npm publish --access public || true +# cd ../.. +# fi +# done diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cbb89903..5dd3a8e5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,13 +44,13 @@ jobs: run: pnpm install - name: Migrate and seed DB - working-directory: ./backend + working-directory: ./api env: DATABASE_URL: postgresql://postgres:postgres@localhost:5433/test run: pnpm run db:migrate - name: Seed DB - working-directory: ./backend + working-directory: ./api env: DATABASE_URL: postgresql://postgres:postgres@localhost:5433/test run: bun ./test/setup/seed-test.ts diff --git a/.gitignore b/.gitignore index 0b7ce4f6..221745a3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ .yarn/install-state.gz /.unlighthouse **/.pnpm-store +node-compile-cache # testing /coverage @@ -50,4 +51,4 @@ package-lock.json bun.lockb # JetBrains -.idea/ +.idea/ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 383b2918..d1945779 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,4 +3,5 @@ coverage node_modules .turbo .next -.docusaurus \ No newline at end of file +.docusaurus +packages/shared-db/migrations \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3a94bb42 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "cSpell.words": [ + "crowdsource", + "ilhagirl", + "jpollock", + "karmaticacid", + "morica", + "murica", + "oklch", + "plugrel", + "plungrel", + "POTLOCK", + "SCURATE", + "yegorgolovnia" + ] +} diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index a146d292..00000000 --- a/Dockerfile +++ /dev/null @@ -1,72 +0,0 @@ -# Base stage with common dependencies -FROM node:18-alpine AS base - -# Install pnpm -RUN npm install -g pnpm turbo - -# Builder stage for pruning the monorepo -FROM base AS pruner -WORKDIR /app - -COPY . . - -# Disable telemetry and prune the monorepo to include only what's needed -RUN turbo telemetry disable -# Prune the monorepo to include only backend and frontend -RUN turbo prune --scope=@curatedotfun/backend --scope=@curatedotfun/frontend --docker - -# Builder stage for installing dependencies and building -FROM base AS builder -WORKDIR /app - -# Copy pruned package.json files and workspace config -COPY --from=pruner /app/out/json/ . -COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml -COPY --from=pruner /app/turbo.json ./turbo.json -COPY --from=pruner /app/pnpm-workspace.yaml ./pnpm-workspace.yaml - -# Install dependencies using pnpm workspaces -RUN pnpm install --frozen-lockfile - -# Copy source code from pruned monorepo -COPY --from=pruner /app/out/full/ . - -# Build the application using turbo (which will respect the dependencies in turbo.json) -ENV NODE_ENV="production" -RUN pnpm run build - -# Production stage -FROM node:18-alpine AS production -WORKDIR /app - -# Create a non-root user for security -RUN addgroup -S app && adduser -S app -G app - -# Copy only the necessary files from the builder stage -COPY --from=builder --chown=app:app /app/backend/dist ./backend/dist -COPY --from=builder --chown=app:app /app/backend/package.json ./backend/package.json -COPY --from=builder --chown=app:app /app/backend/drizzle.config.ts ./backend/drizzle.config.ts -COPY --from=builder --chown=app:app /app/backend/src/services/db/schema.ts ./backend/src/services/db/schema.ts -COPY --from=builder --chown=app:app /app/backend/src/services/twitter/schema.ts ./backend/src/services/twitter/schema.ts -COPY --from=builder --chown=app:app /app/package.json ./ -COPY --from=builder --chown=app:app /app/pnpm-lock.yaml ./ -COPY --from=builder --chown=app:app /app/pnpm-workspace.yaml ./pnpm-workspace.yaml -COPY --chown=app:app curate.config.json ./ - -# Install pnpm -RUN npm install -g pnpm - -# Install only production dependencies -RUN cd backend && pnpm install --prod --frozen-lockfile - -# Use the non-root user -USER app - -# Expose the port -EXPOSE 3000 - -# Set secure environment defaults -ENV NODE_ENV=production - -# Start the application -CMD ["pnpm", "run", "--dir", "backend", "start"] diff --git a/README.md b/README.md index b9c33485..d0184dce 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ graph TD Twitter["Twitter Source Plugin"] style Twitter color:black end - + %% Submission Processing subgraph Submission["Submission Processing"] SubmissionService["Submission Service"] @@ -82,7 +82,7 @@ graph TD style SubmissionService color:black style Moderation color:black end - + %% Content Processing subgraph Processing["Content Processing"] ProcessorService["Processor Service"] @@ -90,7 +90,7 @@ graph TD style ProcessorService color:black style GlobalTransform color:black end - + %% Distribution subgraph Distribution["Distribution"] DistributionService["Distribution Service"] @@ -98,7 +98,7 @@ graph TD style DistributionService color:black style DistTransform color:black end - + %% Distributor Plugins subgraph Distributors["Distributor Plugins"] Telegram["Telegram"] @@ -110,7 +110,7 @@ graph TD style Notion color:black style Supabase color:black end - + %% Flow connections Sources --> SubmissionService SubmissionService --> Moderation @@ -119,12 +119,12 @@ graph TD GlobalTransform --> DistributionService DistributionService --> DistTransform DistTransform --> Distributors - + %% Styling classDef service fill:#f9f,stroke:#333,stroke-width:2px classDef plugin fill:#bbf,stroke:#333,stroke-width:1px classDef process fill:#bfb,stroke:#333,stroke-width:1px - + class SubmissionService,ProcessorService,DistributionService service class Twitter,Telegram,RSS,Notion,Supabase plugin class Moderation,GlobalTransform,DistTransform process @@ -132,19 +132,20 @@ graph TD ### Key Components -- **[Frontend](./frontend/README.md)** +- **[Frontend](./app/README.md)** + - React-based web interface - Built with RSBuild and Tailwind CSS - Handles user interactions and submissions - - See [Frontend README](./frontend/README.md) for detailed documentation + - See [Frontend README](./app/README.md) for detailed documentation -- **[Backend](./backend/README.md)** +- **[Backend](./api/README.md)** - Node.js runtime with Hono.js framework - Plugin-based architecture with module federation - Service-oriented design with clear boundaries - Twitter bot functionality - API endpoints for frontend - - See [Backend README](./backend/README.md) for detailed documentation + - See [Backend README](./api/README.md) for detailed documentation ### Monorepo Overview @@ -172,17 +173,38 @@ This will install dependencies for all packages in the monorepo. ### Running the app +Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop/) (or [Orbstack](https://orbstack.dev/) on MacOS) is running before starting the development servers. + Start both frontend and backend development servers: ```bash -npm run dev +pnpm run dev ``` +This command: + +- Starts a PostgreSQL container for development +- Initializes the database with migrations and seed data +- Starts the frontend and backend development servers +- Preserves your database data between runs + This will launch: - Frontend at - Backend at +For a fresh start with a clean database: + +```bash +pnpm run dev:fresh +``` + +This command performs the same steps as `pnpm run dev` but removes any existing database volumes for a clean slate. + +When you're done, press Ctrl+C (or Cmd+C on Mac) to stop all services. The command will automatically clean up Docker containers while preserving your database data (unless you used the `dev:fresh` command). + +You can customize the development seed data by modifying `backend/scripts/seed-dev.ts`. + ### Building for production Build all packages: @@ -193,15 +215,28 @@ npm run build ### Deploying -For deployment instructions, see our [Deployment Guide](https://docs.curate.fun/docs/developers/deployment). +Start the application in production mode: + +```bash +pnpm run start +``` + +For detailed deployment instructions, see our [Deployment Guide](https://docs.curate.fun/docs/developers/deployment). ### Running tests ```bash -npm run test +pnpm run test ``` -Tests are located in the backend's `src/__tests__` directory. Run them using `npm run test`. +This command: + +- Starts a dedicated PostgreSQL container for testing +- Initializes the test database with migrations and test seed data +- Runs the test suite +- Automatically cleans up all test containers and volumes when complete + +Tests are located in the backend's `test` directory. Test seed data is located in `backend/test/setup/seed-test.ts`. ## Configuration & Usage diff --git a/backend/.env.example b/apps/api/.env.example similarity index 70% rename from backend/.env.example rename to apps/api/.env.example index 829bcd9a..f55e7bbd 100644 --- a/backend/.env.example +++ b/apps/api/.env.example @@ -7,6 +7,14 @@ TWITTER_2FA_SECRET=your_twitter_2fa # Environment NODE_ENV=development DATABASE_URL=postgresql://postgres:postgres@postgres_dev:5432/curatedotfun # Configured in docker-compose +JWT_SECRET=your_jwt_secret + +# CORS Configuration +ALLOWED_ORIGINS=https://example.com,https://api.example.com + +# Redis Configuration +REDIS_HOST=localhost +REDIS_PORT=6379 #PLUGINS diff --git a/backend/.env.test b/apps/api/.env.test similarity index 66% rename from backend/.env.test rename to apps/api/.env.test index 6dc2c98f..ca3b6959 100644 --- a/backend/.env.test +++ b/apps/api/.env.test @@ -2,4 +2,7 @@ NODE_ENV=test # Database configuration for PostgreSQL -DATABASE_URL=postgresql://postgres:postgres@localhost:54321/test \ No newline at end of file +DATABASE_URL=postgresql://postgres:postgres@localhost:54321/test + +# CORS Configuration for testing +ALLOWED_ORIGINS=https://test.example.com diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile new file mode 100644 index 00000000..367da597 --- /dev/null +++ b/apps/api/Dockerfile @@ -0,0 +1,74 @@ +# Base stage with common dependencies +FROM node:18-alpine AS base + +# Install pnpm and turbo +RUN npm install -g pnpm turbo + +# Pruner stage: Creates a pruned monorepo subset +FROM base AS pruner +WORKDIR /app + +# COPY the entire monorepo context. Docker build context should be the monorepo root. +COPY . . + +# Disable telemetry and prune the monorepo to include only what's needed +RUN turbo telemetry disable +# Prune for backend and its direct workspace dependencies (shared-db, types, utils) +RUN turbo prune --scope=@curatedotfun/api --scope=@curatedotfun/shared-db --scope=@curatedotfun/types --scope=@curatedotfun/utils --docker + +# Builder stage: Installs all dependencies and builds the application +FROM base AS builder +WORKDIR /app + +# Copy pruned manifests and lockfile +COPY --from=pruner /app/out/full/ . +COPY --from=pruner /app/out/json/ . +COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml + +COPY --from=pruner /app/turbo.json ./turbo.json +COPY --from=pruner /app/pnpm-workspace.yaml ./pnpm-workspace.yaml +COPY --from=pruner /app/tsconfig.json ./tsconfig.json + +# Install build dependencies for native modules +RUN apk add --no-cache python3 make g++ + +# Install ALL dependencies for the pruned monorepo subset (including devDependencies for build processes) +RUN pnpm install --frozen-lockfile + +# Copy the full source code of the pruned monorepo subset +COPY --from=pruner /app/out/full/ . + +# Build ONLY the backend application +ENV NODE_ENV="production" +RUN pnpm run build --filter=@curatedotfun/api + +# Production stage: Minimal image for running the backend +FROM node:18-alpine AS production +WORKDIR /app + +# Create a non-root user for security +RUN addgroup -S app && adduser -S app -G app + +# Copy the production-ready code from the builder stage. +COPY --from=builder --chown=app:app /app/apps/api/dist ./apps/api/dist +COPY --from=builder --chown=app:app /app/apps/api/public ./apps/api/public +COPY --from=builder --chown=app:app /app/packages/shared-db ./packages/shared-db +COPY --from=builder --chown=app:app /app/packages/utils ./packages/utils + +# Copy the node_modules directory from the builder stage. +COPY --from=builder --chown=app:app /app/node_modules ./node_modules +COPY --from=builder --chown=app:app /app/package.json ./package.json +COPY --from=builder --chown=app:app /app/pnpm-lock.yaml ./pnpm-lock.yaml +COPY --from=builder --chown=app:app /app/pnpm-workspace.yaml ./pnpm-workspace.yaml + +# Use the non-root user +USER app + +# Expose the port +EXPOSE 3000 + +# Set the final working directory to the backend application's root +WORKDIR /app/apps/api + +# Start the application. +CMD ["node", "dist/main.cjs"] diff --git a/backend/LICENSE b/apps/api/LICENSE similarity index 100% rename from backend/LICENSE rename to apps/api/LICENSE diff --git a/backend/README.md b/apps/api/README.md similarity index 65% rename from backend/README.md rename to apps/api/README.md index 05b48605..98e7ae5e 100644 --- a/backend/README.md +++ b/apps/api/README.md @@ -5,7 +5,7 @@
-

curate.fun backend

+

api.curate.fun

Node.js/Hono.js backend service for the curate.fun platform @@ -50,7 +50,7 @@ graph TD Services --> DistributionService["Distribution Service"] Services --> ConfigService["Configuration Service"] Services --> PluginLoader["Plugin Loader Service"] - + style Server color:white style Services color:white style SubmissionService color:white @@ -101,62 +101,77 @@ cp .env.example .env 3. Start development server: +Make sure [Docker Desktop](https://www.docker.com/products/docker-desktop/) (or [Orbstack](https://orbstack.dev/) on MacOS) is running before starting the development server. + ```bash -bun run dev +# From the root directory +pnpm run dev ``` -### Testing +This command: -Run the test suite: +- Starts a PostgreSQL container for development +- Initializes the database with migrations and seed data +- Starts the backend server in watch mode +- Preserves your database data between runs -```bash -bun test -``` - -Run tests in watch mode during development: +For a fresh start with a clean database: ```bash -bun test --watch +# From the root directory +pnpm run dev:fresh ``` -API documentation is available at `/swagger` when running the development server. +This command performs the same steps as `pnpm run dev` but removes any existing database volumes for a clean slate. -## Plugin Development +When you're done, press Ctrl+C (or Cmd+C on Mac) to stop all services. The command will automatically clean up Docker containers while preserving your database data (unless you used the `dev:fresh` command). -To develop new plugins for curate.fun, see the [Plugin Development Guide](https://docs.curate.fun/docs/plugins/build-plugin). +4. Modifying seed data: -Plugins can extend the platform in various ways: +Development seed data is located in `backend/scripts/seed-dev.ts`. You can modify this file to customize the initial data loaded into your development database. -- Add new content sources -- Create custom transformations -- Implement new distribution channels +5. Production deployment: -The plugin system provides a standardized interface with type safety and comprehensive testing support. +```bash +# From the root directory +pnpm run start +``` + +This command starts the application in production mode with a PostgreSQL database. -## Database Backup (Temporary) +For detailed deployment instructions, see the [Deployment Guide](https://docs.curate.fun/docs/developers/deployment). -AWS has been configured inside of the container, in order to take manual back-ups to Tigris object storage. These backups can be installed and replace .db/submissions.sqlite for local development, or for testing migration scripts. +### Testing -1. SSH into container +Run the test suite: ```bash -fly ssh console +# From the root directory +pnpm run test ``` -2. Export a backup, and then gzip it +This command: -```bash -litefs export -name db ./backups/MONTH-DAY -gzip ./backups MONTH-DAY -``` +- Starts a dedicated PostgreSQL container for testing +- Initializes the test database with migrations and test seed data +- Runs the test suite +- Automatically cleans up all test containers and volumes when complete -3. Save to S3 bucket (environment is preconfigured with S3 secrets) +Test seed data is located in `backend/test/setup/seed-test.ts`. You can modify this file to customize the test data. -```bash -aws s3 cp ./MONTH-DAY.gz s3://curatedotfun-backups/MONTH-DAY.gz --endpoint-url https://fly.storage.tigris.dev -``` +API documentation is available at `/swagger` when running the development server. + +## Plugin Development -4. Download from Tigris, unzip, and replace .db/submissions.sqlite +To develop new plugins for curate.fun, see the [Plugin Development Guide](https://docs.curate.fun/docs/plugins/build-plugin). + +Plugins can extend the platform in various ways: + +- Add new content sources +- Create custom transformations +- Implement new distribution channels + +The plugin system provides a standardized interface with type safety and comprehensive testing support.

diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 00000000..6744da53 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,61 @@ +{ + "name": "@curatedotfun/api", + "version": "0.0.1", + "scripts": { + "schemas:generate": "bun ./scripts/generate-json-schemas.ts", + "build": "rspack build", + "start": "node dist/main.cjs", + "dev": "NODE_ENV=development concurrently --kill-others-on-fail \"rspack build --watch\" \"wait-on -d 500 dist/main.cjs && node scripts/dev-server.js\"", + "clean": "rm -rf dist coverage .turbo" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@module-federation/node": "^2.7.7", + "@rspack/binding": "1.2.8", + "@rspack/cli": "1.2.8", + "@rspack/core": "1.2.8", + "@types/lodash": "^4.17.18", + "@types/pg": "^8.15.4", + "concurrently": "^9.2.0", + "typescript": "^5.8.3", + "wait-on": "^8.0.3" + }, + "dependencies": { + "@crosspost/scheduler-sdk": "^0.1.1", + "@crosspost/sdk": "^0.3.1", + "@crosspost/types": "^0.3.1", + "@curatedotfun/core-services": "workspace:*", + "@curatedotfun/shared-db": "workspace:*", + "@curatedotfun/shared-queue": "workspace:*", + "@curatedotfun/types": "workspace:*", + "@curatedotfun/utils": "workspace:*", + "@hono/node-server": "^1.14.4", + "@hono/zod-validator": "^0.5.0", + "@module-federation/runtime": "^0.11.4", + "agent-twitter-client": "0.0.16", + "bullmq": "^5.56.0", + "dotenv": "^16.5.0", + "drizzle-orm": "^0.43.1", + "hono": "^4.8.2", + "ora": "^8.2.0", + "pg": "^8.16.2", + "pinata-web3": "^0.5.4", + "pino": "^9.7.0", + "pino-pretty": "^13.0.0", + "string-width": "^7.2.0", + "zod": "^3.25.67", + "zod-to-json-schema": "^3.24.5" + }, + "packageManager": "pnpm@10.11.0" +} diff --git a/apps/api/pnpm-lock.yaml b/apps/api/pnpm-lock.yaml new file mode 100644 index 00000000..2267abea --- /dev/null +++ b/apps/api/pnpm-lock.yaml @@ -0,0 +1,8281 @@ +lockfileVersion: "9.0" + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + .: + dependencies: + "@crosspost/scheduler-sdk": + specifier: ^0.1.1 + version: 0.1.1 + "@hono/node-server": + specifier: ^1.8.2 + version: 1.14.1(hono@4.7.9) + "@hono/zod-openapi": + specifier: ^0.9.5 + version: 0.9.10(hono@4.7.9)(zod@3.24.4) + "@hono/zod-validator": + specifier: ^0.5.0 + version: 0.5.0(hono@4.7.9)(zod@3.24.4) + "@module-federation/runtime": + specifier: ^0.11.1 + version: 0.11.4 + "@notionhq/client": + specifier: ^2.2.15 + version: 2.3.0(encoding@0.1.13) + "@types/async-retry": + specifier: ^1.4.9 + version: 1.4.9 + "@types/lodash": + specifier: ^4.17.16 + version: 4.17.16 + "@types/pg": + specifier: ^8.11.11 + version: 8.15.1 + agent-twitter-client: + specifier: ^0.0.16 + version: 0.0.16 + async-retry: + specifier: ^1.3.3 + version: 1.3.3 + dotenv: + specifier: ^16.4.7 + version: 16.5.0 + drizzle-kit: + specifier: ^0.30.1 + version: 0.30.6 + drizzle-orm: + specifier: ^0.40.1 + version: 0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0) + drizzle-zod: + specifier: ^0.7.1 + version: 0.7.1(drizzle-orm@0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0))(zod@3.24.4) + hono: + specifier: ^4.0.5 + version: 4.7.9 + jose: + specifier: ^6.0.11 + version: 6.0.11 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + near-api-js: + specifier: ^5.1.1 + version: 5.1.1(encoding@0.1.13) + ora: + specifier: ^8.1.1 + version: 8.2.0 + pg: + specifier: ^8.15.6 + version: 8.16.0 + pino: + specifier: ^9.6.0 + version: 9.6.0 + pino-pretty: + specifier: ^13.0.0 + version: 13.0.0 + string-width: + specifier: ^7.2.0 + version: 7.2.0 + zod-to-json-schema: + specifier: ^3.24.5 + version: 3.24.5(zod@3.24.4) + devDependencies: + "@curatedotfun/types": + specifier: ^0.0.5 + version: 0.0.5 + "@module-federation/node": + specifier: ^2.6.30 + version: 2.7.2(@rspack/core@1.2.8(@swc/helpers@0.5.13))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(webpack@5.99.8(esbuild@0.19.12)) + "@rspack/binding": + specifier: 1.2.8 + version: 1.2.8 + "@rspack/cli": + specifier: 1.2.8 + version: 1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.13))(@types/express@4.17.21)(webpack@5.99.8(esbuild@0.19.12)) + "@rspack/core": + specifier: 1.2.8 + version: 1.2.8(@swc/helpers@0.5.13) + axios: + specifier: ^1.6.8 + version: 1.9.0 + concurrently: + specifier: ^9.1.2 + version: 9.1.2 + drizzle-seed: + specifier: ^0.3.1 + version: 0.3.1(drizzle-orm@0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0)) + nock: + specifier: ^13.5.4 + version: 13.5.6 + typescript: + specifier: ^5.3.3 + version: 5.8.3 + wait-on: + specifier: ^8.0.2 + version: 8.0.3 + zod: + specifier: ^3.24.4 + version: 3.24.4 + +packages: + "@asteasolutions/zod-to-openapi@5.5.0": + resolution: + { + integrity: sha512-d5HwrvM6dOKr3XdeF+DmashGvfEc+1oiEfbscugsiwSTrFtuMa7ETpW9sTNnVgn+hJaz+PRxPQUYD7q9/5dUig==, + } + peerDependencies: + zod: ^3.20.2 + + "@crosspost/scheduler-sdk@0.1.1": + resolution: + { + integrity: sha512-Gx49VVk7KJfht3cti2/B51sor0r2pAAJjNmyQ9/m+ScMdfnJ/SOpaJ2D+KXWjxO/41mXKeSb/h0p2VDvWAusYA==, + } + + "@curatedotfun/types@0.0.5": + resolution: + { + integrity: sha512-thb89PXZHEA2BkVvRbA6b2imiglNDVzPOrdUZswF7q/tsnxGoOCwg7B1u6Y3YrajF7IdWto+TzfNnXUSadjWrA==, + } + + "@discoveryjs/json-ext@0.5.7": + resolution: + { + integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==, + } + engines: { node: ">=10.0.0" } + + "@drizzle-team/brocli@0.10.2": + resolution: + { + integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==, + } + + "@esbuild-kit/core-utils@3.3.2": + resolution: + { + integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==, + } + deprecated: "Merged into tsx: https://tsx.is" + + "@esbuild-kit/esm-loader@2.6.5": + resolution: + { + integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==, + } + deprecated: "Merged into tsx: https://tsx.is" + + "@esbuild/aix-ppc64@0.19.12": + resolution: + { + integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [aix] + + "@esbuild/android-arm64@0.17.19": + resolution: + { + integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [android] + + "@esbuild/android-arm64@0.18.20": + resolution: + { + integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [android] + + "@esbuild/android-arm64@0.19.12": + resolution: + { + integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [android] + + "@esbuild/android-arm@0.17.19": + resolution: + { + integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [android] + + "@esbuild/android-arm@0.18.20": + resolution: + { + integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [android] + + "@esbuild/android-arm@0.19.12": + resolution: + { + integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [android] + + "@esbuild/android-x64@0.17.19": + resolution: + { + integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [android] + + "@esbuild/android-x64@0.18.20": + resolution: + { + integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [android] + + "@esbuild/android-x64@0.19.12": + resolution: + { + integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [android] + + "@esbuild/darwin-arm64@0.17.19": + resolution: + { + integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [darwin] + + "@esbuild/darwin-arm64@0.18.20": + resolution: + { + integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [darwin] + + "@esbuild/darwin-arm64@0.19.12": + resolution: + { + integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [darwin] + + "@esbuild/darwin-x64@0.17.19": + resolution: + { + integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [darwin] + + "@esbuild/darwin-x64@0.18.20": + resolution: + { + integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [darwin] + + "@esbuild/darwin-x64@0.19.12": + resolution: + { + integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [darwin] + + "@esbuild/freebsd-arm64@0.17.19": + resolution: + { + integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [freebsd] + + "@esbuild/freebsd-arm64@0.18.20": + resolution: + { + integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [freebsd] + + "@esbuild/freebsd-arm64@0.19.12": + resolution: + { + integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [freebsd] + + "@esbuild/freebsd-x64@0.17.19": + resolution: + { + integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [freebsd] + + "@esbuild/freebsd-x64@0.18.20": + resolution: + { + integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [freebsd] + + "@esbuild/freebsd-x64@0.19.12": + resolution: + { + integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [freebsd] + + "@esbuild/linux-arm64@0.17.19": + resolution: + { + integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [linux] + + "@esbuild/linux-arm64@0.18.20": + resolution: + { + integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [linux] + + "@esbuild/linux-arm64@0.19.12": + resolution: + { + integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [linux] + + "@esbuild/linux-arm@0.17.19": + resolution: + { + integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [linux] + + "@esbuild/linux-arm@0.18.20": + resolution: + { + integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [linux] + + "@esbuild/linux-arm@0.19.12": + resolution: + { + integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==, + } + engines: { node: ">=12" } + cpu: [arm] + os: [linux] + + "@esbuild/linux-ia32@0.17.19": + resolution: + { + integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [linux] + + "@esbuild/linux-ia32@0.18.20": + resolution: + { + integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [linux] + + "@esbuild/linux-ia32@0.19.12": + resolution: + { + integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [linux] + + "@esbuild/linux-loong64@0.17.19": + resolution: + { + integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==, + } + engines: { node: ">=12" } + cpu: [loong64] + os: [linux] + + "@esbuild/linux-loong64@0.18.20": + resolution: + { + integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==, + } + engines: { node: ">=12" } + cpu: [loong64] + os: [linux] + + "@esbuild/linux-loong64@0.19.12": + resolution: + { + integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==, + } + engines: { node: ">=12" } + cpu: [loong64] + os: [linux] + + "@esbuild/linux-mips64el@0.17.19": + resolution: + { + integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==, + } + engines: { node: ">=12" } + cpu: [mips64el] + os: [linux] + + "@esbuild/linux-mips64el@0.18.20": + resolution: + { + integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==, + } + engines: { node: ">=12" } + cpu: [mips64el] + os: [linux] + + "@esbuild/linux-mips64el@0.19.12": + resolution: + { + integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==, + } + engines: { node: ">=12" } + cpu: [mips64el] + os: [linux] + + "@esbuild/linux-ppc64@0.17.19": + resolution: + { + integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [linux] + + "@esbuild/linux-ppc64@0.18.20": + resolution: + { + integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [linux] + + "@esbuild/linux-ppc64@0.19.12": + resolution: + { + integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==, + } + engines: { node: ">=12" } + cpu: [ppc64] + os: [linux] + + "@esbuild/linux-riscv64@0.17.19": + resolution: + { + integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==, + } + engines: { node: ">=12" } + cpu: [riscv64] + os: [linux] + + "@esbuild/linux-riscv64@0.18.20": + resolution: + { + integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==, + } + engines: { node: ">=12" } + cpu: [riscv64] + os: [linux] + + "@esbuild/linux-riscv64@0.19.12": + resolution: + { + integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==, + } + engines: { node: ">=12" } + cpu: [riscv64] + os: [linux] + + "@esbuild/linux-s390x@0.17.19": + resolution: + { + integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==, + } + engines: { node: ">=12" } + cpu: [s390x] + os: [linux] + + "@esbuild/linux-s390x@0.18.20": + resolution: + { + integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==, + } + engines: { node: ">=12" } + cpu: [s390x] + os: [linux] + + "@esbuild/linux-s390x@0.19.12": + resolution: + { + integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==, + } + engines: { node: ">=12" } + cpu: [s390x] + os: [linux] + + "@esbuild/linux-x64@0.17.19": + resolution: + { + integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [linux] + + "@esbuild/linux-x64@0.18.20": + resolution: + { + integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [linux] + + "@esbuild/linux-x64@0.19.12": + resolution: + { + integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [linux] + + "@esbuild/netbsd-x64@0.17.19": + resolution: + { + integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [netbsd] + + "@esbuild/netbsd-x64@0.18.20": + resolution: + { + integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [netbsd] + + "@esbuild/netbsd-x64@0.19.12": + resolution: + { + integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [netbsd] + + "@esbuild/openbsd-x64@0.17.19": + resolution: + { + integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [openbsd] + + "@esbuild/openbsd-x64@0.18.20": + resolution: + { + integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [openbsd] + + "@esbuild/openbsd-x64@0.19.12": + resolution: + { + integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [openbsd] + + "@esbuild/sunos-x64@0.17.19": + resolution: + { + integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [sunos] + + "@esbuild/sunos-x64@0.18.20": + resolution: + { + integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [sunos] + + "@esbuild/sunos-x64@0.19.12": + resolution: + { + integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [sunos] + + "@esbuild/win32-arm64@0.17.19": + resolution: + { + integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [win32] + + "@esbuild/win32-arm64@0.18.20": + resolution: + { + integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [win32] + + "@esbuild/win32-arm64@0.19.12": + resolution: + { + integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==, + } + engines: { node: ">=12" } + cpu: [arm64] + os: [win32] + + "@esbuild/win32-ia32@0.17.19": + resolution: + { + integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [win32] + + "@esbuild/win32-ia32@0.18.20": + resolution: + { + integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [win32] + + "@esbuild/win32-ia32@0.19.12": + resolution: + { + integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==, + } + engines: { node: ">=12" } + cpu: [ia32] + os: [win32] + + "@esbuild/win32-x64@0.17.19": + resolution: + { + integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [win32] + + "@esbuild/win32-x64@0.18.20": + resolution: + { + integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [win32] + + "@esbuild/win32-x64@0.19.12": + resolution: + { + integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==, + } + engines: { node: ">=12" } + cpu: [x64] + os: [win32] + + "@hapi/hoek@9.3.0": + resolution: + { + integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==, + } + + "@hapi/topo@5.1.0": + resolution: + { + integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==, + } + + "@hono/node-server@1.14.1": + resolution: + { + integrity: sha512-vmbuM+HPinjWzPe7FFPWMMQMsbKE9gDPhaH0FFdqbGpkT5lp++tcWDTxwBl5EgS5y6JVgIaCdjeHRfQ4XRBRjQ==, + } + engines: { node: ">=18.14.1" } + peerDependencies: + hono: ^4 + + "@hono/zod-openapi@0.9.10": + resolution: + { + integrity: sha512-v/b/z0qPxDo952gjRyhJ0n9ifbPoIluR2KmXDL20np0hj99+XvakoIHK5/T/3+hUmXlTj1Kn3TiGsSV6hwZesg==, + } + engines: { node: ">=16.0.0" } + peerDependencies: + hono: ">=3.11.3" + zod: 3.* + + "@hono/zod-validator@0.2.1": + resolution: + { + integrity: sha512-HFoxln7Q6JsE64qz2WBS28SD33UB2alp3aRKmcWnNLDzEL1BLsWfbdX6e1HIiUprHYTIXf5y7ax8eYidKUwyaA==, + } + peerDependencies: + hono: ">=3.9.0" + zod: ^3.19.1 + + "@hono/zod-validator@0.5.0": + resolution: + { + integrity: sha512-ds5bW6DCgAnNHP33E3ieSbaZFd5dkV52ZjyaXtGoR06APFrCtzAsKZxTHwOrJNBdXsi0e5wNwo5L4nVEVnJUdg==, + } + peerDependencies: + hono: ">=3.9.0" + zod: ^3.19.1 + + "@isaacs/cliui@8.0.2": + resolution: + { + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + } + engines: { node: ">=12" } + + "@jridgewell/gen-mapping@0.3.8": + resolution: + { + integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/resolve-uri@3.1.2": + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/set-array@1.2.1": + resolution: + { + integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/source-map@0.3.6": + resolution: + { + integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==, + } + + "@jridgewell/sourcemap-codec@1.5.0": + resolution: + { + integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==, + } + + "@jridgewell/trace-mapping@0.3.25": + resolution: + { + integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==, + } + + "@jsonjoy.com/base64@1.1.2": + resolution: + { + integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==, + } + engines: { node: ">=10.0" } + peerDependencies: + tslib: "2" + + "@jsonjoy.com/json-pack@1.2.0": + resolution: + { + integrity: sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA==, + } + engines: { node: ">=10.0" } + peerDependencies: + tslib: "2" + + "@jsonjoy.com/util@1.6.0": + resolution: + { + integrity: sha512-sw/RMbehRhN68WRtcKCpQOPfnH6lLP4GJfqzi3iYej8tnzpZUDr6UkZYJjcjjC0FWEJOJbyM3PTIwxucUmDG2A==, + } + engines: { node: ">=10.0" } + peerDependencies: + tslib: "2" + + "@leichtgewicht/ip-codec@2.0.5": + resolution: + { + integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==, + } + + "@modern-js/node-bundle-require@2.65.1": + resolution: + { + integrity: sha512-XpEkciVEfDbkkLUI662ZFlI9tXsUQtLXk4NRJDBGosNnk9uL2XszmC8sKsdCSLK8AYuPW2w6MTVWuJsOR0EU8A==, + } + + "@modern-js/utils@2.65.1": + resolution: + { + integrity: sha512-HrChf19F+6nALo5XPra8ycjhXGQfGi23+S7Y2FLfTKe8vaNnky8duT/XvRWpbS4pp3SQj8ryO8m/qWSsJ1Rogw==, + } + + "@module-federation/bridge-react-webpack-plugin@0.13.1": + resolution: + { + integrity: sha512-3RgGd8KcRw5vibnxWa1NUWwfb0tKwn8OvHeQ4GFKzMvDLm+QpCgQd9LeTEBP38wZgGXVtIJR3y5FPnufWswFKw==, + } + + "@module-federation/cli@0.13.1": + resolution: + { + integrity: sha512-ej7eZTVUiRMor37pkl2y3hbXwcaNvPgbZJVO+hb2c7cKBjWto7AndgR5qcKpcXXXlhbGwtnI+VrgldruKC+AqQ==, + } + engines: { node: ">=16.0.0" } + hasBin: true + + "@module-federation/data-prefetch@0.13.1": + resolution: + { + integrity: sha512-hj3R72rRyune4fb4V4OFmo1Rfa9T9u0so2Q4vt69frPc2NV2FPPJkIvHGs/geGTLOgt4nn7OH1/ukmR3wWvSuA==, + } + peerDependencies: + react: ">=16.9.0" + react-dom: ">=16.9.0" + + "@module-federation/dts-plugin@0.13.1": + resolution: + { + integrity: sha512-PQMs57h9s5pCkLWZ0IyDGCcac4VZ+GgJE40pAWrOQ+/AgTC+WFyAT16M7PsRENS57Qed4wWQwgfOjS9zmfxKJA==, + } + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + vue-tsc: + optional: true + + "@module-federation/enhanced@0.13.1": + resolution: + { + integrity: sha512-jbbk68RnvNmusGGcXNXVDJAzJOFB/hV+RVV2wWNWmBOVkDZPiWj7aFb0cJAwc9EYZbPel3QzRitZJ73+SaH1IA==, + } + hasBin: true + peerDependencies: + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + webpack: + optional: true + + "@module-federation/error-codes@0.11.4": + resolution: + { + integrity: sha512-WugZdcNbNVTKuxuArGfnRW1R+siNgMBhad451HniyCG+SjlS0HEO9zIDuVP12l3xJsiTHgLqyutYEvunQ5O1aQ==, + } + + "@module-federation/error-codes@0.13.1": + resolution: + { + integrity: sha512-azgGDBnFRfqlivHOl96ZjlFUFlukESz2Rnnz/pINiSqoBBNjUE0fcAZP4X6jgrVITuEg90YkruZa7pW9I3m7Uw==, + } + + "@module-federation/error-codes@0.8.4": + resolution: + { + integrity: sha512-55LYmrDdKb4jt+qr8qE8U3al62ZANp3FhfVaNPOaAmdTh0jHdD8M3yf5HKFlr5xVkVO4eV/F/J2NCfpbh+pEXQ==, + } + + "@module-federation/inject-external-runtime-core-plugin@0.13.1": + resolution: + { + integrity: sha512-K+ltl2AqVqlsvEds1PffCMLDMlC5lvdkyMXOfcZO6u0O4dZlaTtZbT32NchY7kIEvEsj0wyYhX1i2DnsbHpUBw==, + } + peerDependencies: + "@module-federation/runtime-tools": 0.13.1 + + "@module-federation/managers@0.13.1": + resolution: + { + integrity: sha512-vQMrqSFQxjSuGgByC2wcY7zUTmVfhzCyDpnCCq0PtaozK8DcgwsEMzrAT3dbg8ifGUmse/xiRIbTmS5leKK+UQ==, + } + + "@module-federation/manifest@0.13.1": + resolution: + { + integrity: sha512-XcuFtLycoR0jQj8op+w20V5n459blNBvGXe//AwkEppQERk8SM5kQgIPvOVbZ8zGx7tl/F2HGTDVZlhDiKzIew==, + } + + "@module-federation/node@2.7.2": + resolution: + { + integrity: sha512-NRVF56J0iyWRfCbpW6+HYis2sj8BBNVp8H5jHkIM/NgZt1Ck9Nyd5BVcL/Jys8ku44v8tdDQdnlzl/BjGHp9Yg==, + } + peerDependencies: + next: "*" + react: ^16||^17||^18||^19 + react-dom: ^16||^17||^18||^19 + webpack: ^5.40.0 + peerDependenciesMeta: + next: + optional: true + react: + optional: true + react-dom: + optional: true + + "@module-federation/rspack@0.13.1": + resolution: + { + integrity: sha512-+qz8sW99SYDULajjjn4rSNaI4rogEPVOZsBvT6y0PdfpMD/wZxvh5HlV0u7+5DgWEjgrdm0cJHBHChlIbV/CMQ==, + } + peerDependencies: + "@rspack/core": ">=0.7" + typescript: ^4.9.0 || ^5.0.0 + vue-tsc: ">=1.0.24" + peerDependenciesMeta: + typescript: + optional: true + vue-tsc: + optional: true + + "@module-federation/runtime-core@0.11.4": + resolution: + { + integrity: sha512-+n2fWUPj6cCeHXmChZ35RFyNONfBEcNgQ3o7KEmxOBJ6bRh1vr3AO2OPRPYr5WHcvAyjny+l/xhi+sZPNV3uOQ==, + } + + "@module-federation/runtime-core@0.13.1": + resolution: + { + integrity: sha512-TfyKfkSAentKeuvSsAItk8s5tqQSMfIRTPN2e1aoaq/kFhE+7blps719csyWSX5Lg5Es7WXKMsXHy40UgtBtuw==, + } + + "@module-federation/runtime-tools@0.13.1": + resolution: + { + integrity: sha512-GEF1pxqLc80osIMZmE8j9UKZSaTm2hX2lql8tgIH/O9yK4wnF06k6LL5Ah+wJt+oJv6Dj55ri/MoxMP4SXoPNA==, + } + + "@module-federation/runtime-tools@0.8.4": + resolution: + { + integrity: sha512-fjVOsItJ1u5YY6E9FnS56UDwZgqEQUrWFnouRiPtK123LUuqUI9FH4redZoKWlE1PB0ir1Z3tnqy8eFYzPO38Q==, + } + + "@module-federation/runtime@0.11.4": + resolution: + { + integrity: sha512-pUfhsa3iYoXBV3CsUfBJN04Cvckj9gBbs8+sLsYiWxxU+cJYNiJpco0iKxRX1/60O+RAH8fAaNq5ilz2qc204A==, + } + + "@module-federation/runtime@0.13.1": + resolution: + { + integrity: sha512-ZHnYvBquDm49LiHfv6fgagMo/cVJneijNJzfPh6S0CJrPS2Tay1bnTXzy8VA5sdIrESagYPaskKMGIj7YfnPug==, + } + + "@module-federation/runtime@0.8.4": + resolution: + { + integrity: sha512-yZeZ7z2Rx4gv/0E97oLTF3V6N25vglmwXGgoeju/W2YjsFvWzVtCDI7zRRb0mJhU6+jmSM8jP1DeQGbea/AiZQ==, + } + + "@module-federation/sdk@0.11.4": + resolution: + { + integrity: sha512-23Poajva/+wye8+66NvEiL/dJDUahOjEgxljLvzmxQXi9x5hdrfJvBDIwLtzyewZ+vA5Nzpwz35sSzEOyPJUqg==, + } + + "@module-federation/sdk@0.13.1": + resolution: + { + integrity: sha512-bmf2FGQ0ymZuxYnw9bIUfhV3y6zDhaqgydEjbl4msObKMLGXZqhse2pTIIxBFpIxR1oONKX/y2FAolDCTlWKiw==, + } + + "@module-federation/sdk@0.8.4": + resolution: + { + integrity: sha512-waABomIjg/5m1rPDBWYG4KUhS5r7OUUY7S+avpaVIY/tkPWB3ibRDKy2dNLLAMaLKq0u+B1qIdEp4NIWkqhqpg==, + } + + "@module-federation/third-party-dts-extractor@0.13.1": + resolution: + { + integrity: sha512-0kWSupoC0aTxFjJZE5TVPNsoZ9kBsZhkvRxFnUW2vDYLgtvgs2dIrDlNlIXYiS/MaQCNHGyvdNepbchKQiwFaw==, + } + + "@module-federation/webpack-bundler-runtime@0.13.1": + resolution: + { + integrity: sha512-QSuSIGa09S8mthbB1L6xERqrz+AzPlHR6D7RwAzssAc+IHf40U6NiTLPzUqp9mmKDhC5Tm0EISU0ZHNeJpnpBQ==, + } + + "@module-federation/webpack-bundler-runtime@0.8.4": + resolution: + { + integrity: sha512-HggROJhvHPUX7uqBD/XlajGygMNM1DG0+4OAkk8MBQe4a18QzrRNzZt6XQbRTSG4OaEoyRWhQHvYD3Yps405tQ==, + } + + "@near-js/accounts@1.4.1": + resolution: + { + integrity: sha512-ni3QT9H3NdrbVVKyx56yvz93r89Dvpc/vgVtiIK2OdXjkK6jcj+UKMDRQ6F7rd9qJOInLkHZbVBtcR6j1CXLjw==, + } + + "@near-js/crypto@1.4.2": + resolution: + { + integrity: sha512-GRfchsyfWvSAPA1gI9hYhw5FH94Ac1BUo+Cmp5rSJt/V0K3xVzCWgOQxvv4R3kDnWjaXJEuAmpEEnr4Bp3FWrA==, + } + + "@near-js/keystores-browser@0.2.2": + resolution: + { + integrity: sha512-Pxqm7WGtUu6zj32vGCy9JcEDpZDSB5CCaLQDTQdF3GQyL0flyRv2I/guLAgU5FLoYxU7dJAX9mslJhPW7P2Bfw==, + } + + "@near-js/keystores-node@0.1.2": + resolution: + { + integrity: sha512-MWLvTszZOVziiasqIT/LYNhUyWqOJjDGlsthOsY6dTL4ZcXjjmhmzrbFydIIeQr+CcEl5wukTo68ORI9JrHl6g==, + } + + "@near-js/keystores@0.2.2": + resolution: + { + integrity: sha512-DLhi/3a4qJUY+wgphw2Jl4S+L0AKsUYm1mtU0WxKYV5OBwjOXvbGrXNfdkheYkfh3nHwrQgtjvtszX6LrRXLLw==, + } + + "@near-js/providers@1.0.3": + resolution: + { + integrity: sha512-VJMboL14R/+MGKnlhhE3UPXCGYvMd1PpvF9OqZ9yBbulV7QVSIdTMfY4U1NnDfmUC2S3/rhAEr+3rMrIcNS7Fg==, + } + + "@near-js/signers@0.2.2": + resolution: + { + integrity: sha512-M6ib+af9zXAPRCjH2RyIS0+RhCmd9gxzCeIkQ+I2A3zjgGiEDkBZbYso9aKj8Zh2lPKKSH7h+u8JGymMOSwgyw==, + } + + "@near-js/transactions@1.3.3": + resolution: + { + integrity: sha512-1AXD+HuxlxYQmRTLQlkVmH+RAmV3HwkAT8dyZDu+I2fK/Ec9BQHXakOJUnOBws3ihF+akQhamIBS5T0EXX/Ylw==, + } + + "@near-js/types@0.3.1": + resolution: + { + integrity: sha512-8qIA7ynAEAuVFNAQc0cqz2xRbfyJH3PaAG5J2MgPPhD18lu/tCGd6pzYg45hjhtiJJRFDRjh/FUWKS+ZiIIxUw==, + } + + "@near-js/utils@1.1.0": + resolution: + { + integrity: sha512-5XWRq7xpu8Wud9pRXe2U347KXyi0mXofedUY2DQ9TaqiZUcMIaN9xj7DbCs2v6dws3pJyYrT1KWxeNp5fSaY3w==, + } + + "@near-js/wallet-account@1.3.3": + resolution: + { + integrity: sha512-GDzg/Kz0GBYF7tQfyQQQZ3vviwV8yD+8F2lYDzsWJiqIln7R1ov0zaXN4Tii86TeS21KPn2hHAsVu3Y4txa8OQ==, + } + + "@noble/curves@1.8.1": + resolution: + { + integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==, + } + engines: { node: ^14.21.3 || >=16 } + + "@noble/hashes@1.3.3": + resolution: + { + integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==, + } + engines: { node: ">= 16" } + + "@noble/hashes@1.7.1": + resolution: + { + integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==, + } + engines: { node: ^14.21.3 || >=16 } + + "@notionhq/client@2.3.0": + resolution: + { + integrity: sha512-l7WqTCpQqC+HibkB9chghONQTYcxNQT0/rOJemBfmuKQRTu2vuV8B3yA395iKaUdDo7HI+0KvQaz9687Xskzkw==, + } + engines: { node: ">=12" } + + "@petamoriken/float16@3.9.2": + resolution: + { + integrity: sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==, + } + + "@pkgjs/parseargs@0.11.0": + resolution: + { + integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, + } + engines: { node: ">=14" } + + "@polka/url@1.0.0-next.29": + resolution: + { + integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==, + } + + "@rspack/binding-darwin-arm64@1.2.8": + resolution: + { + integrity: sha512-bDlrlroY3iMlzna/3i1gD6eRmhJW2zRyC3Ov6aR1micshVQ9RteigYZWkjZuQfyC5Z8dCcLUQJVojz+pqp0JXg==, + } + cpu: [arm64] + os: [darwin] + + "@rspack/binding-darwin-x64@1.2.8": + resolution: + { + integrity: sha512-0/qOVbMuzZ+WbtDa4TbH46R4vph/W6MHcXbrXDO+vpdTMFDVJ64DnZXT7aqvGcY+7vTCIGm0GT+6ooR4KaIX8A==, + } + cpu: [x64] + os: [darwin] + + "@rspack/binding-linux-arm64-gnu@1.2.8": + resolution: + { + integrity: sha512-En/SMl45s19iUVb1/ZDFQvFDxIjnlfk7yqV3drMWWAL5HSgksNejaTIFTO52aoohIBbmwuk5wSGcbU0G0IFiPg==, + } + cpu: [arm64] + os: [linux] + + "@rspack/binding-linux-arm64-musl@1.2.8": + resolution: + { + integrity: sha512-N1oZsXfJ9VLLcK7p1PS65cxLYQCZ7iqHW2OP6Ew2+hlz/d1hzngxgzrtZMCXFOHXDvTzVu5ff6jGS2v7+zv2tA==, + } + cpu: [arm64] + os: [linux] + + "@rspack/binding-linux-x64-gnu@1.2.8": + resolution: + { + integrity: sha512-BdPaepoLKuaVwip4QK/nGqNi1xpbCWSxiycPbKRrGqKgt/QGihxxFgiqr4EpWQVIJNIMy4nCsg4arO0+H1KWGQ==, + } + cpu: [x64] + os: [linux] + + "@rspack/binding-linux-x64-musl@1.2.8": + resolution: + { + integrity: sha512-GFv0Bod268OcXIcjeLoPlK0oz8rClEIxIRFkz+ejhbvfCwRJ+Fd+EKaaKQTBfZQujPqc0h2GctIF25nN5pFTmA==, + } + cpu: [x64] + os: [linux] + + "@rspack/binding-win32-arm64-msvc@1.2.8": + resolution: + { + integrity: sha512-aEU+uJdbvJJGrzzAsjbjrPeNbG/bcG8JoXK2kSsUB+/sWHTIkHX0AQ3oX3aV/lcLKgZWrUxLAfLoCXEnIHMEyQ==, + } + cpu: [arm64] + os: [win32] + + "@rspack/binding-win32-ia32-msvc@1.2.8": + resolution: + { + integrity: sha512-GHYzNOSoiLyG9elLTmMqADJMQzjll+co4irp5AgZ+KHG9EVq0qEHxDqDIJxZnUA15U8JDvCgo6YAo3T0BFEL0Q==, + } + cpu: [ia32] + os: [win32] + + "@rspack/binding-win32-x64-msvc@1.2.8": + resolution: + { + integrity: sha512-EigKLhKLH1kfv1e/ZgXuSKlIjkbyneJtiLbNDz7EeEVFGV1XMM6bsCea1sb2WOxsPYiOX4Q5JmR1j1KGrZS/LA==, + } + cpu: [x64] + os: [win32] + + "@rspack/binding@1.2.8": + resolution: + { + integrity: sha512-T3FMB3N9P1AbSAryfkSRJkPtmeSYs/Gj9zUZoPz1ckPEIcWZmpUOQbJylldjbw5waxtCL1haHNbi0pcSvxiaJw==, + } + + "@rspack/cli@1.2.8": + resolution: + { + integrity: sha512-xPNLJCnQt8B1j7i4T67MmVzYxJfx0c+gEhHozfVfpg/2PwuR9PBMnwo+53wJkUJk+ctJ+eMLQomDZymq4j26nA==, + } + hasBin: true + peerDependencies: + "@rspack/core": ^1.0.0-alpha || ^1.x + "@rspack/tracing": ^1.x + peerDependenciesMeta: + "@rspack/tracing": + optional: true + + "@rspack/core@1.2.8": + resolution: + { + integrity: sha512-ppj3uQQtkhgrYDLrUqb33YbpNEZCpAudpfVuOHGsvUrAnu1PijbfJJymoA5ZvUhM+HNMvPI5D1ie97TXyb0UVg==, + } + engines: { node: ">=16.0.0" } + peerDependencies: + "@rspack/tracing": ^1.x + "@swc/helpers": ">=0.5.1" + peerDependenciesMeta: + "@rspack/tracing": + optional: true + "@swc/helpers": + optional: true + + "@rspack/dev-server@1.0.10": + resolution: + { + integrity: sha512-iDsEtP0jNHRm4LJxL00QFTlOuqkdxIFxnd69h0KrFadmtxAWiDLIe4vYdZXWF74w4MezsJFx6dB2nUM/Ok8utA==, + } + engines: { node: ">= 18.12.0" } + peerDependencies: + "@rspack/core": "*" + + "@rspack/lite-tapable@1.0.1": + resolution: + { + integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==, + } + engines: { node: ">=16.0.0" } + + "@scure/base@1.2.5": + resolution: + { + integrity: sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==, + } + + "@sideway/address@4.1.5": + resolution: + { + integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==, + } + + "@sideway/formula@3.0.1": + resolution: + { + integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==, + } + + "@sideway/pinpoint@2.0.0": + resolution: + { + integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==, + } + + "@sinclair/typebox@0.32.35": + resolution: + { + integrity: sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA==, + } + + "@swc/helpers@0.5.13": + resolution: + { + integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==, + } + + "@types/async-retry@1.4.9": + resolution: + { + integrity: sha512-s1ciZQJzRh3708X/m3vPExr5KJlzlZJvXsKpbtE2luqNcbROr64qU+3KpJsYHqWMeaxI839OvXf9PrUSw1Xtyg==, + } + + "@types/body-parser@1.19.5": + resolution: + { + integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==, + } + + "@types/bonjour@3.5.13": + resolution: + { + integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==, + } + + "@types/connect-history-api-fallback@1.5.4": + resolution: + { + integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==, + } + + "@types/connect@3.4.38": + resolution: + { + integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==, + } + + "@types/eslint-scope@3.7.7": + resolution: + { + integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==, + } + + "@types/eslint@9.6.1": + resolution: + { + integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==, + } + + "@types/estree@1.0.7": + resolution: + { + integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==, + } + + "@types/express-serve-static-core@4.19.6": + resolution: + { + integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==, + } + + "@types/express-serve-static-core@5.0.6": + resolution: + { + integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==, + } + + "@types/express@4.17.21": + resolution: + { + integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==, + } + + "@types/http-errors@2.0.4": + resolution: + { + integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==, + } + + "@types/http-proxy@1.17.16": + resolution: + { + integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==, + } + + "@types/json-schema@7.0.15": + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, + } + + "@types/lodash@4.17.16": + resolution: + { + integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==, + } + + "@types/mime@1.3.5": + resolution: + { + integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==, + } + + "@types/node-fetch@2.6.12": + resolution: + { + integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==, + } + + "@types/node-forge@1.3.11": + resolution: + { + integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==, + } + + "@types/node@22.15.17": + resolution: + { + integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==, + } + + "@types/pg@8.15.1": + resolution: + { + integrity: sha512-YKHrkGWBX5+ivzvOQ66I0fdqsQTsvxqM0AGP2i0XrVZ9DP5VA/deEbTf7VuLPGpY7fJB9uGbkZ6KjVhuHcrTkQ==, + } + + "@types/qs@6.9.18": + resolution: + { + integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==, + } + + "@types/range-parser@1.2.7": + resolution: + { + integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==, + } + + "@types/retry@0.12.0": + resolution: + { + integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==, + } + + "@types/retry@0.12.2": + resolution: + { + integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==, + } + + "@types/retry@0.12.5": + resolution: + { + integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==, + } + + "@types/semver@7.5.8": + resolution: + { + integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==, + } + + "@types/send@0.17.4": + resolution: + { + integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==, + } + + "@types/serve-index@1.9.4": + resolution: + { + integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==, + } + + "@types/serve-static@1.15.7": + resolution: + { + integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==, + } + + "@types/sockjs@0.3.36": + resolution: + { + integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==, + } + + "@types/ws@8.18.1": + resolution: + { + integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==, + } + + "@webassemblyjs/ast@1.14.1": + resolution: + { + integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==, + } + + "@webassemblyjs/floating-point-hex-parser@1.13.2": + resolution: + { + integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==, + } + + "@webassemblyjs/helper-api-error@1.13.2": + resolution: + { + integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==, + } + + "@webassemblyjs/helper-buffer@1.14.1": + resolution: + { + integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==, + } + + "@webassemblyjs/helper-numbers@1.13.2": + resolution: + { + integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==, + } + + "@webassemblyjs/helper-wasm-bytecode@1.13.2": + resolution: + { + integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==, + } + + "@webassemblyjs/helper-wasm-section@1.14.1": + resolution: + { + integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==, + } + + "@webassemblyjs/ieee754@1.13.2": + resolution: + { + integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==, + } + + "@webassemblyjs/leb128@1.13.2": + resolution: + { + integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==, + } + + "@webassemblyjs/utf8@1.13.2": + resolution: + { + integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==, + } + + "@webassemblyjs/wasm-edit@1.14.1": + resolution: + { + integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==, + } + + "@webassemblyjs/wasm-gen@1.14.1": + resolution: + { + integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==, + } + + "@webassemblyjs/wasm-opt@1.14.1": + resolution: + { + integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==, + } + + "@webassemblyjs/wasm-parser@1.14.1": + resolution: + { + integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==, + } + + "@webassemblyjs/wast-printer@1.14.1": + resolution: + { + integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==, + } + + "@xtuc/ieee754@1.2.0": + resolution: + { + integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==, + } + + "@xtuc/long@4.2.2": + resolution: + { + integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==, + } + + accepts@1.3.8: + resolution: + { + integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==, + } + engines: { node: ">= 0.6" } + + acorn-walk@8.3.4: + resolution: + { + integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, + } + engines: { node: ">=0.4.0" } + + acorn@8.14.1: + resolution: + { + integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==, + } + engines: { node: ">=0.4.0" } + hasBin: true + + adm-zip@0.5.16: + resolution: + { + integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==, + } + engines: { node: ">=12.0" } + + agent-twitter-client@0.0.16: + resolution: + { + integrity: sha512-Clgb/N2LXoGMlId6GDUaaR05eJ0PqSifM6wikl/FiQ2+3+6I2ZhZB7KRulc8R4xvYFe6h0wNWe6FZiF48r124w==, + } + + ajv-formats@2.1.1: + resolution: + { + integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==, + } + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@5.1.0: + resolution: + { + integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==, + } + peerDependencies: + ajv: ^8.8.2 + + ajv@8.17.1: + resolution: + { + integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==, + } + + ansi-colors@4.1.3: + resolution: + { + integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, + } + engines: { node: ">=6" } + + ansi-html-community@0.0.8: + resolution: + { + integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==, + } + engines: { "0": node >= 0.8.0 } + hasBin: true + + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } + + ansi-regex@6.1.0: + resolution: + { + integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==, + } + engines: { node: ">=12" } + + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } + + ansi-styles@6.2.1: + resolution: + { + integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==, + } + engines: { node: ">=12" } + + anymatch@3.1.3: + resolution: + { + integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, + } + engines: { node: ">= 8" } + + array-flatten@1.1.1: + resolution: + { + integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==, + } + + async-retry@1.3.3: + resolution: + { + integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==, + } + + asynckit@0.4.0: + resolution: + { + integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, + } + + at-least-node@1.0.0: + resolution: + { + integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==, + } + engines: { node: ">= 4.0.0" } + + atomic-sleep@1.0.0: + resolution: + { + integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==, + } + engines: { node: ">=8.0.0" } + + axios@1.9.0: + resolution: + { + integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==, + } + + balanced-match@1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + + batch@0.6.1: + resolution: + { + integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==, + } + + binary-extensions@2.3.0: + resolution: + { + integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, + } + engines: { node: ">=8" } + + bn.js@4.12.2: + resolution: + { + integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==, + } + + body-parser@1.20.3: + resolution: + { + integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==, + } + engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } + + bonjour-service@1.3.0: + resolution: + { + integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==, + } + + borsh@1.0.0: + resolution: + { + integrity: sha512-fSVWzzemnyfF89EPwlUNsrS5swF5CrtiN4e+h0/lLf4dz2he4L3ndM20PS9wj7ICSkXJe/TQUHdaPTq15b1mNQ==, + } + + brace-expansion@2.0.1: + resolution: + { + integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==, + } + + braces@3.0.3: + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, + } + engines: { node: ">=8" } + + brorand@1.1.0: + resolution: + { + integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==, + } + + browserslist@4.24.5: + resolution: + { + integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + + btoa@1.2.1: + resolution: + { + integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==, + } + engines: { node: ">= 0.4.0" } + hasBin: true + + buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, + } + + bundle-name@4.1.0: + resolution: + { + integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==, + } + engines: { node: ">=18" } + + bytes@3.1.2: + resolution: + { + integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, + } + engines: { node: ">= 0.8" } + + cache-content-type@1.0.1: + resolution: + { + integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==, + } + engines: { node: ">= 6.0.0" } + + 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" } + + caniuse-lite@1.0.30001717: + resolution: + { + integrity: sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==, + } + + chalk@3.0.0: + resolution: + { + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==, + } + engines: { node: ">=8" } + + chalk@4.1.2: + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: ">=10" } + + chalk@5.4.1: + resolution: + { + integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + + chokidar@3.6.0: + resolution: + { + integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, + } + engines: { node: ">= 8.10.0" } + + chrome-trace-event@1.0.4: + resolution: + { + integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==, + } + engines: { node: ">=6.0" } + + cli-cursor@5.0.0: + resolution: + { + integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==, + } + engines: { node: ">=18" } + + cli-spinners@2.9.2: + resolution: + { + integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, + } + engines: { node: ">=6" } + + cliui@8.0.1: + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, + } + engines: { node: ">=12" } + + co@4.6.0: + resolution: + { + integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==, + } + engines: { iojs: ">= 1.0.0", node: ">= 0.12.0" } + + 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==, + } + + colorette@2.0.20: + resolution: + { + integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, + } + + combined-stream@1.0.8: + resolution: + { + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, + } + engines: { node: ">= 0.8" } + + commander@11.1.0: + resolution: + { + integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==, + } + engines: { node: ">=16" } + + commander@2.20.3: + resolution: + { + integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, + } + + commander@7.2.0: + resolution: + { + integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==, + } + engines: { node: ">= 10" } + + compressible@2.0.18: + resolution: + { + integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==, + } + engines: { node: ">= 0.6" } + + compression@1.8.0: + resolution: + { + integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==, + } + engines: { node: ">= 0.8.0" } + + concurrently@9.1.2: + resolution: + { + integrity: sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==, + } + engines: { node: ">=18" } + hasBin: true + + connect-history-api-fallback@2.0.0: + resolution: + { + integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==, + } + engines: { node: ">=0.8" } + + content-disposition@0.5.4: + resolution: + { + integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==, + } + engines: { node: ">= 0.6" } + + content-type@1.0.5: + resolution: + { + integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, + } + engines: { node: ">= 0.6" } + + cookie-signature@1.0.6: + resolution: + { + integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==, + } + + cookie@0.7.1: + resolution: + { + integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==, + } + engines: { node: ">= 0.6" } + + cookies@0.9.1: + resolution: + { + integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==, + } + engines: { node: ">= 0.8" } + + core-util-is@1.0.3: + resolution: + { + integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, + } + + cron-parser@4.9.0: + resolution: + { + integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==, + } + engines: { node: ">=12.0.0" } + + cross-spawn@7.0.6: + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, + } + engines: { node: ">= 8" } + + data-uri-to-buffer@4.0.1: + resolution: + { + integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==, + } + engines: { node: ">= 12" } + + date-format@4.0.14: + resolution: + { + integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==, + } + engines: { node: ">=4.0" } + + dateformat@4.6.3: + resolution: + { + integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==, + } + + debug@2.6.9: + resolution: + { + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, + } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: + { + integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==, + } + engines: { node: ">=6.0" } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + deep-equal@1.0.1: + resolution: + { + integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==, + } + + default-browser-id@5.0.0: + resolution: + { + integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==, + } + engines: { node: ">=18" } + + default-browser@5.2.1: + resolution: + { + integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==, + } + engines: { node: ">=18" } + + default-gateway@6.0.3: + resolution: + { + integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==, + } + engines: { node: ">= 10" } + + define-data-property@1.1.4: + resolution: + { + integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, + } + engines: { node: ">= 0.4" } + + define-lazy-prop@3.0.0: + resolution: + { + integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==, + } + engines: { node: ">=12" } + + delayed-stream@1.0.0: + resolution: + { + integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, + } + engines: { node: ">=0.4.0" } + + delegates@1.0.0: + resolution: + { + integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==, + } + + depd@1.1.2: + resolution: + { + integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==, + } + engines: { node: ">= 0.6" } + + depd@2.0.0: + resolution: + { + integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, + } + engines: { node: ">= 0.8" } + + destroy@1.2.0: + resolution: + { + integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==, + } + engines: { node: ">= 0.8", npm: 1.2.8000 || >= 1.4.16 } + + detect-node@2.1.0: + resolution: + { + integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==, + } + + dns-packet@5.6.1: + resolution: + { + integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==, + } + engines: { node: ">=6" } + + dotenv@16.5.0: + resolution: + { + integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==, + } + engines: { node: ">=12" } + + drizzle-kit@0.30.6: + resolution: + { + integrity: sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g==, + } + hasBin: true + + drizzle-orm@0.40.1: + resolution: + { + integrity: sha512-aPNhtiJiPfm3qxz1czrnIDkfvkSdKGXYeZkpG55NPTVI186LmK2fBLMi4dsHpPHlJrZeQ92D322YFPHADBALew==, + } + peerDependencies: + "@aws-sdk/client-rds-data": ">=3" + "@cloudflare/workers-types": ">=4" + "@electric-sql/pglite": ">=0.2.0" + "@libsql/client": ">=0.10.0" + "@libsql/client-wasm": ">=0.10.0" + "@neondatabase/serverless": ">=0.10.0" + "@op-engineering/op-sqlite": ">=2" + "@opentelemetry/api": ^1.4.1 + "@planetscale/database": ">=1" + "@prisma/client": "*" + "@tidbcloud/serverless": "*" + "@types/better-sqlite3": "*" + "@types/pg": "*" + "@types/sql.js": "*" + "@vercel/postgres": ">=0.8.0" + "@xata.io/client": "*" + better-sqlite3: ">=7" + bun-types: "*" + expo-sqlite: ">=14.0.0" + gel: ">=2" + knex: "*" + kysely: "*" + mysql2: ">=2" + pg: ">=8" + postgres: ">=3" + prisma: "*" + sql.js: ">=1" + sqlite3: ">=5" + peerDependenciesMeta: + "@aws-sdk/client-rds-data": + optional: true + "@cloudflare/workers-types": + optional: true + "@electric-sql/pglite": + optional: true + "@libsql/client": + optional: true + "@libsql/client-wasm": + optional: true + "@neondatabase/serverless": + optional: true + "@op-engineering/op-sqlite": + optional: true + "@opentelemetry/api": + optional: true + "@planetscale/database": + optional: true + "@prisma/client": + optional: true + "@tidbcloud/serverless": + optional: true + "@types/better-sqlite3": + optional: true + "@types/pg": + optional: true + "@types/sql.js": + optional: true + "@vercel/postgres": + optional: true + "@xata.io/client": + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + + drizzle-seed@0.3.1: + resolution: + { + integrity: sha512-F/0lgvfOAsqlYoHM/QAGut4xXIOXoE5VoAdv2FIl7DpGYVXlAzKuJO+IphkKUFK3Dz+rFlOsQLnMNrvoQ0cx7g==, + } + peerDependencies: + drizzle-orm: ">=0.36.4" + peerDependenciesMeta: + drizzle-orm: + optional: true + + drizzle-zod@0.7.1: + resolution: + { + integrity: sha512-nZzALOdz44/AL2U005UlmMqaQ1qe5JfanvLujiTHiiT8+vZJTBFhj3pY4Vk+L6UWyKFfNmLhk602Hn4kCTynKQ==, + } + peerDependencies: + drizzle-orm: ">=0.36.0" + zod: ">=3.0.0" + + dunder-proto@1.0.1: + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: ">= 0.4" } + + duplexer@0.1.2: + resolution: + { + integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==, + } + + eastasianwidth@0.2.0: + resolution: + { + integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, + } + + ee-first@1.1.1: + resolution: + { + integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, + } + + electron-to-chromium@1.5.152: + resolution: + { + integrity: sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==, + } + + elliptic@6.6.1: + resolution: + { + integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==, + } + + emoji-regex@10.4.0: + resolution: + { + integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==, + } + + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + emoji-regex@9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + + encodeurl@1.0.2: + resolution: + { + integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==, + } + engines: { node: ">= 0.8" } + + encodeurl@2.0.0: + resolution: + { + integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, + } + engines: { node: ">= 0.8" } + + encoding@0.1.13: + resolution: + { + integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==, + } + + end-of-stream@1.4.4: + resolution: + { + integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==, + } + + enhanced-resolve@5.18.1: + resolution: + { + integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==, + } + engines: { node: ">=10.13.0" } + + env-paths@3.0.0: + resolution: + { + integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + 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-module-lexer@1.7.0: + resolution: + { + integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, + } + + 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" } + + esbuild-register@3.6.0: + resolution: + { + integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==, + } + peerDependencies: + esbuild: ">=0.12 <1" + + esbuild@0.17.19: + resolution: + { + integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==, + } + engines: { node: ">=12" } + hasBin: true + + esbuild@0.18.20: + resolution: + { + integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==, + } + engines: { node: ">=12" } + hasBin: true + + esbuild@0.19.12: + resolution: + { + integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==, + } + engines: { node: ">=12" } + hasBin: true + + escalade@3.2.0: + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, + } + engines: { node: ">=6" } + + escape-html@1.0.3: + resolution: + { + integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, + } + + eslint-scope@5.1.1: + resolution: + { + integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==, + } + engines: { node: ">=8.0.0" } + + esrecurse@4.3.0: + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, + } + engines: { node: ">=4.0" } + + estraverse@4.3.0: + resolution: + { + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, + } + engines: { node: ">=4.0" } + + estraverse@5.3.0: + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: ">=4.0" } + + etag@1.8.1: + resolution: + { + integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, + } + engines: { node: ">= 0.6" } + + eventemitter3@4.0.7: + resolution: + { + integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, + } + + events@3.3.0: + resolution: + { + integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, + } + engines: { node: ">=0.8.x" } + + execa@5.1.1: + resolution: + { + integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==, + } + engines: { node: ">=10" } + + exit-hook@4.0.0: + resolution: + { + integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==, + } + engines: { node: ">=18" } + + expand-tilde@2.0.2: + resolution: + { + integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==, + } + engines: { node: ">=0.10.0" } + + exponential-backoff@3.1.2: + resolution: + { + integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==, + } + + express@4.21.2: + resolution: + { + integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==, + } + engines: { node: ">= 0.10.0" } + + fast-copy@3.0.2: + resolution: + { + integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==, + } + + fast-deep-equal@3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } + + fast-redact@3.5.0: + resolution: + { + integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==, + } + engines: { node: ">=6" } + + fast-safe-stringify@2.1.1: + resolution: + { + integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, + } + + fast-uri@3.0.6: + resolution: + { + integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==, + } + + faye-websocket@0.11.4: + resolution: + { + integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==, + } + engines: { node: ">=0.8.0" } + + fetch-blob@3.2.0: + resolution: + { + integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==, + } + engines: { node: ^12.20 || >= 14.13 } + + fill-range@7.1.1: + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, + } + engines: { node: ">=8" } + + finalhandler@1.3.1: + resolution: + { + integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==, + } + engines: { node: ">= 0.8" } + + find-file-up@2.0.1: + resolution: + { + integrity: sha512-qVdaUhYO39zmh28/JLQM5CoYN9byEOKEH4qfa8K1eNV17W0UUMJ9WgbR/hHFH+t5rcl+6RTb5UC7ck/I+uRkpQ==, + } + engines: { node: ">=8" } + + find-pkg@2.0.0: + resolution: + { + integrity: sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==, + } + engines: { node: ">=8" } + + flatted@3.3.3: + resolution: + { + integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==, + } + + follow-redirects@1.15.9: + resolution: + { + integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==, + } + engines: { node: ">=4.0" } + peerDependencies: + debug: "*" + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: + { + integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, + } + engines: { node: ">=14" } + + form-data@4.0.2: + resolution: + { + integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==, + } + engines: { node: ">= 6" } + + formdata-polyfill@4.0.10: + resolution: + { + integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==, + } + engines: { node: ">=12.20.0" } + + forwarded@0.2.0: + resolution: + { + integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, + } + engines: { node: ">= 0.6" } + + fresh@0.5.2: + resolution: + { + integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==, + } + engines: { node: ">= 0.6" } + + fs-extra@8.1.0: + resolution: + { + integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==, + } + engines: { node: ">=6 <7 || >=8" } + + fs-extra@9.1.0: + resolution: + { + integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==, + } + engines: { node: ">=10" } + + fsevents@2.3.3: + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + function-bind@1.1.2: + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } + + gel@2.1.0: + resolution: + { + integrity: sha512-HCeRqInCt6BjbMmeghJ6BKeYwOj7WJT5Db6IWWAA3IMUUa7or7zJfTUEkUWCxiOtoXnwnm96sFK9Fr47Yh2hOA==, + } + engines: { node: ">= 18.0.0" } + hasBin: true + + generate-function@2.3.1: + resolution: + { + integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==, + } + + generate-object-property@1.2.0: + resolution: + { + integrity: sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==, + } + + get-caller-file@2.0.5: + resolution: + { + integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, + } + engines: { node: 6.* || 8.* || >= 10.* } + + get-east-asian-width@1.3.0: + resolution: + { + integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==, + } + engines: { node: ">=18" } + + 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-stream@6.0.1: + resolution: + { + integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, + } + engines: { node: ">=10" } + + get-tsconfig@4.10.0: + resolution: + { + integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==, + } + + glob-parent@5.1.2: + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: ">= 6" } + + glob-to-regexp@0.4.1: + resolution: + { + integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==, + } + + glob@10.4.5: + resolution: + { + integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==, + } + hasBin: true + + global-modules@1.0.0: + resolution: + { + integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==, + } + engines: { node: ">=0.10.0" } + + global-prefix@1.0.2: + resolution: + { + integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==, + } + engines: { node: ">=0.10.0" } + + 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==, + } + + gzip-size@6.0.0: + resolution: + { + integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==, + } + engines: { node: ">=10" } + + handle-thing@2.0.1: + resolution: + { + integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==, + } + + 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-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" } + + hash.js@1.1.7: + resolution: + { + integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==, + } + + hasown@2.0.2: + resolution: + { + integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, + } + engines: { node: ">= 0.4" } + + headers-polyfill@3.3.0: + resolution: + { + integrity: sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ==, + } + + help-me@5.0.0: + resolution: + { + integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==, + } + + hmac-drbg@1.0.1: + resolution: + { + integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, + } + + homedir-polyfill@1.0.3: + resolution: + { + integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==, + } + engines: { node: ">=0.10.0" } + + hono@4.7.9: + resolution: + { + integrity: sha512-/EsCoR5h7N4yu01TDu9GMCCJa6ZLk5ZJIWFFGNawAXmd1Tp53+Wir4xm0D2X19bbykWUlzQG0+BvPAji6p9E8Q==, + } + engines: { node: ">=16.9.0" } + + hpack.js@2.1.6: + resolution: + { + integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==, + } + + html-entities@2.6.0: + resolution: + { + integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==, + } + + http-assert@1.5.0: + resolution: + { + integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==, + } + engines: { node: ">= 0.8" } + + http-deceiver@1.2.7: + resolution: + { + integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==, + } + + http-errors@1.6.3: + resolution: + { + integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==, + } + engines: { node: ">= 0.6" } + + http-errors@1.7.2: + resolution: + { + integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==, + } + engines: { node: ">= 0.6" } + + http-errors@1.8.1: + resolution: + { + integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==, + } + engines: { node: ">= 0.6" } + + http-errors@2.0.0: + resolution: + { + integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==, + } + engines: { node: ">= 0.8" } + + http-parser-js@0.5.10: + resolution: + { + integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==, + } + + http-proxy-middleware@2.0.9: + resolution: + { + integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==, + } + engines: { node: ">=12.0.0" } + peerDependencies: + "@types/express": ^4.17.13 + peerDependenciesMeta: + "@types/express": + optional: true + + http-proxy@1.18.1: + resolution: + { + integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==, + } + engines: { node: ">=8.0.0" } + + human-signals@2.1.0: + resolution: + { + integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==, + } + engines: { node: ">=10.17.0" } + + hyperdyperid@1.2.0: + resolution: + { + integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==, + } + engines: { node: ">=10.18" } + + iconv-lite@0.4.24: + resolution: + { + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, + } + engines: { node: ">=0.10.0" } + + iconv-lite@0.6.3: + resolution: + { + integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, + } + engines: { node: ">=0.10.0" } + + inherits@2.0.3: + resolution: + { + integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==, + } + + inherits@2.0.4: + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } + + ini@1.3.8: + resolution: + { + integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==, + } + + interpret@3.1.1: + resolution: + { + integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==, + } + engines: { node: ">=10.13.0" } + + ipaddr.js@1.9.1: + resolution: + { + integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, + } + engines: { node: ">= 0.10" } + + ipaddr.js@2.2.0: + resolution: + { + integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==, + } + engines: { node: ">= 10" } + + is-binary-path@2.1.0: + resolution: + { + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, + } + engines: { node: ">=8" } + + is-core-module@2.16.1: + resolution: + { + integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, + } + engines: { node: ">= 0.4" } + + is-docker@3.0.0: + resolution: + { + integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + hasBin: true + + is-extglob@2.1.1: + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: ">=0.10.0" } + + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } + + is-generator-function@1.1.0: + resolution: + { + integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==, + } + engines: { node: ">= 0.4" } + + is-glob@4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: ">=0.10.0" } + + is-inside-container@1.0.0: + resolution: + { + integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==, + } + engines: { node: ">=14.16" } + hasBin: true + + is-interactive@2.0.0: + resolution: + { + integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==, + } + engines: { node: ">=12" } + + is-my-ip-valid@1.0.1: + resolution: + { + integrity: sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==, + } + + is-my-json-valid@2.20.6: + resolution: + { + integrity: sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==, + } + + is-network-error@1.1.0: + resolution: + { + integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==, + } + engines: { node: ">=16" } + + is-number@7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: ">=0.12.0" } + + is-plain-obj@3.0.0: + resolution: + { + integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==, + } + engines: { node: ">=10" } + + is-property@1.0.2: + resolution: + { + integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==, + } + + is-regex@1.2.1: + resolution: + { + integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, + } + engines: { node: ">= 0.4" } + + is-stream@2.0.1: + resolution: + { + integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, + } + engines: { node: ">=8" } + + is-unicode-supported@1.3.0: + resolution: + { + integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==, + } + engines: { node: ">=12" } + + is-unicode-supported@2.1.0: + resolution: + { + integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==, + } + engines: { node: ">=18" } + + is-windows@1.0.2: + resolution: + { + integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==, + } + engines: { node: ">=0.10.0" } + + is-wsl@3.1.0: + resolution: + { + integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==, + } + engines: { node: ">=16" } + + isarray@1.0.0: + resolution: + { + integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, + } + + isarray@2.0.5: + resolution: + { + integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, + } + + isexe@2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + + isexe@3.1.1: + resolution: + { + integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==, + } + engines: { node: ">=16" } + + isomorphic-rslog@0.0.6: + resolution: + { + integrity: sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==, + } + engines: { node: ">=14.17.6" } + + isomorphic-ws@5.0.0: + resolution: + { + integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==, + } + peerDependencies: + ws: "*" + + jackspeak@3.4.3: + resolution: + { + integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, + } + + jest-worker@27.5.1: + resolution: + { + integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==, + } + engines: { node: ">= 10.13.0" } + + joi@17.13.3: + resolution: + { + integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==, + } + + jose@6.0.11: + resolution: + { + integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==, + } + + joycon@3.1.1: + resolution: + { + integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==, + } + engines: { node: ">=10" } + + json-parse-even-better-errors@2.3.1: + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } + + json-schema-traverse@1.0.0: + resolution: + { + integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, + } + + json-stable-stringify@1.3.0: + resolution: + { + integrity: sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==, + } + engines: { node: ">= 0.4" } + + json-stringify-safe@5.0.1: + resolution: + { + integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==, + } + + jsonfile@4.0.0: + resolution: + { + integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==, + } + + jsonfile@6.1.0: + resolution: + { + integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==, + } + + jsonify@0.0.1: + resolution: + { + integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==, + } + + jsonpointer@5.0.1: + resolution: + { + integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==, + } + engines: { node: ">=0.10.0" } + + keygrip@1.1.0: + resolution: + { + integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==, + } + engines: { node: ">= 0.6" } + + koa-compose@4.1.0: + resolution: + { + integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==, + } + + koa-convert@2.0.0: + resolution: + { + integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==, + } + engines: { node: ">= 10" } + + koa@2.16.1: + resolution: + { + integrity: sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==, + } + engines: { node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4 } + + launch-editor@2.10.0: + resolution: + { + integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==, + } + + loader-runner@4.3.0: + resolution: + { + integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==, + } + engines: { node: ">=6.11.5" } + + lodash.clonedeepwith@4.5.0: + resolution: + { + integrity: sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==, + } + + lodash@4.17.21: + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } + + log-symbols@6.0.0: + resolution: + { + integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==, + } + engines: { node: ">=18" } + + log4js@6.9.1: + resolution: + { + integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==, + } + engines: { node: ">=8.0" } + + long-timeout@0.1.1: + resolution: + { + integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==, + } + + lru-cache@10.4.3: + resolution: + { + integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, + } + + lru_map@0.4.1: + resolution: + { + integrity: sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==, + } + + luxon@3.6.1: + resolution: + { + integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==, + } + engines: { node: ">=12" } + + math-intrinsics@1.1.0: + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: ">= 0.4" } + + media-typer@0.3.0: + resolution: + { + integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==, + } + engines: { node: ">= 0.6" } + + memfs@4.17.1: + resolution: + { + integrity: sha512-thuTRd7F4m4dReCIy7vv4eNYnU6XI/tHMLSMMHLiortw/Y0QxqKtinG523U2aerzwYWGi606oBP4oMPy4+edag==, + } + engines: { node: ">= 4.0.0" } + + merge-descriptors@1.0.3: + resolution: + { + integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==, + } + + merge-stream@2.0.0: + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, + } + + methods@1.1.2: + resolution: + { + integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==, + } + engines: { node: ">= 0.6" } + + micromatch@4.0.8: + resolution: + { + integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, + } + engines: { node: ">=8.6" } + + mime-db@1.52.0: + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } + + mime-db@1.54.0: + resolution: + { + integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, + } + engines: { node: ">= 0.6" } + + mime-types@2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } + + mime@1.6.0: + resolution: + { + integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, + } + engines: { node: ">=4" } + hasBin: true + + mimic-fn@2.1.0: + resolution: + { + integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, + } + engines: { node: ">=6" } + + mimic-function@5.0.1: + resolution: + { + integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==, + } + engines: { node: ">=18" } + + minimalistic-assert@1.0.1: + resolution: + { + integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, + } + + minimalistic-crypto-utils@1.0.1: + resolution: + { + integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==, + } + + 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==, + } + + minipass@7.1.2: + resolution: + { + integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==, + } + engines: { node: ">=16 || 14 >=14.17" } + + mrmime@1.0.1: + resolution: + { + integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==, + } + engines: { node: ">=10" } + + ms@2.0.0: + resolution: + { + integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, + } + + ms@2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + + multicast-dns@7.2.5: + resolution: + { + integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==, + } + hasBin: true + + mustache@4.0.0: + resolution: + { + integrity: sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==, + } + engines: { npm: ">=1.4.0" } + hasBin: true + + near-abi@0.2.0: + resolution: + { + integrity: sha512-kCwSf/3fraPU2zENK18sh+kKG4uKbEUEQdyWQkmW8ZofmLarObIz2+zAYjA1teDZLeMvEQew3UysnPDXgjneaA==, + } + + near-api-js@5.1.1: + resolution: + { + integrity: sha512-h23BGSKxNv8ph+zU6snicstsVK1/CTXsQz4LuGGwoRE24Hj424nSe4+/1tzoiC285Ljf60kPAqRCmsfv9etF2g==, + } + + negotiator@0.6.3: + resolution: + { + integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==, + } + engines: { node: ">= 0.6" } + + negotiator@0.6.4: + resolution: + { + integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==, + } + engines: { node: ">= 0.6" } + + neo-async@2.6.2: + resolution: + { + integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==, + } + + nock@13.5.6: + resolution: + { + integrity: sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==, + } + engines: { node: ">= 10.13" } + + node-addon-api@5.1.0: + resolution: + { + integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==, + } + + node-domexception@1.0.0: + resolution: + { + integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==, + } + engines: { node: ">=10.5.0" } + deprecated: Use your platform's native DOMException instead + + node-fetch@2.6.7: + resolution: + { + integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==, + } + engines: { node: 4.x || >=6.0.0 } + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@2.7.0: + resolution: + { + integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, + } + engines: { node: 4.x || >=6.0.0 } + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: + { + integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + node-forge@1.3.1: + resolution: + { + integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==, + } + engines: { node: ">= 6.13.0" } + + node-gyp-build@4.8.4: + resolution: + { + integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==, + } + hasBin: true + + node-releases@2.0.19: + resolution: + { + integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==, + } + + node-schedule@2.1.1: + resolution: + { + integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==, + } + engines: { node: ">=6" } + + normalize-path@3.0.0: + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } + engines: { node: ">=0.10.0" } + + npm-run-path@4.0.1: + resolution: + { + integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==, + } + engines: { node: ">=8" } + + 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" } + + obuf@1.1.2: + resolution: + { + integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==, + } + + on-exit-leak-free@2.1.2: + resolution: + { + integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==, + } + engines: { node: ">=14.0.0" } + + on-finished@2.4.1: + resolution: + { + integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, + } + engines: { node: ">= 0.8" } + + on-headers@1.0.2: + resolution: + { + integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==, + } + engines: { node: ">= 0.8" } + + once@1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } + + onetime@5.1.2: + resolution: + { + integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, + } + engines: { node: ">=6" } + + onetime@7.0.0: + resolution: + { + integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==, + } + engines: { node: ">=18" } + + only@0.0.2: + resolution: + { + integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==, + } + + open@10.1.2: + resolution: + { + integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==, + } + engines: { node: ">=18" } + + openapi3-ts@4.4.0: + resolution: + { + integrity: sha512-9asTNB9IkKEzWMcHmVZE7Ts3kC9G7AFHfs8i7caD8HbI76gEjdkId4z/AkP83xdZsH7PLAnnbl47qZkXuxpArw==, + } + + opener@1.5.2: + resolution: + { + integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==, + } + hasBin: true + + ora@8.2.0: + resolution: + { + integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==, + } + engines: { node: ">=18" } + + otpauth@9.4.0: + resolution: + { + integrity: sha512-fHIfzIG5RqCkK9cmV8WU+dPQr9/ebR5QOwGZn2JAr1RQF+lmAuLL2YdtdqvmBjNmgJlYk3KZ4a0XokaEhg1Jsw==, + } + + p-retry@4.6.2: + resolution: + { + integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==, + } + engines: { node: ">=8" } + + p-retry@6.2.1: + resolution: + { + integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==, + } + engines: { node: ">=16.17" } + + package-json-from-dist@1.0.1: + resolution: + { + integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, + } + + parse-passwd@1.0.0: + resolution: + { + integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==, + } + engines: { node: ">=0.10.0" } + + parseurl@1.3.3: + resolution: + { + integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, + } + engines: { node: ">= 0.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==, + } + + path-scurry@1.11.1: + resolution: + { + integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, + } + engines: { node: ">=16 || 14 >=14.18" } + + path-to-regexp@0.1.12: + resolution: + { + integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==, + } + + pg-cloudflare@1.2.5: + resolution: + { + integrity: sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==, + } + + pg-connection-string@2.9.0: + resolution: + { + integrity: sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==, + } + + pg-int8@1.0.1: + resolution: + { + integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==, + } + engines: { node: ">=4.0.0" } + + pg-numeric@1.0.2: + resolution: + { + integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==, + } + engines: { node: ">=4" } + + pg-pool@3.10.0: + resolution: + { + integrity: sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==, + } + peerDependencies: + pg: ">=8.0" + + pg-protocol@1.10.0: + resolution: + { + integrity: sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==, + } + + pg-types@2.2.0: + resolution: + { + integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==, + } + engines: { node: ">=4" } + + pg-types@4.0.2: + resolution: + { + integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==, + } + engines: { node: ">=10" } + + pg@8.16.0: + resolution: + { + integrity: sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==, + } + engines: { node: ">= 8.0.0" } + peerDependencies: + pg-native: ">=3.0.1" + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: + { + integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==, + } + + picocolors@1.1.1: + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } + + picomatch@2.3.1: + resolution: + { + integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, + } + engines: { node: ">=8.6" } + + pino-abstract-transport@2.0.0: + resolution: + { + integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==, + } + + pino-pretty@13.0.0: + resolution: + { + integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==, + } + hasBin: true + + pino-std-serializers@7.0.0: + resolution: + { + integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==, + } + + pino@9.6.0: + resolution: + { + integrity: sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==, + } + hasBin: true + + postgres-array@2.0.0: + resolution: + { + integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==, + } + engines: { node: ">=4" } + + postgres-array@3.0.4: + resolution: + { + integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==, + } + engines: { node: ">=12" } + + postgres-bytea@1.0.0: + resolution: + { + integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==, + } + engines: { node: ">=0.10.0" } + + postgres-bytea@3.0.0: + resolution: + { + integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==, + } + engines: { node: ">= 6" } + + postgres-date@1.0.7: + resolution: + { + integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==, + } + engines: { node: ">=0.10.0" } + + postgres-date@2.1.0: + resolution: + { + integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==, + } + engines: { node: ">=12" } + + postgres-interval@1.2.0: + resolution: + { + integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==, + } + engines: { node: ">=0.10.0" } + + postgres-interval@3.0.0: + resolution: + { + integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==, + } + engines: { node: ">=12" } + + postgres-range@1.1.4: + resolution: + { + integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==, + } + + process-nextick-args@2.0.1: + resolution: + { + integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, + } + + process-warning@4.0.1: + resolution: + { + integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==, + } + + propagate@2.0.1: + resolution: + { + integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==, + } + engines: { node: ">= 8" } + + proxy-addr@2.0.7: + resolution: + { + integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, + } + engines: { node: ">= 0.10" } + + proxy-from-env@1.1.0: + resolution: + { + integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, + } + + psl@1.15.0: + resolution: + { + integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==, + } + + pump@3.0.2: + resolution: + { + integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==, + } + + punycode@2.3.1: + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, + } + engines: { node: ">=6" } + + pure-rand@6.1.0: + resolution: + { + integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==, + } + + qs@6.13.0: + resolution: + { + integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==, + } + engines: { node: ">=0.6" } + + querystringify@2.2.0: + resolution: + { + integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==, + } + + quick-format-unescaped@4.0.4: + resolution: + { + integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==, + } + + rambda@9.4.2: + resolution: + { + integrity: sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==, + } + + randombytes@2.1.0: + resolution: + { + integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, + } + + range-parser@1.2.1: + resolution: + { + integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, + } + engines: { node: ">= 0.6" } + + raw-body@2.5.2: + resolution: + { + integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==, + } + engines: { node: ">= 0.8" } + + react-dom@19.1.0: + resolution: + { + integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==, + } + peerDependencies: + react: ^19.1.0 + + react@19.1.0: + resolution: + { + integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==, + } + engines: { node: ">=0.10.0" } + + readable-stream@2.3.8: + resolution: + { + integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, + } + + readable-stream@3.6.2: + resolution: + { + integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, + } + engines: { node: ">= 6" } + + readdirp@3.6.0: + resolution: + { + integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, + } + engines: { node: ">=8.10.0" } + + real-require@0.2.0: + resolution: + { + integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==, + } + engines: { node: ">= 12.13.0" } + + rechoir@0.8.0: + resolution: + { + integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==, + } + engines: { node: ">= 10.13.0" } + + require-directory@2.1.1: + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, + } + engines: { node: ">=0.10.0" } + + require-from-string@2.0.2: + resolution: + { + integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, + } + engines: { node: ">=0.10.0" } + + requires-port@1.0.0: + resolution: + { + integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==, + } + + resolve-dir@1.0.1: + resolution: + { + integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==, + } + engines: { node: ">=0.10.0" } + + resolve-pkg-maps@1.0.0: + resolution: + { + integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==, + } + + resolve@1.22.10: + resolution: + { + integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==, + } + engines: { node: ">= 0.4" } + hasBin: true + + resolve@1.22.8: + resolution: + { + integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==, + } + hasBin: true + + restore-cursor@5.1.0: + resolution: + { + integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==, + } + engines: { node: ">=18" } + + retry@0.13.1: + resolution: + { + integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==, + } + engines: { node: ">= 4" } + + rfdc@1.4.1: + resolution: + { + integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==, + } + + rimraf@5.0.10: + resolution: + { + integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==, + } + hasBin: true + + rslog@1.2.3: + resolution: + { + integrity: sha512-antALPJaKBRPBU1X2q9t085K4htWDOOv/K1qhTUk7h0l1ePU/KbDqKJn19eKP0dk7PqMioeA0+fu3gyPXCsXxQ==, + } + engines: { node: ">=14.17.6" } + + run-applescript@7.0.0: + resolution: + { + integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==, + } + engines: { node: ">=18" } + + rxjs@7.8.2: + resolution: + { + integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, + } + + safe-buffer@5.1.2: + resolution: + { + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, + } + + safe-buffer@5.2.1: + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, + } + + safe-regex-test@1.1.0: + resolution: + { + integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, + } + engines: { node: ">= 0.4" } + + safe-stable-stringify@2.5.0: + resolution: + { + integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==, + } + engines: { node: ">=10" } + + safer-buffer@2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } + + scheduler@0.26.0: + resolution: + { + integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==, + } + + schema-utils@4.3.2: + resolution: + { + integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==, + } + engines: { node: ">= 10.13.0" } + + secp256k1@5.0.1: + resolution: + { + integrity: sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==, + } + engines: { node: ">=18.0.0" } + + secure-json-parse@2.7.0: + resolution: + { + integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==, + } + + select-hose@2.0.0: + resolution: + { + integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==, + } + + selfsigned@2.4.1: + resolution: + { + integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==, + } + engines: { node: ">=10" } + + semver@7.6.3: + resolution: + { + integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==, + } + engines: { node: ">=10" } + hasBin: true + + semver@7.7.2: + resolution: + { + integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==, + } + engines: { node: ">=10" } + hasBin: true + + send@0.19.0: + resolution: + { + integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==, + } + engines: { node: ">= 0.8.0" } + + serialize-javascript@6.0.2: + resolution: + { + integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==, + } + + serve-index@1.9.1: + resolution: + { + integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==, + } + engines: { node: ">= 0.8.0" } + + serve-static@1.16.2: + resolution: + { + integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==, + } + engines: { node: ">= 0.8.0" } + + set-cookie-parser@2.7.1: + resolution: + { + integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==, + } + + set-function-length@1.2.2: + resolution: + { + integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, + } + engines: { node: ">= 0.4" } + + setprototypeof@1.1.0: + resolution: + { + integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==, + } + + setprototypeof@1.1.1: + resolution: + { + integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==, + } + + setprototypeof@1.2.0: + resolution: + { + integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, + } + + 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" } + + shell-quote@1.8.2: + resolution: + { + integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==, + } + engines: { node: ">= 0.4" } + + 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" } + + signal-exit@3.0.7: + resolution: + { + integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, + } + + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: ">=14" } + + sirv@1.0.19: + resolution: + { + integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==, + } + engines: { node: ">= 10" } + + sockjs@0.3.24: + resolution: + { + integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==, + } + + sonic-boom@4.2.0: + resolution: + { + integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==, + } + + sorted-array-functions@1.3.0: + resolution: + { + integrity: sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==, + } + + source-map-support@0.5.21: + resolution: + { + integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, + } + + source-map@0.6.1: + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, + } + engines: { node: ">=0.10.0" } + + spdy-transport@3.0.0: + resolution: + { + integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==, + } + + spdy@4.0.2: + resolution: + { + integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==, + } + engines: { node: ">=6.0.0" } + + split2@4.2.0: + resolution: + { + integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, + } + engines: { node: ">= 10.x" } + + statuses@1.5.0: + resolution: + { + integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==, + } + engines: { node: ">= 0.6" } + + statuses@2.0.1: + resolution: + { + integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==, + } + engines: { node: ">= 0.8" } + + stdin-discarder@0.2.2: + resolution: + { + integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==, + } + engines: { node: ">=18" } + + streamroller@3.1.5: + resolution: + { + integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==, + } + engines: { node: ">=8.0" } + + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } + + string-width@5.1.2: + resolution: + { + integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, + } + engines: { node: ">=12" } + + string-width@7.2.0: + resolution: + { + integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==, + } + engines: { node: ">=18" } + + string_decoder@1.1.1: + resolution: + { + integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, + } + + string_decoder@1.3.0: + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, + } + + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } + + strip-ansi@7.1.0: + resolution: + { + integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==, + } + engines: { node: ">=12" } + + strip-final-newline@2.0.0: + resolution: + { + integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==, + } + engines: { node: ">=6" } + + strip-json-comments@3.1.1: + resolution: + { + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, + } + engines: { node: ">=8" } + + supports-color@7.2.0: + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: ">=8" } + + supports-color@8.1.1: + resolution: + { + integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==, + } + engines: { node: ">=10" } + + supports-preserve-symlinks-flag@1.0.0: + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, + } + engines: { node: ">= 0.4" } + + tapable@2.2.1: + resolution: + { + integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==, + } + engines: { node: ">=6" } + + terser-webpack-plugin@5.3.14: + resolution: + { + integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==, + } + engines: { node: ">= 10.13.0" } + peerDependencies: + "@swc/core": "*" + esbuild: "*" + uglify-js: "*" + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@5.39.0: + resolution: + { + integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==, + } + engines: { node: ">=10" } + hasBin: true + + thingies@1.21.0: + resolution: + { + integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==, + } + engines: { node: ">=10.18" } + peerDependencies: + tslib: ^2 + + thread-stream@3.1.0: + resolution: + { + integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==, + } + + thunky@1.1.0: + resolution: + { + integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==, + } + + to-regex-range@5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: ">=8.0" } + + toidentifier@1.0.0: + resolution: + { + integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==, + } + engines: { node: ">=0.6" } + + toidentifier@1.0.1: + resolution: + { + integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, + } + engines: { node: ">=0.6" } + + totalist@1.1.0: + resolution: + { + integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==, + } + engines: { node: ">=6" } + + tough-cookie@4.1.4: + resolution: + { + integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==, + } + engines: { node: ">=6" } + + tr46@0.0.3: + resolution: + { + integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, + } + + tree-dump@1.0.2: + resolution: + { + integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==, + } + engines: { node: ">=10.0" } + peerDependencies: + tslib: "2" + + tree-kill@1.2.2: + resolution: + { + integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==, + } + hasBin: true + + tslib@2.8.1: + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } + + tsscmp@1.0.6: + resolution: + { + integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==, + } + engines: { node: ">=0.6.x" } + + twitter-api-v2@1.23.2: + resolution: + { + integrity: sha512-m0CGXmfGwUhWBOOTVCIXIoSEXwGCQV3Es9yraCwUxaVrjJT2CQcqDrQsQTpBhtiAvVL2HS1cCEGsotNjfX9log==, + } + + type-is@1.6.18: + resolution: + { + integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==, + } + engines: { node: ">= 0.6" } + + typescript@5.8.3: + resolution: + { + integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==, + } + engines: { node: ">=14.17" } + hasBin: true + + undici-types@6.21.0: + resolution: + { + integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, + } + + universalify@0.1.2: + resolution: + { + integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==, + } + engines: { node: ">= 4.0.0" } + + universalify@0.2.0: + resolution: + { + integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==, + } + engines: { node: ">= 4.0.0" } + + universalify@2.0.1: + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, + } + engines: { node: ">= 10.0.0" } + + unpipe@1.0.0: + resolution: + { + integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, + } + engines: { node: ">= 0.8" } + + upath@2.0.1: + resolution: + { + integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==, + } + engines: { node: ">=4" } + + update-browserslist-db@1.1.3: + resolution: + { + integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==, + } + hasBin: true + peerDependencies: + browserslist: ">= 4.21.0" + + url-parse@1.5.10: + resolution: + { + integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==, + } + + util-deprecate@1.0.2: + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, + } + + utils-merge@1.0.1: + resolution: + { + integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==, + } + engines: { node: ">= 0.4.0" } + + uuid@8.3.2: + resolution: + { + integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==, + } + hasBin: true + + vary@1.1.2: + resolution: + { + integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, + } + engines: { node: ">= 0.8" } + + wait-on@8.0.3: + resolution: + { + integrity: sha512-nQFqAFzZDeRxsu7S3C7LbuxslHhk+gnJZHyethuGKAn2IVleIbTB9I3vJSQiSR+DifUqmdzfPMoMPJfLqMF2vw==, + } + engines: { node: ">=12.0.0" } + hasBin: true + + watchpack@2.4.2: + resolution: + { + integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==, + } + engines: { node: ">=10.13.0" } + + wbuf@1.7.3: + resolution: + { + integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==, + } + + web-streams-polyfill@3.3.3: + resolution: + { + integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==, + } + engines: { node: ">= 8" } + + webidl-conversions@3.0.1: + resolution: + { + integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, + } + + webpack-bundle-analyzer@4.6.1: + resolution: + { + integrity: sha512-oKz9Oz9j3rUciLNfpGFjOb49/jEpXNmWdVH8Ls//zNcnLlQdTGXQQMsBbb/gR7Zl8WNLxVCq+0Hqbx3zv6twBw==, + } + engines: { node: ">= 10.13.0" } + hasBin: true + + webpack-dev-middleware@7.4.2: + resolution: + { + integrity: sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==, + } + engines: { node: ">= 18.12.0" } + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.0.4: + resolution: + { + integrity: sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==, + } + engines: { node: ">= 18.12.0" } + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: "*" + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + webpack-sources@3.2.3: + resolution: + { + integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==, + } + engines: { node: ">=10.13.0" } + + webpack@5.99.8: + resolution: + { + integrity: sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==, + } + engines: { node: ">=10.13.0" } + hasBin: true + peerDependencies: + webpack-cli: "*" + peerDependenciesMeta: + webpack-cli: + optional: true + + websocket-driver@0.7.4: + resolution: + { + integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==, + } + engines: { node: ">=0.8.0" } + + websocket-extensions@0.1.4: + resolution: + { + integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==, + } + engines: { node: ">=0.8.0" } + + whatwg-url@5.0.0: + resolution: + { + integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, + } + + which@1.3.1: + resolution: + { + integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==, + } + hasBin: true + + which@2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } + hasBin: true + + which@4.0.0: + resolution: + { + integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==, + } + engines: { node: ^16.13.0 || >=18.0.0 } + hasBin: true + + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: ">=10" } + + wrap-ansi@8.1.0: + resolution: + { + integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, + } + engines: { node: ">=12" } + + wrappy@1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } + + ws@7.5.10: + resolution: + { + integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==, + } + engines: { node: ">=8.3.0" } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: + { + integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==, + } + engines: { node: ">=10.0.0" } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.2: + resolution: + { + integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==, + } + engines: { node: ">=10.0.0" } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xtend@4.0.2: + resolution: + { + integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, + } + engines: { node: ">=0.4" } + + y18n@5.0.8: + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, + } + engines: { node: ">=10" } + + yaml@2.7.1: + resolution: + { + integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==, + } + engines: { node: ">= 14" } + hasBin: true + + yargs-parser@21.1.1: + resolution: + { + integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, + } + engines: { node: ">=12" } + + yargs@17.7.2: + resolution: + { + integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, + } + engines: { node: ">=12" } + + ylru@1.4.0: + resolution: + { + integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==, + } + engines: { node: ">= 4.0.0" } + + zod-to-json-schema@3.24.5: + resolution: + { + integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==, + } + peerDependencies: + zod: ^3.24.1 + + zod@3.24.4: + resolution: + { + integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==, + } + +snapshots: + "@asteasolutions/zod-to-openapi@5.5.0(zod@3.24.4)": + dependencies: + openapi3-ts: 4.4.0 + zod: 3.24.4 + + "@crosspost/scheduler-sdk@0.1.1": + dependencies: + axios: 1.9.0 + transitivePeerDependencies: + - debug + + "@curatedotfun/types@0.0.5": {} + + "@discoveryjs/json-ext@0.5.7": {} + + "@drizzle-team/brocli@0.10.2": {} + + "@esbuild-kit/core-utils@3.3.2": + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + "@esbuild-kit/esm-loader@2.6.5": + dependencies: + "@esbuild-kit/core-utils": 3.3.2 + get-tsconfig: 4.10.0 + + "@esbuild/aix-ppc64@0.19.12": + optional: true + + "@esbuild/android-arm64@0.17.19": + optional: true + + "@esbuild/android-arm64@0.18.20": + optional: true + + "@esbuild/android-arm64@0.19.12": + optional: true + + "@esbuild/android-arm@0.17.19": + optional: true + + "@esbuild/android-arm@0.18.20": + optional: true + + "@esbuild/android-arm@0.19.12": + optional: true + + "@esbuild/android-x64@0.17.19": + optional: true + + "@esbuild/android-x64@0.18.20": + optional: true + + "@esbuild/android-x64@0.19.12": + optional: true + + "@esbuild/darwin-arm64@0.17.19": + optional: true + + "@esbuild/darwin-arm64@0.18.20": + optional: true + + "@esbuild/darwin-arm64@0.19.12": + optional: true + + "@esbuild/darwin-x64@0.17.19": + optional: true + + "@esbuild/darwin-x64@0.18.20": + optional: true + + "@esbuild/darwin-x64@0.19.12": + optional: true + + "@esbuild/freebsd-arm64@0.17.19": + optional: true + + "@esbuild/freebsd-arm64@0.18.20": + optional: true + + "@esbuild/freebsd-arm64@0.19.12": + optional: true + + "@esbuild/freebsd-x64@0.17.19": + optional: true + + "@esbuild/freebsd-x64@0.18.20": + optional: true + + "@esbuild/freebsd-x64@0.19.12": + optional: true + + "@esbuild/linux-arm64@0.17.19": + optional: true + + "@esbuild/linux-arm64@0.18.20": + optional: true + + "@esbuild/linux-arm64@0.19.12": + optional: true + + "@esbuild/linux-arm@0.17.19": + optional: true + + "@esbuild/linux-arm@0.18.20": + optional: true + + "@esbuild/linux-arm@0.19.12": + optional: true + + "@esbuild/linux-ia32@0.17.19": + optional: true + + "@esbuild/linux-ia32@0.18.20": + optional: true + + "@esbuild/linux-ia32@0.19.12": + optional: true + + "@esbuild/linux-loong64@0.17.19": + optional: true + + "@esbuild/linux-loong64@0.18.20": + optional: true + + "@esbuild/linux-loong64@0.19.12": + optional: true + + "@esbuild/linux-mips64el@0.17.19": + optional: true + + "@esbuild/linux-mips64el@0.18.20": + optional: true + + "@esbuild/linux-mips64el@0.19.12": + optional: true + + "@esbuild/linux-ppc64@0.17.19": + optional: true + + "@esbuild/linux-ppc64@0.18.20": + optional: true + + "@esbuild/linux-ppc64@0.19.12": + optional: true + + "@esbuild/linux-riscv64@0.17.19": + optional: true + + "@esbuild/linux-riscv64@0.18.20": + optional: true + + "@esbuild/linux-riscv64@0.19.12": + optional: true + + "@esbuild/linux-s390x@0.17.19": + optional: true + + "@esbuild/linux-s390x@0.18.20": + optional: true + + "@esbuild/linux-s390x@0.19.12": + optional: true + + "@esbuild/linux-x64@0.17.19": + optional: true + + "@esbuild/linux-x64@0.18.20": + optional: true + + "@esbuild/linux-x64@0.19.12": + optional: true + + "@esbuild/netbsd-x64@0.17.19": + optional: true + + "@esbuild/netbsd-x64@0.18.20": + optional: true + + "@esbuild/netbsd-x64@0.19.12": + optional: true + + "@esbuild/openbsd-x64@0.17.19": + optional: true + + "@esbuild/openbsd-x64@0.18.20": + optional: true + + "@esbuild/openbsd-x64@0.19.12": + optional: true + + "@esbuild/sunos-x64@0.17.19": + optional: true + + "@esbuild/sunos-x64@0.18.20": + optional: true + + "@esbuild/sunos-x64@0.19.12": + optional: true + + "@esbuild/win32-arm64@0.17.19": + optional: true + + "@esbuild/win32-arm64@0.18.20": + optional: true + + "@esbuild/win32-arm64@0.19.12": + optional: true + + "@esbuild/win32-ia32@0.17.19": + optional: true + + "@esbuild/win32-ia32@0.18.20": + optional: true + + "@esbuild/win32-ia32@0.19.12": + optional: true + + "@esbuild/win32-x64@0.17.19": + optional: true + + "@esbuild/win32-x64@0.18.20": + optional: true + + "@esbuild/win32-x64@0.19.12": + optional: true + + "@hapi/hoek@9.3.0": {} + + "@hapi/topo@5.1.0": + dependencies: + "@hapi/hoek": 9.3.0 + + "@hono/node-server@1.14.1(hono@4.7.9)": + dependencies: + hono: 4.7.9 + + "@hono/zod-openapi@0.9.10(hono@4.7.9)(zod@3.24.4)": + dependencies: + "@asteasolutions/zod-to-openapi": 5.5.0(zod@3.24.4) + "@hono/zod-validator": 0.2.1(hono@4.7.9)(zod@3.24.4) + hono: 4.7.9 + zod: 3.24.4 + + "@hono/zod-validator@0.2.1(hono@4.7.9)(zod@3.24.4)": + dependencies: + hono: 4.7.9 + zod: 3.24.4 + + "@hono/zod-validator@0.5.0(hono@4.7.9)(zod@3.24.4)": + dependencies: + hono: 4.7.9 + zod: 3.24.4 + + "@isaacs/cliui@8.0.2": + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + "@jridgewell/gen-mapping@0.3.8": + dependencies: + "@jridgewell/set-array": 1.2.1 + "@jridgewell/sourcemap-codec": 1.5.0 + "@jridgewell/trace-mapping": 0.3.25 + + "@jridgewell/resolve-uri@3.1.2": {} + + "@jridgewell/set-array@1.2.1": {} + + "@jridgewell/source-map@0.3.6": + dependencies: + "@jridgewell/gen-mapping": 0.3.8 + "@jridgewell/trace-mapping": 0.3.25 + + "@jridgewell/sourcemap-codec@1.5.0": {} + + "@jridgewell/trace-mapping@0.3.25": + dependencies: + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.0 + + "@jsonjoy.com/base64@1.1.2(tslib@2.8.1)": + dependencies: + tslib: 2.8.1 + + "@jsonjoy.com/json-pack@1.2.0(tslib@2.8.1)": + dependencies: + "@jsonjoy.com/base64": 1.1.2(tslib@2.8.1) + "@jsonjoy.com/util": 1.6.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.8.1) + tslib: 2.8.1 + + "@jsonjoy.com/util@1.6.0(tslib@2.8.1)": + dependencies: + tslib: 2.8.1 + + "@leichtgewicht/ip-codec@2.0.5": {} + + "@modern-js/node-bundle-require@2.65.1": + dependencies: + "@modern-js/utils": 2.65.1 + "@swc/helpers": 0.5.13 + esbuild: 0.17.19 + + "@modern-js/utils@2.65.1": + dependencies: + "@swc/helpers": 0.5.13 + caniuse-lite: 1.0.30001717 + lodash: 4.17.21 + rslog: 1.2.3 + + "@module-federation/bridge-react-webpack-plugin@0.13.1": + dependencies: + "@module-federation/sdk": 0.13.1 + "@types/semver": 7.5.8 + semver: 7.6.3 + + "@module-federation/cli@0.13.1(typescript@5.8.3)": + dependencies: + "@modern-js/node-bundle-require": 2.65.1 + "@module-federation/dts-plugin": 0.13.1(typescript@5.8.3) + "@module-federation/sdk": 0.13.1 + chalk: 3.0.0 + commander: 11.1.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + "@module-federation/data-prefetch@0.13.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)": + dependencies: + "@module-federation/runtime": 0.13.1 + "@module-federation/sdk": 0.13.1 + fs-extra: 9.1.0 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + "@module-federation/dts-plugin@0.13.1(typescript@5.8.3)": + dependencies: + "@module-federation/error-codes": 0.13.1 + "@module-federation/managers": 0.13.1 + "@module-federation/sdk": 0.13.1 + "@module-federation/third-party-dts-extractor": 0.13.1 + adm-zip: 0.5.16 + ansi-colors: 4.1.3 + axios: 1.9.0 + chalk: 3.0.0 + fs-extra: 9.1.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + koa: 2.16.1 + lodash.clonedeepwith: 4.5.0 + log4js: 6.9.1 + node-schedule: 2.1.1 + rambda: 9.4.2 + typescript: 5.8.3 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + "@module-federation/enhanced@0.13.1(@rspack/core@1.2.8(@swc/helpers@0.5.13))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(webpack@5.99.8(esbuild@0.19.12))": + dependencies: + "@module-federation/bridge-react-webpack-plugin": 0.13.1 + "@module-federation/cli": 0.13.1(typescript@5.8.3) + "@module-federation/data-prefetch": 0.13.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + "@module-federation/dts-plugin": 0.13.1(typescript@5.8.3) + "@module-federation/error-codes": 0.13.1 + "@module-federation/inject-external-runtime-core-plugin": 0.13.1(@module-federation/runtime-tools@0.13.1) + "@module-federation/managers": 0.13.1 + "@module-federation/manifest": 0.13.1(typescript@5.8.3) + "@module-federation/rspack": 0.13.1(@rspack/core@1.2.8(@swc/helpers@0.5.13))(typescript@5.8.3) + "@module-federation/runtime-tools": 0.13.1 + "@module-federation/sdk": 0.13.1 + btoa: 1.2.1 + schema-utils: 4.3.2 + upath: 2.0.1 + optionalDependencies: + typescript: 5.8.3 + webpack: 5.99.8(esbuild@0.19.12) + transitivePeerDependencies: + - "@rspack/core" + - bufferutil + - debug + - react + - react-dom + - supports-color + - utf-8-validate + + "@module-federation/error-codes@0.11.4": {} + + "@module-federation/error-codes@0.13.1": {} + + "@module-federation/error-codes@0.8.4": {} + + "@module-federation/inject-external-runtime-core-plugin@0.13.1(@module-federation/runtime-tools@0.13.1)": + dependencies: + "@module-federation/runtime-tools": 0.13.1 + + "@module-federation/managers@0.13.1": + dependencies: + "@module-federation/sdk": 0.13.1 + find-pkg: 2.0.0 + fs-extra: 9.1.0 + + "@module-federation/manifest@0.13.1(typescript@5.8.3)": + dependencies: + "@module-federation/dts-plugin": 0.13.1(typescript@5.8.3) + "@module-federation/managers": 0.13.1 + "@module-federation/sdk": 0.13.1 + chalk: 3.0.0 + find-pkg: 2.0.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + "@module-federation/node@2.7.2(@rspack/core@1.2.8(@swc/helpers@0.5.13))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(webpack@5.99.8(esbuild@0.19.12))": + dependencies: + "@module-federation/enhanced": 0.13.1(@rspack/core@1.2.8(@swc/helpers@0.5.13))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(webpack@5.99.8(esbuild@0.19.12)) + "@module-federation/runtime": 0.13.1 + "@module-federation/sdk": 0.13.1 + btoa: 1.2.1 + encoding: 0.1.13 + node-fetch: 2.7.0(encoding@0.1.13) + webpack: 5.99.8(esbuild@0.19.12) + optionalDependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + transitivePeerDependencies: + - "@rspack/core" + - bufferutil + - debug + - supports-color + - typescript + - utf-8-validate + - vue-tsc + + "@module-federation/rspack@0.13.1(@rspack/core@1.2.8(@swc/helpers@0.5.13))(typescript@5.8.3)": + dependencies: + "@module-federation/bridge-react-webpack-plugin": 0.13.1 + "@module-federation/dts-plugin": 0.13.1(typescript@5.8.3) + "@module-federation/inject-external-runtime-core-plugin": 0.13.1(@module-federation/runtime-tools@0.13.1) + "@module-federation/managers": 0.13.1 + "@module-federation/manifest": 0.13.1(typescript@5.8.3) + "@module-federation/runtime-tools": 0.13.1 + "@module-federation/sdk": 0.13.1 + "@rspack/core": 1.2.8(@swc/helpers@0.5.13) + btoa: 1.2.1 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + "@module-federation/runtime-core@0.11.4": + dependencies: + "@module-federation/error-codes": 0.11.4 + "@module-federation/sdk": 0.11.4 + + "@module-federation/runtime-core@0.13.1": + dependencies: + "@module-federation/error-codes": 0.13.1 + "@module-federation/sdk": 0.13.1 + + "@module-federation/runtime-tools@0.13.1": + dependencies: + "@module-federation/runtime": 0.13.1 + "@module-federation/webpack-bundler-runtime": 0.13.1 + + "@module-federation/runtime-tools@0.8.4": + dependencies: + "@module-federation/runtime": 0.8.4 + "@module-federation/webpack-bundler-runtime": 0.8.4 + + "@module-federation/runtime@0.11.4": + dependencies: + "@module-federation/error-codes": 0.11.4 + "@module-federation/runtime-core": 0.11.4 + "@module-federation/sdk": 0.11.4 + + "@module-federation/runtime@0.13.1": + dependencies: + "@module-federation/error-codes": 0.13.1 + "@module-federation/runtime-core": 0.13.1 + "@module-federation/sdk": 0.13.1 + + "@module-federation/runtime@0.8.4": + dependencies: + "@module-federation/error-codes": 0.8.4 + "@module-federation/sdk": 0.8.4 + + "@module-federation/sdk@0.11.4": {} + + "@module-federation/sdk@0.13.1": {} + + "@module-federation/sdk@0.8.4": + dependencies: + isomorphic-rslog: 0.0.6 + + "@module-federation/third-party-dts-extractor@0.13.1": + dependencies: + find-pkg: 2.0.0 + fs-extra: 9.1.0 + resolve: 1.22.8 + + "@module-federation/webpack-bundler-runtime@0.13.1": + dependencies: + "@module-federation/runtime": 0.13.1 + "@module-federation/sdk": 0.13.1 + + "@module-federation/webpack-bundler-runtime@0.8.4": + dependencies: + "@module-federation/runtime": 0.8.4 + "@module-federation/sdk": 0.8.4 + + "@near-js/accounts@1.4.1(encoding@0.1.13)": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/providers": 1.0.3(encoding@0.1.13) + "@near-js/signers": 0.2.2 + "@near-js/transactions": 1.3.3 + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + "@noble/hashes": 1.7.1 + borsh: 1.0.0 + depd: 2.0.0 + is-my-json-valid: 2.20.6 + lru_map: 0.4.1 + near-abi: 0.2.0 + transitivePeerDependencies: + - encoding + + "@near-js/crypto@1.4.2": + dependencies: + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + "@noble/curves": 1.8.1 + borsh: 1.0.0 + randombytes: 2.1.0 + secp256k1: 5.0.1 + + "@near-js/keystores-browser@0.2.2": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/keystores": 0.2.2 + + "@near-js/keystores-node@0.1.2": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/keystores": 0.2.2 + + "@near-js/keystores@0.2.2": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/types": 0.3.1 + + "@near-js/providers@1.0.3(encoding@0.1.13)": + dependencies: + "@near-js/transactions": 1.3.3 + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + borsh: 1.0.0 + exponential-backoff: 3.1.2 + optionalDependencies: + node-fetch: 2.6.7(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + "@near-js/signers@0.2.2": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/keystores": 0.2.2 + "@noble/hashes": 1.3.3 + + "@near-js/transactions@1.3.3": + dependencies: + "@near-js/crypto": 1.4.2 + "@near-js/signers": 0.2.2 + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + "@noble/hashes": 1.7.1 + borsh: 1.0.0 + + "@near-js/types@0.3.1": {} + + "@near-js/utils@1.1.0": + dependencies: + "@near-js/types": 0.3.1 + "@scure/base": 1.2.5 + depd: 2.0.0 + mustache: 4.0.0 + + "@near-js/wallet-account@1.3.3(encoding@0.1.13)": + dependencies: + "@near-js/accounts": 1.4.1(encoding@0.1.13) + "@near-js/crypto": 1.4.2 + "@near-js/keystores": 0.2.2 + "@near-js/providers": 1.0.3(encoding@0.1.13) + "@near-js/signers": 0.2.2 + "@near-js/transactions": 1.3.3 + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + borsh: 1.0.0 + transitivePeerDependencies: + - encoding + + "@noble/curves@1.8.1": + dependencies: + "@noble/hashes": 1.7.1 + + "@noble/hashes@1.3.3": {} + + "@noble/hashes@1.7.1": {} + + "@notionhq/client@2.3.0(encoding@0.1.13)": + dependencies: + "@types/node-fetch": 2.6.12 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + "@petamoriken/float16@3.9.2": {} + + "@pkgjs/parseargs@0.11.0": + optional: true + + "@polka/url@1.0.0-next.29": {} + + "@rspack/binding-darwin-arm64@1.2.8": + optional: true + + "@rspack/binding-darwin-x64@1.2.8": + optional: true + + "@rspack/binding-linux-arm64-gnu@1.2.8": + optional: true + + "@rspack/binding-linux-arm64-musl@1.2.8": + optional: true + + "@rspack/binding-linux-x64-gnu@1.2.8": + optional: true + + "@rspack/binding-linux-x64-musl@1.2.8": + optional: true + + "@rspack/binding-win32-arm64-msvc@1.2.8": + optional: true + + "@rspack/binding-win32-ia32-msvc@1.2.8": + optional: true + + "@rspack/binding-win32-x64-msvc@1.2.8": + optional: true + + "@rspack/binding@1.2.8": + optionalDependencies: + "@rspack/binding-darwin-arm64": 1.2.8 + "@rspack/binding-darwin-x64": 1.2.8 + "@rspack/binding-linux-arm64-gnu": 1.2.8 + "@rspack/binding-linux-arm64-musl": 1.2.8 + "@rspack/binding-linux-x64-gnu": 1.2.8 + "@rspack/binding-linux-x64-musl": 1.2.8 + "@rspack/binding-win32-arm64-msvc": 1.2.8 + "@rspack/binding-win32-ia32-msvc": 1.2.8 + "@rspack/binding-win32-x64-msvc": 1.2.8 + + "@rspack/cli@1.2.8(@rspack/core@1.2.8(@swc/helpers@0.5.13))(@types/express@4.17.21)(webpack@5.99.8(esbuild@0.19.12))": + dependencies: + "@discoveryjs/json-ext": 0.5.7 + "@rspack/core": 1.2.8(@swc/helpers@0.5.13) + "@rspack/dev-server": 1.0.10(@rspack/core@1.2.8(@swc/helpers@0.5.13))(@types/express@4.17.21)(webpack@5.99.8(esbuild@0.19.12)) + colorette: 2.0.20 + exit-hook: 4.0.0 + interpret: 3.1.1 + rechoir: 0.8.0 + webpack-bundle-analyzer: 4.6.1 + yargs: 17.7.2 + transitivePeerDependencies: + - "@types/express" + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + + "@rspack/core@1.2.8(@swc/helpers@0.5.13)": + dependencies: + "@module-federation/runtime-tools": 0.8.4 + "@rspack/binding": 1.2.8 + "@rspack/lite-tapable": 1.0.1 + caniuse-lite: 1.0.30001717 + optionalDependencies: + "@swc/helpers": 0.5.13 + + "@rspack/dev-server@1.0.10(@rspack/core@1.2.8(@swc/helpers@0.5.13))(@types/express@4.17.21)(webpack@5.99.8(esbuild@0.19.12))": + dependencies: + "@rspack/core": 1.2.8(@swc/helpers@0.5.13) + chokidar: 3.6.0 + connect-history-api-fallback: 2.0.0 + express: 4.21.2 + http-proxy-middleware: 2.0.9(@types/express@4.17.21) + mime-types: 2.1.35 + p-retry: 4.6.2 + webpack-dev-middleware: 7.4.2(webpack@5.99.8(esbuild@0.19.12)) + webpack-dev-server: 5.0.4(webpack@5.99.8(esbuild@0.19.12)) + ws: 8.18.2 + transitivePeerDependencies: + - "@types/express" + - bufferutil + - debug + - supports-color + - utf-8-validate + - webpack + - webpack-cli + + "@rspack/lite-tapable@1.0.1": {} + + "@scure/base@1.2.5": {} + + "@sideway/address@4.1.5": + dependencies: + "@hapi/hoek": 9.3.0 + + "@sideway/formula@3.0.1": {} + + "@sideway/pinpoint@2.0.0": {} + + "@sinclair/typebox@0.32.35": {} + + "@swc/helpers@0.5.13": + dependencies: + tslib: 2.8.1 + + "@types/async-retry@1.4.9": + dependencies: + "@types/retry": 0.12.5 + + "@types/body-parser@1.19.5": + dependencies: + "@types/connect": 3.4.38 + "@types/node": 22.15.17 + + "@types/bonjour@3.5.13": + dependencies: + "@types/node": 22.15.17 + + "@types/connect-history-api-fallback@1.5.4": + dependencies: + "@types/express-serve-static-core": 5.0.6 + "@types/node": 22.15.17 + + "@types/connect@3.4.38": + dependencies: + "@types/node": 22.15.17 + + "@types/eslint-scope@3.7.7": + dependencies: + "@types/eslint": 9.6.1 + "@types/estree": 1.0.7 + + "@types/eslint@9.6.1": + dependencies: + "@types/estree": 1.0.7 + "@types/json-schema": 7.0.15 + + "@types/estree@1.0.7": {} + + "@types/express-serve-static-core@4.19.6": + dependencies: + "@types/node": 22.15.17 + "@types/qs": 6.9.18 + "@types/range-parser": 1.2.7 + "@types/send": 0.17.4 + + "@types/express-serve-static-core@5.0.6": + dependencies: + "@types/node": 22.15.17 + "@types/qs": 6.9.18 + "@types/range-parser": 1.2.7 + "@types/send": 0.17.4 + + "@types/express@4.17.21": + dependencies: + "@types/body-parser": 1.19.5 + "@types/express-serve-static-core": 4.19.6 + "@types/qs": 6.9.18 + "@types/serve-static": 1.15.7 + + "@types/http-errors@2.0.4": {} + + "@types/http-proxy@1.17.16": + dependencies: + "@types/node": 22.15.17 + + "@types/json-schema@7.0.15": {} + + "@types/lodash@4.17.16": {} + + "@types/mime@1.3.5": {} + + "@types/node-fetch@2.6.12": + dependencies: + "@types/node": 22.15.17 + form-data: 4.0.2 + + "@types/node-forge@1.3.11": + dependencies: + "@types/node": 22.15.17 + + "@types/node@22.15.17": + dependencies: + undici-types: 6.21.0 + + "@types/pg@8.15.1": + dependencies: + "@types/node": 22.15.17 + pg-protocol: 1.10.0 + pg-types: 4.0.2 + + "@types/qs@6.9.18": {} + + "@types/range-parser@1.2.7": {} + + "@types/retry@0.12.0": {} + + "@types/retry@0.12.2": {} + + "@types/retry@0.12.5": {} + + "@types/semver@7.5.8": {} + + "@types/send@0.17.4": + dependencies: + "@types/mime": 1.3.5 + "@types/node": 22.15.17 + + "@types/serve-index@1.9.4": + dependencies: + "@types/express": 4.17.21 + + "@types/serve-static@1.15.7": + dependencies: + "@types/http-errors": 2.0.4 + "@types/node": 22.15.17 + "@types/send": 0.17.4 + + "@types/sockjs@0.3.36": + dependencies: + "@types/node": 22.15.17 + + "@types/ws@8.18.1": + dependencies: + "@types/node": 22.15.17 + + "@webassemblyjs/ast@1.14.1": + dependencies: + "@webassemblyjs/helper-numbers": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + + "@webassemblyjs/floating-point-hex-parser@1.13.2": {} + + "@webassemblyjs/helper-api-error@1.13.2": {} + + "@webassemblyjs/helper-buffer@1.14.1": {} + + "@webassemblyjs/helper-numbers@1.13.2": + dependencies: + "@webassemblyjs/floating-point-hex-parser": 1.13.2 + "@webassemblyjs/helper-api-error": 1.13.2 + "@xtuc/long": 4.2.2 + + "@webassemblyjs/helper-wasm-bytecode@1.13.2": {} + + "@webassemblyjs/helper-wasm-section@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/wasm-gen": 1.14.1 + + "@webassemblyjs/ieee754@1.13.2": + dependencies: + "@xtuc/ieee754": 1.2.0 + + "@webassemblyjs/leb128@1.13.2": + dependencies: + "@xtuc/long": 4.2.2 + + "@webassemblyjs/utf8@1.13.2": {} + + "@webassemblyjs/wasm-edit@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/helper-wasm-section": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-opt": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + "@webassemblyjs/wast-printer": 1.14.1 + + "@webassemblyjs/wasm-gen@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + + "@webassemblyjs/wasm-opt@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + + "@webassemblyjs/wasm-parser@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-api-error": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + + "@webassemblyjs/wast-printer@1.14.1": + dependencies: + "@webassemblyjs/ast": 1.14.1 + "@xtuc/long": 4.2.2 + + "@xtuc/ieee754@1.2.0": {} + + "@xtuc/long@4.2.2": {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + adm-zip@0.5.16: {} + + agent-twitter-client@0.0.16: + dependencies: + "@sinclair/typebox": 0.32.35 + headers-polyfill: 3.3.0 + json-stable-stringify: 1.3.0 + node-fetch: 3.3.2 + otpauth: 9.4.0 + set-cookie-parser: 2.7.1 + tough-cookie: 4.1.4 + tslib: 2.8.1 + twitter-api-v2: 1.23.2 + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-html-community@0.0.8: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + array-flatten@1.1.1: {} + + async-retry@1.3.3: + dependencies: + retry: 0.13.1 + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + atomic-sleep@1.0.0: {} + + axios@1.9.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + batch@0.6.1: {} + + binary-extensions@2.3.0: {} + + bn.js@4.12.2: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + borsh@1.0.0: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brorand@1.1.0: {} + + browserslist@4.24.5: + dependencies: + caniuse-lite: 1.0.30001717 + electron-to-chromium: 1.5.152 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.5) + + btoa@1.2.1: {} + + buffer-from@1.1.2: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + bytes@3.1.2: {} + + cache-content-type@1.0.1: + dependencies: + mime-types: 2.1.35 + ylru: 1.4.0 + + 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 + + caniuse-lite@1.0.30001717: {} + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.4.1: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chrome-trace-event@1.0.4: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@11.1.0: {} + + commander@2.20.3: {} + + commander@7.2.0: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.0: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.0.2 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concurrently@9.1.2: + dependencies: + chalk: 4.1.2 + lodash: 4.17.21 + rxjs: 7.8.2 + shell-quote: 1.8.2 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + + connect-history-api-fallback@2.0.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + cookies@0.9.1: + dependencies: + depd: 2.0.0 + keygrip: 1.1.0 + + core-util-is@1.0.3: {} + + cron-parser@4.9.0: + dependencies: + luxon: 3.6.1 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@4.0.1: {} + + date-format@4.0.14: {} + + dateformat@4.6.3: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + deep-equal@1.0.1: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + default-gateway@6.0.3: + dependencies: + execa: 5.1.1 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@3.0.0: {} + + delayed-stream@1.0.0: {} + + delegates@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + destroy@1.2.0: {} + + detect-node@2.1.0: {} + + dns-packet@5.6.1: + dependencies: + "@leichtgewicht/ip-codec": 2.0.5 + + dotenv@16.5.0: {} + + drizzle-kit@0.30.6: + dependencies: + "@drizzle-team/brocli": 0.10.2 + "@esbuild-kit/esm-loader": 2.6.5 + esbuild: 0.19.12 + esbuild-register: 3.6.0(esbuild@0.19.12) + gel: 2.1.0 + transitivePeerDependencies: + - supports-color + + drizzle-orm@0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0): + optionalDependencies: + "@types/pg": 8.15.1 + gel: 2.1.0 + pg: 8.16.0 + + drizzle-seed@0.3.1(drizzle-orm@0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0)): + dependencies: + pure-rand: 6.1.0 + optionalDependencies: + drizzle-orm: 0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0) + + drizzle-zod@0.7.1(drizzle-orm@0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0))(zod@3.24.4): + dependencies: + drizzle-orm: 0.40.1(@types/pg@8.15.1)(gel@2.1.0)(pg@8.16.0) + zod: 3.24.4 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.152: {} + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + env-paths@3.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + 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 + + esbuild-register@3.6.0(esbuild@0.19.12): + dependencies: + debug: 4.4.0 + esbuild: 0.19.12 + transitivePeerDependencies: + - supports-color + + esbuild@0.17.19: + optionalDependencies: + "@esbuild/android-arm": 0.17.19 + "@esbuild/android-arm64": 0.17.19 + "@esbuild/android-x64": 0.17.19 + "@esbuild/darwin-arm64": 0.17.19 + "@esbuild/darwin-x64": 0.17.19 + "@esbuild/freebsd-arm64": 0.17.19 + "@esbuild/freebsd-x64": 0.17.19 + "@esbuild/linux-arm": 0.17.19 + "@esbuild/linux-arm64": 0.17.19 + "@esbuild/linux-ia32": 0.17.19 + "@esbuild/linux-loong64": 0.17.19 + "@esbuild/linux-mips64el": 0.17.19 + "@esbuild/linux-ppc64": 0.17.19 + "@esbuild/linux-riscv64": 0.17.19 + "@esbuild/linux-s390x": 0.17.19 + "@esbuild/linux-x64": 0.17.19 + "@esbuild/netbsd-x64": 0.17.19 + "@esbuild/openbsd-x64": 0.17.19 + "@esbuild/sunos-x64": 0.17.19 + "@esbuild/win32-arm64": 0.17.19 + "@esbuild/win32-ia32": 0.17.19 + "@esbuild/win32-x64": 0.17.19 + + esbuild@0.18.20: + optionalDependencies: + "@esbuild/android-arm": 0.18.20 + "@esbuild/android-arm64": 0.18.20 + "@esbuild/android-x64": 0.18.20 + "@esbuild/darwin-arm64": 0.18.20 + "@esbuild/darwin-x64": 0.18.20 + "@esbuild/freebsd-arm64": 0.18.20 + "@esbuild/freebsd-x64": 0.18.20 + "@esbuild/linux-arm": 0.18.20 + "@esbuild/linux-arm64": 0.18.20 + "@esbuild/linux-ia32": 0.18.20 + "@esbuild/linux-loong64": 0.18.20 + "@esbuild/linux-mips64el": 0.18.20 + "@esbuild/linux-ppc64": 0.18.20 + "@esbuild/linux-riscv64": 0.18.20 + "@esbuild/linux-s390x": 0.18.20 + "@esbuild/linux-x64": 0.18.20 + "@esbuild/netbsd-x64": 0.18.20 + "@esbuild/openbsd-x64": 0.18.20 + "@esbuild/sunos-x64": 0.18.20 + "@esbuild/win32-arm64": 0.18.20 + "@esbuild/win32-ia32": 0.18.20 + "@esbuild/win32-x64": 0.18.20 + + esbuild@0.19.12: + optionalDependencies: + "@esbuild/aix-ppc64": 0.19.12 + "@esbuild/android-arm": 0.19.12 + "@esbuild/android-arm64": 0.19.12 + "@esbuild/android-x64": 0.19.12 + "@esbuild/darwin-arm64": 0.19.12 + "@esbuild/darwin-x64": 0.19.12 + "@esbuild/freebsd-arm64": 0.19.12 + "@esbuild/freebsd-x64": 0.19.12 + "@esbuild/linux-arm": 0.19.12 + "@esbuild/linux-arm64": 0.19.12 + "@esbuild/linux-ia32": 0.19.12 + "@esbuild/linux-loong64": 0.19.12 + "@esbuild/linux-mips64el": 0.19.12 + "@esbuild/linux-ppc64": 0.19.12 + "@esbuild/linux-riscv64": 0.19.12 + "@esbuild/linux-s390x": 0.19.12 + "@esbuild/linux-x64": 0.19.12 + "@esbuild/netbsd-x64": 0.19.12 + "@esbuild/openbsd-x64": 0.19.12 + "@esbuild/sunos-x64": 0.19.12 + "@esbuild/win32-arm64": 0.19.12 + "@esbuild/win32-ia32": 0.19.12 + "@esbuild/win32-x64": 0.19.12 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + etag@1.8.1: {} + + eventemitter3@4.0.7: {} + + events@3.3.0: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit-hook@4.0.0: {} + + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + + exponential-backoff@3.1.2: {} + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-copy@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.0.6: {} + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-file-up@2.0.1: + dependencies: + resolve-dir: 1.0.1 + + find-pkg@2.0.0: + dependencies: + find-file-up: 2.0.1 + + flatted@3.3.3: {} + + follow-redirects@1.15.9: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gel@2.1.0: + dependencies: + "@petamoriken/float16": 3.9.2 + debug: 4.4.0 + env-paths: 3.0.0 + semver: 7.7.2 + shell-quote: 1.8.2 + which: 4.0.0 + transitivePeerDependencies: + - supports-color + + generate-function@2.3.1: + dependencies: + is-property: 1.0.2 + + generate-object-property@1.2.0: + dependencies: + is-property: 1.0.2 + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + 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-stream@6.0.1: {} + + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handle-thing@2.0.1: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + headers-polyfill@3.3.0: {} + + help-me@5.0.0: {} + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + + hono@4.7.9: {} + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-entities@2.6.0: {} + + http-assert@1.5.0: + dependencies: + deep-equal: 1.0.1 + http-errors: 1.8.1 + + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@1.7.2: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.1 + statuses: 1.5.0 + toidentifier: 1.0.0 + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + + http-proxy-middleware@2.0.9(@types/express@4.17.21): + dependencies: + "@types/http-proxy": 1.17.16 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + "@types/express": 4.17.21 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + human-signals@2.1.0: {} + + hyperdyperid@1.2.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + interpret@3.1.1: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.2.0: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + 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-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@2.0.0: {} + + is-my-ip-valid@1.0.1: {} + + is-my-json-valid@2.20.6: + dependencies: + generate-function: 2.3.1 + generate-object-property: 1.2.0 + is-my-ip-valid: 1.0.1 + jsonpointer: 5.0.1 + xtend: 4.0.2 + + is-network-error@1.1.0: {} + + is-number@7.0.0: {} + + is-plain-obj@3.0.0: {} + + is-property@1.0.2: {} + + 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-stream@2.0.1: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + is-windows@1.0.2: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isexe@3.1.1: {} + + isomorphic-rslog@0.0.6: {} + + isomorphic-ws@5.0.0(ws@8.18.0): + dependencies: + ws: 8.18.0 + + jackspeak@3.4.3: + dependencies: + "@isaacs/cliui": 8.0.2 + optionalDependencies: + "@pkgjs/parseargs": 0.11.0 + + jest-worker@27.5.1: + dependencies: + "@types/node": 22.15.17 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + joi@17.13.3: + dependencies: + "@hapi/hoek": 9.3.0 + "@hapi/topo": 5.1.0 + "@sideway/address": 4.1.5 + "@sideway/formula": 3.0.1 + "@sideway/pinpoint": 2.0.0 + + jose@6.0.11: {} + + joycon@3.1.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify@1.3.0: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + isarray: 2.0.5 + jsonify: 0.0.1 + object-keys: 1.1.1 + + json-stringify-safe@5.0.1: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonify@0.0.1: {} + + jsonpointer@5.0.1: {} + + keygrip@1.1.0: + dependencies: + tsscmp: 1.0.6 + + koa-compose@4.1.0: {} + + koa-convert@2.0.0: + dependencies: + co: 4.6.0 + koa-compose: 4.1.0 + + koa@2.16.1: + dependencies: + accepts: 1.3.8 + cache-content-type: 1.0.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookies: 0.9.1 + debug: 4.4.0 + delegates: 1.0.0 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + fresh: 0.5.2 + http-assert: 1.5.0 + http-errors: 1.8.1 + is-generator-function: 1.1.0 + koa-compose: 4.1.0 + koa-convert: 2.0.0 + on-finished: 2.4.1 + only: 0.0.2 + parseurl: 1.3.3 + statuses: 1.5.0 + type-is: 1.6.18 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + launch-editor@2.10.0: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.2 + + loader-runner@4.3.0: {} + + lodash.clonedeepwith@4.5.0: {} + + lodash@4.17.21: {} + + log-symbols@6.0.0: + dependencies: + chalk: 5.4.1 + is-unicode-supported: 1.3.0 + + log4js@6.9.1: + dependencies: + date-format: 4.0.14 + debug: 4.4.0 + flatted: 3.3.3 + rfdc: 1.4.1 + streamroller: 3.1.5 + transitivePeerDependencies: + - supports-color + + long-timeout@0.1.1: {} + + lru-cache@10.4.3: {} + + lru_map@0.4.1: {} + + luxon@3.6.1: {} + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + memfs@4.17.1: + dependencies: + "@jsonjoy.com/json-pack": 1.2.0(tslib@2.8.1) + "@jsonjoy.com/util": 1.6.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) + tslib: 2.8.1 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-fn@2.1.0: {} + + mimic-function@5.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mrmime@1.0.1: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + mustache@4.0.0: {} + + near-abi@0.2.0: + dependencies: + "@types/json-schema": 7.0.15 + + near-api-js@5.1.1(encoding@0.1.13): + dependencies: + "@near-js/accounts": 1.4.1(encoding@0.1.13) + "@near-js/crypto": 1.4.2 + "@near-js/keystores": 0.2.2 + "@near-js/keystores-browser": 0.2.2 + "@near-js/keystores-node": 0.1.2 + "@near-js/providers": 1.0.3(encoding@0.1.13) + "@near-js/signers": 0.2.2 + "@near-js/transactions": 1.3.3 + "@near-js/types": 0.3.1 + "@near-js/utils": 1.1.0 + "@near-js/wallet-account": 1.3.3(encoding@0.1.13) + "@noble/curves": 1.8.1 + borsh: 1.0.0 + depd: 2.0.0 + http-errors: 1.7.2 + near-abi: 0.2.0 + node-fetch: 2.6.7(encoding@0.1.13) + transitivePeerDependencies: + - encoding + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + nock@13.5.6: + dependencies: + debug: 4.4.0 + json-stringify-safe: 5.0.1 + propagate: 2.0.1 + transitivePeerDependencies: + - supports-color + + node-addon-api@5.1.0: {} + + node-domexception@1.0.0: {} + + node-fetch@2.6.7(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-forge@1.3.1: {} + + node-gyp-build@4.8.4: {} + + node-releases@2.0.19: {} + + node-schedule@2.1.1: + dependencies: + cron-parser: 4.9.0 + long-timeout: 0.1.1 + sorted-array-functions: 1.3.0 + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + obuf@1.1.2: {} + + on-exit-leak-free@2.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + only@0.0.2: {} + + open@10.1.2: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + + openapi3-ts@4.4.0: + dependencies: + yaml: 2.7.1 + + opener@1.5.2: {} + + ora@8.2.0: + dependencies: + chalk: 5.4.1 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + otpauth@9.4.0: + dependencies: + "@noble/hashes": 1.7.1 + + p-retry@4.6.2: + dependencies: + "@types/retry": 0.12.0 + retry: 0.13.1 + + p-retry@6.2.1: + dependencies: + "@types/retry": 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + + package-json-from-dist@1.0.1: {} + + parse-passwd@1.0.0: {} + + parseurl@1.3.3: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@0.1.12: {} + + pg-cloudflare@1.2.5: + optional: true + + pg-connection-string@2.9.0: {} + + pg-int8@1.0.1: {} + + pg-numeric@1.0.2: {} + + pg-pool@3.10.0(pg@8.16.0): + dependencies: + pg: 8.16.0 + + pg-protocol@1.10.0: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg-types@4.0.2: + dependencies: + pg-int8: 1.0.1 + pg-numeric: 1.0.2 + postgres-array: 3.0.4 + postgres-bytea: 3.0.0 + postgres-date: 2.1.0 + postgres-interval: 3.0.0 + postgres-range: 1.1.4 + + pg@8.16.0: + dependencies: + pg-connection-string: 2.9.0 + pg-pool: 3.10.0(pg@8.16.0) + pg-protocol: 1.10.0 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.2.5 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.0.0: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.2 + secure-json-parse: 2.7.0 + sonic-boom: 4.2.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.6.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.1 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + + postgres-array@2.0.0: {} + + postgres-array@3.0.4: {} + + postgres-bytea@1.0.0: {} + + postgres-bytea@3.0.0: + dependencies: + obuf: 1.1.2 + + postgres-date@1.0.7: {} + + postgres-date@2.1.0: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + postgres-interval@3.0.0: {} + + postgres-range@1.1.4: {} + + process-nextick-args@2.0.1: {} + + process-warning@4.0.1: {} + + propagate@2.0.1: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@1.1.0: {} + + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@2.3.1: {} + + pure-rand@6.1.0: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + + quick-format-unescaped@4.0.4: {} + + rambda@9.4.2: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + + react@19.1.0: {} + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + real-require@0.2.0: {} + + rechoir@0.8.0: + dependencies: + resolve: 1.22.10 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@1.22.8: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + retry@0.13.1: {} + + rfdc@1.4.1: {} + + rimraf@5.0.10: + dependencies: + glob: 10.4.5 + + rslog@1.2.3: {} + + run-applescript@7.0.0: {} + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + scheduler@0.26.0: {} + + schema-utils@4.3.2: + dependencies: + "@types/json-schema": 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + secp256k1@5.0.1: + dependencies: + elliptic: 6.6.1 + node-addon-api: 5.1.0 + node-gyp-build: 4.8.4 + + secure-json-parse@2.7.0: {} + + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + "@types/node-forge": 1.3.11 + node-forge: 1.3.1 + + semver@7.6.3: {} + + semver@7.7.2: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.1: {} + + 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 + + setprototypeof@1.1.0: {} + + setprototypeof@1.1.1: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.8.2: {} + + 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 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sirv@1.0.19: + dependencies: + "@polka/url": 1.0.0-next.29 + mrmime: 1.0.1 + totalist: 1.1.0 + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + + sorted-array-functions@1.3.0: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.0 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.0 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + + split2@4.2.0: {} + + statuses@1.5.0: {} + + statuses@2.0.1: {} + + stdin-discarder@0.2.2: {} + + streamroller@3.1.5: + dependencies: + date-format: 4.0.14 + debug: 4.4.0 + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tapable@2.2.1: {} + + terser-webpack-plugin@5.3.14(esbuild@0.19.12)(webpack@5.99.8(esbuild@0.19.12)): + dependencies: + "@jridgewell/trace-mapping": 0.3.25 + jest-worker: 27.5.1 + schema-utils: 4.3.2 + serialize-javascript: 6.0.2 + terser: 5.39.0 + webpack: 5.99.8(esbuild@0.19.12) + optionalDependencies: + esbuild: 0.19.12 + + terser@5.39.0: + dependencies: + "@jridgewell/source-map": 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + + thingies@1.21.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + thunky@1.1.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.0: {} + + toidentifier@1.0.1: {} + + totalist@1.1.0: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: {} + + tree-dump@1.0.2(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + tree-kill@1.2.2: {} + + tslib@2.8.1: {} + + tsscmp@1.0.6: {} + + twitter-api-v2@1.23.2: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typescript@5.8.3: {} + + undici-types@6.21.0: {} + + universalify@0.1.2: {} + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + upath@2.0.1: {} + + update-browserslist-db@1.1.3(browserslist@4.24.5): + dependencies: + browserslist: 4.24.5 + escalade: 3.2.0 + picocolors: 1.1.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + vary@1.1.2: {} + + wait-on@8.0.3: + dependencies: + axios: 1.9.0 + joi: 17.13.3 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.2 + transitivePeerDependencies: + - debug + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + web-streams-polyfill@3.3.3: {} + + webidl-conversions@3.0.1: {} + + webpack-bundle-analyzer@4.6.1: + dependencies: + acorn: 8.14.1 + acorn-walk: 8.3.4 + chalk: 4.1.2 + commander: 7.2.0 + gzip-size: 6.0.0 + lodash: 4.17.21 + opener: 1.5.2 + sirv: 1.0.19 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + webpack-dev-middleware@7.4.2(webpack@5.99.8(esbuild@0.19.12)): + dependencies: + colorette: 2.0.20 + memfs: 4.17.1 + mime-types: 2.1.35 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.2 + optionalDependencies: + webpack: 5.99.8(esbuild@0.19.12) + + webpack-dev-server@5.0.4(webpack@5.99.8(esbuild@0.19.12)): + dependencies: + "@types/bonjour": 3.5.13 + "@types/connect-history-api-fallback": 1.5.4 + "@types/express": 4.17.21 + "@types/serve-index": 1.9.4 + "@types/serve-static": 1.15.7 + "@types/sockjs": 0.3.36 + "@types/ws": 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.0 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.21.2 + graceful-fs: 4.2.11 + html-entities: 2.6.0 + http-proxy-middleware: 2.0.9(@types/express@4.17.21) + ipaddr.js: 2.2.0 + launch-editor: 2.10.0 + open: 10.1.2 + p-retry: 6.2.1 + rimraf: 5.0.10 + schema-utils: 4.3.2 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.2(webpack@5.99.8(esbuild@0.19.12)) + ws: 8.18.2 + optionalDependencies: + webpack: 5.99.8(esbuild@0.19.12) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + webpack-sources@3.2.3: {} + + webpack@5.99.8(esbuild@0.19.12): + dependencies: + "@types/eslint-scope": 3.7.7 + "@types/estree": 1.0.7 + "@types/json-schema": 7.0.15 + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/wasm-edit": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + acorn: 8.14.1 + browserslist: 4.24.5 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.18.1 + es-module-lexer: 1.7.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.2 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.14(esbuild@0.19.12)(webpack@5.99.8(esbuild@0.19.12)) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - "@swc/core" + - esbuild + - uglify-js + + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@4.0.0: + dependencies: + isexe: 3.1.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@7.5.10: {} + + ws@8.18.0: {} + + ws@8.18.2: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yaml@2.7.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + ylru@1.4.0: {} + + zod-to-json-schema@3.24.5(zod@3.24.4): + dependencies: + zod: 3.24.4 + + zod@3.24.4: {} diff --git a/apps/api/public/schemas/userProfile.v1.schema.json b/apps/api/public/schemas/userProfile.v1.schema.json new file mode 100644 index 00000000..d54c4fff --- /dev/null +++ b/apps/api/public/schemas/userProfile.v1.schema.json @@ -0,0 +1,41 @@ +{ + "$ref": "#/definitions/userProfile.v1", + "definitions": { + "userProfile.v1": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "image": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "ipfs_cid": { + "type": "string" + } + }, + "additionalProperties": false + }, + "backgroundImage": { + "$ref": "#/definitions/userProfile.v1/properties/image" + }, + "linktree": { + "type": "object", + "additionalProperties": { + "type": "string", + "format": "uri" + } + } + }, + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} diff --git a/backend/rspack.config.js b/apps/api/rspack.config.js similarity index 73% rename from backend/rspack.config.js rename to apps/api/rspack.config.js index f0881437..c2b7daed 100644 --- a/backend/rspack.config.js +++ b/apps/api/rspack.config.js @@ -8,20 +8,23 @@ module.exports = { entry: "./src/index", mode: isProduction ? "production" : "development", target: "async-node", - devtool: "source-map", + devtool: isProduction ? false : "source-map", watch: !isProduction, externals: { bufferutil: "commonjs bufferutil", "pg-native": "commonjs pg-native", + "@roamhq/wrtc": "commonjs @roamhq/wrtc", + "utf-8-validate": "commonjs utf-8-validate", }, output: { path: path.resolve(__dirname, "dist"), + filename: "main.cjs", clean: true, }, module: { rules: [ { - test: /\.tsx?$/, + test: /\.ts?$/, use: "builtin:swc-loader", exclude: /node_modules/, }, @@ -32,17 +35,14 @@ module.exports = { ], }, resolve: { - extensions: [".tsx", ".ts", ".js"], + extensions: [".ts", ".ts", ".js"], + alias: { + "@": path.resolve(__dirname, "./src"), + }, }, plugins: [ - new rspack.CopyRspackPlugin({ - patterns: [ - { - from: "../frontend/dist", - to: "public", - noErrorOnMissing: true, // Don't error in development when dist doesn't exist - }, - ], + new rspack.IgnorePlugin({ + resourceRegExp: /^pg-native$|^cloudflare:sockets$/, }), // new rspack.container.ModuleFederationPlugin({ // name: "host", diff --git a/apps/api/scripts/dev-server.js b/apps/api/scripts/dev-server.js new file mode 100755 index 00000000..2a39fb09 --- /dev/null +++ b/apps/api/scripts/dev-server.js @@ -0,0 +1,190 @@ +#!/usr/bin/env node +const { spawn } = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const dotenv = require("dotenv"); + +// Path to the dist directory +const distDir = path.join(__dirname, "../dist"); +const mainJsPath = path.join(distDir, "main.cjs"); +const envPath = path.join(__dirname, "../.env"); + +// Load environment variables from .env file +let envVars = {}; +if (fs.existsSync(envPath)) { + console.log(`๐Ÿ“„ Loading environment variables from ${envPath}`); + envVars = dotenv.parse(fs.readFileSync(envPath)); +} else { + console.warn(`โš ๏ธ No .env file found at ${envPath}`); + // Create a default .env file with DATABASE_URL if it doesn't exist + if (process.env.DATABASE_URL) { + console.log(`๐Ÿ“ Creating default .env file with DATABASE_URL`); + fs.writeFileSync(envPath, `DATABASE_URL=${process.env.DATABASE_URL}\n`); + envVars = { DATABASE_URL: process.env.DATABASE_URL }; + } +} + +let serverProcess = null; +let isRestarting = false; + +// Function to start or restart the server +function startServer() { + // Prevent multiple restarts from happening simultaneously + if (isRestarting) return; + isRestarting = true; + + // Kill existing server process if it exists + if (serverProcess) { + console.log("๐Ÿ”„ Restarting server..."); + serverProcess.kill("SIGTERM"); + + // Give the process some time to shut down gracefully + setTimeout(() => { + launchNewServer(); + }, 500); + } else { + launchNewServer(); + } +} + +function launchNewServer() { + try { + // Start the server + serverProcess = spawn("node", [mainJsPath], { + stdio: "inherit", + env: { + ...process.env, + ...envVars, + NODE_ENV: "development", + }, + }); + + serverProcess.on("error", (error) => { + console.error("Failed to start server:", error); + isRestarting = false; + }); + + serverProcess.on("exit", (code, signal) => { + if (signal !== "SIGTERM") { + console.log( + `Server process exited with code ${code} and signal ${signal}`, + ); + } + isRestarting = false; + }); + + // Reset the restarting flag after a short delay + setTimeout(() => { + isRestarting = false; + }, 1000); + } catch (error) { + console.error("Error launching server:", error); + isRestarting = false; + } +} + +// Track if this is the first build +let initialBuildTime = 0; +let lastRestartTime = 0; + +// Initial server start +// Wait a bit to ensure the initial build is complete +setTimeout(() => { + if (fs.existsSync(mainJsPath)) { + try { + // Record the initial build time + initialBuildTime = fs.statSync(mainJsPath).mtimeMs; + lastRestartTime = Date.now(); + startServer(); + + // Start watching for changes after the initial server start + setupWatcher(); + } catch (error) { + console.error("Error during initial server start:", error); + process.exit(1); + } + } else { + console.error(`โŒ Server entry point not found at ${mainJsPath}`); + console.log('Make sure to run "rspack build --watch" first'); + process.exit(1); + } +}, 1000); + +// Setup file watcher after initial server start +function setupWatcher() { + let debounceTimer; + let watcherInitialized = false; + + try { + // Watch for changes in the dist directory + const watcher = fs.watch( + distDir, + { recursive: true }, + (eventType, filename) => { + if (!watcherInitialized) { + watcherInitialized = true; + return; // Skip initial events + } + + // Debounce to avoid multiple restarts for the same build + clearTimeout(debounceTimer); + debounceTimer = setTimeout(() => { + try { + if (filename && filename.endsWith(".js")) { + const filePath = path.join(distDir, filename); + + // Check if file exists (it might have been deleted) + if (!fs.existsSync(filePath)) { + return; + } + + // Check if this is a new build (not the initial one) + const currentMtime = fs.statSync(filePath).mtimeMs; + const now = Date.now(); + + // Only restart if: + // 1. This is a new change (not the initial build) + // 2. It's been at least 2 seconds since the last restart (prevent rapid restarts) + if ( + currentMtime > initialBuildTime && + now - lastRestartTime > 2000 + ) { + console.log(`๐Ÿ“ฆ Detected changes in ${filename}`); + lastRestartTime = now; + startServer(); + } + } + } catch (error) { + console.error("Error in file watcher:", error); + } + }, 500); // 500ms debounce + }, + ); + + watcher.on("error", (error) => { + console.error("File watcher error:", error); + }); + + console.log("๐Ÿ” Watching for file changes in dist directory"); + } catch (error) { + console.error("Failed to setup file watcher:", error); + } +} + +// Handle process termination +process.on("SIGINT", () => { + if (serverProcess) { + console.log("Shutting down server..."); + serverProcess.kill("SIGTERM"); + } + process.exit(0); +}); + +// Handle uncaught exceptions +process.on("uncaughtException", (error) => { + console.error("Uncaught exception:", error); + if (serverProcess) { + serverProcess.kill("SIGTERM"); + } + process.exit(1); +}); diff --git a/apps/api/scripts/generate-json-schemas.ts b/apps/api/scripts/generate-json-schemas.ts new file mode 100644 index 00000000..76a48847 --- /dev/null +++ b/apps/api/scripts/generate-json-schemas.ts @@ -0,0 +1,40 @@ +import fs from "fs/promises"; +import path from "path"; +import { zodToJsonSchema } from "zod-to-json-schema"; +import { profileSchema } from "../src/types/zod/userProfile"; + +const schemasToGenerate = [ + { + // Filename will be userProfile.v1.schema.json + // The URL in metadata.type will be /schemas/userProfile.v1.schema.json + id: "userProfile.v1", + schema: profileSchema, + }, + // Add more schemas here as your application grows +]; + +// Output directory within the frontend's public assets +const outputDir = path.resolve(__dirname, "../public/schemas"); + +async function generateSchemas() { + try { + await fs.mkdir(outputDir, { recursive: true }); + console.log(`Ensured schema directory exists: ${outputDir}`); + + for (const item of schemasToGenerate) { + const jsonSchema = zodToJsonSchema(item.schema, item.id); + const outputPath = path.join(outputDir, `${item.id}.schema.json`); + await fs.writeFile(outputPath, JSON.stringify(jsonSchema, null, 2)); + console.log(`Generated JSON schema: ${outputPath}`); + console.log( + ` Accessible at public URL: /schemas/${item.id}.schema.json`, + ); + } + console.log("JSON schema generation complete."); + } catch (error) { + console.error("Error generating JSON schemas:", error); + process.exit(1); + } +} + +generateSchemas(); diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts new file mode 100644 index 00000000..0d8e3fdc --- /dev/null +++ b/apps/api/src/app.ts @@ -0,0 +1,66 @@ +import { ServiceProvider } from "@curatedotfun/core-services"; +import { createLogger } from "@curatedotfun/utils"; +import { Hono } from "hono"; +import { cors } from "hono/cors"; +import { secureHeaders } from "hono/secure-headers"; +import { db } from "./db"; +import { createAuthMiddleware } from "./middlewares/auth.middleware"; +import { apiRoutes } from "./routes/api"; +import { AppInstance, Env } from "./types/app"; +import { getAllowedOrigins } from "./utils/config"; +import { errorHandler } from "./utils/error"; + +const ALLOWED_ORIGINS = getAllowedOrigins(); + +export async function createApp(): Promise { + const logger = createLogger({ service: "api" }); + const sp = ServiceProvider.getInstance({ + db, + logger, + env: { + NODE_ENV: process.env.NODE_ENV || "development", + SUPER_ADMIN_ACCOUNTS: process.env.SUPER_ADMIN_ACCOUNTS, + TWITTER_USERNAME: process.env.TWITTER_USERNAME, + TWITTER_PASSWORD: process.env.TWITTER_PASSWORD, + TWITTER_EMAIL: process.env.TWITTER_EMAIL, + TWITTER_2FA_SECRET: process.env.TWITTER_2FA_SECRET, + MASTER_KEYPAIR: process.env.MASTER_KEYPAIR, + }, + }); + await sp.init(); + + const app = new Hono(); + + app.onError((err, c) => { + return errorHandler(err, c, logger); + }); + + app.use( + "*", + cors({ + origin: (origin) => { + if (ALLOWED_ORIGINS.includes(origin)) { + return origin; + } + return origin; + }, + allowMethods: ["GET", "POST"], + }), + ); + + app.use("*", secureHeaders()); + + app.use("*", async (c, next) => { + c.set("db", db); + c.set("sp", sp); + await next(); + }); + + // Apply auth middleware to all /api routes + app.use("/api/*", createAuthMiddleware()); + + // Mount API routes + app.route("/api", apiRoutes); + + return { app }; +} diff --git a/apps/api/src/db/index.ts b/apps/api/src/db/index.ts new file mode 100644 index 00000000..3340ee4d --- /dev/null +++ b/apps/api/src/db/index.ts @@ -0,0 +1,14 @@ +import { schema, type DB } from "@curatedotfun/shared-db"; +import { drizzle } from "drizzle-orm/node-postgres"; +import { Pool } from "pg"; + +if (!process.env.DATABASE_URL) { + throw new Error("DATABASE_URL environment variable is required"); +} + +const pool = new Pool({ + connectionString: process.env.DATABASE_URL!, +}); +const db: DB = drizzle({ client: pool, schema, casing: "snake_case" }); + +export { db, pool }; diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts new file mode 100644 index 00000000..f24e42f9 --- /dev/null +++ b/apps/api/src/index.ts @@ -0,0 +1,147 @@ +import { loadEnvConfig } from "./utils/config"; + +loadEnvConfig(); + +import { serve } from "@hono/node-server"; +import { createApp } from "./app"; +import { pool } from "./db"; +import { + cleanup, + createHighlightBox, + createSection, + createLogger, +} from "@curatedotfun/utils"; +import { ServiceProvider } from "@curatedotfun/core-services"; + +const PORT = Number(process.env.PORT) || 3000; +const logger = createLogger({ service: "api" }); + +async function startServer() { + try { + createSection("โšก STARTING SERVER โšก"); + + const { app } = await createApp(); + const sp = ServiceProvider.getInstance(); + + app.get("/health", (c) => { + const health = { + status: "OK", + timestamp: new Date().toISOString(), + }; + return c.json(health); + }); + + // Start the server + const server = serve({ + fetch: app.fetch, + port: PORT, + }); + + // Create a multi-line message for the highlight box + const serverMessage = [ + `๐Ÿš€ SERVER RUNNING ๐Ÿš€`, + ``, + `๐Ÿ“ก Available at:`, + `http://localhost:${PORT}`, + ``, + `โœจ Ready and accepting connections`, + ].join("\n"); + + createHighlightBox(serverMessage); + + createSection("SERVICES"); + + // Start all background task services + const backgroundServices = sp.getBackgroundTaskServices(); + if (backgroundServices.length > 0) { + logger.info( + `Starting ${backgroundServices.length} background task service(s)...`, + ); + for (const bgService of backgroundServices) { + bgService + .start() + .catch((err) => + logger.error( + `Error starting background service: ${err.message}`, + err, + ), + ); + } + } else { + logger.info("No background task services configured to start."); + } + + // Graceful shutdown handler + const gracefulShutdown = async (signal: string) => { + createSection("๐Ÿ›‘ SHUTTING DOWN ๐Ÿ›‘"); + logger.info(`Graceful shutdown initiated (${signal})`); + + try { + // Wait for server to close + await new Promise((resolve, reject) => { + server.close((err) => (err ? reject(err) : resolve())); + }); + logger.info("HTTP server closed"); + + const shutdownPromises = []; + + // Stop all background task services + const bgServicesToStop = sp.getBackgroundTaskServices(); // Get fresh list in case it changed + if (bgServicesToStop.length > 0) { + logger.info( + `Stopping ${bgServicesToStop.length} background task service(s)...`, + ); + for (const bgService of bgServicesToStop) { + shutdownPromises.push( + bgService + .stop() + .catch((err) => + logger.error( + `Error stopping background service: ${err.message}`, + err, + ), + ), + ); + } + } + + const distributionService = sp.getDistributionService(); + if ( + distributionService && + typeof distributionService.shutdown === "function" + ) { + shutdownPromises.push( + distributionService + .shutdown() + .then(() => logger.info("Distribution service stopped")), + ); + } + + // Database pool + shutdownPromises.push( + pool + .end() + .then(() => logger.info("Database connection pool closed.")), + ); + + await Promise.all(shutdownPromises); + + logger.info("Shutdown complete"); + process.exit(0); + } catch (error) { + logger.error("Error during shutdown:", error); + process.exit(1); + } + }; + + // Handle manual shutdown (Ctrl+C) and SIGTERM + process.once("SIGINT", () => gracefulShutdown("SIGINT")); + process.once("SIGTERM", () => gracefulShutdown("SIGTERM")); + } catch (error) { + logger.error(`Error during startup: ${error}`); + cleanup(); + process.exit(1); + } +} + +startServer(); diff --git a/apps/api/src/middlewares/auth.middleware.ts b/apps/api/src/middlewares/auth.middleware.ts new file mode 100644 index 00000000..394b8a36 --- /dev/null +++ b/apps/api/src/middlewares/auth.middleware.ts @@ -0,0 +1,31 @@ +import { Context, MiddlewareHandler, Next } from "hono"; +import { verify } from "hono/jwt"; +import { getCookie } from "hono/cookie"; + +export function createAuthMiddleware(): MiddlewareHandler { + return async (c: Context, next: Next) => { + const token = getCookie(c, "token"); + let accountId: string | null = null; + + if (token) { + const secret = process.env.JWT_SECRET; + if (!secret) { + console.error("JWT_SECRET is not set."); + c.status(500); + return c.json({ error: "Internal Server Error" }); + } + try { + const decodedPayload = await verify(token, secret); + if (decodedPayload && typeof decodedPayload.sub === "string") { + accountId = decodedPayload.sub; + } + } catch (error) { + // Invalid token, proceed as anonymous + console.warn("JWT verification failed:", error); + } + } + + c.set("accountId", accountId); + await next(); + }; +} diff --git a/apps/api/src/routes/api/activity.ts b/apps/api/src/routes/api/activity.ts new file mode 100644 index 00000000..b22ae096 --- /dev/null +++ b/apps/api/src/routes/api/activity.ts @@ -0,0 +1,470 @@ +import { ActivityServiceError } from "@curatedotfun/utils"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { Env } from "../../types/app"; + +import { + ActivityFeedPathParamsSchema, + ActivityListResponseSchema, + ActivityUserPathParamsSchema, + ApiErrorResponseSchema, + FeedInfoListResponseSchema, + GetLeaderboardApiQuerySchema, + GetUserActivitiesApiQuerySchema, + GlobalStatsResponseSchema, + LeaderboardResponseSchema, + UserFeedRankResponseSchema, +} from "@curatedotfun/types"; + +const activityRoutes = new Hono(); + +/** + * GET /api/activity/leaderboard + * Get the leaderboard + */ +activityRoutes.get( + "/leaderboard", + zValidator("query", GetLeaderboardApiQuerySchema), + async (c) => { + try { + const options = c.req.valid("query"); + + const sp = c.var.sp; + const activityService = sp.getActivityService(); + const leaderboard = + await activityService.getUserRankingLeaderboard(options); + + return c.json( + LeaderboardResponseSchema.parse({ + statusCode: 200, + success: true, + data: leaderboard, + }), + ); + } catch (error) { + console.error("Error in activityRoutes.get('/leaderboard'):", error); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + const message = + error instanceof Error && error.name === "ValidationError" + ? "Invalid query parameters" + : "Failed to fetch leaderboard"; + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: + error instanceof Error && error.name === "ValidationError" + ? 400 + : 500, + success: false, + error: { message }, + }), + error instanceof Error && error.name === "ValidationError" ? 400 : 500, + ); + } + }, +); + +/** + * GET /api/activity/stats + * Get global activity statistics + */ +activityRoutes.get("/stats", async (c) => { + try { + const sp = c.var.sp; + const activityService = sp.getActivityService(); + const stats = await activityService.getGlobalStats(); + + return c.json( + GlobalStatsResponseSchema.parse({ + statusCode: 200, + success: true, + data: stats, + }), + ); + } catch (error) { + console.error("Error in activityRoutes.get('/stats'):", error); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch global stats" }, + }), + 500, + ); + } +}); + +/** + * GET /api/activity/user/me + * Get activity log for the authenticated user + */ +activityRoutes.get("/user/me", async (c) => { + const accountId = c.get("accountId"); + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { + message: "Unauthorized: Missing or invalid authentication token", + }, + }), + 401, + ); + } + + try { + // Get services from the service provider + const sp = c.var.sp; + const activityService = sp.getActivityService(); + + const activities = await activityService.getUserActivities(accountId); + + return c.json( + ActivityListResponseSchema.parse({ + statusCode: 200, + success: true, + data: activities, + }), + ); + } catch (error) { + console.error("Error in activityRoutes.get('/user/me'):", error); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch user activities" }, + }), + 500, + ); + } +}); + +/** + * GET /api/activity/user/:accountId + * Get activity log for a specific user by NEAR account ID + */ +activityRoutes.get( + "/user/:accountId", + zValidator("param", ActivityUserPathParamsSchema), + zValidator("query", GetUserActivitiesApiQuerySchema), + async (c) => { + try { + const { accountId } = c.req.valid("param"); + const options = c.req.valid("query"); + const sp = c.var.sp; + const activityService = sp.getActivityService(); + const activities = await activityService.getUserActivities( + accountId, + options, + ); + + return c.json( + ActivityListResponseSchema.parse({ + statusCode: 200, + success: true, + data: activities, + }), + ); + } catch (error) { + console.error("Error in activityRoutes.get('/user/:accountId'):", error); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + const message = + error instanceof Error && error.name === "ValidationError" + ? "Invalid query parameters" + : "Failed to fetch user activities"; + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: + error instanceof Error && error.name === "ValidationError" + ? 400 + : 500, + success: false, + error: { message }, + }), + error instanceof Error && error.name === "ValidationError" ? 400 : 500, + ); + } + }, +); + +/** + * GET /api/activity/feeds/curated-by/me + * Get feeds curated by the authenticated user + */ +activityRoutes.get("/feeds/curated-by/me", async (c) => { + const accountId = c.get("accountId"); + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { + message: "Unauthorized: Missing or invalid authentication token", + }, + }), + 401, + ); + } + + try { + const sp = c.var.sp; + const userService = sp.getUserService(); + const activityService = sp.getActivityService(); + + const user = await userService.findUserByNearAccountId(accountId); + + if (!user) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: "User profile not found" }, + }), + 404, + ); + } + + // Get the feeds curated by the user + const feeds = await activityService.getFeedsCuratedByUser(user.id); + + return c.json( + FeedInfoListResponseSchema.parse({ + statusCode: 200, + success: true, + data: feeds, + }), + ); + } catch (error) { + console.error( + "Error in activityRoutes.get('/feeds/curated-by/me'):", + error, + ); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch curated feeds" }, + }), + 500, + ); + } +}); + +/** + * GET /api/activity/feeds/approved-by/me + * Get feeds approved by the authenticated user + */ +activityRoutes.get("/feeds/approved-by/me", async (c) => { + const accountId = c.get("accountId"); + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { + message: "Unauthorized: Missing or invalid authentication token", + }, + }), + 401, + ); + } + + try { + const sp = c.var.sp; + const userService = sp.getUserService(); + const activityService = sp.getActivityService(); + + const user = await userService.findUserByNearAccountId(accountId); + + if (!user) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: "User profile not found" }, + }), + 404, + ); + } + + // Get the feeds approved by the user + const feeds = await activityService.getFeedsApprovedByUser(user.id); + + return c.json( + FeedInfoListResponseSchema.parse({ + statusCode: 200, + success: true, + data: feeds, + }), + ); + } catch (error) { + console.error( + "Error in activityRoutes.get('/feeds/approved-by/me'):", + error, + ); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch approved feeds" }, + }), + 500, + ); + } +}); + +/** + * GET /api/activity/feeds/:feedId/my-rank + * Get the user's rank for a specific feed + */ +activityRoutes.get( + "/feeds/:feedId/my-rank", + zValidator("param", ActivityFeedPathParamsSchema), + async (c) => { + const accountId = c.get("accountId"); + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { + message: "Unauthorized: Missing or invalid authentication token", + }, + }), + 401, + ); + } + + try { + const { feedId } = c.req.valid("param"); + + const sp = c.var.sp; + const userService = sp.getUserService(); + const activityService = sp.getActivityService(); + + const user = await userService.findUserByNearAccountId(accountId); + + if (!user) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: "User profile not found" }, + }), + 404, + ); + } + + // Get the user's rank for the feed + const ranks = await activityService.getUserFeedRanks(user.id, feedId); + + return c.json( + UserFeedRankResponseSchema.parse({ + statusCode: 200, + success: true, + data: ranks, + }), + ); + } catch (error) { + console.error( + "Error in activityRoutes.get('/feeds/:feedId/my-rank'):", + error, + ); + + if (error instanceof ActivityServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch user feed ranks" }, + }), + 500, + ); + } + }, +); + +export { activityRoutes }; diff --git a/apps/api/src/routes/api/auth.ts b/apps/api/src/routes/api/auth.ts new file mode 100644 index 00000000..615ec1a3 --- /dev/null +++ b/apps/api/src/routes/api/auth.ts @@ -0,0 +1,67 @@ +import { Hono } from "hono"; +import { zValidator } from "@hono/zod-validator"; +import { z } from "zod"; +import { Env } from "../../types/app"; +import { setCookie } from "hono/cookie"; +import type { AuthService } from "@curatedotfun/core-services"; + +export const authRoutes = new Hono(); + +const CreateAuthRequestSchema = z.object({ + accountId: z.string(), +}); + +const VerifyAuthRequestSchema = z.object({ + token: z.string(), + accountId: z.string(), +}); + +authRoutes.post( + "/initiate-login", + zValidator("json", CreateAuthRequestSchema), + async (c) => { + const payload = c.req.valid("json"); + const sp = c.var.sp; + const authService = sp.getService("authService"); + const result = await authService.createAuthRequest(payload); + return c.json(result); + }, +); + +authRoutes.post( + "/verify-login", + zValidator("json", VerifyAuthRequestSchema), + async (c) => { + const payload = c.req.valid("json"); + const sp = c.var.sp; + const authService = sp.getService("authService"); + try { + const { jwt } = await authService.verifyAuthRequest(payload); + setCookie(c, "token", jwt, { + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "Strict", + path: "/", + maxAge: 60 * 60 * 24 * 7, // 7 days + }); + return c.json({ success: true }); + } catch (error: unknown) { + c.status(401); + return c.json({ + success: false, + error: error instanceof Error ? error.message : "Authentication failed", + }); + } + }, +); + +authRoutes.post("/logout", async (c) => { + setCookie(c, "token", "", { + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "Strict", + path: "/", + maxAge: 0, + }); + return c.json({ success: true }); +}); diff --git a/apps/api/src/routes/api/config.ts b/apps/api/src/routes/api/config.ts new file mode 100644 index 00000000..76b51c2d --- /dev/null +++ b/apps/api/src/routes/api/config.ts @@ -0,0 +1,6 @@ +import { Hono } from "hono"; +import { Env } from "@/types/app"; + +const configRoutes = new Hono(); + +export { configRoutes }; diff --git a/apps/api/src/routes/api/feeds.ts b/apps/api/src/routes/api/feeds.ts new file mode 100644 index 00000000..fd5c99dc --- /dev/null +++ b/apps/api/src/routes/api/feeds.ts @@ -0,0 +1,315 @@ +import { FeedService } from "@curatedotfun/core-services"; +import { + ApiErrorResponseSchema, + CanModerateResponseSchema, + CreateFeedRequestSchema, + FeedsWrappedResponseSchema, + FeedWrappedResponseSchema, + UpdateFeedRequestSchema, +} from "@curatedotfun/types"; +import { ForbiddenError, NotFoundError } from "@curatedotfun/utils"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { z } from "zod"; +import { Env } from "../../types/app"; + +const feedsRoutes = new Hono(); + +const feedIdParamSchema = z.object({ + feedId: z.string().min(1, "Feed ID is required"), +}); + +// GET /api/feeds - Get all feeds +feedsRoutes.get("/", async (c) => { + try { + const sp = c.var.sp; + const feedService: FeedService = sp.getFeedService(); + const feeds = await feedService.getAllFeeds(); + return c.json( + FeedsWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: feeds.map((feed) => ({ + ...feed, + config: feed.config, + })), + }), + ); + } catch (error) { + c.var.sp.getLogger().error({ error }, "Error fetching all feeds"); + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch feeds" }, + }), + 500, + ); + } +}); + +// POST /api/feeds - Create a new feed +feedsRoutes.post( + "/", + zValidator("json", CreateFeedRequestSchema), + async (c) => { + const accountId = c.get("accountId"); + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized. User must be logged in." }, + }), + 401, + ); + } + + try { + const feedConfig = c.req.valid("json"); + const sp = c.var.sp; + const feedService = sp.getFeedService(); + const newFeed = await feedService.createFeed(feedConfig, accountId); + + return c.json( + FeedWrappedResponseSchema.parse({ + statusCode: 201, + success: true, + data: { + ...newFeed, + config: newFeed.config, + }, + }), + 201, + ); + } catch (error) { + c.var.sp.getLogger().error({ error, accountId }, "Error creating feed"); + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to create feed" }, + }), + 500, + ); + } + }, +); + +// GET /api/feeds/:feedId - Get a specific feed +feedsRoutes.get( + "/:feedId", + zValidator("param", feedIdParamSchema), + async (c) => { + try { + const { feedId } = c.req.valid("param"); + const sp = c.var.sp; + const feedService = sp.getFeedService(); + const feed = await feedService.getFeedById(feedId); + + return c.json( + FeedWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: { + ...feed, + config: feed.config, + }, + }), + ); + } catch (error) { + c.var.sp.getLogger().error({ error }, `Error fetching feed`); + if (error instanceof NotFoundError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: error.message }, + }), + 404, + ); + } + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch feed" }, + }), + 500, + ); + } + }, +); + +// PUT /api/feeds/:feedId - Update an existing feed +feedsRoutes.put( + "/:feedId", + zValidator("param", feedIdParamSchema), + zValidator("json", UpdateFeedRequestSchema), + async (c) => { + const accountId = c.get("accountId"); + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized. User must be logged in." }, + }), + 401, + ); + } + + try { + const { feedId } = c.req.valid("param"); + const feedConfig = c.req.valid("json"); + const sp = c.var.sp; + const feedService = sp.getFeedService(); + + const updatedFeed = await feedService.updateFeed( + feedId, + feedConfig, + accountId, + ); + + return c.json( + FeedWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: { + ...updatedFeed, + config: updatedFeed.config, + }, + }), + ); + } catch (error) { + c.var.sp.getLogger().error({ error, accountId }, "Error updating feed"); + if (error instanceof NotFoundError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: error.message }, + }), + 404, + ); + } + if (error instanceof ForbiddenError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 403, + success: false, + error: { message: error.message }, + }), + 403, + ); + } + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to update feed" }, + }), + 500, + ); + } + }, +); + +// DELETE /api/feeds/:feedId - Delete a feed +feedsRoutes.delete( + "/:feedId", + zValidator("param", feedIdParamSchema), + async (c) => { + const accountId = c.get("accountId"); + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized. User must be logged in." }, + }), + 401, + ); + } + + try { + const { feedId } = c.req.valid("param"); + const sp = c.var.sp; + const feedService = sp.getFeedService(); + await feedService.deleteFeed(feedId, accountId); + return c.body(null, 204); + } catch (error: unknown) { + c.var.sp.getLogger().error({ error, accountId }, "Error deleting feed"); + if (error instanceof NotFoundError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: error.message }, + }), + 404, + ); + } + if (error instanceof ForbiddenError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 403, + success: false, + error: { message: error.message }, + }), + 403, + ); + } + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to delete feed" }, + }), + 500, + ); + } + }, +); + +// GET /api/feeds/:feedId/can-moderate - Check moderation permission +feedsRoutes.get( + "/:feedId/can-moderate", + zValidator("param", feedIdParamSchema), + async (c) => { + const actingAccountId = c.get("accountId"); + if (!actingAccountId) { + return c.json( + CanModerateResponseSchema.parse({ + canModerate: false, + reason: "User not authenticated", + }), + ); + } + + try { + const { feedId } = c.req.valid("param"); + const sp = c.var.sp; + const moderationService = sp.getModerationService(); + const canModerate = + await moderationService.checkUserFeedModerationPermission( + feedId, + actingAccountId, + ); + return c.json(CanModerateResponseSchema.parse({ canModerate })); + } catch (error: unknown) { + c.var.sp + .getLogger() + .error({ error, actingAccountId }, "Error in /:feedId/can-moderate"); + return c.json( + CanModerateResponseSchema.parse({ + canModerate: false, + error: "Failed to check moderation permission", + }), + 500, + ); + } + }, +); + +export { feedsRoutes }; diff --git a/apps/api/src/routes/api/index.ts b/apps/api/src/routes/api/index.ts new file mode 100644 index 00000000..beb3adb7 --- /dev/null +++ b/apps/api/src/routes/api/index.ts @@ -0,0 +1,41 @@ +import { Hono } from "hono"; +import { configRoutes } from "./config"; +import { feedsRoutes } from "./feeds"; +import { leaderboardRoutes } from "./leaderboard"; +import { processingRoutes } from "./processing"; +import { statsRoutes } from "./stats"; +import { submissionRoutes } from "./submission"; +import { testRoutes } from "./test"; +import { triggerRoutes } from "./trigger"; +import { twitterRoutes } from "./twitter"; +import { Env } from "@/types/app"; +import { usersRoutes } from "./users"; +import { activityRoutes } from "./activity"; +import { uploadRoutes } from "./upload"; +import { pluginsRoutes } from "./plugins"; +import { moderationRoutes } from "./moderation"; +import { authRoutes } from "./auth"; + +// Create main API router +export const apiRoutes = new Hono(); + +// Test routes in development +if (process.env.NODE_URL !== "production") { + apiRoutes.route("/test", testRoutes); +} + +// Mount sub-routers +apiRoutes.route("/twitter", twitterRoutes); +apiRoutes.route("/submissions", submissionRoutes); +apiRoutes.route("/feeds", feedsRoutes); +apiRoutes.route("/config", configRoutes); +apiRoutes.route("/plugins", pluginsRoutes); +apiRoutes.route("/leaderboard", leaderboardRoutes); +apiRoutes.route("/stats", statsRoutes); +apiRoutes.route("/trigger", triggerRoutes); +apiRoutes.route("/users", usersRoutes); +apiRoutes.route("/activity", activityRoutes); +apiRoutes.route("/upload", uploadRoutes); +apiRoutes.route("/moderate", moderationRoutes); +apiRoutes.route("/auth", authRoutes); +apiRoutes.route("/processing", processingRoutes); diff --git a/apps/api/src/routes/api/leaderboard.ts b/apps/api/src/routes/api/leaderboard.ts new file mode 100644 index 00000000..0e17fe0e --- /dev/null +++ b/apps/api/src/routes/api/leaderboard.ts @@ -0,0 +1,21 @@ +import { LeaderboardRepository } from "@curatedotfun/shared-db"; +import { Hono } from "hono"; +import { Env } from "@/types/app"; + +// TODO: depreciate and combine with activity routes +const leaderboardRoutes = new Hono(); + +/** + * Get the leaderboard data + * @param timeRange - Optional time range filter: "all", "month", "week", "today" + */ +leaderboardRoutes.get("/", async (c) => { + const db = c.get("db"); + const leaderboardRepository = new LeaderboardRepository(db); + const timeRange = c.req.query("timeRange") || "all"; + const leaderboard = + await leaderboardRepository.getCuratorStatsLeaderboard(timeRange); + return c.json(leaderboard); +}); + +export { leaderboardRoutes }; diff --git a/apps/api/src/routes/api/moderation.ts b/apps/api/src/routes/api/moderation.ts new file mode 100644 index 00000000..39ff6d61 --- /dev/null +++ b/apps/api/src/routes/api/moderation.ts @@ -0,0 +1,223 @@ +import { + ApiErrorResponseSchema, + CreateModerationRequestSchema, + ModerationActionWrappedResponseSchema, + ModerationActionListWrappedResponseSchema, + ModerationActionCreatedWrappedResponseSchema, + ModerationIdParamSchema, + SubmissionIdParamSchema, + SubmissionAndFeedIdsParamSchema, +} from "@curatedotfun/types"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { ModerationService } from "@curatedotfun/core-services"; +import { Env } from "../../types/app"; +import { NotFoundError, ServiceError } from "@curatedotfun/utils"; +import { createQueue, QUEUE_NAMES } from "@curatedotfun/shared-queue"; + +export const moderationRoutes = new Hono(); + +// Create a new moderation action +moderationRoutes.post( + "/", + zValidator("json", CreateModerationRequestSchema), + async (c) => { + const payload = c.req.valid("json"); + + try { + const moderationQueue = createQueue(QUEUE_NAMES.MODERATION); + + await moderationQueue.add(QUEUE_NAMES.MODERATION, { + ...payload, + source: "ui", + moderatorAccountIdType: "near", + }); + + // Return a 202 Accepted response + return c.json( + ModerationActionCreatedWrappedResponseSchema.parse({ + statusCode: 202, + success: true, + data: { message: "Moderation action accepted for processing." }, + }), + 202, + ); + } catch (error: unknown) { + console.error("Error in moderationRoutes.post('/'):", error); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to create moderation action" }, + }), + 500, + ); + } + }, +); + +// Get a specific moderation entry by its ID +moderationRoutes.get( + "/:id", + zValidator("param", ModerationIdParamSchema), + async (c) => { + const { id } = c.req.valid("param"); + const sp = c.var.sp; + const moderationService = + sp.getService("moderationService"); + try { + const moderation = await moderationService.getModerationById(id); + if (!moderation) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: "Moderation entry not found" }, + }), + 404, + ); + } + return c.json( + ModerationActionWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: moderation, + }), + ); + } catch (error: unknown) { + console.error("Error in moderationRoutes.get('/:id'):", error); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to get moderation entry" }, + }), + 500, + ); + } + }, +); + +// Get all moderation entries for a submission +moderationRoutes.get( + "/submission/:submissionId", + zValidator("param", SubmissionIdParamSchema), + async (c) => { + const { submissionId } = c.req.valid("param"); + const sp = c.var.sp; + const moderationService = + sp.getService("moderationService"); + try { + const moderations = + await moderationService.getModerationsForSubmission(submissionId); + return c.json( + ModerationActionListWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: moderations, + }), + ); + } catch (error: unknown) { + console.error( + "Error in moderationRoutes.get('/submission/:submissionId'):", + error, + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to get moderation entries" }, + }), + 500, + ); + } + }, +); + +// Get all moderation entries for a specific submission within a feed +moderationRoutes.get( + "/submission/:submissionId/feed/:feedId", + zValidator("param", SubmissionAndFeedIdsParamSchema), + async (c) => { + const { submissionId, feedId } = c.req.valid("param"); + const sp = c.var.sp; + const moderationService = + sp.getService("moderationService"); + try { + const moderations = + await moderationService.getModerationsForSubmissionFeed( + submissionId, + feedId, + ); + return c.json( + ModerationActionListWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: moderations, + }), + ); + } catch (error: unknown) { + console.error( + "Error in moderationRoutes.get('/submission/:submissionId/feed/:feedId'):", + error, + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to get moderation entries" }, + }), + 500, + ); + } + }, +); diff --git a/apps/api/src/routes/api/plugins.ts b/apps/api/src/routes/api/plugins.ts new file mode 100644 index 00000000..5146f042 --- /dev/null +++ b/apps/api/src/routes/api/plugins.ts @@ -0,0 +1,145 @@ +import { + InsertPlugin, + insertPluginSchema, + PluginRepository, + selectPluginSchema, + updatePluginSchema, +} from "@curatedotfun/shared-db"; +import { AppErrorCode, ServiceError } from "@curatedotfun/utils"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { HTTPException } from "hono/http-exception"; +import { z } from "zod"; +import { db } from "../../db"; +import { Env } from "../../types/app"; + +const pluginsRoutes = new Hono(); +const pluginRepository = new PluginRepository(db); + +// --- Register a new Plugin --- +pluginsRoutes.post( + "/", + zValidator( + "json", + insertPluginSchema.omit({ id: true, createdAt: true, updatedAt: true }), + ), + async (c) => { + const pluginData = c.req.valid("json"); + + try { + const newPlugin = await pluginRepository.createPlugin(pluginData); + return c.json(newPlugin, 201); + } catch (error: unknown) { + console.error("Error registering plugin:", { error, pluginData }); + if ( + error instanceof ServiceError && + error.errorCode === AppErrorCode.RESOURCE_CONFLICT + ) { + throw new HTTPException(409, { message: error.message }); + } + throw new HTTPException(500, { message: "Failed to register plugin" }); + } + }, +); + +// --- Get a specific Plugin by ID --- +pluginsRoutes.get( + "/:pluginId", + zValidator("param", z.object({ pluginId: z.string().uuid() })), + async (c) => { + const { pluginId } = c.req.valid("param"); + const plugin = await pluginRepository.getPlugin(pluginId); + + if (!plugin) { + throw new HTTPException(404, { message: "Plugin not found" }); + } + return c.json(plugin); + }, +); + +// --- List Plugins (filter by type and name) --- +pluginsRoutes.get( + "/", + zValidator( + "query", + z.object({ + type: selectPluginSchema.shape.type.optional(), + name: z.string().optional(), + }), + ), + async (c) => { + const { type, name } = c.req.valid("query"); + + const filters: any = {}; + if (type) filters.type = type; + if (name) filters.name = name; + + const result = await pluginRepository.listPlugins(filters); + return c.json(result); + }, +); + +// --- Update a Plugin (e.g., entryPoint, schemaDefinition) --- +pluginsRoutes.patch( + "/:pluginId", + zValidator("param", z.object({ pluginId: z.string().uuid() })), + zValidator( + "json", + updatePluginSchema.partial().omit({ + id: true, + createdAt: true, + name: true, + repoUrl: true, + }), + ), + async (c) => { + const { pluginId } = c.req.valid("param"); + const updateData = c.req.valid("json"); + + if (Object.keys(updateData).length === 0) { + throw new HTTPException(400, { message: "No update data provided" }); + } + + const updatedPlugin = await pluginRepository.updatePlugin( + pluginId, + updateData, + ); + + if (!updatedPlugin) { + throw new HTTPException(404, { + message: "Plugin not found or failed to update", + }); + } + return c.json(updatedPlugin); + }, +); + +// --- Delete a Plugin --- +pluginsRoutes.delete( + "/:pluginId", + zValidator("param", z.object({ pluginId: z.string().uuid() })), + async (c) => { + const { pluginId } = c.req.valid("param"); + + const deletedPlugin = await pluginRepository.deletePlugin(pluginId); + + if (!deletedPlugin) { + throw new HTTPException(404, { + message: "Plugin not found or failed to delete", + }); + } + return c.json({ + message: "Plugin deleted successfully", + plugin: deletedPlugin, + }); + }, +); + +pluginsRoutes.post("/reload", async (c) => { + const sp = c.get("sp"); + const pluginService = sp.getPluginService(); + await pluginService.reloadAllPlugins(); + return c.json({ success: true }); +}); + +export { pluginsRoutes }; diff --git a/apps/api/src/routes/api/processing.ts b/apps/api/src/routes/api/processing.ts new file mode 100644 index 00000000..a94bed8b --- /dev/null +++ b/apps/api/src/routes/api/processing.ts @@ -0,0 +1,303 @@ +import { createQueue, QUEUE_NAMES } from "@curatedotfun/shared-queue"; +import { + ApiErrorResponseSchema, + JobIdParamSchema, + ProcessingJobRetryResponseSchema, + ProcessingJobsResponseSchema, + ProcessingStepsResponseSchema, + SubmissionIdParamSchema, +} from "@curatedotfun/types"; +import { + NotFoundError, + ProcessorError, + ServiceError, +} from "@curatedotfun/utils"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { z } from "zod"; +import { Env } from "../../types/app"; +export const processingRoutes = new Hono(); + +// Get processing jobs for a submission +processingRoutes.get( + "/jobs/:submissionId", + zValidator("param", SubmissionIdParamSchema), + async (c) => { + const { submissionId } = c.req.valid("param"); + const feedId = c.req.query("feedId"); + const sp = c.var.sp; + const db = c.var.db; + + if (!feedId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 400, + success: false, + error: { message: "Missing required query parameter: feedId" }, + }), + 400, + ); + } + + try { + const processingService = sp.getProcessingService(); + const jobs = await processingService.getJobsBySubmissionAndFeed( + submissionId, + feedId, + ); + + return c.json( + ProcessingJobsResponseSchema.parse({ + statusCode: 200, + success: true, + data: { jobs }, + }), + ); + } catch (error: unknown) { + sp.getLogger().error( + { error, submissionId, feedId }, + "Error in processingRoutes.get('/jobs/:submissionId')", + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch processing jobs" }, + }), + 500, + ); + } + }, +); + +// Get processing steps for a job +processingRoutes.get( + "/jobs/:jobId/steps", + zValidator("param", JobIdParamSchema), + async (c) => { + const { jobId } = c.req.valid("param"); + const sp = c.var.sp; + const db = c.var.db; + + try { + const processingService = sp.getProcessingService(); + const steps = await processingService.getStepsByJobId(jobId); + + return c.json( + ProcessingStepsResponseSchema.parse({ + statusCode: 200, + success: true, + data: { steps }, + }), + ); + } catch (error: unknown) { + sp.getLogger().error( + { error, jobId }, + "Error in processingRoutes.get('/jobs/:jobId/steps')", + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch processing steps" }, + }), + 500, + ); + } + }, +); + +// Retry a failed processing job +processingRoutes.post( + "/jobs/:jobId/retry", + zValidator("param", JobIdParamSchema), + async (c) => { + const { jobId } = c.req.valid("param"); + const sp = c.var.sp; + + try { + const processingService = sp.getProcessingService(); + const submissionService = sp.getSubmissionService(); + const feedService = sp.getFeedService(); + + const originalJob = await processingService.getJobById(jobId); + if (!originalJob) { + throw new NotFoundError("ProcessingJob", jobId); + } + + if (originalJob.status !== "failed") { + throw new ProcessorError( + "job_not_failed", + "Only failed jobs can be retried.", + ); + } + + const submission = await submissionService.getSubmission( + originalJob.submissionId, + ); + if (!submission) { + throw new NotFoundError("Submission", originalJob.submissionId); + } + + const feed = await feedService.getFeedById(originalJob.feedId); + if (!feed || !feed.config) { + throw new NotFoundError("Feed or FeedConfig", originalJob.feedId); + } + + const processingQueue = createQueue(QUEUE_NAMES.SUBMISSION_PROCESSING); + const newQueueJob = await processingQueue.add( + QUEUE_NAMES.SUBMISSION_PROCESSING, + { + submissionId: originalJob.submissionId, + feedId: originalJob.feedId, + retryOfJobId: jobId, + }, + ); + + if (!newQueueJob || !newQueueJob.id) { + throw new ProcessorError( + "queue_error", + "Failed to create new job in queue.", + ); + } + + return c.json( + ProcessingJobRetryResponseSchema.parse({ + statusCode: 200, + success: true, + data: { + job: originalJob, // Returning original job, UI should refetch. + message: "Processing job retry initiated successfully", + }, + }), + ); + } catch (error: unknown) { + sp.getLogger().error( + { error, jobId }, + "Error in processingRoutes.post('/jobs/:jobId/retry')", + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to retry processing job" }, + }), + 500, + ); + } + }, +); + +// Define step ID param schema +const StepIdParamSchema = z.object({ + stepId: z.string(), +}); + +// Retry processing from a specific failed step +processingRoutes.post( + "/steps/:stepId/retry", + zValidator("param", StepIdParamSchema), + async (c) => { + const { stepId } = c.req.valid("param"); + const sp = c.var.sp; + + try { + const processingService = sp.getProcessingService(); + const feedService = sp.getFeedService(); + + // We need to get the job from the step to find the feed + const step = await processingService.getStepById(stepId); + if (!step) { + throw new NotFoundError("ProcessingStep", stepId); + } + const job = await processingService.getJobById(step.jobId); + if (!job) { + throw new NotFoundError("ProcessingJob", step.jobId); + } + + const feed = await feedService.getFeedById(job.feedId); + if (!feed || !feed.config?.outputs?.stream) { + throw new NotFoundError("Feed or FeedConfig", job.feedId); + } + + // Retry from the specific step + const newJob = await processingService.retryStep( + stepId, + feed as any, // Cast to avoid type issues with config structure + ); + + return c.json( + ProcessingJobRetryResponseSchema.parse({ + statusCode: 200, + success: true, + data: { + job: newJob, + message: "Processing step retry initiated successfully", + }, + }), + ); + } catch (error: unknown) { + sp.getLogger().error( + { error, stepId }, + "Error in processingRoutes.post('/steps/:stepId/retry')", + ); + + if (error instanceof NotFoundError || error instanceof ServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to retry processing step" }, + }), + 500, + ); + } + }, +); diff --git a/apps/api/src/routes/api/recap.ts b/apps/api/src/routes/api/recap.ts new file mode 100644 index 00000000..012fc7c6 --- /dev/null +++ b/apps/api/src/routes/api/recap.ts @@ -0,0 +1,313 @@ +// import { Hono } from "hono"; +// import { zValidator } from "@hono/zod-validator"; +// import { z } from "zod"; +// import { AppContext } from "../../types/app"; +// import { RecapConfig } from "../../types/recap"; +// import { logger } from "@curatedotfun/utils"; + +// // Create a router for recap API endpoints +// export const recapRouter = new Hono<{ Variables: { context: AppContext } }>(); + +// // Schema for validating recap configuration +// const recapConfigSchema = z.object({ +// id: z.string().min(1), +// name: z.string().min(1), +// enabled: z.boolean(), +// schedule: z +// .string() +// .regex( +// /^(@every|(?:\d+ [\d\*\/,-]+.*)|(?:[a-z]+:\d+))$/, +// "invalid schedule", +// ), +// timezone: z +// .string() +// .optional() +// .refine((tz) => !tz || Intl.supportedValuesOf("timeZone").includes(tz), { +// message: "invalid timezone", +// }), +// transform: z +// .array( +// z.object({ +// plugin: z.string(), +// config: z.record(z.any()), +// }), +// ) +// .optional(), +// batchTransform: z +// .array( +// z.object({ +// plugin: z.string(), +// config: z.record(z.any()), +// }), +// ) +// .optional(), +// distribute: z +// .array( +// z.object({ +// plugin: z.string(), +// config: z.record(z.string()), +// transform: z +// .array( +// z.object({ +// plugin: z.string(), +// config: z.record(z.any()), +// }), +// ) +// .optional(), +// }), +// ) +// .optional(), +// }); + +// // GET /api/feed/:feedId/recap +// // Get all recap configurations for a feed +// recapRouter.get("/:feedId/recap", async (c) => { +// const { feedId } = c.req.param(); +// const { feedRepository } = c.get("context"); + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// // Get recap states to include status information +// const recapStates = await feedRepository.getAllRecapStatesForFeed(feedId); + +// // Combine recap configs with their states +// const recaps = feedConfig.outputs?.recap ?? []; +// const recapsWithState = recaps.map((recap) => { +// const state = recapStates.find((s) => s.recapId === recap.id); +// return { +// ...recap, +// state: state +// ? { +// lastSuccessfulCompletion: state.lastSuccessfulCompletion, +// lastRunError: state.lastRunError, +// } +// : null, +// }; +// }); + +// return c.json({ recaps: recapsWithState }); +// } catch (error) { +// logger.error(`Error getting recap configs for feed ${feedId}:`, error); +// return c.json({ error: "Failed to get recap configurations" }, 500); +// } +// }); + +// // GET /api/feed/:feedId/recap/:recapIndex +// // Get a specific recap configuration +// recapRouter.get("/:feedId/recap/:recapIndex", async (c) => { +// const { feedId, recapIndex } = c.req.param(); +// const recapIdx = parseInt(recapIndex, 10); +// const { feedRepository } = c.get("context"); + +// if (isNaN(recapIdx) || recapIdx < 0) { +// return c.json({ error: "Invalid recap index" }, 400); +// } + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// const recaps = feedConfig.outputs.recap || []; +// if (recapIdx >= recaps.length) { +// return c.json({ error: "Recap configuration not found" }, 404); +// } + +// // Get recap state +// const recapId = recaps[recapIdx].id; +// const state = await feedRepository.getRecapState(feedId, recapId); + +// return c.json({ +// recap: { +// ...recaps[recapIdx], +// state: state +// ? { +// lastSuccessfulCompletion: state.lastSuccessfulCompletion, +// lastRunError: state.lastRunError, +// } +// : null, +// }, +// }); +// } catch (error) { +// logger.error( +// `Error getting recap config ${recapIdx} for feed ${feedId}:`, +// error, +// ); +// return c.json({ error: "Failed to get recap configuration" }, 500); +// } +// }); + +// // POST /api/feed/:feedId/recap +// // Add a new recap configuration +// recapRouter.post( +// "/:feedId/recap", +// zValidator("json", recapConfigSchema), +// async (c) => { +// const { feedId } = c.req.param(); +// const recapConfig = c.req.valid("json"); +// const { feedRepository, schedulerService } = c.get("context"); + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// // Initialize recap array if it doesn't exist +// if (!feedConfig.outputs.recap) { +// feedConfig.outputs.recap = []; +// } + +// // Add the new recap config +// feedConfig.outputs.recap.push(recapConfig); + +// // Update feed config +// await feedRepository.updateFeedConfig(feedId, feedConfig); + +// // Sync schedules to create the new job if enabled +// await schedulerService.syncFeedSchedules(feedId); + +// return c.json({ +// success: true, +// recapIndex: feedConfig.outputs.recap.length - 1, +// }); +// } catch (error) { +// logger.error(`Error adding recap config for feed ${feedId}:`, error); +// return c.json({ error: "Failed to add recap configuration" }, 500); +// } +// }, +// ); + +// // PUT /api/feed/:feedId/recap/:recapIndex +// // Update a specific recap configuration +// recapRouter.put( +// "/:feedId/recap/:recapIndex", +// zValidator("json", recapConfigSchema), +// async (c) => { +// const { feedId, recapIndex } = c.req.param(); +// const recapIdx = parseInt(recapIndex, 10); +// const recapConfig = c.req.valid("json"); +// const { feedRepository, schedulerService } = c.get("context"); + +// if (isNaN(recapIdx) || recapIdx < 0) { +// return c.json({ error: "Invalid recap index" }, 400); +// } + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// // Initialize recap array if it doesn't exist +// if (!feedConfig.outputs.recap) { +// feedConfig.outputs.recap = []; +// } + +// // Check if recap exists +// if (recapIdx >= feedConfig.outputs.recap.length) { +// return c.json({ error: "Recap configuration not found" }, 404); +// } + +// // Update the recap config +// feedConfig.outputs.recap[recapIdx] = recapConfig; + +// // Update feed config +// await feedRepository.updateFeedConfig(feedId, feedConfig); + +// // Sync schedules to update the job +// await schedulerService.syncFeedSchedules(feedId); + +// return c.json({ success: true }); +// } catch (error) { +// logger.error( +// `Error updating recap config ${recapIdx} for feed ${feedId}:`, +// error, +// ); +// return c.json({ error: "Failed to update recap configuration" }, 500); +// } +// }, +// ); + +// // DELETE /api/feed/:feedId/recap/:recapIndex +// // Delete a specific recap configuration +// recapRouter.delete("/:feedId/recap/:recapIndex", async (c) => { +// const { feedId, recapIndex } = c.req.param(); +// const recapIdx = parseInt(recapIndex, 10); +// const { feedRepository, schedulerService } = c.get("context"); + +// if (isNaN(recapIdx) || recapIdx < 0) { +// return c.json({ error: "Invalid recap index" }, 400); +// } + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// // Check if recap exists +// if ( +// !feedConfig.outputs.recap || +// recapIdx >= feedConfig.outputs.recap.length +// ) { +// return c.json({ error: "Recap configuration not found" }, 404); +// } + +// // Remove the recap config +// feedConfig.outputs.recap.splice(recapIdx, 1); + +// // Update feed config +// await feedRepository.updateFeedConfig(feedId, feedConfig); + +// // Sync schedules to delete the job +// await schedulerService.syncFeedSchedules(feedId); + +// return c.json({ success: true }); +// } catch (error) { +// logger.error( +// `Error deleting recap config ${recapIdx} for feed ${feedId}:`, +// error, +// ); +// return c.json({ error: "Failed to delete recap configuration" }, 500); +// } +// }); + +// // POST /api/feed/:feedId/recap/:recapIndex/run +// // Manually trigger a recap job +// recapRouter.post("/:feedId/recap/:recapIndex/run", async (c) => { +// const { feedId, recapIndex } = c.req.param(); +// const recapIdx = parseInt(recapIndex, 10); +// const { schedulerService, feedRepository } = c.get("context"); + +// if (isNaN(recapIdx) || recapIdx < 0) { +// return c.json({ error: "Invalid recap index" }, 400); +// } + +// try { +// const feedConfig = await feedRepository.getFeedConfig(feedId); +// if (!feedConfig) { +// return c.json({ error: "Feed not found" }, 404); +// } + +// const recaps = feedConfig.outputs.recap || []; +// if (recapIdx >= recaps.length) { +// return c.json({ error: "Recap configuration not found" }, 404); +// } + +// const recapId = recaps[recapIdx].id; +// await schedulerService.runRecapJob(feedId, recapId); +// return c.json({ success: true }); +// } catch (error) { +// logger.error( +// `Error running recap job ${recapIdx} for feed ${feedId}:`, +// error, +// ); +// return c.json({ error: "Failed to run recap job" }, 500); +// } +// }); diff --git a/apps/api/src/routes/api/stats.ts b/apps/api/src/routes/api/stats.ts new file mode 100644 index 00000000..af0ab214 --- /dev/null +++ b/apps/api/src/routes/api/stats.ts @@ -0,0 +1,41 @@ +import { SubmissionRepository } from "@curatedotfun/shared-db"; +import { Hono } from "hono"; +import { Env } from "@/types/app"; + +export const statsRoutes = new Hono(); + +/** + * Get platform statistics (used by landing page) + */ +statsRoutes.get("/", async (c) => { + const db = c.get("db"); + const sp = c.var.sp; + const submissionRepository = new SubmissionRepository(db); + // Get posts count from database + const postsCount = await submissionRepository.getPostsCount(); + + // Get curators count from database + const curatorsCount = await submissionRepository.getCuratorsCount(); + + // Get other stats from config + const feedService = sp.getFeedService(); + const allFeeds = await feedService.getAllFeeds(); // TODO: Optimize query (get count) + const feedsCount = allFeeds.length; + + // Count total distributions from all feeds' distribute arrays + let distributionsCount = 0; + allFeeds.forEach((feed) => { + const { config } = feed; + // Count stream distributions if enabled + if (config.outputs.stream?.enabled && config.outputs.stream.distribute) { + distributionsCount += config.outputs.stream.distribute.length; + } + }); + + return c.json({ + postsCount, + feedsCount, + curatorsCount, + distributionsCount, + }); +}); diff --git a/apps/api/src/routes/api/submission.ts b/apps/api/src/routes/api/submission.ts new file mode 100644 index 00000000..215c92a0 --- /dev/null +++ b/apps/api/src/routes/api/submission.ts @@ -0,0 +1,287 @@ +import { + SubmissionRepository, + FeedRepository, + PaginatedResponse, + RichSubmission, +} from "@curatedotfun/shared-db"; +import { + FeedContextSubmission, + Submission, + SubmissionFeed, + SubmissionStatus, + SubmissionStatusSchema, +} from "@curatedotfun/types"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { z } from "zod"; +import { Env } from "../../types/app"; + +const submissionRoutes = new Hono(); + +/** + * Get all submissions with optional status filtering and pagination + */ +submissionRoutes.get( + "/", + zValidator( + "query", + z.object({ + page: z.coerce.number().int().min(0).optional(), + limit: z.coerce.number().int().min(1).max(100).optional(), + status: z.enum(["pending", "approved", "rejected"]).optional(), + sortOrder: z.enum(["newest", "oldest"]).optional().default("newest"), + q: z.string().optional(), + }), + ), + async (c) => { + const db = c.get("db"); + const submissionRepository = new SubmissionRepository(db); + const { page, limit, status, sortOrder, q } = c.req.valid("query"); + + const repoResult: PaginatedResponse = + await submissionRepository.getAllSubmissions( + status, + sortOrder, + q, + page, + limit, + ); + + const domainItems: Submission[] = repoResult.items.map((rs) => { + let overallStatus: SubmissionStatus = SubmissionStatusSchema.enum.pending; + if (rs.moderationHistory && rs.moderationHistory.length > 0) { + // Prefer direct moderation history for overall status if available + const approvedAction = rs.moderationHistory.find( + (mh) => mh.action === "approve", + ); + const rejectedAction = rs.moderationHistory.find( + (mh) => mh.action === "reject", + ); + + if (approvedAction) + overallStatus = SubmissionStatusSchema.enum.approved; + else if (rejectedAction) + overallStatus = SubmissionStatusSchema.enum.rejected; + // If only pending or other actions, it remains PENDING by default + } else if (rs.feeds && rs.feeds.length > 0) { + // Fallback to feed statuses if no direct moderation history + if (rs.feeds.some((f) => f.status === "approved")) { + overallStatus = SubmissionStatusSchema.enum.approved; + } else if (rs.feeds.every((f) => f.status === "rejected")) { + overallStatus = SubmissionStatusSchema.enum.rejected; + } + // If feeds are all pending, it remains PENDING + } + + return { + tweetId: rs.tweetId, + userId: rs.userId, + username: rs.username, + curatorId: rs.curatorId!, + curatorUsername: rs.curatorUsername!, + content: rs.content, + curatorNotes: rs.curatorNotes, + curatorTweetId: rs.curatorTweetId!, + createdAt: rs.createdAt.toISOString(), + submittedAt: rs.submittedAt ? rs.submittedAt.toISOString() : null, + updatedAt: rs.updatedAt ? rs.updatedAt.toISOString() : null, + moderationHistory: (rs.moderationHistory ?? []).map((mh) => ({ + id: mh.id, + moderatorAccountId: mh.moderatorAccountId, + moderatorAccountIdType: mh.moderatorAccountIdType, + action: mh.action as "approve" | "reject", + submissionId: mh.submissionId, + source: mh.source, + feedId: mh.feedId, + note: mh.note, + createdAt: mh.createdAt.toISOString(), + updatedAt: mh.updatedAt + ? mh.updatedAt.toISOString() + : mh.createdAt.toISOString(), + })), + feeds: (rs.feeds ?? []).map( + (sf) => + ({ + submissionId: sf.submissionId, + feedId: sf.feedId, + status: sf.status as SubmissionStatus, + createdAt: sf.createdAt.toISOString(), + updatedAt: sf.updatedAt ? sf.updatedAt.toISOString() : null, + }) as SubmissionFeed, + ), + status: overallStatus, + }; + }); + + const response: PaginatedResponse = { + items: domainItems, + pagination: repoResult.pagination, + }; + + return c.json(response); + }, +); + +/** + * Get a specific submission by ID + */ +submissionRoutes.get("/single/:submissionId", async (c) => { + const db = c.get("db"); + const submissionRepository = new SubmissionRepository(db); + const submissionId = c.req.param("submissionId"); + const richSubmission = + await submissionRepository.getRichSubmission(submissionId); + + if (!richSubmission) { + return c.notFound(); + } + + let overallStatusSingle: SubmissionStatus = + SubmissionStatusSchema.enum.pending; + if ( + richSubmission.moderationHistory && + richSubmission.moderationHistory.length > 0 + ) { + const approvedAction = richSubmission.moderationHistory.find( + (mh) => mh.action === "approve", + ); + const rejectedAction = richSubmission.moderationHistory.find( + (mh) => mh.action === "reject", + ); + + if (approvedAction) + overallStatusSingle = SubmissionStatusSchema.enum.approved; + else if (rejectedAction) + overallStatusSingle = SubmissionStatusSchema.enum.rejected; + } else if (richSubmission.feeds && richSubmission.feeds.length > 0) { + if (richSubmission.feeds.some((f) => f.status === "approved")) { + overallStatusSingle = SubmissionStatusSchema.enum.approved; + } else if (richSubmission.feeds.every((f) => f.status === "rejected")) { + overallStatusSingle = SubmissionStatusSchema.enum.rejected; + } + } + + const domainSubmission: Submission = { + tweetId: richSubmission.tweetId, + userId: richSubmission.userId, + username: richSubmission.username, + curatorId: richSubmission.curatorId!, + curatorUsername: richSubmission.curatorUsername!, + content: richSubmission.content, + curatorNotes: richSubmission.curatorNotes, + curatorTweetId: richSubmission.curatorTweetId!, + createdAt: richSubmission.createdAt.toISOString(), + submittedAt: richSubmission.submittedAt + ? richSubmission.submittedAt.toISOString() + : null, + updatedAt: richSubmission.updatedAt + ? richSubmission.updatedAt.toISOString() + : null, + moderationHistory: (richSubmission.moderationHistory ?? []).map((mh) => ({ + id: mh.id, + moderatorAccountId: mh.moderatorAccountId, + moderatorAccountIdType: mh.moderatorAccountIdType, + source: mh.source, + action: mh.action as "approve" | "reject", + submissionId: mh.submissionId, + feedId: mh.feedId, + note: mh.note, + createdAt: mh.createdAt.toISOString(), + updatedAt: mh.updatedAt + ? mh.updatedAt.toISOString() + : mh.createdAt.toISOString(), + })), + feeds: (richSubmission.feeds ?? []).map( + (sf) => + ({ + submissionId: sf.submissionId, + feedId: sf.feedId, + status: sf.status as SubmissionStatus, + createdAt: sf.createdAt.toISOString(), + updatedAt: sf.updatedAt ? sf.updatedAt.toISOString() : null, + }) as SubmissionFeed, + ), + status: overallStatusSingle, + }; + + return c.json(domainSubmission); +}); + +/** + * Get submissions for a specific feed + */ +submissionRoutes.get( + "/feed/:feedId", + zValidator( + "query", + z.object({ + page: z.coerce.number().int().min(0).optional(), + limit: z.coerce.number().int().min(1).max(100).optional(), + status: z.enum(["pending", "approved", "rejected"]).optional(), + sortOrder: z.enum(["newest", "oldest"]).optional().default("newest"), + q: z.string().optional(), + }), + ), + async (c) => { + const db = c.get("db"); + const feedRepository = new FeedRepository(db); + const feedIdParam = c.req.param("feedId"); + const { page, limit, status, sortOrder, q } = c.req.valid("query"); + + const repoResult: PaginatedResponse = + await feedRepository.getSubmissionsByFeed( + feedIdParam, + status, + sortOrder, + q, + page, + limit, + ); + + const domainItems: FeedContextSubmission[] = repoResult.items.map((rs) => { + const specificFeedLink = rs.feeds.find((f) => f.feedId === feedIdParam); + + const statusInFeed: SubmissionStatus = specificFeedLink + ? (specificFeedLink.status as SubmissionStatus) + : SubmissionStatusSchema.enum.pending; + + return { + tweetId: rs.tweetId, + userId: rs.userId, + username: rs.username, + curatorId: rs.curatorId!, + curatorUsername: rs.curatorUsername!, + content: rs.content, + curatorNotes: rs.curatorNotes, + curatorTweetId: rs.curatorTweetId!, + createdAt: rs.createdAt.toISOString(), + submittedAt: rs.submittedAt ? rs.submittedAt.toISOString() : null, + updatedAt: rs.updatedAt ? rs.updatedAt.toISOString() : null, + status: statusInFeed, + moderationHistory: (rs.moderationHistory ?? []).map((mh) => ({ + id: mh.id, + moderatorAccountId: mh.moderatorAccountId, + moderatorAccountIdType: mh.moderatorAccountIdType, + source: mh.source, + action: mh.action as "approve" | "reject", + submissionId: mh.submissionId, + feedId: mh.feedId, + note: mh.note, + createdAt: mh.createdAt.toISOString(), + updatedAt: mh.updatedAt + ? mh.updatedAt.toISOString() + : mh.createdAt.toISOString(), + })), + }; + }); + + const response: PaginatedResponse = { + items: domainItems, + pagination: repoResult.pagination, + }; + + return c.json(response); + }, +); + +export { submissionRoutes }; diff --git a/apps/api/src/routes/api/test.ts b/apps/api/src/routes/api/test.ts new file mode 100644 index 00000000..805131b4 --- /dev/null +++ b/apps/api/src/routes/api/test.ts @@ -0,0 +1,116 @@ +import { MockTwitterService } from "@curatedotfun/core-services"; +import { zValidator } from "@hono/zod-validator"; +import { Tweet } from "agent-twitter-client"; +import { Hono } from "hono"; +import { z } from "zod"; +import { Env } from "../../types/app"; + +const testRoutes = new Hono(); + +// Guard middleware for development only +testRoutes.use("*", async (c, next) => { + if (process.env.NODE_ENV === "production") { + return c.notFound(); + } + await next(); +}); + +/** + * Mock a tweet submission. This is a protected endpoint. + */ +testRoutes.post( + "/mock-submission", + zValidator( + "json", + z.object({ + text: z.string(), + user: z.object({ + id: z.string(), + name: z.string(), + username: z.string(), + }), + }), + ), + async (c) => { + const sp = c.get("sp"); + const accountId = c.get("accountId"); + const twitterService = sp.getTwitterService(); + + if (!accountId) { + return c.json({ error: "Unauthorized" }, 401); + } + + const { text, user } = c.req.valid("json"); + + try { + const mockTweet: Partial = { + id: Date.now().toString(), + text, + username: user.username, + userId: user.id, + }; + + if (twitterService instanceof MockTwitterService) { + twitterService.addMockTweet(mockTweet); + return c.json({ success: true, message: "Mock tweet submitted." }); + } else { + return c.json( + { + success: false, + message: "Mock submission only available in test environment.", + }, + 400, + ); + } + } catch (error) { + c.var.sp.getLogger().error(`Failed to mock tweet submission: ${error}`); + return c.json( + { success: false, message: "Failed to mock tweet submission" }, + 500, + ); + } + }, +); + +// POST /api/test/tweets +testRoutes.post( + "/tweets", + zValidator( + "json", + z.object({ + text: z.string(), + username: z.string(), + inReplyToStatusId: z.string().optional(), + hashtags: z.array(z.string()).optional(), + }), + ), + async (c) => { + const sp = c.get("sp"); + const twitterService = sp.getTwitterService(); + const { text, username, inReplyToStatusId, hashtags } = c.req.valid("json"); + + if (twitterService instanceof MockTwitterService) { + const tweet = twitterService.addMockTweet({ + text, + username, + inReplyToStatusId, + hashtags, + }); + return c.json(tweet); + } + return c.json({ error: "Not a mock service" }, 400); + }, +); + +// POST /api/test/reset +testRoutes.post("/reset", (c) => { + const sp = c.get("sp"); + const twitterService = sp.getTwitterService(); + if (twitterService instanceof MockTwitterService) { + twitterService.clearMockTweets(); + return c.json({ success: true }); + } + return c.json({ error: "Not a mock service" }, 400); +}); + +export { testRoutes }; diff --git a/apps/api/src/routes/api/trigger.ts b/apps/api/src/routes/api/trigger.ts new file mode 100644 index 00000000..43e98be1 --- /dev/null +++ b/apps/api/src/routes/api/trigger.ts @@ -0,0 +1,48 @@ +import { Env } from "@/types/app"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { z } from "zod"; + +// Define validation schema for the recap job payload +const recapJobSchema = z.object({ + feedId: z.string(), + recapId: z.string(), +}); + +// Create a router for internal API endpoints +export const triggerRoutes = new Hono(); + +// TODO: Middleware to validate API token +// internalRouter.use(async (c, next) => { +// const apiToken = c.req.header("X-API-Token"); +// const expectedToken = process.env.INTERNAL_API_TOKEN; + +// if (!expectedToken || apiToken !== expectedToken) { +// logger.warn("Unauthorized access attempt to internal API"); +// return c.json({ error: "Unauthorized" }, 401); +// } + +// await next(); +// }); + +// POST /api/trigger/recap +// Endpoint for the scheduler to trigger recap jobs +triggerRoutes.post("/recap", zValidator("json", recapJobSchema), async (c) => { + const { feedId, recapId } = c.req.valid("json"); + const logger = c.var.sp.getLogger().child({ component: "TriggerRoutes" }); + + logger.info(`Received request to run recap: ${feedId}/${recapId}`); + + try { + // TODO: need to handle schedulerService injection + // await schedulerService.runRecapJob(feedId, recapId); + return c.json({ success: true }); + } catch (error) { + logger.error(`Error running recap job: ${feedId}/${recapId}`, error); + + const errorMessage = error instanceof Error ? error.message : String(error); + return c.json({ error: errorMessage }, 500); + } +}); + +export default triggerRoutes; diff --git a/backend/src/routes/api/twitter.ts b/apps/api/src/routes/api/twitter.ts similarity index 57% rename from backend/src/routes/api/twitter.ts rename to apps/api/src/routes/api/twitter.ts index bf660b70..d444900c 100644 --- a/backend/src/routes/api/twitter.ts +++ b/apps/api/src/routes/api/twitter.ts @@ -1,27 +1,28 @@ import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; import { z } from "zod"; -import { HonoApp } from "../../types/app"; +import { Env } from "../../types/app"; import { serviceUnavailable } from "../../utils/error"; -import { logger } from "../../utils/logger"; // Create Twitter routes -const router = HonoApp(); +const twitterRoutes = new Hono(); /** * Get the last checked tweet ID */ -router.get("/last-tweet-id", (c) => { - const context = c.get("context"); +twitterRoutes.get("/last-tweet-id", (c) => { + const sp = c.get("sp"); + const twitterService = sp.getTwitterService(); - if (!context.twitterService) { + if (!twitterService) { throw serviceUnavailable("Twitter"); } try { - const lastTweetId = context.twitterService.getLastCheckedTweetId(); + const lastTweetId = twitterService.getLastCheckedTweetId(); return c.json({ lastTweetId }); } catch (error) { - logger.error(`Failed to get last tweet ID: ${error}`); + c.var.sp.getLogger().error(`Failed to get last tweet ID: ${error}`); return c.json( { success: false, message: "Failed to retrieve last tweet ID" }, 500, @@ -32,7 +33,7 @@ router.get("/last-tweet-id", (c) => { /** * Set the last checked tweet ID */ -router.post( +twitterRoutes.post( "/last-tweet-id", zValidator( "json", @@ -41,18 +42,19 @@ router.post( }), ), async (c) => { - const context = c.get("context"); + const sp = c.get("sp"); + const twitterService = sp.getTwitterService(); - if (!context.twitterService) { + if (!twitterService) { throw serviceUnavailable("Twitter"); } const { tweetId } = c.req.valid("json"); try { - context.twitterService.setLastCheckedTweetId(tweetId); + twitterService.setLastCheckedTweetId(tweetId); return c.json({ success: true }); } catch (error) { - logger.error(`Failed to set last tweet ID: ${error}`); + c.var.sp.getLogger().error(`Failed to set last tweet ID: ${error}`); return c.json( { success: false, message: "Failed to update tweet ID" }, 500, @@ -61,4 +63,4 @@ router.post( }, ); -export default router; +export { twitterRoutes }; diff --git a/apps/api/src/routes/api/upload.ts b/apps/api/src/routes/api/upload.ts new file mode 100644 index 00000000..8232aaac --- /dev/null +++ b/apps/api/src/routes/api/upload.ts @@ -0,0 +1,36 @@ +import { Hono } from "hono"; +import { PinataSDK } from "pinata-web3"; + +const IPFS_GATEWAY_URL = "potlock.mypinata.cloud"; + +export const sdk = new PinataSDK({ + pinataJwt: process.env.PINATA_JWT, + pinataGateway: IPFS_GATEWAY_URL, +}); + +const uploadRoutes = new Hono(); + +// Pinata Auth Key +uploadRoutes.get("/get-auth-key", async (c) => { + try { + const uuid = crypto.randomUUID(); + + const keyData = await sdk.keys.create({ + keyName: uuid.toString(), + maxUses: 1, + permissions: { endpoints: { pinning: { pinFileToIPFS: true } } }, + }); + + return c.json(keyData, 200); + } catch (error) { + console.error("Failed to create Pinata API key:", error); + const errorMessage = + error instanceof Error ? error.message : "An unexpected error occurred"; + return c.json( + { error: "Failed to create API key", details: errorMessage }, + 500, + ); + } +}); + +export { uploadRoutes }; diff --git a/apps/api/src/routes/api/users.ts b/apps/api/src/routes/api/users.ts new file mode 100644 index 00000000..aababcaa --- /dev/null +++ b/apps/api/src/routes/api/users.ts @@ -0,0 +1,336 @@ +import { + ApiErrorResponseSchema, + CreateUserRequestSchema, + UpdateUserRequestSchema, + UserDeletedWrappedResponseSchema, + UserNearAccountIdParamSchema, + UserProfileWrappedResponseSchema, +} from "@curatedotfun/types"; +import { + NearAccountError, + NotFoundError, + UserServiceError, +} from "@curatedotfun/utils"; +import { zValidator } from "@hono/zod-validator"; +import { Hono } from "hono"; +import { ContentfulStatusCode } from "hono/utils/http-status"; +import { Env } from "../../types/app"; + +const usersRoutes = new Hono(); + +// --- GET /api/users/me --- +usersRoutes.get("/me", async (c) => { + const accountId = c.get("accountId"); + const sp = c.var.sp; + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized: User not authenticated." }, + }), + 401, + ); + } + + try { + const userService = sp.getUserService(); + const user = await userService.findUserByNearAccountId(accountId); + + if (!user) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { + message: "User profile not found for the given NEAR account ID.", + }, + }), + 404, + ); + } + + return c.json( + UserProfileWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: user, + }), + ); + } catch (error) { + c.var.sp.getLogger().error({ error }, "Error in usersRoutes.get('/me')"); + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch user profile" }, + }), + 500, + ); + } +}); + +// --- POST /api/users --- +usersRoutes.post( + "/", + zValidator("json", CreateUserRequestSchema), + async (c) => { + const apiData = c.req.valid("json"); + + try { + const sp = c.var.sp; + const userService = sp.getUserService(); + + const newUser = await userService.createUser(apiData); + + return c.json( + UserProfileWrappedResponseSchema.parse({ + statusCode: 201, + success: true, + data: newUser, + }), + 201, + ); + } catch (error: unknown) { + c.var.sp.getLogger().error({ error }, "Error in usersRoutes.post('/')"); + + if ( + error instanceof NearAccountError || + error instanceof UserServiceError + ) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to create user profile" }, + }), + 500, + ); + } + }, +); + +// --- PUT /api/users/me --- +usersRoutes.put( + "/me", + zValidator("json", UpdateUserRequestSchema), + async (c) => { + const apiData = c.req.valid("json"); + const accountId = c.get("accountId"); + const sp = c.var.sp; + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized: User not authenticated." }, + }), + 401, + ); + } + + try { + const userService = sp.getUserService(); + const updatedUser = await userService.updateUserByNearAccountId( + accountId, + apiData, + ); + + if (!updatedUser) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: "User profile not found" }, + }), + 404, + ); + } + + return c.json( + UserProfileWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: updatedUser, + }), + ); + } catch (error) { + c.var.sp.getLogger().error({ error }, "Error in usersRoutes.put('/me')"); + + if (error instanceof NotFoundError || error instanceof UserServiceError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to update user profile" }, + }), + 500, + ); + } + }, +); + +// --- DELETE /api/users/me --- +usersRoutes.delete("/me", async (c) => { + const accountId = c.get("accountId"); + + if (!accountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 401, + success: false, + error: { message: "Unauthorized: User not authenticated." }, + }), + 401, + ); + } + + try { + const sp = c.var.sp; + const userService = sp.getUserService(); + const success = await userService.deleteUserByNearAccountId(accountId); + + if (success) { + return c.json( + UserDeletedWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: { message: "User profile deleted successfully" }, + }), + ); + } else { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to delete user profile" }, + }), + 500, + ); + } + } catch (error: unknown) { + c.var.sp.getLogger().error({ error }, "Error in usersRoutes.delete('/me')"); + + if ( + error instanceof NotFoundError || + error instanceof NearAccountError || + error instanceof UserServiceError + ) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: error.statusCode as ContentfulStatusCode, + success: false, + error: { message: error.message }, + }), + error.statusCode as ContentfulStatusCode, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to delete user profile" }, + }), + 500, + ); + } +}); + +// --- GET /api/users/by-near/:nearAccountId --- +usersRoutes.get( + "/by-near/:nearAccountId", + zValidator("param", UserNearAccountIdParamSchema), + async (c) => { + const { nearAccountId } = c.req.param(); + const sp = c.var.sp; + + if (!nearAccountId) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 400, + success: false, + error: { message: "nearAccountId path parameter is required." }, + }), + 400, + ); + } + + try { + const userService = sp.getUserService(); + const user = await userService.findUserByNearAccountId(nearAccountId); + + if (!user) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { + message: "User profile not found for the given NEAR account ID.", + }, + }), + 404, + ); + } + + return c.json( + UserProfileWrappedResponseSchema.parse({ + statusCode: 200, + success: true, + data: user, + }), + ); + } catch (error) { + c.var.sp + .getLogger() + .error( + { error }, + `Error in usersRoutes.get('/by-near/${nearAccountId}')`, + ); + + if (error instanceof NotFoundError) { + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 404, + success: false, + error: { message: error.message }, + }), + 404, + ); + } + + return c.json( + ApiErrorResponseSchema.parse({ + statusCode: 500, + success: false, + error: { message: "Failed to fetch user profile" }, + }), + 500, + ); + } + }, +); + +export { usersRoutes }; diff --git a/apps/api/src/types/app.ts b/apps/api/src/types/app.ts new file mode 100644 index 00000000..181af80e --- /dev/null +++ b/apps/api/src/types/app.ts @@ -0,0 +1,15 @@ +import type { ServiceProvider } from "@curatedotfun/core-services"; +import { Hono } from "hono"; +import { db } from "../db"; + +export type Env = { + Variables: { + db: typeof db; + sp: ServiceProvider; + accountId?: string | null; + }; +}; + +export interface AppInstance { + app: Hono; +} diff --git a/apps/api/src/types/recap.ts b/apps/api/src/types/recap.ts new file mode 100644 index 00000000..d29b0180 --- /dev/null +++ b/apps/api/src/types/recap.ts @@ -0,0 +1,63 @@ +import { DistributorConfig, TransformConfig } from "@curatedotfun/types"; + +/** + * Configuration for a recap job + */ +export interface RecapConfig { + /** Unique identifier for this recap configuration */ + id: string; + + /** Unique name for this recap configuration */ + name: string; + + /** Whether this recap is enabled */ + enabled: boolean; + + /** + * Schedule for the recap + * Can be a cron expression (e.g., "0 0 * * 0") or + * an interval specification (e.g., "day:1") + */ + schedule: string; + + /** Timezone for the schedule (e.g., "UTC", "America/New_York") */ + timezone?: string; + + /** Transformations to apply to the collected content */ + transform?: TransformConfig[]; + + /** Batch transformations to apply to the collected results */ + batchTransform?: TransformConfig[]; + + /** Distribution configurations */ + distribute?: DistributorConfig[]; +} + +/** + * State of a recap job + */ +export interface RecapState { + /** Internal ID for this state record */ + id: number; + + /** Feed ID this recap belongs to */ + feedId: string; + + /** Unique ID of the recap configuration */ + recapId: string; + + /** External job ID from the scheduler service */ + externalJobId: string | null; + + /** Last time this recap was successfully processed */ + lastSuccessfulCompletion: Date | null; + + /** Error message if the last run failed */ + lastRunError: string | null; + + /** Creation timestamp */ + createdAt: Date; + + /** Last update timestamp */ + updatedAt: Date | null; +} diff --git a/apps/api/src/types/zod/userProfile.ts b/apps/api/src/types/zod/userProfile.ts new file mode 100644 index 00000000..eedb2114 --- /dev/null +++ b/apps/api/src/types/zod/userProfile.ts @@ -0,0 +1,20 @@ +import { z } from "zod"; + +export const socialImageSchema = z + .object({ + url: z.string().url().optional(), + }) + .strict(); + +export const profileSchema = z + .object({ + name: z.string().optional(), + description: z.string().optional(), + image: socialImageSchema.optional(), + backgroundImage: socialImageSchema.optional(), + linktree: z.record(z.string(), z.string().url()).optional(), + }) + .strict(); + +export type Profile = z.infer; +export type SocialImage = z.infer; diff --git a/apps/api/src/utils/config.ts b/apps/api/src/utils/config.ts new file mode 100644 index 00000000..c00173ce --- /dev/null +++ b/apps/api/src/utils/config.ts @@ -0,0 +1,23 @@ +import { config } from "dotenv"; +import path from "path"; + +const isTest = process.env.NODE_ENV === "test"; +/** + * Loads environment variables from the appropriate .env file + */ +export function loadEnvConfig(): void { + if (isTest) { + config({ path: path.resolve(process.cwd(), "backend/.env.test") }); + } else { + config({ path: path.resolve(process.cwd(), "backend/.env") }); + } +} + +/** + * Gets the allowed origins for CORS from environment variables + */ +export function getAllowedOrigins(): string[] { + return process.env.ALLOWED_ORIGINS + ? process.env.ALLOWED_ORIGINS.split(",").map((origin) => origin.trim()) + : []; +} diff --git a/backend/src/utils/error.ts b/apps/api/src/utils/error.ts similarity index 89% rename from backend/src/utils/error.ts rename to apps/api/src/utils/error.ts index 603363d4..304eef86 100644 --- a/backend/src/utils/error.ts +++ b/apps/api/src/utils/error.ts @@ -1,6 +1,6 @@ import { Context } from "hono"; import { HTTPException } from "hono/http-exception"; -import { logger } from "./logger"; +import type { Logger } from "pino"; /** * Error codes for API responses @@ -18,7 +18,7 @@ export enum ErrorCode { /** * Global error handler middleware */ -export function errorHandler(err: Error, c: Context) { +export function errorHandler(err: Error, c: Context, logger: Logger) { logger.error(`Error handling request: ${err.message}`, { path: c.req.path, method: c.req.method, diff --git a/apps/api/test/setup/seed-test.ts b/apps/api/test/setup/seed-test.ts new file mode 100644 index 00000000..abc0025d --- /dev/null +++ b/apps/api/test/setup/seed-test.ts @@ -0,0 +1,40 @@ +import { drizzle } from "drizzle-orm/node-postgres"; +import { Pool } from "pg"; +import * as schema from "@curatedotfun/shared-db"; + +// This seed file inserts seed data necessary for tests +async function main() { + console.log("Seeding test database... ", process.env.DATABASE_URL); + + if (!process.env.DATABASE_URL) { + throw new Error("DATABASE_URL environment variable is required"); + } + + // Create a connection to the database + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + }); + + // Initialize Drizzle with the pool + const db = drizzle(pool, { schema }); + + try { + console.log("Database seeded successfully!"); + } catch (error) { + console.error("Failed to seed database:", error); + throw error; + } finally { + // Close the connection + await pool.end(); + } +} + +main() + .then(() => { + console.log("Seeding complete."); + process.exit(0); + }) + .catch((err) => { + console.error("An error occurred while seeding:", err); + process.exit(1); + }); diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 00000000..1ef8c32c --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "tests"], + "references": [ + { "path": "../../packages/core-services" }, + { "path": "../../packages/shared-db" }, + { "path": "../../packages/shared-queue" }, + { "path": "../../packages/types" }, + { "path": "../../packages/utils" } + ] +} diff --git a/apps/app/.env.example b/apps/app/.env.example new file mode 100644 index 00000000..3b91e589 --- /dev/null +++ b/apps/app/.env.example @@ -0,0 +1,3 @@ +PUBLIC_WEB3_CLIENT_ID=your_web3_client_id +PUBLIC_NETWORK=testnet +PUBLIC_SMART_CONTRACT= \ No newline at end of file diff --git a/frontend/.gitignore b/apps/app/.gitignore similarity index 86% rename from frontend/.gitignore rename to apps/app/.gitignore index 6cedcb33..2d624c87 100644 --- a/frontend/.gitignore +++ b/apps/app/.gitignore @@ -8,6 +8,7 @@ pnpm-debug.log* lerna-debug.log* /node_modules +/node-compile-cache /dist dist-ssr *.local @@ -22,3 +23,6 @@ dist-ssr *.njsproj *.sln *.sw? +bun.lock + +.tanstack \ No newline at end of file diff --git a/frontend/README.md b/apps/app/README.md similarity index 72% rename from frontend/README.md rename to apps/app/README.md index 0b59a708..ca1c192f 100644 --- a/frontend/README.md +++ b/apps/app/README.md @@ -5,7 +5,7 @@
-

curate.fun frontend

+

app.curate.fun

React-based frontend application for the curate.fun platform @@ -37,16 +37,19 @@ The frontend leverages modern web technologies for optimal performance and developer experience: - **Framework**: [React](https://reactjs.org) + TypeScript + - Component-based architecture - Strong type safety - Excellent ecosystem support - **Build Tool**: [RSBuild](https://rsbuild.dev/) + - High-performance build system - Optimized production builds - Modern development experience - **Styling**: [Tailwind CSS](https://tailwindcss.com) + - Utility-first CSS framework - Highly customizable - Zero runtime overhead @@ -56,32 +59,6 @@ The frontend leverages modern web technologies for optimal performance and devel - Efficient navigation - Data-driven route handling -### Application Structure - -```bash -src/ -โ”œโ”€โ”€ components/ # React components -โ”‚ โ”œโ”€โ”€ FeedItem.tsx -โ”‚ โ”œโ”€โ”€ FeedList.tsx -โ”‚ โ”œโ”€โ”€ Header.tsx -โ”‚ โ”œโ”€โ”€ HowItWorks.tsx -โ”‚ โ”œโ”€โ”€ Layout.tsx -โ”‚ โ”œโ”€โ”€ Modal.tsx -โ”‚ โ””โ”€โ”€ Settings.tsx -โ”œโ”€โ”€ lib/ # Utility functions and API clients -โ”‚ โ”œโ”€โ”€ api.ts -โ”‚ โ”œโ”€โ”€ config.ts -โ”‚ โ””โ”€โ”€ twitter.ts -โ”œโ”€โ”€ routes/ # Application routes -โ”‚ โ”œโ”€โ”€ __root.tsx -โ”‚ โ”œโ”€โ”€ feed.$feedId.tsx -โ”‚ โ”œโ”€โ”€ index.tsx -โ”‚ โ””โ”€โ”€ settings.tsx -โ”œโ”€โ”€ types/ # TypeScript definitions -โ”œโ”€โ”€ App.tsx # Root component -โ””โ”€โ”€ index.tsx # Application entry point -``` - ## Key Features ### Content Display @@ -133,14 +110,14 @@ The app will be available at `http://localhost:5173` ## Backend Integration -The frontend communicates with the [backend service](../backend/README.md) through a RESTful API: +The frontend communicates with the [backend service](../api/README.md) through a RESTful API: - Content retrieval via `/api/feeds` endpoints - Settings management through `/api/settings` - Plugin configuration via `/api/plugins` - Content submission through Twitter integration -See the [Backend README](../backend/README.md) for detailed API documentation and service architecture. +See the [Backend README](../api/README.md) for detailed API documentation and service architecture.

diff --git a/apps/app/components.json b/apps/app/components.json new file mode 100644 index 00000000..c48c246b --- /dev/null +++ b/apps/app/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "neutral", + "cssVariables": false, + "prefix": "" + }, + "aliases": { + "components": "src/components", + "utils": "src/lib/utils", + "ui": "src/components/ui", + "lib": "src/lib", + "hooks": "src/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/frontend/eslint.config.js b/apps/app/eslint.config.js similarity index 100% rename from frontend/eslint.config.js rename to apps/app/eslint.config.js diff --git a/frontend/index.html b/apps/app/index.html similarity index 65% rename from frontend/index.html rename to apps/app/index.html index 95c2a95e..2e670aef 100644 --- a/frontend/index.html +++ b/apps/app/index.html @@ -1,9 +1,10 @@ - + curate.fun - crowdsource automated content + - - + + + + +
+ diff --git a/apps/app/package.json b/apps/app/package.json new file mode 100644 index 00000000..203d7499 --- /dev/null +++ b/apps/app/package.json @@ -0,0 +1,81 @@ +{ + "name": "@curatedotfun/app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "rsbuild dev --port 5173", + "dev:pg": "rsbuild dev --port 5173", + "build": "rsbuild build && tsc --noEmit", + "preview": "rsbuild preview", + "lint": "eslint .", + "test": "echo 'No tests yet'", + "clean": "rm -rf dist .turbo" + }, + "dependencies": { + "@crosspost/sdk": "^0.3.1", + "@fastnear/utils": "^0.9.7", + "@hookform/resolvers": "^5.1.1", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.2", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-popover": "^1.1.14", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.1.12", + "@radix-ui/react-toast": "^1.2.14", + "@radix-ui/react-tooltip": "^1.2.7", + "@tailwindcss/typography": "^0.5.16", + "@tanstack/react-form": "^1.12.3", + "@tanstack/react-query": "^5.81.2", + "@tanstack/react-router": "^1.121.34", + "@tanstack/react-table": "^8.21.3", + "@tanstack/zod-form-adapter": "^0.42.1", + "autoprefixer": "^10.4.21", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "date-fns": "^4.1.0", + "fastintear": "latest", + "immer": "^10.1.1", + "lodash": "^4.17.21", + "lucide-react": "^0.483.0", + "near-sign-verify": "^0.4.1", + "pinata-web3": "^0.5.4", + "postcss": "^8.5.6", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-hook-form": "^7.58.1", + "react-icons": "^5.5.0", + "sonner": "^2.0.5", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^3.4.17", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.25.67", + "zustand": "^5.0.5" + }, + "devDependencies": { + "@crosspost/types": "^0.3.1", + "@curatedotfun/types": "workspace:*", + "@eslint/js": "^9.29.0", + "@rsbuild/core": "1.1.13", + "@rsbuild/plugin-react": "1.1.0", + "@tanstack/router-devtools": "1.97.23", + "@tanstack/router-plugin": "^1.121.34", + "@types/lodash": "^4.17.18", + "@types/react": "^18.3.23", + "@types/react-dom": "^18.3.7", + "@vitejs/plugin-react": "^4.6.0", + "dotenv": "^16.5.0", + "eslint": "^9.29.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^15.15.0", + "typescript": "5.8.3", + "typescript-eslint": "^8.35.0" + } +} diff --git a/frontend/postcss.config.js b/apps/app/postcss.config.js similarity index 100% rename from frontend/postcss.config.js rename to apps/app/postcss.config.js diff --git a/frontend/public/apple-touch-icon.png b/apps/app/public/apple-touch-icon.png similarity index 100% rename from frontend/public/apple-touch-icon.png rename to apps/app/public/apple-touch-icon.png diff --git a/frontend/public/curatedotfunicon1.png b/apps/app/public/curatedotfunicon1.png similarity index 100% rename from frontend/public/curatedotfunicon1.png rename to apps/app/public/curatedotfunicon1.png diff --git a/frontend/public/curatedotfuntransparenticon.png b/apps/app/public/curatedotfuntransparenticon.png similarity index 100% rename from frontend/public/curatedotfuntransparenticon.png rename to apps/app/public/curatedotfuntransparenticon.png diff --git a/frontend/public/favicon-96x96.png b/apps/app/public/favicon-96x96.png similarity index 100% rename from frontend/public/favicon-96x96.png rename to apps/app/public/favicon-96x96.png diff --git a/frontend/public/favicon.ico b/apps/app/public/favicon.ico similarity index 100% rename from frontend/public/favicon.ico rename to apps/app/public/favicon.ico diff --git a/frontend/public/favicon.svg b/apps/app/public/favicon.svg similarity index 100% rename from frontend/public/favicon.svg rename to apps/app/public/favicon.svg diff --git a/frontend/public/fonts/LondrinaSolid-NNS.ttf b/apps/app/public/fonts/LondrinaSolid-NNS.ttf similarity index 100% rename from frontend/public/fonts/LondrinaSolid-NNS.ttf rename to apps/app/public/fonts/LondrinaSolid-NNS.ttf diff --git a/apps/app/public/grid.png b/apps/app/public/grid.png new file mode 100644 index 00000000..d19ad60d Binary files /dev/null and b/apps/app/public/grid.png differ diff --git a/apps/app/public/icons/novice-badge.png b/apps/app/public/icons/novice-badge.png new file mode 100644 index 00000000..c9ec4c1f Binary files /dev/null and b/apps/app/public/icons/novice-badge.png differ diff --git a/frontend/public/icons/star-bronze.svg b/apps/app/public/icons/star-bronze.svg similarity index 100% rename from frontend/public/icons/star-bronze.svg rename to apps/app/public/icons/star-bronze.svg diff --git a/frontend/public/icons/star-gold.svg b/apps/app/public/icons/star-gold.svg similarity index 100% rename from frontend/public/icons/star-gold.svg rename to apps/app/public/icons/star-gold.svg diff --git a/frontend/public/icons/star-silver.svg b/apps/app/public/icons/star-silver.svg similarity index 100% rename from frontend/public/icons/star-silver.svg rename to apps/app/public/icons/star-silver.svg diff --git a/apps/app/public/images/ca1aeb55a83a97a139b53b47327bdcc0f02d6022.png b/apps/app/public/images/ca1aeb55a83a97a139b53b47327bdcc0f02d6022.png new file mode 100644 index 00000000..fa7288ff --- /dev/null +++ b/apps/app/public/images/ca1aeb55a83a97a139b53b47327bdcc0f02d6022.png @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://www.figma.com/design/3PPZahS4mHxkgAKQ90pqp3/Curate.fun?node-id=1780-14293&m=dev +HostUrl=https://www.figma.com/file/3PPZahS4mHxkgAKQ90pqp3/image/ca1aeb55a83a97a139b53b47327bdcc0f02d6022/download diff --git a/apps/app/public/images/curate-coins.png b/apps/app/public/images/curate-coins.png new file mode 100644 index 00000000..3aacb189 Binary files /dev/null and b/apps/app/public/images/curate-coins.png differ diff --git a/apps/app/public/images/feed-image.png b/apps/app/public/images/feed-image.png new file mode 100644 index 00000000..604ffb50 Binary files /dev/null and b/apps/app/public/images/feed-image.png differ diff --git a/apps/app/public/images/metamask.png b/apps/app/public/images/metamask.png new file mode 100644 index 00000000..b5aabbf4 Binary files /dev/null and b/apps/app/public/images/metamask.png differ diff --git a/apps/app/public/images/near-week.png b/apps/app/public/images/near-week.png new file mode 100644 index 00000000..64fdb7b5 Binary files /dev/null and b/apps/app/public/images/near-week.png differ diff --git a/apps/app/public/images/near.png b/apps/app/public/images/near.png new file mode 100644 index 00000000..c8ca8b9e Binary files /dev/null and b/apps/app/public/images/near.png differ diff --git a/apps/app/public/images/overview-bg.png b/apps/app/public/images/overview-bg.png new file mode 100644 index 00000000..a20ded01 Binary files /dev/null and b/apps/app/public/images/overview-bg.png differ diff --git a/apps/app/public/images/solana.jpeg b/apps/app/public/images/solana.jpeg new file mode 100644 index 00000000..0ef6d615 Binary files /dev/null and b/apps/app/public/images/solana.jpeg differ diff --git a/apps/app/public/images/solana.png b/apps/app/public/images/solana.png new file mode 100644 index 00000000..4e887dd2 Binary files /dev/null and b/apps/app/public/images/solana.png differ diff --git a/apps/app/public/images/web3-plug.png b/apps/app/public/images/web3-plug.png new file mode 100644 index 00000000..bc1e3fee Binary files /dev/null and b/apps/app/public/images/web3-plug.png differ diff --git a/frontend/public/site.webmanifest b/apps/app/public/site.webmanifest similarity index 99% rename from frontend/public/site.webmanifest rename to apps/app/public/site.webmanifest index 8e2aa83d..3164c1af 100644 --- a/frontend/public/site.webmanifest +++ b/apps/app/public/site.webmanifest @@ -18,4 +18,4 @@ "theme_color": "#ffffff", "background_color": "#ffffff", "display": "standalone" -} \ No newline at end of file +} diff --git a/frontend/public/web-app-manifest-192x192.png b/apps/app/public/web-app-manifest-192x192.png similarity index 100% rename from frontend/public/web-app-manifest-192x192.png rename to apps/app/public/web-app-manifest-192x192.png diff --git a/frontend/public/web-app-manifest-512x512.png b/apps/app/public/web-app-manifest-512x512.png similarity index 100% rename from frontend/public/web-app-manifest-512x512.png rename to apps/app/public/web-app-manifest-512x512.png diff --git a/apps/app/rsbuild.config.ts b/apps/app/rsbuild.config.ts new file mode 100644 index 00000000..7e502bb8 --- /dev/null +++ b/apps/app/rsbuild.config.ts @@ -0,0 +1,105 @@ +import { defineConfig, rspack } from "@rsbuild/core"; +import { pluginReact } from "@rsbuild/plugin-react"; +import { tanstackRouter } from "@tanstack/router-plugin/rspack"; +import "dotenv/config"; +import path from "path"; + +const network = process.env.PUBLIC_NETWORK || "testnet"; + +const isProduction = process.env.NODE_ENV === "production"; +const isStaging = process.env.NODE_ENV === "staging"; + +export default defineConfig({ + plugins: [pluginReact()], + html: { + template: "./index.html", + templateParameters: { + // near + networkId: network, + fastintear: + isProduction || isStaging + ? "https://unpkg.com/fastintear@latest/dist/umd/browser.global.js" + : "/js/fastintear.js", + }, + }, + source: { + alias: { + "@": path.resolve(__dirname, "./src"), + "@fonts": path.resolve(__dirname, "public/fonts"), + }, + define: { + "process.env": { + ...Object.keys(process.env) + .filter((key) => key.startsWith("PUBLIC_")) + .reduce((acc, key) => { + // @ts-expect-error whatever + acc[key] = JSON.stringify(process.env[key]); + return acc; + }, {}), + NODE_ENV: JSON.stringify(process.env.NODE_ENV), + }, + }, + }, + output: { + assetPrefix: "/", + }, + tools: { + rspack: { + plugins: [ + tanstackRouter({ + routesDirectory: "./src/routes", + enableRouteGeneration: true, + }), + ...(isProduction || isStaging + ? [] + : [ + new rspack.CopyRspackPlugin({ + patterns: [ + { + from: path.resolve( + __dirname, + "node_modules/fastintear/dist/umd/browser.global.js", + ), + to: "js/fastintear.js", + }, + ], + }), + ]), + ], + module: { + rules: [ + { + test: /\.(woff|woff2|eot|ttf|otf)$/i, + type: "asset/resource", + generator: { + filename: "fonts/[name][ext]", + }, + }, + { + test: /\.(png|jpg|jpeg|gif|svg|ico)$/i, + type: "asset/resource", + generator: { + filename: "images/[name][ext]", + }, + }, + ], + }, + }, + }, + server: { + port: 5173, + proxy: { + "/api": { + // target: "https://staging.curate.press", + target: "http://localhost:3000", + secure: false, + changeOrigin: true, + ws: true, + }, + }, + }, + dev: { + assetPrefix: "/", + writeToDisk: true, + }, +}); diff --git a/frontend/src/App.tsx b/apps/app/src/App.tsx similarity index 59% rename from frontend/src/App.tsx rename to apps/app/src/App.tsx index 708dc4c5..38751df6 100644 --- a/frontend/src/App.tsx +++ b/apps/app/src/App.tsx @@ -1,13 +1,17 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { createRouter, RouterProvider } from "@tanstack/react-router"; - import { routeTree } from "./routeTree.gen"; +import "./index.css"; + // Set up a Router instance const router = createRouter({ routeTree, defaultPreload: "intent", }); +const queryClient = new QueryClient(); + // Register things for typesafety declare module "@tanstack/react-router" { interface Register { @@ -16,7 +20,11 @@ declare module "@tanstack/react-router" { } function App() { - return ; + return ( + + + + ); } export default App; diff --git a/apps/app/src/components/AvatarProfile.tsx b/apps/app/src/components/AvatarProfile.tsx new file mode 100644 index 00000000..0c7554f9 --- /dev/null +++ b/apps/app/src/components/AvatarProfile.tsx @@ -0,0 +1,208 @@ +import { near } from "../lib/near"; +import { getProfile } from "../lib/near-social"; +import { useCallback, useEffect, useState } from "react"; +import { replaceIpfsUrl } from "../utils/ipfs"; + +// Constants +const DEFAULT_AVATAR = + "https://ipfs.near.social/ipfs/bafkreibiyqabm3kl24gcb2oegb7pmwdi6wwrpui62iwb44l7uomnn3lhbi"; + +interface NFTMetadata { + base_uri?: string; + [key: string]: unknown; +} + +interface NFTToken { + media?: string; + reference?: string; + metadata?: { + media?: string; + }; + [key: string]: unknown; +} + +type AvatarSize = "small" | "medium" | "large"; + +interface AvatarProfileProps { + accountId: string; + size?: AvatarSize; + style?: string; + image?: string; +} + +const sizeMap: Record = { + small: 24, + medium: 32, + large: 40, +}; + +export const AvatarProfile: React.FC = ({ + accountId, + size = "medium", + style, + image, +}) => { + const [avatar, setAvatar] = useState(null); + const [oldUrl, setOldUrl] = useState(null); + const [imageUrls, setImageUrl] = useState(null); + const [img, setImg] = useState(null); + + const replaceIpfs = useCallback( + (imageUrl: string) => { + if (oldUrl !== imageUrl && imageUrl) { + const newImageUrl = replaceIpfsUrl(imageUrl); + if (newImageUrl) { + setOldUrl(imageUrl); + setImageUrl(newImageUrl); + return; + } + } + if (imageUrl !== null) { + setImageUrl(null); + } + }, + [oldUrl], + ); + + const getThumbnailUrl = useCallback( + (imageUrl: string) => + imageUrl && !imageUrl.startsWith("data:image/") + ? `https://i.near.social/${imageUrl}` + : imageUrl, + [], + ); + + const fetchNFTMetadata = useCallback( + async (contractId: string, tokenId: string) => { + try { + const nftMetadata: NFTMetadata = await near.view({ + contractId, + methodName: "nft_metadata", + }); + const tokenMetadata: NFTToken = await near.view({ + contractId, + methodName: "nft_token", + args: { + token_id: tokenId, + }, + }); + + if (!nftMetadata || !tokenMetadata) return null; + + const imageUrl = tokenMetadata.media || ""; + + if (imageUrl) { + if ( + imageUrl.startsWith("https://") || + imageUrl.startsWith("http://") || + imageUrl.startsWith("data:image") + ) { + return imageUrl; + } + if (nftMetadata.base_uri) { + return `${nftMetadata.base_uri}/${imageUrl}`; + } + if (imageUrl.startsWith("Qm") || imageUrl.startsWith("ba")) { + return `https://ipfs.near.social/ipfs/${imageUrl}`; + } + return imageUrl; + } + + if (tokenMetadata.reference) { + const referenceUrl = await handleReferenceUrl( + nftMetadata.base_uri, + tokenMetadata.reference, + ); + if (referenceUrl) return referenceUrl; + } + + return null; + } catch (error) { + console.error("Error fetching NFT metadata:", error); + return null; + } + }, + [], + ); + + const handleReferenceUrl = async ( + baseUri: string | undefined, + reference: string, + ) => { + try { + if ( + baseUri === "https://arweave.net" && + !reference.startsWith("https://") + ) { + const res = await fetch(`${baseUri}/${reference}`); + const data = await res.json(); + return data.media; + } + if (reference.startsWith("https://") || reference.startsWith("http://")) { + const res = await fetch(reference); + const data = await res.json(); + return data.media; + } + if (reference.startsWith("ar://")) { + const res = await fetch( + `${"https://arweave.net"}/${reference.split("//")[1]}`, + ); + const data = await res.json(); + return data.media; + } + return null; + } catch (error) { + console.error("Error handling reference URL:", error); + return null; + } + }; + + useEffect(() => { + const fetchAvatar = async () => { + if (!accountId) return; + + try { + const profile = await getProfile(accountId); + + const avatarUrl = profile?.image?.ipfs_cid; + const nftData = profile?.image?.nft; + + if (nftData) { + const { contractId, tokenId } = nftData; + const imageUrl = await fetchNFTMetadata(contractId, tokenId); + if (imageUrl) { + const src = imageUrls || imageUrl; + setImg(src); + setAvatar(getThumbnailUrl(src)); + } + } else if (avatarUrl) { + setAvatar(`https://ipfs.near.social/ipfs/${avatarUrl}`); + } + } catch (error) { + console.error("Error fetching avatar:", error); + setAvatar(DEFAULT_AVATAR); + } + }; + + fetchAvatar(); + }, [accountId, fetchNFTMetadata, getThumbnailUrl, imageUrls]); + + const avatarSrc = + avatar || + (image ? `https://ipfs.near.social/ipfs/${image}` : DEFAULT_AVATAR); + const avatarSize = sizeMap[size]; + + return ( +
+ User Avatar replaceIpfs(img as string)} + /> +
+ ); +}; diff --git a/apps/app/src/components/BasicInformationForm.tsx b/apps/app/src/components/BasicInformationForm.tsx new file mode 100644 index 00000000..a9185cbd --- /dev/null +++ b/apps/app/src/components/BasicInformationForm.tsx @@ -0,0 +1,165 @@ +import { useAuth } from "../contexts/auth-context"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import { useFeedCreationStore } from "../store/feed-creation-store"; +import { ImageUpload } from "./ImageUpload"; +import { Button } from "./ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "./ui/form"; +import { Input } from "./ui/input"; +import { Textarea } from "./ui/textarea"; + +const BasicInformationFormSchema = z.object({ + profileImage: z.string().optional(), + feedName: z.string().min(3, "Feed name must be at least 3 characters"), + description: z.string().min(10, "Description must be at least 10 characters"), + hashtags: z.string().min(1, "Please provide at least one hashtag"), +}); + +type FormValues = z.infer; + +export default function BasicInformationForm() { + const { isSignedIn, handleSignIn } = useAuth(); + + const { + profileImage: storedProfileImage, + name, + description, + hashtags, + setBasicInfo, + } = useFeedCreationStore(); + + const form = useForm({ + resolver: zodResolver(BasicInformationFormSchema), + defaultValues: { + profileImage: storedProfileImage || "", + feedName: feedName || "", + description: description || "", + hashtags: hashtags || "", + }, + }); + + const onSubmit = (data: FormValues) => { + setBasicInfo({ + ...data, + createdAt: new Date(), + }); + }; + + return ( +
+ {isSignedIn ? ( +
+ + {/* Image Upload */} + ( + + + { + field.onChange(ipfsUrl); + setBasicInfo({ profileImage: ipfsUrl }); + }} + recommendedText="Recommended: Square, at least 400x400px. This will be your feed's avatar." + /> + + + + )} + /> + + {/* Feed Name */} + ( + + Feed Name + + { + field.onChange(e); + setBasicInfo({ feedName: e.target.value }); + }} + /> + + + + )} + /> + + {/* Description */} + ( + + Description + +