kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: migrate to node.js (#138)

* chore: remove bun.lockb and update package manager to pnpm; add hono-api dependency

* feat: implement user authentication and workspace management

- Added user authentication middleware to handle session validation and management.
- Enhanced sign-in and sign-up controllers to utilize HTTP exceptions for error handling.
- Introduced workspace management features including create, read, update, and delete operations.
- Integrated dotenv for environment variable management and updated dependencies in pnpm-lock.yaml.
- Refactored API fetchers to align with new client structure and improve error handling.

* feat: add workspace user management API and update related components

- Introduced a new workspace user management API with routes for creating, deleting, inviting, and
retrieving workspace users.
- Implemented controllers for handling workspace user operations, including validation using Zod.
- Updated the Hono API to include the new workspace user routes.
- Refactored frontend components to utilize the new API for fetching active workspace users and
managing user assignments.
- Renamed hooks for clarity, changing `useActiveWorkspaceUsers` to `useGetActiveWorkspaceUsers`
for consistency.

* feat: implement project and task management APIs

- Added project management API with routes for creating, retrieving, updating, and deleting
projects.
- Introduced task management API with routes for creating, retrieving, updating tasks, and
fetching tasks by project.
- Implemented controllers for project and task operations, utilizing Zod for validation.
- Updated Hono API to include new project and task routes.
- Refactored frontend components and fetchers to integrate with the new APIs and improve
type safety.

* feat: enhance user authentication and session management

- Added a new endpoint to retrieve the current user session with the `/me` route.
- Updated authentication middleware to streamline session validation.
- Refactored frontend components to align with the new user session structure.
- Modified API client to include credentials in requests for improved session handling.

* refactor: simplify getWorkspaces function and update return value in updateWorkspace

- Removed the unnecessary Promise.all logic in getWorkspaces, returning workspaces
directly.
- Updated the return statement in updateWorkspace to return the updated workspace
directly instead of accessing the first element of the array.

* refactor: remove project, task, user, and workspace APIs

- Deleted project, task, user, and workspace management APIs along with their associated
controllers and routes.
- Cleaned up the main API entry point by removing unused imports and middleware.
- Commented out session validation logic for future implementation.

* fix: improve error handling in updateProject function

- Replaced generic error throwing with HTTPException for better error response.
- Updated the error message for non-existing projects to return a 404 status code.

* feat: enhance demo mode functionality and improve authentication middleware

* feat: refactor database structure and enhance API functionality

- Introduced a new database module to centralize database interactions.
- Updated import paths across various controllers to reference the new database module.
- Added new dependencies for cryptographic functions and encoding.
- Enhanced TypeScript configuration for better module resolution and source mapping.
- Updated package versions in pnpm-lock.yaml for improved compatibility.

* refactor: move Hono API and related components

- Renamed the Hono API along with all associated routes, controllers, and configuration files.
- Cleaned up the project structure by removing unused files and dependencies.
- Updated the Dockerfile and configuration files to reflect the move of the Hono API.
- Ensured that the database schema and related utilities are preserved for future use.

* fix: update schema path in drizzle configuration

* feat: add Docker Compose configuration and enhance API error handling

- Introduced a new Docker Compose configuration file for local development.
- Updated API to throw HTTPException for failed task and workspace creation.
- Adjusted TypeScript configuration to include declaration files.
- Fixed port number for the API server to ensure correct operation.
- Improved error handling in session token validation and task number retrieval.

* chore: update lucide-react to version 0.486.0 and refine API routes

- Bumped lucide-react from 0.484.0 to 0.486.0 in pnpm-lock.yaml for improved compatibility.
- Simplified authentication middleware in the API by directly using the auth function.
- Updated task route to include 'tasks' in the path for clarity.
- Adjusted user info component styles for better alignment and visibility.
- Fixed API client URL to point to the correct port for local development.

* feat: implement Dockerfile for API and update TypeScript configuration

- Added Dockerfile for the API service to streamline the build and deployment process.
- Updated TypeScript configuration to use CommonJS module format and improved path references.
- Adjusted package.json scripts to include a build command using esbuild.
- Enhanced database schema definition for better clarity and structure.
- Updated pnpm-lock.yaml with new dependency versions for improved compatibility.

* feat: update drizzle-orm version and refactor task handling

* feat: add GitHub Actions workflow for tagging Docker images with :node tag

- Introduced a new workflow to tag web and API Docker images with the :node tag.
- Configured inputs for conditional tagging of images based on user selection.
- Implemented steps for logging into GitHub Container Registry and tagging images accordingly.

* feat: add push trigger for node tagging workflow

- Added a push trigger to the GitHub Actions workflow for tagging Docker images with the :node tag.
- Configured the trigger to activate on pushes to the feat/migrate-to-node-js branch.

* fix: update conditions for Docker image tagging in workflow

- Modified the conditions for tagging web and API Docker images to include a push event trigger.
- Ensured that images are tagged with the :node tag on both user input and push events.

* refactor: remove unused WebSocket hook and update API URL reference

* refactor: optimize Dockerfile for API and web services
building.

* refactor: update CORS origin configuration in API

* fix: update service ports and configurations for local development

- Changed the web service port mapping from 5173:80 to 5173:5173 in Docker Compose and README.
- Updated the Dockerfile to expose port 5173 and adjusted the health check URL accordingly.
- Modified nginx configuration to listen on port 5173.
- Updated Kubernetes deployment template to reflect the new container port and added liveness/readiness probes.
- Revised NOTES.txt to clarify port forwarding instructions for accessing the application.

* chore: remove unused vite-env type definitions

- Deleted vite-env.d.ts files from the root and libs directory as they are no longer needed.

* feat: enhance workspace management and settings functionality

- Added description field to project and workspace update APIs.
- Implemented new workspace settings section in the sidebar for better navigation.
- Created a dedicated route for workspace settings with form handling for updates and deletion.
- Updated various dependencies in package.json for improved functionality and compatibility.
- Introduced new hooks for managing workspace updates and deletions.

* refactor: improve workspace settings sidebar layout

- Updated the WorkspaceSettings component to enhance the layout and styling of the sidebar.
- Introduced a header for the workspace section and adjusted link alignment for better user experience.
- Improved conditional rendering for sidebar items based on the sidebar's open state.

* ci: pdating node tagging

* ci: pdating node tagging

* ci: pdating node tagging

* ci: commenting type checking for now

* feat: implement database schema updates and workspace user management

- Added new SQL migration files to restructure the database schema, including the creation of new tables for activities, projects, tasks, users, workspaces, and workspace members.
- Updated the database schema in TypeScript to reflect changes in the new tables and their relationships.
- Enhanced workspace user management functionality by updating API routes and controllers to handle workspace user invitations and retrievals more effectively.
- Improved the user interface for workspace settings, including permission checks for modifying settings based on user roles.

* chore: update pre-commit script and format JSON files

* ci: remove node tagging workflow file

authored by

Andrej and committed by
GitHub
d0995338 d4d498b4

+7860 -1426
+1 -2
.husky/pre-commit
··· 1 - bun x biome ci . 2 - bun x turbo run build 1 + pnpm dlx @biomejs/biome ci .
+1 -1
README.md
··· 57 57 environment: 58 58 KANEO_API_URL: "http://localhost:1337" 59 59 ports: 60 - - 5173:80 60 + - 5173:5173 61 61 restart: unless-stopped 62 62 63 63 volumes:
+49 -30
apps/api/Dockerfile
··· 1 - FROM --platform=$BUILDPLATFORM oven/bun:1.2.5 AS base 2 - WORKDIR /app 1 + # Build stage 2 + FROM --platform=$BUILDPLATFORM node:20-alpine AS builder 3 3 4 - # Install build dependencies 5 - RUN apt-get update && apt-get install -y \ 6 - python3 \ 7 - make \ 8 - g++ \ 9 - && rm -rf /var/lib/apt/lists/* 4 + # Install build dependencies in a single layer 5 + RUN apk add --no-cache python3 make g++ sqlite && \ 6 + corepack enable && \ 7 + corepack prepare pnpm@10.7.0 --activate 10 8 11 - # Copy package files first for better layer caching 12 - COPY package.json bun.lockb ./ 13 - COPY apps/api/package.json ./apps/api/ 9 + WORKDIR /app 10 + 11 + # Copy only package files first for better caching 12 + COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./ 14 13 COPY packages/typescript-config/package.json ./packages/typescript-config/ 14 + COPY packages/libs/package.json ./packages/libs/ 15 + COPY apps/api/package.json ./apps/api/ 15 16 16 17 # Install dependencies 17 - RUN bun install --no-frozen-lockfile 18 + RUN pnpm install --frozen-lockfile 18 19 19 - # Copy source code 20 + # Copy source files 20 21 COPY packages/typescript-config ./packages/typescript-config 22 + COPY packages/libs ./packages/libs 21 23 COPY apps/api ./apps/api 22 24 23 - # Production stage 24 - FROM oven/bun:1-alpine AS runtime 25 + # Fix TypeScript config and build in one layer 26 + WORKDIR /app/apps/api 27 + RUN sed -i 's/"extends": "@kaneo\/typescript-config\/base.json"/"extends": "..\/..\/packages\/typescript-config\/base.json"/g' /app/apps/api/tsconfig.json && \ 28 + pnpm run build 29 + 30 + # Production stage - use specific version tag without SHA256 31 + FROM node:20.12-alpine AS runtime 32 + 33 + # Install SQLite and set up user in a single layer 34 + RUN apk add --no-cache sqlite && \ 35 + addgroup -g 1001 appuser && \ 36 + adduser -u 1001 -G appuser -D appuser && \ 37 + mkdir -p /app/apps/api/data && \ 38 + chown -R appuser:appuser /app 25 39 26 - # Create non-root user 27 - RUN addgroup -g 1001 appuser && \ 28 - adduser -u 1001 -G appuser -D appuser 40 + WORKDIR /app 29 41 30 - WORKDIR /app/apps/api 42 + # Copy package files for production install 43 + COPY --from=builder /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./ 44 + COPY --from=builder /app/apps/api/package.json ./apps/api/ 45 + COPY --from=builder /app/packages/typescript-config/package.json ./packages/typescript-config/ 46 + COPY --from=builder /app/packages/libs/package.json ./packages/libs/ 31 47 32 - # Create data directory with proper permissions 33 - RUN mkdir -p /app/apps/api/data && \ 34 - chown -R appuser:appuser /app 48 + # Install production dependencies only 49 + RUN sed -i 's/"prepare": "husky"/"prepare": ""/g' package.json && \ 50 + corepack enable && \ 51 + corepack prepare pnpm@10.7.0 --activate && \ 52 + HUSKY=0 NODE_ENV=production pnpm install --prod --frozen-lockfile --no-optional 35 53 36 - # Copy built files from base stage 37 - COPY --from=base --chown=appuser:appuser /app/apps/api ./ 38 - COPY --from=base --chown=appuser:appuser /app/node_modules ../node_modules 39 - COPY --from=base --chown=appuser:appuser /app/packages ../packages 54 + # Copy built files 55 + COPY --from=builder /app/apps/api/dist ./apps/api/dist 56 + COPY --from=builder /app/apps/api/drizzle ./apps/api/drizzle 40 57 41 58 # Set environment variables 42 59 ENV NODE_ENV=production 43 - ENV BUN_ENV=production 44 60 45 61 # Switch to non-root user 46 62 USER appuser 63 + WORKDIR /app/apps/api 64 + EXPOSE 1337 47 65 48 - EXPOSE 1337 66 + # Add health check 67 + HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ 68 + CMD wget --no-verbose --tries=1 --spider http://localhost:1337/me || exit 1 49 69 50 - # Use exec form of CMD for proper signal handling 51 - CMD ["bun", "run", "/app/apps/api/src/index.ts"] 70 + CMD ["node", "--enable-source-maps", "dist/index.js"]
+7 -6
apps/api/drizzle/0000_cool_mattie_franklin.sql apps/api/drizzle/0000_deep_spot.sql
··· 2 2 `id` text PRIMARY KEY NOT NULL, 3 3 `task_id` text NOT NULL, 4 4 `type` text NOT NULL, 5 - `created_at` integer DEFAULT '"2025-02-28T19:33:25.542Z"' NOT NULL, 5 + `created_at` integer DEFAULT '"2025-04-17T20:55:01.755Z"' NOT NULL, 6 6 `user_email` text NOT NULL, 7 7 `content` text, 8 8 FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE cascade ON DELETE cascade, ··· 16 16 `icon` text DEFAULT 'Layout', 17 17 `name` text NOT NULL, 18 18 `description` text, 19 - `created_at` integer DEFAULT '"2025-02-28T19:33:25.542Z"' NOT NULL, 19 + `created_at` integer DEFAULT '"2025-04-17T20:55:01.755Z"' NOT NULL, 20 20 FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade 21 21 ); 22 22 --> statement-breakpoint ··· 30 30 CREATE TABLE `task` ( 31 31 `id` text PRIMARY KEY NOT NULL, 32 32 `project_id` text NOT NULL, 33 + `position` integer DEFAULT 0, 33 34 `number` integer DEFAULT 1, 34 35 `assignee_email` text, 35 36 `title` text NOT NULL, ··· 37 38 `status` text DEFAULT 'to-do' NOT NULL, 38 39 `priority` text DEFAULT 'low', 39 40 `due_date` integer, 40 - `created_at` integer DEFAULT '"2025-02-28T19:33:25.542Z"' NOT NULL, 41 + `created_at` integer DEFAULT '"2025-04-17T20:55:01.755Z"' NOT NULL, 41 42 FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE cascade ON DELETE cascade, 42 43 FOREIGN KEY (`assignee_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 43 44 ); ··· 47 48 `name` text NOT NULL, 48 49 `password` text NOT NULL, 49 50 `email` text NOT NULL, 50 - `created_at` integer DEFAULT '"2025-02-28T19:33:25.541Z"' NOT NULL 51 + `created_at` integer DEFAULT '"2025-04-17T20:55:01.754Z"' NOT NULL 51 52 ); 52 53 --> statement-breakpoint 53 54 CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint ··· 56 57 `name` text NOT NULL, 57 58 `description` text, 58 59 `owner_email` text NOT NULL, 59 - `created_at` integer DEFAULT '"2025-02-28T19:33:25.542Z"' NOT NULL, 60 + `created_at` integer DEFAULT '"2025-04-17T20:55:01.755Z"' NOT NULL, 60 61 FOREIGN KEY (`owner_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 61 62 ); 62 63 --> statement-breakpoint ··· 65 66 `workspace_id` text NOT NULL, 66 67 `user_email` text NOT NULL, 67 68 `role` text DEFAULT 'member' NOT NULL, 68 - `joined_at` integer DEFAULT '"2025-02-28T19:33:25.542Z"' NOT NULL, 69 + `joined_at` integer DEFAULT '"2025-04-17T20:55:01.755Z"' NOT NULL, 69 70 `status` text DEFAULT 'pending' NOT NULL, 70 71 FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade, 71 72 FOREIGN KEY (`user_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade
+7 -7
apps/api/drizzle/0001_short_imperial_guard.sql apps/api/drizzle/0001_blue_unicorn.sql
··· 3 3 `id` text PRIMARY KEY NOT NULL, 4 4 `task_id` text NOT NULL, 5 5 `type` text NOT NULL, 6 - `created_at` integer DEFAULT '"2025-03-13T21:45:13.973Z"' NOT NULL, 6 + `created_at` integer DEFAULT '"2025-04-20T15:06:18.576Z"' NOT NULL, 7 7 `user_email` text NOT NULL, 8 8 `content` text, 9 9 FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE cascade ON DELETE cascade, ··· 21 21 `icon` text DEFAULT 'Layout', 22 22 `name` text NOT NULL, 23 23 `description` text, 24 - `created_at` integer DEFAULT '"2025-03-13T21:45:13.973Z"' NOT NULL, 24 + `created_at` integer DEFAULT '"2025-04-20T15:06:18.576Z"' NOT NULL, 25 25 FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade 26 26 ); 27 27 --> statement-breakpoint ··· 39 39 `status` text DEFAULT 'to-do' NOT NULL, 40 40 `priority` text DEFAULT 'low', 41 41 `due_date` integer, 42 - `created_at` integer DEFAULT '"2025-03-13T21:45:13.973Z"' NOT NULL, 42 + `created_at` integer DEFAULT '"2025-04-20T15:06:18.576Z"' NOT NULL, 43 43 FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE cascade ON DELETE cascade, 44 44 FOREIGN KEY (`assignee_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 45 45 ); ··· 52 52 `name` text NOT NULL, 53 53 `password` text NOT NULL, 54 54 `email` text NOT NULL, 55 - `created_at` integer DEFAULT '"2025-03-13T21:45:13.972Z"' NOT NULL 55 + `created_at` integer DEFAULT '"2025-04-20T15:06:18.575Z"' NOT NULL 56 56 ); 57 57 --> statement-breakpoint 58 58 INSERT INTO `__new_user`("id", "name", "password", "email", "created_at") SELECT "id", "name", "password", "email", "created_at" FROM `user`;--> statement-breakpoint ··· 64 64 `name` text NOT NULL, 65 65 `description` text, 66 66 `owner_email` text NOT NULL, 67 - `created_at` integer DEFAULT '"2025-03-13T21:45:13.973Z"' NOT NULL, 67 + `created_at` integer DEFAULT '"2025-04-20T15:06:18.575Z"' NOT NULL, 68 68 FOREIGN KEY (`owner_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 69 69 ); 70 70 --> statement-breakpoint ··· 74 74 CREATE TABLE `__new_workspace_member` ( 75 75 `id` text PRIMARY KEY NOT NULL, 76 76 `workspace_id` text NOT NULL, 77 - `user_email` text NOT NULL, 77 + `user_email` text, 78 78 `role` text DEFAULT 'member' NOT NULL, 79 - `joined_at` integer DEFAULT '"2025-03-13T21:45:13.973Z"' NOT NULL, 79 + `joined_at` integer DEFAULT '"2025-04-20T15:06:18.575Z"' NOT NULL, 80 80 `status` text DEFAULT 'pending' NOT NULL, 81 81 FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade, 82 82 FOREIGN KEY (`user_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade
+86
apps/api/drizzle/0002_many_lake.sql
··· 1 + PRAGMA foreign_keys=OFF;--> statement-breakpoint 2 + CREATE TABLE `__new_workspace_member` ( 3 + `id` text PRIMARY KEY NOT NULL, 4 + `workspace_id` text NOT NULL, 5 + `user_email` text, 6 + `role` text DEFAULT 'member' NOT NULL, 7 + `joined_at` integer DEFAULT '"2025-04-20T15:14:33.402Z"' NOT NULL, 8 + `status` text DEFAULT 'pending' NOT NULL, 9 + FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade 10 + ); 11 + --> statement-breakpoint 12 + INSERT INTO `__new_workspace_member`("id", "workspace_id", "user_email", "role", "joined_at", "status") SELECT "id", "workspace_id", "user_email", "role", "joined_at", "status" FROM `workspace_member`;--> statement-breakpoint 13 + DROP TABLE `workspace_member`;--> statement-breakpoint 14 + ALTER TABLE `__new_workspace_member` RENAME TO `workspace_member`;--> statement-breakpoint 15 + PRAGMA foreign_keys=ON;--> statement-breakpoint 16 + CREATE TABLE `__new_activity` ( 17 + `id` text PRIMARY KEY NOT NULL, 18 + `task_id` text NOT NULL, 19 + `type` text NOT NULL, 20 + `created_at` integer DEFAULT '"2025-04-20T15:14:33.402Z"' NOT NULL, 21 + `user_email` text NOT NULL, 22 + `content` text, 23 + FOREIGN KEY (`task_id`) REFERENCES `task`(`id`) ON UPDATE cascade ON DELETE cascade, 24 + FOREIGN KEY (`user_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 25 + ); 26 + --> statement-breakpoint 27 + INSERT INTO `__new_activity`("id", "task_id", "type", "created_at", "user_email", "content") SELECT "id", "task_id", "type", "created_at", "user_email", "content" FROM `activity`;--> statement-breakpoint 28 + DROP TABLE `activity`;--> statement-breakpoint 29 + ALTER TABLE `__new_activity` RENAME TO `activity`;--> statement-breakpoint 30 + CREATE TABLE `__new_project` ( 31 + `id` text PRIMARY KEY NOT NULL, 32 + `workspace_id` text NOT NULL, 33 + `slug` text NOT NULL, 34 + `icon` text DEFAULT 'Layout', 35 + `name` text NOT NULL, 36 + `description` text, 37 + `created_at` integer DEFAULT '"2025-04-20T15:14:33.402Z"' NOT NULL, 38 + FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE cascade ON DELETE cascade 39 + ); 40 + --> statement-breakpoint 41 + INSERT INTO `__new_project`("id", "workspace_id", "slug", "icon", "name", "description", "created_at") SELECT "id", "workspace_id", "slug", "icon", "name", "description", "created_at" FROM `project`;--> statement-breakpoint 42 + DROP TABLE `project`;--> statement-breakpoint 43 + ALTER TABLE `__new_project` RENAME TO `project`;--> statement-breakpoint 44 + CREATE TABLE `__new_task` ( 45 + `id` text PRIMARY KEY NOT NULL, 46 + `project_id` text NOT NULL, 47 + `position` integer DEFAULT 0, 48 + `number` integer DEFAULT 1, 49 + `assignee_email` text, 50 + `title` text NOT NULL, 51 + `description` text, 52 + `status` text DEFAULT 'to-do' NOT NULL, 53 + `priority` text DEFAULT 'low', 54 + `due_date` integer, 55 + `created_at` integer DEFAULT '"2025-04-20T15:14:33.402Z"' NOT NULL, 56 + FOREIGN KEY (`project_id`) REFERENCES `project`(`id`) ON UPDATE cascade ON DELETE cascade, 57 + FOREIGN KEY (`assignee_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 58 + ); 59 + --> statement-breakpoint 60 + INSERT INTO `__new_task`("id", "project_id", "position", "number", "assignee_email", "title", "description", "status", "priority", "due_date", "created_at") SELECT "id", "project_id", "position", "number", "assignee_email", "title", "description", "status", "priority", "due_date", "created_at" FROM `task`;--> statement-breakpoint 61 + DROP TABLE `task`;--> statement-breakpoint 62 + ALTER TABLE `__new_task` RENAME TO `task`;--> statement-breakpoint 63 + CREATE TABLE `__new_user` ( 64 + `id` text PRIMARY KEY NOT NULL, 65 + `name` text NOT NULL, 66 + `password` text NOT NULL, 67 + `email` text NOT NULL, 68 + `created_at` integer DEFAULT '"2025-04-20T15:14:33.401Z"' NOT NULL 69 + ); 70 + --> statement-breakpoint 71 + INSERT INTO `__new_user`("id", "name", "password", "email", "created_at") SELECT "id", "name", "password", "email", "created_at" FROM `user`;--> statement-breakpoint 72 + DROP TABLE `user`;--> statement-breakpoint 73 + ALTER TABLE `__new_user` RENAME TO `user`;--> statement-breakpoint 74 + CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint 75 + CREATE TABLE `__new_workspace` ( 76 + `id` text PRIMARY KEY NOT NULL, 77 + `name` text NOT NULL, 78 + `description` text, 79 + `owner_email` text NOT NULL, 80 + `created_at` integer DEFAULT '"2025-04-20T15:14:33.401Z"' NOT NULL, 81 + FOREIGN KEY (`owner_email`) REFERENCES `user`(`email`) ON UPDATE cascade ON DELETE cascade 82 + ); 83 + --> statement-breakpoint 84 + INSERT INTO `__new_workspace`("id", "name", "description", "owner_email", "created_at") SELECT "id", "name", "description", "owner_email", "created_at" FROM `workspace`;--> statement-breakpoint 85 + DROP TABLE `workspace`;--> statement-breakpoint 86 + ALTER TABLE `__new_workspace` RENAME TO `workspace`;
+15 -7
apps/api/drizzle/meta/0000_snapshot.json
··· 1 1 { 2 2 "version": "6", 3 3 "dialect": "sqlite", 4 - "id": "f146a115-68e7-4707-b858-8d9029a87136", 4 + "id": "85665cab-8b3a-4f4c-97a2-35c752fc7ad2", 5 5 "prevId": "00000000-0000-0000-0000-000000000000", 6 6 "tables": { 7 7 "activity": { ··· 34 34 "primaryKey": false, 35 35 "notNull": true, 36 36 "autoincrement": false, 37 - "default": "'\"2025-02-28T19:33:25.542Z\"'" 37 + "default": "'\"2025-04-17T20:55:01.755Z\"'" 38 38 }, 39 39 "user_email": { 40 40 "name": "user_email", ··· 128 128 "primaryKey": false, 129 129 "notNull": true, 130 130 "autoincrement": false, 131 - "default": "'\"2025-02-28T19:33:25.542Z\"'" 131 + "default": "'\"2025-04-17T20:55:01.755Z\"'" 132 132 } 133 133 }, 134 134 "indexes": {}, ··· 205 205 "notNull": true, 206 206 "autoincrement": false 207 207 }, 208 + "position": { 209 + "name": "position", 210 + "type": "integer", 211 + "primaryKey": false, 212 + "notNull": false, 213 + "autoincrement": false, 214 + "default": 0 215 + }, 208 216 "number": { 209 217 "name": "number", 210 218 "type": "integer", ··· 263 271 "primaryKey": false, 264 272 "notNull": true, 265 273 "autoincrement": false, 266 - "default": "'\"2025-02-28T19:33:25.542Z\"'" 274 + "default": "'\"2025-04-17T20:55:01.755Z\"'" 267 275 } 268 276 }, 269 277 "indexes": {}, ··· 328 336 "primaryKey": false, 329 337 "notNull": true, 330 338 "autoincrement": false, 331 - "default": "'\"2025-02-28T19:33:25.541Z\"'" 339 + "default": "'\"2025-04-17T20:55:01.754Z\"'" 332 340 } 333 341 }, 334 342 "indexes": { ··· 380 388 "primaryKey": false, 381 389 "notNull": true, 382 390 "autoincrement": false, 383 - "default": "'\"2025-02-28T19:33:25.542Z\"'" 391 + "default": "'\"2025-04-17T20:55:01.755Z\"'" 384 392 } 385 393 }, 386 394 "indexes": {}, ··· 437 445 "primaryKey": false, 438 446 "notNull": true, 439 447 "autoincrement": false, 440 - "default": "'\"2025-02-28T19:33:25.542Z\"'" 448 + "default": "'\"2025-04-17T20:55:01.755Z\"'" 441 449 }, 442 450 "status": { 443 451 "name": "status",
+9 -9
apps/api/drizzle/meta/0001_snapshot.json
··· 1 1 { 2 2 "version": "6", 3 3 "dialect": "sqlite", 4 - "id": "8acd32cb-c859-4926-ae60-df1b4ea9a6bf", 5 - "prevId": "f146a115-68e7-4707-b858-8d9029a87136", 4 + "id": "8c533750-62a3-432a-9006-5a6bac28c095", 5 + "prevId": "85665cab-8b3a-4f4c-97a2-35c752fc7ad2", 6 6 "tables": { 7 7 "activity": { 8 8 "name": "activity", ··· 34 34 "primaryKey": false, 35 35 "notNull": true, 36 36 "autoincrement": false, 37 - "default": "'\"2025-03-13T21:45:13.973Z\"'" 37 + "default": "'\"2025-04-20T15:06:18.576Z\"'" 38 38 }, 39 39 "user_email": { 40 40 "name": "user_email", ··· 128 128 "primaryKey": false, 129 129 "notNull": true, 130 130 "autoincrement": false, 131 - "default": "'\"2025-03-13T21:45:13.973Z\"'" 131 + "default": "'\"2025-04-20T15:06:18.576Z\"'" 132 132 } 133 133 }, 134 134 "indexes": {}, ··· 271 271 "primaryKey": false, 272 272 "notNull": true, 273 273 "autoincrement": false, 274 - "default": "'\"2025-03-13T21:45:13.973Z\"'" 274 + "default": "'\"2025-04-20T15:06:18.576Z\"'" 275 275 } 276 276 }, 277 277 "indexes": {}, ··· 336 336 "primaryKey": false, 337 337 "notNull": true, 338 338 "autoincrement": false, 339 - "default": "'\"2025-03-13T21:45:13.972Z\"'" 339 + "default": "'\"2025-04-20T15:06:18.575Z\"'" 340 340 } 341 341 }, 342 342 "indexes": { ··· 388 388 "primaryKey": false, 389 389 "notNull": true, 390 390 "autoincrement": false, 391 - "default": "'\"2025-03-13T21:45:13.973Z\"'" 391 + "default": "'\"2025-04-20T15:06:18.575Z\"'" 392 392 } 393 393 }, 394 394 "indexes": {}, ··· 428 428 "name": "user_email", 429 429 "type": "text", 430 430 "primaryKey": false, 431 - "notNull": true, 431 + "notNull": false, 432 432 "autoincrement": false 433 433 }, 434 434 "role": { ··· 445 445 "primaryKey": false, 446 446 "notNull": true, 447 447 "autoincrement": false, 448 - "default": "'\"2025-03-13T21:45:13.973Z\"'" 448 + "default": "'\"2025-04-20T15:06:18.575Z\"'" 449 449 }, 450 450 "status": { 451 451 "name": "status",
+486
apps/api/drizzle/meta/0002_snapshot.json
··· 1 + { 2 + "version": "6", 3 + "dialect": "sqlite", 4 + "id": "0b01528e-2d71-498c-9ab6-1c16128a7c9b", 5 + "prevId": "8c533750-62a3-432a-9006-5a6bac28c095", 6 + "tables": { 7 + "activity": { 8 + "name": "activity", 9 + "columns": { 10 + "id": { 11 + "name": "id", 12 + "type": "text", 13 + "primaryKey": true, 14 + "notNull": true, 15 + "autoincrement": false 16 + }, 17 + "task_id": { 18 + "name": "task_id", 19 + "type": "text", 20 + "primaryKey": false, 21 + "notNull": true, 22 + "autoincrement": false 23 + }, 24 + "type": { 25 + "name": "type", 26 + "type": "text", 27 + "primaryKey": false, 28 + "notNull": true, 29 + "autoincrement": false 30 + }, 31 + "created_at": { 32 + "name": "created_at", 33 + "type": "integer", 34 + "primaryKey": false, 35 + "notNull": true, 36 + "autoincrement": false, 37 + "default": "'\"2025-04-20T15:14:33.402Z\"'" 38 + }, 39 + "user_email": { 40 + "name": "user_email", 41 + "type": "text", 42 + "primaryKey": false, 43 + "notNull": true, 44 + "autoincrement": false 45 + }, 46 + "content": { 47 + "name": "content", 48 + "type": "text", 49 + "primaryKey": false, 50 + "notNull": false, 51 + "autoincrement": false 52 + } 53 + }, 54 + "indexes": {}, 55 + "foreignKeys": { 56 + "activity_task_id_task_id_fk": { 57 + "name": "activity_task_id_task_id_fk", 58 + "tableFrom": "activity", 59 + "tableTo": "task", 60 + "columnsFrom": ["task_id"], 61 + "columnsTo": ["id"], 62 + "onDelete": "cascade", 63 + "onUpdate": "cascade" 64 + }, 65 + "activity_user_email_user_email_fk": { 66 + "name": "activity_user_email_user_email_fk", 67 + "tableFrom": "activity", 68 + "tableTo": "user", 69 + "columnsFrom": ["user_email"], 70 + "columnsTo": ["email"], 71 + "onDelete": "cascade", 72 + "onUpdate": "cascade" 73 + } 74 + }, 75 + "compositePrimaryKeys": {}, 76 + "uniqueConstraints": {}, 77 + "checkConstraints": {} 78 + }, 79 + "project": { 80 + "name": "project", 81 + "columns": { 82 + "id": { 83 + "name": "id", 84 + "type": "text", 85 + "primaryKey": true, 86 + "notNull": true, 87 + "autoincrement": false 88 + }, 89 + "workspace_id": { 90 + "name": "workspace_id", 91 + "type": "text", 92 + "primaryKey": false, 93 + "notNull": true, 94 + "autoincrement": false 95 + }, 96 + "slug": { 97 + "name": "slug", 98 + "type": "text", 99 + "primaryKey": false, 100 + "notNull": true, 101 + "autoincrement": false 102 + }, 103 + "icon": { 104 + "name": "icon", 105 + "type": "text", 106 + "primaryKey": false, 107 + "notNull": false, 108 + "autoincrement": false, 109 + "default": "'Layout'" 110 + }, 111 + "name": { 112 + "name": "name", 113 + "type": "text", 114 + "primaryKey": false, 115 + "notNull": true, 116 + "autoincrement": false 117 + }, 118 + "description": { 119 + "name": "description", 120 + "type": "text", 121 + "primaryKey": false, 122 + "notNull": false, 123 + "autoincrement": false 124 + }, 125 + "created_at": { 126 + "name": "created_at", 127 + "type": "integer", 128 + "primaryKey": false, 129 + "notNull": true, 130 + "autoincrement": false, 131 + "default": "'\"2025-04-20T15:14:33.402Z\"'" 132 + } 133 + }, 134 + "indexes": {}, 135 + "foreignKeys": { 136 + "project_workspace_id_workspace_id_fk": { 137 + "name": "project_workspace_id_workspace_id_fk", 138 + "tableFrom": "project", 139 + "tableTo": "workspace", 140 + "columnsFrom": ["workspace_id"], 141 + "columnsTo": ["id"], 142 + "onDelete": "cascade", 143 + "onUpdate": "cascade" 144 + } 145 + }, 146 + "compositePrimaryKeys": {}, 147 + "uniqueConstraints": {}, 148 + "checkConstraints": {} 149 + }, 150 + "session": { 151 + "name": "session", 152 + "columns": { 153 + "id": { 154 + "name": "id", 155 + "type": "text", 156 + "primaryKey": true, 157 + "notNull": true, 158 + "autoincrement": false 159 + }, 160 + "user_id": { 161 + "name": "user_id", 162 + "type": "text", 163 + "primaryKey": false, 164 + "notNull": true, 165 + "autoincrement": false 166 + }, 167 + "expires_at": { 168 + "name": "expires_at", 169 + "type": "integer", 170 + "primaryKey": false, 171 + "notNull": true, 172 + "autoincrement": false 173 + } 174 + }, 175 + "indexes": {}, 176 + "foreignKeys": { 177 + "session_user_id_user_id_fk": { 178 + "name": "session_user_id_user_id_fk", 179 + "tableFrom": "session", 180 + "tableTo": "user", 181 + "columnsFrom": ["user_id"], 182 + "columnsTo": ["id"], 183 + "onDelete": "cascade", 184 + "onUpdate": "cascade" 185 + } 186 + }, 187 + "compositePrimaryKeys": {}, 188 + "uniqueConstraints": {}, 189 + "checkConstraints": {} 190 + }, 191 + "task": { 192 + "name": "task", 193 + "columns": { 194 + "id": { 195 + "name": "id", 196 + "type": "text", 197 + "primaryKey": true, 198 + "notNull": true, 199 + "autoincrement": false 200 + }, 201 + "project_id": { 202 + "name": "project_id", 203 + "type": "text", 204 + "primaryKey": false, 205 + "notNull": true, 206 + "autoincrement": false 207 + }, 208 + "position": { 209 + "name": "position", 210 + "type": "integer", 211 + "primaryKey": false, 212 + "notNull": false, 213 + "autoincrement": false, 214 + "default": 0 215 + }, 216 + "number": { 217 + "name": "number", 218 + "type": "integer", 219 + "primaryKey": false, 220 + "notNull": false, 221 + "autoincrement": false, 222 + "default": 1 223 + }, 224 + "assignee_email": { 225 + "name": "assignee_email", 226 + "type": "text", 227 + "primaryKey": false, 228 + "notNull": false, 229 + "autoincrement": false 230 + }, 231 + "title": { 232 + "name": "title", 233 + "type": "text", 234 + "primaryKey": false, 235 + "notNull": true, 236 + "autoincrement": false 237 + }, 238 + "description": { 239 + "name": "description", 240 + "type": "text", 241 + "primaryKey": false, 242 + "notNull": false, 243 + "autoincrement": false 244 + }, 245 + "status": { 246 + "name": "status", 247 + "type": "text", 248 + "primaryKey": false, 249 + "notNull": true, 250 + "autoincrement": false, 251 + "default": "'to-do'" 252 + }, 253 + "priority": { 254 + "name": "priority", 255 + "type": "text", 256 + "primaryKey": false, 257 + "notNull": false, 258 + "autoincrement": false, 259 + "default": "'low'" 260 + }, 261 + "due_date": { 262 + "name": "due_date", 263 + "type": "integer", 264 + "primaryKey": false, 265 + "notNull": false, 266 + "autoincrement": false 267 + }, 268 + "created_at": { 269 + "name": "created_at", 270 + "type": "integer", 271 + "primaryKey": false, 272 + "notNull": true, 273 + "autoincrement": false, 274 + "default": "'\"2025-04-20T15:14:33.402Z\"'" 275 + } 276 + }, 277 + "indexes": {}, 278 + "foreignKeys": { 279 + "task_project_id_project_id_fk": { 280 + "name": "task_project_id_project_id_fk", 281 + "tableFrom": "task", 282 + "tableTo": "project", 283 + "columnsFrom": ["project_id"], 284 + "columnsTo": ["id"], 285 + "onDelete": "cascade", 286 + "onUpdate": "cascade" 287 + }, 288 + "task_assignee_email_user_email_fk": { 289 + "name": "task_assignee_email_user_email_fk", 290 + "tableFrom": "task", 291 + "tableTo": "user", 292 + "columnsFrom": ["assignee_email"], 293 + "columnsTo": ["email"], 294 + "onDelete": "cascade", 295 + "onUpdate": "cascade" 296 + } 297 + }, 298 + "compositePrimaryKeys": {}, 299 + "uniqueConstraints": {}, 300 + "checkConstraints": {} 301 + }, 302 + "user": { 303 + "name": "user", 304 + "columns": { 305 + "id": { 306 + "name": "id", 307 + "type": "text", 308 + "primaryKey": true, 309 + "notNull": true, 310 + "autoincrement": false 311 + }, 312 + "name": { 313 + "name": "name", 314 + "type": "text", 315 + "primaryKey": false, 316 + "notNull": true, 317 + "autoincrement": false 318 + }, 319 + "password": { 320 + "name": "password", 321 + "type": "text", 322 + "primaryKey": false, 323 + "notNull": true, 324 + "autoincrement": false 325 + }, 326 + "email": { 327 + "name": "email", 328 + "type": "text", 329 + "primaryKey": false, 330 + "notNull": true, 331 + "autoincrement": false 332 + }, 333 + "created_at": { 334 + "name": "created_at", 335 + "type": "integer", 336 + "primaryKey": false, 337 + "notNull": true, 338 + "autoincrement": false, 339 + "default": "'\"2025-04-20T15:14:33.401Z\"'" 340 + } 341 + }, 342 + "indexes": { 343 + "user_email_unique": { 344 + "name": "user_email_unique", 345 + "columns": ["email"], 346 + "isUnique": true 347 + } 348 + }, 349 + "foreignKeys": {}, 350 + "compositePrimaryKeys": {}, 351 + "uniqueConstraints": {}, 352 + "checkConstraints": {} 353 + }, 354 + "workspace": { 355 + "name": "workspace", 356 + "columns": { 357 + "id": { 358 + "name": "id", 359 + "type": "text", 360 + "primaryKey": true, 361 + "notNull": true, 362 + "autoincrement": false 363 + }, 364 + "name": { 365 + "name": "name", 366 + "type": "text", 367 + "primaryKey": false, 368 + "notNull": true, 369 + "autoincrement": false 370 + }, 371 + "description": { 372 + "name": "description", 373 + "type": "text", 374 + "primaryKey": false, 375 + "notNull": false, 376 + "autoincrement": false 377 + }, 378 + "owner_email": { 379 + "name": "owner_email", 380 + "type": "text", 381 + "primaryKey": false, 382 + "notNull": true, 383 + "autoincrement": false 384 + }, 385 + "created_at": { 386 + "name": "created_at", 387 + "type": "integer", 388 + "primaryKey": false, 389 + "notNull": true, 390 + "autoincrement": false, 391 + "default": "'\"2025-04-20T15:14:33.401Z\"'" 392 + } 393 + }, 394 + "indexes": {}, 395 + "foreignKeys": { 396 + "workspace_owner_email_user_email_fk": { 397 + "name": "workspace_owner_email_user_email_fk", 398 + "tableFrom": "workspace", 399 + "tableTo": "user", 400 + "columnsFrom": ["owner_email"], 401 + "columnsTo": ["email"], 402 + "onDelete": "cascade", 403 + "onUpdate": "cascade" 404 + } 405 + }, 406 + "compositePrimaryKeys": {}, 407 + "uniqueConstraints": {}, 408 + "checkConstraints": {} 409 + }, 410 + "workspace_member": { 411 + "name": "workspace_member", 412 + "columns": { 413 + "id": { 414 + "name": "id", 415 + "type": "text", 416 + "primaryKey": true, 417 + "notNull": true, 418 + "autoincrement": false 419 + }, 420 + "workspace_id": { 421 + "name": "workspace_id", 422 + "type": "text", 423 + "primaryKey": false, 424 + "notNull": true, 425 + "autoincrement": false 426 + }, 427 + "user_email": { 428 + "name": "user_email", 429 + "type": "text", 430 + "primaryKey": false, 431 + "notNull": false, 432 + "autoincrement": false 433 + }, 434 + "role": { 435 + "name": "role", 436 + "type": "text", 437 + "primaryKey": false, 438 + "notNull": true, 439 + "autoincrement": false, 440 + "default": "'member'" 441 + }, 442 + "joined_at": { 443 + "name": "joined_at", 444 + "type": "integer", 445 + "primaryKey": false, 446 + "notNull": true, 447 + "autoincrement": false, 448 + "default": "'\"2025-04-20T15:14:33.402Z\"'" 449 + }, 450 + "status": { 451 + "name": "status", 452 + "type": "text", 453 + "primaryKey": false, 454 + "notNull": true, 455 + "autoincrement": false, 456 + "default": "'pending'" 457 + } 458 + }, 459 + "indexes": {}, 460 + "foreignKeys": { 461 + "workspace_member_workspace_id_workspace_id_fk": { 462 + "name": "workspace_member_workspace_id_workspace_id_fk", 463 + "tableFrom": "workspace_member", 464 + "tableTo": "workspace", 465 + "columnsFrom": ["workspace_id"], 466 + "columnsTo": ["id"], 467 + "onDelete": "cascade", 468 + "onUpdate": "cascade" 469 + } 470 + }, 471 + "compositePrimaryKeys": {}, 472 + "uniqueConstraints": {}, 473 + "checkConstraints": {} 474 + } 475 + }, 476 + "views": {}, 477 + "enums": {}, 478 + "_meta": { 479 + "schemas": {}, 480 + "tables": {}, 481 + "columns": {} 482 + }, 483 + "internal": { 484 + "indexes": {} 485 + } 486 + }
+11 -4
apps/api/drizzle/meta/_journal.json
··· 5 5 { 6 6 "idx": 0, 7 7 "version": "6", 8 - "when": 1740771205551, 9 - "tag": "0000_cool_mattie_franklin", 8 + "when": 1744923301762, 9 + "tag": "0000_deep_spot", 10 10 "breakpoints": true 11 11 }, 12 12 { 13 13 "idx": 1, 14 14 "version": "6", 15 - "when": 1741902313985, 16 - "tag": "0001_short_imperial_guard", 15 + "when": 1745161578587, 16 + "tag": "0001_blue_unicorn", 17 + "breakpoints": true 18 + }, 19 + { 20 + "idx": 2, 21 + "version": "6", 22 + "when": 1745162073413, 23 + "tag": "0002_many_lake", 17 24 "breakpoints": true 18 25 } 19 26 ]
+28 -30
apps/api/package.json
··· 1 1 { 2 - "name": "@kaneo/api", 3 - "version": "1.0.50", 4 - "main": "./src/index.ts", 5 - "scripts": { 6 - "test": "echo \"Error: no test specified\" && exit 1", 7 - "dev": "bun run --watch src/index.ts" 8 - }, 9 - "dependencies": { 10 - "@elysiajs/cors": "^1.2.0", 11 - "@elysiajs/cron": "^1.2.0", 12 - "@elysiajs/jwt": "^1.2.0", 13 - "@elysiajs/websocket": "^0.2.8", 14 - "@kaneo/typescript-config": "workspace:*", 15 - "@oslojs/crypto": "^1.0.1", 16 - "@oslojs/encoding": "^1.1.0", 17 - "@paralleldrive/cuid2": "^2.2.2", 18 - "better-sqlite3": "^11.8.1", 19 - "drizzle-kit": "^0.31.0", 20 - "drizzle-orm": "^0.42.0", 21 - "drizzle-typebox": "^0.3.1", 22 - "elysia": "1.2.25" 23 - }, 24 - "devDependencies": { 25 - "bun-types": "latest" 26 - }, 27 - "override": { 28 - "@sinclair/typebox": "0.32.4" 29 - }, 30 - "module": "src/index.ts", 31 - "type": "module" 2 + "name": "@kaneo/api", 3 + "type": "commonjs", 4 + "main": "./src/index.ts", 5 + "scripts": { 6 + "dev": "tsx watch src/index.ts", 7 + "build": "esbuild src/index.ts --bundle --platform=node --outdir=dist --format=cjs --external:better-sqlite3 --external:bcrypt --external:mock-aws-s3 --external:aws-sdk --external:nock" 8 + }, 9 + "dependencies": { 10 + "@hono/node-server": "^1.14.1", 11 + "@hono/zod-validator": "^0.4.3", 12 + "@oslojs/crypto": "^1.0.1", 13 + "@oslojs/encoding": "^1.1.0", 14 + "@paralleldrive/cuid2": "^2.2.2", 15 + "bcrypt": "^5.1.1", 16 + "better-sqlite3": "^11.9.1", 17 + "dotenv": "^16.5.0", 18 + "drizzle-orm": "^0.42.0", 19 + "hono": "^4.7.7", 20 + "zod": "^3.24.3" 21 + }, 22 + "devDependencies": { 23 + "@types/node": "^22.14.1", 24 + "tsx": "^4.19.3", 25 + "typescript": "^5.8.3", 26 + "esbuild": "^0.25.2", 27 + "@types/bcrypt": "^5.0.2", 28 + "@types/better-sqlite3": "^7.6.13" 29 + } 32 30 }
+12 -7
apps/api/src/activity/controllers/create-activity.ts
··· 1 1 import db from "../../database"; 2 2 import { activityTable } from "../../database/schema"; 3 3 4 - async function createActivity(body: { 5 - taskId: string; 6 - type: string; 7 - userEmail: string; 8 - content: string; 9 - }) { 10 - const activity = await db.insert(activityTable).values(body); 4 + async function createActivity( 5 + taskId: string, 6 + type: string, 7 + userEmail: string, 8 + content: string, 9 + ) { 10 + const activity = await db.insert(activityTable).values({ 11 + taskId, 12 + type, 13 + userEmail, 14 + content, 15 + }); 11 16 return activity; 12 17 } 13 18
+8 -6
apps/api/src/activity/controllers/create-comment.ts
··· 1 1 import db from "../../database"; 2 2 import { activityTable } from "../../database/schema"; 3 3 4 - async function createComment(data: { 5 - taskId: string; 6 - content: string; 7 - userEmail: string; 8 - }) { 4 + async function createComment( 5 + taskId: string, 6 + userEmail: string, 7 + content: string, 8 + ) { 9 9 const activity = await db.insert(activityTable).values({ 10 - ...data, 10 + taskId, 11 11 type: "comment", 12 + userEmail, 13 + content, 12 14 }); 13 15 return activity; 14 16 }
-23
apps/api/src/activity/events/index.ts
··· 1 - import { subscribeToEvent } from "../../events"; 2 - import createActivity from "../controllers/create-activity"; 3 - 4 - subscribeToEvent( 5 - "task.created", 6 - async (data: { 7 - taskId: string; 8 - userEmail: string; 9 - type: string; 10 - content: string; 11 - }) => { 12 - if (!data.userEmail) { 13 - return; 14 - } 15 - 16 - await createActivity({ 17 - taskId: data.taskId, 18 - userEmail: data.userEmail, 19 - type: data.type, 20 - content: data.content, 21 - }); 22 - }, 23 - );
+64 -26
apps/api/src/activity/index.ts
··· 1 - import Elysia, { t } from "elysia"; 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { z } from "zod"; 4 + import { subscribeToEvent } from "../events"; 2 5 import createActivity from "./controllers/create-activity"; 3 6 import createComment from "./controllers/create-comment"; 4 7 import getActivitiesFromTaskId from "./controllers/get-activities"; 5 - import "./events"; 8 + 9 + const activity = new Hono() 10 + .get( 11 + "/:taskId", 12 + zValidator("param", z.object({ taskId: z.string() })), 13 + async (c) => { 14 + const { taskId } = c.req.valid("param"); 15 + 16 + const activities = await getActivitiesFromTaskId(taskId); 6 17 7 - const activity = new Elysia({ prefix: "/activity" }) 8 - .get("/list/:taskId", async ({ params }) => { 9 - const activities = await getActivitiesFromTaskId(params.taskId); 10 - return activities; 11 - }) 18 + return c.json(activities); 19 + }, 20 + ) 12 21 .post( 13 22 "/create", 14 - async ({ body }) => { 15 - const activity = await createActivity(body); 16 - return activity; 17 - }, 18 - { 19 - body: t.Object({ 20 - taskId: t.String(), 21 - type: t.String(), 22 - userEmail: t.String(), 23 - content: t.String(), 23 + zValidator( 24 + "json", 25 + z.object({ 26 + taskId: z.string(), 27 + type: z.string(), 28 + userEmail: z.string(), 29 + content: z.string(), 24 30 }), 31 + ), 32 + async (c) => { 33 + const { taskId, type, userEmail, content } = c.req.valid("json"); 34 + 35 + const activity = await createActivity(taskId, type, userEmail, content); 36 + 37 + return c.json(activity); 25 38 }, 26 39 ) 27 40 .post( 28 41 "/comment", 29 - async ({ body }) => { 30 - const activity = await createComment(body); 31 - return activity; 32 - }, 33 - { 34 - body: t.Object({ 35 - taskId: t.String(), 36 - content: t.String(), 37 - userEmail: t.String(), 42 + zValidator( 43 + "json", 44 + z.object({ 45 + taskId: z.string(), 46 + content: z.string(), 47 + userEmail: z.string(), 38 48 }), 49 + ), 50 + async (c) => { 51 + const { taskId, content, userEmail } = c.req.valid("json"); 52 + 53 + const activity = await createComment(taskId, userEmail, content); 54 + 55 + return c.json(activity); 39 56 }, 40 57 ); 58 + 59 + subscribeToEvent( 60 + "task.created", 61 + async ({ 62 + taskId, 63 + userEmail, 64 + type, 65 + content, 66 + }: { 67 + taskId: string; 68 + userEmail: string; 69 + type: string; 70 + content: string; 71 + }) => { 72 + if (!userEmail || !taskId || !type || !content) { 73 + return; 74 + } 75 + 76 + await createActivity(taskId, type, userEmail, content); 77 + }, 78 + ); 41 79 42 80 export default activity;
+3 -2
apps/api/src/database/index.ts
··· 1 - import { Database } from "bun:sqlite"; 2 1 import { join } from "node:path"; 3 - import { drizzle } from "drizzle-orm/bun-sqlite"; 2 + import Database from "better-sqlite3"; 3 + import { drizzle } from "drizzle-orm/better-sqlite3"; 4 4 import * as schema from "./schema"; 5 5 6 6 const dbPath = process.env.DB_PATH 7 7 ? process.env.DB_PATH 8 8 : join(process.cwd(), "kaneo.db"); 9 + 9 10 const sqlite = new Database(dbPath); 10 11 11 12 const db = drizzle(sqlite, { schema });
+4 -9
apps/api/src/database/schema.ts
··· 1 1 import { createId } from "@paralleldrive/cuid2"; 2 - import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; 2 + import { int, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; 3 3 4 4 export const userTable = sqliteTable("user", { 5 5 id: text("id") ··· 53 53 onDelete: "cascade", 54 54 onUpdate: "cascade", 55 55 }), 56 - userEmail: text("user_email") 57 - .notNull() 58 - .references(() => userTable.email, { 59 - onDelete: "cascade", 60 - onUpdate: "cascade", 61 - }), 56 + userEmail: text("user_email"), 62 57 role: text("role").default("member").notNull(), 63 58 joinedAt: integer("joined_at", { mode: "timestamp" }) 64 59 .default(new Date()) ··· 95 90 onDelete: "cascade", 96 91 onUpdate: "cascade", 97 92 }), 98 - position: integer("position").default(0), 99 - number: integer("number").default(1), 93 + position: int("position").default(0), 94 + number: int("number").default(1), 100 95 userEmail: text("assignee_email").references(() => userTable.email, { 101 96 onDelete: "cascade", 102 97 onUpdate: "cascade",
+79 -81
apps/api/src/index.ts
··· 1 - import path from "node:path"; 2 - import { cors } from "@elysiajs/cors"; 3 - import { cron } from "@elysiajs/cron"; 4 - import { migrate } from "drizzle-orm/bun-sqlite/migrator"; 5 - import { Elysia } from "elysia"; 1 + import { serve } from "@hono/node-server"; 2 + import { migrate } from "drizzle-orm/better-sqlite3/migrator"; 3 + import { Hono } from "hono"; 4 + import { getCookie } from "hono/cookie"; 5 + import { cors } from "hono/cors"; 6 6 import activity from "./activity"; 7 7 import db from "./database"; 8 + import { auth } from "./middlewares/auth"; 8 9 import project from "./project"; 9 10 import task from "./task"; 10 11 import user from "./user"; 11 - import { validateSessionToken } from "./user/controllers/validate-session-token"; 12 - import purgeData from "./utils/purge-demo-data"; 12 + import { validateSessionToken } from "./user/utils/validate-session-token"; 13 13 import setDemoUser from "./utils/set-demo-user"; 14 14 import workspace from "./workspace"; 15 15 import workspaceUser from "./workspace-user"; 16 16 17 + const app = new Hono<{ Variables: { userEmail: string } }>(); 18 + 17 19 const isDemoMode = process.env.DEMO_MODE === "true"; 18 20 19 - const app = new Elysia() 20 - .state("userEmail", "") 21 - .use(cors()) 22 - .use(user) 23 - .use( 24 - cron({ 25 - name: "purge-demo-data", 26 - pattern: "30 * * * *", 27 - run: async () => { 28 - const isDemoMode = process.env.DEMO_MODE === "true"; 21 + app.use( 22 + "*", 23 + cors({ 24 + credentials: true, 25 + origin: (origin) => origin || "*", 26 + }), 27 + ); 29 28 30 - if (isDemoMode) { 31 - console.log("Purging demo data"); 32 - await purgeData(); 33 - } 34 - }, 35 - }), 36 - ) 37 - .guard({ 38 - async beforeHandle({ store, cookie: { session }, set }) { 39 - if (isDemoMode) { 40 - if (!session?.value) { 41 - await setDemoUser(set); 42 - } 29 + const userRoute = app.route("/user", user); 43 30 44 - const { user, session: validatedSession } = await validateSessionToken( 45 - session.value ?? "", 46 - ); 31 + app.use("*", auth); 47 32 48 - if (!user || !validatedSession) { 49 - await setDemoUser(set); 50 - } 33 + app.use("*", async (c, next) => { 34 + if (isDemoMode) { 35 + const session = getCookie(c, "session"); 51 36 52 - store.userEmail = user?.email ?? ""; 53 - } else { 54 - if (!session?.value) { 55 - return { user: null }; 56 - } 37 + if (!session) { 38 + await setDemoUser(c); 39 + } 57 40 58 - const { user, session: validatedSession } = await validateSessionToken( 59 - session.value, 60 - ); 41 + const { user, session: validatedSession } = await validateSessionToken( 42 + session ?? "", 43 + ); 61 44 62 - if (!user || !validatedSession) { 63 - return { user: null }; 64 - } 45 + if (!user || !validatedSession) { 46 + await setDemoUser(c); 47 + } 65 48 66 - store.userEmail = user.email; 67 - } 68 - }, 69 - }) 70 - .get("/me", async ({ cookie: { session } }) => { 71 - const { user } = await validateSessionToken(session.value ?? ""); 49 + c.set("userEmail", user?.email ?? ""); 50 + } 72 51 73 - if (user === null) { 74 - return { user: null }; 75 - } 52 + await next(); 53 + }); 76 54 77 - return { user }; 78 - }) 79 - .use(workspace) 80 - .use(project) 81 - .use(task) 82 - .use(workspaceUser) 83 - .use(activity) 84 - .onError(({ code, error }) => { 85 - switch (code) { 86 - case "VALIDATION": 87 - return error.all; 88 - default: 89 - if (error instanceof Error) { 90 - return { 91 - name: error.name, 92 - message: error.message, 93 - }; 94 - } 95 - } 96 - }) 97 - .listen(1337); 55 + const meRoute = app.get("/me", async (c) => { 56 + const session = getCookie(c, "session"); 98 57 99 - export type App = typeof app; 58 + if (!session) { 59 + return c.json({ user: null }); 60 + } 100 61 101 - migrate(db, { 102 - migrationsFolder: path.join(__dirname, "../drizzle"), 62 + const { user } = await validateSessionToken(session); 63 + 64 + if (user === null) { 65 + return c.json({ user: null }); 66 + } 67 + 68 + return c.json({ user }); 103 69 }); 104 70 105 - console.log(`🏃 Kaneo is running at ${app.server?.url}`); 71 + const workspaceRoute = app.route("/workspace", workspace); 72 + const workspaceUserRoute = app.route("/workspace-user", workspaceUser); 73 + const projectRoute = app.route("/project", project); 74 + const taskRoute = app.route("/task", task); 75 + const activityRoute = app.route("/activity", activity); 76 + 77 + try { 78 + console.log("Migrating database..."); 79 + migrate(db, { 80 + migrationsFolder: `${process.cwd()}/drizzle`, 81 + }); 82 + } catch (error) { 83 + console.error(error); 84 + } 85 + 86 + serve( 87 + { 88 + fetch: app.fetch, 89 + port: 1337, 90 + }, 91 + (info) => { 92 + console.log(`🏃 Hono API is running at http://localhost:${info.port}`); 93 + }, 94 + ); 95 + 96 + export type AppType = 97 + | typeof userRoute 98 + | typeof workspaceRoute 99 + | typeof workspaceUserRoute 100 + | typeof projectRoute 101 + | typeof taskRoute 102 + | typeof activityRoute 103 + | typeof meRoute;
-79
apps/api/src/middleware/check-permissions.ts
··· 1 - import { and, eq } from "drizzle-orm"; 2 - import { Elysia } from "elysia"; 3 - import db from "../database"; 4 - import { workspaceTable, workspaceUserTable } from "../database/schema"; 5 - 6 - type PermissionLevel = "owner" | "member"; 7 - 8 - export async function checkWorkspacePermission( 9 - userEmail: string, 10 - workspaceId: string, 11 - requiredRole: PermissionLevel = "member", 12 - ): Promise<boolean> { 13 - const [workspace] = await db 14 - .select() 15 - .from(workspaceTable) 16 - .where( 17 - and( 18 - eq(workspaceTable.id, workspaceId), 19 - eq(workspaceTable.ownerEmail, userEmail), 20 - ), 21 - ) 22 - .limit(1); 23 - 24 - if (workspace) return true; 25 - if (requiredRole === "owner") return false; 26 - 27 - const [member] = await db 28 - .select() 29 - .from(workspaceUserTable) 30 - .where( 31 - and( 32 - eq(workspaceUserTable.workspaceId, workspaceId), 33 - eq(workspaceUserTable.userEmail, userEmail), 34 - eq(workspaceUserTable.status, "active"), 35 - ), 36 - ) 37 - .limit(1); 38 - 39 - return Boolean(member); 40 - } 41 - 42 - export const requireWorkspacePermission = ( 43 - requiredRole: PermissionLevel = "member", 44 - ) => 45 - new Elysia() 46 - .state("userEmail", "" as string) 47 - .derive(async ({ store, params, set }) => { 48 - const userEmail = store.userEmail; 49 - 50 - let workspaceId: string | undefined; 51 - 52 - if (typeof params === "object" && params !== null) { 53 - if ("workspaceId" in params && typeof params.workspaceId === "string") { 54 - workspaceId = params.workspaceId; 55 - } else if ("id" in params && typeof params.id === "string") { 56 - workspaceId = params.id; 57 - } 58 - } 59 - 60 - if (!workspaceId) { 61 - set.status = 400; 62 - throw new Error("Workspace ID is required"); 63 - } 64 - 65 - const hasPermission = await checkWorkspacePermission( 66 - userEmail, 67 - workspaceId, 68 - requiredRole, 69 - ); 70 - 71 - if (!hasPermission) { 72 - set.status = 403; 73 - throw new Error( 74 - requiredRole === "owner" 75 - ? "Only workspace owners can perform this action" 76 - : "You don't have permission to access this workspace", 77 - ); 78 - } 79 - });
+29
apps/api/src/middlewares/auth.ts
··· 1 + import { getCookie, setCookie } from "hono/cookie"; 2 + import { createMiddleware } from "hono/factory"; 3 + import isInSecureMode from "../user/utils/is-in-secure-mode"; 4 + import { validateSessionToken } from "../user/utils/validate-session-token"; 5 + 6 + export const auth = createMiddleware(async (c, next) => { 7 + const token = getCookie(c, "session"); 8 + 9 + if (!token) { 10 + return c.json({ user: null }); 11 + } 12 + 13 + const { user, session: validatedSession } = await validateSessionToken(token); 14 + 15 + if (!user || !validatedSession) { 16 + return c.json({ user: null }); 17 + } 18 + 19 + setCookie(c, "session", token, { 20 + path: "/", 21 + secure: isInSecureMode(c.req), 22 + sameSite: "lax", 23 + expires: validatedSession.expiresAt, 24 + }); 25 + 26 + c.set("userEmail", user.email); 27 + 28 + return next(); 29 + });
+4 -1
apps/api/src/project/controllers/delete-project.ts
··· 1 1 import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { projectTable } from "../../database/schema"; 4 5 ··· 11 12 const isProjectExisting = Boolean(existingProject); 12 13 13 14 if (!isProjectExisting) { 14 - throw new Error("Project doesn't exist"); 15 + throw new HTTPException(404, { 16 + message: "Project doesn't exist", 17 + }); 15 18 } 16 19 17 20 const [deletedProject] = await db
+6 -1
apps/api/src/project/controllers/get-projects.ts
··· 21 21 .leftJoin(workspaceTable, eq(projectTable.workspaceId, workspaceTable.id)) 22 22 .where(and(eq(projectTable.workspaceId, workspaceId))); 23 23 24 - return projects; 24 + return projects.map((project) => ({ 25 + ...project, 26 + columns: [], 27 + plannedTasks: [], 28 + archivedTasks: [], 29 + })); 25 30 } 26 31 27 32 export default getProjects;
+9 -11
apps/api/src/project/controllers/update-project.ts
··· 1 - import { and, eq } from "drizzle-orm"; 1 + import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { projectTable } from "../../database/schema"; 4 5 5 6 async function updateProject( 6 7 id: string, 7 - workspaceId: string, 8 8 name: string, 9 - description: string, 10 9 icon: string, 11 10 slug: string, 11 + description: string, 12 12 ) { 13 13 const [existingProject] = await db 14 14 .select() 15 15 .from(projectTable) 16 - .where( 17 - and(eq(projectTable.id, id), eq(projectTable.workspaceId, workspaceId)), 18 - ); 16 + .where(eq(projectTable.id, id)); 19 17 20 18 const isProjectExisting = Boolean(existingProject); 21 19 22 20 if (!isProjectExisting) { 23 - throw new Error("Project doesn't exist"); 21 + throw new HTTPException(404, { 22 + message: "Project doesn't exist", 23 + }); 24 24 } 25 25 26 26 const [updatedWorkspace] = await db 27 27 .update(projectTable) 28 28 .set({ 29 29 name, 30 - description, 31 30 icon, 32 31 slug, 32 + description, 33 33 }) 34 - .where( 35 - and(eq(projectTable.id, id), eq(projectTable.workspaceId, workspaceId)), 36 - ) 34 + .where(eq(projectTable.id, id)) 37 35 .returning(); 38 36 39 37 return updatedWorkspace;
+66 -54
apps/api/src/project/index.ts
··· 1 - import Elysia, { t } from "elysia"; 2 - import { requireWorkspacePermission } from "../middleware/check-permissions"; 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { z } from "zod"; 3 4 import createProject from "./controllers/create-project"; 4 5 import deleteProject from "./controllers/delete-project"; 5 6 import getProject from "./controllers/get-project"; 6 7 import getProjects from "./controllers/get-projects"; 7 8 import updateProject from "./controllers/update-project"; 8 9 9 - const project = new Elysia({ prefix: "/project" }) 10 - .state("userEmail", "") 11 - .post( 12 - "/create", 13 - async ({ body: { workspaceId, icon, slug, name } }) => { 14 - const createdProject = await createProject(workspaceId, name, icon, slug); 15 - return createdProject; 10 + const project = new Hono() 11 + .get( 12 + "/", 13 + zValidator("query", z.object({ workspaceId: z.string() })), 14 + async (c) => { 15 + const { workspaceId } = c.req.valid("query"); 16 + const projects = await getProjects(workspaceId); 17 + return c.json(projects); 16 18 }, 17 - { 18 - body: t.Object({ 19 - name: t.String(), 20 - workspaceId: t.String(), 21 - icon: t.String(), 22 - slug: t.String(), 19 + ) 20 + .post( 21 + "/", 22 + zValidator( 23 + "json", 24 + z.object({ 25 + name: z.string(), 26 + workspaceId: z.string(), 27 + icon: z.string(), 28 + slug: z.string(), 23 29 }), 30 + ), 31 + async (c) => { 32 + const { name, workspaceId, icon, slug } = c.req.valid("json"); 33 + const project = await createProject(workspaceId, name, icon, slug); 34 + return c.json(project); 24 35 }, 25 36 ) 26 - .use(requireWorkspacePermission("owner")) 27 - .get("/list/:workspaceId", async ({ params: { workspaceId } }) => { 28 - const projects = await getProjects(workspaceId); 29 - return projects; 30 - }) 31 - .use(requireWorkspacePermission("member")) 32 - .get("/:id", async ({ params: { id }, query: { workspaceId } }) => { 33 - if (!workspaceId) throw new Error("Workspace ID is required"); 34 - const project = await getProject(id, workspaceId); 35 - return project; 36 - }) 37 - .use(requireWorkspacePermission("owner")) 38 - .put( 37 + .delete( 39 38 "/:id", 40 - async ({ 41 - params: { id }, 42 - body: { workspaceId, name, description, icon, slug }, 43 - }) => { 44 - const updatedProject = await updateProject( 45 - id, 46 - workspaceId, 47 - name, 48 - description, 49 - icon, 50 - slug, 51 - ); 52 - return updatedProject; 39 + zValidator("param", z.object({ id: z.string() })), 40 + async (c) => { 41 + const { id } = c.req.valid("param"); 42 + 43 + const project = await deleteProject(id); 44 + 45 + return c.json(project); 53 46 }, 54 - { 55 - body: t.Object({ 56 - workspaceId: t.String(), 57 - name: t.String(), 58 - description: t.String(), 59 - icon: t.String(), 60 - slug: t.String(), 47 + ) 48 + .put( 49 + "/:id", 50 + zValidator("param", z.object({ id: z.string() })), 51 + zValidator( 52 + "json", 53 + z.object({ 54 + name: z.string(), 55 + icon: z.string(), 56 + slug: z.string(), 57 + description: z.string(), 61 58 }), 59 + ), 60 + async (c) => { 61 + const { id } = c.req.valid("param"); 62 + const { name, icon, slug, description } = c.req.valid("json"); 63 + 64 + const project = await updateProject(id, name, icon, slug, description); 65 + 66 + return c.json(project); 62 67 }, 63 68 ) 64 - .use(requireWorkspacePermission("owner")) 65 - .delete("/:id", async ({ params: { id } }) => { 66 - const deletedProject = await deleteProject(id); 67 - return deletedProject; 68 - }) 69 - .use(requireWorkspacePermission("owner")); 69 + .get( 70 + "/:id", 71 + zValidator("param", z.object({ id: z.string() })), 72 + zValidator("query", z.object({ workspaceId: z.string() })), 73 + async (c) => { 74 + const { id } = c.req.valid("param"); 75 + const { workspaceId } = c.req.valid("query"); 76 + 77 + const project = await getProject(id, workspaceId); 78 + 79 + return c.json(project); 80 + }, 81 + ); 70 82 71 83 export default project;
+33 -26
apps/api/src/task/controllers/create-task.ts
··· 1 - import { count, eq } from "drizzle-orm"; 1 + import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { taskTable, userTable } from "../../database/schema"; 4 5 import { publishEvent } from "../../events"; 6 + import getNextTaskNumber from "./get-next-task-number"; 5 7 6 - async function getNextTaskNumber(projectId: string) { 7 - const [task] = await db 8 - .select({ count: count() }) 9 - .from(taskTable) 10 - .where(eq(taskTable.projectId, projectId)); 11 - 12 - return task.count; 13 - } 14 - 15 - async function createTask(body: { 8 + async function createTask({ 9 + projectId, 10 + userEmail, 11 + title, 12 + status, 13 + dueDate, 14 + description, 15 + priority, 16 + }: { 16 17 projectId: string; 17 - userEmail: string | null; 18 - title: string | null; 19 - status: string | null; 20 - dueDate: Date | null; 21 - description: string | null; 22 - priority: string | null; 18 + userEmail?: string; 19 + title: string; 20 + status: string; 21 + dueDate?: Date; 22 + description?: string; 23 + priority?: string; 23 24 }) { 24 25 const [assignee] = await db 25 26 .select({ name: userTable.name }) 26 27 .from(userTable) 27 - .where(eq(userTable.email, body.userEmail ?? "")); 28 + .where(eq(userTable.email, userEmail ?? "")); 28 29 29 - const nextTaskNumber = await getNextTaskNumber(body.projectId); 30 + const nextTaskNumber = await getNextTaskNumber(projectId); 30 31 31 32 const [createdTask] = await db 32 33 .insert(taskTable) 33 34 .values({ 34 - ...body, 35 - userEmail: body.userEmail ?? "", 36 - title: body.title ?? "", 37 - status: body.status ?? "", 38 - dueDate: body.dueDate ?? new Date(), 39 - description: body.description ?? "", 40 - priority: body.priority ?? "", 35 + projectId, 36 + userEmail: userEmail || null, 37 + title: title || "", 38 + status: status || "", 39 + dueDate: dueDate || new Date(), 40 + description: description || "", 41 + priority: priority || "", 41 42 number: nextTaskNumber + 1, 42 43 }) 43 44 .returning(); 45 + 46 + if (!createdTask) { 47 + throw new HTTPException(500, { 48 + message: "Failed to create task", 49 + }); 50 + } 44 51 45 52 await publishEvent("task.created", { 46 53 taskId: createdTask.id,
+14
apps/api/src/task/controllers/get-next-task-number.ts
··· 1 + import { count, eq } from "drizzle-orm"; 2 + import db from "../../database"; 3 + import { taskTable } from "../../database/schema"; 4 + 5 + async function getNextTaskNumber(projectId: string) { 6 + const [task] = await db 7 + .select({ count: count() }) 8 + .from(taskTable) 9 + .where(eq(taskTable.projectId, projectId)); 10 + 11 + return task ? task.count : 0; 12 + } 13 + 14 + export default getNextTaskNumber;
+4 -1
apps/api/src/task/controllers/get-task.ts
··· 1 1 import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { taskTable } from "../../database/schema"; 4 5 ··· 8 9 }); 9 10 10 11 if (!task) { 11 - throw new Error("Task not found"); 12 + throw new HTTPException(404, { 13 + message: "Task not found", 14 + }); 12 15 } 13 16 14 17 return task;
+4 -1
apps/api/src/task/controllers/get-tasks.ts
··· 1 1 import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { projectTable, taskTable, userTable } from "../../database/schema"; 4 5 ··· 15 16 }); 16 17 17 18 if (!project) { 18 - throw new Error("Project not found"); 19 + throw new HTTPException(404, { 20 + message: "Project not found", 21 + }); 19 22 } 20 23 21 24 const tasks = await db
+22 -18
apps/api/src/task/controllers/update-task.ts
··· 1 1 import { eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { taskTable } from "../../database/schema"; 4 5 5 6 async function updateTask( 6 7 taskId: string, 7 - body: { 8 - projectId: string; 9 - userEmail: string; 10 - title: string; 11 - status: string; 12 - dueDate: Date | null; 13 - description: string; 14 - priority: string; 15 - position: number; 16 - }, 8 + title: string, 9 + status: string, 10 + dueDate: Date, 11 + projectId: string, 12 + description?: string, 13 + priority?: string, 14 + position?: number, 15 + userEmail?: string, 17 16 ) { 18 17 const [existingTask] = await db 19 18 .select() ··· 23 22 const isTaskExisting = Boolean(existingTask); 24 23 25 24 if (!isTaskExisting) { 26 - throw new Error("Task doesn't exist"); 25 + throw new HTTPException(404, { 26 + message: "Task doesn't exist", 27 + }); 27 28 } 29 + 30 + const userEmailToUpdate = userEmail?.length ? userEmail : null; 28 31 29 32 const [updatedTask] = await db 30 33 .update(taskTable) 31 34 .set({ 32 - title: body.title, 33 - description: body.description, 34 - status: body.status, 35 - dueDate: new Date(body.dueDate ?? ""), 36 - priority: body.priority, 37 - userEmail: body.userEmail, 38 - position: body.position, 35 + title, 36 + description, 37 + status, 38 + dueDate, 39 + priority, 40 + userEmail: userEmailToUpdate, 41 + position, 42 + projectId, 39 43 }) 40 44 .where(eq(taskTable.id, taskId)) 41 45 .returning();
+91 -55
apps/api/src/task/index.ts
··· 1 - import Elysia, { t } from "elysia"; 2 - 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { z } from "zod"; 3 4 import createTask from "./controllers/create-task"; 4 5 import getTask from "./controllers/get-task"; 5 6 import getTasks from "./controllers/get-tasks"; 6 7 import updateTask from "./controllers/update-task"; 7 8 8 - const task = new Elysia({ prefix: "/task" }) 9 - .post( 10 - "/create", 11 - async ({ body }) => { 12 - const createdTask = await createTask(body); 13 - return createdTask; 14 - }, 15 - { 16 - body: t.Object({ 17 - projectId: t.String(), 18 - userEmail: t.String(), 19 - title: t.String(), 20 - status: t.String(), 21 - dueDate: t.Date(), 22 - description: t.String(), 23 - priority: t.String(), 24 - position: t.Number(), 25 - }), 26 - }, 27 - ) 9 + const task = new Hono<{ 10 + Variables: { 11 + userEmail: string; 12 + }; 13 + }>() 28 14 .get( 29 - "/:taskId", 30 - async ({ params }) => { 31 - const task = await getTask(params.taskId); 32 - return task; 33 - }, 34 - { 35 - params: t.Object({ 36 - taskId: t.String(), 37 - }), 15 + "/tasks/:projectId", 16 + zValidator("param", z.object({ projectId: z.string() })), 17 + async (c) => { 18 + const { projectId } = c.req.valid("param"); 19 + 20 + const tasks = await getTasks(projectId); 21 + 22 + return c.json(tasks); 38 23 }, 39 24 ) 40 - .get( 41 - "/list/:projectId", 42 - async ({ params }) => { 43 - const tasks = await getTasks(params.projectId); 44 - return tasks; 45 - }, 46 - { 47 - params: t.Object({ 48 - projectId: t.String(), 25 + .post( 26 + "/:projectId", 27 + zValidator( 28 + "json", 29 + z.object({ 30 + title: z.string(), 31 + description: z.string(), 32 + dueDate: z.string(), 33 + priority: z.string(), 34 + status: z.string(), 35 + userEmail: z.string().optional(), 49 36 }), 37 + ), 38 + async (c) => { 39 + const { projectId } = c.req.param(); 40 + const { title, description, dueDate, priority, status, userEmail } = 41 + c.req.valid("json"); 42 + 43 + const task = await createTask({ 44 + projectId, 45 + userEmail, 46 + title, 47 + description, 48 + dueDate: new Date(dueDate), 49 + priority, 50 + status, 51 + }); 52 + 53 + return c.json(task); 50 54 }, 51 55 ) 56 + .get("/:id", zValidator("param", z.object({ id: z.string() })), async (c) => { 57 + const { id } = c.req.valid("param"); 58 + 59 + const task = await getTask(id); 60 + 61 + return c.json(task); 62 + }) 52 63 .put( 53 - "/:taskId/update", 54 - async ({ params, body }) => { 55 - const updatedTask = await updateTask(params.taskId, body); 56 - return updatedTask; 57 - }, 58 - { 59 - body: t.Object({ 60 - projectId: t.String(), 61 - userEmail: t.String(), 62 - title: t.String(), 63 - status: t.String(), 64 - dueDate: t.Date(), 65 - description: t.String(), 66 - priority: t.String(), 67 - position: t.Number(), 64 + "/:id", 65 + zValidator("param", z.object({ id: z.string() })), 66 + zValidator( 67 + "json", 68 + z.object({ 69 + title: z.string(), 70 + description: z.string(), 71 + dueDate: z.string(), 72 + priority: z.string(), 73 + status: z.string(), 74 + projectId: z.string(), 75 + position: z.number(), 76 + userEmail: z.string().optional(), 68 77 }), 78 + ), 79 + async (c) => { 80 + const { id } = c.req.valid("param"); 81 + const { 82 + title, 83 + description, 84 + dueDate, 85 + priority, 86 + status, 87 + projectId, 88 + position, 89 + userEmail, 90 + } = c.req.valid("json"); 91 + 92 + const task = await updateTask( 93 + id, 94 + title, 95 + status, 96 + new Date(dueDate), 97 + projectId, 98 + description, 99 + priority, 100 + position, 101 + userEmail, 102 + ); 103 + 104 + return c.json(task); 69 105 }, 70 106 ); 71 107
+2 -3
apps/api/src/user/controllers/create-session.ts apps/api/src/user/utils/create-session.ts
··· 2 2 import { encodeHexLowerCase } from "@oslojs/encoding"; 3 3 import db from "../../database"; 4 4 import { sessionTable } from "../../database/schema"; 5 - import type { Session } from "../types"; 6 5 7 - async function createSession(token: string, userId: string): Promise<Session> { 6 + async function createSession(token: string, userId: string) { 8 7 const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); 9 - const session: Session = { 8 + const session = { 10 9 id: sessionId, 11 10 userId, 12 11 expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30),
+1 -1
apps/api/src/user/controllers/invalidate-session.ts apps/api/src/user/utils/invalidate-session.ts
··· 2 2 import db from "../../database"; 3 3 import { sessionTable } from "../../database/schema"; 4 4 5 - async function invalidateSession(sessionId: string): Promise<void> { 5 + async function invalidateSession(sessionId: string) { 6 6 await db.delete(sessionTable).where(eq(sessionTable.id, sessionId)); 7 7 } 8 8
+2 -5
apps/api/src/user/controllers/sign-in.ts
··· 1 + import bcrypt from "bcrypt"; 1 2 import db from "../../database"; 2 3 3 4 async function signIn(email: string, password: string) { ··· 9 10 throw new Error("User not found"); 10 11 } 11 12 12 - const isPasswordValid = await Bun.password.verify( 13 - password, 14 - user.password, 15 - "bcrypt", 16 - ); 13 + const isPasswordValid = await bcrypt.compare(password, user.password); 17 14 18 15 if (!isPasswordValid) { 19 16 throw new Error("Invalid credentials");
+12 -6
apps/api/src/user/controllers/sign-up.ts
··· 1 + import bcrypt from "bcrypt"; 2 + import { HTTPException } from "hono/http-exception"; 1 3 import db from "../../database"; 2 4 import { userTable } from "../../database/schema"; 3 5 import { publishEvent } from "../../events"; ··· 7 9 const { allowRegistration, isDemoMode } = getSettings(); 8 10 9 11 if (!allowRegistration && !isDemoMode) { 10 - throw new Error("Registration is disabled on this instance"); 12 + throw new HTTPException(400, { 13 + message: "Registration is disabled on this instance", 14 + }); 11 15 } 12 16 13 17 const isEmailTaken = Boolean( ··· 17 21 ); 18 22 19 23 if (isEmailTaken) { 20 - throw new Error("Email taken"); 24 + throw new HTTPException(400, { 25 + message: "Email taken", 26 + }); 21 27 } 22 28 23 - const hashedPassword = await Bun.password.hash(password, { 24 - algorithm: "bcrypt", 25 - }); 29 + const hashedPassword = await bcrypt.hash(password, 10); 26 30 27 31 const user = ( 28 32 await db ··· 32 36 ).at(0); 33 37 34 38 if (!user) { 35 - throw new Error("Failed to create an account"); 39 + throw new HTTPException(500, { 40 + message: "Failed to create an account", 41 + }); 36 42 } 37 43 38 44 publishEvent("user.signed_up", {
+2 -5
apps/api/src/user/controllers/validate-session-token.ts apps/api/src/user/utils/validate-session-token.ts
··· 3 3 import { eq } from "drizzle-orm"; 4 4 import db from "../../database"; 5 5 import { sessionTable, userTable } from "../../database/schema"; 6 - import type { SessionValidationResult } from "../types"; 7 6 8 - export async function validateSessionToken( 9 - token: string, 10 - ): Promise<SessionValidationResult> { 7 + export async function validateSessionToken(token: string) { 11 8 const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); 12 9 const sessions = await db 13 10 .select({ user: userTable, session: sessionTable }) ··· 15 12 .innerJoin(userTable, eq(sessionTable.userId, userTable.id)) 16 13 .where(eq(sessionTable.id, sessionId)); 17 14 18 - if (sessions.length < 1) { 15 + if (sessions.length < 1 || !sessions[0]) { 19 16 return { session: null, user: null }; 20 17 } 21 18
+43 -67
apps/api/src/user/index.ts
··· 1 - import { jwt } from "@elysiajs/jwt"; 2 - import { Elysia, t } from "elysia"; 3 - import createSession from "./controllers/create-session"; 4 - import invalidateSession from "./controllers/invalidate-session"; 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { deleteCookie, getCookie, setCookie } from "hono/cookie"; 4 + import { z } from "zod"; 5 5 import signIn from "./controllers/sign-in"; 6 6 import signUp from "./controllers/sign-up"; 7 + import createSession from "./utils/create-session"; 7 8 import generateSessionToken from "./utils/generate-session-token"; 9 + import invalidateSession from "./utils/invalidate-session"; 8 10 import isInSecureMode from "./utils/is-in-secure-mode"; 9 11 10 - const user = new Elysia({ prefix: "/user" }) 11 - .use( 12 - jwt({ 13 - name: "sessionToken", 14 - secret: process.env.JWT_ACCESS ?? "", 15 - }), 16 - ) 12 + const user = new Hono() 17 13 .post( 18 14 "/sign-in", 19 - async ({ body: { email, password }, set, request }) => { 15 + zValidator("json", z.object({ email: z.string(), password: z.string() })), 16 + async (c) => { 17 + const { email, password } = c.req.valid("json"); 18 + 20 19 const user = await signIn(email, password); 21 20 22 21 const token = generateSessionToken(); 23 22 const session = await createSession(token, user.id); 24 - set.cookie = { 25 - session: { 26 - value: token, 27 - httpOnly: true, 28 - path: "/", 29 - secure: isInSecureMode(request), 30 - sameSite: "lax", 31 - expires: session.expiresAt, 32 - }, 33 - }; 23 + 24 + setCookie(c, "session", token, { 25 + path: "/", 26 + secure: isInSecureMode(c.req), 27 + sameSite: "lax", 28 + expires: session.expiresAt, 29 + }); 34 30 35 - return user; 36 - }, 37 - { 38 - body: t.Object({ 39 - email: t.String(), 40 - password: t.String(), 41 - }), 31 + return c.json(user); 42 32 }, 43 33 ) 44 34 .post( 45 35 "/sign-up", 46 - async ({ body: { email, password, name }, set, request }) => { 47 - const user = await signUp(email, password, name); 36 + zValidator( 37 + "json", 38 + z.object({ email: z.string(), password: z.string(), name: z.string() }), 39 + ), 40 + async (c) => { 41 + const { email, password, name } = c.req.valid("json"); 48 42 49 - if (!user) throw new Error("Failed to create an account"); 43 + const user = await signUp(email, password, name); 50 44 51 45 const token = generateSessionToken(); 52 46 const session = await createSession(token, user.id); 53 - set.cookie = { 54 - session: { 55 - value: token, 56 - httpOnly: true, 57 - path: "/", 58 - secure: isInSecureMode(request), 59 - sameSite: "lax", 60 - expires: session.expiresAt, 61 - }, 62 - }; 63 47 64 - return user; 65 - }, 66 - { 67 - body: t.Object({ 68 - email: t.String(), 69 - password: t.String(), 70 - name: t.String(), 71 - }), 48 + setCookie(c, "session", token, { 49 + path: "/", 50 + secure: isInSecureMode(c.req), 51 + sameSite: "lax", 52 + expires: session.expiresAt, 53 + }); 54 + 55 + return c.json(user); 72 56 }, 73 57 ) 74 - .post("/sign-out", async ({ cookie, cookie: { session } }) => { 75 - await invalidateSession(session?.value ?? ""); 76 - session.remove(); 58 + .post("/sign-out", async (c) => { 59 + const token = getCookie(c, "session"); 77 60 78 - // biome-ignore lint/performance/noDelete: https://elysiajs.com/patterns/cookie#remove 79 - delete cookie.session; 80 - }) 81 - .onError(({ code, error }) => { 82 - switch (code) { 83 - case "VALIDATION": 84 - return error.all; 85 - default: 86 - if (error instanceof Error) { 87 - return { 88 - name: error.name, 89 - message: error.message, 90 - }; 91 - } 61 + if (!token) { 62 + return c.json({ message: "No session token found" }, 401); 92 63 } 64 + 65 + await invalidateSession(token); 66 + deleteCookie(c, "session"); 67 + 68 + return c.json({ message: "Signed out" }); 93 69 }); 94 70 95 71 export default user;
-9
apps/api/src/user/types.ts
··· 1 - import type { InferSelectModel } from "drizzle-orm"; 2 - import type { sessionTable, userTable } from "../database/schema"; 3 - 4 - export type User = InferSelectModel<typeof userTable>; 5 - export type Session = InferSelectModel<typeof sessionTable>; 6 - 7 - export type SessionValidationResult = 8 - | { session: Session; user: User } 9 - | { session: null; user: null };
+4 -2
apps/api/src/user/utils/is-in-secure-mode.ts
··· 1 - export default function isInSecureMode(request: Request) { 2 - return request.headers.get("x-forwarded-proto") === "https"; 1 + import type { Context } from "hono"; 2 + 3 + export default function isInSecureMode(request: Context["req"]) { 4 + return request.header("x-forwarded-proto") === "https"; 3 5 }
+4 -5
apps/api/src/utils/create-demo-user.ts
··· 1 1 import { createId } from "@paralleldrive/cuid2"; 2 + import bcrypt from "bcrypt"; 2 3 import db from "../database"; 3 4 import { userTable } from "../database/schema"; 4 - import createSession from "../user/controllers/create-session"; 5 + import createSession from "../user/utils/create-session"; 5 6 import generateSessionToken from "../user/utils/generate-session-token"; 6 7 import { generateDemoName } from "./generate-demo-name"; 7 - 8 8 export async function createDemoUser() { 9 9 const demoId = createId(); 10 10 const demoName = generateDemoName(); 11 11 const demoEmail = `${demoName}-${demoId}@kaneo.app`; 12 12 13 - const hashedPassword = await Bun.password.hash("demo", { 14 - algorithm: "bcrypt", 15 - }); 13 + const hashedPassword = await bcrypt.hash("demo", 10); 14 + 16 15 await db.insert(userTable).values({ 17 16 id: demoId, 18 17 name: demoName
+1 -1
apps/api/src/utils/purge-demo-data.ts
··· 1 - import { userTable } from "../database/schema"; 2 1 import { projectTable } from "../database/schema"; 3 2 import { taskTable } from "../database/schema"; 3 + import { userTable } from "../database/schema"; 4 4 import { workspaceTable } from "../database/schema"; 5 5 import { workspaceUserTable } from "../database/schema"; 6 6
+11 -11
apps/api/src/utils/set-demo-user.ts
··· 1 1 // @ts-ignore - This is used by Elysia 2 2 import type { ElysiaCookie } from "elysia/dist/cookies"; 3 + import type { Context } from "hono"; 4 + import { setCookie } from "hono/cookie"; 5 + import isInSecureMode from "../user/utils/is-in-secure-mode"; 3 6 import { createDemoUser } from "./create-demo-user"; 4 7 5 - async function setDemoUser(set: { cookie?: Record<string, ElysiaCookie> }) { 8 + async function setDemoUser(c: Context) { 6 9 const demoExpiresAt = new Date(Date.now() + 15 * 60 * 1000); 7 10 const { session: demoSession, expiresAt = demoExpiresAt } = 8 11 await createDemoUser(); 9 12 10 - set.cookie = { 11 - session: { 12 - value: demoSession, 13 - httpOnly: true, 14 - path: "/", 15 - secure: true, 16 - sameSite: "lax", 17 - expires: expiresAt, 18 - }, 19 - }; 13 + setCookie(c, "session", demoSession, { 14 + httpOnly: isInSecureMode(c.req), 15 + path: "/", 16 + secure: true, 17 + sameSite: "lax", 18 + expires: expiresAt, 19 + }); 20 20 } 21 21 22 22 export default setDemoUser;
+1 -4
apps/api/src/workspace-user/controllers/create-root-workspace-user.ts
··· 1 1 import db from "../../database"; 2 2 import { workspaceUserTable } from "../../database/schema"; 3 3 4 - async function createRootWorkspaceUser({ 5 - workspaceId, 6 - userEmail, 7 - }: { workspaceId: string; userEmail: string }) { 4 + async function createRootWorkspaceUser(workspaceId: string, userEmail: string) { 8 5 const [workspaceUser] = await db 9 6 .insert(workspaceUserTable) 10 7 .values({
+6 -6
apps/api/src/workspace-user/controllers/delete-workspace-user.ts
··· 2 2 import db from "../../database"; 3 3 import { workspaceUserTable } from "../../database/schema"; 4 4 5 - async function deleteWorkspaceUser({ 6 - workspaceId, 7 - userEmail, 8 - }: { workspaceId: string; userEmail: string }) { 9 - await db 5 + async function deleteWorkspaceUser(workspaceId: string, userEmail: string) { 6 + const [deletedWorkspaceUser] = await db 10 7 .delete(workspaceUserTable) 11 8 .where( 12 9 and( 13 10 eq(workspaceUserTable.workspaceId, workspaceId), 14 11 eq(workspaceUserTable.userEmail, userEmail), 15 12 ), 16 - ); 13 + ) 14 + .returning(); 15 + 16 + return deletedWorkspaceUser; 17 17 } 18 18 19 19 export default deleteWorkspaceUser;
+11 -3
apps/api/src/workspace-user/controllers/get-active-workspace-users.ts
··· 2 2 import db from "../../database"; 3 3 import { userTable, workspaceUserTable } from "../../database/schema"; 4 4 5 - function getActiveWorkspaceUsers(workspaceId: string) { 6 - return db 7 - .select() 5 + async function getActiveWorkspaceUsers(workspaceId: string) { 6 + const activeWorkspaceUsers = await db 7 + .select({ 8 + id: workspaceUserTable.id, 9 + userEmail: workspaceUserTable.userEmail, 10 + userName: userTable.name, 11 + role: workspaceUserTable.role, 12 + status: workspaceUserTable.status, 13 + }) 8 14 .from(workspaceUserTable) 9 15 .where( 10 16 and( ··· 13 19 ), 14 20 ) 15 21 .innerJoin(userTable, eq(workspaceUserTable.userEmail, userTable.email)); 22 + 23 + return activeWorkspaceUsers; 16 24 } 17 25 18 26 export default getActiveWorkspaceUsers;
+1 -1
apps/api/src/workspace-user/controllers/get-workspace-users.ts
··· 2 2 import db from "../../database"; 3 3 import { userTable, workspaceUserTable } from "../../database/schema"; 4 4 5 - function getWorkspaceUsers({ workspaceId }: { workspaceId: string }) { 5 + function getWorkspaceUsers(workspaceId: string) { 6 6 return db 7 7 .select({ 8 8 userEmail: workspaceUserTable.userEmail,
+21 -6
apps/api/src/workspace-user/controllers/invite-workspace-user.ts
··· 1 1 import { and, eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 - import { workspaceUserTable } from "../../database/schema"; 4 + import { 5 + userTable, 6 + workspaceTable, 7 + workspaceUserTable, 8 + } from "../../database/schema"; 9 + 10 + async function inviteWorkspaceUser(workspaceId: string, userEmail: string) { 11 + const [workspace] = await db 12 + .select() 13 + .from(workspaceTable) 14 + .where(eq(workspaceTable.id, workspaceId)); 15 + 16 + if (!workspace) { 17 + throw new HTTPException(404, { 18 + message: "Workspace not found", 19 + }); 20 + } 4 21 5 - async function inviteWorkspaceUser({ 6 - workspaceId, 7 - userEmail, 8 - }: { workspaceId: string; userEmail: string }) { 9 22 const [existingUser] = await db 10 23 .select() 11 24 .from(workspaceUserTable) ··· 17 30 ); 18 31 19 32 if (existingUser) { 20 - throw new Error("User is already invited to this workspace"); 33 + throw new HTTPException(400, { 34 + message: "User is already invited to this workspace", 35 + }); 21 36 } 22 37 23 38 const [invitedUser] = await db
+8 -16
apps/api/src/workspace-user/controllers/update-workspace-user.ts
··· 2 2 import db from "../../database"; 3 3 import { workspaceUserTable } from "../../database/schema"; 4 4 5 - async function upsertWorkspaceUser(data: { 6 - email: string; 7 - status: string; 8 - }) { 9 - const workspaceUser = await db.query.workspaceUserTable.findFirst({ 10 - where: eq(workspaceUserTable.userEmail, data.email), 11 - }); 12 - 13 - if (!workspaceUser) { 14 - return; 15 - } 16 - 17 - await db 5 + async function updateWorkspaceUser(userEmail: string, status: string) { 6 + const [updatedWorkspaceUser] = await db 18 7 .update(workspaceUserTable) 19 - .set({ status: data.status }) 20 - .where(eq(workspaceUserTable.id, workspaceUser.id)); 8 + .set({ status }) 9 + .where(eq(workspaceUserTable.userEmail, userEmail)) 10 + .returning(); 11 + 12 + return updatedWorkspaceUser; 21 13 } 22 14 23 - export default upsertWorkspaceUser; 15 + export default updateWorkspaceUser;
-20
apps/api/src/workspace-user/events/index.ts
··· 1 - import { subscribeToEvent } from "../../events"; 2 - import createRootWorkspaceUser from "../controllers/create-root-workspace-user"; 3 - import updateWorkspaceUser from "../controllers/update-workspace-user"; 4 - 5 - subscribeToEvent("user.signed_up", async (data: { email: string }) => { 6 - await updateWorkspaceUser({ 7 - email: data.email, 8 - status: "active", 9 - }); 10 - }); 11 - 12 - subscribeToEvent( 13 - "workspace.created", 14 - async (data: { workspaceId: string; ownerEmail: string }) => { 15 - await createRootWorkspaceUser({ 16 - workspaceId: data.workspaceId, 17 - userEmail: data.ownerEmail, 18 - }); 19 - }, 20 - );
+119 -57
apps/api/src/workspace-user/index.ts
··· 1 - import Elysia, { t } from "elysia"; 2 - import { requireWorkspacePermission } from "../middleware/check-permissions"; 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { z } from "zod"; 4 + import { subscribeToEvent } from "../events"; 5 + import createRootWorkspaceUser from "./controllers/create-root-workspace-user"; 3 6 import deleteWorkspaceUser from "./controllers/delete-workspace-user"; 7 + import getActiveWorkspaceUsers from "./controllers/get-active-workspace-users"; 4 8 import getWorkspaceUsers from "./controllers/get-workspace-users"; 5 9 import inviteWorkspaceUser from "./controllers/invite-workspace-user"; 6 - import "./events"; 7 - import getActiveWorkspaceUsers from "./controllers/get-active-workspace-users"; 10 + import updateWorkspaceUser from "./controllers/update-workspace-user"; 8 11 9 - const workspaceUser = new Elysia({ prefix: "/workspace-user" }) 10 - .state("userEmail", "") 11 - .get( 12 - "/list/:workspaceId", 13 - async ({ params: { workspaceId } }) => { 14 - const workspaceUsersInWorkspace = await getWorkspaceUsers({ 12 + const workspaceUser = new Hono<{ 13 + Variables: { 14 + userEmail: string; 15 + }; 16 + }>() 17 + .post( 18 + "/root", 19 + zValidator( 20 + "json", 21 + z.object({ 22 + workspaceId: z.string(), 23 + userEmail: z.string(), 24 + }), 25 + ), 26 + async (c) => { 27 + const { workspaceId, userEmail } = c.req.valid("json"); 28 + 29 + const workspaceUser = await createRootWorkspaceUser( 15 30 workspaceId, 16 - }); 31 + userEmail, 32 + ); 17 33 18 - return workspaceUsersInWorkspace; 34 + return c.json(workspaceUser); 19 35 }, 20 - { 21 - params: t.Object({ 22 - workspaceId: t.String(), 23 - }), 36 + ) 37 + .get( 38 + "/:workspaceId", 39 + zValidator("param", z.object({ workspaceId: z.string() })), 40 + async (c) => { 41 + const { workspaceId } = c.req.valid("param"); 42 + 43 + const workspaceUsers = await getWorkspaceUsers(workspaceId); 44 + 45 + return c.json(workspaceUsers); 24 46 }, 25 47 ) 26 - .use(requireWorkspacePermission("member")) 27 - .post( 28 - "/:workspaceId/invite", 29 - async ({ params: { workspaceId }, body: { userEmail } }) => { 30 - const invitedUser = await inviteWorkspaceUser({ 48 + .delete( 49 + "/:workspaceId", 50 + zValidator("param", z.object({ workspaceId: z.string() })), 51 + zValidator("query", z.object({ userEmail: z.string() })), 52 + async (c) => { 53 + const { workspaceId } = c.req.valid("param"); 54 + const { userEmail } = c.req.valid("query"); 55 + 56 + const deletedWorkspaceUser = await deleteWorkspaceUser( 31 57 workspaceId, 32 58 userEmail, 33 - }); 34 - return invitedUser; 59 + ); 60 + 61 + return c.json(deletedWorkspaceUser); 35 62 }, 36 - { 37 - body: t.Object({ 38 - workspaceId: t.String(), 39 - userEmail: t.String(), 40 - }), 63 + ) 64 + .put( 65 + "/:userEmail", 66 + zValidator("param", z.object({ userEmail: z.string() })), 67 + zValidator("json", z.object({ status: z.string() })), 68 + async (c) => { 69 + const { userEmail } = c.req.valid("param"); 70 + const { status } = c.req.valid("json"); 71 + 72 + const updatedWorkspaceUser = await updateWorkspaceUser(userEmail, status); 73 + 74 + return c.json(updatedWorkspaceUser); 41 75 }, 42 76 ) 43 - .use(requireWorkspacePermission("owner")) 77 + .get( 78 + "/:workspaceId/active", 79 + zValidator("param", z.object({ workspaceId: z.string() })), 80 + async (c) => { 81 + const { workspaceId } = c.req.valid("param"); 82 + 83 + const activeWorkspaceUsers = await getActiveWorkspaceUsers(workspaceId); 84 + 85 + return c.json(activeWorkspaceUsers); 86 + }, 87 + ) 88 + .post( 89 + "/:workspaceId/invite", 90 + zValidator("param", z.object({ workspaceId: z.string() })), 91 + zValidator("json", z.object({ userEmail: z.string() })), 92 + async (c) => { 93 + const { workspaceId } = c.req.valid("param"); 94 + const { userEmail } = c.req.valid("json"); 95 + 96 + const workspaceUser = await inviteWorkspaceUser(workspaceId, userEmail); 97 + 98 + return c.json(workspaceUser); 99 + }, 100 + ) 44 101 .delete( 45 - "/:workspaceId/:userEmail", 46 - async ({ params: { workspaceId, userEmail } }) => { 47 - const deletedUser = await deleteWorkspaceUser({ 102 + "/:workspaceId/invite/:userEmail", 103 + zValidator( 104 + "param", 105 + z.object({ workspaceId: z.string(), userEmail: z.string() }), 106 + ), 107 + async (c) => { 108 + const { workspaceId, userEmail } = c.req.valid("param"); 109 + 110 + const deletedWorkspaceUser = await deleteWorkspaceUser( 48 111 workspaceId, 49 112 userEmail, 50 - }); 51 - return deletedUser; 52 - }, 53 - { 54 - params: t.Object({ 55 - workspaceId: t.String(), 56 - userEmail: t.String(), 57 - }), 113 + ); 114 + 115 + return c.json(deletedWorkspaceUser); 58 116 }, 59 - ) 60 - .get("/:workspaceId/active", async ({ params: { workspaceId } }) => { 61 - const activeWorkspaceUsers = await getActiveWorkspaceUsers(workspaceId); 117 + ); 62 118 63 - return activeWorkspaceUsers; 64 - }) 65 - .onError(({ code, error }) => { 66 - switch (code) { 67 - case "VALIDATION": 68 - return error.all; 69 - default: 70 - if (error instanceof Error) { 71 - return { 72 - name: error.name, 73 - message: error.message, 74 - }; 75 - } 119 + subscribeToEvent("user.signed_up", async ({ email }: { email: string }) => { 120 + if (!email) { 121 + return; 122 + } 123 + 124 + await updateWorkspaceUser(email, "active"); 125 + }); 126 + 127 + subscribeToEvent( 128 + "workspace.created", 129 + async ({ 130 + workspaceId, 131 + ownerEmail, 132 + }: { workspaceId: string; ownerEmail: string }) => { 133 + if (!workspaceId || !ownerEmail) { 134 + return; 76 135 } 77 - }); 136 + 137 + await createRootWorkspaceUser(workspaceId, ownerEmail); 138 + }, 139 + ); 78 140 79 141 export default workspaceUser;
+7 -1
apps/api/src/workspace/controllers/create-workspace.ts
··· 1 + import { HTTPException } from "hono/http-exception"; 1 2 import db from "../../database"; 2 3 import { workspaceTable } from "../../database/schema"; 3 4 import { publishEvent } from "../../events"; 4 - 5 5 async function createWorkspace(name: string, ownerEmail: string) { 6 6 const [workspace] = await db 7 7 .insert(workspaceTable) ··· 10 10 ownerEmail, 11 11 }) 12 12 .returning(); 13 + 14 + if (!workspace) { 15 + throw new HTTPException(500, { 16 + message: "Failed to create workspace", 17 + }); 18 + } 13 19 14 20 publishEvent("workspace.created", { 15 21 workspaceId: workspace.id,
+4 -1
apps/api/src/workspace/controllers/delete-workspace.ts
··· 1 1 import { and, eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { workspaceTable } from "../../database/schema"; 4 5 ··· 20 21 const isWorkspaceExisting = Boolean(existingWorkspace); 21 22 22 23 if (!isWorkspaceExisting) { 23 - throw new Error("Workspace not found or access denied"); 24 + throw new HTTPException(404, { 25 + message: "Workspace not found", 26 + }); 24 27 } 25 28 26 29 const [deletedWorkspace] = await db
+9
apps/api/src/workspace/controllers/get-workspace.ts
··· 1 1 import { and, eq, or } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { workspaceTable, workspaceUserTable } from "../../database/schema"; 4 5 ··· 26 27 ), 27 28 ) 28 29 .limit(1); 30 + 31 + const isWorkspaceExisting = Boolean(existingWorkspace); 32 + 33 + if (!isWorkspaceExisting) { 34 + throw new HTTPException(404, { 35 + message: "Workspace not found", 36 + }); 37 + } 29 38 30 39 return existingWorkspace; 31 40 }
+9 -20
apps/api/src/workspace/controllers/get-workspaces.ts
··· 1 1 import { eq, or } from "drizzle-orm"; 2 2 import db from "../../database"; 3 - import { 4 - projectTable, 5 - workspaceTable, 6 - workspaceUserTable, 7 - } from "../../database/schema"; 3 + import { workspaceTable, workspaceUserTable } from "../../database/schema"; 8 4 9 5 async function getWorkspaces(userEmail: string) { 10 6 const workspaces = await db ··· 12 8 id: workspaceTable.id, 13 9 name: workspaceTable.name, 14 10 ownerEmail: workspaceTable.ownerEmail, 11 + createdAt: workspaceTable.createdAt, 15 12 description: workspaceTable.description, 16 13 }) 17 14 .from(workspaceTable) ··· 25 22 eq(workspaceUserTable.userEmail, userEmail), 26 23 ), 27 24 ) 28 - .groupBy(workspaceTable.id, workspaceTable.name, workspaceTable.ownerEmail); 25 + .groupBy( 26 + workspaceTable.id, 27 + workspaceTable.name, 28 + workspaceTable.ownerEmail, 29 + workspaceTable.description, 30 + ); 29 31 30 - const workspacesWithProjects = await Promise.all( 31 - workspaces.map(async (workspace) => ({ 32 - ...workspace, 33 - projects: await db 34 - .select({ 35 - id: projectTable.id, 36 - name: projectTable.name, 37 - }) 38 - .from(projectTable) 39 - .where(eq(projectTable.workspaceId, workspace.id)), 40 - })), 41 - ); 42 - 43 - return workspacesWithProjects; 32 + return workspaces; 44 33 } 45 34 46 35 export default getWorkspaces;
+6 -3
apps/api/src/workspace/controllers/update-workspace.ts
··· 1 1 import { and, eq } from "drizzle-orm"; 2 + import { HTTPException } from "hono/http-exception"; 2 3 import db from "../../database"; 3 4 import { workspaceTable } from "../../database/schema"; 4 5 ··· 25 26 const isWorkspaceExisting = Boolean(existingWorkspace); 26 27 27 28 if (!isWorkspaceExisting) { 28 - throw new Error("Workspace doesn't exist"); 29 + throw new HTTPException(404, { 30 + message: "Workspace not found", 31 + }); 29 32 } 30 33 31 - const updatedWorkspace = await db 34 + const [updatedWorkspace] = await db 32 35 .update(workspaceTable) 33 36 .set({ 34 37 name, ··· 43 46 createdAt: workspaceTable.createdAt, 44 47 }); 45 48 46 - return updatedWorkspace.at(0); 49 + return updatedWorkspace; 47 50 } 48 51 49 52 export default updateWorkspace;
+53 -47
apps/api/src/workspace/index.ts
··· 1 - import Elysia, { t } from "elysia"; 2 - import { requireWorkspacePermission } from "../middleware/check-permissions"; 1 + import { zValidator } from "@hono/zod-validator"; 2 + import { Hono } from "hono"; 3 + import { z } from "zod"; 3 4 import createWorkspace from "./controllers/create-workspace"; 4 5 import deleteWorkspace from "./controllers/delete-workspace"; 5 6 import getWorkspace from "./controllers/get-workspace"; 6 7 import getWorkspaces from "./controllers/get-workspaces"; 7 8 import updateWorkspace from "./controllers/update-workspace"; 8 9 9 - const workspace = new Elysia({ prefix: "/workspace" }) 10 - .state("userEmail", "") 11 - .post( 12 - "/create", 13 - async ({ body: { name }, store }) => { 14 - const userEmail = store.userEmail; 15 - const createdWorkspace = await createWorkspace(name, userEmail); 16 - return createdWorkspace; 17 - }, 18 - { 19 - body: t.Object({ 20 - name: t.String(), 21 - }), 22 - }, 23 - ) 24 - .get("/list", async ({ store }) => { 25 - const userEmail = store.userEmail; 10 + const workspace = new Hono<{ 11 + Variables: { 12 + userEmail: string; 13 + }; 14 + }>() 15 + .get("/", async (c) => { 16 + const userEmail = c.get("userEmail"); 17 + 26 18 const workspaces = await getWorkspaces(userEmail); 27 - return workspaces; 19 + 20 + return c.json(workspaces); 28 21 }) 29 - .get("/:id", async ({ store, params }) => { 30 - const userEmail = store.userEmail; 31 - const workspace = await getWorkspace(userEmail, params.id); 32 - return workspace; 22 + .get("/:id", zValidator("param", z.object({ id: z.string() })), async (c) => { 23 + const id = c.req.param("id"); 24 + 25 + const userEmail = c.get("userEmail"); 26 + 27 + const workspace = await getWorkspace(userEmail, id); 28 + 29 + return c.json(workspace); 33 30 }) 34 - .use(requireWorkspacePermission("owner")) 31 + .post("/", zValidator("json", z.object({ name: z.string() })), async (c) => { 32 + const { name } = c.req.valid("json"); 33 + 34 + const userEmail = c.get("userEmail"); 35 + 36 + const workspace = await createWorkspace(name, userEmail); 37 + 38 + return c.json(workspace); 39 + }) 35 40 .put( 36 41 "/:id", 37 - async ({ store, params, body }) => { 38 - const userEmail = store.userEmail; 39 - const updatedWorkspace = await updateWorkspace( 40 - userEmail, 41 - params.id, 42 - body.name, 43 - body.description, 44 - ); 45 - return updatedWorkspace; 46 - }, 47 - { 48 - body: t.Object({ 49 - name: t.String(), 50 - description: t.String(), 51 - }), 42 + zValidator("json", z.object({ name: z.string(), description: z.string() })), 43 + async (c) => { 44 + const id = c.req.param("id"); 45 + const { name, description } = c.req.valid("json"); 46 + 47 + const userEmail = c.get("userEmail"); 48 + 49 + const workspace = await updateWorkspace(userEmail, id, name, description); 50 + 51 + return c.json(workspace); 52 52 }, 53 53 ) 54 - .use(requireWorkspacePermission("owner")) 55 - .delete("/:id", async ({ store, params }) => { 56 - const userEmail = store.userEmail; 57 - const deletedWorkspace = await deleteWorkspace(userEmail, params.id); 58 - return deletedWorkspace; 59 - }) 60 - .use(requireWorkspacePermission("owner")); 54 + .delete( 55 + "/:id", 56 + zValidator("param", z.object({ id: z.string() })), 57 + async (c) => { 58 + const id = c.req.param("id"); 59 + 60 + const userEmail = c.get("userEmail"); 61 + 62 + const workspace = await deleteWorkspace(userEmail, id); 63 + 64 + return c.json(workspace); 65 + }, 66 + ); 61 67 62 68 export default workspace;
+24 -103
apps/api/tsconfig.json
··· 1 1 { 2 - "compilerOptions": { 3 - /* Visit https://aka.ms/tsconfig to read more about this file */ 4 - 5 - /* Projects */ 6 - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 - 13 - /* Language and Environment */ 14 - "target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 15 - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 - // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 - 27 - /* Modules */ 28 - "module": "ES2022" /* Specify what module code is generated. */, 29 - // "rootDir": "./", /* Specify the root folder within your source files. */ 30 - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, 31 - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 - "types": [ 36 - "bun-types" 37 - ] /* Specify type package names to be included without being referenced in a source file. */, 38 - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 39 - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 40 - // "resolveJsonModule": true, /* Enable importing .json files. */ 41 - // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */ 2 + "extends": "../../packages/typescript-config/base.json", 42 3 43 - /* JavaScript Support */ 44 - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 45 - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 46 - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 47 - 48 - /* Emit */ 49 - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 50 - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 51 - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 52 - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 53 - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 54 - // "outDir": "./", /* Specify an output folder for all emitted files. */ 55 - // "removeComments": true, /* Disable emitting comments. */ 56 - // "noEmit": true, /* Disable emitting files from a compilation. */ 57 - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 58 - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 59 - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 60 - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 61 - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 62 - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 63 - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 64 - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 65 - // "newLine": "crlf", /* Set the newline character for emitting files. */ 66 - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 67 - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 68 - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 69 - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 70 - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 71 - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 72 - 73 - /* Interop Constraints */ 74 - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 75 - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 76 - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 77 - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 78 - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 79 - 80 - /* Type Checking */ 81 - "strict": true /* Enable all strict type-checking options. */, 82 - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 83 - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 84 - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 85 - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 86 - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 87 - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 88 - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 89 - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 90 - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 91 - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 92 - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 93 - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 94 - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 95 - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 96 - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 97 - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 98 - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 99 - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 100 - 101 - /* Completeness */ 102 - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 103 - "skipLibCheck": true /* Skip type checking all .d.ts files. */ 104 - } 105 - } 4 + "compilerOptions": { 5 + "outDir": "dist", 6 + "rootDir": "src", 7 + "module": "CommonJS", 8 + "moduleResolution": "Node", 9 + "target": "ES2022", 10 + "lib": [ 11 + "ES2022", 12 + "DOM" 13 + ], 14 + "sourceMap": true, 15 + "declaration": true, 16 + "skipLibCheck": true, 17 + "isolatedModules": true 18 + }, 19 + "include": [ 20 + "src/**/*" 21 + ], 22 + "exclude": [ 23 + "node_modules", 24 + "dist" 25 + ] 26 + }
+17 -15
apps/web/Dockerfile
··· 1 - FROM --platform=$BUILDPLATFORM oven/bun:1.2.5 AS builder 1 + # Build stage 2 + FROM --platform=$BUILDPLATFORM node:20-alpine AS builder 2 3 3 - # Install build dependencies 4 - RUN apt-get update && apt-get install -y \ 5 - python3 \ 6 - make \ 7 - g++ \ 8 - && rm -rf /var/lib/apt/lists/* 4 + # Install build dependencies in a single layer 5 + RUN apk add --no-cache python3 make g++ && \ 6 + corepack enable && \ 7 + corepack prepare pnpm@10.7.0 --activate 9 8 10 9 WORKDIR /app 11 10 12 11 # Copy package files first for better layer caching 13 - COPY package.json bun.lockb ./ 12 + COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./ 14 13 COPY apps/web/package.json ./apps/web/ 15 14 COPY packages/typescript-config/package.json ./packages/typescript-config/ 16 15 COPY packages/libs/package.json ./packages/libs/ 17 16 COPY apps/api/package.json ./apps/api/ 18 17 19 18 # Install dependencies 20 - RUN bun install --no-frozen-lockfile 19 + RUN pnpm install --frozen-lockfile 21 20 22 21 # Copy only necessary source code 23 22 COPY packages/typescript-config ./packages/typescript-config ··· 27 26 28 27 # Build the application 29 28 WORKDIR /app/apps/web 30 - RUN bun run build 29 + RUN pnpm run build 31 30 32 - # Production stage with pinned version 33 - FROM nginx:alpine 31 + # Production stage with specific version 32 + FROM nginx:1.25-alpine AS runtime 34 33 35 - # Create non-root user for nginx 34 + # Create non-root user and configure nginx in a single layer 36 35 RUN addgroup -g 1001 appuser && \ 37 36 adduser -u 1001 -G appuser -D appuser && \ 38 37 # Set permissions for nginx directories ··· 63 62 64 63 # Switch to non-root user 65 64 USER appuser 65 + EXPOSE 5173 66 66 67 - EXPOSE 80 67 + # Add health check 68 + HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ 69 + CMD wget --no-verbose --tries=1 --spider http://localhost:5173/ || exit 1 68 70 69 71 # Use exec form of CMD for proper signal handling 70 - CMD ["nginx", "-g", "daemon off;"] 72 + CMD ["nginx", "-g", "daemon off;"]
+1 -1
apps/web/nginx.conf
··· 1 1 server { 2 - listen 80; 2 + listen 5173; 3 3 server_name localhost; 4 4 5 5 # Security headers
+2 -1
apps/web/package.json
··· 5 5 "type": "module", 6 6 "scripts": { 7 7 "dev": "vite", 8 - "build": "tsc -b && vite build", 8 + "build": "vite build", 9 9 "preview": "vite preview" 10 10 }, 11 11 "dependencies": { ··· 43 43 "cmdk": "^1.1.1", 44 44 "date-fns": "^4.1.0", 45 45 "framer-motion": "^12.0.1", 46 + "hono": "^4.7.5", 46 47 "immer": "^10.1.1", 47 48 "lucide-react": "^0.488.0", 48 49 "react": "^19.0.0",
+1 -1
apps/web/src/components/auth/sign-in-form.tsx
··· 43 43 44 44 const onSubmit = async (data: SignInFormValues) => { 45 45 try { 46 - const { data: user } = await mutateAsync({ 46 + const user = await mutateAsync({ 47 47 email: data.email, 48 48 password: data.password, 49 49 });
+1 -1
apps/web/src/components/auth/sign-up-form.tsx
··· 46 46 47 47 const onSubmit = async (data: SignUpFormValues) => { 48 48 try { 49 - const { data: user } = await mutateAsync({ 49 + const user = await mutateAsync({ 50 50 email: data.email, 51 51 name: data.name, 52 52 password: data.password,
+27 -16
apps/web/src/components/backlog-list-view/backlog-task-row.tsx
··· 2 2 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 3 3 import { cn } from "@/lib/cn"; 4 4 import useProjectStore from "@/store/project"; 5 - import type { Task } from "@/types/project"; 5 + import type { ProjectWithTasks } from "@/types/project"; 6 + import type Task from "@/types/task"; 6 7 import { useSortable } from "@dnd-kit/sortable"; 7 8 import { CSS } from "@dnd-kit/utilities"; 8 9 import * as Popover from "@radix-ui/react-popover"; ··· 58 59 status: columnId, 59 60 }); 60 61 61 - const updatedProject = produce(project, (draft) => { 62 + const updatedProject = produce(project, (draft: ProjectWithTasks) => { 62 63 if (draft.archivedTasks) { 63 - const index = draft.archivedTasks.findIndex((t) => t.id === task.id); 64 + const index = draft.archivedTasks.findIndex( 65 + (t: Task) => t.id === task.id, 66 + ); 64 67 if (index !== -1) { 65 68 draft.archivedTasks.splice(index, 1); 66 69 } 67 70 } 68 71 69 72 if (draft.plannedTasks) { 70 - const index = draft.plannedTasks.findIndex((t) => t.id === task.id); 73 + const index = draft.plannedTasks.findIndex( 74 + (t: Task) => t.id === task.id, 75 + ); 71 76 if (index !== -1) { 72 77 draft.plannedTasks.splice(index, 1); 73 78 } 74 79 } 75 80 76 - const targetColumn = draft.columns?.find((col) => col.id === columnId); 81 + const targetColumn = draft.columns?.find( 82 + (col: ProjectWithTasks["columns"][number]) => col.id === columnId, 83 + ); 77 84 if (targetColumn) { 78 85 targetColumn.tasks.push({ 79 86 ...task, 80 87 status: columnId, 88 + assigneeName: task.userEmail, 89 + assigneeEmail: task.userEmail, 81 90 }); 82 91 } 83 92 }); ··· 186 195 </div> 187 196 </div> 188 197 <div className="p-1 max-h-60 overflow-y-auto"> 189 - {project?.columns?.map((column) => ( 190 - <button 191 - key={column.id} 192 - type="button" 193 - className="w-full text-left px-2 py-1.5 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-md flex items-center gap-2 transition-colors" 194 - onClick={() => handleMoveToColumn(column.id)} 195 - > 196 - <MoveRight className="w-3.5 h-3.5 text-zinc-500 dark:text-zinc-400" /> 197 - <span>{column.name}</span> 198 - </button> 199 - ))} 198 + {project?.columns?.map( 199 + (column: ProjectWithTasks["columns"][number]) => ( 200 + <button 201 + key={column.id} 202 + type="button" 203 + className="w-full text-left px-2 py-1.5 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-md flex items-center gap-2 transition-colors" 204 + onClick={() => handleMoveToColumn(column.id)} 205 + > 206 + <MoveRight className="w-3.5 h-3.5 text-zinc-500 dark:text-zinc-400" /> 207 + <span>{column.name}</span> 208 + </button> 209 + ), 210 + )} 200 211 </div> 201 212 </Popover.Content> 202 213 </Popover.Root>
+25 -11
apps/web/src/components/backlog-list-view/index.tsx
··· 2 2 import { cn } from "@/lib/cn"; 3 3 import toKebabCase from "@/lib/to-kebab-case"; 4 4 import useProjectStore from "@/store/project"; 5 - import type { Column, Project, Task } from "@/types/project"; 5 + import type { ProjectWithTasks } from "@/types/project"; 6 + import type Task from "@/types/task"; 6 7 import { 7 8 DndContext, 8 9 type DragEndEvent, ··· 29 30 import BacklogTaskRow from "./backlog-task-row"; 30 31 31 32 interface BacklogListViewProps { 32 - project?: Project; 33 + project?: ProjectWithTasks; 33 34 } 34 35 35 36 function BacklogListView({ project }: BacklogListViewProps) { ··· 86 87 status: targetColumnId, 87 88 }); 88 89 89 - const updatedProject = produce(project, (draft) => { 90 + const updatedProject = produce(project, (draft: ProjectWithTasks) => { 90 91 if (task.status === "planned" && targetColumnId === "archived") { 91 92 if (draft.plannedTasks) { 92 - const index = draft.plannedTasks.findIndex((t) => t.id === task.id); 93 + const index = draft.plannedTasks.findIndex( 94 + (t: Task) => t.id === task.id, 95 + ); 93 96 if (index !== -1) { 94 97 const [removedTask] = draft.plannedTasks.splice(index, 1); 95 98 if (draft.archivedTasks) { ··· 103 106 } else if (task.status === "archived" && targetColumnId === "planned") { 104 107 if (draft.archivedTasks) { 105 108 const index = draft.archivedTasks.findIndex( 106 - (t) => t.id === task.id, 109 + (t: Task) => t.id === task.id, 107 110 ); 108 111 if (index !== -1) { 109 112 const [removedTask] = draft.archivedTasks.splice(index, 1); ··· 123 126 targetColumnId === "done") 124 127 ) { 125 128 if (task.status === "planned" && draft.plannedTasks) { 126 - const index = draft.plannedTasks.findIndex((t) => t.id === task.id); 129 + const index = draft.plannedTasks.findIndex( 130 + (t: Task) => t.id === task.id, 131 + ); 127 132 if (index !== -1) { 128 133 draft.plannedTasks.splice(index, 1); 129 134 } 130 135 } else if (task.status === "archived" && draft.archivedTasks) { 131 136 const index = draft.archivedTasks.findIndex( 132 - (t) => t.id === task.id, 137 + (t: Task) => t.id === task.id, 133 138 ); 134 139 if (index !== -1) { 135 140 draft.archivedTasks.splice(index, 1); ··· 137 142 } 138 143 139 144 const targetColumn = draft.columns?.find( 140 - (col) => col.id === targetColumnId, 145 + (col: ProjectWithTasks["columns"][number]) => 146 + col.id === targetColumnId, 141 147 ); 142 148 if (targetColumn) { 143 149 targetColumn.tasks.push({ 144 150 ...task, 145 151 status: targetColumnId, 152 + assigneeName: task.userEmail, 153 + assigneeEmail: task.userEmail, 146 154 }); 147 155 } 148 156 } ··· 162 170 })); 163 171 }; 164 172 165 - function ColumnSection({ column }: { column: Column }) { 173 + function ColumnSection({ 174 + column, 175 + }: { 176 + column: ProjectWithTasks["columns"][number]; 177 + }) { 166 178 const { setNodeRef } = useDroppable({ 167 179 id: column.id, 168 180 data: { ··· 209 221 className="space-y-1 p-2" 210 222 > 211 223 {column.tasks.length > 0 ? ( 212 - column.tasks.map((task) => ( 224 + column.tasks.map((task: Task) => ( 213 225 <BacklogTaskRow key={task.id} task={task} /> 214 226 )) 215 227 ) : ( 216 228 <div className="p-4 text-center text-sm text-zinc-500 dark:text-zinc-400"> 229 + {/* @ts-expect-error */} 217 230 No {column.id === "planned" ? "planned" : "archived"} tasks 218 231 </div> 219 232 )} 220 233 </motion.div> 221 234 </SortableContext> 222 235 236 + {/* @ts-expect-error */} 223 237 {column.id === "planned" && ( 224 238 <button 225 239 type="button" ··· 250 264 onDragEnd={handleDragEnd} 251 265 > 252 266 <div className="w-full h-full p-4 space-y-4"> 253 - {project.columns.map((column) => ( 267 + {project.columns.map((column: ProjectWithTasks["columns"][number]) => ( 254 268 <ColumnSection key={column.id} column={column} /> 255 269 ))} 256 270 </div>
+1 -1
apps/web/src/components/command-palette/index.tsx
··· 41 41 ); 42 42 43 43 useEffect(() => { 44 - let timeout: Timer; 44 + let timeout: ReturnType<typeof setTimeout>; 45 45 if (!open && pendingAction) { 46 46 setOpen(false); 47 47 timeout = setTimeout(() => {
+13 -1
apps/web/src/components/common/logo.tsx
··· 1 + import useProjectStore from "@/store/project"; 2 + import useWorkspaceStore from "@/store/workspace"; 1 3 import { Link } from "@tanstack/react-router"; 2 4 import { LayoutGrid } from "lucide-react"; 3 5 ··· 6 8 } 7 9 8 10 export function Logo({ className = "" }: LogoProps) { 11 + const { setWorkspace } = useWorkspaceStore(); 12 + const { setProject } = useProjectStore(); 13 + 9 14 return ( 10 - <Link to="/dashboard" className={`flex items-center gap-2 ${className}`}> 15 + <Link 16 + onClick={() => { 17 + setWorkspace(null); 18 + setProject(null); 19 + }} 20 + to="/dashboard" 21 + className={`flex items-center gap-2 ${className}`} 22 + > 11 23 <div className="p-1.5"> 12 24 <LayoutGrid className="w-5 h-5 text-indigo-600 dark:text-indigo-400" /> 13 25 </div>
+9 -3
apps/web/src/components/common/sidebar/sections/projects/index.tsx
··· 4 4 import { cn } from "@/lib/cn"; 5 5 import useProjectStore from "@/store/project"; 6 6 import { useUserPreferencesStore } from "@/store/user-preferences"; 7 - import type { Project } from "@/types/project"; 7 + import type { ProjectWithTasks } from "@/types/project"; 8 8 import { useLocation, useNavigate } from "@tanstack/react-router"; 9 9 import { 10 10 Layout, ··· 28 28 const navigate = useNavigate(); 29 29 const location = useLocation(); 30 30 31 - const handleSelectProject = (selectedProject: Project) => { 31 + const handleSelectProject = (selectedProject: ProjectWithTasks) => { 32 32 if ( 33 33 currentProject?.id === selectedProject.id && 34 34 location.pathname.includes("/board") ··· 90 90 </div> 91 91 <div className="space-y-0.5"> 92 92 {projects && projects.length > 0 93 - ? projects.map((project) => ( 93 + ? projects.map((project: ProjectWithTasks) => ( 94 94 <div key={project.id} className="space-y-0.5"> 95 95 {!isSidebarOpened ? ( 96 96 <Tip content={project.name}> ··· 104 104 description: project.description, 105 105 workspaceId: project.workspaceId, 106 106 icon: project.icon ?? "Layout", 107 + columns: project.columns, 108 + archivedTasks: project.archivedTasks, 109 + plannedTasks: project.plannedTasks, 107 110 }) 108 111 } 109 112 className={cn( ··· 134 137 description: project.description, 135 138 workspaceId: project.workspaceId, 136 139 icon: project.icon ?? "Layout", 140 + columns: project.columns, 141 + archivedTasks: project.archivedTasks, 142 + plannedTasks: project.plannedTasks, 137 143 }) 138 144 } 139 145 className={cn(
+3 -3
apps/web/src/components/common/sidebar/sections/user-info.tsx
··· 47 47 type="button" 48 48 className={cn( 49 49 "flex items-center w-full", 50 - isSidebarOpened ? "gap-3 justify-center" : "justify-center", 50 + isSidebarOpened ? "gap-3 justify-start" : "justify-center", 51 51 "rounded-lg p-2 transition-all", 52 52 "border border-transparent", 53 53 "hover:bg-white dark:hover:bg-zinc-800/50", ··· 58 58 <Avatar className="text-zinc-900 dark:text-zinc-100"> 59 59 <AvatarFallback>{user?.name?.charAt(0)}</AvatarFallback> 60 60 </Avatar> 61 - <div className={cn("flex-1 min-w-0", !isSidebarOpened && "hidden")}> 62 - <p className="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate"> 61 + <div className={cn(!isSidebarOpened && "hidden")}> 62 + <p className="text-sm text-left font-medium text-zinc-900 dark:text-zinc-100 truncate"> 63 63 {user?.name} 64 64 </p> 65 65 <p className="text-xs text-zinc-500 dark:text-zinc-400 truncate">
+27 -16
apps/web/src/components/common/sidebar/sections/workspace-settings/index.tsx
··· 14 14 if (!workspace) return null; 15 15 16 16 return ( 17 - <Link 18 - to={"/dashboard/workspace-settings/$workspaceId"} 19 - params={{ workspaceId: workspace.id }} 20 - className={cn( 21 - "flex items-center gap-2 text-sm px-3 py-1.5 rounded-md", 22 - isOnWorkspaceRoute 23 - ? "bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100" 24 - : "text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 hover:text-zinc-900 dark:hover:text-zinc-100", 25 - )} 26 - > 27 - <Settings 17 + <div> 18 + <h2 19 + className={cn( 20 + "text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2", 21 + isSidebarOpened && "px-3", 22 + )} 23 + > 24 + {isSidebarOpened && "Workspace"} 25 + </h2> 26 + <Link 27 + to={"/dashboard/workspace-settings/$workspaceId"} 28 + params={{ workspaceId: workspace.id }} 28 29 className={cn( 29 - "shrink-0", 30 - !isSidebarOpened ? "w-6 h-6" : "w-4 h-4 mr-2", 30 + "flex items-center gap-2 text-sm justify-center py-1.5 rounded-md", 31 + isOnWorkspaceRoute 32 + ? "bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100" 33 + : "text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 hover:text-zinc-900 dark:hover:text-zinc-100", 34 + isSidebarOpened && "justify-start px-3", 31 35 )} 32 - /> 33 - {isSidebarOpened && "Workspace Settings"} 34 - </Link> 36 + > 37 + <Settings 38 + className={cn( 39 + "shrink-0", 40 + !isSidebarOpened ? "w-6 h-6" : "w-4 h-4 mr-2", 41 + )} 42 + /> 43 + {isSidebarOpened && "Settings"} 44 + </Link> 45 + </div> 35 46 ); 36 47 } 37 48
+10 -10
apps/web/src/components/filters/index.tsx
··· 1 1 import { Input } from "@/components/ui/input"; 2 2 import { priorityColorsFilter } from "@/constants/priority-colors"; 3 - import useActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 3 + import useGetActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 4 4 import { cn } from "@/lib/cn"; 5 5 import useProjectStore from "@/store/project"; 6 6 import { useUserPreferencesStore } from "@/store/user-preferences"; ··· 36 36 const [selectedDueDate, setSelectedDueDate] = useState<string | null>(null); 37 37 const { viewMode, setViewMode } = useUserPreferencesStore(); 38 38 39 - const { data: users } = useActiveWorkspaceUsers(project?.workspaceId ?? ""); 39 + const { data: users } = useGetActiveWorkspaceUsers({ 40 + workspaceId: project?.workspaceId ?? "", 41 + }); 40 42 41 43 const handleSearch = (value: string) => { 42 44 setSearchValue(value); ··· 174 176 {users?.map((user) => ( 175 177 <button 176 178 type="button" 177 - key={user?.user?.email} 178 - onClick={() => 179 - handleAssigneeChange(user?.user?.email ?? null) 180 - } 179 + key={user.userEmail} 180 + onClick={() => handleAssigneeChange(user.userEmail ?? null)} 181 181 className={cn( 182 182 "w-full flex items-center gap-2 px-2 py-1.5 text-xs text-left transition-colors", 183 - selectedAssignee === user?.user?.email 183 + selectedAssignee === user.userEmail 184 184 ? "bg-indigo-50 text-indigo-600 dark:bg-indigo-500/10 dark:text-indigo-400" 185 185 : "text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800", 186 186 )} 187 187 > 188 188 <UserIcon className="w-3.5 h-3.5" /> 189 - <span>{user?.user?.name}</span> 189 + <span>{user.userName}</span> 190 190 </button> 191 191 ))} 192 192 ··· 290 290 > 291 291 <UserIcon className="w-3 h-3" /> 292 292 <span> 293 - {users?.find((u) => u.user?.email === selectedAssignee)?.user 294 - ?.name || "Unassigned"} 293 + {users?.find((u) => u.userEmail === selectedAssignee) 294 + ?.userName || "Unassigned"} 295 295 </span> 296 296 <X className="w-3 h-3 ml-1 text-zinc-400" /> 297 297 </button>
+2 -2
apps/web/src/components/kanban-board/column/column-dropzone.tsx
··· 1 - import type { Column } from "@/types/project"; 1 + import type { ProjectWithTasks } from "@/types/project"; 2 2 import { useDroppable } from "@dnd-kit/core"; 3 3 import { 4 4 SortableContext, ··· 7 7 import TaskCard from "../task-card"; 8 8 9 9 interface ColumnDropzoneProps { 10 - column: Column; 10 + column: ProjectWithTasks["columns"][number]; 11 11 } 12 12 13 13 export function ColumnDropzone({ column }: ColumnDropzoneProps) {
+2 -2
apps/web/src/components/kanban-board/column/column-footer.tsx
··· 1 1 import CreateTaskModal from "@/components/shared/modals/create-task-modal"; 2 2 import toKebabCase from "@/lib/to-kebab-case"; 3 - import type { Column } from "@/types/project"; 3 + import type { ProjectWithTasks } from "@/types/project"; 4 4 import { Plus } from "lucide-react"; 5 5 import { useState } from "react"; 6 6 7 7 interface ColumnFooterProps { 8 - column: Column; 8 + column: ProjectWithTasks["columns"][number]; 9 9 } 10 10 11 11 export function ColumnFooter({ column }: ColumnFooterProps) {
+2 -2
apps/web/src/components/kanban-board/column/column-header.tsx
··· 1 1 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 2 2 import useProjectStore from "@/store/project"; 3 - import type { Column } from "@/types/project"; 3 + import type { ProjectWithTasks } from "@/types/project"; 4 4 import { produce } from "immer"; 5 5 import { Archive } from "lucide-react"; 6 6 import { toast } from "sonner"; 7 7 8 8 interface ColumnHeaderProps { 9 - column: Column; 9 + column: ProjectWithTasks["columns"][number]; 10 10 } 11 11 12 12 export function ColumnHeader({ column }: ColumnHeaderProps) {
+2 -2
apps/web/src/components/kanban-board/column/index.tsx
··· 1 1 import CreateTaskModal from "@/components/shared/modals/create-task-modal"; 2 2 import toKebabCase from "@/lib/to-kebab-case"; 3 - import type { Column as ColumnType } from "@/types/project"; 3 + import type { ProjectWithTasks } from "@/types/project"; 4 4 import { Plus } from "lucide-react"; 5 5 import { useState } from "react"; 6 6 import { ColumnDropzone } from "./column-dropzone"; 7 7 import { ColumnHeader } from "./column-header"; 8 8 9 9 interface ColumnProps { 10 - column: ColumnType; 10 + column: ProjectWithTasks["columns"][number]; 11 11 } 12 12 13 13 function Column({ column }: ColumnProps) {
+4 -4
apps/web/src/components/kanban-board/index.tsx
··· 1 1 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 2 2 import useProjectStore from "@/store/project"; 3 - import type { Project } from "@/types/project"; 3 + import type { ProjectWithTasks } from "@/types/project"; 4 4 import { 5 5 DndContext, 6 6 type DragEndEvent, ··· 19 19 import Column from "./column"; 20 20 import TaskCard from "./task-card"; 21 21 22 - interface KanbanBoardProps { 23 - project: Project | undefined; 24 - } 22 + type KanbanBoardProps = { 23 + project: ProjectWithTasks; 24 + }; 25 25 26 26 function KanbanBoard({ project }: KanbanBoardProps) { 27 27 const { setProject } = useProjectStore();
+1 -1
apps/web/src/components/kanban-board/task-card.tsx
··· 1 1 import { priorityColorsTaskCard } from "@/constants/priority-colors"; 2 2 import useProjectStore from "@/store/project"; 3 3 import useWorkspaceStore from "@/store/workspace"; 4 - import type { Task } from "@/types/project"; 4 + import type Task from "@/types/task"; 5 5 import { useSortable } from "@dnd-kit/sortable"; 6 6 import { CSS } from "@dnd-kit/utilities"; 7 7 import { useNavigate } from "@tanstack/react-router";
+8 -5
apps/web/src/components/list-view/index.tsx
··· 2 2 import { cn } from "@/lib/cn"; 3 3 import toKebabCase from "@/lib/to-kebab-case"; 4 4 import useProjectStore from "@/store/project"; 5 - import type { Column, Project, Task } from "@/types/project"; 5 + import type { ProjectWithTasks } from "@/types/project"; 6 + import type Task from "@/types/task"; 6 7 import { 7 8 DndContext, 8 9 type DragEndEvent, ··· 28 29 import TaskRow from "./task-row"; 29 30 import TaskRowOverlay from "./task-row-overlay"; 30 31 31 - interface ListViewProps { 32 - project: Project | undefined; 33 - } 32 + type ListViewProps = { 33 + project: ProjectWithTasks; 34 + }; 34 35 35 36 function ListView({ project }: ListViewProps) { 36 37 const { setProject } = useProjectStore(); ··· 117 118 })); 118 119 }; 119 120 120 - function ColumnSection({ column }: { column: Column }) { 121 + function ColumnSection({ 122 + column, 123 + }: { column: ProjectWithTasks["columns"][number] }) { 121 124 const { setNodeRef } = useDroppable({ 122 125 id: column.id, 123 126 data: {
+1 -1
apps/web/src/components/list-view/task-row-overlay.tsx
··· 1 1 import { Avatar, AvatarFallback } from "@/components/ui/avatar"; 2 2 import { priorityColorsTaskCard } from "@/constants/priority-colors"; 3 3 import { cn } from "@/lib/cn"; 4 - import type { Task } from "@/types/project"; 4 + import type Task from "@/types/task"; 5 5 import { format } from "date-fns"; 6 6 import { Flag } from "lucide-react"; 7 7
+1 -1
apps/web/src/components/list-view/task-row.tsx
··· 2 2 import { priorityColorsTaskCard } from "@/constants/priority-colors"; 3 3 import { cn } from "@/lib/cn"; 4 4 import useProjectStore from "@/store/project"; 5 - import type { Task } from "@/types/project"; 5 + import type Task from "@/types/task"; 6 6 import { useSortable } from "@dnd-kit/sortable"; 7 7 import { CSS } from "@dnd-kit/utilities"; 8 8 import { useNavigate } from "@tanstack/react-router";
+3 -3
apps/web/src/components/providers/auth-provider/index.tsx
··· 24 24 const { data, isFetching } = useGetMe(); 25 25 26 26 useEffect(() => { 27 - if (data?.data?.user === null) { 27 + if (data?.user === null) { 28 28 setUser(null); 29 - } else if (data?.data?.user) { 30 - setUser({ ...data?.data?.user }); 29 + } else if (data?.user) { 30 + setUser({ ...data?.user }); 31 31 } 32 32 }, [data]); 33 33
+2 -2
apps/web/src/components/shared/modals/create-project-modal.tsx
··· 37 37 if (!name.trim()) return; 38 38 39 39 try { 40 - const { data } = await mutateAsync(); 40 + const { id } = await mutateAsync(); 41 41 toast.success("Project created successfully"); 42 42 await queryClient.invalidateQueries({ queryKey: ["projects"] }); 43 43 ··· 45 45 to: "/dashboard/workspace/$workspaceId/project/$projectId/board", 46 46 params: { 47 47 workspaceId: workspace?.id ?? "", 48 - projectId: data?.id ?? "", 48 + projectId: id, 49 49 }, 50 50 }); 51 51
+9 -7
apps/web/src/components/shared/modals/create-task-modal.tsx
··· 11 11 import { Input } from "@/components/ui/input"; 12 12 import useCreateTask from "@/hooks/mutations/task/use-create-task"; 13 13 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 14 - import useActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 14 + import useGetActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 15 15 import useProjectStore from "@/store/project"; 16 16 import useWorkspaceStore from "@/store/workspace"; 17 17 import { zodResolver } from "@hookform/resolvers/zod"; ··· 42 42 const { project, setProject } = useProjectStore(); 43 43 const { workspace } = useWorkspaceStore(); 44 44 const { mutate: updateTask } = useUpdateTask(); 45 - const { data: users } = useActiveWorkspaceUsers(workspace?.id ?? ""); 45 + const { data: users } = useGetActiveWorkspaceUsers({ 46 + workspaceId: workspace?.id ?? "", 47 + }); 46 48 47 49 const form = useForm<TaskFormValues>({ 48 50 resolver: zodResolver(taskSchema), ··· 72 74 userEmail: data.email, 73 75 priority: data.priority, 74 76 projectId: project?.id, 75 - dueDate: new Date(), 77 + dueDate: new Date().toISOString(), 76 78 status: taskStatus, 77 - position: 0, 78 79 }); 79 80 80 81 const updatedProject = produce(project, (draft) => { ··· 85 86 if (targetColumn) { 86 87 targetColumn.tasks.push({ 87 88 ...newTask, 88 - userEmail: data.email, 89 + assigneeEmail: data.email, 90 + assigneeName: data.email, 89 91 position: 0, 90 92 }); 91 93 } ··· 189 191 ), 190 192 }, 191 193 ...(users ?? []).map((user) => ({ 192 - value: user.user?.email ?? "", 193 - label: user.user?.name ?? "", 194 + value: user.userEmail ?? "", 195 + label: user.userName ?? "", 194 196 })), 195 197 ]} 196 198 placeholder="Select assignee"
+1 -1
apps/web/src/components/task/task-description.tsx
··· 35 35 userEmail: task.userEmail || "", 36 36 title: task.title || "", 37 37 status: task.status || "", 38 - dueDate: task.dueDate || new Date(), 38 + dueDate: task.dueDate ? new Date(task.dueDate).toISOString() : null, 39 39 priority: task.priority || "", 40 40 position: task.position || 0, 41 41 });
+9 -9
apps/web/src/components/task/task-info.tsx
··· 1 1 import { Form, FormField, FormItem, FormLabel } from "@/components/ui/form"; 2 2 import { Select } from "@/components/ui/select"; 3 3 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 4 - import useActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 4 + import useGetActiveWorkspaceUsers from "@/hooks/queries/workspace-users/use-active-workspace-users"; 5 5 import useProjectStore from "@/store/project"; 6 - import type { Task } from "@/types/project"; 6 + import type Task from "@/types/task"; 7 7 import { Flag } from "lucide-react"; 8 8 import { useEffect } from "react"; 9 9 import { useForm } from "react-hook-form"; ··· 26 26 setIsSaving: (isSaving: boolean) => void; 27 27 }) { 28 28 const { project } = useProjectStore(); 29 - const { data: workspaceUsers } = useActiveWorkspaceUsers( 30 - project?.workspaceId || "", 31 - ); 29 + const { data: workspaceUsers } = useGetActiveWorkspaceUsers({ 30 + workspaceId: project?.workspaceId ?? "", 31 + }); 32 32 const { mutateAsync: updateTask } = useUpdateTask(); 33 33 34 34 const form = useForm<z.infer<typeof taskInfoSchema>>({ ··· 36 36 status: task?.status || "", 37 37 userEmail: task?.userEmail || "", 38 38 priority: task?.priority || "", 39 - dueDate: task?.dueDate || new Date(), 39 + dueDate: task?.dueDate ? new Date(task.dueDate) : new Date(), 40 40 }, 41 41 }); 42 42 ··· 50 50 userEmail: data.userEmail, 51 51 status: data.status || "", 52 52 priority: data.priority || "", 53 - dueDate: data.dueDate || new Date(), 53 + dueDate: data.dueDate.toISOString(), 54 54 projectId: project?.id || "", 55 55 }); 56 56 toast.success("Task updated successfully"); ··· 115 115 label: "Unassigned", 116 116 }, 117 117 ...(workspaceUsers?.map((user) => ({ 118 - value: user.user?.email ?? "", 119 - label: user.user?.name ?? "", 118 + value: user.userEmail ?? "", 119 + label: user.userName ?? "", 120 120 })) || []), 121 121 ]} 122 122 />
+1 -1
apps/web/src/components/task/task-title.tsx
··· 33 33 title: value, 34 34 userEmail: task.userEmail || "", 35 35 status: task.status || "", 36 - dueDate: task.dueDate || new Date(), 36 + dueDate: task.dueDate ? new Date(task.dueDate).toISOString() : null, 37 37 priority: task.priority || "", 38 38 position: task.position || 0, 39 39 });
+3 -2
apps/web/src/components/team/delete-team-member-modal.tsx
··· 4 4 import { useQueryClient } from "@tanstack/react-query"; 5 5 import { Trash2, X } from "lucide-react"; 6 6 import { Button } from "../ui/button"; 7 + 7 8 function DeleteTeamMemberModal({ 8 9 userEmail, 9 10 open, ··· 19 20 20 21 const onRemoveMember = async () => { 21 22 await deleteWorkspaceUser({ 22 - workspaceId: workspaceId, 23 - userEmail: userEmail, 23 + workspaceId, 24 + userEmail, 24 25 }); 25 26 26 27 queryClient.invalidateQueries({
+1 -5
apps/web/src/components/team/members-table.tsx
··· 7 7 import { Avatar, AvatarFallback } from "../ui/avatar"; 8 8 import DeleteTeamMemberModal from "./delete-team-member-modal"; 9 9 10 - type MembersTableProps = { 11 - users: WorkspaceUser[]; 12 - }; 13 - 14 - function MembersTable({ users }: MembersTableProps) { 10 + function MembersTable({ users }: { users: WorkspaceUser[] }) { 15 11 const { isOwner } = useWorkspacePermission(); 16 12 const [isRemoveMemberModalOpen, setIsRemoveMemberModalOpen] = useState(false); 17 13 const [selectedMember, setSelectedMember] = useState<WorkspaceUser | null>(
+19 -14
apps/web/src/fetchers/activity/create-activity.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type CreateActivityRequest = InferRequestType< 5 + (typeof client)["activity"]["comment"]["$post"] 6 + >["json"]; 2 7 3 - async function createActivity(data: { 4 - taskId: string; 5 - content: string; 6 - userEmail: string; 7 - }) { 8 - const response = await api.activity.comment.post({ 9 - taskId: data.taskId, 10 - content: data.content, 11 - userEmail: data.userEmail, 8 + async function createActivity({ 9 + taskId, 10 + content, 11 + userEmail, 12 + }: CreateActivityRequest) { 13 + const response = await client.activity.comment.$post({ 14 + json: { 15 + taskId, 16 + content, 17 + userEmail, 18 + }, 12 19 }); 13 20 14 - if (response.error) { 15 - throw new Error(response.error.value.message); 16 - } 21 + const data = await response.json(); 17 22 18 - return response.data; 23 + return data; 19 24 } 20 25 21 26 export default createActivity;
+12 -7
apps/web/src/fetchers/activity/get-activites-by-task-id.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - async function getActivitesByTaskId(taskId: string) { 4 - const response = await api.activity.list({ taskId }).get(); 4 + export type GetActivitesByTaskIdRequest = InferRequestType< 5 + (typeof client)["activity"][":taskId"]["$get"] 6 + >["param"]; 7 + 8 + async function getActivitesByTaskId({ taskId }: GetActivitesByTaskIdRequest) { 9 + const response = await client.activity[":taskId"].$get({ 10 + param: { taskId }, 11 + }); 5 12 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 13 + const data = await response.json(); 9 14 10 - return response.data; 15 + return data; 11 16 } 12 17 13 18 export default getActivitesByTaskId;
+11 -11
apps/web/src/fetchers/project/create-project.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type CreateProjectRequest = InferRequestType< 5 + (typeof client)["project"]["$post"] 6 + >["json"]; 2 7 3 8 async function createProject({ 4 9 name, 5 10 slug, 6 11 workspaceId, 7 12 icon, 8 - }: { name: string; slug: string; workspaceId: string; icon: string }) { 9 - const response = await api.project.create.post({ 10 - name, 11 - workspaceId, 12 - icon, 13 - slug, 13 + }: CreateProjectRequest) { 14 + const response = await client.project.$post({ 15 + json: { name, slug, icon, workspaceId }, 14 16 }); 15 17 16 - if (response.error) { 17 - throw new Error(response.error.value.message); 18 - } 18 + const data = await response.json(); 19 19 20 - return response; 20 + return data; 21 21 } 22 22 23 23 export default createProject;
+12 -7
apps/web/src/fetchers/project/delete-project.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - export default async function deleteProject({ id }: { id: string }) { 4 - const response = await api.project({ id }).delete(); 4 + export type DeleteProjectRequest = InferRequestType< 5 + (typeof client)["project"][":id"]["$delete"] 6 + >["param"]; 7 + 8 + async function deleteProject({ id }: DeleteProjectRequest) { 9 + const response = await client.project[":id"].$delete({ param: { id } }); 5 10 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 11 + const data = await response.json(); 9 12 10 - return response?.data; 13 + return data; 11 14 } 15 + 16 + export default deleteProject;
+14 -10
apps/web/src/fetchers/project/get-project.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - async function getProject({ 4 - id, 5 - workspaceId, 6 - }: { id: string; workspaceId: string }) { 7 - const response = await api.project({ id }).get({ query: { workspaceId } }); 4 + export type GetProjectRequest = InferRequestType< 5 + (typeof client)["project"][":id"]["$get"] 6 + >["param"] & 7 + InferRequestType<(typeof client)["project"][":id"]["$get"]>["query"]; 8 8 9 - if (response.error) { 10 - throw new Error(response.error.value.message); 11 - } 9 + async function getProject({ id, workspaceId }: GetProjectRequest) { 10 + const response = await client.project[":id"].$get({ 11 + param: { id }, 12 + query: { workspaceId }, 13 + }); 12 14 13 - return response?.data; 15 + const data = await response.json(); 16 + 17 + return data; 14 18 } 15 19 16 20 export default getProject;
+10 -7
apps/web/src/fetchers/project/get-projects.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type GetProjectsRequest = InferRequestType< 5 + (typeof client)["project"]["$get"] 6 + >["query"]; 2 7 3 - async function getProjects({ workspaceId }: { workspaceId: string }) { 8 + async function getProjects({ workspaceId }: GetProjectsRequest) { 4 9 if (!workspaceId) return; 5 10 6 - const response = await api.project.list({ workspaceId }).get(); 11 + const response = await client.project.$get({ query: { workspaceId } }); 7 12 8 - if (response.error) { 9 - throw new Error(response.error.value.message); 10 - } 13 + const data = await response.json(); 11 14 12 - return response?.data; 15 + return data; 13 16 } 14 17 15 18 export default getProjects;
+13 -26
apps/web/src/fetchers/project/update-project.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - async function updateProject({ 4 - id, 5 - workspaceId, 6 - name, 7 - description, 8 - icon, 9 - slug, 10 - }: { 11 - id: string; 12 - workspaceId: string; 13 - name: string; 14 - description: string; 15 - icon: string; 16 - slug: string; 17 - }) { 18 - const response = await api.project({ id }).put({ 19 - workspaceId, 20 - name, 21 - description, 22 - icon, 23 - slug, 4 + export type UpdateProjectRequest = InferRequestType< 5 + (typeof client)["project"][":id"]["$put"] 6 + >["json"] & 7 + InferRequestType<(typeof client)["project"][":id"]["$put"]>["param"]; 8 + 9 + async function updateProject({ id, name, icon, slug }: UpdateProjectRequest) { 10 + const response = await client.project[":id"].$put({ 11 + param: { id }, 12 + json: { name, icon, slug }, 24 13 }); 25 14 26 - if (response.error) { 27 - throw new Error(response.error.value.message); 28 - } 15 + const data = await response.json(); 29 16 30 - return response?.data; 17 + return data; 31 18 } 32 19 33 20 export default updateProject;
+19 -15
apps/web/src/fetchers/task/create-task.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type CreateTaskRequest = InferRequestType< 5 + (typeof client)["task"][":projectId"]["$post"] 6 + >["json"] & 7 + InferRequestType<(typeof client)["task"][":projectId"]["$post"]>["param"]; 2 8 3 9 async function createTask( 4 10 title: string, ··· 8 14 status: string, 9 15 dueDate: Date, 10 16 priority: string, 11 - position: number, 12 17 ) { 13 - const response = await api.task.create.post({ 14 - title, 15 - description, 16 - projectId, 17 - userEmail, 18 - status, 19 - dueDate, 20 - priority, 21 - position, 18 + const response = await client.task[":projectId"].$post({ 19 + json: { 20 + title, 21 + description, 22 + userEmail, 23 + status, 24 + dueDate: dueDate.toISOString(), 25 + priority, 26 + }, 27 + param: { projectId }, 22 28 }); 23 29 24 - if (response.error) { 25 - throw new Error(response.error.value.message); 26 - } 30 + const data = await response.json(); 27 31 28 - return response?.data; 32 + return data; 29 33 } 30 34 31 35 export default createTask;
+9 -6
apps/web/src/fetchers/task/get-task.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type GetTaskRequest = InferRequestType< 5 + (typeof client)["task"][":id"]["$get"] 6 + >["param"]; 2 7 3 8 async function getTask(taskId: string) { 4 - const response = await api.task({ taskId }).get(); 9 + const response = await client.task[":id"].$get({ param: { id: taskId } }); 5 10 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 11 + const data = await response.json(); 9 12 10 - return response.data; 13 + return data; 11 14 } 12 15 13 16 export default getTask;
+6 -6
apps/web/src/fetchers/task/get-tasks.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 2 3 3 async function getTasks(projectId: string) { 4 - const response = await api.task.list({ projectId }).get(); 4 + const response = await client.task.tasks[":projectId"].$get({ 5 + param: { projectId }, 6 + }); 5 7 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 8 + const data = await response.json(); 9 9 10 - return response.data; 10 + return data; 11 11 } 12 12 13 13 export default getTasks;
+16 -15
apps/web/src/fetchers/task/update-task.ts
··· 1 - import type { Task } from "@/types/project"; 2 - import { api } from "@kaneo/libs"; 1 + import type Task from "@/types/task"; 2 + import { client } from "@kaneo/libs"; 3 3 4 4 async function updateTask(taskId: string, task: Task) { 5 - const response = await api.task({ taskId }).update.put({ 6 - userEmail: task.userEmail || "", 7 - title: task.title, 8 - description: task.description || "", 9 - status: task.status, 10 - projectId: task.projectId, 11 - priority: task.priority || "", 12 - dueDate: task.dueDate || new Date(), 13 - position: task.position || 0, 5 + const response = await client.task[":id"].$put({ 6 + param: { id: taskId }, 7 + json: { 8 + userEmail: task.userEmail || "", 9 + title: task.title, 10 + description: task.description || "", 11 + status: task.status, 12 + priority: task.priority || "", 13 + dueDate: task.dueDate?.toString() || new Date().toString(), 14 + position: task.position || 0, 15 + projectId: task.projectId, 16 + }, 14 17 }); 15 18 16 - if (response.status !== 200) { 17 - throw new Error("Failed to update task"); 18 - } 19 + const data = await response.json(); 19 20 20 - return response.data; 21 + return data; 21 22 } 22 23 23 24 export default updateTask;
+5 -3
apps/web/src/fetchers/user/me.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 2 3 3 const me = async () => { 4 - const response = await api.me.get(); 4 + const response = await client.me.$get(); 5 5 6 - return response; 6 + const data = await response.json(); 7 + 8 + return data; 7 9 }; 8 10 9 11 export default me;
+8 -8
apps/web/src/fetchers/user/sign-in.ts
··· 1 1 import type { SignInFormValues } from "@/components/auth/sign-in-form"; 2 - import { api } from "@kaneo/libs"; 2 + import { client } from "@kaneo/libs"; 3 3 4 4 const signIn = async ({ email, password }: SignInFormValues) => { 5 - const response = await api.user["sign-in"].post({ 6 - email, 7 - password, 5 + const response = await client.user["sign-in"].$post({ 6 + json: { 7 + email, 8 + password, 9 + }, 8 10 }); 9 11 10 - if (response.error) { 11 - throw new Error(response.error.value.message); 12 - } 12 + const user = await response.json(); 13 13 14 - return response; 14 + return user; 15 15 }; 16 16 17 17 export default signIn;
+5 -3
apps/web/src/fetchers/user/sign-out.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 2 3 3 const signOut = async () => { 4 - const response = await api.user["sign-out"].post(); 4 + const response = await client.user["sign-out"].$post(); 5 5 6 - return response; 6 + const { message } = await response.json(); 7 + 8 + return message; 7 9 }; 8 10 9 11 export default signOut;
+9 -9
apps/web/src/fetchers/user/sign-up.ts
··· 1 1 import type { SignUpFormValues } from "@/components/auth/sign-up-form"; 2 - import { api } from "@kaneo/libs"; 2 + import { client } from "@kaneo/libs"; 3 3 4 4 const signUp = async ({ email, password, name }: SignUpFormValues) => { 5 - const response = await api.user["sign-up"].post({ 6 - email, 7 - password, 8 - name, 5 + const response = await client.user["sign-up"].$post({ 6 + json: { 7 + email, 8 + password, 9 + name, 10 + }, 9 11 }); 10 12 11 - if (response.error) { 12 - throw new Error(response.error.value.message); 13 - } 13 + const user = await response.json(); 14 14 15 - return response; 15 + return user; 16 16 }; 17 17 18 18 export default signUp;
+16 -9
apps/web/src/fetchers/workspace-user/delete-workspace-user.ts
··· 1 - import { api } from "@kaneo/libs/src/eden"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type DeleteWorkspaceUserRequest = InferRequestType< 5 + (typeof client)["workspace-user"][":workspaceId"]["$delete"] 6 + >["param"] & 7 + InferRequestType< 8 + (typeof client)["workspace-user"][":workspaceId"]["$delete"] 9 + >["query"]; 2 10 3 11 async function deleteWorkspaceUser({ 4 12 workspaceId, 5 13 userEmail, 6 - }: { workspaceId: string; userEmail: string }) { 7 - const response = await api["workspace-user"]({ workspaceId })({ 8 - userEmail, 9 - }).delete(); 14 + }: DeleteWorkspaceUserRequest) { 15 + const response = await client["workspace-user"][":workspaceId"].$delete({ 16 + param: { workspaceId }, 17 + query: { userEmail }, 18 + }); 10 19 11 - if (response.error) { 12 - throw new Error(response.error.value.message); 13 - } 20 + const data = await response.json(); 14 21 15 - return response.data; 22 + return data; 16 23 } 17 24 18 25 export default deleteWorkspaceUser;
+14 -7
apps/web/src/fetchers/workspace-user/get-active-workspace-users.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type GetActiveWorkspaceUsersRequest = InferRequestType< 5 + (typeof client)["workspace-user"][":workspaceId"]["active"]["$get"] 6 + >["param"]; 2 7 3 - async function getActiveWorkspaceUsers(workspaceId: string) { 4 - const response = await api["workspace-user"]({ workspaceId }).active.get(); 8 + async function getActiveWorkspaceUsers({ 9 + workspaceId, 10 + }: GetActiveWorkspaceUsersRequest) { 11 + const response = await client["workspace-user"][":workspaceId"].active.$get({ 12 + param: { workspaceId }, 13 + }); 5 14 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 15 + const data = await response.json(); 9 16 10 - return response.data; 17 + return data; 11 18 } 12 19 13 20 export default getActiveWorkspaceUsers;
+12 -9
apps/web/src/fetchers/workspace-user/get-workspace-users.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type GetWorkspaceUsersRequest = InferRequestType< 5 + (typeof client)["workspace-user"][":workspaceId"]["$get"] 6 + >; 2 7 3 - async function getWorkspaceUsers({ workspaceId }: { workspaceId: string }) { 4 - const response = await api["workspace-user"] 5 - .list({ workspaceId: workspaceId }) 6 - .get(); 8 + async function getWorkspaceUsers({ workspaceId }: GetWorkspaceUsersRequest) { 9 + const response = await client["workspace-user"][":workspaceId"].$get({ 10 + param: { workspaceId }, 11 + }); 7 12 8 - if (response.error) { 9 - throw new Error(response.error.value.message); 10 - } 13 + const data = await response.json(); 11 14 12 - return response.data; 15 + return data; 13 16 } 14 17 15 18 export default getWorkspaceUsers;
+15 -9
apps/web/src/fetchers/workspace-user/invite-workspace-member.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + export type InviteWorkspaceMemberRequest = InferRequestType< 5 + (typeof client)["workspace-user"][":workspaceId"]["invite"]["$post"] 6 + >["json"] & 7 + InferRequestType< 8 + (typeof client)["workspace-user"][":workspaceId"]["invite"]["$post"] 9 + >["param"]; 2 10 3 11 const inviteWorkspaceMember = async ({ 4 12 workspaceId, 5 13 userEmail, 6 - }: { workspaceId: string; userEmail: string }) => { 7 - const response = await api["workspace-user"]({ workspaceId }).invite.post({ 8 - workspaceId, 9 - userEmail, 14 + }: InviteWorkspaceMemberRequest) => { 15 + const response = await client["workspace-user"][":workspaceId"].invite.$post({ 16 + json: { userEmail }, 17 + param: { workspaceId }, 10 18 }); 11 19 12 - if (response.error) { 13 - throw new Error(response.error.value.message); 14 - } 20 + const data = await response.json(); 15 21 16 - return response.data; 22 + return data; 17 23 }; 18 24 19 25 export default inviteWorkspaceMember;
+12 -7
apps/web/src/fetchers/workspace/create-workspace.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - const createWorkspace = async ({ name }: { name: string }) => { 4 - const response = await api.workspace.create.post({ name }); 4 + type CreateWorkspaceRequest = InferRequestType< 5 + typeof client.workspace.$post 6 + >["json"]; 7 + 8 + const createWorkspace = async ({ name }: CreateWorkspaceRequest) => { 9 + const response = await client.workspace.$post({ 10 + json: { name }, 11 + }); 5 12 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 13 + const workspace = await response.json(); 9 14 10 - return response.data; 15 + return workspace; 11 16 }; 12 17 13 18 export default createWorkspace;
+12 -7
apps/web/src/fetchers/workspace/delete-workspace.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - const deleteWorkspace = async ({ id }: { id: string }) => { 4 - const response = await api.workspace({ id }).delete(); 4 + type DeleteWorkspaceRequest = InferRequestType< 5 + (typeof client.workspace)[":id"]["$delete"] 6 + >["param"]; 7 + 8 + const deleteWorkspace = async ({ id }: DeleteWorkspaceRequest) => { 9 + const response = await client.workspace[":id"].$delete({ 10 + param: { id }, 11 + }); 5 12 6 - if (response.error) { 7 - throw new Error(response.error.value.message); 8 - } 13 + const workspace = await response.json(); 9 14 10 - return response; 15 + return workspace; 11 16 }; 12 17 13 18 export default deleteWorkspace;
+12 -7
apps/web/src/fetchers/workspace/get-workspace.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 2 3 3 - async function getWorkspace({ workspaceId }: { workspaceId: string }) { 4 - const response = await api.workspace({ id: workspaceId }).get(); 4 + type GetWorkspaceRequest = InferRequestType< 5 + (typeof client.workspace)[":id"]["$get"] 6 + >["param"]; 7 + 8 + async function getWorkspace({ id }: GetWorkspaceRequest) { 9 + const response = await client.workspace[":id"].$get({ 10 + param: { id }, 11 + }); 5 12 6 - if (response.error?.value.message) { 7 - throw new Error(response.error.value.message); 8 - } 13 + const workspace = await response.json(); 9 14 10 - return response.data; 15 + return workspace; 11 16 } 12 17 13 18 export default getWorkspace;
+5 -3
apps/web/src/fetchers/workspace/get-workspaces.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 2 3 3 const getWorkspaces = async () => { 4 - const response = await api.workspace.list.get(); 4 + const response = await client.workspace.$get(); 5 5 6 - return response.data; 6 + const workspaces = await response.json(); 7 + 8 + return workspaces; 7 9 }; 8 10 9 11 export default getWorkspaces;
+15 -16
apps/web/src/fetchers/workspace/update-workspace.ts
··· 1 - import { api } from "@kaneo/libs"; 1 + import { client } from "@kaneo/libs"; 2 + import type { InferRequestType } from "hono/client"; 3 + 4 + type UpdateWorkspaceRequest = InferRequestType< 5 + (typeof client.workspace)[":id"]["$put"] 6 + >["param"] & 7 + InferRequestType<(typeof client.workspace)[":id"]["$put"]>["json"]; 2 8 3 9 const updateWorkspace = async ({ 4 - workspaceId, 5 - userEmail, 10 + id, 6 11 name, 7 12 description, 8 - }: { 9 - workspaceId: string; 10 - userEmail: string; 11 - name: string; 12 - description: string; 13 - }) => { 14 - const response = await api 15 - .workspace({ id: workspaceId }) 16 - .put({ name, description }, { headers: { "x-user-email": userEmail } }); 13 + }: UpdateWorkspaceRequest) => { 14 + const response = await client.workspace[":id"].$put({ 15 + param: { id }, 16 + json: { name, description }, 17 + }); 17 18 18 - if (response.error) { 19 - throw new Error(response.error.value.message); 20 - } 19 + const workspace = await response.json(); 21 20 22 - return response.data; 21 + return workspace; 23 22 }; 24 23 25 24 export default updateWorkspace;
+6 -18
apps/web/src/hooks/mutations/task/use-create-task.ts
··· 1 - import createTask from "@/fetchers/task/create-task"; 1 + import createTask, { 2 + type CreateTaskRequest, 3 + } from "@/fetchers/task/create-task"; 2 4 import { useMutation } from "@tanstack/react-query"; 3 5 4 - type CreateTaskInput = { 5 - title: string; 6 - description: string; 7 - userEmail: string; 8 - projectId: string; 9 - status: string; 10 - dueDate: Date; 11 - number?: number; 12 - priority: "low" | "medium" | "high" | "urgent"; 13 - position: number; 14 - }; 15 - 16 6 function useCreateTask() { 17 7 return useMutation({ 18 8 mutationFn: ({ ··· 23 13 status, 24 14 dueDate, 25 15 priority, 26 - position, 27 - }: CreateTaskInput) => 16 + }: CreateTaskRequest) => 28 17 createTask( 29 18 title, 30 19 description, 31 20 projectId, 32 - userEmail, 21 + userEmail ?? "", 33 22 status, 34 - dueDate, 23 + new Date(dueDate), 35 24 priority, 36 - position, 37 25 ), 38 26 }); 39 27 }
+1 -1
apps/web/src/hooks/mutations/task/use-update-task.ts
··· 1 1 import updateTask from "@/fetchers/task/update-task"; 2 - import type { Task } from "@/types/project"; 2 + import type Task from "@/types/task"; 3 3 import { useMutation, useQueryClient } from "@tanstack/react-query"; 4 4 5 5 function useUpdateTask() {
+4 -5
apps/web/src/hooks/mutations/workspace-user/use-delete-workspace-user.ts
··· 1 1 import { useMutation } from "@tanstack/react-query"; 2 2 3 - import deleteWorkspaceUser from "@/fetchers/workspace-user/delete-workspace-user"; 3 + import deleteWorkspaceUser, { 4 + type DeleteWorkspaceUserRequest, 5 + } from "@/fetchers/workspace-user/delete-workspace-user"; 4 6 5 7 function useDeleteWorkspaceUser() { 6 8 return useMutation({ 7 - mutationFn: ({ 8 - workspaceId, 9 - userEmail, 10 - }: { workspaceId: string; userEmail: string }) => 9 + mutationFn: ({ workspaceId, userEmail }: DeleteWorkspaceUserRequest) => 11 10 deleteWorkspaceUser({ workspaceId, userEmail }), 12 11 }); 13 12 }
+1 -1
apps/web/src/hooks/queries/activity/use-get-activities-by-task-id.ts
··· 4 4 function useGetActivitiesByTaskId(taskId: string) { 5 5 return useQuery({ 6 6 queryKey: ["activities", taskId], 7 - queryFn: () => getActivitesByTaskId(taskId), 7 + queryFn: () => getActivitesByTaskId({ taskId }), 8 8 }); 9 9 } 10 10
+8 -4
apps/web/src/hooks/queries/workspace-users/use-active-workspace-users.ts
··· 1 - import getActiveWorkspaceUsers from "@/fetchers/workspace-user/get-active-workspace-users"; 1 + import getActiveWorkspaceUsers, { 2 + type GetActiveWorkspaceUsersRequest, 3 + } from "@/fetchers/workspace-user/get-active-workspace-users"; 2 4 import { useQuery } from "@tanstack/react-query"; 3 5 4 - export const useActiveWorkspaceUsers = (workspaceId: string) => { 6 + export const useGetActiveWorkspaceUsers = ({ 7 + workspaceId, 8 + }: GetActiveWorkspaceUsersRequest) => { 5 9 return useQuery({ 6 10 queryKey: ["workspace-users", "active", workspaceId], 7 - queryFn: () => getActiveWorkspaceUsers(workspaceId), 11 + queryFn: () => getActiveWorkspaceUsers({ workspaceId }), 8 12 enabled: !!workspaceId, 9 13 }); 10 14 }; 11 15 12 - export default useActiveWorkspaceUsers; 16 + export default useGetActiveWorkspaceUsers;
+2 -2
apps/web/src/hooks/queries/workspace-users/use-get-workspace-users.ts
··· 1 - import getWorkspaceUsers from "@/fetchers/workspace-user/get-workspace-users"; 1 + import getActiveWorkspaceUsers from "@/fetchers/workspace-user/get-workspace-users"; 2 2 import { useQuery } from "@tanstack/react-query"; 3 3 4 4 function useGetWorkspaceUsers({ workspaceId }: { workspaceId: string }) { 5 5 return useQuery({ 6 6 queryKey: ["workspace-users", workspaceId], 7 - queryFn: () => getWorkspaceUsers({ workspaceId }), 7 + queryFn: () => getActiveWorkspaceUsers({ workspaceId }), 8 8 }); 9 9 } 10 10
+4 -4
apps/web/src/hooks/queries/workspace/use-get-workspace.ts
··· 1 1 import getWorkspace from "@/fetchers/workspace/get-workspace"; 2 2 import { useQuery } from "@tanstack/react-query"; 3 3 4 - function useGetWorkspace({ workspaceId }: { workspaceId: string }) { 4 + function useGetWorkspace({ id }: { id: string }) { 5 5 return useQuery({ 6 - queryKey: [`workspace-${workspaceId}`], 7 - enabled: !!workspaceId, 8 - queryFn: () => getWorkspace({ workspaceId }), 6 + queryKey: [`workspace-${id}`], 7 + enabled: !!id, 8 + queryFn: () => getWorkspace({ id }), 9 9 }); 10 10 } 11 11
+44 -3
apps/web/src/routes/dashboard/workspace-settings/$workspaceId/index.tsx
··· 12 12 import { Input } from "@/components/ui/input"; 13 13 import useDeleteWorkspace from "@/hooks/mutations/workspace/use-delete-workspace"; 14 14 import useUpdateWorkspace from "@/hooks/mutations/workspace/use-update-workspace"; 15 + import { useWorkspacePermission } from "@/hooks/useWorkspacePermission"; 15 16 import queryClient from "@/query-client"; 16 17 import useWorkspaceStore from "@/store/workspace"; 17 18 import { zodResolver } from "@hookform/resolvers/zod"; 18 19 import { createFileRoute, useNavigate } from "@tanstack/react-router"; 19 - import { AlertTriangle } from "lucide-react"; 20 + import { AlertTriangle, ArrowLeft, Lock } from "lucide-react"; 20 21 import { useState } from "react"; 21 22 import { useForm } from "react-hook-form"; 22 23 import { toast } from "sonner"; ··· 40 41 const navigate = useNavigate(); 41 42 const { workspaceId } = Route.useParams(); 42 43 const [confirmWorkSpaceName, setConfirmWorkSpaceName] = useState(""); 44 + const { isOwner } = useWorkspacePermission(); 43 45 44 46 const { workspace, setWorkspace } = useWorkspaceStore(); 45 47 ··· 114 116 } 115 117 }; 116 118 119 + if (!isOwner) { 120 + return ( 121 + <div className="flex-1 p-6"> 122 + <PageTitle title="Project Settings" /> 123 + <div className="mt-6 max-w-2xl mx-auto"> 124 + <div className="bg-white dark:bg-zinc-800/50 rounded-lg p-8 shadow-sm border border-zinc-200 dark:border-zinc-700/50 text-center"> 125 + <div className="flex justify-center mb-4"> 126 + <div className="w-16 h-16 rounded-full bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center"> 127 + <Lock className="w-8 h-8 text-amber-600 dark:text-amber-400" /> 128 + </div> 129 + </div> 130 + <h2 className="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-2"> 131 + Permission Required 132 + </h2> 133 + <p className="text-zinc-500 dark:text-zinc-400 mb-6 max-w-md mx-auto"> 134 + Only workspace owners can modify workspace settings. Please 135 + contact the workspace owner if you need to make changes. 136 + </p> 137 + <Button 138 + variant="outline" 139 + onClick={() => 140 + navigate({ 141 + to: "/dashboard/workspace/$workspaceId", 142 + params: { 143 + workspaceId: workspaceId ?? "", 144 + }, 145 + }) 146 + } 147 + className="gap-2" 148 + > 149 + <ArrowLeft className="w-4 h-4" /> 150 + Back to Workspace 151 + </Button> 152 + </div> 153 + </div> 154 + </div> 155 + ); 156 + } 157 + 117 158 return ( 118 159 <> 119 160 <PageTitle title={`${workspace?.name} Settings`} /> ··· 149 190 name="name" 150 191 render={({ field }) => ( 151 192 <FormItem> 152 - <FormLabel>WorkSpace Name</FormLabel> 193 + <FormLabel>Workspace Name</FormLabel> 153 194 <FormControl> 154 195 <Input 155 196 {...field} ··· 191 232 )} 192 233 </div> 193 234 </div> 194 - {workspace && workspace.ownerEmail === user?.email && ( 235 + {workspace && isOwner && ( 195 236 <div className="bg-white dark:bg-zinc-900 rounded-lg border border-zinc-200 dark:border-zinc-800"> 196 237 <div className="p-4 md:p-6"> 197 238 <h2 className="text-base font-medium text-red-600 dark:text-red-400 mb-1">
+1 -1
apps/web/src/routes/dashboard/workspace/$workspaceId.tsx
··· 14 14 function RouteComponent() { 15 15 const { workspaceId } = Route.useParams(); 16 16 const { data } = useGetWorkspace({ 17 - workspaceId, 17 + id: workspaceId, 18 18 }); 19 19 const { setWorkspace } = useWorkspaceStore(); 20 20 const { project } = useProjectStore();
+25 -9
apps/web/src/routes/dashboard/workspace/$workspaceId/project/$projectId/backlog.tsx
··· 7 7 import useUpdateTask from "@/hooks/mutations/task/use-update-task"; 8 8 import useGetTasks from "@/hooks/queries/task/use-get-tasks"; 9 9 import useProjectStore from "@/store/project"; 10 - import type { Task } from "@/types/project"; 10 + import type Task from "@/types/task"; 11 11 import { createFileRoute } from "@tanstack/react-router"; 12 12 import { addWeeks, endOfWeek, isWithinInterval, startOfWeek } from "date-fns"; 13 13 import { produce } from "immer"; ··· 100 100 ...project, 101 101 columns: [ 102 102 { 103 - id: "planned", 104 - name: "Planned Tasks", 103 + id: "to-do" as const, 104 + name: "To Do" as const, 105 105 tasks: project.plannedTasks 106 - ? filterTasks(project.plannedTasks) 106 + ? filterTasks(project.plannedTasks).map((task) => ({ 107 + ...task, 108 + assigneeName: null, 109 + assigneeEmail: null, 110 + })) 107 111 : [], 108 112 }, 109 113 { 110 - id: "archived", 111 - name: "Archived Tasks", 114 + id: "done" as const, 115 + name: "Done" as const, 112 116 tasks: project.archivedTasks 113 - ? filterTasks(project.archivedTasks) 117 + ? filterTasks(project.archivedTasks).map((task) => ({ 118 + ...task, 119 + assigneeName: null, 120 + assigneeEmail: null, 121 + })) 114 122 : [], 115 123 }, 116 124 ], 117 125 plannedTasks: project.plannedTasks 118 - ? filterTasks(project.plannedTasks) 126 + ? filterTasks(project.plannedTasks).map((task) => ({ 127 + ...task, 128 + assigneeName: null, 129 + assigneeEmail: null, 130 + })) 119 131 : [], 120 132 archivedTasks: project.archivedTasks 121 - ? filterTasks(project.archivedTasks) 133 + ? filterTasks(project.archivedTasks).map((task) => ({ 134 + ...task, 135 + assigneeName: null, 136 + assigneeEmail: null, 137 + })) 122 138 : [], 123 139 } 124 140 : undefined;
+102 -46
apps/web/src/routes/dashboard/workspace/$workspaceId/project/$projectId/board.tsx
··· 7 7 import useGetTasks from "@/hooks/queries/task/use-get-tasks"; 8 8 import useProjectStore from "@/store/project"; 9 9 import { useUserPreferencesStore } from "@/store/user-preferences"; 10 - import type { Task } from "@/types/project"; 10 + import type Task from "@/types/task"; 11 11 import { createFileRoute } from "@tanstack/react-router"; 12 12 import { addWeeks, endOfWeek, isWithinInterval, startOfWeek } from "date-fns"; 13 13 import { useEffect, useState } from "react"; ··· 37 37 }, [data, setProject]); 38 38 39 39 const filterTasks = (tasks: Task[]): Task[] => { 40 - return tasks.filter((task) => { 41 - if ( 42 - filters.search && 43 - !task.title.toLowerCase().includes(filters.search.toLowerCase()) 44 - ) { 45 - return false; 46 - } 40 + return tasks 41 + .filter((task) => { 42 + if ( 43 + filters.search && 44 + !task.title.toLowerCase().includes(filters.search.toLowerCase()) 45 + ) { 46 + return false; 47 + } 47 48 48 - if (filters.assignee && task.userEmail !== filters.assignee) { 49 - return false; 50 - } 49 + if (filters.assignee && task.userEmail !== filters.assignee) { 50 + return false; 51 + } 51 52 52 - if (filters.priority && task.priority !== filters.priority) { 53 - return false; 54 - } 53 + if (filters.priority && task.priority !== filters.priority) { 54 + return false; 55 + } 55 56 56 - if (filters.dueDate && task.dueDate) { 57 - const today = new Date(); 58 - const taskDate = new Date(task.dueDate); 57 + if (filters.dueDate && task.dueDate) { 58 + const today = new Date(); 59 + const taskDate = new Date(task.dueDate); 59 60 60 - switch (filters.dueDate) { 61 - case "Due this week": { 62 - const weekStart = startOfWeek(today); 63 - const weekEnd = endOfWeek(today); 64 - if ( 65 - !isWithinInterval(taskDate, { start: weekStart, end: weekEnd }) 66 - ) { 67 - return false; 61 + switch (filters.dueDate) { 62 + case "Due this week": { 63 + const weekStart = startOfWeek(today); 64 + const weekEnd = endOfWeek(today); 65 + if ( 66 + !isWithinInterval(taskDate, { start: weekStart, end: weekEnd }) 67 + ) { 68 + return false; 69 + } 70 + break; 68 71 } 69 - break; 70 - } 71 - case "Due next week": { 72 - const nextWeekStart = startOfWeek(addWeeks(today, 1)); 73 - const nextWeekEnd = endOfWeek(addWeeks(today, 1)); 74 - if ( 75 - !isWithinInterval(taskDate, { 76 - start: nextWeekStart, 77 - end: nextWeekEnd, 78 - }) 79 - ) { 72 + case "Due next week": { 73 + const nextWeekStart = startOfWeek(addWeeks(today, 1)); 74 + const nextWeekEnd = endOfWeek(addWeeks(today, 1)); 75 + if ( 76 + !isWithinInterval(taskDate, { 77 + start: nextWeekStart, 78 + end: nextWeekEnd, 79 + }) 80 + ) { 81 + return false; 82 + } 83 + break; 84 + } 85 + case "No due date": { 80 86 return false; 81 87 } 82 - break; 83 - } 84 - case "No due date": { 85 - return false; 86 88 } 87 89 } 88 - } 89 90 90 - return true; 91 - }); 91 + return true; 92 + }) 93 + .map((task) => ({ 94 + ...task, 95 + assigneeName: null, 96 + assigneeEmail: task.userEmail ?? null, 97 + })); 92 98 }; 93 99 94 100 const filteredProject = project 95 101 ? { 96 102 ...project, 97 - columns: project.columns?.map((column) => ({ 98 - ...column, 99 - tasks: filterTasks(column.tasks), 103 + columns: 104 + project.columns?.map((column) => ({ 105 + id: column.id as "to-do" | "in-progress" | "in-review" | "done", 106 + name: column.name as "To Do" | "In Progress" | "In Review" | "Done", 107 + tasks: filterTasks(column.tasks).map((task) => ({ 108 + id: task.id, 109 + title: task.title, 110 + number: task.number, 111 + description: task.description, 112 + status: task.status, 113 + priority: task.priority, 114 + dueDate: task.dueDate, 115 + position: task.position, 116 + createdAt: task.createdAt, 117 + userEmail: task.userEmail, 118 + assigneeName: null, 119 + assigneeEmail: task.userEmail ?? null, 120 + projectId: task.projectId, 121 + })), 122 + })) ?? [], 123 + archivedTasks: filterTasks(project.archivedTasks).map((task) => ({ 124 + id: task.id, 125 + title: task.title, 126 + number: task.number, 127 + description: task.description, 128 + status: task.status, 129 + priority: task.priority, 130 + dueDate: task.dueDate, 131 + position: task.position, 132 + createdAt: task.createdAt, 133 + userEmail: task.userEmail, 134 + assigneeName: null, 135 + assigneeEmail: task.userEmail ?? null, 136 + projectId: task.projectId, 137 + })), 138 + plannedTasks: filterTasks(project.plannedTasks).map((task) => ({ 139 + id: task.id, 140 + title: task.title, 141 + number: task.number, 142 + description: task.description, 143 + status: task.status, 144 + priority: task.priority, 145 + dueDate: task.dueDate, 146 + position: task.position, 147 + createdAt: task.createdAt, 148 + userEmail: task.userEmail, 149 + assigneeName: null, 150 + assigneeEmail: task.userEmail ?? null, 151 + projectId: task.projectId, 100 152 })), 101 153 } 102 154 : undefined; 155 + 156 + if (!filteredProject) { 157 + return <div>No project found</div>; 158 + } 103 159 104 160 return ( 105 161 <div className="flex flex-col flex-1">
-2
apps/web/src/routes/dashboard/workspace/$workspaceId/project/$projectId/settings.tsx
··· 61 61 try { 62 62 await updateProject({ 63 63 id: project?.id ?? "", 64 - workspaceId: project?.workspaceId ?? "", 65 - description: project?.description ?? "", 66 64 name: data.name, 67 65 icon: data.icon, 68 66 slug: data.slug,
+3 -3
apps/web/src/store/project.ts
··· 1 - import type { Project } from "@/types/project"; 1 + import type { ProjectWithTasks } from "@/types/project"; 2 2 import { create } from "zustand"; 3 3 4 4 const useProjectStore = create<{ 5 - project: Project | undefined; 6 - setProject: (updatedProject: Project | undefined) => void; 5 + project: ProjectWithTasks | undefined; 6 + setProject: (updatedProject: ProjectWithTasks | undefined) => void; 7 7 }>((set) => ({ 8 8 project: undefined, 9 9 setProject: (updatedProject) => set(() => ({ project: updatedProject })),
+8 -30
apps/web/src/types/project/index.ts
··· 1 - export type Project = { 2 - id: string; 3 - name: string; 4 - slug: string; 5 - icon: string | null; 6 - description: string | null; 7 - workspaceId: string; 8 - columns?: Column[]; 9 - archivedTasks?: Task[]; 10 - plannedTasks?: Task[]; 11 - }; 1 + import type { client } from "@kaneo/libs"; 2 + import type { InferResponseType } from "hono/client"; 12 3 13 - export type Column = { 14 - id: string; 15 - name: string; 16 - tasks: Task[]; 17 - }; 4 + export type Project = InferResponseType< 5 + (typeof client)["project"][":id"]["$get"] 6 + >; 18 7 19 - export type Task = { 20 - id: string; 21 - createdAt: Date; 22 - number: number | null; 23 - description: string | null; 24 - projectId: string; 25 - userEmail: string | null; 26 - title: string; 27 - status: string; 28 - dueDate: Date | null; 29 - priority: string | null; 30 - projectSlug?: string; 31 - position: number | null; 32 - }; 8 + export type ProjectWithTasks = InferResponseType< 9 + (typeof client)["task"]["tasks"][":projectId"]["$get"] 10 + >;
+6
apps/web/src/types/task/index.ts
··· 1 + import type { client } from "@kaneo/libs"; 2 + import type { InferResponseType } from "hono/client"; 3 + 4 + type Task = InferResponseType<(typeof client)["task"][":id"]["$get"]>; 5 + 6 + export default Task;
+3 -3
apps/web/src/types/user.ts
··· 1 - import type { api } from "@kaneo/libs"; 2 - import type ApiResponse from "./api-response"; 1 + import type { client } from "@kaneo/libs"; 2 + import type { InferResponseType } from "hono"; 3 3 4 - export type User = NonNullable<ApiResponse<typeof api.me.get>> | undefined; 4 + export type User = InferResponseType<typeof client.me.$get>; 5 5 6 6 export type LoggedInUser = { 7 7 name: string;
+6 -7
apps/web/src/types/workspace-user/index.ts
··· 1 - type WorkspaceUser = { 2 - userEmail: string; 3 - userName: string | null; 4 - joinedAt: Date; 5 - status: string; 6 - role: string; 7 - }; 1 + import type { client } from "@kaneo/libs"; 2 + import type { InferResponseType } from "hono/client"; 3 + 4 + export type WorkspaceUser = NonNullable< 5 + InferResponseType<(typeof client)["workspace-user"]["$get"]> 6 + >[number]; 8 7 9 8 export default WorkspaceUser;
+8 -6
apps/web/src/types/workspace/index.ts
··· 1 - export type Workspace = { 2 - id: string; 3 - name: string; 4 - ownerEmail: string; 5 - description: string | null; 6 - }; 1 + import type { client } from "@kaneo/libs"; 2 + import type { InferResponseType } from "hono/client"; 3 + 4 + export type Workspace = InferResponseType< 5 + (typeof client)["workspace"][":id"]["$get"] 6 + >; 7 + 8 + export default Workspace;
+9
apps/web/src/vite-env.d.ts
··· 1 1 /// <reference types="vite/client" /> 2 + /// <reference types="vite/types/importMeta.d.ts" /> 3 + 4 + interface ImportMetaEnv { 5 + readonly KANEO_API_URL: string; 6 + } 7 + 8 + interface ImportMeta { 9 + readonly env: ImportMetaEnv; 10 + }
bun.lockb

This is a binary file and will not be displayed.

+5 -4
charts/kaneo/templates/NOTES.txt
··· 19 19 Make sure your ingress controller supports the configured annotations: 20 20 nginx.ingress.kubernetes.io/rewrite-target: /$1 21 21 {{- else }} 22 + 22 23 To access the application, you need to set up port forwarding to both services: 23 24 24 - $ kubectl port-forward svc/{{ include "kaneo.fullname" . }}-web 5173:{{ .Values.web.service.port }} -n {{ .Release.Namespace }} & 25 - $ kubectl port-forward svc/{{ include "kaneo.fullname" . }}-api 1337:{{ .Values.api.service.port }} -n {{ .Release.Namespace }} & 25 + $ kubectl port-forward svc/{{ include "kaneo.fullname" . }}-web 5173:{{ .Values.web.service.port }} -n {{ .Release.Namespace }} & 26 + $ kubectl port-forward svc/{{ include "kaneo.fullname" . }}-api 1337:{{ .Values.api.service.port }} -n {{ .Release.Namespace }} & 26 27 27 - Then access the application at http://localhost:5173 28 - The web frontend will communicate with the API at http://localhost:1337 28 + Then access the application at http://localhost:5173 29 + The web frontend will communicate with the API at http://localhost:1337 29 30 30 31 Alternatively, you can expose the services using an Ingress by setting .Values.ingress.enabled=true 31 32 {{- end }}
+11 -3
charts/kaneo/templates/deployment.yaml
··· 66 66 imagePullPolicy: {{ .Values.web.image.pullPolicy }} 67 67 ports: 68 68 - name: web 69 - containerPort: {{ .Values.web.service.targetPort }} 69 + containerPort: 5173 70 70 protocol: TCP 71 71 env: 72 72 - name: KANEO_API_URL ··· 80 80 http://localhost:{{ .Values.api.service.targetPort }} 81 81 {{- end -}}" 82 82 livenessProbe: 83 - {{- toYaml .Values.web.livenessProbe | nindent 12 }} 83 + httpGet: 84 + path: / 85 + port: web 86 + initialDelaySeconds: 30 87 + periodSeconds: 10 84 88 readinessProbe: 85 - {{- toYaml .Values.web.readinessProbe | nindent 12 }} 89 + httpGet: 90 + path: / 91 + port: web 92 + initialDelaySeconds: 5 93 + periodSeconds: 10 86 94 resources: 87 95 {{- toYaml .Values.web.resources | nindent 12 }} 88 96
+29
compose.local.yml
··· 1 + services: 2 + api: 3 + build: 4 + context: . 5 + dockerfile: apps/api/Dockerfile 6 + ports: 7 + - "1337:1337" 8 + environment: 9 + - JWT_ACCESS="change-me" 10 + - DB_PATH=/app/apps/api/data/kaneo.db 11 + volumes: 12 + - sqlite_data:/app/apps/api/data 13 + restart: unless-stopped 14 + 15 + web: 16 + build: 17 + context: . 18 + dockerfile: apps/web/Dockerfile 19 + ports: 20 + - "5173:5173" 21 + environment: 22 + - KANEO_API_URL=http://localhost:1337 23 + depends_on: 24 + - api 25 + restart: unless-stopped 26 + 27 + volumes: 28 + sqlite_data: 29 + name: kaneo_sqlite_data
+1 -5
package.json
··· 18 18 "engines": { 19 19 "node": ">=18" 20 20 }, 21 - "packageManager": "bun@1.1.42", 22 - "workspaces": [ 23 - "apps/*", 24 - "packages/*" 25 - ], 21 + "packageManager": "pnpm@10.7.0", 26 22 "version": "0.3.0" 27 23 }
+1 -5
packages/libs/package.json
··· 7 7 "scripts": { 8 8 "lint": " *.ts*" 9 9 }, 10 - "dependencies": { 11 - "@elysiajs/eden": "^1.2.0" 12 - }, 13 10 "devDependencies": { 14 - "@types/bun": "^1.2.0", 15 11 "@types/react": "^19.0.8", 16 12 "@types/react-dom": "^19.0.3", 17 13 "@kaneo/api": "workspace:*", 18 - "elysia": "^1.2.10", 14 + "hono": "^4.7.5", 19 15 "react": "^19.0.0", 20 16 "@kaneo/typescript-config": "workspace:*", 21 17 "typescript": "^5.5.4"
-11
packages/libs/src/eden.ts
··· 1 - import { treaty } from "@elysiajs/eden"; 2 - import type { App } from "@kaneo/api"; 3 - 4 - export const api = treaty<App>( 5 - import.meta.env.VITE_API_URL ?? "http://localhost:1337", 6 - { 7 - fetch: { 8 - credentials: "include", 9 - }, 10 - }, 11 - );
+18
packages/libs/src/hono.ts
··· 1 + import type { AppType } from "@kaneo/api"; 2 + import { hc } from "hono/client"; 3 + 4 + export const client = hc<AppType>( 5 + import.meta.env.VITE_API_URL ?? "http://localhost:1337", 6 + { 7 + fetch: (input: RequestInfo | URL, init?: RequestInit) => { 8 + return fetch(input, { 9 + ...init, 10 + headers: { 11 + ...init?.headers, 12 + "Content-Type": "application/json", 13 + }, 14 + credentials: "include", 15 + }); 16 + }, 17 + }, 18 + );
+1 -1
packages/libs/src/index.ts
··· 1 - export { api } from "./eden"; 1 + export { client } from "./hono";
-1
packages/libs/src/vite-env.d.ts
··· 1 - /// <reference types="vite/client" />
+5562
pnpm-lock.yaml
··· 1 + lockfileVersion: '9.0' 2 + 3 + settings: 4 + autoInstallPeers: true 5 + excludeLinksFromLockfile: false 6 + 7 + importers: 8 + 9 + .: 10 + devDependencies: 11 + '@biomejs/biome': 12 + specifier: 1.9.4 13 + version: 1.9.4 14 + '@commitlint/cli': 15 + specifier: ^19.6.1 16 + version: 19.8.0(@types/node@22.14.1)(typescript@5.5.4) 17 + '@commitlint/config-conventional': 18 + specifier: ^19.6.0 19 + version: 19.8.0 20 + husky: 21 + specifier: ^9.1.7 22 + version: 9.1.7 23 + turbo: 24 + specifier: ^2.4.2 25 + version: 2.4.4 26 + typescript: 27 + specifier: 5.5.4 28 + version: 5.5.4 29 + 30 + apps/api: 31 + dependencies: 32 + '@hono/node-server': 33 + specifier: ^1.14.1 34 + version: 1.14.1(hono@4.7.7) 35 + '@hono/zod-validator': 36 + specifier: ^0.4.3 37 + version: 0.4.3(hono@4.7.7)(zod@3.24.3) 38 + '@oslojs/crypto': 39 + specifier: ^1.0.1 40 + version: 1.0.1 41 + '@oslojs/encoding': 42 + specifier: ^1.1.0 43 + version: 1.1.0 44 + '@paralleldrive/cuid2': 45 + specifier: ^2.2.2 46 + version: 2.2.2 47 + bcrypt: 48 + specifier: ^5.1.1 49 + version: 5.1.1 50 + better-sqlite3: 51 + specifier: ^11.9.1 52 + version: 11.9.1 53 + dotenv: 54 + specifier: ^16.5.0 55 + version: 16.5.0 56 + drizzle-orm: 57 + specifier: ^0.42.0 58 + version: 0.42.0(@types/better-sqlite3@7.6.13)(better-sqlite3@11.9.1)(bun-types@1.2.8) 59 + hono: 60 + specifier: ^4.7.7 61 + version: 4.7.7 62 + zod: 63 + specifier: ^3.24.3 64 + version: 3.24.3 65 + devDependencies: 66 + '@types/bcrypt': 67 + specifier: ^5.0.2 68 + version: 5.0.2 69 + '@types/better-sqlite3': 70 + specifier: ^7.6.13 71 + version: 7.6.13 72 + '@types/node': 73 + specifier: ^22.14.1 74 + version: 22.14.1 75 + esbuild: 76 + specifier: ^0.25.2 77 + version: 0.25.2 78 + tsx: 79 + specifier: ^4.19.3 80 + version: 4.19.3 81 + typescript: 82 + specifier: ^5.8.3 83 + version: 5.8.3 84 + 85 + apps/web: 86 + dependencies: 87 + '@dnd-kit/core': 88 + specifier: ^6.3.1 89 + version: 6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 90 + '@dnd-kit/sortable': 91 + specifier: ^10.0.0 92 + version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) 93 + '@dnd-kit/utilities': 94 + specifier: ^3.2.2 95 + version: 3.2.2(react@19.1.0) 96 + '@hookform/resolvers': 97 + specifier: ^5.0.1 98 + version: 5.0.1(react-hook-form@7.55.0(react@19.1.0)) 99 + '@radix-ui/react-accordion': 100 + specifier: ^1.2.2 101 + version: 1.2.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 102 + '@radix-ui/react-avatar': 103 + specifier: ^1.1.2 104 + version: 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 105 + '@radix-ui/react-dialog': 106 + specifier: ^1.1.5 107 + version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 108 + '@radix-ui/react-dropdown-menu': 109 + specifier: ^2.1.5 110 + version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 111 + '@radix-ui/react-label': 112 + specifier: ^2.1.1 113 + version: 2.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 114 + '@radix-ui/react-popover': 115 + specifier: ^1.1.6 116 + version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 117 + '@radix-ui/react-select': 118 + specifier: ^2.1.6 119 + version: 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 120 + '@radix-ui/react-slot': 121 + specifier: ^1.1.2 122 + version: 1.1.2(@types/react@19.0.12)(react@19.1.0) 123 + '@radix-ui/react-switch': 124 + specifier: ^1.1.3 125 + version: 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 126 + '@radix-ui/react-tooltip': 127 + specifier: ^1.1.7 128 + version: 1.1.8(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 129 + '@tanstack/react-query': 130 + specifier: ^5.64.2 131 + version: 5.70.0(react@19.1.0) 132 + '@tanstack/react-query-devtools': 133 + specifier: ^5.64.2 134 + version: 5.70.0(@tanstack/react-query@5.70.0(react@19.1.0))(react@19.1.0) 135 + '@tanstack/react-router': 136 + specifier: ^1.97.14 137 + version: 1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 138 + '@tanstack/router-devtools': 139 + specifier: ^1.97.14 140 + version: 1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.114.29)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3) 141 + '@tanstack/router-plugin': 142 + specifier: ^1.97.7 143 + version: 1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)) 144 + '@tiptap/extension-highlight': 145 + specifier: ^2.11.5 146 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 147 + '@tiptap/extension-link': 148 + specifier: ^2.11.5 149 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 150 + '@tiptap/extension-placeholder': 151 + specifier: ^2.11.5 152 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 153 + '@tiptap/extension-task-item': 154 + specifier: ^2.11.5 155 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 156 + '@tiptap/extension-task-list': 157 + specifier: ^2.11.5 158 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 159 + '@tiptap/pm': 160 + specifier: ^2.11.5 161 + version: 2.11.6 162 + '@tiptap/react': 163 + specifier: ^2.11.5 164 + version: 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 165 + '@tiptap/starter-kit': 166 + specifier: ^2.11.5 167 + version: 2.11.6 168 + '@vitejs/plugin-react': 169 + specifier: ^4.3.4 170 + version: 4.3.4(vite@6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3)) 171 + babel-plugin-react-compiler: 172 + specifier: ^19.0.0-beta-21e868a-20250216 173 + version: 19.0.0-beta-aeaed83-20250323 174 + class-variance-authority: 175 + specifier: ^0.7.1 176 + version: 0.7.1 177 + clsx: 178 + specifier: ^2.1.1 179 + version: 2.1.1 180 + cmdk: 181 + specifier: ^1.1.1 182 + version: 1.1.1(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 183 + date-fns: 184 + specifier: ^4.1.0 185 + version: 4.1.0 186 + framer-motion: 187 + specifier: ^12.0.1 188 + version: 12.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 189 + hono: 190 + specifier: ^4.7.5 191 + version: 4.7.5 192 + immer: 193 + specifier: ^10.1.1 194 + version: 10.1.1 195 + lucide-react: 196 + specifier: ^0.488.0 197 + version: 0.488.0(react@19.1.0) 198 + react: 199 + specifier: ^19.0.0 200 + version: 19.1.0 201 + react-day-picker: 202 + specifier: 8.10.1 203 + version: 8.10.1(date-fns@4.1.0)(react@19.1.0) 204 + react-dom: 205 + specifier: ^19.0.0 206 + version: 19.1.0(react@19.1.0) 207 + react-hook-form: 208 + specifier: ^7.54.2 209 + version: 7.55.0(react@19.1.0) 210 + react-use-websocket: 211 + specifier: ^4.11.1 212 + version: 4.13.0 213 + sonner: 214 + specifier: ^2.0.1 215 + version: 2.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 216 + tailwind-merge: 217 + specifier: ^3.0.1 218 + version: 3.0.2 219 + tailwindcss-animate: 220 + specifier: ^1.0.7 221 + version: 1.0.7(tailwindcss@4.0.17) 222 + zod: 223 + specifier: 3.24.3 224 + version: 3.24.3 225 + zustand: 226 + specifier: ^5.0.3 227 + version: 5.0.3(@types/react@19.0.12)(immer@10.1.1)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) 228 + devDependencies: 229 + '@kaneo/libs': 230 + specifier: workspace:* 231 + version: link:../../packages/libs 232 + '@tailwindcss/postcss': 233 + specifier: ^4.0.0 234 + version: 4.0.17 235 + '@types/node': 236 + specifier: ^22.10.10 237 + version: 22.13.14 238 + '@types/react': 239 + specifier: ^19.0.8 240 + version: 19.0.12 241 + '@types/react-dom': 242 + specifier: ^19.0.3 243 + version: 19.0.4(@types/react@19.0.12) 244 + globals: 245 + specifier: ^16.0.0 246 + version: 16.0.0 247 + postcss: 248 + specifier: ^8.5.1 249 + version: 8.5.3 250 + tailwindcss: 251 + specifier: ^4.0.0 252 + version: 4.0.17 253 + typescript: 254 + specifier: ~5.8.2 255 + version: 5.8.2 256 + vite: 257 + specifier: ^6.0.11 258 + version: 6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3) 259 + 260 + packages/libs: 261 + devDependencies: 262 + '@kaneo/api': 263 + specifier: workspace:* 264 + version: link:../../apps/api 265 + '@kaneo/typescript-config': 266 + specifier: workspace:* 267 + version: link:../typescript-config 268 + '@types/react': 269 + specifier: ^19.0.8 270 + version: 19.0.12 271 + '@types/react-dom': 272 + specifier: ^19.0.3 273 + version: 19.0.4(@types/react@19.0.12) 274 + hono: 275 + specifier: ^4.7.5 276 + version: 4.7.5 277 + react: 278 + specifier: ^19.0.0 279 + version: 19.1.0 280 + typescript: 281 + specifier: ^5.5.4 282 + version: 5.8.3 283 + 284 + packages/typescript-config: {} 285 + 286 + packages: 287 + 288 + '@alloc/quick-lru@5.2.0': 289 + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 290 + engines: {node: '>=10'} 291 + 292 + '@ampproject/remapping@2.3.0': 293 + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 294 + engines: {node: '>=6.0.0'} 295 + 296 + '@babel/code-frame@7.26.2': 297 + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 298 + engines: {node: '>=6.9.0'} 299 + 300 + '@babel/compat-data@7.26.8': 301 + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} 302 + engines: {node: '>=6.9.0'} 303 + 304 + '@babel/core@7.26.10': 305 + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} 306 + engines: {node: '>=6.9.0'} 307 + 308 + '@babel/generator@7.27.0': 309 + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} 310 + engines: {node: '>=6.9.0'} 311 + 312 + '@babel/helper-compilation-targets@7.27.0': 313 + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} 314 + engines: {node: '>=6.9.0'} 315 + 316 + '@babel/helper-module-imports@7.25.9': 317 + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} 318 + engines: {node: '>=6.9.0'} 319 + 320 + '@babel/helper-module-transforms@7.26.0': 321 + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} 322 + engines: {node: '>=6.9.0'} 323 + peerDependencies: 324 + '@babel/core': ^7.0.0 325 + 326 + '@babel/helper-plugin-utils@7.26.5': 327 + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} 328 + engines: {node: '>=6.9.0'} 329 + 330 + '@babel/helper-string-parser@7.25.9': 331 + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 332 + engines: {node: '>=6.9.0'} 333 + 334 + '@babel/helper-validator-identifier@7.25.9': 335 + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 336 + engines: {node: '>=6.9.0'} 337 + 338 + '@babel/helper-validator-option@7.25.9': 339 + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} 340 + engines: {node: '>=6.9.0'} 341 + 342 + '@babel/helpers@7.27.0': 343 + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} 344 + engines: {node: '>=6.9.0'} 345 + 346 + '@babel/parser@7.27.0': 347 + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} 348 + engines: {node: '>=6.0.0'} 349 + hasBin: true 350 + 351 + '@babel/plugin-syntax-jsx@7.25.9': 352 + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} 353 + engines: {node: '>=6.9.0'} 354 + peerDependencies: 355 + '@babel/core': ^7.0.0-0 356 + 357 + '@babel/plugin-syntax-typescript@7.25.9': 358 + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} 359 + engines: {node: '>=6.9.0'} 360 + peerDependencies: 361 + '@babel/core': ^7.0.0-0 362 + 363 + '@babel/plugin-transform-react-jsx-self@7.25.9': 364 + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} 365 + engines: {node: '>=6.9.0'} 366 + peerDependencies: 367 + '@babel/core': ^7.0.0-0 368 + 369 + '@babel/plugin-transform-react-jsx-source@7.25.9': 370 + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} 371 + engines: {node: '>=6.9.0'} 372 + peerDependencies: 373 + '@babel/core': ^7.0.0-0 374 + 375 + '@babel/template@7.27.0': 376 + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} 377 + engines: {node: '>=6.9.0'} 378 + 379 + '@babel/traverse@7.27.0': 380 + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} 381 + engines: {node: '>=6.9.0'} 382 + 383 + '@babel/types@7.27.0': 384 + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} 385 + engines: {node: '>=6.9.0'} 386 + 387 + '@biomejs/biome@1.9.4': 388 + resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} 389 + engines: {node: '>=14.21.3'} 390 + hasBin: true 391 + 392 + '@biomejs/cli-darwin-arm64@1.9.4': 393 + resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} 394 + engines: {node: '>=14.21.3'} 395 + cpu: [arm64] 396 + os: [darwin] 397 + 398 + '@biomejs/cli-darwin-x64@1.9.4': 399 + resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} 400 + engines: {node: '>=14.21.3'} 401 + cpu: [x64] 402 + os: [darwin] 403 + 404 + '@biomejs/cli-linux-arm64-musl@1.9.4': 405 + resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} 406 + engines: {node: '>=14.21.3'} 407 + cpu: [arm64] 408 + os: [linux] 409 + 410 + '@biomejs/cli-linux-arm64@1.9.4': 411 + resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} 412 + engines: {node: '>=14.21.3'} 413 + cpu: [arm64] 414 + os: [linux] 415 + 416 + '@biomejs/cli-linux-x64-musl@1.9.4': 417 + resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} 418 + engines: {node: '>=14.21.3'} 419 + cpu: [x64] 420 + os: [linux] 421 + 422 + '@biomejs/cli-linux-x64@1.9.4': 423 + resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} 424 + engines: {node: '>=14.21.3'} 425 + cpu: [x64] 426 + os: [linux] 427 + 428 + '@biomejs/cli-win32-arm64@1.9.4': 429 + resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} 430 + engines: {node: '>=14.21.3'} 431 + cpu: [arm64] 432 + os: [win32] 433 + 434 + '@biomejs/cli-win32-x64@1.9.4': 435 + resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} 436 + engines: {node: '>=14.21.3'} 437 + cpu: [x64] 438 + os: [win32] 439 + 440 + '@commitlint/cli@19.8.0': 441 + resolution: {integrity: sha512-t/fCrLVu+Ru01h0DtlgHZXbHV2Y8gKocTR5elDOqIRUzQd0/6hpt2VIWOj9b3NDo7y4/gfxeR2zRtXq/qO6iUg==} 442 + engines: {node: '>=v18'} 443 + hasBin: true 444 + 445 + '@commitlint/config-conventional@19.8.0': 446 + resolution: {integrity: sha512-9I2kKJwcAPwMoAj38hwqFXG0CzS2Kj+SAByPUQ0SlHTfb7VUhYVmo7G2w2tBrqmOf7PFd6MpZ/a1GQJo8na8kw==} 447 + engines: {node: '>=v18'} 448 + 449 + '@commitlint/config-validator@19.8.0': 450 + resolution: {integrity: sha512-+r5ZvD/0hQC3w5VOHJhGcCooiAVdynFlCe2d6I9dU+PvXdV3O+fU4vipVg+6hyLbQUuCH82mz3HnT/cBQTYYuA==} 451 + engines: {node: '>=v18'} 452 + 453 + '@commitlint/ensure@19.8.0': 454 + resolution: {integrity: sha512-kNiNU4/bhEQ/wutI1tp1pVW1mQ0QbAjfPRo5v8SaxoVV+ARhkB8Wjg3BSseNYECPzWWfg/WDqQGIfV1RaBFQZg==} 455 + engines: {node: '>=v18'} 456 + 457 + '@commitlint/execute-rule@19.8.0': 458 + resolution: {integrity: sha512-fuLeI+EZ9x2v/+TXKAjplBJWI9CNrHnyi5nvUQGQt4WRkww/d95oVRsc9ajpt4xFrFmqMZkd/xBQHZDvALIY7A==} 459 + engines: {node: '>=v18'} 460 + 461 + '@commitlint/format@19.8.0': 462 + resolution: {integrity: sha512-EOpA8IERpQstxwp/WGnDArA7S+wlZDeTeKi98WMOvaDLKbjptuHWdOYYr790iO7kTCif/z971PKPI2PkWMfOxg==} 463 + engines: {node: '>=v18'} 464 + 465 + '@commitlint/is-ignored@19.8.0': 466 + resolution: {integrity: sha512-L2Jv9yUg/I+jF3zikOV0rdiHUul9X3a/oU5HIXhAJLE2+TXTnEBfqYP9G5yMw/Yb40SnR764g4fyDK6WR2xtpw==} 467 + engines: {node: '>=v18'} 468 + 469 + '@commitlint/lint@19.8.0': 470 + resolution: {integrity: sha512-+/NZKyWKSf39FeNpqhfMebmaLa1P90i1Nrb1SrA7oSU5GNN/lksA4z6+ZTnsft01YfhRZSYMbgGsARXvkr/VLQ==} 471 + engines: {node: '>=v18'} 472 + 473 + '@commitlint/load@19.8.0': 474 + resolution: {integrity: sha512-4rvmm3ff81Sfb+mcWT5WKlyOa+Hd33WSbirTVUer0wjS1Hv/Hzr07Uv1ULIV9DkimZKNyOwXn593c+h8lsDQPQ==} 475 + engines: {node: '>=v18'} 476 + 477 + '@commitlint/message@19.8.0': 478 + resolution: {integrity: sha512-qs/5Vi9bYjf+ZV40bvdCyBn5DvbuelhR6qewLE8Bh476F7KnNyLfdM/ETJ4cp96WgeeHo6tesA2TMXS0sh5X4A==} 479 + engines: {node: '>=v18'} 480 + 481 + '@commitlint/parse@19.8.0': 482 + resolution: {integrity: sha512-YNIKAc4EXvNeAvyeEnzgvm1VyAe0/b3Wax7pjJSwXuhqIQ1/t2hD3OYRXb6D5/GffIvaX82RbjD+nWtMZCLL7Q==} 483 + engines: {node: '>=v18'} 484 + 485 + '@commitlint/read@19.8.0': 486 + resolution: {integrity: sha512-6ywxOGYajcxK1y1MfzrOnwsXO6nnErna88gRWEl3qqOOP8MDu/DTeRkGLXBFIZuRZ7mm5yyxU5BmeUvMpNte5w==} 487 + engines: {node: '>=v18'} 488 + 489 + '@commitlint/resolve-extends@19.8.0': 490 + resolution: {integrity: sha512-CLanRQwuG2LPfFVvrkTrBR/L/DMy3+ETsgBqW1OvRxmzp/bbVJW0Xw23LnnExgYcsaFtos967lul1CsbsnJlzQ==} 491 + engines: {node: '>=v18'} 492 + 493 + '@commitlint/rules@19.8.0': 494 + resolution: {integrity: sha512-IZ5IE90h6DSWNuNK/cwjABLAKdy8tP8OgGVGbXe1noBEX5hSsu00uRlLu6JuruiXjWJz2dZc+YSw3H0UZyl/mA==} 495 + engines: {node: '>=v18'} 496 + 497 + '@commitlint/to-lines@19.8.0': 498 + resolution: {integrity: sha512-3CKLUw41Cur8VMjh16y8LcsOaKbmQjAKCWlXx6B0vOUREplp6em9uIVhI8Cv934qiwkbi2+uv+mVZPnXJi1o9A==} 499 + engines: {node: '>=v18'} 500 + 501 + '@commitlint/top-level@19.8.0': 502 + resolution: {integrity: sha512-Rphgoc/omYZisoNkcfaBRPQr4myZEHhLPx2/vTXNLjiCw4RgfPR1wEgUpJ9OOmDCiv5ZyIExhprNLhteqH4FuQ==} 503 + engines: {node: '>=v18'} 504 + 505 + '@commitlint/types@19.8.0': 506 + resolution: {integrity: sha512-LRjP623jPyf3Poyfb0ohMj8I3ORyBDOwXAgxxVPbSD0unJuW2mJWeiRfaQinjtccMqC5Wy1HOMfa4btKjbNxbg==} 507 + engines: {node: '>=v18'} 508 + 509 + '@dnd-kit/accessibility@3.1.1': 510 + resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} 511 + peerDependencies: 512 + react: '>=16.8.0' 513 + 514 + '@dnd-kit/core@6.3.1': 515 + resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} 516 + peerDependencies: 517 + react: '>=16.8.0' 518 + react-dom: '>=16.8.0' 519 + 520 + '@dnd-kit/sortable@10.0.0': 521 + resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==} 522 + peerDependencies: 523 + '@dnd-kit/core': ^6.3.0 524 + react: '>=16.8.0' 525 + 526 + '@dnd-kit/utilities@3.2.2': 527 + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} 528 + peerDependencies: 529 + react: '>=16.8.0' 530 + 531 + '@esbuild/aix-ppc64@0.25.2': 532 + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} 533 + engines: {node: '>=18'} 534 + cpu: [ppc64] 535 + os: [aix] 536 + 537 + '@esbuild/android-arm64@0.25.2': 538 + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} 539 + engines: {node: '>=18'} 540 + cpu: [arm64] 541 + os: [android] 542 + 543 + '@esbuild/android-arm@0.25.2': 544 + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} 545 + engines: {node: '>=18'} 546 + cpu: [arm] 547 + os: [android] 548 + 549 + '@esbuild/android-x64@0.25.2': 550 + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} 551 + engines: {node: '>=18'} 552 + cpu: [x64] 553 + os: [android] 554 + 555 + '@esbuild/darwin-arm64@0.25.2': 556 + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} 557 + engines: {node: '>=18'} 558 + cpu: [arm64] 559 + os: [darwin] 560 + 561 + '@esbuild/darwin-x64@0.25.2': 562 + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} 563 + engines: {node: '>=18'} 564 + cpu: [x64] 565 + os: [darwin] 566 + 567 + '@esbuild/freebsd-arm64@0.25.2': 568 + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} 569 + engines: {node: '>=18'} 570 + cpu: [arm64] 571 + os: [freebsd] 572 + 573 + '@esbuild/freebsd-x64@0.25.2': 574 + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} 575 + engines: {node: '>=18'} 576 + cpu: [x64] 577 + os: [freebsd] 578 + 579 + '@esbuild/linux-arm64@0.25.2': 580 + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} 581 + engines: {node: '>=18'} 582 + cpu: [arm64] 583 + os: [linux] 584 + 585 + '@esbuild/linux-arm@0.25.2': 586 + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} 587 + engines: {node: '>=18'} 588 + cpu: [arm] 589 + os: [linux] 590 + 591 + '@esbuild/linux-ia32@0.25.2': 592 + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} 593 + engines: {node: '>=18'} 594 + cpu: [ia32] 595 + os: [linux] 596 + 597 + '@esbuild/linux-loong64@0.25.2': 598 + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} 599 + engines: {node: '>=18'} 600 + cpu: [loong64] 601 + os: [linux] 602 + 603 + '@esbuild/linux-mips64el@0.25.2': 604 + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} 605 + engines: {node: '>=18'} 606 + cpu: [mips64el] 607 + os: [linux] 608 + 609 + '@esbuild/linux-ppc64@0.25.2': 610 + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} 611 + engines: {node: '>=18'} 612 + cpu: [ppc64] 613 + os: [linux] 614 + 615 + '@esbuild/linux-riscv64@0.25.2': 616 + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} 617 + engines: {node: '>=18'} 618 + cpu: [riscv64] 619 + os: [linux] 620 + 621 + '@esbuild/linux-s390x@0.25.2': 622 + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} 623 + engines: {node: '>=18'} 624 + cpu: [s390x] 625 + os: [linux] 626 + 627 + '@esbuild/linux-x64@0.25.2': 628 + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} 629 + engines: {node: '>=18'} 630 + cpu: [x64] 631 + os: [linux] 632 + 633 + '@esbuild/netbsd-arm64@0.25.2': 634 + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} 635 + engines: {node: '>=18'} 636 + cpu: [arm64] 637 + os: [netbsd] 638 + 639 + '@esbuild/netbsd-x64@0.25.2': 640 + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} 641 + engines: {node: '>=18'} 642 + cpu: [x64] 643 + os: [netbsd] 644 + 645 + '@esbuild/openbsd-arm64@0.25.2': 646 + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} 647 + engines: {node: '>=18'} 648 + cpu: [arm64] 649 + os: [openbsd] 650 + 651 + '@esbuild/openbsd-x64@0.25.2': 652 + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} 653 + engines: {node: '>=18'} 654 + cpu: [x64] 655 + os: [openbsd] 656 + 657 + '@esbuild/sunos-x64@0.25.2': 658 + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} 659 + engines: {node: '>=18'} 660 + cpu: [x64] 661 + os: [sunos] 662 + 663 + '@esbuild/win32-arm64@0.25.2': 664 + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} 665 + engines: {node: '>=18'} 666 + cpu: [arm64] 667 + os: [win32] 668 + 669 + '@esbuild/win32-ia32@0.25.2': 670 + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} 671 + engines: {node: '>=18'} 672 + cpu: [ia32] 673 + os: [win32] 674 + 675 + '@esbuild/win32-x64@0.25.2': 676 + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} 677 + engines: {node: '>=18'} 678 + cpu: [x64] 679 + os: [win32] 680 + 681 + '@floating-ui/core@1.6.9': 682 + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} 683 + 684 + '@floating-ui/dom@1.6.13': 685 + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} 686 + 687 + '@floating-ui/react-dom@2.1.2': 688 + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} 689 + peerDependencies: 690 + react: '>=16.8.0' 691 + react-dom: '>=16.8.0' 692 + 693 + '@floating-ui/utils@0.2.9': 694 + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} 695 + 696 + '@hono/node-server@1.14.1': 697 + resolution: {integrity: sha512-vmbuM+HPinjWzPe7FFPWMMQMsbKE9gDPhaH0FFdqbGpkT5lp++tcWDTxwBl5EgS5y6JVgIaCdjeHRfQ4XRBRjQ==} 698 + engines: {node: '>=18.14.1'} 699 + peerDependencies: 700 + hono: ^4 701 + 702 + '@hono/zod-validator@0.4.3': 703 + resolution: {integrity: sha512-xIgMYXDyJ4Hj6ekm9T9Y27s080Nl9NXHcJkOvkXPhubOLj8hZkOL8pDnnXfvCf5xEE8Q4oMFenQUZZREUY2gqQ==} 704 + peerDependencies: 705 + hono: '>=3.9.0' 706 + zod: ^3.19.1 707 + 708 + '@hookform/resolvers@5.0.1': 709 + resolution: {integrity: sha512-u/+Jp83luQNx9AdyW2fIPGY6Y7NG68eN2ZW8FOJYL+M0i4s49+refdJdOp/A9n9HFQtQs3HIDHQvX3ZET2o7YA==} 710 + peerDependencies: 711 + react-hook-form: ^7.55.0 712 + 713 + '@jridgewell/gen-mapping@0.3.8': 714 + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 715 + engines: {node: '>=6.0.0'} 716 + 717 + '@jridgewell/resolve-uri@3.1.2': 718 + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 719 + engines: {node: '>=6.0.0'} 720 + 721 + '@jridgewell/set-array@1.2.1': 722 + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 723 + engines: {node: '>=6.0.0'} 724 + 725 + '@jridgewell/sourcemap-codec@1.5.0': 726 + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 727 + 728 + '@jridgewell/trace-mapping@0.3.25': 729 + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 730 + 731 + '@mapbox/node-pre-gyp@1.0.11': 732 + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} 733 + hasBin: true 734 + 735 + '@noble/hashes@1.7.1': 736 + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} 737 + engines: {node: ^14.21.3 || >=16} 738 + 739 + '@oslojs/asn1@1.0.0': 740 + resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==} 741 + 742 + '@oslojs/binary@1.0.0': 743 + resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==} 744 + 745 + '@oslojs/crypto@1.0.1': 746 + resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==} 747 + 748 + '@oslojs/encoding@1.1.0': 749 + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} 750 + 751 + '@paralleldrive/cuid2@2.2.2': 752 + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} 753 + 754 + '@popperjs/core@2.11.8': 755 + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} 756 + 757 + '@radix-ui/number@1.1.0': 758 + resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} 759 + 760 + '@radix-ui/primitive@1.1.1': 761 + resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} 762 + 763 + '@radix-ui/react-accordion@1.2.3': 764 + resolution: {integrity: sha512-RIQ15mrcvqIkDARJeERSuXSry2N8uYnxkdDetpfmalT/+0ntOXLkFOsh9iwlAsCv+qcmhZjbdJogIm6WBa6c4A==} 765 + peerDependencies: 766 + '@types/react': '*' 767 + '@types/react-dom': '*' 768 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 769 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 770 + peerDependenciesMeta: 771 + '@types/react': 772 + optional: true 773 + '@types/react-dom': 774 + optional: true 775 + 776 + '@radix-ui/react-arrow@1.1.2': 777 + resolution: {integrity: sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==} 778 + peerDependencies: 779 + '@types/react': '*' 780 + '@types/react-dom': '*' 781 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 782 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 783 + peerDependenciesMeta: 784 + '@types/react': 785 + optional: true 786 + '@types/react-dom': 787 + optional: true 788 + 789 + '@radix-ui/react-avatar@1.1.3': 790 + resolution: {integrity: sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==} 791 + peerDependencies: 792 + '@types/react': '*' 793 + '@types/react-dom': '*' 794 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 795 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 796 + peerDependenciesMeta: 797 + '@types/react': 798 + optional: true 799 + '@types/react-dom': 800 + optional: true 801 + 802 + '@radix-ui/react-collapsible@1.1.3': 803 + resolution: {integrity: sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw==} 804 + peerDependencies: 805 + '@types/react': '*' 806 + '@types/react-dom': '*' 807 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 808 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 809 + peerDependenciesMeta: 810 + '@types/react': 811 + optional: true 812 + '@types/react-dom': 813 + optional: true 814 + 815 + '@radix-ui/react-collection@1.1.2': 816 + resolution: {integrity: sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==} 817 + peerDependencies: 818 + '@types/react': '*' 819 + '@types/react-dom': '*' 820 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 821 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 822 + peerDependenciesMeta: 823 + '@types/react': 824 + optional: true 825 + '@types/react-dom': 826 + optional: true 827 + 828 + '@radix-ui/react-compose-refs@1.1.1': 829 + resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} 830 + peerDependencies: 831 + '@types/react': '*' 832 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 833 + peerDependenciesMeta: 834 + '@types/react': 835 + optional: true 836 + 837 + '@radix-ui/react-context@1.1.1': 838 + resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} 839 + peerDependencies: 840 + '@types/react': '*' 841 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 842 + peerDependenciesMeta: 843 + '@types/react': 844 + optional: true 845 + 846 + '@radix-ui/react-dialog@1.1.6': 847 + resolution: {integrity: sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==} 848 + peerDependencies: 849 + '@types/react': '*' 850 + '@types/react-dom': '*' 851 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 852 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 853 + peerDependenciesMeta: 854 + '@types/react': 855 + optional: true 856 + '@types/react-dom': 857 + optional: true 858 + 859 + '@radix-ui/react-direction@1.1.0': 860 + resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} 861 + peerDependencies: 862 + '@types/react': '*' 863 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 864 + peerDependenciesMeta: 865 + '@types/react': 866 + optional: true 867 + 868 + '@radix-ui/react-dismissable-layer@1.1.5': 869 + resolution: {integrity: sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==} 870 + peerDependencies: 871 + '@types/react': '*' 872 + '@types/react-dom': '*' 873 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 874 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 875 + peerDependenciesMeta: 876 + '@types/react': 877 + optional: true 878 + '@types/react-dom': 879 + optional: true 880 + 881 + '@radix-ui/react-dropdown-menu@2.1.6': 882 + resolution: {integrity: sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==} 883 + peerDependencies: 884 + '@types/react': '*' 885 + '@types/react-dom': '*' 886 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 887 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 888 + peerDependenciesMeta: 889 + '@types/react': 890 + optional: true 891 + '@types/react-dom': 892 + optional: true 893 + 894 + '@radix-ui/react-focus-guards@1.1.1': 895 + resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} 896 + peerDependencies: 897 + '@types/react': '*' 898 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 899 + peerDependenciesMeta: 900 + '@types/react': 901 + optional: true 902 + 903 + '@radix-ui/react-focus-scope@1.1.2': 904 + resolution: {integrity: sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==} 905 + peerDependencies: 906 + '@types/react': '*' 907 + '@types/react-dom': '*' 908 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 909 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 910 + peerDependenciesMeta: 911 + '@types/react': 912 + optional: true 913 + '@types/react-dom': 914 + optional: true 915 + 916 + '@radix-ui/react-id@1.1.0': 917 + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} 918 + peerDependencies: 919 + '@types/react': '*' 920 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 921 + peerDependenciesMeta: 922 + '@types/react': 923 + optional: true 924 + 925 + '@radix-ui/react-label@2.1.2': 926 + resolution: {integrity: sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==} 927 + peerDependencies: 928 + '@types/react': '*' 929 + '@types/react-dom': '*' 930 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 931 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 932 + peerDependenciesMeta: 933 + '@types/react': 934 + optional: true 935 + '@types/react-dom': 936 + optional: true 937 + 938 + '@radix-ui/react-menu@2.1.6': 939 + resolution: {integrity: sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==} 940 + peerDependencies: 941 + '@types/react': '*' 942 + '@types/react-dom': '*' 943 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 944 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 945 + peerDependenciesMeta: 946 + '@types/react': 947 + optional: true 948 + '@types/react-dom': 949 + optional: true 950 + 951 + '@radix-ui/react-popover@1.1.6': 952 + resolution: {integrity: sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg==} 953 + peerDependencies: 954 + '@types/react': '*' 955 + '@types/react-dom': '*' 956 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 957 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 958 + peerDependenciesMeta: 959 + '@types/react': 960 + optional: true 961 + '@types/react-dom': 962 + optional: true 963 + 964 + '@radix-ui/react-popper@1.2.2': 965 + resolution: {integrity: sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==} 966 + peerDependencies: 967 + '@types/react': '*' 968 + '@types/react-dom': '*' 969 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 970 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 971 + peerDependenciesMeta: 972 + '@types/react': 973 + optional: true 974 + '@types/react-dom': 975 + optional: true 976 + 977 + '@radix-ui/react-portal@1.1.4': 978 + resolution: {integrity: sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==} 979 + peerDependencies: 980 + '@types/react': '*' 981 + '@types/react-dom': '*' 982 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 983 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 984 + peerDependenciesMeta: 985 + '@types/react': 986 + optional: true 987 + '@types/react-dom': 988 + optional: true 989 + 990 + '@radix-ui/react-presence@1.1.2': 991 + resolution: {integrity: sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==} 992 + peerDependencies: 993 + '@types/react': '*' 994 + '@types/react-dom': '*' 995 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 996 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 997 + peerDependenciesMeta: 998 + '@types/react': 999 + optional: true 1000 + '@types/react-dom': 1001 + optional: true 1002 + 1003 + '@radix-ui/react-primitive@2.0.2': 1004 + resolution: {integrity: sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==} 1005 + peerDependencies: 1006 + '@types/react': '*' 1007 + '@types/react-dom': '*' 1008 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1009 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1010 + peerDependenciesMeta: 1011 + '@types/react': 1012 + optional: true 1013 + '@types/react-dom': 1014 + optional: true 1015 + 1016 + '@radix-ui/react-roving-focus@1.1.2': 1017 + resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==} 1018 + peerDependencies: 1019 + '@types/react': '*' 1020 + '@types/react-dom': '*' 1021 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1022 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1023 + peerDependenciesMeta: 1024 + '@types/react': 1025 + optional: true 1026 + '@types/react-dom': 1027 + optional: true 1028 + 1029 + '@radix-ui/react-select@2.1.6': 1030 + resolution: {integrity: sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==} 1031 + peerDependencies: 1032 + '@types/react': '*' 1033 + '@types/react-dom': '*' 1034 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1035 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1036 + peerDependenciesMeta: 1037 + '@types/react': 1038 + optional: true 1039 + '@types/react-dom': 1040 + optional: true 1041 + 1042 + '@radix-ui/react-slot@1.1.2': 1043 + resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==} 1044 + peerDependencies: 1045 + '@types/react': '*' 1046 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1047 + peerDependenciesMeta: 1048 + '@types/react': 1049 + optional: true 1050 + 1051 + '@radix-ui/react-switch@1.1.3': 1052 + resolution: {integrity: sha512-1nc+vjEOQkJVsJtWPSiISGT6OKm4SiOdjMo+/icLxo2G4vxz1GntC5MzfL4v8ey9OEfw787QCD1y3mUv0NiFEQ==} 1053 + peerDependencies: 1054 + '@types/react': '*' 1055 + '@types/react-dom': '*' 1056 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1057 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1058 + peerDependenciesMeta: 1059 + '@types/react': 1060 + optional: true 1061 + '@types/react-dom': 1062 + optional: true 1063 + 1064 + '@radix-ui/react-tooltip@1.1.8': 1065 + resolution: {integrity: sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==} 1066 + peerDependencies: 1067 + '@types/react': '*' 1068 + '@types/react-dom': '*' 1069 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1070 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1071 + peerDependenciesMeta: 1072 + '@types/react': 1073 + optional: true 1074 + '@types/react-dom': 1075 + optional: true 1076 + 1077 + '@radix-ui/react-use-callback-ref@1.1.0': 1078 + resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} 1079 + peerDependencies: 1080 + '@types/react': '*' 1081 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1082 + peerDependenciesMeta: 1083 + '@types/react': 1084 + optional: true 1085 + 1086 + '@radix-ui/react-use-controllable-state@1.1.0': 1087 + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} 1088 + peerDependencies: 1089 + '@types/react': '*' 1090 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1091 + peerDependenciesMeta: 1092 + '@types/react': 1093 + optional: true 1094 + 1095 + '@radix-ui/react-use-escape-keydown@1.1.0': 1096 + resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} 1097 + peerDependencies: 1098 + '@types/react': '*' 1099 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1100 + peerDependenciesMeta: 1101 + '@types/react': 1102 + optional: true 1103 + 1104 + '@radix-ui/react-use-layout-effect@1.1.0': 1105 + resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} 1106 + peerDependencies: 1107 + '@types/react': '*' 1108 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1109 + peerDependenciesMeta: 1110 + '@types/react': 1111 + optional: true 1112 + 1113 + '@radix-ui/react-use-previous@1.1.0': 1114 + resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==} 1115 + peerDependencies: 1116 + '@types/react': '*' 1117 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1118 + peerDependenciesMeta: 1119 + '@types/react': 1120 + optional: true 1121 + 1122 + '@radix-ui/react-use-rect@1.1.0': 1123 + resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==} 1124 + peerDependencies: 1125 + '@types/react': '*' 1126 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1127 + peerDependenciesMeta: 1128 + '@types/react': 1129 + optional: true 1130 + 1131 + '@radix-ui/react-use-size@1.1.0': 1132 + resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} 1133 + peerDependencies: 1134 + '@types/react': '*' 1135 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1136 + peerDependenciesMeta: 1137 + '@types/react': 1138 + optional: true 1139 + 1140 + '@radix-ui/react-visually-hidden@1.1.2': 1141 + resolution: {integrity: sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==} 1142 + peerDependencies: 1143 + '@types/react': '*' 1144 + '@types/react-dom': '*' 1145 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1146 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 1147 + peerDependenciesMeta: 1148 + '@types/react': 1149 + optional: true 1150 + '@types/react-dom': 1151 + optional: true 1152 + 1153 + '@radix-ui/rect@1.1.0': 1154 + resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} 1155 + 1156 + '@remirror/core-constants@3.0.0': 1157 + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} 1158 + 1159 + '@rollup/rollup-android-arm-eabi@4.38.0': 1160 + resolution: {integrity: sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==} 1161 + cpu: [arm] 1162 + os: [android] 1163 + 1164 + '@rollup/rollup-android-arm64@4.38.0': 1165 + resolution: {integrity: sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==} 1166 + cpu: [arm64] 1167 + os: [android] 1168 + 1169 + '@rollup/rollup-darwin-arm64@4.38.0': 1170 + resolution: {integrity: sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==} 1171 + cpu: [arm64] 1172 + os: [darwin] 1173 + 1174 + '@rollup/rollup-darwin-x64@4.38.0': 1175 + resolution: {integrity: sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==} 1176 + cpu: [x64] 1177 + os: [darwin] 1178 + 1179 + '@rollup/rollup-freebsd-arm64@4.38.0': 1180 + resolution: {integrity: sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==} 1181 + cpu: [arm64] 1182 + os: [freebsd] 1183 + 1184 + '@rollup/rollup-freebsd-x64@4.38.0': 1185 + resolution: {integrity: sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==} 1186 + cpu: [x64] 1187 + os: [freebsd] 1188 + 1189 + '@rollup/rollup-linux-arm-gnueabihf@4.38.0': 1190 + resolution: {integrity: sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==} 1191 + cpu: [arm] 1192 + os: [linux] 1193 + 1194 + '@rollup/rollup-linux-arm-musleabihf@4.38.0': 1195 + resolution: {integrity: sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==} 1196 + cpu: [arm] 1197 + os: [linux] 1198 + 1199 + '@rollup/rollup-linux-arm64-gnu@4.38.0': 1200 + resolution: {integrity: sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==} 1201 + cpu: [arm64] 1202 + os: [linux] 1203 + 1204 + '@rollup/rollup-linux-arm64-musl@4.38.0': 1205 + resolution: {integrity: sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==} 1206 + cpu: [arm64] 1207 + os: [linux] 1208 + 1209 + '@rollup/rollup-linux-loongarch64-gnu@4.38.0': 1210 + resolution: {integrity: sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==} 1211 + cpu: [loong64] 1212 + os: [linux] 1213 + 1214 + '@rollup/rollup-linux-powerpc64le-gnu@4.38.0': 1215 + resolution: {integrity: sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==} 1216 + cpu: [ppc64] 1217 + os: [linux] 1218 + 1219 + '@rollup/rollup-linux-riscv64-gnu@4.38.0': 1220 + resolution: {integrity: sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==} 1221 + cpu: [riscv64] 1222 + os: [linux] 1223 + 1224 + '@rollup/rollup-linux-riscv64-musl@4.38.0': 1225 + resolution: {integrity: sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==} 1226 + cpu: [riscv64] 1227 + os: [linux] 1228 + 1229 + '@rollup/rollup-linux-s390x-gnu@4.38.0': 1230 + resolution: {integrity: sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==} 1231 + cpu: [s390x] 1232 + os: [linux] 1233 + 1234 + '@rollup/rollup-linux-x64-gnu@4.38.0': 1235 + resolution: {integrity: sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==} 1236 + cpu: [x64] 1237 + os: [linux] 1238 + 1239 + '@rollup/rollup-linux-x64-musl@4.38.0': 1240 + resolution: {integrity: sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==} 1241 + cpu: [x64] 1242 + os: [linux] 1243 + 1244 + '@rollup/rollup-win32-arm64-msvc@4.38.0': 1245 + resolution: {integrity: sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==} 1246 + cpu: [arm64] 1247 + os: [win32] 1248 + 1249 + '@rollup/rollup-win32-ia32-msvc@4.38.0': 1250 + resolution: {integrity: sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==} 1251 + cpu: [ia32] 1252 + os: [win32] 1253 + 1254 + '@rollup/rollup-win32-x64-msvc@4.38.0': 1255 + resolution: {integrity: sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==} 1256 + cpu: [x64] 1257 + os: [win32] 1258 + 1259 + '@standard-schema/utils@0.3.0': 1260 + resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} 1261 + 1262 + '@tailwindcss/node@4.0.17': 1263 + resolution: {integrity: sha512-LIdNwcqyY7578VpofXyqjH6f+3fP4nrz7FBLki5HpzqjYfXdF2m/eW18ZfoKePtDGg90Bvvfpov9d2gy5XVCbg==} 1264 + 1265 + '@tailwindcss/oxide-android-arm64@4.0.17': 1266 + resolution: {integrity: sha512-3RfO0ZK64WAhop+EbHeyxGThyDr/fYhxPzDbEQjD2+v7ZhKTb2svTWy+KK+J1PHATus2/CQGAGp7pHY/8M8ugg==} 1267 + engines: {node: '>= 10'} 1268 + cpu: [arm64] 1269 + os: [android] 1270 + 1271 + '@tailwindcss/oxide-darwin-arm64@4.0.17': 1272 + resolution: {integrity: sha512-e1uayxFQCCDuzTk9s8q7MC5jFN42IY7nzcr5n0Mw/AcUHwD6JaBkXnATkD924ZsHyPDvddnusIEvkgLd2CiREg==} 1273 + engines: {node: '>= 10'} 1274 + cpu: [arm64] 1275 + os: [darwin] 1276 + 1277 + '@tailwindcss/oxide-darwin-x64@4.0.17': 1278 + resolution: {integrity: sha512-d6z7HSdOKfXQ0HPlVx1jduUf/YtBuCCtEDIEFeBCzgRRtDsUuRtofPqxIVaSCUTOk5+OfRLonje6n9dF6AH8wQ==} 1279 + engines: {node: '>= 10'} 1280 + cpu: [x64] 1281 + os: [darwin] 1282 + 1283 + '@tailwindcss/oxide-freebsd-x64@4.0.17': 1284 + resolution: {integrity: sha512-EjrVa6lx3wzXz3l5MsdOGtYIsRjgs5Mru6lDv4RuiXpguWeOb3UzGJ7vw7PEzcFadKNvNslEQqoAABeMezprxQ==} 1285 + engines: {node: '>= 10'} 1286 + cpu: [x64] 1287 + os: [freebsd] 1288 + 1289 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17': 1290 + resolution: {integrity: sha512-65zXfCOdi8wuaY0Ye6qMR5LAXokHYtrGvo9t/NmxvSZtCCitXV/gzJ/WP5ksXPhff1SV5rov0S+ZIZU+/4eyCQ==} 1291 + engines: {node: '>= 10'} 1292 + cpu: [arm] 1293 + os: [linux] 1294 + 1295 + '@tailwindcss/oxide-linux-arm64-gnu@4.0.17': 1296 + resolution: {integrity: sha512-+aaq6hJ8ioTdbJV5IA1WjWgLmun4T7eYLTvJIToiXLHy5JzUERRbIZjAcjgK9qXMwnvuu7rqpxzej+hGoEcG5g==} 1297 + engines: {node: '>= 10'} 1298 + cpu: [arm64] 1299 + os: [linux] 1300 + 1301 + '@tailwindcss/oxide-linux-arm64-musl@4.0.17': 1302 + resolution: {integrity: sha512-/FhWgZCdUGAeYHYnZKekiOC0aXFiBIoNCA0bwzkICiMYS5Rtx2KxFfMUXQVnl4uZRblG5ypt5vpPhVaXgGk80w==} 1303 + engines: {node: '>= 10'} 1304 + cpu: [arm64] 1305 + os: [linux] 1306 + 1307 + '@tailwindcss/oxide-linux-x64-gnu@4.0.17': 1308 + resolution: {integrity: sha512-gELJzOHK6GDoIpm/539Golvk+QWZjxQcbkKq9eB2kzNkOvrP0xc5UPgO9bIMNt1M48mO8ZeNenCMGt6tfkvVBg==} 1309 + engines: {node: '>= 10'} 1310 + cpu: [x64] 1311 + os: [linux] 1312 + 1313 + '@tailwindcss/oxide-linux-x64-musl@4.0.17': 1314 + resolution: {integrity: sha512-68NwxcJrZn94IOW4TysMIbYv5AlM6So1luTlbYUDIGnKma1yTFGBRNEJ+SacJ3PZE2rgcTBNRHX1TB4EQ/XEHw==} 1315 + engines: {node: '>= 10'} 1316 + cpu: [x64] 1317 + os: [linux] 1318 + 1319 + '@tailwindcss/oxide-win32-arm64-msvc@4.0.17': 1320 + resolution: {integrity: sha512-AkBO8efP2/7wkEXkNlXzRD4f/7WerqKHlc6PWb5v0jGbbm22DFBLbIM19IJQ3b+tNewQZa+WnPOaGm0SmwMNjw==} 1321 + engines: {node: '>= 10'} 1322 + cpu: [arm64] 1323 + os: [win32] 1324 + 1325 + '@tailwindcss/oxide-win32-x64-msvc@4.0.17': 1326 + resolution: {integrity: sha512-7/DTEvXcoWlqX0dAlcN0zlmcEu9xSermuo7VNGX9tJ3nYMdo735SHvbrHDln1+LYfF6NhJ3hjbpbjkMOAGmkDg==} 1327 + engines: {node: '>= 10'} 1328 + cpu: [x64] 1329 + os: [win32] 1330 + 1331 + '@tailwindcss/oxide@4.0.17': 1332 + resolution: {integrity: sha512-B4OaUIRD2uVrULpAD1Yksx2+wNarQr2rQh65nXqaqbLY1jCd8fO+3KLh/+TH4Hzh2NTHQvgxVbPdUDOtLk7vAw==} 1333 + engines: {node: '>= 10'} 1334 + 1335 + '@tailwindcss/postcss@4.0.17': 1336 + resolution: {integrity: sha512-qeJbRTB5FMZXmuJF+eePd235EGY6IyJZF0Bh0YM6uMcCI4L9Z7dy+lPuLAhxOJzxnajsbjPoDAKOuAqZRtf1PQ==} 1337 + 1338 + '@tanstack/history@1.114.29': 1339 + resolution: {integrity: sha512-OTRMhwidScQSA0xsc5OCtm3K/oAChe47jy1e4OY3VpXUnKrI7C8iwfQ9XDRdpdsRASH2xi6P5I0+7ksFBehaQQ==} 1340 + engines: {node: '>=12'} 1341 + 1342 + '@tanstack/query-core@5.70.0': 1343 + resolution: {integrity: sha512-ZkkjQAZjI6nS5OyAmaSQafQXK180Xvp0lZYk4BzrnskkTV8On3zSJUxOIXnh0h/8EgqRkCA9i879DiJovA1kGw==} 1344 + 1345 + '@tanstack/query-devtools@5.67.2': 1346 + resolution: {integrity: sha512-O4QXFFd7xqp6EX7sdvc9tsVO8nm4lpWBqwpgjpVLW5g7IeOY6VnS/xvs/YzbRhBVkKTMaJMOUGU7NhSX+YGoNg==} 1347 + 1348 + '@tanstack/react-query-devtools@5.70.0': 1349 + resolution: {integrity: sha512-jFtpA3mnUoVn/ic1EVxmA6qG7z8S19nchsHciMCWOvC1Z2Mt8f0wbl1p8hNvrBpzWywZa+Hl0AxMVs48psUvhg==} 1350 + peerDependencies: 1351 + '@tanstack/react-query': ^5.70.0 1352 + react: ^18 || ^19 1353 + 1354 + '@tanstack/react-query@5.70.0': 1355 + resolution: {integrity: sha512-z0tx1zz2CQ6nTm+fCaOp93FqsFjNgXtOy+4mC5ifQ4B+rJiMD0AGfJrYSGh/OuefhrzTYDAbkGUAGw6JzkWy8g==} 1356 + peerDependencies: 1357 + react: ^18 || ^19 1358 + 1359 + '@tanstack/react-router-devtools@1.114.29': 1360 + resolution: {integrity: sha512-T2yzpAkhSKzJt9Une8B37UahD5bmtzVHdhoQgj9/L/7FuxInppbMzKBHZM9VXg/WtWO53EVFba+Gi4A0npZ9iw==} 1361 + engines: {node: '>=12'} 1362 + peerDependencies: 1363 + '@tanstack/react-router': ^1.114.29 1364 + react: '>=18.0.0 || >=19.0.0' 1365 + react-dom: '>=18.0.0 || >=19.0.0' 1366 + 1367 + '@tanstack/react-router@1.114.29': 1368 + resolution: {integrity: sha512-5nNWQoVKP+HIuhIZImSwid5pdSFE/Ge8XEX068U/1SaivEX4of0DCyOh1qKsswelmBVvqHFmtY6/GN/8dVLrHw==} 1369 + engines: {node: '>=12'} 1370 + peerDependencies: 1371 + react: '>=18.0.0 || >=19.0.0' 1372 + react-dom: '>=18.0.0 || >=19.0.0' 1373 + 1374 + '@tanstack/react-store@0.7.0': 1375 + resolution: {integrity: sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng==} 1376 + peerDependencies: 1377 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1378 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1379 + 1380 + '@tanstack/router-core@1.114.29': 1381 + resolution: {integrity: sha512-CLf7HhHNiTz3cW1uB+DGyxiVwkEY+2YO36MXjtTLLtt5tQozDe3Kp7Dtb6B7aacMpvnLLwWtfmgptOce4Y8TQQ==} 1382 + engines: {node: '>=12'} 1383 + 1384 + '@tanstack/router-devtools-core@1.114.29': 1385 + resolution: {integrity: sha512-QDtVcUGalFi9e5lFABOchGQI7gyxnk2z8cUET+DpZF8LWS0eJTv5+QWvLc7F7UHhz1MeFPbmIR2vQ4PDspWRfA==} 1386 + engines: {node: '>=12'} 1387 + peerDependencies: 1388 + '@tanstack/router-core': ^1.114.29 1389 + csstype: ^3.0.10 1390 + solid-js: '>=1.9.5' 1391 + tiny-invariant: ^1.3.3 1392 + peerDependenciesMeta: 1393 + csstype: 1394 + optional: true 1395 + 1396 + '@tanstack/router-devtools@1.114.29': 1397 + resolution: {integrity: sha512-bfTD3qyFh1TZEEq6iVnj5RgnC/iKV94yNo7BMMY+B2puO1mQJpvFSwEc4RQfTNC5MgEvpn7LY6R3Q8E1ya5o7Q==} 1398 + engines: {node: '>=12'} 1399 + peerDependencies: 1400 + '@tanstack/react-router': ^1.114.29 1401 + csstype: ^3.0.10 1402 + react: '>=18.0.0 || >=19.0.0' 1403 + react-dom: '>=18.0.0 || >=19.0.0' 1404 + peerDependenciesMeta: 1405 + csstype: 1406 + optional: true 1407 + 1408 + '@tanstack/router-generator@1.114.29': 1409 + resolution: {integrity: sha512-YGAKnVrv775GCmU5tUIStpVewibK+Q5nLSWbA+xV2J4M7nA/ozjN1GeVp0+Wo+5T0tkU5cyHjlCPRP+M/aikWQ==} 1410 + engines: {node: '>=12'} 1411 + peerDependencies: 1412 + '@tanstack/react-router': ^1.114.29 1413 + peerDependenciesMeta: 1414 + '@tanstack/react-router': 1415 + optional: true 1416 + 1417 + '@tanstack/router-plugin@1.114.29': 1418 + resolution: {integrity: sha512-0xWAtyiselqTQiV9O8WtgFb/DN4yOgTP75uHAwxpHq6upcnBFBXqVw8DO/KR6AoTRsN96HdtuyjhK98JuQqngA==} 1419 + engines: {node: '>=12'} 1420 + peerDependencies: 1421 + '@rsbuild/core': '>=1.0.2' 1422 + '@tanstack/react-router': ^1.114.29 1423 + vite: '>=5.0.0 || >=6.0.0' 1424 + vite-plugin-solid: ^2.11.2 1425 + webpack: '>=5.92.0' 1426 + peerDependenciesMeta: 1427 + '@rsbuild/core': 1428 + optional: true 1429 + '@tanstack/react-router': 1430 + optional: true 1431 + vite: 1432 + optional: true 1433 + vite-plugin-solid: 1434 + optional: true 1435 + webpack: 1436 + optional: true 1437 + 1438 + '@tanstack/router-utils@1.114.29': 1439 + resolution: {integrity: sha512-RDn3aMOHPrXYCQGXNaN4P0MvwiuCZHBKTO9srtLqYYCzW2iipqbyZ53RI54TzPgNLE37jtN5XaEH4FNF0Ydodg==} 1440 + engines: {node: '>=12'} 1441 + 1442 + '@tanstack/store@0.7.0': 1443 + resolution: {integrity: sha512-CNIhdoUsmD2NolYuaIs8VfWM467RK6oIBAW4nPEKZhg1smZ+/CwtCdpURgp7nxSqOaV9oKkzdWD80+bC66F/Jg==} 1444 + 1445 + '@tanstack/virtual-file-routes@1.114.29': 1446 + resolution: {integrity: sha512-DufKsQy/qxDpOTiggJCgshhJkpSyUygwHHfl2LA66CXOf3aUjZtlNu4io1UpmJNf8C/9lVlGARhkoq5fTRRk0w==} 1447 + engines: {node: '>=12'} 1448 + 1449 + '@tiptap/core@2.11.6': 1450 + resolution: {integrity: sha512-6ULwy6z8IytDPgmFPPPPs/4a+dRPnQ4dipuuv4SGRlSt1lozUyVJrFuBYYZQJnaZJGyTyWrIA36YIZr9NFWRww==} 1451 + peerDependencies: 1452 + '@tiptap/pm': ^2.7.0 1453 + 1454 + '@tiptap/extension-blockquote@2.11.6': 1455 + resolution: {integrity: sha512-5Fr6aqzFusXBju4X/K8WU7gZ89YyICC97RHWbHX21qkIm4I5WVjrTPy4vFAcazwmJWLhaURIj5aYllbpKBosMw==} 1456 + peerDependencies: 1457 + '@tiptap/core': ^2.7.0 1458 + 1459 + '@tiptap/extension-bold@2.11.6': 1460 + resolution: {integrity: sha512-+PG8puMbUrxuVxEeGxhRu9zcO0UcyjzmriDOxY0+8otqerz8u1CriUgeVE+O3Pscqq5UT8aBfBNnL66Ab811tw==} 1461 + peerDependencies: 1462 + '@tiptap/core': ^2.7.0 1463 + 1464 + '@tiptap/extension-bubble-menu@2.11.6': 1465 + resolution: {integrity: sha512-U2whGy3N3xhNxdIoRaOwPdMphvmqWrAh8ods6jQu3FF8bFaW0d82kzefg7xvdKfDtybBpxU9kPukbwymAUmzOg==} 1466 + peerDependencies: 1467 + '@tiptap/core': ^2.7.0 1468 + '@tiptap/pm': ^2.7.0 1469 + 1470 + '@tiptap/extension-bullet-list@2.11.6': 1471 + resolution: {integrity: sha512-vRUhnzJoL8yHL7taJJM6IDaR/neZsBQrGa0N9HaUhfyEIicpwNvW2Spo7YR2EGxVekd0GFoHy+MXpi80mN3cIg==} 1472 + peerDependencies: 1473 + '@tiptap/core': ^2.7.0 1474 + 1475 + '@tiptap/extension-code-block@2.11.6': 1476 + resolution: {integrity: sha512-NcbzWS6zIfI96OaPmFeRdqL0cMWcHWrNbeYaPLx5JzHherxFRlW75Gh9bYVh5pLMNlZACvpc41NJdXTS0H2/2g==} 1477 + peerDependencies: 1478 + '@tiptap/core': ^2.7.0 1479 + '@tiptap/pm': ^2.7.0 1480 + 1481 + '@tiptap/extension-code@2.11.6': 1482 + resolution: {integrity: sha512-vDKhmF+SkS6XIKkPf9PnDnuReszaCjRk0hNAbvZWpOQBZkDlZzuqWUf2/T8/dbTF+QhOic+izU5hxabFjWVgUA==} 1483 + peerDependencies: 1484 + '@tiptap/core': ^2.7.0 1485 + 1486 + '@tiptap/extension-document@2.11.6': 1487 + resolution: {integrity: sha512-TP0bTUqT7s1x5PeT8lFSRQ0bATaku5Xn8cCu59183EHCmX4frTTKLJv+ksg3FqVIQffO06l0yzsaOnPQbdWmkg==} 1488 + peerDependencies: 1489 + '@tiptap/core': ^2.7.0 1490 + 1491 + '@tiptap/extension-dropcursor@2.11.6': 1492 + resolution: {integrity: sha512-6nHqfiskoUo0avM8rwgHuGTOP6N08teZGUPc7q73wSIEMGBViPHPA4awW2lp5OpJCmXCsY69lJjaJOChuXeRSg==} 1493 + peerDependencies: 1494 + '@tiptap/core': ^2.7.0 1495 + '@tiptap/pm': ^2.7.0 1496 + 1497 + '@tiptap/extension-floating-menu@2.11.6': 1498 + resolution: {integrity: sha512-4mm+PaNZ9oriDD7w8kdU91/WQ+cKNGGD6ip9w9ewGYS0w5j4T6iZzHSK8jFggPiIntBCkNRfl8tAUF0xDz14ow==} 1499 + peerDependencies: 1500 + '@tiptap/core': ^2.7.0 1501 + '@tiptap/pm': ^2.7.0 1502 + 1503 + '@tiptap/extension-gapcursor@2.11.6': 1504 + resolution: {integrity: sha512-Bl39PVQQShy52NtB6eUKc/RsvEnHQ+/iF7cd8xR8SGWVqP1+KpUXokOt/3B/giMAQgCmrJqS8VR6mvPkZKOaZA==} 1505 + peerDependencies: 1506 + '@tiptap/core': ^2.7.0 1507 + '@tiptap/pm': ^2.7.0 1508 + 1509 + '@tiptap/extension-hard-break@2.11.6': 1510 + resolution: {integrity: sha512-2qaUhjc0DOX/AtruaEs9siPwlm4Ps5QV3y7/R+4BQrPB7EcPFZwP4cPHTDXNMt6NfEjVarGxs3KXmlER6/V3qg==} 1511 + peerDependencies: 1512 + '@tiptap/core': ^2.7.0 1513 + 1514 + '@tiptap/extension-heading@2.11.6': 1515 + resolution: {integrity: sha512-0sq77OxVaFrKCZx6x5SETJRqWLK8sXSqfdRgusWGvjq3VpyWRPRAsUBw2H/PqJIcotso+m8eACMNyFbKf301Lw==} 1516 + peerDependencies: 1517 + '@tiptap/core': ^2.7.0 1518 + 1519 + '@tiptap/extension-highlight@2.11.6': 1520 + resolution: {integrity: sha512-QuVAuzZAUbdtNrmCT1d4gDQuH1Qni9qD9I36WccGD73MR5z/rGsJLcTU4m+1UEooo2E1NfVZv7hdhDCHsOCkpA==} 1521 + peerDependencies: 1522 + '@tiptap/core': ^2.7.0 1523 + 1524 + '@tiptap/extension-history@2.11.6': 1525 + resolution: {integrity: sha512-6LAXHMBijQGw8azbCg97VCWlkEZgJ9umOhDD7Sta/yFyYu4Q/lrvzju663ueY3yasDWj/mrXBHyXFs5zDUvAaw==} 1526 + peerDependencies: 1527 + '@tiptap/core': ^2.7.0 1528 + '@tiptap/pm': ^2.7.0 1529 + 1530 + '@tiptap/extension-horizontal-rule@2.11.6': 1531 + resolution: {integrity: sha512-kZwWyiyNcKsDqdpkaVUlZEaT6mHzi35Zuq0wmEzGlIfxixCN9DlO2zTpWslJtxvyR8G3YSB6YCjFMTPliTS5QQ==} 1532 + peerDependencies: 1533 + '@tiptap/core': ^2.7.0 1534 + '@tiptap/pm': ^2.7.0 1535 + 1536 + '@tiptap/extension-italic@2.11.6': 1537 + resolution: {integrity: sha512-yZ9kkquuYBTlagCdQk7pPdOl0ckSjl64pJLVMz47bANZOEXg7o7iGNUPI4MzQOOmMY2bWfZyWzv+KH9sdR5Vvg==} 1538 + peerDependencies: 1539 + '@tiptap/core': ^2.7.0 1540 + 1541 + '@tiptap/extension-link@2.11.6': 1542 + resolution: {integrity: sha512-PrGvzxLFZXx2DX4nxJhtkWSiXd1NH0aIj/h86W4ReOT8o0h4BepI/c8ZWYZOyDtXBMJXwn7O8s9iMbzTZwbD0A==} 1543 + peerDependencies: 1544 + '@tiptap/core': ^2.7.0 1545 + '@tiptap/pm': ^2.7.0 1546 + 1547 + '@tiptap/extension-list-item@2.11.6': 1548 + resolution: {integrity: sha512-CyBpuGV61ge4FrwjcVwWsx8K4ih2wb/ruOX/Ujr7ewaKvJDXLSzkN4vfR6WpAXMxPBXKLF6C+xVLZYY/8KuSNA==} 1549 + peerDependencies: 1550 + '@tiptap/core': ^2.7.0 1551 + 1552 + '@tiptap/extension-ordered-list@2.11.6': 1553 + resolution: {integrity: sha512-0VeUWK6SdHSwsrWUqF8b65on8SleGJq7E0poztNBRKw5/fJ6EWLsHson47wBafTdOHh4XECfMW9Nfynk9r9hTw==} 1554 + peerDependencies: 1555 + '@tiptap/core': ^2.7.0 1556 + 1557 + '@tiptap/extension-paragraph@2.11.6': 1558 + resolution: {integrity: sha512-tz/tLbjz/tdX0S0OjTVb6XhSGrSPcn0RTRD4dMWy5jAUDr1kummyb7PHQrtrKyxMvn529kXOfShh9mdpRIRgiQ==} 1559 + peerDependencies: 1560 + '@tiptap/core': ^2.7.0 1561 + 1562 + '@tiptap/extension-placeholder@2.11.6': 1563 + resolution: {integrity: sha512-6djBAdSKS4+lyDdpBJMYVHaqE9sd+JJ+ed89l6kH3gPynxe8cDiBEA3nfinc4eMfKiSbseMjPzk+l3dPBIva/g==} 1564 + peerDependencies: 1565 + '@tiptap/core': ^2.7.0 1566 + '@tiptap/pm': ^2.7.0 1567 + 1568 + '@tiptap/extension-strike@2.11.6': 1569 + resolution: {integrity: sha512-oh8xuOjJdHoj6HIaGQjHjSIC9cpvgslomsDsqbB6n/ZYVNhVBsQuiT76jE8iLlULHsRxmwCQ3K8RGC6cKbsxtQ==} 1570 + peerDependencies: 1571 + '@tiptap/core': ^2.7.0 1572 + 1573 + '@tiptap/extension-task-item@2.11.6': 1574 + resolution: {integrity: sha512-+lthxREN9aFSlyDt6v++aKQ7pEK4BfROjO7gOOsx+uPIZLmVvRoWyrH/bx50/neWLhWZcLMWMQ53yHGnzywbzw==} 1575 + peerDependencies: 1576 + '@tiptap/core': ^2.7.0 1577 + '@tiptap/pm': ^2.7.0 1578 + 1579 + '@tiptap/extension-task-list@2.11.6': 1580 + resolution: {integrity: sha512-ODSDu2PLyWPMQcl3yZAGeDFlWnH4gu+uK3EbgRTAyljfZKnBhmN3c06SUP7aO7H7d+zHjY6D5PsyMgCJk79Z5w==} 1581 + peerDependencies: 1582 + '@tiptap/core': ^2.7.0 1583 + 1584 + '@tiptap/extension-text-style@2.11.6': 1585 + resolution: {integrity: sha512-bh0sp0QbHk1xj3gQ/hyn3hapZNPa8rcDnGK6OXC0UC3nMKfyG1J3yYJa+N3fcTgFoFm/kfIajE52UJeBQZV4Jw==} 1586 + peerDependencies: 1587 + '@tiptap/core': ^2.7.0 1588 + 1589 + '@tiptap/extension-text@2.11.6': 1590 + resolution: {integrity: sha512-4XaQiDPrKGNwnjoBPzjRm9Rw6svFKOwOEUgT0PB2meiP3HLwpayFoOog2tcSJul/oi0Vrrgsr2IRc3WBhLGaQw==} 1591 + peerDependencies: 1592 + '@tiptap/core': ^2.7.0 1593 + 1594 + '@tiptap/pm@2.11.6': 1595 + resolution: {integrity: sha512-BUl3XQPOSdyY3k6QG01aDSi/vub6bgolLdQjsEa4fCbcoiidIxgTJfcfNUJE+dpV9Ku11eB24gxPPCunHkYFUw==} 1596 + 1597 + '@tiptap/react@2.11.6': 1598 + resolution: {integrity: sha512-thDbau/uuUEoF2XKoPLXUsCssM1GXfVvZWiOOWhbfISxRPVk8eLDSVcXN2SlplaLH6CjRlZ/TCX3o4D43QrA5A==} 1599 + peerDependencies: 1600 + '@tiptap/core': ^2.7.0 1601 + '@tiptap/pm': ^2.7.0 1602 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 1603 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 1604 + 1605 + '@tiptap/starter-kit@2.11.6': 1606 + resolution: {integrity: sha512-isxrC/Ivp8DBhaO/jHPzBqSS37FW/cGJ9E5xylng0SOzyfTLy+hsXxiCH0FThct++49a7jRuNEyiB293YwxiDQ==} 1607 + 1608 + '@types/babel__core@7.20.5': 1609 + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} 1610 + 1611 + '@types/babel__generator@7.6.8': 1612 + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} 1613 + 1614 + '@types/babel__template@7.4.4': 1615 + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} 1616 + 1617 + '@types/babel__traverse@7.20.7': 1618 + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} 1619 + 1620 + '@types/bcrypt@5.0.2': 1621 + resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==} 1622 + 1623 + '@types/better-sqlite3@7.6.13': 1624 + resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} 1625 + 1626 + '@types/conventional-commits-parser@5.0.1': 1627 + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} 1628 + 1629 + '@types/estree@1.0.7': 1630 + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 1631 + 1632 + '@types/linkify-it@5.0.0': 1633 + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} 1634 + 1635 + '@types/markdown-it@14.1.2': 1636 + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} 1637 + 1638 + '@types/mdurl@2.0.0': 1639 + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} 1640 + 1641 + '@types/node@22.13.14': 1642 + resolution: {integrity: sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==} 1643 + 1644 + '@types/node@22.14.1': 1645 + resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} 1646 + 1647 + '@types/react-dom@19.0.4': 1648 + resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} 1649 + peerDependencies: 1650 + '@types/react': ^19.0.0 1651 + 1652 + '@types/react@19.0.12': 1653 + resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==} 1654 + 1655 + '@types/use-sync-external-store@0.0.6': 1656 + resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} 1657 + 1658 + '@types/ws@8.18.0': 1659 + resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==} 1660 + 1661 + '@vitejs/plugin-react@4.3.4': 1662 + resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} 1663 + engines: {node: ^14.18.0 || >=16.0.0} 1664 + peerDependencies: 1665 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 1666 + 1667 + JSONStream@1.3.5: 1668 + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} 1669 + hasBin: true 1670 + 1671 + abbrev@1.1.1: 1672 + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 1673 + 1674 + acorn@8.14.1: 1675 + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 1676 + engines: {node: '>=0.4.0'} 1677 + hasBin: true 1678 + 1679 + agent-base@6.0.2: 1680 + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 1681 + engines: {node: '>= 6.0.0'} 1682 + 1683 + ajv@8.17.1: 1684 + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} 1685 + 1686 + ansi-regex@5.0.1: 1687 + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 1688 + engines: {node: '>=8'} 1689 + 1690 + ansi-styles@4.3.0: 1691 + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 1692 + engines: {node: '>=8'} 1693 + 1694 + ansis@3.17.0: 1695 + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} 1696 + engines: {node: '>=14'} 1697 + 1698 + anymatch@3.1.3: 1699 + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 1700 + engines: {node: '>= 8'} 1701 + 1702 + aproba@2.0.0: 1703 + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} 1704 + 1705 + are-we-there-yet@2.0.0: 1706 + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} 1707 + engines: {node: '>=10'} 1708 + deprecated: This package is no longer supported. 1709 + 1710 + argparse@2.0.1: 1711 + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 1712 + 1713 + aria-hidden@1.2.4: 1714 + resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} 1715 + engines: {node: '>=10'} 1716 + 1717 + array-ify@1.0.0: 1718 + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} 1719 + 1720 + babel-dead-code-elimination@1.0.9: 1721 + resolution: {integrity: sha512-JLIhax/xullfInZjtu13UJjaLHDeTzt3vOeomaSUdO/nAMEL/pWC/laKrSvWylXMnVWyL5bpmG9njqBZlUQOdg==} 1722 + 1723 + babel-plugin-react-compiler@19.0.0-beta-aeaed83-20250323: 1724 + resolution: {integrity: sha512-7WKelqaC8mz3SIy9YRAySkY9veHKE80HruUmXUOhk0ZcBvDBgAlltv06lMIiGyHB7TDzAHS1fANzOXCPcfSErQ==} 1725 + 1726 + balanced-match@1.0.2: 1727 + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 1728 + 1729 + base64-js@1.5.1: 1730 + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 1731 + 1732 + bcrypt@5.1.1: 1733 + resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} 1734 + engines: {node: '>= 10.0.0'} 1735 + 1736 + better-sqlite3@11.9.1: 1737 + resolution: {integrity: sha512-Ba0KR+Fzxh2jDRhdg6TSH0SJGzb8C0aBY4hR8w8madIdIzzC6Y1+kx5qR6eS1Z+Gy20h6ZU28aeyg0z1VIrShQ==} 1738 + 1739 + binary-extensions@2.3.0: 1740 + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 1741 + engines: {node: '>=8'} 1742 + 1743 + bindings@1.5.0: 1744 + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 1745 + 1746 + bl@4.1.0: 1747 + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 1748 + 1749 + brace-expansion@1.1.11: 1750 + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 1751 + 1752 + braces@3.0.3: 1753 + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 1754 + engines: {node: '>=8'} 1755 + 1756 + browserslist@4.24.4: 1757 + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} 1758 + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 1759 + hasBin: true 1760 + 1761 + buffer@5.7.1: 1762 + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 1763 + 1764 + bun-types@1.2.8: 1765 + resolution: {integrity: sha512-D5npfxKIGuYe9dTHLK1hi4XFmbMdKYoLrgyd25rrUyCrnyU4ljmQW7vDdonvibKeyU72mZuixIhQ2J+q6uM0Mg==} 1766 + 1767 + callsites@3.1.0: 1768 + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 1769 + engines: {node: '>=6'} 1770 + 1771 + caniuse-lite@1.0.30001707: 1772 + resolution: {integrity: sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==} 1773 + 1774 + chalk@5.4.1: 1775 + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 1776 + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 1777 + 1778 + chokidar@3.6.0: 1779 + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 1780 + engines: {node: '>= 8.10.0'} 1781 + 1782 + chownr@1.1.4: 1783 + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 1784 + 1785 + chownr@2.0.0: 1786 + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 1787 + engines: {node: '>=10'} 1788 + 1789 + class-variance-authority@0.7.1: 1790 + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} 1791 + 1792 + cliui@8.0.1: 1793 + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} 1794 + engines: {node: '>=12'} 1795 + 1796 + clsx@2.1.1: 1797 + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} 1798 + engines: {node: '>=6'} 1799 + 1800 + cmdk@1.1.1: 1801 + resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} 1802 + peerDependencies: 1803 + react: ^18 || ^19 || ^19.0.0-rc 1804 + react-dom: ^18 || ^19 || ^19.0.0-rc 1805 + 1806 + color-convert@2.0.1: 1807 + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 1808 + engines: {node: '>=7.0.0'} 1809 + 1810 + color-name@1.1.4: 1811 + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 1812 + 1813 + color-support@1.1.3: 1814 + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} 1815 + hasBin: true 1816 + 1817 + compare-func@2.0.0: 1818 + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} 1819 + 1820 + concat-map@0.0.1: 1821 + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 1822 + 1823 + console-control-strings@1.1.0: 1824 + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} 1825 + 1826 + conventional-changelog-angular@7.0.0: 1827 + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} 1828 + engines: {node: '>=16'} 1829 + 1830 + conventional-changelog-conventionalcommits@7.0.2: 1831 + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} 1832 + engines: {node: '>=16'} 1833 + 1834 + conventional-commits-parser@5.0.0: 1835 + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} 1836 + engines: {node: '>=16'} 1837 + hasBin: true 1838 + 1839 + convert-source-map@2.0.0: 1840 + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 1841 + 1842 + cosmiconfig-typescript-loader@6.1.0: 1843 + resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} 1844 + engines: {node: '>=v18'} 1845 + peerDependencies: 1846 + '@types/node': '*' 1847 + cosmiconfig: '>=9' 1848 + typescript: '>=5' 1849 + 1850 + cosmiconfig@9.0.0: 1851 + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} 1852 + engines: {node: '>=14'} 1853 + peerDependencies: 1854 + typescript: '>=4.9.5' 1855 + peerDependenciesMeta: 1856 + typescript: 1857 + optional: true 1858 + 1859 + crelt@1.0.6: 1860 + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} 1861 + 1862 + csstype@3.1.3: 1863 + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 1864 + 1865 + dargs@8.1.0: 1866 + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} 1867 + engines: {node: '>=12'} 1868 + 1869 + date-fns@4.1.0: 1870 + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} 1871 + 1872 + debug@4.4.0: 1873 + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 1874 + engines: {node: '>=6.0'} 1875 + peerDependencies: 1876 + supports-color: '*' 1877 + peerDependenciesMeta: 1878 + supports-color: 1879 + optional: true 1880 + 1881 + decompress-response@6.0.0: 1882 + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 1883 + engines: {node: '>=10'} 1884 + 1885 + deep-extend@0.6.0: 1886 + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} 1887 + engines: {node: '>=4.0.0'} 1888 + 1889 + delegates@1.0.0: 1890 + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} 1891 + 1892 + detect-libc@2.0.3: 1893 + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 1894 + engines: {node: '>=8'} 1895 + 1896 + detect-node-es@1.1.0: 1897 + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} 1898 + 1899 + diff@7.0.0: 1900 + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} 1901 + engines: {node: '>=0.3.1'} 1902 + 1903 + dot-prop@5.3.0: 1904 + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} 1905 + engines: {node: '>=8'} 1906 + 1907 + dotenv@16.5.0: 1908 + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} 1909 + engines: {node: '>=12'} 1910 + 1911 + drizzle-orm@0.42.0: 1912 + resolution: {integrity: sha512-pS8nNJm2kBNZwrOjTHJfdKkaU+KuUQmV/vk5D57NojDq4FG+0uAYGMulXtYT///HfgsMF0hnFFvu1ezI3OwOkg==} 1913 + peerDependencies: 1914 + '@aws-sdk/client-rds-data': '>=3' 1915 + '@cloudflare/workers-types': '>=4' 1916 + '@electric-sql/pglite': '>=0.2.0' 1917 + '@libsql/client': '>=0.10.0' 1918 + '@libsql/client-wasm': '>=0.10.0' 1919 + '@neondatabase/serverless': '>=0.10.0' 1920 + '@op-engineering/op-sqlite': '>=2' 1921 + '@opentelemetry/api': ^1.4.1 1922 + '@planetscale/database': '>=1.13' 1923 + '@prisma/client': '*' 1924 + '@tidbcloud/serverless': '*' 1925 + '@types/better-sqlite3': '*' 1926 + '@types/pg': '*' 1927 + '@types/sql.js': '*' 1928 + '@vercel/postgres': '>=0.8.0' 1929 + '@xata.io/client': '*' 1930 + better-sqlite3: '>=7' 1931 + bun-types: '*' 1932 + expo-sqlite: '>=14.0.0' 1933 + gel: '>=2' 1934 + knex: '*' 1935 + kysely: '*' 1936 + mysql2: '>=2' 1937 + pg: '>=8' 1938 + postgres: '>=3' 1939 + prisma: '*' 1940 + sql.js: '>=1' 1941 + sqlite3: '>=5' 1942 + peerDependenciesMeta: 1943 + '@aws-sdk/client-rds-data': 1944 + optional: true 1945 + '@cloudflare/workers-types': 1946 + optional: true 1947 + '@electric-sql/pglite': 1948 + optional: true 1949 + '@libsql/client': 1950 + optional: true 1951 + '@libsql/client-wasm': 1952 + optional: true 1953 + '@neondatabase/serverless': 1954 + optional: true 1955 + '@op-engineering/op-sqlite': 1956 + optional: true 1957 + '@opentelemetry/api': 1958 + optional: true 1959 + '@planetscale/database': 1960 + optional: true 1961 + '@prisma/client': 1962 + optional: true 1963 + '@tidbcloud/serverless': 1964 + optional: true 1965 + '@types/better-sqlite3': 1966 + optional: true 1967 + '@types/pg': 1968 + optional: true 1969 + '@types/sql.js': 1970 + optional: true 1971 + '@vercel/postgres': 1972 + optional: true 1973 + '@xata.io/client': 1974 + optional: true 1975 + better-sqlite3: 1976 + optional: true 1977 + bun-types: 1978 + optional: true 1979 + expo-sqlite: 1980 + optional: true 1981 + gel: 1982 + optional: true 1983 + knex: 1984 + optional: true 1985 + kysely: 1986 + optional: true 1987 + mysql2: 1988 + optional: true 1989 + pg: 1990 + optional: true 1991 + postgres: 1992 + optional: true 1993 + prisma: 1994 + optional: true 1995 + sql.js: 1996 + optional: true 1997 + sqlite3: 1998 + optional: true 1999 + 2000 + electron-to-chromium@1.5.128: 2001 + resolution: {integrity: sha512-bo1A4HH/NS522Ws0QNFIzyPcyUUNV/yyy70Ho1xqfGYzPUme2F/xr4tlEOuM6/A538U1vDA7a4XfCd1CKRegKQ==} 2002 + 2003 + emoji-regex@8.0.0: 2004 + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 2005 + 2006 + end-of-stream@1.4.4: 2007 + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 2008 + 2009 + enhanced-resolve@5.18.1: 2010 + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} 2011 + engines: {node: '>=10.13.0'} 2012 + 2013 + entities@4.5.0: 2014 + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 2015 + engines: {node: '>=0.12'} 2016 + 2017 + env-paths@2.2.1: 2018 + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} 2019 + engines: {node: '>=6'} 2020 + 2021 + error-ex@1.3.2: 2022 + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} 2023 + 2024 + esbuild@0.25.2: 2025 + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} 2026 + engines: {node: '>=18'} 2027 + hasBin: true 2028 + 2029 + escalade@3.2.0: 2030 + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 2031 + engines: {node: '>=6'} 2032 + 2033 + escape-string-regexp@4.0.0: 2034 + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 2035 + engines: {node: '>=10'} 2036 + 2037 + expand-template@2.0.3: 2038 + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} 2039 + engines: {node: '>=6'} 2040 + 2041 + fast-deep-equal@3.1.3: 2042 + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 2043 + 2044 + fast-uri@3.0.6: 2045 + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} 2046 + 2047 + file-uri-to-path@1.0.0: 2048 + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 2049 + 2050 + fill-range@7.1.1: 2051 + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 2052 + engines: {node: '>=8'} 2053 + 2054 + find-up@7.0.0: 2055 + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} 2056 + engines: {node: '>=18'} 2057 + 2058 + framer-motion@12.6.2: 2059 + resolution: {integrity: sha512-7LgPRlPs5aG8UxeZiMCMZz8firC53+2+9TnWV22tuSi38D3IFRxHRUqOREKckAkt6ztX+Dn6weLcatQilJTMcg==} 2060 + peerDependencies: 2061 + '@emotion/is-prop-valid': '*' 2062 + react: ^18.0.0 || ^19.0.0 2063 + react-dom: ^18.0.0 || ^19.0.0 2064 + peerDependenciesMeta: 2065 + '@emotion/is-prop-valid': 2066 + optional: true 2067 + react: 2068 + optional: true 2069 + react-dom: 2070 + optional: true 2071 + 2072 + fs-constants@1.0.0: 2073 + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} 2074 + 2075 + fs-minipass@2.1.0: 2076 + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 2077 + engines: {node: '>= 8'} 2078 + 2079 + fs.realpath@1.0.0: 2080 + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 2081 + 2082 + fsevents@2.3.3: 2083 + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 2084 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 2085 + os: [darwin] 2086 + 2087 + gauge@3.0.2: 2088 + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} 2089 + engines: {node: '>=10'} 2090 + deprecated: This package is no longer supported. 2091 + 2092 + gensync@1.0.0-beta.2: 2093 + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 2094 + engines: {node: '>=6.9.0'} 2095 + 2096 + get-caller-file@2.0.5: 2097 + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 2098 + engines: {node: 6.* || 8.* || >= 10.*} 2099 + 2100 + get-nonce@1.0.1: 2101 + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} 2102 + engines: {node: '>=6'} 2103 + 2104 + get-tsconfig@4.10.0: 2105 + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} 2106 + 2107 + git-raw-commits@4.0.0: 2108 + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} 2109 + engines: {node: '>=16'} 2110 + hasBin: true 2111 + 2112 + github-from-package@0.0.0: 2113 + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} 2114 + 2115 + glob-parent@5.1.2: 2116 + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 2117 + engines: {node: '>= 6'} 2118 + 2119 + glob@7.2.3: 2120 + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 2121 + deprecated: Glob versions prior to v9 are no longer supported 2122 + 2123 + global-directory@4.0.1: 2124 + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} 2125 + engines: {node: '>=18'} 2126 + 2127 + globals@11.12.0: 2128 + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 2129 + engines: {node: '>=4'} 2130 + 2131 + globals@16.0.0: 2132 + resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} 2133 + engines: {node: '>=18'} 2134 + 2135 + goober@2.1.16: 2136 + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} 2137 + peerDependencies: 2138 + csstype: ^3.0.10 2139 + 2140 + graceful-fs@4.2.11: 2141 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 2142 + 2143 + has-unicode@2.0.1: 2144 + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} 2145 + 2146 + hono@4.7.5: 2147 + resolution: {integrity: sha512-fDOK5W2C1vZACsgLONigdZTRZxuBqFtcKh7bUQ5cVSbwI2RWjloJDcgFOVzbQrlI6pCmhlTsVYZ7zpLj4m4qMQ==} 2148 + engines: {node: '>=16.9.0'} 2149 + 2150 + hono@4.7.7: 2151 + resolution: {integrity: sha512-2PCpQRbN87Crty8/L/7akZN3UyZIAopSoRxCwRbJgUuV1+MHNFHzYFxZTg4v/03cXUm+jce/qa2VSBZpKBm3Qw==} 2152 + engines: {node: '>=16.9.0'} 2153 + 2154 + https-proxy-agent@5.0.1: 2155 + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} 2156 + engines: {node: '>= 6'} 2157 + 2158 + husky@9.1.7: 2159 + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} 2160 + engines: {node: '>=18'} 2161 + hasBin: true 2162 + 2163 + ieee754@1.2.1: 2164 + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 2165 + 2166 + immer@10.1.1: 2167 + resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==} 2168 + 2169 + import-fresh@3.3.1: 2170 + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 2171 + engines: {node: '>=6'} 2172 + 2173 + import-meta-resolve@4.1.0: 2174 + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} 2175 + 2176 + inflight@1.0.6: 2177 + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 2178 + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 2179 + 2180 + inherits@2.0.4: 2181 + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 2182 + 2183 + ini@1.3.8: 2184 + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 2185 + 2186 + ini@4.1.1: 2187 + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} 2188 + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} 2189 + 2190 + is-arrayish@0.2.1: 2191 + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} 2192 + 2193 + is-binary-path@2.1.0: 2194 + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 2195 + engines: {node: '>=8'} 2196 + 2197 + is-extglob@2.1.1: 2198 + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 2199 + engines: {node: '>=0.10.0'} 2200 + 2201 + is-fullwidth-code-point@3.0.0: 2202 + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 2203 + engines: {node: '>=8'} 2204 + 2205 + is-glob@4.0.3: 2206 + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 2207 + engines: {node: '>=0.10.0'} 2208 + 2209 + is-number@7.0.0: 2210 + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 2211 + engines: {node: '>=0.12.0'} 2212 + 2213 + is-obj@2.0.0: 2214 + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} 2215 + engines: {node: '>=8'} 2216 + 2217 + is-text-path@2.0.0: 2218 + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} 2219 + engines: {node: '>=8'} 2220 + 2221 + jiti@2.4.2: 2222 + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} 2223 + hasBin: true 2224 + 2225 + js-tokens@4.0.0: 2226 + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 2227 + 2228 + js-yaml@4.1.0: 2229 + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 2230 + hasBin: true 2231 + 2232 + jsesc@3.1.0: 2233 + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} 2234 + engines: {node: '>=6'} 2235 + hasBin: true 2236 + 2237 + json-parse-even-better-errors@2.3.1: 2238 + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} 2239 + 2240 + json-schema-traverse@1.0.0: 2241 + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 2242 + 2243 + json5@2.2.3: 2244 + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 2245 + engines: {node: '>=6'} 2246 + hasBin: true 2247 + 2248 + jsonparse@1.3.1: 2249 + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} 2250 + engines: {'0': node >= 0.2.0} 2251 + 2252 + lightningcss-darwin-arm64@1.29.2: 2253 + resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} 2254 + engines: {node: '>= 12.0.0'} 2255 + cpu: [arm64] 2256 + os: [darwin] 2257 + 2258 + lightningcss-darwin-x64@1.29.2: 2259 + resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==} 2260 + engines: {node: '>= 12.0.0'} 2261 + cpu: [x64] 2262 + os: [darwin] 2263 + 2264 + lightningcss-freebsd-x64@1.29.2: 2265 + resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==} 2266 + engines: {node: '>= 12.0.0'} 2267 + cpu: [x64] 2268 + os: [freebsd] 2269 + 2270 + lightningcss-linux-arm-gnueabihf@1.29.2: 2271 + resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==} 2272 + engines: {node: '>= 12.0.0'} 2273 + cpu: [arm] 2274 + os: [linux] 2275 + 2276 + lightningcss-linux-arm64-gnu@1.29.2: 2277 + resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==} 2278 + engines: {node: '>= 12.0.0'} 2279 + cpu: [arm64] 2280 + os: [linux] 2281 + 2282 + lightningcss-linux-arm64-musl@1.29.2: 2283 + resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==} 2284 + engines: {node: '>= 12.0.0'} 2285 + cpu: [arm64] 2286 + os: [linux] 2287 + 2288 + lightningcss-linux-x64-gnu@1.29.2: 2289 + resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==} 2290 + engines: {node: '>= 12.0.0'} 2291 + cpu: [x64] 2292 + os: [linux] 2293 + 2294 + lightningcss-linux-x64-musl@1.29.2: 2295 + resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==} 2296 + engines: {node: '>= 12.0.0'} 2297 + cpu: [x64] 2298 + os: [linux] 2299 + 2300 + lightningcss-win32-arm64-msvc@1.29.2: 2301 + resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==} 2302 + engines: {node: '>= 12.0.0'} 2303 + cpu: [arm64] 2304 + os: [win32] 2305 + 2306 + lightningcss-win32-x64-msvc@1.29.2: 2307 + resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==} 2308 + engines: {node: '>= 12.0.0'} 2309 + cpu: [x64] 2310 + os: [win32] 2311 + 2312 + lightningcss@1.29.2: 2313 + resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} 2314 + engines: {node: '>= 12.0.0'} 2315 + 2316 + lines-and-columns@1.2.4: 2317 + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 2318 + 2319 + linkify-it@5.0.0: 2320 + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} 2321 + 2322 + linkifyjs@4.2.0: 2323 + resolution: {integrity: sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw==} 2324 + 2325 + locate-path@7.2.0: 2326 + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} 2327 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 2328 + 2329 + lodash.camelcase@4.3.0: 2330 + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} 2331 + 2332 + lodash.isplainobject@4.0.6: 2333 + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} 2334 + 2335 + lodash.kebabcase@4.1.1: 2336 + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} 2337 + 2338 + lodash.merge@4.6.2: 2339 + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 2340 + 2341 + lodash.mergewith@4.6.2: 2342 + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} 2343 + 2344 + lodash.snakecase@4.1.1: 2345 + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} 2346 + 2347 + lodash.startcase@4.4.0: 2348 + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 2349 + 2350 + lodash.uniq@4.5.0: 2351 + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} 2352 + 2353 + lodash.upperfirst@4.3.1: 2354 + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} 2355 + 2356 + lru-cache@5.1.1: 2357 + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 2358 + 2359 + lucide-react@0.488.0: 2360 + resolution: {integrity: sha512-ronlL0MyKut4CEzBY/ai2ZpKPxyWO4jUqdAkm2GNK5Zn3Rj+swDz+3lvyAUXN0PNqPKIX6XM9Xadwz/skLs/pQ==} 2361 + peerDependencies: 2362 + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 2363 + 2364 + make-dir@3.1.0: 2365 + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 2366 + engines: {node: '>=8'} 2367 + 2368 + markdown-it@14.1.0: 2369 + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} 2370 + hasBin: true 2371 + 2372 + mdurl@2.0.0: 2373 + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} 2374 + 2375 + meow@12.1.1: 2376 + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} 2377 + engines: {node: '>=16.10'} 2378 + 2379 + mimic-response@3.1.0: 2380 + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 2381 + engines: {node: '>=10'} 2382 + 2383 + minimatch@3.1.2: 2384 + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 2385 + 2386 + minimist@1.2.8: 2387 + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 2388 + 2389 + minipass@3.3.6: 2390 + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} 2391 + engines: {node: '>=8'} 2392 + 2393 + minipass@5.0.0: 2394 + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 2395 + engines: {node: '>=8'} 2396 + 2397 + minizlib@2.1.2: 2398 + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 2399 + engines: {node: '>= 8'} 2400 + 2401 + mkdirp-classic@0.5.3: 2402 + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} 2403 + 2404 + mkdirp@1.0.4: 2405 + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 2406 + engines: {node: '>=10'} 2407 + hasBin: true 2408 + 2409 + motion-dom@12.6.1: 2410 + resolution: {integrity: sha512-8XVsriTUEVOepoIDgE/LDGdg7qaKXWdt+wQA/8z0p8YzJDLYL8gbimZ3YkCLlj7bB2i/4UBD/g+VO7y9ZY0zHQ==} 2411 + 2412 + motion-utils@12.5.0: 2413 + resolution: {integrity: sha512-+hFFzvimn0sBMP9iPxBa9OtRX35ZQ3py0UHnb8U29VD+d8lQ8zH3dTygJWqK7av2v6yhg7scj9iZuvTS0f4+SA==} 2414 + 2415 + ms@2.1.3: 2416 + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 2417 + 2418 + nanoid@3.3.11: 2419 + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 2420 + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 2421 + hasBin: true 2422 + 2423 + napi-build-utils@2.0.0: 2424 + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} 2425 + 2426 + node-abi@3.74.0: 2427 + resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} 2428 + engines: {node: '>=10'} 2429 + 2430 + node-addon-api@5.1.0: 2431 + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} 2432 + 2433 + node-fetch@2.7.0: 2434 + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 2435 + engines: {node: 4.x || >=6.0.0} 2436 + peerDependencies: 2437 + encoding: ^0.1.0 2438 + peerDependenciesMeta: 2439 + encoding: 2440 + optional: true 2441 + 2442 + node-releases@2.0.19: 2443 + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 2444 + 2445 + nopt@5.0.0: 2446 + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} 2447 + engines: {node: '>=6'} 2448 + hasBin: true 2449 + 2450 + normalize-path@3.0.0: 2451 + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 2452 + engines: {node: '>=0.10.0'} 2453 + 2454 + npmlog@5.0.1: 2455 + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} 2456 + deprecated: This package is no longer supported. 2457 + 2458 + object-assign@4.1.1: 2459 + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 2460 + engines: {node: '>=0.10.0'} 2461 + 2462 + once@1.4.0: 2463 + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 2464 + 2465 + orderedmap@2.1.1: 2466 + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} 2467 + 2468 + p-limit@4.0.0: 2469 + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} 2470 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 2471 + 2472 + p-locate@6.0.0: 2473 + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} 2474 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 2475 + 2476 + parent-module@1.0.1: 2477 + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 2478 + engines: {node: '>=6'} 2479 + 2480 + parse-json@5.2.0: 2481 + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} 2482 + engines: {node: '>=8'} 2483 + 2484 + path-exists@5.0.0: 2485 + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} 2486 + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 2487 + 2488 + path-is-absolute@1.0.1: 2489 + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 2490 + engines: {node: '>=0.10.0'} 2491 + 2492 + picocolors@1.1.1: 2493 + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 2494 + 2495 + picomatch@2.3.1: 2496 + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 2497 + engines: {node: '>=8.6'} 2498 + 2499 + postcss@8.5.3: 2500 + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} 2501 + engines: {node: ^10 || ^12 || >=14} 2502 + 2503 + prebuild-install@7.1.3: 2504 + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} 2505 + engines: {node: '>=10'} 2506 + hasBin: true 2507 + 2508 + prettier@3.5.3: 2509 + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} 2510 + engines: {node: '>=14'} 2511 + hasBin: true 2512 + 2513 + prosemirror-changeset@2.2.1: 2514 + resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==} 2515 + 2516 + prosemirror-collab@1.3.1: 2517 + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} 2518 + 2519 + prosemirror-commands@1.7.0: 2520 + resolution: {integrity: sha512-6toodS4R/Aah5pdsrIwnTYPEjW70SlO5a66oo5Kk+CIrgJz3ukOoS+FYDGqvQlAX5PxoGWDX1oD++tn5X3pyRA==} 2521 + 2522 + prosemirror-dropcursor@1.8.1: 2523 + resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} 2524 + 2525 + prosemirror-gapcursor@1.3.2: 2526 + resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} 2527 + 2528 + prosemirror-history@1.4.1: 2529 + resolution: {integrity: sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==} 2530 + 2531 + prosemirror-inputrules@1.5.0: 2532 + resolution: {integrity: sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==} 2533 + 2534 + prosemirror-keymap@1.2.2: 2535 + resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} 2536 + 2537 + prosemirror-markdown@1.13.2: 2538 + resolution: {integrity: sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==} 2539 + 2540 + prosemirror-menu@1.2.4: 2541 + resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} 2542 + 2543 + prosemirror-model@1.25.0: 2544 + resolution: {integrity: sha512-/8XUmxWf0pkj2BmtqZHYJipTBMHIdVjuvFzMvEoxrtyGNmfvdhBiRwYt/eFwy2wA9DtBW3RLqvZnjurEkHaFCw==} 2545 + 2546 + prosemirror-schema-basic@1.2.4: 2547 + resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==} 2548 + 2549 + prosemirror-schema-list@1.5.1: 2550 + resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==} 2551 + 2552 + prosemirror-state@1.4.3: 2553 + resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} 2554 + 2555 + prosemirror-tables@1.6.4: 2556 + resolution: {integrity: sha512-TkDY3Gw52gRFRfRn2f4wJv5WOgAOXLJA2CQJYIJ5+kdFbfj3acR4JUW6LX2e1hiEBiUwvEhzH5a3cZ5YSztpIA==} 2557 + 2558 + prosemirror-trailing-node@3.0.0: 2559 + resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==} 2560 + peerDependencies: 2561 + prosemirror-model: ^1.22.1 2562 + prosemirror-state: ^1.4.2 2563 + prosemirror-view: ^1.33.8 2564 + 2565 + prosemirror-transform@1.10.3: 2566 + resolution: {integrity: sha512-Nhh/+1kZGRINbEHmVu39oynhcap4hWTs/BlU7NnxWj3+l0qi8I1mu67v6mMdEe/ltD8hHvU4FV6PHiCw2VSpMw==} 2567 + 2568 + prosemirror-view@1.38.1: 2569 + resolution: {integrity: sha512-4FH/uM1A4PNyrxXbD+RAbAsf0d/mM0D/wAKSVVWK7o0A9Q/oOXJBrw786mBf2Vnrs/Edly6dH6Z2gsb7zWwaUw==} 2570 + 2571 + pump@3.0.2: 2572 + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} 2573 + 2574 + punycode.js@2.3.1: 2575 + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} 2576 + engines: {node: '>=6'} 2577 + 2578 + rc@1.2.8: 2579 + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} 2580 + hasBin: true 2581 + 2582 + react-day-picker@8.10.1: 2583 + resolution: {integrity: sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==} 2584 + peerDependencies: 2585 + date-fns: ^2.28.0 || ^3.0.0 2586 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 2587 + 2588 + react-dom@19.1.0: 2589 + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} 2590 + peerDependencies: 2591 + react: ^19.1.0 2592 + 2593 + react-hook-form@7.55.0: 2594 + resolution: {integrity: sha512-XRnjsH3GVMQz1moZTW53MxfoWN7aDpUg/GpVNc4A3eXRVNdGXfbzJ4vM4aLQ8g6XCUh1nIbx70aaNCl7kxnjog==} 2595 + engines: {node: '>=18.0.0'} 2596 + peerDependencies: 2597 + react: ^16.8.0 || ^17 || ^18 || ^19 2598 + 2599 + react-refresh@0.14.2: 2600 + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} 2601 + engines: {node: '>=0.10.0'} 2602 + 2603 + react-remove-scroll-bar@2.3.8: 2604 + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} 2605 + engines: {node: '>=10'} 2606 + peerDependencies: 2607 + '@types/react': '*' 2608 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 2609 + peerDependenciesMeta: 2610 + '@types/react': 2611 + optional: true 2612 + 2613 + react-remove-scroll@2.6.3: 2614 + resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} 2615 + engines: {node: '>=10'} 2616 + peerDependencies: 2617 + '@types/react': '*' 2618 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2619 + peerDependenciesMeta: 2620 + '@types/react': 2621 + optional: true 2622 + 2623 + react-style-singleton@2.2.3: 2624 + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} 2625 + engines: {node: '>=10'} 2626 + peerDependencies: 2627 + '@types/react': '*' 2628 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2629 + peerDependenciesMeta: 2630 + '@types/react': 2631 + optional: true 2632 + 2633 + react-use-websocket@4.13.0: 2634 + resolution: {integrity: sha512-anMuVoV//g2N76Wxqvqjjo1X48r9Np3y1/gMl7arX84tAPXdy5R7sB5lO5hvCzQRYjqXwV8XMAiEBOUbyrZFrw==} 2635 + 2636 + react@19.1.0: 2637 + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} 2638 + engines: {node: '>=0.10.0'} 2639 + 2640 + readable-stream@3.6.2: 2641 + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 2642 + engines: {node: '>= 6'} 2643 + 2644 + readdirp@3.6.0: 2645 + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 2646 + engines: {node: '>=8.10.0'} 2647 + 2648 + require-directory@2.1.1: 2649 + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 2650 + engines: {node: '>=0.10.0'} 2651 + 2652 + require-from-string@2.0.2: 2653 + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 2654 + engines: {node: '>=0.10.0'} 2655 + 2656 + resolve-from@4.0.0: 2657 + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 2658 + engines: {node: '>=4'} 2659 + 2660 + resolve-from@5.0.0: 2661 + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 2662 + engines: {node: '>=8'} 2663 + 2664 + resolve-pkg-maps@1.0.0: 2665 + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 2666 + 2667 + rimraf@3.0.2: 2668 + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 2669 + deprecated: Rimraf versions prior to v4 are no longer supported 2670 + hasBin: true 2671 + 2672 + rollup@4.38.0: 2673 + resolution: {integrity: sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==} 2674 + engines: {node: '>=18.0.0', npm: '>=8.0.0'} 2675 + hasBin: true 2676 + 2677 + rope-sequence@1.3.4: 2678 + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} 2679 + 2680 + safe-buffer@5.2.1: 2681 + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 2682 + 2683 + scheduler@0.26.0: 2684 + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} 2685 + 2686 + semver@6.3.1: 2687 + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 2688 + hasBin: true 2689 + 2690 + semver@7.7.1: 2691 + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 2692 + engines: {node: '>=10'} 2693 + hasBin: true 2694 + 2695 + seroval-plugins@1.2.1: 2696 + resolution: {integrity: sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw==} 2697 + engines: {node: '>=10'} 2698 + peerDependencies: 2699 + seroval: ^1.0 2700 + 2701 + seroval@1.2.1: 2702 + resolution: {integrity: sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw==} 2703 + engines: {node: '>=10'} 2704 + 2705 + set-blocking@2.0.0: 2706 + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} 2707 + 2708 + signal-exit@3.0.7: 2709 + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 2710 + 2711 + simple-concat@1.0.1: 2712 + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} 2713 + 2714 + simple-get@4.0.1: 2715 + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} 2716 + 2717 + solid-js@1.9.5: 2718 + resolution: {integrity: sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw==} 2719 + 2720 + sonner@2.0.2: 2721 + resolution: {integrity: sha512-xOeXErZ4blqQd11ZnlDmoRmg+ctUJBkTU8H+HVh9rnWi9Ke28xiL39r4iCTeDX31ODTe/s1MaiaY333dUzLCtA==} 2722 + peerDependencies: 2723 + react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2724 + react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2725 + 2726 + source-map-js@1.2.1: 2727 + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 2728 + engines: {node: '>=0.10.0'} 2729 + 2730 + split2@4.2.0: 2731 + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 2732 + engines: {node: '>= 10.x'} 2733 + 2734 + string-width@4.2.3: 2735 + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 2736 + engines: {node: '>=8'} 2737 + 2738 + string_decoder@1.3.0: 2739 + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 2740 + 2741 + strip-ansi@6.0.1: 2742 + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 2743 + engines: {node: '>=8'} 2744 + 2745 + strip-json-comments@2.0.1: 2746 + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} 2747 + engines: {node: '>=0.10.0'} 2748 + 2749 + tailwind-merge@3.0.2: 2750 + resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==} 2751 + 2752 + tailwindcss-animate@1.0.7: 2753 + resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} 2754 + peerDependencies: 2755 + tailwindcss: '>=3.0.0 || insiders' 2756 + 2757 + tailwindcss@4.0.17: 2758 + resolution: {integrity: sha512-OErSiGzRa6rLiOvaipsDZvLMSpsBZ4ysB4f0VKGXUrjw2jfkJRd6kjRKV2+ZmTCNvwtvgdDam5D7w6WXsdLJZw==} 2759 + 2760 + tapable@2.2.1: 2761 + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} 2762 + engines: {node: '>=6'} 2763 + 2764 + tar-fs@2.1.2: 2765 + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} 2766 + 2767 + tar-stream@2.2.0: 2768 + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} 2769 + engines: {node: '>=6'} 2770 + 2771 + tar@6.2.1: 2772 + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} 2773 + engines: {node: '>=10'} 2774 + 2775 + text-extensions@2.4.0: 2776 + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} 2777 + engines: {node: '>=8'} 2778 + 2779 + through@2.3.8: 2780 + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} 2781 + 2782 + tiny-invariant@1.3.3: 2783 + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} 2784 + 2785 + tiny-warning@1.0.3: 2786 + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} 2787 + 2788 + tinyexec@0.3.2: 2789 + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} 2790 + 2791 + tippy.js@6.3.7: 2792 + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} 2793 + 2794 + to-regex-range@5.0.1: 2795 + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 2796 + engines: {node: '>=8.0'} 2797 + 2798 + tr46@0.0.3: 2799 + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 2800 + 2801 + tslib@2.8.1: 2802 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 2803 + 2804 + tsx@4.19.3: 2805 + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} 2806 + engines: {node: '>=18.0.0'} 2807 + hasBin: true 2808 + 2809 + tunnel-agent@0.6.0: 2810 + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} 2811 + 2812 + turbo-darwin-64@2.4.4: 2813 + resolution: {integrity: sha512-5kPvRkLAfmWI0MH96D+/THnDMGXlFNmjeqNRj5grLKiry+M9pKj3pRuScddAXPdlxjO5Ptz06UNaOQrrYGTx1g==} 2814 + cpu: [x64] 2815 + os: [darwin] 2816 + 2817 + turbo-darwin-arm64@2.4.4: 2818 + resolution: {integrity: sha512-/gtHPqbGQXDFhrmy+Q/MFW2HUTUlThJ97WLLSe4bxkDrKHecDYhAjbZ4rN3MM93RV9STQb3Tqy4pZBtsd4DfCw==} 2819 + cpu: [arm64] 2820 + os: [darwin] 2821 + 2822 + turbo-linux-64@2.4.4: 2823 + resolution: {integrity: sha512-SR0gri4k0bda56hw5u9VgDXLKb1Q+jrw4lM7WAhnNdXvVoep4d6LmnzgMHQQR12Wxl3KyWPbkz9d1whL6NTm2Q==} 2824 + cpu: [x64] 2825 + os: [linux] 2826 + 2827 + turbo-linux-arm64@2.4.4: 2828 + resolution: {integrity: sha512-COXXwzRd3vslQIfJhXUklgEqlwq35uFUZ7hnN+AUyXx7hUOLIiD5NblL+ETrHnhY4TzWszrbwUMfe2BYWtaPQg==} 2829 + cpu: [arm64] 2830 + os: [linux] 2831 + 2832 + turbo-windows-64@2.4.4: 2833 + resolution: {integrity: sha512-PV9rYNouGz4Ff3fd6sIfQy5L7HT9a4fcZoEv8PKRavU9O75G7PoDtm8scpHU10QnK0QQNLbE9qNxOAeRvF0fJg==} 2834 + cpu: [x64] 2835 + os: [win32] 2836 + 2837 + turbo-windows-arm64@2.4.4: 2838 + resolution: {integrity: sha512-403sqp9t5sx6YGEC32IfZTVWkRAixOQomGYB8kEc6ZD+//LirSxzeCHCnM8EmSXw7l57U1G+Fb0kxgTcKPU/Lg==} 2839 + cpu: [arm64] 2840 + os: [win32] 2841 + 2842 + turbo@2.4.4: 2843 + resolution: {integrity: sha512-N9FDOVaY3yz0YCOhYIgOGYad7+m2ptvinXygw27WPLQvcZDl3+0Sa77KGVlLSiuPDChOUEnTKE9VJwLSi9BPGQ==} 2844 + hasBin: true 2845 + 2846 + typescript@5.5.4: 2847 + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} 2848 + engines: {node: '>=14.17'} 2849 + hasBin: true 2850 + 2851 + typescript@5.8.2: 2852 + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 2853 + engines: {node: '>=14.17'} 2854 + hasBin: true 2855 + 2856 + typescript@5.8.3: 2857 + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 2858 + engines: {node: '>=14.17'} 2859 + hasBin: true 2860 + 2861 + uc.micro@2.1.0: 2862 + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} 2863 + 2864 + undici-types@6.20.0: 2865 + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 2866 + 2867 + undici-types@6.21.0: 2868 + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} 2869 + 2870 + unicorn-magic@0.1.0: 2871 + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} 2872 + engines: {node: '>=18'} 2873 + 2874 + unplugin@2.2.2: 2875 + resolution: {integrity: sha512-Qp+iiD+qCRnUek+nDoYvtWX7tfnYyXsrOnJ452FRTgOyKmTM7TUJ3l+PLPJOOWPTUyKISKp4isC5JJPSXUjGgw==} 2876 + engines: {node: '>=18.12.0'} 2877 + 2878 + update-browserslist-db@1.1.3: 2879 + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 2880 + hasBin: true 2881 + peerDependencies: 2882 + browserslist: '>= 4.21.0' 2883 + 2884 + use-callback-ref@1.3.3: 2885 + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} 2886 + engines: {node: '>=10'} 2887 + peerDependencies: 2888 + '@types/react': '*' 2889 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2890 + peerDependenciesMeta: 2891 + '@types/react': 2892 + optional: true 2893 + 2894 + use-sidecar@1.1.3: 2895 + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} 2896 + engines: {node: '>=10'} 2897 + peerDependencies: 2898 + '@types/react': '*' 2899 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc 2900 + peerDependenciesMeta: 2901 + '@types/react': 2902 + optional: true 2903 + 2904 + use-sync-external-store@1.5.0: 2905 + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} 2906 + peerDependencies: 2907 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 2908 + 2909 + util-deprecate@1.0.2: 2910 + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 2911 + 2912 + vite@6.2.3: 2913 + resolution: {integrity: sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==} 2914 + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 2915 + hasBin: true 2916 + peerDependencies: 2917 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 2918 + jiti: '>=1.21.0' 2919 + less: '*' 2920 + lightningcss: ^1.21.0 2921 + sass: '*' 2922 + sass-embedded: '*' 2923 + stylus: '*' 2924 + sugarss: '*' 2925 + terser: ^5.16.0 2926 + tsx: ^4.8.1 2927 + yaml: ^2.4.2 2928 + peerDependenciesMeta: 2929 + '@types/node': 2930 + optional: true 2931 + jiti: 2932 + optional: true 2933 + less: 2934 + optional: true 2935 + lightningcss: 2936 + optional: true 2937 + sass: 2938 + optional: true 2939 + sass-embedded: 2940 + optional: true 2941 + stylus: 2942 + optional: true 2943 + sugarss: 2944 + optional: true 2945 + terser: 2946 + optional: true 2947 + tsx: 2948 + optional: true 2949 + yaml: 2950 + optional: true 2951 + 2952 + w3c-keyname@2.2.8: 2953 + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} 2954 + 2955 + webidl-conversions@3.0.1: 2956 + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 2957 + 2958 + webpack-virtual-modules@0.6.2: 2959 + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} 2960 + 2961 + whatwg-url@5.0.0: 2962 + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 2963 + 2964 + wide-align@1.1.5: 2965 + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} 2966 + 2967 + wrap-ansi@7.0.0: 2968 + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 2969 + engines: {node: '>=10'} 2970 + 2971 + wrappy@1.0.2: 2972 + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 2973 + 2974 + y18n@5.0.8: 2975 + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 2976 + engines: {node: '>=10'} 2977 + 2978 + yallist@3.1.1: 2979 + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 2980 + 2981 + yallist@4.0.0: 2982 + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 2983 + 2984 + yargs-parser@21.1.1: 2985 + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 2986 + engines: {node: '>=12'} 2987 + 2988 + yargs@17.7.2: 2989 + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} 2990 + engines: {node: '>=12'} 2991 + 2992 + yocto-queue@1.2.1: 2993 + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} 2994 + engines: {node: '>=12.20'} 2995 + 2996 + zod@3.24.3: 2997 + resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==} 2998 + 2999 + zustand@5.0.3: 3000 + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} 3001 + engines: {node: '>=12.20.0'} 3002 + peerDependencies: 3003 + '@types/react': '>=18.0.0' 3004 + immer: '>=9.0.6' 3005 + react: '>=18.0.0' 3006 + use-sync-external-store: '>=1.2.0' 3007 + peerDependenciesMeta: 3008 + '@types/react': 3009 + optional: true 3010 + immer: 3011 + optional: true 3012 + react: 3013 + optional: true 3014 + use-sync-external-store: 3015 + optional: true 3016 + 3017 + snapshots: 3018 + 3019 + '@alloc/quick-lru@5.2.0': {} 3020 + 3021 + '@ampproject/remapping@2.3.0': 3022 + dependencies: 3023 + '@jridgewell/gen-mapping': 0.3.8 3024 + '@jridgewell/trace-mapping': 0.3.25 3025 + 3026 + '@babel/code-frame@7.26.2': 3027 + dependencies: 3028 + '@babel/helper-validator-identifier': 7.25.9 3029 + js-tokens: 4.0.0 3030 + picocolors: 1.1.1 3031 + 3032 + '@babel/compat-data@7.26.8': {} 3033 + 3034 + '@babel/core@7.26.10': 3035 + dependencies: 3036 + '@ampproject/remapping': 2.3.0 3037 + '@babel/code-frame': 7.26.2 3038 + '@babel/generator': 7.27.0 3039 + '@babel/helper-compilation-targets': 7.27.0 3040 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) 3041 + '@babel/helpers': 7.27.0 3042 + '@babel/parser': 7.27.0 3043 + '@babel/template': 7.27.0 3044 + '@babel/traverse': 7.27.0 3045 + '@babel/types': 7.27.0 3046 + convert-source-map: 2.0.0 3047 + debug: 4.4.0 3048 + gensync: 1.0.0-beta.2 3049 + json5: 2.2.3 3050 + semver: 6.3.1 3051 + transitivePeerDependencies: 3052 + - supports-color 3053 + 3054 + '@babel/generator@7.27.0': 3055 + dependencies: 3056 + '@babel/parser': 7.27.0 3057 + '@babel/types': 7.27.0 3058 + '@jridgewell/gen-mapping': 0.3.8 3059 + '@jridgewell/trace-mapping': 0.3.25 3060 + jsesc: 3.1.0 3061 + 3062 + '@babel/helper-compilation-targets@7.27.0': 3063 + dependencies: 3064 + '@babel/compat-data': 7.26.8 3065 + '@babel/helper-validator-option': 7.25.9 3066 + browserslist: 4.24.4 3067 + lru-cache: 5.1.1 3068 + semver: 6.3.1 3069 + 3070 + '@babel/helper-module-imports@7.25.9': 3071 + dependencies: 3072 + '@babel/traverse': 7.27.0 3073 + '@babel/types': 7.27.0 3074 + transitivePeerDependencies: 3075 + - supports-color 3076 + 3077 + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': 3078 + dependencies: 3079 + '@babel/core': 7.26.10 3080 + '@babel/helper-module-imports': 7.25.9 3081 + '@babel/helper-validator-identifier': 7.25.9 3082 + '@babel/traverse': 7.27.0 3083 + transitivePeerDependencies: 3084 + - supports-color 3085 + 3086 + '@babel/helper-plugin-utils@7.26.5': {} 3087 + 3088 + '@babel/helper-string-parser@7.25.9': {} 3089 + 3090 + '@babel/helper-validator-identifier@7.25.9': {} 3091 + 3092 + '@babel/helper-validator-option@7.25.9': {} 3093 + 3094 + '@babel/helpers@7.27.0': 3095 + dependencies: 3096 + '@babel/template': 7.27.0 3097 + '@babel/types': 7.27.0 3098 + 3099 + '@babel/parser@7.27.0': 3100 + dependencies: 3101 + '@babel/types': 7.27.0 3102 + 3103 + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': 3104 + dependencies: 3105 + '@babel/core': 7.26.10 3106 + '@babel/helper-plugin-utils': 7.26.5 3107 + 3108 + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': 3109 + dependencies: 3110 + '@babel/core': 7.26.10 3111 + '@babel/helper-plugin-utils': 7.26.5 3112 + 3113 + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.10)': 3114 + dependencies: 3115 + '@babel/core': 7.26.10 3116 + '@babel/helper-plugin-utils': 7.26.5 3117 + 3118 + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.10)': 3119 + dependencies: 3120 + '@babel/core': 7.26.10 3121 + '@babel/helper-plugin-utils': 7.26.5 3122 + 3123 + '@babel/template@7.27.0': 3124 + dependencies: 3125 + '@babel/code-frame': 7.26.2 3126 + '@babel/parser': 7.27.0 3127 + '@babel/types': 7.27.0 3128 + 3129 + '@babel/traverse@7.27.0': 3130 + dependencies: 3131 + '@babel/code-frame': 7.26.2 3132 + '@babel/generator': 7.27.0 3133 + '@babel/parser': 7.27.0 3134 + '@babel/template': 7.27.0 3135 + '@babel/types': 7.27.0 3136 + debug: 4.4.0 3137 + globals: 11.12.0 3138 + transitivePeerDependencies: 3139 + - supports-color 3140 + 3141 + '@babel/types@7.27.0': 3142 + dependencies: 3143 + '@babel/helper-string-parser': 7.25.9 3144 + '@babel/helper-validator-identifier': 7.25.9 3145 + 3146 + '@biomejs/biome@1.9.4': 3147 + optionalDependencies: 3148 + '@biomejs/cli-darwin-arm64': 1.9.4 3149 + '@biomejs/cli-darwin-x64': 1.9.4 3150 + '@biomejs/cli-linux-arm64': 1.9.4 3151 + '@biomejs/cli-linux-arm64-musl': 1.9.4 3152 + '@biomejs/cli-linux-x64': 1.9.4 3153 + '@biomejs/cli-linux-x64-musl': 1.9.4 3154 + '@biomejs/cli-win32-arm64': 1.9.4 3155 + '@biomejs/cli-win32-x64': 1.9.4 3156 + 3157 + '@biomejs/cli-darwin-arm64@1.9.4': 3158 + optional: true 3159 + 3160 + '@biomejs/cli-darwin-x64@1.9.4': 3161 + optional: true 3162 + 3163 + '@biomejs/cli-linux-arm64-musl@1.9.4': 3164 + optional: true 3165 + 3166 + '@biomejs/cli-linux-arm64@1.9.4': 3167 + optional: true 3168 + 3169 + '@biomejs/cli-linux-x64-musl@1.9.4': 3170 + optional: true 3171 + 3172 + '@biomejs/cli-linux-x64@1.9.4': 3173 + optional: true 3174 + 3175 + '@biomejs/cli-win32-arm64@1.9.4': 3176 + optional: true 3177 + 3178 + '@biomejs/cli-win32-x64@1.9.4': 3179 + optional: true 3180 + 3181 + '@commitlint/cli@19.8.0(@types/node@22.14.1)(typescript@5.5.4)': 3182 + dependencies: 3183 + '@commitlint/format': 19.8.0 3184 + '@commitlint/lint': 19.8.0 3185 + '@commitlint/load': 19.8.0(@types/node@22.14.1)(typescript@5.5.4) 3186 + '@commitlint/read': 19.8.0 3187 + '@commitlint/types': 19.8.0 3188 + tinyexec: 0.3.2 3189 + yargs: 17.7.2 3190 + transitivePeerDependencies: 3191 + - '@types/node' 3192 + - typescript 3193 + 3194 + '@commitlint/config-conventional@19.8.0': 3195 + dependencies: 3196 + '@commitlint/types': 19.8.0 3197 + conventional-changelog-conventionalcommits: 7.0.2 3198 + 3199 + '@commitlint/config-validator@19.8.0': 3200 + dependencies: 3201 + '@commitlint/types': 19.8.0 3202 + ajv: 8.17.1 3203 + 3204 + '@commitlint/ensure@19.8.0': 3205 + dependencies: 3206 + '@commitlint/types': 19.8.0 3207 + lodash.camelcase: 4.3.0 3208 + lodash.kebabcase: 4.1.1 3209 + lodash.snakecase: 4.1.1 3210 + lodash.startcase: 4.4.0 3211 + lodash.upperfirst: 4.3.1 3212 + 3213 + '@commitlint/execute-rule@19.8.0': {} 3214 + 3215 + '@commitlint/format@19.8.0': 3216 + dependencies: 3217 + '@commitlint/types': 19.8.0 3218 + chalk: 5.4.1 3219 + 3220 + '@commitlint/is-ignored@19.8.0': 3221 + dependencies: 3222 + '@commitlint/types': 19.8.0 3223 + semver: 7.7.1 3224 + 3225 + '@commitlint/lint@19.8.0': 3226 + dependencies: 3227 + '@commitlint/is-ignored': 19.8.0 3228 + '@commitlint/parse': 19.8.0 3229 + '@commitlint/rules': 19.8.0 3230 + '@commitlint/types': 19.8.0 3231 + 3232 + '@commitlint/load@19.8.0(@types/node@22.14.1)(typescript@5.5.4)': 3233 + dependencies: 3234 + '@commitlint/config-validator': 19.8.0 3235 + '@commitlint/execute-rule': 19.8.0 3236 + '@commitlint/resolve-extends': 19.8.0 3237 + '@commitlint/types': 19.8.0 3238 + chalk: 5.4.1 3239 + cosmiconfig: 9.0.0(typescript@5.5.4) 3240 + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.14.1)(cosmiconfig@9.0.0(typescript@5.5.4))(typescript@5.5.4) 3241 + lodash.isplainobject: 4.0.6 3242 + lodash.merge: 4.6.2 3243 + lodash.uniq: 4.5.0 3244 + transitivePeerDependencies: 3245 + - '@types/node' 3246 + - typescript 3247 + 3248 + '@commitlint/message@19.8.0': {} 3249 + 3250 + '@commitlint/parse@19.8.0': 3251 + dependencies: 3252 + '@commitlint/types': 19.8.0 3253 + conventional-changelog-angular: 7.0.0 3254 + conventional-commits-parser: 5.0.0 3255 + 3256 + '@commitlint/read@19.8.0': 3257 + dependencies: 3258 + '@commitlint/top-level': 19.8.0 3259 + '@commitlint/types': 19.8.0 3260 + git-raw-commits: 4.0.0 3261 + minimist: 1.2.8 3262 + tinyexec: 0.3.2 3263 + 3264 + '@commitlint/resolve-extends@19.8.0': 3265 + dependencies: 3266 + '@commitlint/config-validator': 19.8.0 3267 + '@commitlint/types': 19.8.0 3268 + global-directory: 4.0.1 3269 + import-meta-resolve: 4.1.0 3270 + lodash.mergewith: 4.6.2 3271 + resolve-from: 5.0.0 3272 + 3273 + '@commitlint/rules@19.8.0': 3274 + dependencies: 3275 + '@commitlint/ensure': 19.8.0 3276 + '@commitlint/message': 19.8.0 3277 + '@commitlint/to-lines': 19.8.0 3278 + '@commitlint/types': 19.8.0 3279 + 3280 + '@commitlint/to-lines@19.8.0': {} 3281 + 3282 + '@commitlint/top-level@19.8.0': 3283 + dependencies: 3284 + find-up: 7.0.0 3285 + 3286 + '@commitlint/types@19.8.0': 3287 + dependencies: 3288 + '@types/conventional-commits-parser': 5.0.1 3289 + chalk: 5.4.1 3290 + 3291 + '@dnd-kit/accessibility@3.1.1(react@19.1.0)': 3292 + dependencies: 3293 + react: 19.1.0 3294 + tslib: 2.8.1 3295 + 3296 + '@dnd-kit/core@6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3297 + dependencies: 3298 + '@dnd-kit/accessibility': 3.1.1(react@19.1.0) 3299 + '@dnd-kit/utilities': 3.2.2(react@19.1.0) 3300 + react: 19.1.0 3301 + react-dom: 19.1.0(react@19.1.0) 3302 + tslib: 2.8.1 3303 + 3304 + '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)': 3305 + dependencies: 3306 + '@dnd-kit/core': 6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3307 + '@dnd-kit/utilities': 3.2.2(react@19.1.0) 3308 + react: 19.1.0 3309 + tslib: 2.8.1 3310 + 3311 + '@dnd-kit/utilities@3.2.2(react@19.1.0)': 3312 + dependencies: 3313 + react: 19.1.0 3314 + tslib: 2.8.1 3315 + 3316 + '@esbuild/aix-ppc64@0.25.2': 3317 + optional: true 3318 + 3319 + '@esbuild/android-arm64@0.25.2': 3320 + optional: true 3321 + 3322 + '@esbuild/android-arm@0.25.2': 3323 + optional: true 3324 + 3325 + '@esbuild/android-x64@0.25.2': 3326 + optional: true 3327 + 3328 + '@esbuild/darwin-arm64@0.25.2': 3329 + optional: true 3330 + 3331 + '@esbuild/darwin-x64@0.25.2': 3332 + optional: true 3333 + 3334 + '@esbuild/freebsd-arm64@0.25.2': 3335 + optional: true 3336 + 3337 + '@esbuild/freebsd-x64@0.25.2': 3338 + optional: true 3339 + 3340 + '@esbuild/linux-arm64@0.25.2': 3341 + optional: true 3342 + 3343 + '@esbuild/linux-arm@0.25.2': 3344 + optional: true 3345 + 3346 + '@esbuild/linux-ia32@0.25.2': 3347 + optional: true 3348 + 3349 + '@esbuild/linux-loong64@0.25.2': 3350 + optional: true 3351 + 3352 + '@esbuild/linux-mips64el@0.25.2': 3353 + optional: true 3354 + 3355 + '@esbuild/linux-ppc64@0.25.2': 3356 + optional: true 3357 + 3358 + '@esbuild/linux-riscv64@0.25.2': 3359 + optional: true 3360 + 3361 + '@esbuild/linux-s390x@0.25.2': 3362 + optional: true 3363 + 3364 + '@esbuild/linux-x64@0.25.2': 3365 + optional: true 3366 + 3367 + '@esbuild/netbsd-arm64@0.25.2': 3368 + optional: true 3369 + 3370 + '@esbuild/netbsd-x64@0.25.2': 3371 + optional: true 3372 + 3373 + '@esbuild/openbsd-arm64@0.25.2': 3374 + optional: true 3375 + 3376 + '@esbuild/openbsd-x64@0.25.2': 3377 + optional: true 3378 + 3379 + '@esbuild/sunos-x64@0.25.2': 3380 + optional: true 3381 + 3382 + '@esbuild/win32-arm64@0.25.2': 3383 + optional: true 3384 + 3385 + '@esbuild/win32-ia32@0.25.2': 3386 + optional: true 3387 + 3388 + '@esbuild/win32-x64@0.25.2': 3389 + optional: true 3390 + 3391 + '@floating-ui/core@1.6.9': 3392 + dependencies: 3393 + '@floating-ui/utils': 0.2.9 3394 + 3395 + '@floating-ui/dom@1.6.13': 3396 + dependencies: 3397 + '@floating-ui/core': 1.6.9 3398 + '@floating-ui/utils': 0.2.9 3399 + 3400 + '@floating-ui/react-dom@2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3401 + dependencies: 3402 + '@floating-ui/dom': 1.6.13 3403 + react: 19.1.0 3404 + react-dom: 19.1.0(react@19.1.0) 3405 + 3406 + '@floating-ui/utils@0.2.9': {} 3407 + 3408 + '@hono/node-server@1.14.1(hono@4.7.7)': 3409 + dependencies: 3410 + hono: 4.7.7 3411 + 3412 + '@hono/zod-validator@0.4.3(hono@4.7.7)(zod@3.24.3)': 3413 + dependencies: 3414 + hono: 4.7.7 3415 + zod: 3.24.3 3416 + 3417 + '@hookform/resolvers@5.0.1(react-hook-form@7.55.0(react@19.1.0))': 3418 + dependencies: 3419 + '@standard-schema/utils': 0.3.0 3420 + react-hook-form: 7.55.0(react@19.1.0) 3421 + 3422 + '@jridgewell/gen-mapping@0.3.8': 3423 + dependencies: 3424 + '@jridgewell/set-array': 1.2.1 3425 + '@jridgewell/sourcemap-codec': 1.5.0 3426 + '@jridgewell/trace-mapping': 0.3.25 3427 + 3428 + '@jridgewell/resolve-uri@3.1.2': {} 3429 + 3430 + '@jridgewell/set-array@1.2.1': {} 3431 + 3432 + '@jridgewell/sourcemap-codec@1.5.0': {} 3433 + 3434 + '@jridgewell/trace-mapping@0.3.25': 3435 + dependencies: 3436 + '@jridgewell/resolve-uri': 3.1.2 3437 + '@jridgewell/sourcemap-codec': 1.5.0 3438 + 3439 + '@mapbox/node-pre-gyp@1.0.11': 3440 + dependencies: 3441 + detect-libc: 2.0.3 3442 + https-proxy-agent: 5.0.1 3443 + make-dir: 3.1.0 3444 + node-fetch: 2.7.0 3445 + nopt: 5.0.0 3446 + npmlog: 5.0.1 3447 + rimraf: 3.0.2 3448 + semver: 7.7.1 3449 + tar: 6.2.1 3450 + transitivePeerDependencies: 3451 + - encoding 3452 + - supports-color 3453 + 3454 + '@noble/hashes@1.7.1': {} 3455 + 3456 + '@oslojs/asn1@1.0.0': 3457 + dependencies: 3458 + '@oslojs/binary': 1.0.0 3459 + 3460 + '@oslojs/binary@1.0.0': {} 3461 + 3462 + '@oslojs/crypto@1.0.1': 3463 + dependencies: 3464 + '@oslojs/asn1': 1.0.0 3465 + '@oslojs/binary': 1.0.0 3466 + 3467 + '@oslojs/encoding@1.1.0': {} 3468 + 3469 + '@paralleldrive/cuid2@2.2.2': 3470 + dependencies: 3471 + '@noble/hashes': 1.7.1 3472 + 3473 + '@popperjs/core@2.11.8': {} 3474 + 3475 + '@radix-ui/number@1.1.0': {} 3476 + 3477 + '@radix-ui/primitive@1.1.1': {} 3478 + 3479 + '@radix-ui/react-accordion@1.2.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3480 + dependencies: 3481 + '@radix-ui/primitive': 1.1.1 3482 + '@radix-ui/react-collapsible': 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3483 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3484 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3485 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3486 + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3487 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3488 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3489 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3490 + react: 19.1.0 3491 + react-dom: 19.1.0(react@19.1.0) 3492 + optionalDependencies: 3493 + '@types/react': 19.0.12 3494 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3495 + 3496 + '@radix-ui/react-arrow@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3497 + dependencies: 3498 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3499 + react: 19.1.0 3500 + react-dom: 19.1.0(react@19.1.0) 3501 + optionalDependencies: 3502 + '@types/react': 19.0.12 3503 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3504 + 3505 + '@radix-ui/react-avatar@1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3506 + dependencies: 3507 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3508 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3509 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3510 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3511 + react: 19.1.0 3512 + react-dom: 19.1.0(react@19.1.0) 3513 + optionalDependencies: 3514 + '@types/react': 19.0.12 3515 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3516 + 3517 + '@radix-ui/react-collapsible@1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3518 + dependencies: 3519 + '@radix-ui/primitive': 1.1.1 3520 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3521 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3522 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3523 + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3524 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3525 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3526 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3527 + react: 19.1.0 3528 + react-dom: 19.1.0(react@19.1.0) 3529 + optionalDependencies: 3530 + '@types/react': 19.0.12 3531 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3532 + 3533 + '@radix-ui/react-collection@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3534 + dependencies: 3535 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3536 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3537 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3538 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3539 + react: 19.1.0 3540 + react-dom: 19.1.0(react@19.1.0) 3541 + optionalDependencies: 3542 + '@types/react': 19.0.12 3543 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3544 + 3545 + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.12)(react@19.1.0)': 3546 + dependencies: 3547 + react: 19.1.0 3548 + optionalDependencies: 3549 + '@types/react': 19.0.12 3550 + 3551 + '@radix-ui/react-context@1.1.1(@types/react@19.0.12)(react@19.1.0)': 3552 + dependencies: 3553 + react: 19.1.0 3554 + optionalDependencies: 3555 + '@types/react': 19.0.12 3556 + 3557 + '@radix-ui/react-dialog@1.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3558 + dependencies: 3559 + '@radix-ui/primitive': 1.1.1 3560 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3561 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3562 + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3563 + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3564 + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3565 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3566 + '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3567 + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3568 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3569 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3570 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3571 + aria-hidden: 1.2.4 3572 + react: 19.1.0 3573 + react-dom: 19.1.0(react@19.1.0) 3574 + react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.1.0) 3575 + optionalDependencies: 3576 + '@types/react': 19.0.12 3577 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3578 + 3579 + '@radix-ui/react-direction@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3580 + dependencies: 3581 + react: 19.1.0 3582 + optionalDependencies: 3583 + '@types/react': 19.0.12 3584 + 3585 + '@radix-ui/react-dismissable-layer@1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3586 + dependencies: 3587 + '@radix-ui/primitive': 1.1.1 3588 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3589 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3590 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3591 + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3592 + react: 19.1.0 3593 + react-dom: 19.1.0(react@19.1.0) 3594 + optionalDependencies: 3595 + '@types/react': 19.0.12 3596 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3597 + 3598 + '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3599 + dependencies: 3600 + '@radix-ui/primitive': 1.1.1 3601 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3602 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3603 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3604 + '@radix-ui/react-menu': 2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3605 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3606 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3607 + react: 19.1.0 3608 + react-dom: 19.1.0(react@19.1.0) 3609 + optionalDependencies: 3610 + '@types/react': 19.0.12 3611 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3612 + 3613 + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.12)(react@19.1.0)': 3614 + dependencies: 3615 + react: 19.1.0 3616 + optionalDependencies: 3617 + '@types/react': 19.0.12 3618 + 3619 + '@radix-ui/react-focus-scope@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3620 + dependencies: 3621 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3622 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3623 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3624 + react: 19.1.0 3625 + react-dom: 19.1.0(react@19.1.0) 3626 + optionalDependencies: 3627 + '@types/react': 19.0.12 3628 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3629 + 3630 + '@radix-ui/react-id@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3631 + dependencies: 3632 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3633 + react: 19.1.0 3634 + optionalDependencies: 3635 + '@types/react': 19.0.12 3636 + 3637 + '@radix-ui/react-label@2.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3638 + dependencies: 3639 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3640 + react: 19.1.0 3641 + react-dom: 19.1.0(react@19.1.0) 3642 + optionalDependencies: 3643 + '@types/react': 19.0.12 3644 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3645 + 3646 + '@radix-ui/react-menu@2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3647 + dependencies: 3648 + '@radix-ui/primitive': 1.1.1 3649 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3650 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3651 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3652 + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3653 + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3654 + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3655 + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3656 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3657 + '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3658 + '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3659 + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3660 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3661 + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3662 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3663 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3664 + aria-hidden: 1.2.4 3665 + react: 19.1.0 3666 + react-dom: 19.1.0(react@19.1.0) 3667 + react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.1.0) 3668 + optionalDependencies: 3669 + '@types/react': 19.0.12 3670 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3671 + 3672 + '@radix-ui/react-popover@1.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3673 + dependencies: 3674 + '@radix-ui/primitive': 1.1.1 3675 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3676 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3677 + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3678 + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3679 + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3680 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3681 + '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3682 + '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3683 + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3684 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3685 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3686 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3687 + aria-hidden: 1.2.4 3688 + react: 19.1.0 3689 + react-dom: 19.1.0(react@19.1.0) 3690 + react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.1.0) 3691 + optionalDependencies: 3692 + '@types/react': 19.0.12 3693 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3694 + 3695 + '@radix-ui/react-popper@1.2.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3696 + dependencies: 3697 + '@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3698 + '@radix-ui/react-arrow': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3699 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3700 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3701 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3702 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3703 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3704 + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3705 + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3706 + '@radix-ui/rect': 1.1.0 3707 + react: 19.1.0 3708 + react-dom: 19.1.0(react@19.1.0) 3709 + optionalDependencies: 3710 + '@types/react': 19.0.12 3711 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3712 + 3713 + '@radix-ui/react-portal@1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3714 + dependencies: 3715 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3716 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3717 + react: 19.1.0 3718 + react-dom: 19.1.0(react@19.1.0) 3719 + optionalDependencies: 3720 + '@types/react': 19.0.12 3721 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3722 + 3723 + '@radix-ui/react-presence@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3724 + dependencies: 3725 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3726 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3727 + react: 19.1.0 3728 + react-dom: 19.1.0(react@19.1.0) 3729 + optionalDependencies: 3730 + '@types/react': 19.0.12 3731 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3732 + 3733 + '@radix-ui/react-primitive@2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3734 + dependencies: 3735 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3736 + react: 19.1.0 3737 + react-dom: 19.1.0(react@19.1.0) 3738 + optionalDependencies: 3739 + '@types/react': 19.0.12 3740 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3741 + 3742 + '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3743 + dependencies: 3744 + '@radix-ui/primitive': 1.1.1 3745 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3746 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3747 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3748 + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3749 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3750 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3751 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3752 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3753 + react: 19.1.0 3754 + react-dom: 19.1.0(react@19.1.0) 3755 + optionalDependencies: 3756 + '@types/react': 19.0.12 3757 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3758 + 3759 + '@radix-ui/react-select@2.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3760 + dependencies: 3761 + '@radix-ui/number': 1.1.0 3762 + '@radix-ui/primitive': 1.1.1 3763 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3764 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3765 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3766 + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3767 + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3768 + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3769 + '@radix-ui/react-focus-scope': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3770 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3771 + '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3772 + '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3773 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3774 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3775 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3776 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3777 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3778 + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3779 + '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3780 + aria-hidden: 1.2.4 3781 + react: 19.1.0 3782 + react-dom: 19.1.0(react@19.1.0) 3783 + react-remove-scroll: 2.6.3(@types/react@19.0.12)(react@19.1.0) 3784 + optionalDependencies: 3785 + '@types/react': 19.0.12 3786 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3787 + 3788 + '@radix-ui/react-slot@1.1.2(@types/react@19.0.12)(react@19.1.0)': 3789 + dependencies: 3790 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3791 + react: 19.1.0 3792 + optionalDependencies: 3793 + '@types/react': 19.0.12 3794 + 3795 + '@radix-ui/react-switch@1.1.3(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3796 + dependencies: 3797 + '@radix-ui/primitive': 1.1.1 3798 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3799 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3800 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3801 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3802 + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3803 + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3804 + react: 19.1.0 3805 + react-dom: 19.1.0(react@19.1.0) 3806 + optionalDependencies: 3807 + '@types/react': 19.0.12 3808 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3809 + 3810 + '@radix-ui/react-tooltip@1.1.8(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3811 + dependencies: 3812 + '@radix-ui/primitive': 1.1.1 3813 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3814 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.12)(react@19.1.0) 3815 + '@radix-ui/react-dismissable-layer': 1.1.5(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3816 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3817 + '@radix-ui/react-popper': 1.2.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3818 + '@radix-ui/react-portal': 1.1.4(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3819 + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3820 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3821 + '@radix-ui/react-slot': 1.1.2(@types/react@19.0.12)(react@19.1.0) 3822 + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3823 + '@radix-ui/react-visually-hidden': 1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3824 + react: 19.1.0 3825 + react-dom: 19.1.0(react@19.1.0) 3826 + optionalDependencies: 3827 + '@types/react': 19.0.12 3828 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3829 + 3830 + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3831 + dependencies: 3832 + react: 19.1.0 3833 + optionalDependencies: 3834 + '@types/react': 19.0.12 3835 + 3836 + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3837 + dependencies: 3838 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3839 + react: 19.1.0 3840 + optionalDependencies: 3841 + '@types/react': 19.0.12 3842 + 3843 + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3844 + dependencies: 3845 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3846 + react: 19.1.0 3847 + optionalDependencies: 3848 + '@types/react': 19.0.12 3849 + 3850 + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3851 + dependencies: 3852 + react: 19.1.0 3853 + optionalDependencies: 3854 + '@types/react': 19.0.12 3855 + 3856 + '@radix-ui/react-use-previous@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3857 + dependencies: 3858 + react: 19.1.0 3859 + optionalDependencies: 3860 + '@types/react': 19.0.12 3861 + 3862 + '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3863 + dependencies: 3864 + '@radix-ui/rect': 1.1.0 3865 + react: 19.1.0 3866 + optionalDependencies: 3867 + '@types/react': 19.0.12 3868 + 3869 + '@radix-ui/react-use-size@1.1.0(@types/react@19.0.12)(react@19.1.0)': 3870 + dependencies: 3871 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.12)(react@19.1.0) 3872 + react: 19.1.0 3873 + optionalDependencies: 3874 + '@types/react': 19.0.12 3875 + 3876 + '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 3877 + dependencies: 3878 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 3879 + react: 19.1.0 3880 + react-dom: 19.1.0(react@19.1.0) 3881 + optionalDependencies: 3882 + '@types/react': 19.0.12 3883 + '@types/react-dom': 19.0.4(@types/react@19.0.12) 3884 + 3885 + '@radix-ui/rect@1.1.0': {} 3886 + 3887 + '@remirror/core-constants@3.0.0': {} 3888 + 3889 + '@rollup/rollup-android-arm-eabi@4.38.0': 3890 + optional: true 3891 + 3892 + '@rollup/rollup-android-arm64@4.38.0': 3893 + optional: true 3894 + 3895 + '@rollup/rollup-darwin-arm64@4.38.0': 3896 + optional: true 3897 + 3898 + '@rollup/rollup-darwin-x64@4.38.0': 3899 + optional: true 3900 + 3901 + '@rollup/rollup-freebsd-arm64@4.38.0': 3902 + optional: true 3903 + 3904 + '@rollup/rollup-freebsd-x64@4.38.0': 3905 + optional: true 3906 + 3907 + '@rollup/rollup-linux-arm-gnueabihf@4.38.0': 3908 + optional: true 3909 + 3910 + '@rollup/rollup-linux-arm-musleabihf@4.38.0': 3911 + optional: true 3912 + 3913 + '@rollup/rollup-linux-arm64-gnu@4.38.0': 3914 + optional: true 3915 + 3916 + '@rollup/rollup-linux-arm64-musl@4.38.0': 3917 + optional: true 3918 + 3919 + '@rollup/rollup-linux-loongarch64-gnu@4.38.0': 3920 + optional: true 3921 + 3922 + '@rollup/rollup-linux-powerpc64le-gnu@4.38.0': 3923 + optional: true 3924 + 3925 + '@rollup/rollup-linux-riscv64-gnu@4.38.0': 3926 + optional: true 3927 + 3928 + '@rollup/rollup-linux-riscv64-musl@4.38.0': 3929 + optional: true 3930 + 3931 + '@rollup/rollup-linux-s390x-gnu@4.38.0': 3932 + optional: true 3933 + 3934 + '@rollup/rollup-linux-x64-gnu@4.38.0': 3935 + optional: true 3936 + 3937 + '@rollup/rollup-linux-x64-musl@4.38.0': 3938 + optional: true 3939 + 3940 + '@rollup/rollup-win32-arm64-msvc@4.38.0': 3941 + optional: true 3942 + 3943 + '@rollup/rollup-win32-ia32-msvc@4.38.0': 3944 + optional: true 3945 + 3946 + '@rollup/rollup-win32-x64-msvc@4.38.0': 3947 + optional: true 3948 + 3949 + '@standard-schema/utils@0.3.0': {} 3950 + 3951 + '@tailwindcss/node@4.0.17': 3952 + dependencies: 3953 + enhanced-resolve: 5.18.1 3954 + jiti: 2.4.2 3955 + tailwindcss: 4.0.17 3956 + 3957 + '@tailwindcss/oxide-android-arm64@4.0.17': 3958 + optional: true 3959 + 3960 + '@tailwindcss/oxide-darwin-arm64@4.0.17': 3961 + optional: true 3962 + 3963 + '@tailwindcss/oxide-darwin-x64@4.0.17': 3964 + optional: true 3965 + 3966 + '@tailwindcss/oxide-freebsd-x64@4.0.17': 3967 + optional: true 3968 + 3969 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.17': 3970 + optional: true 3971 + 3972 + '@tailwindcss/oxide-linux-arm64-gnu@4.0.17': 3973 + optional: true 3974 + 3975 + '@tailwindcss/oxide-linux-arm64-musl@4.0.17': 3976 + optional: true 3977 + 3978 + '@tailwindcss/oxide-linux-x64-gnu@4.0.17': 3979 + optional: true 3980 + 3981 + '@tailwindcss/oxide-linux-x64-musl@4.0.17': 3982 + optional: true 3983 + 3984 + '@tailwindcss/oxide-win32-arm64-msvc@4.0.17': 3985 + optional: true 3986 + 3987 + '@tailwindcss/oxide-win32-x64-msvc@4.0.17': 3988 + optional: true 3989 + 3990 + '@tailwindcss/oxide@4.0.17': 3991 + optionalDependencies: 3992 + '@tailwindcss/oxide-android-arm64': 4.0.17 3993 + '@tailwindcss/oxide-darwin-arm64': 4.0.17 3994 + '@tailwindcss/oxide-darwin-x64': 4.0.17 3995 + '@tailwindcss/oxide-freebsd-x64': 4.0.17 3996 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.17 3997 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.17 3998 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.17 3999 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.17 4000 + '@tailwindcss/oxide-linux-x64-musl': 4.0.17 4001 + '@tailwindcss/oxide-win32-arm64-msvc': 4.0.17 4002 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.17 4003 + 4004 + '@tailwindcss/postcss@4.0.17': 4005 + dependencies: 4006 + '@alloc/quick-lru': 5.2.0 4007 + '@tailwindcss/node': 4.0.17 4008 + '@tailwindcss/oxide': 4.0.17 4009 + lightningcss: 1.29.2 4010 + postcss: 8.5.3 4011 + tailwindcss: 4.0.17 4012 + 4013 + '@tanstack/history@1.114.29': {} 4014 + 4015 + '@tanstack/query-core@5.70.0': {} 4016 + 4017 + '@tanstack/query-devtools@5.67.2': {} 4018 + 4019 + '@tanstack/react-query-devtools@5.70.0(@tanstack/react-query@5.70.0(react@19.1.0))(react@19.1.0)': 4020 + dependencies: 4021 + '@tanstack/query-devtools': 5.67.2 4022 + '@tanstack/react-query': 5.70.0(react@19.1.0) 4023 + react: 19.1.0 4024 + 4025 + '@tanstack/react-query@5.70.0(react@19.1.0)': 4026 + dependencies: 4027 + '@tanstack/query-core': 5.70.0 4028 + react: 19.1.0 4029 + 4030 + '@tanstack/react-router-devtools@1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.114.29)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3)': 4031 + dependencies: 4032 + '@tanstack/react-router': 1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4033 + '@tanstack/router-devtools-core': 1.114.29(@tanstack/router-core@1.114.29)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) 4034 + react: 19.1.0 4035 + react-dom: 19.1.0(react@19.1.0) 4036 + solid-js: 1.9.5 4037 + transitivePeerDependencies: 4038 + - '@tanstack/router-core' 4039 + - csstype 4040 + - tiny-invariant 4041 + 4042 + '@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 4043 + dependencies: 4044 + '@tanstack/history': 1.114.29 4045 + '@tanstack/react-store': 0.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4046 + '@tanstack/router-core': 1.114.29 4047 + jsesc: 3.1.0 4048 + react: 19.1.0 4049 + react-dom: 19.1.0(react@19.1.0) 4050 + tiny-invariant: 1.3.3 4051 + tiny-warning: 1.0.3 4052 + 4053 + '@tanstack/react-store@0.7.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 4054 + dependencies: 4055 + '@tanstack/store': 0.7.0 4056 + react: 19.1.0 4057 + react-dom: 19.1.0(react@19.1.0) 4058 + use-sync-external-store: 1.5.0(react@19.1.0) 4059 + 4060 + '@tanstack/router-core@1.114.29': 4061 + dependencies: 4062 + '@tanstack/history': 1.114.29 4063 + '@tanstack/store': 0.7.0 4064 + tiny-invariant: 1.3.3 4065 + 4066 + '@tanstack/router-devtools-core@1.114.29(@tanstack/router-core@1.114.29)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': 4067 + dependencies: 4068 + '@tanstack/router-core': 1.114.29 4069 + clsx: 2.1.1 4070 + goober: 2.1.16(csstype@3.1.3) 4071 + solid-js: 1.9.5 4072 + tiny-invariant: 1.3.3 4073 + optionalDependencies: 4074 + csstype: 3.1.3 4075 + 4076 + '@tanstack/router-devtools@1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.114.29)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3)': 4077 + dependencies: 4078 + '@tanstack/react-router': 1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4079 + '@tanstack/react-router-devtools': 1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.114.29)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3) 4080 + clsx: 2.1.1 4081 + goober: 2.1.16(csstype@3.1.3) 4082 + react: 19.1.0 4083 + react-dom: 19.1.0(react@19.1.0) 4084 + optionalDependencies: 4085 + csstype: 3.1.3 4086 + transitivePeerDependencies: 4087 + - '@tanstack/router-core' 4088 + - tiny-invariant 4089 + 4090 + '@tanstack/router-generator@1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))': 4091 + dependencies: 4092 + '@tanstack/virtual-file-routes': 1.114.29 4093 + prettier: 3.5.3 4094 + tsx: 4.19.3 4095 + zod: 3.24.3 4096 + optionalDependencies: 4097 + '@tanstack/react-router': 1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4098 + 4099 + '@tanstack/router-plugin@1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3))': 4100 + dependencies: 4101 + '@babel/core': 7.26.10 4102 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) 4103 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) 4104 + '@babel/template': 7.27.0 4105 + '@babel/traverse': 7.27.0 4106 + '@babel/types': 7.27.0 4107 + '@tanstack/router-core': 1.114.29 4108 + '@tanstack/router-generator': 1.114.29(@tanstack/react-router@1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) 4109 + '@tanstack/router-utils': 1.114.29 4110 + '@tanstack/virtual-file-routes': 1.114.29 4111 + '@types/babel__core': 7.20.5 4112 + '@types/babel__template': 7.4.4 4113 + '@types/babel__traverse': 7.20.7 4114 + babel-dead-code-elimination: 1.0.9 4115 + chokidar: 3.6.0 4116 + unplugin: 2.2.2 4117 + zod: 3.24.3 4118 + optionalDependencies: 4119 + '@tanstack/react-router': 1.114.29(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4120 + vite: 6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3) 4121 + transitivePeerDependencies: 4122 + - supports-color 4123 + 4124 + '@tanstack/router-utils@1.114.29': 4125 + dependencies: 4126 + '@babel/generator': 7.27.0 4127 + '@babel/parser': 7.27.0 4128 + ansis: 3.17.0 4129 + diff: 7.0.0 4130 + 4131 + '@tanstack/store@0.7.0': {} 4132 + 4133 + '@tanstack/virtual-file-routes@1.114.29': {} 4134 + 4135 + '@tiptap/core@2.11.6(@tiptap/pm@2.11.6)': 4136 + dependencies: 4137 + '@tiptap/pm': 2.11.6 4138 + 4139 + '@tiptap/extension-blockquote@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4140 + dependencies: 4141 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4142 + 4143 + '@tiptap/extension-bold@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4144 + dependencies: 4145 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4146 + 4147 + '@tiptap/extension-bubble-menu@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4148 + dependencies: 4149 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4150 + '@tiptap/pm': 2.11.6 4151 + tippy.js: 6.3.7 4152 + 4153 + '@tiptap/extension-bullet-list@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4154 + dependencies: 4155 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4156 + 4157 + '@tiptap/extension-code-block@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4158 + dependencies: 4159 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4160 + '@tiptap/pm': 2.11.6 4161 + 4162 + '@tiptap/extension-code@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4163 + dependencies: 4164 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4165 + 4166 + '@tiptap/extension-document@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4167 + dependencies: 4168 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4169 + 4170 + '@tiptap/extension-dropcursor@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4171 + dependencies: 4172 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4173 + '@tiptap/pm': 2.11.6 4174 + 4175 + '@tiptap/extension-floating-menu@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4176 + dependencies: 4177 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4178 + '@tiptap/pm': 2.11.6 4179 + tippy.js: 6.3.7 4180 + 4181 + '@tiptap/extension-gapcursor@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4182 + dependencies: 4183 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4184 + '@tiptap/pm': 2.11.6 4185 + 4186 + '@tiptap/extension-hard-break@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4187 + dependencies: 4188 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4189 + 4190 + '@tiptap/extension-heading@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4191 + dependencies: 4192 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4193 + 4194 + '@tiptap/extension-highlight@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4195 + dependencies: 4196 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4197 + 4198 + '@tiptap/extension-history@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4199 + dependencies: 4200 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4201 + '@tiptap/pm': 2.11.6 4202 + 4203 + '@tiptap/extension-horizontal-rule@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4204 + dependencies: 4205 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4206 + '@tiptap/pm': 2.11.6 4207 + 4208 + '@tiptap/extension-italic@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4209 + dependencies: 4210 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4211 + 4212 + '@tiptap/extension-link@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4213 + dependencies: 4214 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4215 + '@tiptap/pm': 2.11.6 4216 + linkifyjs: 4.2.0 4217 + 4218 + '@tiptap/extension-list-item@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4219 + dependencies: 4220 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4221 + 4222 + '@tiptap/extension-ordered-list@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4223 + dependencies: 4224 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4225 + 4226 + '@tiptap/extension-paragraph@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4227 + dependencies: 4228 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4229 + 4230 + '@tiptap/extension-placeholder@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4231 + dependencies: 4232 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4233 + '@tiptap/pm': 2.11.6 4234 + 4235 + '@tiptap/extension-strike@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4236 + dependencies: 4237 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4238 + 4239 + '@tiptap/extension-task-item@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)': 4240 + dependencies: 4241 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4242 + '@tiptap/pm': 2.11.6 4243 + 4244 + '@tiptap/extension-task-list@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4245 + dependencies: 4246 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4247 + 4248 + '@tiptap/extension-text-style@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4249 + dependencies: 4250 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4251 + 4252 + '@tiptap/extension-text@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))': 4253 + dependencies: 4254 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4255 + 4256 + '@tiptap/pm@2.11.6': 4257 + dependencies: 4258 + prosemirror-changeset: 2.2.1 4259 + prosemirror-collab: 1.3.1 4260 + prosemirror-commands: 1.7.0 4261 + prosemirror-dropcursor: 1.8.1 4262 + prosemirror-gapcursor: 1.3.2 4263 + prosemirror-history: 1.4.1 4264 + prosemirror-inputrules: 1.5.0 4265 + prosemirror-keymap: 1.2.2 4266 + prosemirror-markdown: 1.13.2 4267 + prosemirror-menu: 1.2.4 4268 + prosemirror-model: 1.25.0 4269 + prosemirror-schema-basic: 1.2.4 4270 + prosemirror-schema-list: 1.5.1 4271 + prosemirror-state: 1.4.3 4272 + prosemirror-tables: 1.6.4 4273 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.0)(prosemirror-state@1.4.3)(prosemirror-view@1.38.1) 4274 + prosemirror-transform: 1.10.3 4275 + prosemirror-view: 1.38.1 4276 + 4277 + '@tiptap/react@2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': 4278 + dependencies: 4279 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4280 + '@tiptap/extension-bubble-menu': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4281 + '@tiptap/extension-floating-menu': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4282 + '@tiptap/pm': 2.11.6 4283 + '@types/use-sync-external-store': 0.0.6 4284 + fast-deep-equal: 3.1.3 4285 + react: 19.1.0 4286 + react-dom: 19.1.0(react@19.1.0) 4287 + use-sync-external-store: 1.5.0(react@19.1.0) 4288 + 4289 + '@tiptap/starter-kit@2.11.6': 4290 + dependencies: 4291 + '@tiptap/core': 2.11.6(@tiptap/pm@2.11.6) 4292 + '@tiptap/extension-blockquote': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4293 + '@tiptap/extension-bold': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4294 + '@tiptap/extension-bullet-list': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4295 + '@tiptap/extension-code': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4296 + '@tiptap/extension-code-block': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4297 + '@tiptap/extension-document': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4298 + '@tiptap/extension-dropcursor': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4299 + '@tiptap/extension-gapcursor': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4300 + '@tiptap/extension-hard-break': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4301 + '@tiptap/extension-heading': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4302 + '@tiptap/extension-history': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4303 + '@tiptap/extension-horizontal-rule': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6))(@tiptap/pm@2.11.6) 4304 + '@tiptap/extension-italic': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4305 + '@tiptap/extension-list-item': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4306 + '@tiptap/extension-ordered-list': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4307 + '@tiptap/extension-paragraph': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4308 + '@tiptap/extension-strike': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4309 + '@tiptap/extension-text': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4310 + '@tiptap/extension-text-style': 2.11.6(@tiptap/core@2.11.6(@tiptap/pm@2.11.6)) 4311 + '@tiptap/pm': 2.11.6 4312 + 4313 + '@types/babel__core@7.20.5': 4314 + dependencies: 4315 + '@babel/parser': 7.27.0 4316 + '@babel/types': 7.27.0 4317 + '@types/babel__generator': 7.6.8 4318 + '@types/babel__template': 7.4.4 4319 + '@types/babel__traverse': 7.20.7 4320 + 4321 + '@types/babel__generator@7.6.8': 4322 + dependencies: 4323 + '@babel/types': 7.27.0 4324 + 4325 + '@types/babel__template@7.4.4': 4326 + dependencies: 4327 + '@babel/parser': 7.27.0 4328 + '@babel/types': 7.27.0 4329 + 4330 + '@types/babel__traverse@7.20.7': 4331 + dependencies: 4332 + '@babel/types': 7.27.0 4333 + 4334 + '@types/bcrypt@5.0.2': 4335 + dependencies: 4336 + '@types/node': 22.14.1 4337 + 4338 + '@types/better-sqlite3@7.6.13': 4339 + dependencies: 4340 + '@types/node': 22.14.1 4341 + 4342 + '@types/conventional-commits-parser@5.0.1': 4343 + dependencies: 4344 + '@types/node': 22.14.1 4345 + 4346 + '@types/estree@1.0.7': {} 4347 + 4348 + '@types/linkify-it@5.0.0': {} 4349 + 4350 + '@types/markdown-it@14.1.2': 4351 + dependencies: 4352 + '@types/linkify-it': 5.0.0 4353 + '@types/mdurl': 2.0.0 4354 + 4355 + '@types/mdurl@2.0.0': {} 4356 + 4357 + '@types/node@22.13.14': 4358 + dependencies: 4359 + undici-types: 6.20.0 4360 + 4361 + '@types/node@22.14.1': 4362 + dependencies: 4363 + undici-types: 6.21.0 4364 + 4365 + '@types/react-dom@19.0.4(@types/react@19.0.12)': 4366 + dependencies: 4367 + '@types/react': 19.0.12 4368 + 4369 + '@types/react@19.0.12': 4370 + dependencies: 4371 + csstype: 3.1.3 4372 + 4373 + '@types/use-sync-external-store@0.0.6': {} 4374 + 4375 + '@types/ws@8.18.0': 4376 + dependencies: 4377 + '@types/node': 22.14.1 4378 + optional: true 4379 + 4380 + '@vitejs/plugin-react@4.3.4(vite@6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3))': 4381 + dependencies: 4382 + '@babel/core': 7.26.10 4383 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.10) 4384 + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.10) 4385 + '@types/babel__core': 7.20.5 4386 + react-refresh: 0.14.2 4387 + vite: 6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3) 4388 + transitivePeerDependencies: 4389 + - supports-color 4390 + 4391 + JSONStream@1.3.5: 4392 + dependencies: 4393 + jsonparse: 1.3.1 4394 + through: 2.3.8 4395 + 4396 + abbrev@1.1.1: {} 4397 + 4398 + acorn@8.14.1: {} 4399 + 4400 + agent-base@6.0.2: 4401 + dependencies: 4402 + debug: 4.4.0 4403 + transitivePeerDependencies: 4404 + - supports-color 4405 + 4406 + ajv@8.17.1: 4407 + dependencies: 4408 + fast-deep-equal: 3.1.3 4409 + fast-uri: 3.0.6 4410 + json-schema-traverse: 1.0.0 4411 + require-from-string: 2.0.2 4412 + 4413 + ansi-regex@5.0.1: {} 4414 + 4415 + ansi-styles@4.3.0: 4416 + dependencies: 4417 + color-convert: 2.0.1 4418 + 4419 + ansis@3.17.0: {} 4420 + 4421 + anymatch@3.1.3: 4422 + dependencies: 4423 + normalize-path: 3.0.0 4424 + picomatch: 2.3.1 4425 + 4426 + aproba@2.0.0: {} 4427 + 4428 + are-we-there-yet@2.0.0: 4429 + dependencies: 4430 + delegates: 1.0.0 4431 + readable-stream: 3.6.2 4432 + 4433 + argparse@2.0.1: {} 4434 + 4435 + aria-hidden@1.2.4: 4436 + dependencies: 4437 + tslib: 2.8.1 4438 + 4439 + array-ify@1.0.0: {} 4440 + 4441 + babel-dead-code-elimination@1.0.9: 4442 + dependencies: 4443 + '@babel/core': 7.26.10 4444 + '@babel/parser': 7.27.0 4445 + '@babel/traverse': 7.27.0 4446 + '@babel/types': 7.27.0 4447 + transitivePeerDependencies: 4448 + - supports-color 4449 + 4450 + babel-plugin-react-compiler@19.0.0-beta-aeaed83-20250323: 4451 + dependencies: 4452 + '@babel/types': 7.27.0 4453 + 4454 + balanced-match@1.0.2: {} 4455 + 4456 + base64-js@1.5.1: {} 4457 + 4458 + bcrypt@5.1.1: 4459 + dependencies: 4460 + '@mapbox/node-pre-gyp': 1.0.11 4461 + node-addon-api: 5.1.0 4462 + transitivePeerDependencies: 4463 + - encoding 4464 + - supports-color 4465 + 4466 + better-sqlite3@11.9.1: 4467 + dependencies: 4468 + bindings: 1.5.0 4469 + prebuild-install: 7.1.3 4470 + 4471 + binary-extensions@2.3.0: {} 4472 + 4473 + bindings@1.5.0: 4474 + dependencies: 4475 + file-uri-to-path: 1.0.0 4476 + 4477 + bl@4.1.0: 4478 + dependencies: 4479 + buffer: 5.7.1 4480 + inherits: 2.0.4 4481 + readable-stream: 3.6.2 4482 + 4483 + brace-expansion@1.1.11: 4484 + dependencies: 4485 + balanced-match: 1.0.2 4486 + concat-map: 0.0.1 4487 + 4488 + braces@3.0.3: 4489 + dependencies: 4490 + fill-range: 7.1.1 4491 + 4492 + browserslist@4.24.4: 4493 + dependencies: 4494 + caniuse-lite: 1.0.30001707 4495 + electron-to-chromium: 1.5.128 4496 + node-releases: 2.0.19 4497 + update-browserslist-db: 1.1.3(browserslist@4.24.4) 4498 + 4499 + buffer@5.7.1: 4500 + dependencies: 4501 + base64-js: 1.5.1 4502 + ieee754: 1.2.1 4503 + 4504 + bun-types@1.2.8: 4505 + dependencies: 4506 + '@types/node': 22.14.1 4507 + '@types/ws': 8.18.0 4508 + optional: true 4509 + 4510 + callsites@3.1.0: {} 4511 + 4512 + caniuse-lite@1.0.30001707: {} 4513 + 4514 + chalk@5.4.1: {} 4515 + 4516 + chokidar@3.6.0: 4517 + dependencies: 4518 + anymatch: 3.1.3 4519 + braces: 3.0.3 4520 + glob-parent: 5.1.2 4521 + is-binary-path: 2.1.0 4522 + is-glob: 4.0.3 4523 + normalize-path: 3.0.0 4524 + readdirp: 3.6.0 4525 + optionalDependencies: 4526 + fsevents: 2.3.3 4527 + 4528 + chownr@1.1.4: {} 4529 + 4530 + chownr@2.0.0: {} 4531 + 4532 + class-variance-authority@0.7.1: 4533 + dependencies: 4534 + clsx: 2.1.1 4535 + 4536 + cliui@8.0.1: 4537 + dependencies: 4538 + string-width: 4.2.3 4539 + strip-ansi: 6.0.1 4540 + wrap-ansi: 7.0.0 4541 + 4542 + clsx@2.1.1: {} 4543 + 4544 + cmdk@1.1.1(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): 4545 + dependencies: 4546 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.12)(react@19.1.0) 4547 + '@radix-ui/react-dialog': 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4548 + '@radix-ui/react-id': 1.1.0(@types/react@19.0.12)(react@19.1.0) 4549 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.12))(@types/react@19.0.12)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) 4550 + react: 19.1.0 4551 + react-dom: 19.1.0(react@19.1.0) 4552 + transitivePeerDependencies: 4553 + - '@types/react' 4554 + - '@types/react-dom' 4555 + 4556 + color-convert@2.0.1: 4557 + dependencies: 4558 + color-name: 1.1.4 4559 + 4560 + color-name@1.1.4: {} 4561 + 4562 + color-support@1.1.3: {} 4563 + 4564 + compare-func@2.0.0: 4565 + dependencies: 4566 + array-ify: 1.0.0 4567 + dot-prop: 5.3.0 4568 + 4569 + concat-map@0.0.1: {} 4570 + 4571 + console-control-strings@1.1.0: {} 4572 + 4573 + conventional-changelog-angular@7.0.0: 4574 + dependencies: 4575 + compare-func: 2.0.0 4576 + 4577 + conventional-changelog-conventionalcommits@7.0.2: 4578 + dependencies: 4579 + compare-func: 2.0.0 4580 + 4581 + conventional-commits-parser@5.0.0: 4582 + dependencies: 4583 + JSONStream: 1.3.5 4584 + is-text-path: 2.0.0 4585 + meow: 12.1.1 4586 + split2: 4.2.0 4587 + 4588 + convert-source-map@2.0.0: {} 4589 + 4590 + cosmiconfig-typescript-loader@6.1.0(@types/node@22.14.1)(cosmiconfig@9.0.0(typescript@5.5.4))(typescript@5.5.4): 4591 + dependencies: 4592 + '@types/node': 22.14.1 4593 + cosmiconfig: 9.0.0(typescript@5.5.4) 4594 + jiti: 2.4.2 4595 + typescript: 5.5.4 4596 + 4597 + cosmiconfig@9.0.0(typescript@5.5.4): 4598 + dependencies: 4599 + env-paths: 2.2.1 4600 + import-fresh: 3.3.1 4601 + js-yaml: 4.1.0 4602 + parse-json: 5.2.0 4603 + optionalDependencies: 4604 + typescript: 5.5.4 4605 + 4606 + crelt@1.0.6: {} 4607 + 4608 + csstype@3.1.3: {} 4609 + 4610 + dargs@8.1.0: {} 4611 + 4612 + date-fns@4.1.0: {} 4613 + 4614 + debug@4.4.0: 4615 + dependencies: 4616 + ms: 2.1.3 4617 + 4618 + decompress-response@6.0.0: 4619 + dependencies: 4620 + mimic-response: 3.1.0 4621 + 4622 + deep-extend@0.6.0: {} 4623 + 4624 + delegates@1.0.0: {} 4625 + 4626 + detect-libc@2.0.3: {} 4627 + 4628 + detect-node-es@1.1.0: {} 4629 + 4630 + diff@7.0.0: {} 4631 + 4632 + dot-prop@5.3.0: 4633 + dependencies: 4634 + is-obj: 2.0.0 4635 + 4636 + dotenv@16.5.0: {} 4637 + 4638 + drizzle-orm@0.42.0(@types/better-sqlite3@7.6.13)(better-sqlite3@11.9.1)(bun-types@1.2.8): 4639 + optionalDependencies: 4640 + '@types/better-sqlite3': 7.6.13 4641 + better-sqlite3: 11.9.1 4642 + bun-types: 1.2.8 4643 + 4644 + electron-to-chromium@1.5.128: {} 4645 + 4646 + emoji-regex@8.0.0: {} 4647 + 4648 + end-of-stream@1.4.4: 4649 + dependencies: 4650 + once: 1.4.0 4651 + 4652 + enhanced-resolve@5.18.1: 4653 + dependencies: 4654 + graceful-fs: 4.2.11 4655 + tapable: 2.2.1 4656 + 4657 + entities@4.5.0: {} 4658 + 4659 + env-paths@2.2.1: {} 4660 + 4661 + error-ex@1.3.2: 4662 + dependencies: 4663 + is-arrayish: 0.2.1 4664 + 4665 + esbuild@0.25.2: 4666 + optionalDependencies: 4667 + '@esbuild/aix-ppc64': 0.25.2 4668 + '@esbuild/android-arm': 0.25.2 4669 + '@esbuild/android-arm64': 0.25.2 4670 + '@esbuild/android-x64': 0.25.2 4671 + '@esbuild/darwin-arm64': 0.25.2 4672 + '@esbuild/darwin-x64': 0.25.2 4673 + '@esbuild/freebsd-arm64': 0.25.2 4674 + '@esbuild/freebsd-x64': 0.25.2 4675 + '@esbuild/linux-arm': 0.25.2 4676 + '@esbuild/linux-arm64': 0.25.2 4677 + '@esbuild/linux-ia32': 0.25.2 4678 + '@esbuild/linux-loong64': 0.25.2 4679 + '@esbuild/linux-mips64el': 0.25.2 4680 + '@esbuild/linux-ppc64': 0.25.2 4681 + '@esbuild/linux-riscv64': 0.25.2 4682 + '@esbuild/linux-s390x': 0.25.2 4683 + '@esbuild/linux-x64': 0.25.2 4684 + '@esbuild/netbsd-arm64': 0.25.2 4685 + '@esbuild/netbsd-x64': 0.25.2 4686 + '@esbuild/openbsd-arm64': 0.25.2 4687 + '@esbuild/openbsd-x64': 0.25.2 4688 + '@esbuild/sunos-x64': 0.25.2 4689 + '@esbuild/win32-arm64': 0.25.2 4690 + '@esbuild/win32-ia32': 0.25.2 4691 + '@esbuild/win32-x64': 0.25.2 4692 + 4693 + escalade@3.2.0: {} 4694 + 4695 + escape-string-regexp@4.0.0: {} 4696 + 4697 + expand-template@2.0.3: {} 4698 + 4699 + fast-deep-equal@3.1.3: {} 4700 + 4701 + fast-uri@3.0.6: {} 4702 + 4703 + file-uri-to-path@1.0.0: {} 4704 + 4705 + fill-range@7.1.1: 4706 + dependencies: 4707 + to-regex-range: 5.0.1 4708 + 4709 + find-up@7.0.0: 4710 + dependencies: 4711 + locate-path: 7.2.0 4712 + path-exists: 5.0.0 4713 + unicorn-magic: 0.1.0 4714 + 4715 + framer-motion@12.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): 4716 + dependencies: 4717 + motion-dom: 12.6.1 4718 + motion-utils: 12.5.0 4719 + tslib: 2.8.1 4720 + optionalDependencies: 4721 + react: 19.1.0 4722 + react-dom: 19.1.0(react@19.1.0) 4723 + 4724 + fs-constants@1.0.0: {} 4725 + 4726 + fs-minipass@2.1.0: 4727 + dependencies: 4728 + minipass: 3.3.6 4729 + 4730 + fs.realpath@1.0.0: {} 4731 + 4732 + fsevents@2.3.3: 4733 + optional: true 4734 + 4735 + gauge@3.0.2: 4736 + dependencies: 4737 + aproba: 2.0.0 4738 + color-support: 1.1.3 4739 + console-control-strings: 1.1.0 4740 + has-unicode: 2.0.1 4741 + object-assign: 4.1.1 4742 + signal-exit: 3.0.7 4743 + string-width: 4.2.3 4744 + strip-ansi: 6.0.1 4745 + wide-align: 1.1.5 4746 + 4747 + gensync@1.0.0-beta.2: {} 4748 + 4749 + get-caller-file@2.0.5: {} 4750 + 4751 + get-nonce@1.0.1: {} 4752 + 4753 + get-tsconfig@4.10.0: 4754 + dependencies: 4755 + resolve-pkg-maps: 1.0.0 4756 + 4757 + git-raw-commits@4.0.0: 4758 + dependencies: 4759 + dargs: 8.1.0 4760 + meow: 12.1.1 4761 + split2: 4.2.0 4762 + 4763 + github-from-package@0.0.0: {} 4764 + 4765 + glob-parent@5.1.2: 4766 + dependencies: 4767 + is-glob: 4.0.3 4768 + 4769 + glob@7.2.3: 4770 + dependencies: 4771 + fs.realpath: 1.0.0 4772 + inflight: 1.0.6 4773 + inherits: 2.0.4 4774 + minimatch: 3.1.2 4775 + once: 1.4.0 4776 + path-is-absolute: 1.0.1 4777 + 4778 + global-directory@4.0.1: 4779 + dependencies: 4780 + ini: 4.1.1 4781 + 4782 + globals@11.12.0: {} 4783 + 4784 + globals@16.0.0: {} 4785 + 4786 + goober@2.1.16(csstype@3.1.3): 4787 + dependencies: 4788 + csstype: 3.1.3 4789 + 4790 + graceful-fs@4.2.11: {} 4791 + 4792 + has-unicode@2.0.1: {} 4793 + 4794 + hono@4.7.5: {} 4795 + 4796 + hono@4.7.7: {} 4797 + 4798 + https-proxy-agent@5.0.1: 4799 + dependencies: 4800 + agent-base: 6.0.2 4801 + debug: 4.4.0 4802 + transitivePeerDependencies: 4803 + - supports-color 4804 + 4805 + husky@9.1.7: {} 4806 + 4807 + ieee754@1.2.1: {} 4808 + 4809 + immer@10.1.1: {} 4810 + 4811 + import-fresh@3.3.1: 4812 + dependencies: 4813 + parent-module: 1.0.1 4814 + resolve-from: 4.0.0 4815 + 4816 + import-meta-resolve@4.1.0: {} 4817 + 4818 + inflight@1.0.6: 4819 + dependencies: 4820 + once: 1.4.0 4821 + wrappy: 1.0.2 4822 + 4823 + inherits@2.0.4: {} 4824 + 4825 + ini@1.3.8: {} 4826 + 4827 + ini@4.1.1: {} 4828 + 4829 + is-arrayish@0.2.1: {} 4830 + 4831 + is-binary-path@2.1.0: 4832 + dependencies: 4833 + binary-extensions: 2.3.0 4834 + 4835 + is-extglob@2.1.1: {} 4836 + 4837 + is-fullwidth-code-point@3.0.0: {} 4838 + 4839 + is-glob@4.0.3: 4840 + dependencies: 4841 + is-extglob: 2.1.1 4842 + 4843 + is-number@7.0.0: {} 4844 + 4845 + is-obj@2.0.0: {} 4846 + 4847 + is-text-path@2.0.0: 4848 + dependencies: 4849 + text-extensions: 2.4.0 4850 + 4851 + jiti@2.4.2: {} 4852 + 4853 + js-tokens@4.0.0: {} 4854 + 4855 + js-yaml@4.1.0: 4856 + dependencies: 4857 + argparse: 2.0.1 4858 + 4859 + jsesc@3.1.0: {} 4860 + 4861 + json-parse-even-better-errors@2.3.1: {} 4862 + 4863 + json-schema-traverse@1.0.0: {} 4864 + 4865 + json5@2.2.3: {} 4866 + 4867 + jsonparse@1.3.1: {} 4868 + 4869 + lightningcss-darwin-arm64@1.29.2: 4870 + optional: true 4871 + 4872 + lightningcss-darwin-x64@1.29.2: 4873 + optional: true 4874 + 4875 + lightningcss-freebsd-x64@1.29.2: 4876 + optional: true 4877 + 4878 + lightningcss-linux-arm-gnueabihf@1.29.2: 4879 + optional: true 4880 + 4881 + lightningcss-linux-arm64-gnu@1.29.2: 4882 + optional: true 4883 + 4884 + lightningcss-linux-arm64-musl@1.29.2: 4885 + optional: true 4886 + 4887 + lightningcss-linux-x64-gnu@1.29.2: 4888 + optional: true 4889 + 4890 + lightningcss-linux-x64-musl@1.29.2: 4891 + optional: true 4892 + 4893 + lightningcss-win32-arm64-msvc@1.29.2: 4894 + optional: true 4895 + 4896 + lightningcss-win32-x64-msvc@1.29.2: 4897 + optional: true 4898 + 4899 + lightningcss@1.29.2: 4900 + dependencies: 4901 + detect-libc: 2.0.3 4902 + optionalDependencies: 4903 + lightningcss-darwin-arm64: 1.29.2 4904 + lightningcss-darwin-x64: 1.29.2 4905 + lightningcss-freebsd-x64: 1.29.2 4906 + lightningcss-linux-arm-gnueabihf: 1.29.2 4907 + lightningcss-linux-arm64-gnu: 1.29.2 4908 + lightningcss-linux-arm64-musl: 1.29.2 4909 + lightningcss-linux-x64-gnu: 1.29.2 4910 + lightningcss-linux-x64-musl: 1.29.2 4911 + lightningcss-win32-arm64-msvc: 1.29.2 4912 + lightningcss-win32-x64-msvc: 1.29.2 4913 + 4914 + lines-and-columns@1.2.4: {} 4915 + 4916 + linkify-it@5.0.0: 4917 + dependencies: 4918 + uc.micro: 2.1.0 4919 + 4920 + linkifyjs@4.2.0: {} 4921 + 4922 + locate-path@7.2.0: 4923 + dependencies: 4924 + p-locate: 6.0.0 4925 + 4926 + lodash.camelcase@4.3.0: {} 4927 + 4928 + lodash.isplainobject@4.0.6: {} 4929 + 4930 + lodash.kebabcase@4.1.1: {} 4931 + 4932 + lodash.merge@4.6.2: {} 4933 + 4934 + lodash.mergewith@4.6.2: {} 4935 + 4936 + lodash.snakecase@4.1.1: {} 4937 + 4938 + lodash.startcase@4.4.0: {} 4939 + 4940 + lodash.uniq@4.5.0: {} 4941 + 4942 + lodash.upperfirst@4.3.1: {} 4943 + 4944 + lru-cache@5.1.1: 4945 + dependencies: 4946 + yallist: 3.1.1 4947 + 4948 + lucide-react@0.488.0(react@19.1.0): 4949 + dependencies: 4950 + react: 19.1.0 4951 + 4952 + make-dir@3.1.0: 4953 + dependencies: 4954 + semver: 6.3.1 4955 + 4956 + markdown-it@14.1.0: 4957 + dependencies: 4958 + argparse: 2.0.1 4959 + entities: 4.5.0 4960 + linkify-it: 5.0.0 4961 + mdurl: 2.0.0 4962 + punycode.js: 2.3.1 4963 + uc.micro: 2.1.0 4964 + 4965 + mdurl@2.0.0: {} 4966 + 4967 + meow@12.1.1: {} 4968 + 4969 + mimic-response@3.1.0: {} 4970 + 4971 + minimatch@3.1.2: 4972 + dependencies: 4973 + brace-expansion: 1.1.11 4974 + 4975 + minimist@1.2.8: {} 4976 + 4977 + minipass@3.3.6: 4978 + dependencies: 4979 + yallist: 4.0.0 4980 + 4981 + minipass@5.0.0: {} 4982 + 4983 + minizlib@2.1.2: 4984 + dependencies: 4985 + minipass: 3.3.6 4986 + yallist: 4.0.0 4987 + 4988 + mkdirp-classic@0.5.3: {} 4989 + 4990 + mkdirp@1.0.4: {} 4991 + 4992 + motion-dom@12.6.1: 4993 + dependencies: 4994 + motion-utils: 12.5.0 4995 + 4996 + motion-utils@12.5.0: {} 4997 + 4998 + ms@2.1.3: {} 4999 + 5000 + nanoid@3.3.11: {} 5001 + 5002 + napi-build-utils@2.0.0: {} 5003 + 5004 + node-abi@3.74.0: 5005 + dependencies: 5006 + semver: 7.7.1 5007 + 5008 + node-addon-api@5.1.0: {} 5009 + 5010 + node-fetch@2.7.0: 5011 + dependencies: 5012 + whatwg-url: 5.0.0 5013 + 5014 + node-releases@2.0.19: {} 5015 + 5016 + nopt@5.0.0: 5017 + dependencies: 5018 + abbrev: 1.1.1 5019 + 5020 + normalize-path@3.0.0: {} 5021 + 5022 + npmlog@5.0.1: 5023 + dependencies: 5024 + are-we-there-yet: 2.0.0 5025 + console-control-strings: 1.1.0 5026 + gauge: 3.0.2 5027 + set-blocking: 2.0.0 5028 + 5029 + object-assign@4.1.1: {} 5030 + 5031 + once@1.4.0: 5032 + dependencies: 5033 + wrappy: 1.0.2 5034 + 5035 + orderedmap@2.1.1: {} 5036 + 5037 + p-limit@4.0.0: 5038 + dependencies: 5039 + yocto-queue: 1.2.1 5040 + 5041 + p-locate@6.0.0: 5042 + dependencies: 5043 + p-limit: 4.0.0 5044 + 5045 + parent-module@1.0.1: 5046 + dependencies: 5047 + callsites: 3.1.0 5048 + 5049 + parse-json@5.2.0: 5050 + dependencies: 5051 + '@babel/code-frame': 7.26.2 5052 + error-ex: 1.3.2 5053 + json-parse-even-better-errors: 2.3.1 5054 + lines-and-columns: 1.2.4 5055 + 5056 + path-exists@5.0.0: {} 5057 + 5058 + path-is-absolute@1.0.1: {} 5059 + 5060 + picocolors@1.1.1: {} 5061 + 5062 + picomatch@2.3.1: {} 5063 + 5064 + postcss@8.5.3: 5065 + dependencies: 5066 + nanoid: 3.3.11 5067 + picocolors: 1.1.1 5068 + source-map-js: 1.2.1 5069 + 5070 + prebuild-install@7.1.3: 5071 + dependencies: 5072 + detect-libc: 2.0.3 5073 + expand-template: 2.0.3 5074 + github-from-package: 0.0.0 5075 + minimist: 1.2.8 5076 + mkdirp-classic: 0.5.3 5077 + napi-build-utils: 2.0.0 5078 + node-abi: 3.74.0 5079 + pump: 3.0.2 5080 + rc: 1.2.8 5081 + simple-get: 4.0.1 5082 + tar-fs: 2.1.2 5083 + tunnel-agent: 0.6.0 5084 + 5085 + prettier@3.5.3: {} 5086 + 5087 + prosemirror-changeset@2.2.1: 5088 + dependencies: 5089 + prosemirror-transform: 1.10.3 5090 + 5091 + prosemirror-collab@1.3.1: 5092 + dependencies: 5093 + prosemirror-state: 1.4.3 5094 + 5095 + prosemirror-commands@1.7.0: 5096 + dependencies: 5097 + prosemirror-model: 1.25.0 5098 + prosemirror-state: 1.4.3 5099 + prosemirror-transform: 1.10.3 5100 + 5101 + prosemirror-dropcursor@1.8.1: 5102 + dependencies: 5103 + prosemirror-state: 1.4.3 5104 + prosemirror-transform: 1.10.3 5105 + prosemirror-view: 1.38.1 5106 + 5107 + prosemirror-gapcursor@1.3.2: 5108 + dependencies: 5109 + prosemirror-keymap: 1.2.2 5110 + prosemirror-model: 1.25.0 5111 + prosemirror-state: 1.4.3 5112 + prosemirror-view: 1.38.1 5113 + 5114 + prosemirror-history@1.4.1: 5115 + dependencies: 5116 + prosemirror-state: 1.4.3 5117 + prosemirror-transform: 1.10.3 5118 + prosemirror-view: 1.38.1 5119 + rope-sequence: 1.3.4 5120 + 5121 + prosemirror-inputrules@1.5.0: 5122 + dependencies: 5123 + prosemirror-state: 1.4.3 5124 + prosemirror-transform: 1.10.3 5125 + 5126 + prosemirror-keymap@1.2.2: 5127 + dependencies: 5128 + prosemirror-state: 1.4.3 5129 + w3c-keyname: 2.2.8 5130 + 5131 + prosemirror-markdown@1.13.2: 5132 + dependencies: 5133 + '@types/markdown-it': 14.1.2 5134 + markdown-it: 14.1.0 5135 + prosemirror-model: 1.25.0 5136 + 5137 + prosemirror-menu@1.2.4: 5138 + dependencies: 5139 + crelt: 1.0.6 5140 + prosemirror-commands: 1.7.0 5141 + prosemirror-history: 1.4.1 5142 + prosemirror-state: 1.4.3 5143 + 5144 + prosemirror-model@1.25.0: 5145 + dependencies: 5146 + orderedmap: 2.1.1 5147 + 5148 + prosemirror-schema-basic@1.2.4: 5149 + dependencies: 5150 + prosemirror-model: 1.25.0 5151 + 5152 + prosemirror-schema-list@1.5.1: 5153 + dependencies: 5154 + prosemirror-model: 1.25.0 5155 + prosemirror-state: 1.4.3 5156 + prosemirror-transform: 1.10.3 5157 + 5158 + prosemirror-state@1.4.3: 5159 + dependencies: 5160 + prosemirror-model: 1.25.0 5161 + prosemirror-transform: 1.10.3 5162 + prosemirror-view: 1.38.1 5163 + 5164 + prosemirror-tables@1.6.4: 5165 + dependencies: 5166 + prosemirror-keymap: 1.2.2 5167 + prosemirror-model: 1.25.0 5168 + prosemirror-state: 1.4.3 5169 + prosemirror-transform: 1.10.3 5170 + prosemirror-view: 1.38.1 5171 + 5172 + prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.0)(prosemirror-state@1.4.3)(prosemirror-view@1.38.1): 5173 + dependencies: 5174 + '@remirror/core-constants': 3.0.0 5175 + escape-string-regexp: 4.0.0 5176 + prosemirror-model: 1.25.0 5177 + prosemirror-state: 1.4.3 5178 + prosemirror-view: 1.38.1 5179 + 5180 + prosemirror-transform@1.10.3: 5181 + dependencies: 5182 + prosemirror-model: 1.25.0 5183 + 5184 + prosemirror-view@1.38.1: 5185 + dependencies: 5186 + prosemirror-model: 1.25.0 5187 + prosemirror-state: 1.4.3 5188 + prosemirror-transform: 1.10.3 5189 + 5190 + pump@3.0.2: 5191 + dependencies: 5192 + end-of-stream: 1.4.4 5193 + once: 1.4.0 5194 + 5195 + punycode.js@2.3.1: {} 5196 + 5197 + rc@1.2.8: 5198 + dependencies: 5199 + deep-extend: 0.6.0 5200 + ini: 1.3.8 5201 + minimist: 1.2.8 5202 + strip-json-comments: 2.0.1 5203 + 5204 + react-day-picker@8.10.1(date-fns@4.1.0)(react@19.1.0): 5205 + dependencies: 5206 + date-fns: 4.1.0 5207 + react: 19.1.0 5208 + 5209 + react-dom@19.1.0(react@19.1.0): 5210 + dependencies: 5211 + react: 19.1.0 5212 + scheduler: 0.26.0 5213 + 5214 + react-hook-form@7.55.0(react@19.1.0): 5215 + dependencies: 5216 + react: 19.1.0 5217 + 5218 + react-refresh@0.14.2: {} 5219 + 5220 + react-remove-scroll-bar@2.3.8(@types/react@19.0.12)(react@19.1.0): 5221 + dependencies: 5222 + react: 19.1.0 5223 + react-style-singleton: 2.2.3(@types/react@19.0.12)(react@19.1.0) 5224 + tslib: 2.8.1 5225 + optionalDependencies: 5226 + '@types/react': 19.0.12 5227 + 5228 + react-remove-scroll@2.6.3(@types/react@19.0.12)(react@19.1.0): 5229 + dependencies: 5230 + react: 19.1.0 5231 + react-remove-scroll-bar: 2.3.8(@types/react@19.0.12)(react@19.1.0) 5232 + react-style-singleton: 2.2.3(@types/react@19.0.12)(react@19.1.0) 5233 + tslib: 2.8.1 5234 + use-callback-ref: 1.3.3(@types/react@19.0.12)(react@19.1.0) 5235 + use-sidecar: 1.1.3(@types/react@19.0.12)(react@19.1.0) 5236 + optionalDependencies: 5237 + '@types/react': 19.0.12 5238 + 5239 + react-style-singleton@2.2.3(@types/react@19.0.12)(react@19.1.0): 5240 + dependencies: 5241 + get-nonce: 1.0.1 5242 + react: 19.1.0 5243 + tslib: 2.8.1 5244 + optionalDependencies: 5245 + '@types/react': 19.0.12 5246 + 5247 + react-use-websocket@4.13.0: {} 5248 + 5249 + react@19.1.0: {} 5250 + 5251 + readable-stream@3.6.2: 5252 + dependencies: 5253 + inherits: 2.0.4 5254 + string_decoder: 1.3.0 5255 + util-deprecate: 1.0.2 5256 + 5257 + readdirp@3.6.0: 5258 + dependencies: 5259 + picomatch: 2.3.1 5260 + 5261 + require-directory@2.1.1: {} 5262 + 5263 + require-from-string@2.0.2: {} 5264 + 5265 + resolve-from@4.0.0: {} 5266 + 5267 + resolve-from@5.0.0: {} 5268 + 5269 + resolve-pkg-maps@1.0.0: {} 5270 + 5271 + rimraf@3.0.2: 5272 + dependencies: 5273 + glob: 7.2.3 5274 + 5275 + rollup@4.38.0: 5276 + dependencies: 5277 + '@types/estree': 1.0.7 5278 + optionalDependencies: 5279 + '@rollup/rollup-android-arm-eabi': 4.38.0 5280 + '@rollup/rollup-android-arm64': 4.38.0 5281 + '@rollup/rollup-darwin-arm64': 4.38.0 5282 + '@rollup/rollup-darwin-x64': 4.38.0 5283 + '@rollup/rollup-freebsd-arm64': 4.38.0 5284 + '@rollup/rollup-freebsd-x64': 4.38.0 5285 + '@rollup/rollup-linux-arm-gnueabihf': 4.38.0 5286 + '@rollup/rollup-linux-arm-musleabihf': 4.38.0 5287 + '@rollup/rollup-linux-arm64-gnu': 4.38.0 5288 + '@rollup/rollup-linux-arm64-musl': 4.38.0 5289 + '@rollup/rollup-linux-loongarch64-gnu': 4.38.0 5290 + '@rollup/rollup-linux-powerpc64le-gnu': 4.38.0 5291 + '@rollup/rollup-linux-riscv64-gnu': 4.38.0 5292 + '@rollup/rollup-linux-riscv64-musl': 4.38.0 5293 + '@rollup/rollup-linux-s390x-gnu': 4.38.0 5294 + '@rollup/rollup-linux-x64-gnu': 4.38.0 5295 + '@rollup/rollup-linux-x64-musl': 4.38.0 5296 + '@rollup/rollup-win32-arm64-msvc': 4.38.0 5297 + '@rollup/rollup-win32-ia32-msvc': 4.38.0 5298 + '@rollup/rollup-win32-x64-msvc': 4.38.0 5299 + fsevents: 2.3.3 5300 + 5301 + rope-sequence@1.3.4: {} 5302 + 5303 + safe-buffer@5.2.1: {} 5304 + 5305 + scheduler@0.26.0: {} 5306 + 5307 + semver@6.3.1: {} 5308 + 5309 + semver@7.7.1: {} 5310 + 5311 + seroval-plugins@1.2.1(seroval@1.2.1): 5312 + dependencies: 5313 + seroval: 1.2.1 5314 + 5315 + seroval@1.2.1: {} 5316 + 5317 + set-blocking@2.0.0: {} 5318 + 5319 + signal-exit@3.0.7: {} 5320 + 5321 + simple-concat@1.0.1: {} 5322 + 5323 + simple-get@4.0.1: 5324 + dependencies: 5325 + decompress-response: 6.0.0 5326 + once: 1.4.0 5327 + simple-concat: 1.0.1 5328 + 5329 + solid-js@1.9.5: 5330 + dependencies: 5331 + csstype: 3.1.3 5332 + seroval: 1.2.1 5333 + seroval-plugins: 1.2.1(seroval@1.2.1) 5334 + 5335 + sonner@2.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): 5336 + dependencies: 5337 + react: 19.1.0 5338 + react-dom: 19.1.0(react@19.1.0) 5339 + 5340 + source-map-js@1.2.1: {} 5341 + 5342 + split2@4.2.0: {} 5343 + 5344 + string-width@4.2.3: 5345 + dependencies: 5346 + emoji-regex: 8.0.0 5347 + is-fullwidth-code-point: 3.0.0 5348 + strip-ansi: 6.0.1 5349 + 5350 + string_decoder@1.3.0: 5351 + dependencies: 5352 + safe-buffer: 5.2.1 5353 + 5354 + strip-ansi@6.0.1: 5355 + dependencies: 5356 + ansi-regex: 5.0.1 5357 + 5358 + strip-json-comments@2.0.1: {} 5359 + 5360 + tailwind-merge@3.0.2: {} 5361 + 5362 + tailwindcss-animate@1.0.7(tailwindcss@4.0.17): 5363 + dependencies: 5364 + tailwindcss: 4.0.17 5365 + 5366 + tailwindcss@4.0.17: {} 5367 + 5368 + tapable@2.2.1: {} 5369 + 5370 + tar-fs@2.1.2: 5371 + dependencies: 5372 + chownr: 1.1.4 5373 + mkdirp-classic: 0.5.3 5374 + pump: 3.0.2 5375 + tar-stream: 2.2.0 5376 + 5377 + tar-stream@2.2.0: 5378 + dependencies: 5379 + bl: 4.1.0 5380 + end-of-stream: 1.4.4 5381 + fs-constants: 1.0.0 5382 + inherits: 2.0.4 5383 + readable-stream: 3.6.2 5384 + 5385 + tar@6.2.1: 5386 + dependencies: 5387 + chownr: 2.0.0 5388 + fs-minipass: 2.1.0 5389 + minipass: 5.0.0 5390 + minizlib: 2.1.2 5391 + mkdirp: 1.0.4 5392 + yallist: 4.0.0 5393 + 5394 + text-extensions@2.4.0: {} 5395 + 5396 + through@2.3.8: {} 5397 + 5398 + tiny-invariant@1.3.3: {} 5399 + 5400 + tiny-warning@1.0.3: {} 5401 + 5402 + tinyexec@0.3.2: {} 5403 + 5404 + tippy.js@6.3.7: 5405 + dependencies: 5406 + '@popperjs/core': 2.11.8 5407 + 5408 + to-regex-range@5.0.1: 5409 + dependencies: 5410 + is-number: 7.0.0 5411 + 5412 + tr46@0.0.3: {} 5413 + 5414 + tslib@2.8.1: {} 5415 + 5416 + tsx@4.19.3: 5417 + dependencies: 5418 + esbuild: 0.25.2 5419 + get-tsconfig: 4.10.0 5420 + optionalDependencies: 5421 + fsevents: 2.3.3 5422 + 5423 + tunnel-agent@0.6.0: 5424 + dependencies: 5425 + safe-buffer: 5.2.1 5426 + 5427 + turbo-darwin-64@2.4.4: 5428 + optional: true 5429 + 5430 + turbo-darwin-arm64@2.4.4: 5431 + optional: true 5432 + 5433 + turbo-linux-64@2.4.4: 5434 + optional: true 5435 + 5436 + turbo-linux-arm64@2.4.4: 5437 + optional: true 5438 + 5439 + turbo-windows-64@2.4.4: 5440 + optional: true 5441 + 5442 + turbo-windows-arm64@2.4.4: 5443 + optional: true 5444 + 5445 + turbo@2.4.4: 5446 + optionalDependencies: 5447 + turbo-darwin-64: 2.4.4 5448 + turbo-darwin-arm64: 2.4.4 5449 + turbo-linux-64: 2.4.4 5450 + turbo-linux-arm64: 2.4.4 5451 + turbo-windows-64: 2.4.4 5452 + turbo-windows-arm64: 2.4.4 5453 + 5454 + typescript@5.5.4: {} 5455 + 5456 + typescript@5.8.2: {} 5457 + 5458 + typescript@5.8.3: {} 5459 + 5460 + uc.micro@2.1.0: {} 5461 + 5462 + undici-types@6.20.0: {} 5463 + 5464 + undici-types@6.21.0: {} 5465 + 5466 + unicorn-magic@0.1.0: {} 5467 + 5468 + unplugin@2.2.2: 5469 + dependencies: 5470 + acorn: 8.14.1 5471 + webpack-virtual-modules: 0.6.2 5472 + 5473 + update-browserslist-db@1.1.3(browserslist@4.24.4): 5474 + dependencies: 5475 + browserslist: 4.24.4 5476 + escalade: 3.2.0 5477 + picocolors: 1.1.1 5478 + 5479 + use-callback-ref@1.3.3(@types/react@19.0.12)(react@19.1.0): 5480 + dependencies: 5481 + react: 19.1.0 5482 + tslib: 2.8.1 5483 + optionalDependencies: 5484 + '@types/react': 19.0.12 5485 + 5486 + use-sidecar@1.1.3(@types/react@19.0.12)(react@19.1.0): 5487 + dependencies: 5488 + detect-node-es: 1.1.0 5489 + react: 19.1.0 5490 + tslib: 2.8.1 5491 + optionalDependencies: 5492 + '@types/react': 19.0.12 5493 + 5494 + use-sync-external-store@1.5.0(react@19.1.0): 5495 + dependencies: 5496 + react: 19.1.0 5497 + 5498 + util-deprecate@1.0.2: {} 5499 + 5500 + vite@6.2.3(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(tsx@4.19.3): 5501 + dependencies: 5502 + esbuild: 0.25.2 5503 + postcss: 8.5.3 5504 + rollup: 4.38.0 5505 + optionalDependencies: 5506 + '@types/node': 22.13.14 5507 + fsevents: 2.3.3 5508 + jiti: 2.4.2 5509 + lightningcss: 1.29.2 5510 + tsx: 4.19.3 5511 + 5512 + w3c-keyname@2.2.8: {} 5513 + 5514 + webidl-conversions@3.0.1: {} 5515 + 5516 + webpack-virtual-modules@0.6.2: {} 5517 + 5518 + whatwg-url@5.0.0: 5519 + dependencies: 5520 + tr46: 0.0.3 5521 + webidl-conversions: 3.0.1 5522 + 5523 + wide-align@1.1.5: 5524 + dependencies: 5525 + string-width: 4.2.3 5526 + 5527 + wrap-ansi@7.0.0: 5528 + dependencies: 5529 + ansi-styles: 4.3.0 5530 + string-width: 4.2.3 5531 + strip-ansi: 6.0.1 5532 + 5533 + wrappy@1.0.2: {} 5534 + 5535 + y18n@5.0.8: {} 5536 + 5537 + yallist@3.1.1: {} 5538 + 5539 + yallist@4.0.0: {} 5540 + 5541 + yargs-parser@21.1.1: {} 5542 + 5543 + yargs@17.7.2: 5544 + dependencies: 5545 + cliui: 8.0.1 5546 + escalade: 3.2.0 5547 + get-caller-file: 2.0.5 5548 + require-directory: 2.1.1 5549 + string-width: 4.2.3 5550 + y18n: 5.0.8 5551 + yargs-parser: 21.1.1 5552 + 5553 + yocto-queue@1.2.1: {} 5554 + 5555 + zod@3.24.3: {} 5556 + 5557 + zustand@5.0.3(@types/react@19.0.12)(immer@10.1.1)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)): 5558 + optionalDependencies: 5559 + '@types/react': 19.0.12 5560 + immer: 10.1.1 5561 + react: 19.1.0 5562 + use-sync-external-store: 1.5.0(react@19.1.0)
+8
pnpm-workspace.yaml
··· 1 + packages: 2 + - packages/** 3 + - apps/** 4 + onlyBuiltDependencies: 5 + - '@biomejs/biome' 6 + - bcrypt 7 + - better-sqlite3 8 + - esbuild