From e82ea71c2267ca46622aa518621d790e3a6df09c Mon Sep 17 00:00:00 2001 From: Mayne0213 Date: Mon, 5 Jan 2026 02:29:10 +0900 Subject: [PATCH] REFACTOR(repo): simplify project structure - Move services/nextjs to nextjs/ - Move deploy/docker/Dockerfile.prod to Dockerfile - Add GitHub Actions workflows (ci.yml, build.yml) - Remove deploy/, services/, scripts/ folders --- .dockerignore | 148 + .github/workflows/build.yml | 73 + .github/workflows/ci.yml | 45 + .gitignore | 56 + Dockerfile | 62 + nextjs/app/api/auth/login/route.ts | 61 + nextjs/app/api/auth/logout/route.ts | 22 + nextjs/app/api/auth/me/route.ts | 54 + nextjs/app/api/auth/register/route.ts | 76 + nextjs/app/api/documents/[id]/public/route.ts | 49 + nextjs/app/api/documents/[id]/route.ts | 202 + nextjs/app/api/documents/route.ts | 84 + nextjs/app/api/download-url/route.ts | 46 + nextjs/app/api/folders/[id]/route.ts | 264 + nextjs/app/api/folders/route.ts | 154 + nextjs/app/api/health/route.ts | 27 + nextjs/app/api/metadata/route.ts | 22 + nextjs/app/api/templates/route.ts | 105 + nextjs/app/api/upload-url/route.ts | 57 + nextjs/app/api/upload/route.ts | 177 + nextjs/app/documents/[id]/page.tsx | 296 + nextjs/app/documents/layout.tsx | 45 + nextjs/app/documents/page.tsx | 202 + nextjs/app/documents/todos/page.tsx | 12 + nextjs/app/favicon.ico | Bin 0 -> 26928 bytes nextjs/app/globals.css | 321 + nextjs/app/home/layout.tsx | 12 + nextjs/app/home/page.tsx | 17 + nextjs/app/home/share/[id]/page.tsx | 161 + nextjs/app/home/signIn/page.tsx | 116 + nextjs/app/home/signUp/page.tsx | 167 + nextjs/app/layout.tsx | 62 + nextjs/components.json | 17 + nextjs/middleware.ts | 71 + nextjs/next.config.mjs | 48 + nextjs/package-lock.json | 6346 +++++++++++++++++ nextjs/package.json | 66 + nextjs/postcss.config.mjs | 9 + nextjs/prisma/schema.prisma | 131 + nextjs/public/documents.png | Bin 0 -> 54914 bytes nextjs/public/documents_dark.png | Bin 0 -> 61572 bytes nextjs/public/notionIcon.png | Bin 0 -> 142554 bytes nextjs/public/notionIcond.png | Bin 0 -> 11406 bytes nextjs/src/app/config/index.ts | 3 + nextjs/src/app/config/metadata.ts | 21 + nextjs/src/app/favicon.ico | Bin 0 -> 25931 bytes nextjs/src/app/globals.css | 321 + nextjs/src/app/providers/auth-provider.tsx | 72 + nextjs/src/app/providers/theme-provider.tsx | 10 + nextjs/src/entities/document/api/index.ts | 67 + nextjs/src/entities/document/index.ts | 4 + nextjs/src/entities/document/model/index.ts | 4 + nextjs/src/entities/document/model/store.ts | 36 + nextjs/src/entities/document/model/types.ts | 70 + .../src/entities/document/model/validation.ts | 21 + .../src/entities/document/ui/DocumentItem.tsx | 45 + nextjs/src/entities/document/ui/index.ts | 2 + nextjs/src/entities/folder/api/index.ts | 57 + nextjs/src/entities/folder/index.ts | 4 + nextjs/src/entities/folder/model/index.ts | 4 + nextjs/src/entities/folder/model/store.ts | 36 + nextjs/src/entities/folder/model/types.ts | 44 + .../src/entities/folder/model/validation.ts | 13 + nextjs/src/entities/folder/ui/FolderItem.tsx | 40 + nextjs/src/entities/folder/ui/index.ts | 2 + nextjs/src/entities/index.ts | 6 + nextjs/src/entities/template/api/index.ts | 56 + nextjs/src/entities/template/index.ts | 4 + nextjs/src/entities/template/model/index.ts | 4 + nextjs/src/entities/template/model/store.ts | 36 + nextjs/src/entities/template/model/types.ts | 49 + .../src/entities/template/model/validation.ts | 14 + nextjs/src/entities/template/ui/index.ts | 6 + nextjs/src/entities/todo/api/index.ts | 170 + nextjs/src/entities/todo/index.ts | 3 + nextjs/src/entities/todo/model/index.ts | 3 + nextjs/src/entities/todo/model/store.ts | 133 + nextjs/src/entities/todo/model/types.ts | 42 + nextjs/src/entities/todo/ui/TodoItem.tsx | 132 + nextjs/src/entities/todo/ui/TodoList.tsx | 53 + nextjs/src/entities/todo/ui/index.ts | 3 + nextjs/src/entities/user/api/index.ts | 53 + nextjs/src/entities/user/index.ts | 4 + nextjs/src/entities/user/model/index.ts | 4 + nextjs/src/entities/user/model/store.ts | 13 + nextjs/src/entities/user/model/types.ts | 27 + nextjs/src/entities/user/model/validation.ts | 11 + nextjs/src/entities/user/ui/index.ts | 6 + nextjs/src/features/document-edit/index.ts | 3 + .../src/features/document-edit/model/index.ts | 9 + .../src/features/document-edit/model/store.ts | 70 + .../model/use-document-actions.tsx | 75 + .../document-edit/model/use-document-data.tsx | 98 + .../model/use-document-headings.tsx | 219 + .../document-edit/model/use-document-save.tsx | 78 + .../model/use-document-templates.tsx | 40 + .../model/use-document-utils.tsx | 37 + .../model/use-sidebar-search.tsx | 204 + nextjs/src/features/document-edit/ui/index.ts | 5 + .../src/features/document-management/index.ts | 3 + .../document-management/model/index.ts | 2 + .../document-management/model/store.ts | 153 + .../features/document-management/ui/index.ts | 6 + .../src/features/folder-management/index.ts | 3 + .../features/folder-management/model/index.ts | 2 + .../features/folder-management/model/store.ts | 143 + .../features/folder-management/ui/index.ts | 6 + nextjs/src/features/index.ts | 6 + nextjs/src/features/template-apply/index.ts | 3 + .../features/template-apply/model/index.ts | 2 + .../features/template-apply/model/store.ts | 42 + .../src/features/template-apply/ui/index.ts | 6 + nextjs/src/features/todo-management/index.ts | 2 + .../todo-management/ui/TodoCreateForm.tsx | 68 + .../todo-management/ui/TodoFilter.tsx | 52 + .../src/features/todo-management/ui/index.ts | 3 + nextjs/src/shared/api/client.ts | 65 + nextjs/src/shared/api/index.ts | 1 + nextjs/src/shared/config/s3.ts | 20 + nextjs/src/shared/hooks/index.ts | 2 + .../shared/hooks/use-folder-navigation.tsx | 42 + nextjs/src/shared/hooks/use-scroll-top.tsx | 21 + nextjs/src/shared/index.ts | 6 + nextjs/src/shared/lib/api-client.ts | 66 + nextjs/src/shared/lib/auth.ts | 59 + nextjs/src/shared/lib/db.ts | 18 + nextjs/src/shared/lib/index.ts | 2 + nextjs/src/shared/lib/metadata-extractor.ts | 186 + nextjs/src/shared/lib/middleware.ts | 45 + nextjs/src/shared/lib/prisma.ts | 18 + nextjs/src/shared/lib/s3.ts | 168 + nextjs/src/shared/lib/supabase.ts | 94 + nextjs/src/shared/lib/utils.ts | 6 + nextjs/src/shared/types/bookmark.ts | 27 + nextjs/src/shared/types/document.ts | 53 + nextjs/src/shared/types/editor.ts | 42 + nextjs/src/shared/types/folder.ts | 27 + nextjs/src/shared/types/index.ts | 7 + nextjs/src/shared/types/template.ts | 32 + nextjs/src/shared/types/user.ts | 15 + nextjs/src/shared/ui/SignedImage.tsx | 86 + nextjs/src/shared/ui/button.tsx | 56 + nextjs/src/shared/ui/checkbox.tsx | 51 + nextjs/src/shared/ui/dialog.tsx | 119 + nextjs/src/shared/ui/dropdown-menu.tsx | 200 + nextjs/src/shared/ui/index.ts | 10 + nextjs/src/shared/ui/input.tsx | 24 + nextjs/src/shared/ui/label.tsx | 23 + nextjs/src/shared/ui/mode-toggle.tsx | 40 + nextjs/src/shared/ui/skeleton.tsx | 218 + nextjs/src/shared/ui/spinner.tsx | 30 + nextjs/src/shared/ui/textarea.tsx | 23 + nextjs/src/widgets/documents/create-input.tsx | 45 + nextjs/src/widgets/documents/delete-modal.tsx | 67 + nextjs/src/widgets/documents/document.tsx | 72 + nextjs/src/widgets/documents/empty-state.tsx | 73 + nextjs/src/widgets/documents/file-tree.tsx | 282 + nextjs/src/widgets/documents/folder-view.tsx | 230 + nextjs/src/widgets/documents/folder.tsx | 127 + nextjs/src/widgets/documents/header.tsx | 80 + nextjs/src/widgets/documents/index.ts | 11 + nextjs/src/widgets/documents/navigation.tsx | 467 ++ nextjs/src/widgets/documents/root-view.tsx | 129 + .../editor/blocks/audio/audio-component.tsx | 198 + .../editor/blocks/audio/audio-extension.tsx | 78 + .../blocks/bookmark/bookmark-component.tsx | 135 + .../blocks/bookmark/bookmark-extension.tsx | 174 + .../editor/blocks/bookmark/bookmark-modal.tsx | 179 + .../blocks/calendar/calendar-component.tsx | 393 + .../blocks/calendar/calendar-extension.tsx | 121 + .../editor/blocks/calendar/calendar-modal.tsx | 139 + .../document-link/document-link-extension.tsx | 93 + .../document-link/document-link-node-view.tsx | 32 + .../editor/blocks/file/file-component.tsx | 186 + .../editor/blocks/file/file-extension.tsx | 81 + .../blocks/heading/heading-id-extension.tsx | 50 + .../blocks/image/image-upload-component.tsx | 334 + .../blocks/image/image-upload-extension.tsx | 96 + .../editor/core/notion-block-selector.tsx | 213 + .../editor/core/notion-floating-toolbar.tsx | 260 + .../editor/editor/core/rich-text-editor.tsx | 844 +++ nextjs/src/widgets/editor/editor/index.ts | 21 + nextjs/src/widgets/editor/index.ts | 6 + .../editor/sidebar/document-overview.tsx | 119 + .../editor/sidebar/document-sidebar.tsx | 128 + .../editor/sidebar/document-statistics.tsx | 50 + nextjs/src/widgets/editor/sidebar/index.ts | 7 + .../widgets/editor/sidebar/quick-actions.tsx | 87 + .../src/widgets/editor/sidebar/search-bar.tsx | 49 + .../widgets/editor/sidebar/search-results.tsx | 70 + nextjs/src/widgets/editor/template/index.ts | 4 + .../editor/template/template-browser.tsx | 189 + .../editor/template/template-modal.tsx | 177 + .../editor/template/template-selector.tsx | 43 + nextjs/src/widgets/index.ts | 4 + nextjs/src/widgets/landing/footer.tsx | 21 + nextjs/src/widgets/landing/heading.tsx | 38 + nextjs/src/widgets/landing/heroes.tsx | 25 + nextjs/src/widgets/landing/index.ts | 6 + nextjs/src/widgets/landing/logo.tsx | 22 + nextjs/src/widgets/landing/navbar.tsx | 49 + nextjs/src/widgets/todo/index.ts | 2 + nextjs/src/widgets/todo/todo-panel.tsx | 32 + nextjs/tailwind.config.ts | 80 + nextjs/tsconfig.json | 53 + 205 files changed, 21304 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 nextjs/app/api/auth/login/route.ts create mode 100644 nextjs/app/api/auth/logout/route.ts create mode 100644 nextjs/app/api/auth/me/route.ts create mode 100644 nextjs/app/api/auth/register/route.ts create mode 100644 nextjs/app/api/documents/[id]/public/route.ts create mode 100644 nextjs/app/api/documents/[id]/route.ts create mode 100644 nextjs/app/api/documents/route.ts create mode 100644 nextjs/app/api/download-url/route.ts create mode 100644 nextjs/app/api/folders/[id]/route.ts create mode 100644 nextjs/app/api/folders/route.ts create mode 100644 nextjs/app/api/health/route.ts create mode 100644 nextjs/app/api/metadata/route.ts create mode 100644 nextjs/app/api/templates/route.ts create mode 100644 nextjs/app/api/upload-url/route.ts create mode 100644 nextjs/app/api/upload/route.ts create mode 100644 nextjs/app/documents/[id]/page.tsx create mode 100644 nextjs/app/documents/layout.tsx create mode 100644 nextjs/app/documents/page.tsx create mode 100644 nextjs/app/documents/todos/page.tsx create mode 100644 nextjs/app/favicon.ico create mode 100644 nextjs/app/globals.css create mode 100644 nextjs/app/home/layout.tsx create mode 100644 nextjs/app/home/page.tsx create mode 100644 nextjs/app/home/share/[id]/page.tsx create mode 100644 nextjs/app/home/signIn/page.tsx create mode 100644 nextjs/app/home/signUp/page.tsx create mode 100644 nextjs/app/layout.tsx create mode 100644 nextjs/components.json create mode 100644 nextjs/middleware.ts create mode 100644 nextjs/next.config.mjs create mode 100644 nextjs/package-lock.json create mode 100644 nextjs/package.json create mode 100644 nextjs/postcss.config.mjs create mode 100644 nextjs/prisma/schema.prisma create mode 100644 nextjs/public/documents.png create mode 100644 nextjs/public/documents_dark.png create mode 100644 nextjs/public/notionIcon.png create mode 100644 nextjs/public/notionIcond.png create mode 100644 nextjs/src/app/config/index.ts create mode 100644 nextjs/src/app/config/metadata.ts create mode 100644 nextjs/src/app/favicon.ico create mode 100644 nextjs/src/app/globals.css create mode 100644 nextjs/src/app/providers/auth-provider.tsx create mode 100644 nextjs/src/app/providers/theme-provider.tsx create mode 100644 nextjs/src/entities/document/api/index.ts create mode 100644 nextjs/src/entities/document/index.ts create mode 100644 nextjs/src/entities/document/model/index.ts create mode 100644 nextjs/src/entities/document/model/store.ts create mode 100644 nextjs/src/entities/document/model/types.ts create mode 100644 nextjs/src/entities/document/model/validation.ts create mode 100644 nextjs/src/entities/document/ui/DocumentItem.tsx create mode 100644 nextjs/src/entities/document/ui/index.ts create mode 100644 nextjs/src/entities/folder/api/index.ts create mode 100644 nextjs/src/entities/folder/index.ts create mode 100644 nextjs/src/entities/folder/model/index.ts create mode 100644 nextjs/src/entities/folder/model/store.ts create mode 100644 nextjs/src/entities/folder/model/types.ts create mode 100644 nextjs/src/entities/folder/model/validation.ts create mode 100644 nextjs/src/entities/folder/ui/FolderItem.tsx create mode 100644 nextjs/src/entities/folder/ui/index.ts create mode 100644 nextjs/src/entities/index.ts create mode 100644 nextjs/src/entities/template/api/index.ts create mode 100644 nextjs/src/entities/template/index.ts create mode 100644 nextjs/src/entities/template/model/index.ts create mode 100644 nextjs/src/entities/template/model/store.ts create mode 100644 nextjs/src/entities/template/model/types.ts create mode 100644 nextjs/src/entities/template/model/validation.ts create mode 100644 nextjs/src/entities/template/ui/index.ts create mode 100644 nextjs/src/entities/todo/api/index.ts create mode 100644 nextjs/src/entities/todo/index.ts create mode 100644 nextjs/src/entities/todo/model/index.ts create mode 100644 nextjs/src/entities/todo/model/store.ts create mode 100644 nextjs/src/entities/todo/model/types.ts create mode 100644 nextjs/src/entities/todo/ui/TodoItem.tsx create mode 100644 nextjs/src/entities/todo/ui/TodoList.tsx create mode 100644 nextjs/src/entities/todo/ui/index.ts create mode 100644 nextjs/src/entities/user/api/index.ts create mode 100644 nextjs/src/entities/user/index.ts create mode 100644 nextjs/src/entities/user/model/index.ts create mode 100644 nextjs/src/entities/user/model/store.ts create mode 100644 nextjs/src/entities/user/model/types.ts create mode 100644 nextjs/src/entities/user/model/validation.ts create mode 100644 nextjs/src/entities/user/ui/index.ts create mode 100644 nextjs/src/features/document-edit/index.ts create mode 100644 nextjs/src/features/document-edit/model/index.ts create mode 100644 nextjs/src/features/document-edit/model/store.ts create mode 100644 nextjs/src/features/document-edit/model/use-document-actions.tsx create mode 100644 nextjs/src/features/document-edit/model/use-document-data.tsx create mode 100644 nextjs/src/features/document-edit/model/use-document-headings.tsx create mode 100644 nextjs/src/features/document-edit/model/use-document-save.tsx create mode 100644 nextjs/src/features/document-edit/model/use-document-templates.tsx create mode 100644 nextjs/src/features/document-edit/model/use-document-utils.tsx create mode 100644 nextjs/src/features/document-edit/model/use-sidebar-search.tsx create mode 100644 nextjs/src/features/document-edit/ui/index.ts create mode 100644 nextjs/src/features/document-management/index.ts create mode 100644 nextjs/src/features/document-management/model/index.ts create mode 100644 nextjs/src/features/document-management/model/store.ts create mode 100644 nextjs/src/features/document-management/ui/index.ts create mode 100644 nextjs/src/features/folder-management/index.ts create mode 100644 nextjs/src/features/folder-management/model/index.ts create mode 100644 nextjs/src/features/folder-management/model/store.ts create mode 100644 nextjs/src/features/folder-management/ui/index.ts create mode 100644 nextjs/src/features/index.ts create mode 100644 nextjs/src/features/template-apply/index.ts create mode 100644 nextjs/src/features/template-apply/model/index.ts create mode 100644 nextjs/src/features/template-apply/model/store.ts create mode 100644 nextjs/src/features/template-apply/ui/index.ts create mode 100644 nextjs/src/features/todo-management/index.ts create mode 100644 nextjs/src/features/todo-management/ui/TodoCreateForm.tsx create mode 100644 nextjs/src/features/todo-management/ui/TodoFilter.tsx create mode 100644 nextjs/src/features/todo-management/ui/index.ts create mode 100644 nextjs/src/shared/api/client.ts create mode 100644 nextjs/src/shared/api/index.ts create mode 100644 nextjs/src/shared/config/s3.ts create mode 100644 nextjs/src/shared/hooks/index.ts create mode 100644 nextjs/src/shared/hooks/use-folder-navigation.tsx create mode 100644 nextjs/src/shared/hooks/use-scroll-top.tsx create mode 100644 nextjs/src/shared/index.ts create mode 100644 nextjs/src/shared/lib/api-client.ts create mode 100644 nextjs/src/shared/lib/auth.ts create mode 100644 nextjs/src/shared/lib/db.ts create mode 100644 nextjs/src/shared/lib/index.ts create mode 100644 nextjs/src/shared/lib/metadata-extractor.ts create mode 100644 nextjs/src/shared/lib/middleware.ts create mode 100644 nextjs/src/shared/lib/prisma.ts create mode 100644 nextjs/src/shared/lib/s3.ts create mode 100644 nextjs/src/shared/lib/supabase.ts create mode 100644 nextjs/src/shared/lib/utils.ts create mode 100644 nextjs/src/shared/types/bookmark.ts create mode 100644 nextjs/src/shared/types/document.ts create mode 100644 nextjs/src/shared/types/editor.ts create mode 100644 nextjs/src/shared/types/folder.ts create mode 100644 nextjs/src/shared/types/index.ts create mode 100644 nextjs/src/shared/types/template.ts create mode 100644 nextjs/src/shared/types/user.ts create mode 100644 nextjs/src/shared/ui/SignedImage.tsx create mode 100644 nextjs/src/shared/ui/button.tsx create mode 100644 nextjs/src/shared/ui/checkbox.tsx create mode 100644 nextjs/src/shared/ui/dialog.tsx create mode 100644 nextjs/src/shared/ui/dropdown-menu.tsx create mode 100644 nextjs/src/shared/ui/index.ts create mode 100644 nextjs/src/shared/ui/input.tsx create mode 100644 nextjs/src/shared/ui/label.tsx create mode 100644 nextjs/src/shared/ui/mode-toggle.tsx create mode 100644 nextjs/src/shared/ui/skeleton.tsx create mode 100644 nextjs/src/shared/ui/spinner.tsx create mode 100644 nextjs/src/shared/ui/textarea.tsx create mode 100644 nextjs/src/widgets/documents/create-input.tsx create mode 100644 nextjs/src/widgets/documents/delete-modal.tsx create mode 100644 nextjs/src/widgets/documents/document.tsx create mode 100644 nextjs/src/widgets/documents/empty-state.tsx create mode 100644 nextjs/src/widgets/documents/file-tree.tsx create mode 100644 nextjs/src/widgets/documents/folder-view.tsx create mode 100644 nextjs/src/widgets/documents/folder.tsx create mode 100644 nextjs/src/widgets/documents/header.tsx create mode 100644 nextjs/src/widgets/documents/index.ts create mode 100644 nextjs/src/widgets/documents/navigation.tsx create mode 100644 nextjs/src/widgets/documents/root-view.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/audio/audio-component.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/audio/audio-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/bookmark/bookmark-component.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/bookmark/bookmark-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/bookmark/bookmark-modal.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/calendar/calendar-component.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/calendar/calendar-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/calendar/calendar-modal.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/document-link/document-link-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/document-link/document-link-node-view.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/file/file-component.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/file/file-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/heading/heading-id-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/image/image-upload-component.tsx create mode 100644 nextjs/src/widgets/editor/editor/blocks/image/image-upload-extension.tsx create mode 100644 nextjs/src/widgets/editor/editor/core/notion-block-selector.tsx create mode 100644 nextjs/src/widgets/editor/editor/core/notion-floating-toolbar.tsx create mode 100644 nextjs/src/widgets/editor/editor/core/rich-text-editor.tsx create mode 100644 nextjs/src/widgets/editor/editor/index.ts create mode 100644 nextjs/src/widgets/editor/index.ts create mode 100644 nextjs/src/widgets/editor/sidebar/document-overview.tsx create mode 100644 nextjs/src/widgets/editor/sidebar/document-sidebar.tsx create mode 100644 nextjs/src/widgets/editor/sidebar/document-statistics.tsx create mode 100644 nextjs/src/widgets/editor/sidebar/index.ts create mode 100644 nextjs/src/widgets/editor/sidebar/quick-actions.tsx create mode 100644 nextjs/src/widgets/editor/sidebar/search-bar.tsx create mode 100644 nextjs/src/widgets/editor/sidebar/search-results.tsx create mode 100644 nextjs/src/widgets/editor/template/index.ts create mode 100644 nextjs/src/widgets/editor/template/template-browser.tsx create mode 100644 nextjs/src/widgets/editor/template/template-modal.tsx create mode 100644 nextjs/src/widgets/editor/template/template-selector.tsx create mode 100644 nextjs/src/widgets/index.ts create mode 100644 nextjs/src/widgets/landing/footer.tsx create mode 100644 nextjs/src/widgets/landing/heading.tsx create mode 100644 nextjs/src/widgets/landing/heroes.tsx create mode 100644 nextjs/src/widgets/landing/index.ts create mode 100644 nextjs/src/widgets/landing/logo.tsx create mode 100644 nextjs/src/widgets/landing/navbar.tsx create mode 100644 nextjs/src/widgets/todo/index.ts create mode 100644 nextjs/src/widgets/todo/todo-panel.tsx create mode 100644 nextjs/tailwind.config.ts create mode 100644 nextjs/tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4d8d51b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,148 @@ +# Dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Next.js +.next/ +out/ +build/ + +# Production +dist/ + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ +*.lcov + +# nyc test coverage +.nyc_output + +# Dependency directories +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt + +# Gatsby files +.cache/ +public + +# Storybook build outputs +.out +.storybook-out + +# Temporary folders +tmp/ +temp/ + +# Editor directories and files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git +.git +.gitignore + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Documentation +README.md +*.md + +# Backup files +backups/ +*.backup +*.bak + +# Uploads (should be handled by volumes) +uploads/ + +# SSL certificates +ssl/ + +# Nginx config (handled by volumes) +nginx/ + +# Scripts +scripts/ +backup-scripts/ + +# Prisma +prisma/migrations/ + +# TypeScript +*.tsbuildinfo + +# Testing +coverage/ +.nyc_output/ + +# Misc +.editorconfig +.prettierrc +.eslintrc* + +# Trunk +.trunk \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..c7ee892 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,73 @@ +name: Build Docker Image + +on: + push: + branches: [main] + tags: + - 'v*' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-24.04-arm + permissions: + contents: read + packages: write + + outputs: + image-tag: ${{ steps.meta.outputs.tags }} + image-digest: ${{ steps.build.outputs.digest }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.CR_PAT }} + + - name: Lowercase repository name + id: lowercase + run: | + echo "repo=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ steps.lowercase.outputs.repo }} + tags: | + type=sha,prefix=sha-,format=long + type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v5 + with: + context: ./nextjs + file: ./Dockerfile + push: true + platforms: linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Display image information + run: | + echo "Image built and pushed successfully!" + echo "Image tags:" + echo "${{ steps.meta.outputs.tags }}" + echo "Digest: ${{ steps.build.outputs.digest }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..afbf679 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + lint-and-build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: nextjs/package-lock.json + + - name: Install dependencies + working-directory: nextjs + run: npm ci + + - name: Run ESLint + working-directory: nextjs + run: npm run lint + + - name: Build Next.js application + working-directory: nextjs + run: npm run build + env: + NEXT_TELEMETRY_DISABLED: 1 + + - name: Check build output + working-directory: nextjs + run: | + if [ ! -d ".next" ]; then + echo "Build failed: .next directory not found" + exit 1 + fi + echo "Build completed successfully" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dea05c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# dependencies +node_modules +services/nextjs/node_modules +.pnp +.pnp.* + +# testing +coverage + +# next.js +services/nextjs/.next/ +.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env* +!.env.example + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# prisma +/prisma/dev.db +/prisma/dev.db-journal +/prisma/*.db +/prisma/*.db-journal + +# IDE +.vscode +.idea +*.swp +*.swo +*~ + +# OS +Thumbs.db + +# trunk +.trunk \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d027e11 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +# Multi-stage build for Next.js application +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json package-lock.json* ./ +RUN npm ci --only=production + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Generate Prisma Client +RUN npx prisma generate + +# Build the application +ENV NEXT_TELEMETRY_DISABLED=1 +RUN npm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs + +# Copy built application +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next && chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +# https://nextjs.org/docs/advanced-features/output-file-tracing +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +# Copy Prisma files +COPY --from=builder /app/prisma ./prisma +COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:3000/api/health || exit 1 + +CMD ["node", "server.js"] diff --git a/nextjs/app/api/auth/login/route.ts b/nextjs/app/api/auth/login/route.ts new file mode 100644 index 0000000..c58945c --- /dev/null +++ b/nextjs/app/api/auth/login/route.ts @@ -0,0 +1,61 @@ +import { NextRequest, NextResponse } from 'next/server' +import { authenticateUser, generateToken } from '@/shared/lib/auth' + +export async function POST(req: NextRequest) { + try { + const { email, password } = await req.json() + + // Validation + if (!email || !password) { + return NextResponse.json( + { error: 'Email and password are required' }, + { status: 400 } + ) + } + + // Authenticate user + const user = await authenticateUser(email, password) + + if (!user) { + return NextResponse.json( + { error: 'Invalid credentials' }, + { status: 401 } + ) + } + + // Generate JWT token + const token = generateToken({ + userId: user.id, + email: user.email, + }) + + // Create response with user data + const response = NextResponse.json({ + message: 'Login successful', + token, + user: { + id: user.id, + email: user.email, + name: user.name, + image: user.image, + }, + }) + + // Set auth token in cookie (HttpOnly for security) + response.cookies.set('auth-token', token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7, // 7 days + path: '/', + }) + + return response + } catch (error) { + console.error('Login error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} diff --git a/nextjs/app/api/auth/logout/route.ts b/nextjs/app/api/auth/logout/route.ts new file mode 100644 index 0000000..289edd6 --- /dev/null +++ b/nextjs/app/api/auth/logout/route.ts @@ -0,0 +1,22 @@ +import { NextRequest, NextResponse } from 'next/server' + +export async function POST(req: NextRequest) { + try { + // Create response + const response = NextResponse.json({ + message: 'Logout successful', + }) + + // Clear auth token cookie + response.cookies.delete('auth-token') + + return response + } catch (error) { + console.error('Logout error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} + diff --git a/nextjs/app/api/auth/me/route.ts b/nextjs/app/api/auth/me/route.ts new file mode 100644 index 0000000..4bee065 --- /dev/null +++ b/nextjs/app/api/auth/me/route.ts @@ -0,0 +1,54 @@ +import { NextRequest, NextResponse } from 'next/server' +import { verifyToken } from '@/shared/lib/auth' +import { db } from '@/shared/lib/db' + +export async function GET(req: NextRequest) { + try { + // Get token from cookie + const token = req.cookies.get('auth-token')?.value + + if (!token) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ) + } + + // Verify token + const payload = verifyToken(token) + + if (!payload) { + return NextResponse.json( + { error: 'Invalid token' }, + { status: 401 } + ) + } + + // Get user from database + const user = await db.user.findUnique({ + where: { id: payload.userId }, + select: { + id: true, + email: true, + name: true, + image: true, + }, + }) + + if (!user) { + return NextResponse.json( + { error: 'User not found' }, + { status: 404 } + ) + } + + return NextResponse.json(user) + } catch (error) { + console.error('Get user error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} + diff --git a/nextjs/app/api/auth/register/route.ts b/nextjs/app/api/auth/register/route.ts new file mode 100644 index 0000000..2df9109 --- /dev/null +++ b/nextjs/app/api/auth/register/route.ts @@ -0,0 +1,76 @@ +import { NextRequest, NextResponse } from 'next/server' +import { createUser, generateToken } from '@/shared/lib/auth' +import { db } from '@/shared/lib/db' + +export async function POST(req: NextRequest) { + try { + const { email, password, name } = await req.json() + + // Validation + if (!email || !password) { + return NextResponse.json( + { error: 'Email and password are required' }, + { status: 400 } + ) + } + + if (password.length < 6) { + return NextResponse.json( + { error: 'Password must be at least 6 characters' }, + { status: 400 } + ) + } + + // Check if user already exists + const existingUser = await db.user.findUnique({ + where: { email }, + }) + + if (existingUser) { + return NextResponse.json( + { error: 'User already exists' }, + { status: 400 } + ) + } + + // Create user + const user = await createUser(email, password, name) + + // Generate JWT token + const token = generateToken({ + userId: user.id, + email: user.email, + }) + + // Create response with user data + const response = NextResponse.json( + { + message: 'User created successfully', + token, + user: { + id: user.id, + email: user.email, + name: user.name, + } + }, + { status: 201 } + ) + + // Set auth token in cookie (HttpOnly for security) + response.cookies.set('auth-token', token, { + httpOnly: true, + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax', + maxAge: 60 * 60 * 24 * 7, // 7 days + path: '/', + }) + + return response + } catch (error) { + console.error('Registration error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} diff --git a/nextjs/app/api/documents/[id]/public/route.ts b/nextjs/app/api/documents/[id]/public/route.ts new file mode 100644 index 0000000..56bd690 --- /dev/null +++ b/nextjs/app/api/documents/[id]/public/route.ts @@ -0,0 +1,49 @@ +import { NextRequest, NextResponse } from 'next/server' +import { db } from '@/shared/lib/db' + +// GET /api/documents/[id]/public - Get a public document (no auth required) +export async function GET(req: NextRequest) { + try { + const url = new URL(req.url) + const id = url.pathname.split('/')[3] // Extract ID from /api/documents/[id]/public + + if (!id) { + return NextResponse.json( + { error: 'Document ID is required' }, + { status: 400 } + ) + } + + // 공개된 문서만 조회 (인증 없이) + const document = await db.document.findFirst({ + where: { + id, + isPublished: true, // 공개된 문서만 + isArchived: false, + }, + include: { + user: { + select: { + name: true, + email: true, + } + } + } + }) + + if (!document) { + return NextResponse.json( + { error: 'Document not found or not published' }, + { status: 404 } + ) + } + + return NextResponse.json(document) + } catch (error) { + console.error('Error fetching public document:', error) + return NextResponse.json( + { error: 'Failed to fetch document' }, + { status: 500 } + ) + } +} diff --git a/nextjs/app/api/documents/[id]/route.ts b/nextjs/app/api/documents/[id]/route.ts new file mode 100644 index 0000000..bda7963 --- /dev/null +++ b/nextjs/app/api/documents/[id]/route.ts @@ -0,0 +1,202 @@ +import { NextRequest, NextResponse } from 'next/server' +import { withAuth } from '@/shared/lib/middleware' +import { db } from '@/shared/lib/db' +import { deleteFile } from '@/shared/lib/s3' + +// GET /api/documents/[id] - Get a specific document +export const GET = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + + if (!id) { + return NextResponse.json( + { error: 'Document ID is required' }, + { status: 400 } + ) + } + + // Allow viewing both archived and non-archived documents + const document = await db.document.findFirst({ + where: { + id, + userId, + }, + }) + + if (!document) { + return NextResponse.json( + { error: 'Document not found' }, + { status: 404 } + ) + } + + return NextResponse.json(document) + } catch (error) { + console.error('Error fetching document:', error) + return NextResponse.json( + { error: 'Failed to fetch document' }, + { status: 500 } + ) + } +}) + +// PUT /api/documents/[id] - Update a specific document +export const PUT = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + const { title, content, icon, cover, isPublished } = await req.json() + + if (!id) { + return NextResponse.json( + { error: 'Document ID is required' }, + { status: 400 } + ) + } + + // Check if document exists and belongs to user + const existingDocument = await db.document.findFirst({ + where: { + id, + userId, + isArchived: false, + }, + }) + + if (!existingDocument) { + return NextResponse.json( + { error: 'Document not found' }, + { status: 404 } + ) + } + + const document = await db.document.update({ + where: { id }, + data: { + ...(title && { title }), + ...(content && { content }), + ...(icon !== undefined && { icon }), + ...(cover !== undefined && { cover }), + ...(isPublished !== undefined && { isPublished }), + updatedAt: new Date(), + }, + }) + + return NextResponse.json(document) + } catch (error) { + console.error('Error updating document:', error) + return NextResponse.json( + { error: 'Failed to update document' }, + { status: 500 } + ) + } +}) + +// Helper function to extract image paths from document content +async function extractImagePaths(content: any): Promise { + if (!content) return []; + + const paths: string[] = []; + + try { + const parsed = typeof content === 'string' ? JSON.parse(content) : content; + + // Recursive function to traverse the document structure + const traverse = (node: any) => { + if (!node) return; + + // Check if this is an imageUpload node with a path + if (node.type === 'imageUpload' && node.attrs?.path) { + paths.push(node.attrs.path); + } + + // Recursively check content and children + if (node.content && Array.isArray(node.content)) { + node.content.forEach(traverse); + } + if (node.children && Array.isArray(node.children)) { + node.children.forEach(traverse); + } + }; + + // Check if parsed is an object with content + if (parsed.content) { + traverse(parsed); + } else if (Array.isArray(parsed)) { + parsed.forEach(traverse); + } else if (parsed.type) { + traverse(parsed); + } + } catch (error) { + console.error('Error parsing document content:', error); + } + + return paths; +} + +// DELETE /api/documents/[id] - Archive a specific document +export const DELETE = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + + if (!id) { + return NextResponse.json( + { error: 'Document ID is required' }, + { status: 400 } + ) + } + + // Check if document exists and belongs to user + const existingDocument = await db.document.findFirst({ + where: { + id, + userId, + isArchived: false, + }, + }) + + if (!existingDocument) { + return NextResponse.json( + { error: 'Document not found' }, + { status: 404 } + ) + } + + // Extract and delete all image files from the document + const imagePaths = await extractImagePaths(existingDocument.content); + if (imagePaths.length > 0) { + console.log(`Deleting ${imagePaths.length} image files from document ${id}`); + + // Delete all image files + await Promise.allSettled( + imagePaths.map(path => { + try { + return deleteFile(path); + } catch (error) { + console.error(`Failed to delete image file ${path}:`, error); + return Promise.resolve(); + } + }) + ); + } + + // Archive the document instead of deleting it + const document = await db.document.update({ + where: { id }, + data: { + isArchived: true, + updatedAt: new Date(), + }, + }) + + return NextResponse.json({ message: 'Document archived successfully' }) + } catch (error) { + console.error('Error archiving document:', error) + return NextResponse.json( + { error: 'Failed to archive document' }, + { status: 500 } + ) + } +}) diff --git a/nextjs/app/api/documents/route.ts b/nextjs/app/api/documents/route.ts new file mode 100644 index 0000000..eba7cac --- /dev/null +++ b/nextjs/app/api/documents/route.ts @@ -0,0 +1,84 @@ +import { NextRequest, NextResponse } from 'next/server' +import { withAuth } from '@/shared/lib/middleware' +import { db } from '@/shared/lib/db' + +// GET /api/documents - Get all documents for the authenticated user +export const GET = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const folderId = url.searchParams.get('folderId') + + const documents = await db.document.findMany({ + where: { + userId, + isArchived: false, + ...(folderId && { folderId }), + }, + include: { + folder: { + select: { + id: true, + name: true, + icon: true, + }, + }, + }, + orderBy: { + createdAt: 'desc', + }, + }) + + return NextResponse.json(documents) + } catch (error) { + console.error('Error fetching documents:', error) + return NextResponse.json( + { error: 'Failed to fetch documents' }, + { status: 500 } + ) + } +}) + +// POST /api/documents - Create a new document +export const POST = withAuth(async (req: NextRequest, userId: string) => { + try { + const { title, parentId, folderId } = await req.json() + + if (!title) { + return NextResponse.json( + { error: 'Title is required' }, + { status: 400 } + ) + } + + const document = await db.document.create({ + data: { + title, + userId, + parentId: parentId || null, + folderId: folderId || null, + content: { + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Start writing...', + }, + ], + }, + ], + }, + }, + }) + + return NextResponse.json(document, { status: 201 }) + } catch (error) { + console.error('Error creating document:', error) + return NextResponse.json( + { error: 'Failed to create document' }, + { status: 500 } + ) + } +}) diff --git a/nextjs/app/api/download-url/route.ts b/nextjs/app/api/download-url/route.ts new file mode 100644 index 0000000..867662b --- /dev/null +++ b/nextjs/app/api/download-url/route.ts @@ -0,0 +1,46 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { GetObjectCommand } from '@aws-sdk/client-s3'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +import { S3_CONFIG, s3Client } from '@/shared/config/s3'; + +// 파일 다운로드 URL 생성 +const generateDownloadUrl = async (fileKey: string): Promise => { + try { + const command = new GetObjectCommand({ + Bucket: S3_CONFIG.BUCKET_NAME, + Key: fileKey, + }); + + const downloadUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); + + return downloadUrl; + } catch (error) { + throw new Error('다운로드 URL 생성에 실패했습니다.'); + } +}; + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { fileKey } = body; + + if (!fileKey) { + return NextResponse.json( + { error: 'fileKey가 필요합니다.' }, + { status: 400 } + ); + } + + const downloadUrl = await generateDownloadUrl(fileKey); + + return NextResponse.json({ + downloadUrl, + }); + } catch (error: any) { + return NextResponse.json( + { error: error.message || '다운로드 URL 생성에 실패했습니다.' }, + { status: 500 } + ); + } +} + diff --git a/nextjs/app/api/folders/[id]/route.ts b/nextjs/app/api/folders/[id]/route.ts new file mode 100644 index 0000000..1806e47 --- /dev/null +++ b/nextjs/app/api/folders/[id]/route.ts @@ -0,0 +1,264 @@ +import { NextRequest, NextResponse } from 'next/server' +import { withAuth } from '@/shared/lib/middleware' +import { db } from '@/shared/lib/db' + +// GET /api/folders/[id] - Get a specific folder +export const GET = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + + if (!id) { + return NextResponse.json( + { error: 'Folder ID is required' }, + { status: 400 } + ) + } + + const folder = await db.folder.findFirst({ + where: { + id, + userId, + isArchived: false, + }, + include: { + documents: { + where: { + isArchived: false, + }, + select: { + id: true, + title: true, + icon: true, + updatedAt: true, + }, + orderBy: { + updatedAt: 'desc', + }, + }, + children: { + where: { + isArchived: false, + }, + orderBy: { + createdAt: 'desc', + }, + }, + parent: { + select: { + id: true, + name: true, + }, + }, + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + }) + + if (!folder) { + return NextResponse.json( + { error: 'Folder not found' }, + { status: 404 } + ) + } + + return NextResponse.json(folder) + } catch (error) { + console.error('Error fetching folder:', error) + return NextResponse.json( + { error: 'Failed to fetch folder' }, + { status: 500 } + ) + } +}) + +// PUT /api/folders/[id] - Update a specific folder +export const PUT = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + const { name, parentId, icon, color } = await req.json() + + if (!id) { + return NextResponse.json( + { error: 'Folder ID is required' }, + { status: 400 } + ) + } + + // Check if folder exists and belongs to user + const existingFolder = await db.folder.findFirst({ + where: { + id, + userId, + isArchived: false, + }, + }) + + if (!existingFolder) { + return NextResponse.json( + { error: 'Folder not found' }, + { status: 404 } + ) + } + + const folder = await db.folder.update({ + where: { id }, + data: { + ...(name && { name }), + ...(parentId !== undefined && { parentId: parentId || null }), + ...(icon !== undefined && { icon }), + ...(color !== undefined && { color }), + updatedAt: new Date(), + }, + include: { + documents: { + where: { + isArchived: false, + }, + select: { + id: true, + title: true, + icon: true, + updatedAt: true, + }, + orderBy: { + updatedAt: 'desc', + }, + }, + children: { + where: { + isArchived: false, + }, + orderBy: { + createdAt: 'desc', + }, + }, + parent: { + select: { + id: true, + name: true, + }, + }, + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + }) + + return NextResponse.json(folder) + } catch (error) { + console.error('Error updating folder:', error) + return NextResponse.json( + { error: 'Failed to update folder' }, + { status: 500 } + ) + } +}) + +// DELETE /api/folders/[id] - Archive a specific folder +export const DELETE = withAuth(async (req: NextRequest, userId: string) => { + try { + const url = new URL(req.url) + const id = url.pathname.split('/').pop() + + if (!id) { + return NextResponse.json( + { error: 'Folder ID is required' }, + { status: 400 } + ) + } + + // Check if folder exists and belongs to user + const existingFolder = await db.folder.findFirst({ + where: { + id, + userId, + isArchived: false, + }, + }) + + if (!existingFolder) { + return NextResponse.json( + { error: 'Folder not found' }, + { status: 404 } + ) + } + + // Recursively archive the folder and all its contents + const archiveFolderRecursively = async (folderId: string, tx: any) => { + // Archive all documents in this folder + await tx.document.updateMany({ + where: { + folderId: folderId, + isArchived: false, + }, + data: { + isArchived: true, + updatedAt: new Date(), + }, + }) + + // Get all child folders + const childFolders = await tx.folder.findMany({ + where: { + parentId: folderId, + isArchived: false, + }, + select: { + id: true, + }, + }) + + // Recursively archive all child folders + for (const childFolder of childFolders) { + await archiveFolderRecursively(childFolder.id, tx) + } + + // Archive this folder + await tx.folder.update({ + where: { id: folderId }, + data: { + isArchived: true, + updatedAt: new Date(), + }, + }) + } + + // Archive the folder and all its contents + await db.$transaction(async (tx) => { + await archiveFolderRecursively(id, tx) + }) + + return NextResponse.json({ message: 'Folder archived successfully' }) + } catch (error) { + console.error('Error archiving folder:', error) + return NextResponse.json( + { error: 'Failed to archive folder' }, + { status: 500 } + ) + } +}) diff --git a/nextjs/app/api/folders/route.ts b/nextjs/app/api/folders/route.ts new file mode 100644 index 0000000..7680f20 --- /dev/null +++ b/nextjs/app/api/folders/route.ts @@ -0,0 +1,154 @@ +import { NextRequest, NextResponse } from 'next/server' +import { withAuth } from '@/shared/lib/middleware' +import { db } from '@/shared/lib/db' + +// GET /api/folders - Get all folders for the authenticated user +export const GET = withAuth(async (req: NextRequest, userId: string) => { + try { + const folders = await db.folder.findMany({ + where: { + userId, + isArchived: false, + }, + include: { + documents: { + where: { + isArchived: false, + }, + select: { + id: true, + title: true, + icon: true, + updatedAt: true, + }, + }, + children: { + where: { + isArchived: false, + }, + include: { + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + }, + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + orderBy: { + createdAt: 'desc', + }, + }) + + return NextResponse.json(folders) + } catch (error) { + console.error('Error fetching folders:', error) + return NextResponse.json( + { error: 'Failed to fetch folders' }, + { status: 500 } + ) + } +}) + +// POST /api/folders - Create a new folder +export const POST = withAuth(async (req: NextRequest, userId: string) => { + try { + const { name, parentId, icon, color } = await req.json() + + if (!name) { + return NextResponse.json( + { error: 'Folder name is required' }, + { status: 400 } + ) + } + + const folder = await db.folder.create({ + data: { + name, + userId, + parentId: parentId || null, + icon: icon || '📁', + color: color || null, + }, + include: { + documents: { + where: { + isArchived: false, + }, + select: { + id: true, + title: true, + icon: true, + updatedAt: true, + }, + }, + children: { + where: { + isArchived: false, + }, + include: { + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + }, + _count: { + select: { + documents: { + where: { + isArchived: false, + }, + }, + children: { + where: { + isArchived: false, + }, + }, + }, + }, + }, + }) + + return NextResponse.json(folder, { status: 201 }) + } catch (error) { + console.error('Error creating folder:', error) + return NextResponse.json( + { error: 'Failed to create folder' }, + { status: 500 } + ) + } +}) diff --git a/nextjs/app/api/health/route.ts b/nextjs/app/api/health/route.ts new file mode 100644 index 0000000..5802677 --- /dev/null +++ b/nextjs/app/api/health/route.ts @@ -0,0 +1,27 @@ +import { NextResponse } from 'next/server'; +import { db } from '@/shared/lib/db'; + +export async function GET() { + try { + // Check database connectivity + await db.$queryRaw`SELECT 1`; + + return NextResponse.json({ + status: 'healthy', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + environment: process.env.NODE_ENV, + version: process.env.npm_package_version || '1.0.0', + database: 'connected' + }); + } catch (error) { + return NextResponse.json( + { + status: 'unhealthy', + timestamp: new Date().toISOString(), + error: 'Database connection failed' + }, + { status: 503 } + ); + } +} diff --git a/nextjs/app/api/metadata/route.ts b/nextjs/app/api/metadata/route.ts new file mode 100644 index 0000000..3ce695a --- /dev/null +++ b/nextjs/app/api/metadata/route.ts @@ -0,0 +1,22 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { extractBookmarkMetadata } from '@/shared/lib/metadata-extractor'; + +export async function POST(request: NextRequest) { + try { + const { url } = await request.json(); + + if (!url) { + return NextResponse.json({ error: 'URL is required' }, { status: 400 }); + } + + const metadata = await extractBookmarkMetadata(url); + + return NextResponse.json(metadata); + } catch (error) { + console.error('Error in metadata API:', error); + return NextResponse.json( + { error: 'Failed to fetch metadata' }, + { status: 500 } + ); + } +} diff --git a/nextjs/app/api/templates/route.ts b/nextjs/app/api/templates/route.ts new file mode 100644 index 0000000..91c35ab --- /dev/null +++ b/nextjs/app/api/templates/route.ts @@ -0,0 +1,105 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/shared/lib/prisma'; +import { withAuth } from '@/shared/lib/middleware'; + +async function createTemplate(request: NextRequest, userId: string) { + try { + const { name, description, category, title, content } = await request.json(); + + if (!name || !title || !content) { + return NextResponse.json( + { error: 'Template name, title, and content are required' }, + { status: 400 } + ); + } + + // Verify user exists in database + const user = await prisma.user.findUnique({ + where: { id: userId } + }); + + if (!user) { + return NextResponse.json( + { error: 'User not found' }, + { status: 404 } + ); + } + + // Save template to database (always private to the user) + const template = await prisma.template.create({ + data: { + name, + description: description || '', + category: category || 'General', + title, + content, + isPublic: false, // Always private + userId, + }, + }); + + console.log('Template created:', template); + + return NextResponse.json({ + success: true, + template, + message: 'Template created successfully' + }); + } catch (error) { + console.error('Error creating template:', error); + return NextResponse.json( + { error: 'Failed to create template' }, + { status: 500 } + ); + } +} + +export const POST = withAuth(createTemplate); + +async function getTemplates(request: NextRequest, userId: string) { + try { + // Verify user exists in database + const user = await prisma.user.findUnique({ + where: { id: userId } + }); + + if (!user) { + return NextResponse.json( + { error: 'User not found' }, + { status: 404 } + ); + } + + // Fetch only user's own templates + const templates = await prisma.template.findMany({ + where: { + userId // Only user's own templates + }, + orderBy: { + createdAt: 'desc' + }, + select: { + id: true, + name: true, + description: true, + category: true, + title: true, + content: true, + isPublic: true, + createdAt: true, + updatedAt: true, + userId: true, + } + }); + + return NextResponse.json({ templates }); + } catch (error) { + console.error('Error fetching templates:', error); + return NextResponse.json( + { error: 'Failed to fetch templates' }, + { status: 500 } + ); + } +} + +export const GET = withAuth(getTemplates); diff --git a/nextjs/app/api/upload-url/route.ts b/nextjs/app/api/upload-url/route.ts new file mode 100644 index 0000000..4f77c2f --- /dev/null +++ b/nextjs/app/api/upload-url/route.ts @@ -0,0 +1,57 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { PutObjectCommand } from '@aws-sdk/client-s3'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +import { S3_CONFIG, s3Client } from '@/shared/config/s3'; + +// 파일 업로드 URL 생성 +const generateUploadUrl = async ( + fileName: string, + fileType: string, + folder?: string +): Promise<{ uploadUrl: string; fileKey: string }> => { + try { + const fileKey = folder ? `${folder}/${Date.now()}-${fileName}` : `${Date.now()}-${fileName}`; + + const command = new PutObjectCommand({ + Bucket: S3_CONFIG.BUCKET_NAME, + Key: fileKey, + ContentType: fileType, + }); + + const uploadUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); + + return { + uploadUrl, + fileKey, + }; + } catch (error: any) { + throw new Error(`업로드 URL 생성에 실패했습니다: ${error.message}`); + } +}; + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { fileName, fileType, folder } = body; + + if (!fileName || !fileType) { + return NextResponse.json( + { error: 'fileName과 fileType이 필요합니다.' }, + { status: 400 } + ); + } + + const { uploadUrl, fileKey } = await generateUploadUrl(fileName, fileType, folder || 'jotion-uploads'); + + return NextResponse.json({ + uploadUrl, + fileKey, + }); + } catch (error: any) { + return NextResponse.json( + { error: error.message || '업로드 URL 생성에 실패했습니다.' }, + { status: 500 } + ); + } +} + diff --git a/nextjs/app/api/upload/route.ts b/nextjs/app/api/upload/route.ts new file mode 100644 index 0000000..7689ec4 --- /dev/null +++ b/nextjs/app/api/upload/route.ts @@ -0,0 +1,177 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { uploadFileServer, deleteFile } from '@/shared/lib/s3'; +import { cookies } from 'next/headers'; +import { verifyToken } from '@/shared/lib/auth'; + +// File size limits (in bytes) +const MAX_FILE_SIZE = { + image: 10 * 1024 * 1024, // 10MB + audio: 50 * 1024 * 1024, // 50MB + document: 20 * 1024 * 1024, // 20MB +}; + +// Allowed file types +const ALLOWED_TYPES = { + image: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'], + audio: ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/mp4', 'audio/webm'], + document: [ + 'application/pdf', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'text/plain', + 'text/csv', + ], +}; + +export async function POST(request: NextRequest) { + try { + // Verify authentication - check cookie + const cookieStore = await cookies(); + const cookieToken = cookieStore.get('auth-token')?.value; + + const token = cookieToken; + + if (!token) { + console.error('[Upload] No token found in Authorization header or cookie'); + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + const decoded = verifyToken(token); + if (!decoded) { + console.error('[Upload] Token verification failed'); + return NextResponse.json( + { error: 'Invalid token' }, + { status: 401 } + ); + } + console.log('[Upload] Token verified successfully for user:', decoded.userId); + + // Parse form data + const formData = await request.formData(); + const file = formData.get('file') as File; + const fileType = formData.get('type') as 'images' | 'audio' | 'documents'; + + if (!file) { + return NextResponse.json( + { error: 'No file provided' }, + { status: 400 } + ); + } + + // Determine folder based on file type + let folder: 'images' | 'audio' | 'documents' = 'documents'; + let maxSize = MAX_FILE_SIZE.document; + let allowedTypes = ALLOWED_TYPES.document; + + if (fileType === 'images') { + folder = 'images'; + maxSize = MAX_FILE_SIZE.image; + allowedTypes = ALLOWED_TYPES.image; + } else if (fileType === 'audio') { + folder = 'audio'; + maxSize = MAX_FILE_SIZE.audio; + allowedTypes = ALLOWED_TYPES.audio; + } else if (file.type.startsWith('image/')) { + folder = 'images'; + maxSize = MAX_FILE_SIZE.image; + allowedTypes = ALLOWED_TYPES.image; + } else if (file.type.startsWith('audio/')) { + folder = 'audio'; + maxSize = MAX_FILE_SIZE.audio; + allowedTypes = ALLOWED_TYPES.audio; + } + + // Validate file size + if (file.size > maxSize) { + return NextResponse.json( + { error: `File size exceeds maximum limit of ${maxSize / 1024 / 1024}MB` }, + { status: 400 } + ); + } + + // Validate file type + if (!allowedTypes.includes(file.type)) { + return NextResponse.json( + { error: `File type ${file.type} is not allowed` }, + { status: 400 } + ); + } + + // Upload file to S3 + const { url, path } = await uploadFileServer(file, file.name, file.type, folder); + + return NextResponse.json({ + success: true, + url, + path, + fileName: file.name, + fileSize: file.size, + fileType: file.type, + }); + } catch (error) { + console.error('Upload error:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Failed to upload file' }, + { status: 500 } + ); + } +} + +// DELETE /api/upload - Delete a file from storage +export async function DELETE(request: NextRequest) { + try { + // Verify authentication + const authHeader = request.headers.get('Authorization'); + const cookieStore = await cookies(); + const cookieToken = cookieStore.get('auth-token')?.value; + + const token = authHeader?.startsWith('Bearer ') + ? authHeader.substring(7) + : cookieToken; + + if (!token) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + const decoded = verifyToken(token); + if (!decoded) { + return NextResponse.json( + { error: 'Invalid token' }, + { status: 401 } + ); + } + + const { searchParams } = new URL(request.url); + const filePath = searchParams.get('path'); + + if (!filePath) { + return NextResponse.json( + { error: 'File path is required' }, + { status: 400 } + ); + } + + // Delete file from S3 + await deleteFile(filePath); + + return NextResponse.json({ + success: true, + message: 'File deleted successfully', + }); + } catch (error) { + console.error('Delete file error:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Failed to delete file' }, + { status: 500 } + ); + } +} + diff --git a/nextjs/app/documents/[id]/page.tsx b/nextjs/app/documents/[id]/page.tsx new file mode 100644 index 0000000..d10422b --- /dev/null +++ b/nextjs/app/documents/[id]/page.tsx @@ -0,0 +1,296 @@ +"use client"; + +import { useAuth } from "@/src/app/providers/auth-provider"; +import { + useDocumentData, + useDocumentSave, + useDocumentActions, + useDocumentTemplates, + useDocumentUtils, + useDocumentHeadings, + useSidebarSearch +} from "@/features/document-edit/model"; +import { Button } from "@/shared/ui/button"; +import { Spinner } from "@/shared/ui/spinner"; +import { RichTextEditor } from "@/widgets/editor/editor/core/rich-text-editor"; +import { DocumentSidebar } from "@/widgets/editor/sidebar/document-sidebar"; +import { ArrowLeft, Save, Clock, User, Eye, BookOpen, FileText, Calendar } from "lucide-react"; +import { useState } from "react"; +import { useRouter, useParams } from "next/navigation"; +import { DocumentDetailSkeleton } from "@/shared/ui/skeleton"; + +const DocumentPage = () => { + const { user } = useAuth(); + const router = useRouter(); + const params = useParams(); + const documentId = params.id as string; + + // 1. 문서 데이터 관리 + const { + document, + isLoading, + title, + setTitle, + content, + setContent, + availableDocuments, + updateDocument, + } = useDocumentData({ documentId }); + + // 2. 저장 기능 + const { + saveDocument, + isSaving, + isAutoSaving, + lastSaved, + } = useDocumentSave({ + documentId, + title, + content, + onSaveSuccess: updateDocument, + }); + + // 3. 문서 액션 + const { + deleteDocument, + shareDocument, + unshareDocument, + isDeleting, + } = useDocumentActions({ + documentId, + onPublishChange: (isPublished) => { + if (document) { + updateDocument({ ...document, isPublished }); + } + }, + }); + + // 4. 템플릿 기능 + const { + createTemplate, + applyTemplate, + } = useDocumentTemplates({ + onApply: (templateContent, templateTitle) => { + setContent(templateContent); + if (templateTitle && !title.trim()) { + setTitle(templateTitle); + } + }, + }); + + // 5. 유틸리티 + const { getWordCount, formatDate } = useDocumentUtils(); + + const [showWordCount, setShowWordCount] = useState(false); + + + if (isLoading) { + return ; + } + + if (!document) { + return ( +
+
+
+ +
+

Document not found

+

+ The document you're looking for doesn't exist or you don't have access to it. +

+ +
+
+ ); + } + + return ( +
+ {/* Modern header */} +
+
+
+ {/* Breadcrumb */} +
+ +
+ {user?.name ? `${user.name}'s` : "My"} Workspace + / + {document.folder && ( + <> + {document.folder.name} + / + + )} + {title || "Untitled"} +
+
+ + {/* Status and actions */} +
+ {/* Auto-save status */} +
+ {isAutoSaving ? ( + <> + + Saving... + + ) : lastSaved ? ( + <> + + Saved {formatDate(lastSaved)} + + ) : null} +
+ + {/* Word count - Hidden on very small screens */} + + + {/* Actions */} +
+ + + {/* Mobile save button */} + +
+
+
+
+
+ + {/* Main content area - Responsive layout */} +
+ {/* Document editor - Full width on mobile/tablet, left side on desktop */} +
+
+ {/* Document header */} +
+ {/* Document icon and title */} +
+
+ {document.icon ? ( + {document.icon} + ) : ( + + )} +
+
+ setTitle(e.target.value)} + className="w-full text-2xl sm:text-3xl lg:text-4xl font-bold text-gray-900 dark:text-white bg-transparent border-none outline-none placeholder-gray-400 dark:placeholder-gray-500" + placeholder="Untitled" + /> +
+
+ + {user?.name || "Anonymous"} +
+
+ + Created {new Date(document.createdAt).toLocaleDateString()} +
+ {document.isPublished && ( + + )} +
+
+
+
+ + {/* Editor */} +
+ +
+
+
+ + {/* Right panel - Document sidebar - Hidden on mobile/tablet, shown on desktop */} +
+ +
+
+ +
+ ); +}; + +export default DocumentPage; diff --git a/nextjs/app/documents/layout.tsx b/nextjs/app/documents/layout.tsx new file mode 100644 index 0000000..5f5a8cb --- /dev/null +++ b/nextjs/app/documents/layout.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { Spinner } from "@/shared/ui/spinner"; +import { useRouter } from "next/navigation"; +import { Navigation } from "@/widgets/documents"; +import { useAuth } from "@/src/app/providers/auth-provider"; +import { useEffect } from "react"; + +const MainLayout = ({ children }: { children: React.ReactNode }) => { + const { user, isLoading } = useAuth(); + const router = useRouter(); + + useEffect(() => { + if (!isLoading && !user) { + router.push("/"); + } + }, [isLoading, user, router]); + + if (isLoading) { + return ( +
+ +
+ ); + } + + if (!user) { + return ( +
+ +
+ ); + } + + return ( +
+ +
+ {children} +
+
+ ); +}; + +export default MainLayout; diff --git a/nextjs/app/documents/page.tsx b/nextjs/app/documents/page.tsx new file mode 100644 index 0000000..07dc773 --- /dev/null +++ b/nextjs/app/documents/page.tsx @@ -0,0 +1,202 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { useSearchParams } from "next/navigation"; +import { useAuth } from "@/src/app/providers/auth-provider"; +import { useDocumentManagementStore } from "@/features/document-management/model/store"; +import { useFolderManagementStore } from "@/features/folder-management/model/store"; +import { useDocumentStore } from "@/entities/document/model/store"; +import { useFolderStore } from "@/entities/folder/model/store"; +import { Spinner } from "@/shared/ui/spinner"; +import { Header, CreateInput, FolderView, RootView } from "@/widgets/documents"; +import { Button } from "@/shared/ui/button"; +import { Plus, Folder } from "lucide-react"; +import { DocumentsPageSkeleton } from "@/shared/ui/skeleton"; + +const DocumentsPage = () => { + const { user } = useAuth(); + const searchParams = useSearchParams(); + const currentFolderId = searchParams?.get('folder'); + + // Use management stores for operations + const documentManagement = useDocumentManagementStore(); + const folderManagement = useFolderManagementStore(); + + // Use entity stores for state + const documentStore = useDocumentStore(); + const folderStore = useFolderStore(); + + const documents = documentStore.documents; + const folders = folderStore.folders; + const isLoading = documentStore.isLoading || folderStore.isLoading; + + // Destructure specific functions + const { fetchDocuments, createDocument } = documentManagement; + const { fetchFolders, createFolder } = folderManagement; + + const [isCreatingFolder, setIsCreatingFolder] = useState(false); + const [newFolderName, setNewFolderName] = useState(''); + const [refreshKey, setRefreshKey] = useState(0); + + // Fetch initial data + useEffect(() => { + fetchDocuments(); + fetchFolders(); + }, []); // eslint-disable-line react-hooks/exhaustive-deps + + const handleCreateFolder = async () => { + if (!newFolderName.trim()) return; + + const newFolder = await createFolder(newFolderName, currentFolderId); + if (newFolder) { + setNewFolderName(''); + setIsCreatingFolder(false); + // Refresh data to show the new folder + fetchFolders(); + if (currentFolderId) { + setRefreshKey(prev => prev + 1); + } + } + }; + + const handleCreateDocumentFromHeader = async () => { + await createDocument(currentFolderId); + if (currentFolderId) { + setRefreshKey(prev => prev + 1); + } + }; + + const handleNavigateToFolder = (folderId: string) => { + window.history.pushState({}, '', `/documents?folder=${folderId}`); + window.dispatchEvent(new Event('popstate')); + }; + + const handleGoBack = () => { + window.history.back(); + }; + + const handleFolderDeleted = () => { + // Refresh folders list + fetchFolders(); + fetchDocuments(); + // Force refresh if we're in a folder view + if (currentFolderId) { + setRefreshKey(prev => prev + 1); + } + }; + + // Show loading skeleton while data is being fetched + if (isLoading) { + return ( +
+
setIsCreatingFolder(true)} + onCreateDocument={handleCreateDocumentFromHeader} + /> +
+ +
+
+ ); + } + + return ( +
+ {/* Header */} +
setIsCreatingFolder(true)} + onCreateDocument={handleCreateDocumentFromHeader} + /> + + {/* Create folder input - shown when creating from header */} + {isCreatingFolder && ( +
+ { + setIsCreatingFolder(false); + setNewFolderName(''); + }} + /> +
+ )} + + {/* Main content - Desktop layout */} +
+
+
+
+ {currentFolderId ? ( + + ) : ( + setIsCreatingFolder(true)} + onNavigateToFolder={handleNavigateToFolder} + onFolderDeleted={handleFolderDeleted} + variant="desktop" + /> + )} +
+
+
+
+ + {/* Mobile layout */} +
+
+
+ + {/* Create folder input */} + {isCreatingFolder && ( + { + setIsCreatingFolder(false); + setNewFolderName(''); + }} + /> + )} + + {/* Content */} + {currentFolderId ? ( + + ) : ( + setIsCreatingFolder(true)} + onNavigateToFolder={handleNavigateToFolder} + onFolderDeleted={handleFolderDeleted} + variant="mobile" + /> + )} +
+
+
+
+ ); +}; + +export default DocumentsPage; diff --git a/nextjs/app/documents/todos/page.tsx b/nextjs/app/documents/todos/page.tsx new file mode 100644 index 0000000..4ae3129 --- /dev/null +++ b/nextjs/app/documents/todos/page.tsx @@ -0,0 +1,12 @@ +'use client' + +import { TodoPanel } from '@/widgets/todo' + +export default function TodosPage() { + return ( +
+ +
+ ) +} + diff --git a/nextjs/app/favicon.ico b/nextjs/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fb679887c80f21dc0d06ad83d5fb66d4ef96cb49 GIT binary patch literal 26928 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 VsgmQDK%N5ts48kGe37?|_#Y-dv|0cF literal 0 HcmV?d00001 diff --git a/nextjs/app/globals.css b/nextjs/app/globals.css new file mode 100644 index 0000000..5890da7 --- /dev/null +++ b/nextjs/app/globals.css @@ -0,0 +1,321 @@ +@tailwind base; + @tailwind components; + @tailwind utilities; + + /* Hide scrollbar but keep functionality */ + .scrollbar-hide { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } + .scrollbar-hide::-webkit-scrollbar { + display: none; /* Chrome, Safari and Opera */ + } + + html, + body, + :root { + height: 100%; + } + + @layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + } + } + + @layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } + } + + /* Tiptap Editor Styles */ + .ProseMirror { + outline: none; + min-height: 200px; + color: #1f2937; /* Default text color for light theme */ + } + + /* Dark theme text color */ + .dark .ProseMirror, + .dark .ProseMirror p, + .dark .ProseMirror div, + .dark .ProseMirror span { + color: #ffffff !important; /* 완전한 하얀색 강제 적용 */ + } + + .ProseMirror p.is-editor-empty:first-child::before { + color: #adb5bd; + content: attr(data-placeholder); + float: left; + height: 0; + pointer-events: none; + } + + /* Dark theme placeholder */ + .dark .ProseMirror p.is-editor-empty:first-child::before { + color: #6b7280; + } + + .ProseMirror h1 { + font-size: 2em; + font-weight: bold; + margin: 0.67em 0; + color: #111827; + } + + .ProseMirror h2 { + font-size: 1.5em; + font-weight: bold; + margin: 0.83em 0; + color: #111827; + } + + .ProseMirror h3 { + font-size: 1.17em; + font-weight: bold; + margin: 1em 0; + color: #111827; + } + + /* Dark theme headings */ + .dark .ProseMirror h1, + .dark .ProseMirror h2, + .dark .ProseMirror h3 { + color: #f9fafb; + } + + .ProseMirror ul, + .ProseMirror ol { + padding-left: 1.5em; + color: inherit; + } + + .ProseMirror li { + color: inherit; + } + + .ProseMirror blockquote { + border-left: 3px solid #e2e8f0; + padding-left: 1rem; + margin: 1rem 0; + font-style: italic; + color: #6b7280; + } + + /* Dark theme blockquote */ + .dark .ProseMirror blockquote { + color: #ffffff; /* 완전한 하얀색 */ + } + + .ProseMirror code { + background-color: #f1f5f9; + border-radius: 0.25rem; + padding: 0.125rem 0.25rem; + font-family: 'Courier New', monospace; + color: #374151; + } + + /* Dark theme inline code */ + .dark .ProseMirror code { + background-color: #374151; + color: #f3f4f6; + } + + .ProseMirror pre { + background-color: #1e293b; + color: #e2e8f0; + border-radius: 0.5rem; + padding: 1rem; + overflow-x: auto; + margin: 1rem 0; + } + + .ProseMirror pre code { + background: none; + padding: 0; + color: inherit; + } + + .ProseMirror table { + border-collapse: collapse; + margin: 1rem 0; + width: 100%; + } + + .ProseMirror th, + .ProseMirror td { + border: 1px solid #e2e8f0; + padding: 0.5rem; + text-align: left; + } + + .ProseMirror th { + background-color: #f8fafc; + font-weight: bold; + } + + .ProseMirror img { + max-width: 100%; + height: auto; + border-radius: 0.5rem; + } + + .ProseMirror a { + color: #3b82f6; + text-decoration: underline; + } + + /* Dark theme links */ + .dark .ProseMirror a { + color: #60a5fa; + } + + .ProseMirror mark { + background-color: #fef08a; + padding: 0.125rem 0.25rem; + border-radius: 0.25rem; + } + + /* Dark theme highlight */ + .dark .ProseMirror mark { + background-color: #fbbf24; + color: #111827; + } + + .ProseMirror ul[data-type="taskList"] { + list-style: none; + padding: 0; + } + + .ProseMirror ul[data-type="taskList"] li { + display: flex; + align-items: flex-start; + } + + .ProseMirror ul[data-type="taskList"] li > label { + flex: 0 0 auto; + margin-right: 0.5rem; + user-select: none; + } + + .ProseMirror ul[data-type="taskList"] li > div { + flex: 1 1 auto; + } + + .ProseMirror ul[data-type="taskList"] input[type="checkbox"] { + cursor: pointer; + } + + /* Dark mode styles */ + .dark .ProseMirror blockquote { + border-left-color: #475569; + } + + .dark .ProseMirror code { + background-color: #334155; + } + + .dark .ProseMirror th { + background-color: #1e293b; + } + + .dark .ProseMirror th, + .dark .ProseMirror td { + border-color: #475569; + } + + /* Line clamp utilities */ + .line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } + + /* Code block styles */ + pre { + display: block; + overflow-x: auto; + padding: 1rem; + background: #1e1e1e; + color: #d4d4d4; + border-radius: 0.5rem; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 0.875rem; + line-height: 1.5; + } + + /* Light mode code block */ + .light pre { + background: #f8f8f8; + color: #333; + } \ No newline at end of file diff --git a/nextjs/app/home/layout.tsx b/nextjs/app/home/layout.tsx new file mode 100644 index 0000000..f09860c --- /dev/null +++ b/nextjs/app/home/layout.tsx @@ -0,0 +1,12 @@ +import { Navbar } from "@/widgets/landing"; + +const MarketingLayout = ({ children }: { children: React.ReactNode }) => { + return ( +
+ +
{children}
+
+ ); +}; + +export default MarketingLayout; \ No newline at end of file diff --git a/nextjs/app/home/page.tsx b/nextjs/app/home/page.tsx new file mode 100644 index 0000000..7d89e43 --- /dev/null +++ b/nextjs/app/home/page.tsx @@ -0,0 +1,17 @@ +import { Heading } from "@/widgets/landing"; +import { Heroes } from "@/widgets/landing"; +import { Footer } from "@/widgets/landing"; + +const MarketingPage = () => { + return ( +
+
+ + +
+
+
+ ); +}; + +export default MarketingPage; diff --git a/nextjs/app/home/share/[id]/page.tsx b/nextjs/app/home/share/[id]/page.tsx new file mode 100644 index 0000000..1799e47 --- /dev/null +++ b/nextjs/app/home/share/[id]/page.tsx @@ -0,0 +1,161 @@ +"use client"; + +import { useState, useEffect } from 'react'; +import { useParams } from 'next/navigation'; +import { DocumentSidebar } from '@/widgets/editor/sidebar/document-sidebar'; +import { RichTextEditor } from '@/widgets/editor/editor/core/rich-text-editor'; +import { Button } from '@/shared/ui/button'; +import { ArrowLeft, Copy, Check, Share2, User, Calendar } from 'lucide-react'; +import Link from 'next/link'; +import type { Document } from '@/shared/types/document'; +import { SharedDocumentSkeleton } from '@/shared/ui/skeleton'; + +interface SharedDocument extends Document { + user: { + name: string; + email: string; + }; +} + +export default function ShareDocumentPage() { + const params = useParams(); + const documentId = params.id as string; + + const [document, setDocument] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchDocument = async () => { + try { + const response = await fetch(`/api/documents/${documentId}/public`); + if (!response.ok) { + throw new Error('Document not found or not published'); + } + + const data = await response.json(); + setDocument(data); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to load document'); + } finally { + setLoading(false); + } + }; + + if (documentId) { + fetchDocument(); + } + }, [documentId]); + + const getWordCount = (content: any): number => { + if (!content) return 0; + + const extractText = (node: any): string => { + if (typeof node === 'string') return node; + if (node.text) return node.text; + if (node.content) { + return node.content.map(extractText).join(' '); + } + return ''; + }; + + const text = extractText(content); + return text.trim().split(/\s+/).filter(word => word.length > 0).length; + }; + + if (loading) { + return ; + } + + if (error || !document) { + return ( +
+
+
📄
+

Document Not Found

+

+ {error || 'This document may not exist or may not be publicly shared.'} +

+ + + +
+
+ ); + } + + const wordCount = getWordCount(document.content); + + return ( +
+ {/* Main Content */} +
+
+ {/* Document Content */} +
+
+
+ +
+
+
+ + {/* Sidebar */} +
+
+ + + {/* Document Info */} +
+

+ + Document Info +

+
+
+ + Author: {document.user.name} +
+
+ + Created: {new Date(document.createdAt).toLocaleDateString()} +
+
+ + Updated: {new Date(document.updatedAt).toLocaleDateString()} +
+
+
+
+
+
+
+ + {/* Footer */} +
+
+
+

This document was shared from Jotion

+

+ Last updated: {new Date(document.updatedAt).toLocaleDateString()} +

+
+
+
+
+ ); +} diff --git a/nextjs/app/home/signIn/page.tsx b/nextjs/app/home/signIn/page.tsx new file mode 100644 index 0000000..7d986ce --- /dev/null +++ b/nextjs/app/home/signIn/page.tsx @@ -0,0 +1,116 @@ +"use client" + +import { useState } from "react" +import { useRouter } from "next/navigation" +import { Button } from "@/shared/ui/button" +import { Logo } from "@/widgets/landing" +import Link from "next/link" +import { useAuth } from "@/src/app/providers/auth-provider" + +export default function LoginPage() { + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState("") + const router = useRouter() + const { login } = useAuth() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setIsLoading(true) + setError("") + + try { + const response = await fetch("/api/auth/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, password }), + }) + + const data = await response.json() + + if (response.ok) { + // Update auth context with user data + login(data.token, data.user) + + // Redirect to documents page + router.push("/documents") + } else { + setError(data.error || "Login failed") + } + } catch (error) { + setError("An error occurred. Please try again.") + } finally { + setIsLoading(false) + } + } + + return ( +
+
+
+ +

Sign in to your account

+

+ Or{" "} + + create a new account + +

+
+ +
+ {error && ( +
+ {error} +
+ )} + +
+
+ + setEmail(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Enter your email" + /> +
+ +
+ + setPassword(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Enter your password" + /> +
+
+ + +
+
+
+ ) +} diff --git a/nextjs/app/home/signUp/page.tsx b/nextjs/app/home/signUp/page.tsx new file mode 100644 index 0000000..d45f9e5 --- /dev/null +++ b/nextjs/app/home/signUp/page.tsx @@ -0,0 +1,167 @@ +"use client" + +import { useState } from "react" +import { useRouter } from "next/navigation" +import { Button } from "@/shared/ui/button" +import { Logo } from "@/widgets/landing" +import Link from "next/link" +import { useAuth } from "@/src/app/providers/auth-provider" + +export default function SignupPage() { + const [name, setName] = useState("") + const [email, setEmail] = useState("") + const [password, setPassword] = useState("") + const [confirmPassword, setConfirmPassword] = useState("") + const [isLoading, setIsLoading] = useState(false) + const [error, setError] = useState("") + const router = useRouter() + const { login } = useAuth() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setIsLoading(true) + setError("") + + if (password !== confirmPassword) { + setError("Passwords do not match") + setIsLoading(false) + return + } + + try { + const response = await fetch("/api/auth/register", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ name, email, password }), + }) + + const data = await response.json() + + if (response.ok) { + // Auto login after successful registration + const loginResponse = await fetch("/api/auth/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, password }), + }) + + const loginData = await loginResponse.json() + + if (loginResponse.ok) { + login(loginData.token, loginData.user) + router.push("/documents") + } else { + router.push("/signIn") + } + } else { + setError(data.error || "Registration failed") + } + } catch (error) { + setError("An error occurred. Please try again.") + } finally { + setIsLoading(false) + } + } + + return ( +
+
+
+ +

Create your account

+

+ Or{" "} + + sign in to your existing account + +

+
+ +
+ {error && ( +
+ {error} +
+ )} + +
+
+ + setName(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Enter your full name" + /> +
+ +
+ + setEmail(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Enter your email" + /> +
+ +
+ + setPassword(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Enter your password" + /> +
+ +
+ + setConfirmPassword(e.target.value)} + className="mt-1 block w-full px-3 py-2 border border-input rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent" + placeholder="Confirm your password" + /> +
+
+ + +
+
+
+ ) +} diff --git a/nextjs/app/layout.tsx b/nextjs/app/layout.tsx new file mode 100644 index 0000000..4c47e11 --- /dev/null +++ b/nextjs/app/layout.tsx @@ -0,0 +1,62 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import "./globals.css"; +import { ThemeProvider } from "@/src/app/providers/theme-provider"; +import { AuthProvider } from "@/src/app/providers/auth-provider"; +import NextTopLoader from 'nextjs-toploader'; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Jotion", + description: "Generated by Jotion", + icons: { + icon: [ + { + media: "(prefers-color-scheme: light)", + url: "/next.svg", + href: "/next.svg", + }, + { + media: "(prefers-color-scheme: dark)", + url: "/next.svg", + href: "/next.svg", + } + ] + } +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + + + {children} + + + + + ); +} \ No newline at end of file diff --git a/nextjs/components.json b/nextjs/components.json new file mode 100644 index 0000000..1e879bc --- /dev/null +++ b/nextjs/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils" + } +} \ No newline at end of file diff --git a/nextjs/middleware.ts b/nextjs/middleware.ts new file mode 100644 index 0000000..670183f --- /dev/null +++ b/nextjs/middleware.ts @@ -0,0 +1,71 @@ +import { NextRequest, NextResponse } from 'next/server' +import { verifyToken } from './src/shared/lib/auth' + +export function middleware(request: NextRequest) { + const { pathname } = request.nextUrl + + // Public paths that don't require authentication + const publicPaths = [ + '/', + '/home', + '/home/signIn', + '/home/signUp', + '/home/share', + '/api/auth/login', + '/api/auth/register', + '/api/health', + '/api/metadata', + ] + + // Check if the current path is public + const isPublicPath = publicPaths.some(path => pathname.startsWith(path)) + + // Allow public paths + if (isPublicPath) { + return NextResponse.next() + } + + // Check for authentication on protected paths + if (pathname.startsWith('/documents')) { + // Get token from cookie + const token = request.cookies.get('auth-token')?.value + + if (!token) { + // Redirect to home page if no token + const url = new URL('/home', request.url) + return NextResponse.redirect(url) + } + + // Verify token + const payload = verifyToken(token) + + if (!payload) { + // Invalid token, clear cookie and redirect + const url = new URL('/home', request.url) + const response = NextResponse.redirect(url) + response.cookies.delete('auth-token') + return response + } + + // Token is valid, continue to the requested page + return NextResponse.next() + } + + // Allow all other paths by default + return NextResponse.next() +} + +// Configure which paths this middleware should run on +export const config = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + * - public folder + */ + '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', + ], +} + diff --git a/nextjs/next.config.mjs b/nextjs/next.config.mjs new file mode 100644 index 0000000..4e7718c --- /dev/null +++ b/nextjs/next.config.mjs @@ -0,0 +1,48 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + // Enable standalone output for Docker + output: 'standalone', + + // Optimize for Docker + outputFileTracingRoot: '/app', + + // Image optimization + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: '**', + }, + ], + }, + + // API configuration + async headers() { + return [ + { + source: '/api/:path*', + headers: [ + { + key: 'Cache-Control', + value: 'no-store, max-age=0', + }, + ], + }, + ]; + }, + + // Webpack configuration for Docker + webpack: (config, { isServer }) => { + if (!isServer) { + config.resolve.fallback = { + ...config.resolve.fallback, + fs: false, + net: false, + tls: false, + }; + } + return config; + }, +}; + +export default nextConfig; \ No newline at end of file diff --git a/nextjs/package-lock.json b/nextjs/package-lock.json new file mode 100644 index 0000000..8b52692 --- /dev/null +++ b/nextjs/package-lock.json @@ -0,0 +1,6346 @@ +{ + "name": "notion-clone", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "notion-clone", + "version": "0.1.0", + "dependencies": { + "@aws-sdk/client-s3": "^3.918.0", + "@aws-sdk/s3-request-presigner": "^3.918.0", + "@monaco-editor/react": "^4.6.0", + "@prisma/client": "^6.16.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-slot": "^1.0.2", + "@supabase/supabase-js": "^2.76.1", + "@tiptap/core": "^3.6.3", + "@tiptap/extension-highlight": "^3.6.3", + "@tiptap/extension-image": "^3.6.3", + "@tiptap/extension-link": "^3.6.3", + "@tiptap/extension-placeholder": "^3.6.3", + "@tiptap/extension-strike": "^3.6.3", + "@tiptap/extension-table": "^3.6.3", + "@tiptap/extension-table-cell": "^3.6.3", + "@tiptap/extension-table-header": "^3.6.3", + "@tiptap/extension-table-row": "^3.6.3", + "@tiptap/extension-task-item": "^3.6.3", + "@tiptap/extension-task-list": "^3.6.3", + "@tiptap/extension-text-align": "^3.6.3", + "@tiptap/extension-underline": "^3.6.3", + "@tiptap/react": "^3.6.3", + "@tiptap/starter-kit": "^3.6.3", + "autoprefixer": "^10.4.21", + "bcryptjs": "^3.0.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "jsonwebtoken": "^9.0.2", + "lucide-react": "^0.544.0", + "monaco-editor": "^0.47.0", + "next": "^15.5.4", + "next-themes": "^0.4.6", + "nextjs-toploader": "^3.9.17", + "node-html-parser": "^7.0.1", + "prisma": "^6.16.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "tailwind-merge": "^2.3.0", + "tailwindcss-animate": "^1.0.7", + "usehooks-ts": "^3.1.0", + "zod": "^4.1.12", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@types/bcryptjs": "^3.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/node": "20.12.11", + "@types/react": "18.3.2", + "@types/react-dom": "^18", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.918.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.918.0.tgz", + "integrity": "sha512-25DhKO0QB4QbhbX1t+txCoRNRvchcq9s3lrDrVJLDwpS7e3cTwSOsicyvMpme6Wk/NSln/lWkYazx8MgUbO6RA==", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.916.0", + "@aws-sdk/credential-provider-node": "3.918.0", + "@aws-sdk/middleware-bucket-endpoint": "3.914.0", + "@aws-sdk/middleware-expect-continue": "3.917.0", + "@aws-sdk/middleware-flexible-checksums": "3.916.0", + "@aws-sdk/middleware-host-header": "3.914.0", + "@aws-sdk/middleware-location-constraint": "3.914.0", + "@aws-sdk/middleware-logger": "3.914.0", + "@aws-sdk/middleware-recursion-detection": "3.914.0", + "@aws-sdk/middleware-sdk-s3": "3.916.0", + "@aws-sdk/middleware-ssec": "3.914.0", + "@aws-sdk/middleware-user-agent": "3.916.0", + "@aws-sdk/region-config-resolver": "3.914.0", + "@aws-sdk/signature-v4-multi-region": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-endpoints": "3.916.0", + "@aws-sdk/util-user-agent-browser": "3.914.0", + "@aws-sdk/util-user-agent-node": "3.916.0", + "@aws-sdk/xml-builder": "3.914.0", + "@smithy/config-resolver": "^4.4.0", + "@smithy/core": "^3.17.1", + "@smithy/eventstream-serde-browser": "^4.2.3", + "@smithy/eventstream-serde-config-resolver": "^4.3.3", + "@smithy/eventstream-serde-node": "^4.2.3", + "@smithy/fetch-http-handler": "^5.3.4", + "@smithy/hash-blob-browser": "^4.2.4", + "@smithy/hash-node": "^4.2.3", + "@smithy/hash-stream-node": "^4.2.3", + "@smithy/invalid-dependency": "^4.2.3", + "@smithy/md5-js": "^4.2.3", + "@smithy/middleware-content-length": "^4.2.3", + "@smithy/middleware-endpoint": "^4.3.5", + "@smithy/middleware-retry": "^4.4.5", + "@smithy/middleware-serde": "^4.2.3", + "@smithy/middleware-stack": "^4.2.3", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/node-http-handler": "^4.4.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.4", + "@smithy/util-defaults-mode-node": "^4.2.6", + "@smithy/util-endpoints": "^3.2.3", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-retry": "^4.2.3", + "@smithy/util-stream": "^4.5.4", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.3", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.916.0.tgz", + "integrity": "sha512-Eu4PtEUL1MyRvboQnoq5YKg0Z9vAni3ccebykJy615xokVZUdA3di2YxHM/hykDQX7lcUC62q9fVIvh0+UNk/w==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.916.0", + "@aws-sdk/middleware-host-header": "3.914.0", + "@aws-sdk/middleware-logger": "3.914.0", + "@aws-sdk/middleware-recursion-detection": "3.914.0", + "@aws-sdk/middleware-user-agent": "3.916.0", + "@aws-sdk/region-config-resolver": "3.914.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-endpoints": "3.916.0", + "@aws-sdk/util-user-agent-browser": "3.914.0", + "@aws-sdk/util-user-agent-node": "3.916.0", + "@smithy/config-resolver": "^4.4.0", + "@smithy/core": "^3.17.1", + "@smithy/fetch-http-handler": "^5.3.4", + "@smithy/hash-node": "^4.2.3", + "@smithy/invalid-dependency": "^4.2.3", + "@smithy/middleware-content-length": "^4.2.3", + "@smithy/middleware-endpoint": "^4.3.5", + "@smithy/middleware-retry": "^4.4.5", + "@smithy/middleware-serde": "^4.2.3", + "@smithy/middleware-stack": "^4.2.3", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/node-http-handler": "^4.4.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.4", + "@smithy/util-defaults-mode-node": "^4.2.6", + "@smithy/util-endpoints": "^3.2.3", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-retry": "^4.2.3", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.916.0.tgz", + "integrity": "sha512-1JHE5s6MD5PKGovmx/F1e01hUbds/1y3X8rD+Gvi/gWVfdg5noO7ZCerpRsWgfzgvCMZC9VicopBqNHCKLykZA==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@aws-sdk/xml-builder": "3.914.0", + "@smithy/core": "^3.17.1", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/signature-v4": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.916.0.tgz", + "integrity": "sha512-3gDeqOXcBRXGHScc6xb7358Lyf64NRG2P08g6Bu5mv1Vbg9PKDyCAZvhKLkG7hkdfAM8Yc6UJNhbFxr1ud/tCQ==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/property-provider": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.916.0.tgz", + "integrity": "sha512-NmooA5Z4/kPFJdsyoJgDxuqXC1C6oPMmreJjbOPqcwo6E/h2jxaG8utlQFgXe5F9FeJsMx668dtxVxSYnAAqHQ==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/fetch-http-handler": "^5.3.4", + "@smithy/node-http-handler": "^4.4.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/util-stream": "^4.5.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.918.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.918.0.tgz", + "integrity": "sha512-oDViX9z4o8jShY0unX9T7MJqyt+/ojhRB2zoLQVr0Mln7GbXwJ0aUtxgb4PFROG27pJpR11oAaZHzI3LI0jm/A==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/credential-provider-env": "3.916.0", + "@aws-sdk/credential-provider-http": "3.916.0", + "@aws-sdk/credential-provider-process": "3.916.0", + "@aws-sdk/credential-provider-sso": "3.916.0", + "@aws-sdk/credential-provider-web-identity": "3.918.0", + "@aws-sdk/nested-clients": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/credential-provider-imds": "^4.2.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.918.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.918.0.tgz", + "integrity": "sha512-gl9ECsPB1i8UBPrAJV0HcTn+sgYuD3jYy8ps6KK4c8LznFizwgpah1jd3eF4qq3kPGzrdAE3MKua9OlCCNWAKQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.916.0", + "@aws-sdk/credential-provider-http": "3.916.0", + "@aws-sdk/credential-provider-ini": "3.918.0", + "@aws-sdk/credential-provider-process": "3.916.0", + "@aws-sdk/credential-provider-sso": "3.916.0", + "@aws-sdk/credential-provider-web-identity": "3.918.0", + "@aws-sdk/types": "3.914.0", + "@smithy/credential-provider-imds": "^4.2.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.916.0.tgz", + "integrity": "sha512-SXDyDvpJ1+WbotZDLJW1lqP6gYGaXfZJrgFSXIuZjHb75fKeNRgPkQX/wZDdUvCwdrscvxmtyJorp2sVYkMcvA==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.916.0.tgz", + "integrity": "sha512-gu9D+c+U/Dp1AKBcVxYHNNoZF9uD4wjAKYCjgSN37j4tDsazwMEylbbZLuRNuxfbXtizbo4/TiaxBXDbWM7AkQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.916.0", + "@aws-sdk/core": "3.916.0", + "@aws-sdk/token-providers": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.918.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.918.0.tgz", + "integrity": "sha512-qQx5qOhSovVF1EEKTc809WsiKzMqEJrlMSOUycDkE+JMgLPIy2pB2LR1crrIeBGgxFUgFsXHvNHbFjRy+AFBdA==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/nested-clients": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.914.0.tgz", + "integrity": "sha512-mHLsVnPPp4iq3gL2oEBamfpeETFV0qzxRHmcnCfEP3hualV8YF8jbXGmwPCPopUPQDpbYDBHYtXaoClZikCWPQ==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-config-provider": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.917.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.917.0.tgz", + "integrity": "sha512-UPBq1ZP2CaxwbncWSbVqkhYXQrmfNiqAtHyBxi413hjRVZ4JhQ1UyH7pz5yqiG8zx2/+Po8cUD4SDUwJgda4nw==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.916.0.tgz", + "integrity": "sha512-CBRRg6slHHBYAm26AWY/pECHK0vVO/peDoNhZiAzUNt4jV6VftotjszEJ904pKGOr7/86CfZxtCnP3CCs3lQjA==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-stream": "^4.5.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.914.0.tgz", + "integrity": "sha512-7r9ToySQ15+iIgXMF/h616PcQStByylVkCshmQqcdeynD/lCn2l667ynckxW4+ql0Q+Bo/URljuhJRxVJzydNA==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.914.0.tgz", + "integrity": "sha512-Mpd0Sm9+GN7TBqGnZg1+dO5QZ/EOYEcDTo7KfvoyrXScMlxvYm9fdrUVMmLdPn/lntweZGV3uNrs+huasGOOTA==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.914.0.tgz", + "integrity": "sha512-/gaW2VENS5vKvJbcE1umV4Ag3NuiVzpsANxtrqISxT3ovyro29o1RezW/Avz/6oJqjnmgz8soe9J1t65jJdiNg==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.914.0.tgz", + "integrity": "sha512-yiAjQKs5S2JKYc+GrkvGMwkUvhepXDigEXpSJqUseR/IrqHhvGNuOxDxq+8LbDhM4ajEW81wkiBbU+Jl9G82yQ==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@aws/lambda-invoke-store": "^0.0.1", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.916.0.tgz", + "integrity": "sha512-pjmzzjkEkpJObzmTthqJPq/P13KoNFuEi/x5PISlzJtHofCNcyXeVAQ90yvY2dQ6UXHf511Rh1/ytiKy2A8M0g==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-arn-parser": "3.893.0", + "@smithy/core": "^3.17.1", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/signature-v4": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-stream": "^4.5.4", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.914.0.tgz", + "integrity": "sha512-V1Oae/oLVbpNb9uWs+v80GKylZCdsbqs2c2Xb1FsAUPtYeSnxFuAWsF3/2AEMSSpFe0dTC5KyWr/eKl2aim9VQ==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.916.0.tgz", + "integrity": "sha512-mzF5AdrpQXc2SOmAoaQeHpDFsK2GE6EGcEACeNuoESluPI2uYMpuuNMYrUufdnIAIyqgKlis0NVxiahA5jG42w==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-endpoints": "3.916.0", + "@smithy/core": "^3.17.1", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.916.0.tgz", + "integrity": "sha512-tgg8e8AnVAer0rcgeWucFJ/uNN67TbTiDHfD+zIOPKep0Z61mrHEoeT/X8WxGIOkEn4W6nMpmS4ii8P42rNtnA==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.916.0", + "@aws-sdk/middleware-host-header": "3.914.0", + "@aws-sdk/middleware-logger": "3.914.0", + "@aws-sdk/middleware-recursion-detection": "3.914.0", + "@aws-sdk/middleware-user-agent": "3.916.0", + "@aws-sdk/region-config-resolver": "3.914.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-endpoints": "3.916.0", + "@aws-sdk/util-user-agent-browser": "3.914.0", + "@aws-sdk/util-user-agent-node": "3.916.0", + "@smithy/config-resolver": "^4.4.0", + "@smithy/core": "^3.17.1", + "@smithy/fetch-http-handler": "^5.3.4", + "@smithy/hash-node": "^4.2.3", + "@smithy/invalid-dependency": "^4.2.3", + "@smithy/middleware-content-length": "^4.2.3", + "@smithy/middleware-endpoint": "^4.3.5", + "@smithy/middleware-retry": "^4.4.5", + "@smithy/middleware-serde": "^4.2.3", + "@smithy/middleware-stack": "^4.2.3", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/node-http-handler": "^4.4.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.4", + "@smithy/util-defaults-mode-node": "^4.2.6", + "@smithy/util-endpoints": "^3.2.3", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-retry": "^4.2.3", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.914.0.tgz", + "integrity": "sha512-KlmHhRbn1qdwXUdsdrJ7S/MAkkC1jLpQ11n+XvxUUUCGAJd1gjC7AjxPZUM7ieQ2zcb8bfEzIU7al+Q3ZT0u7Q==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/config-resolver": "^4.4.0", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.918.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.918.0.tgz", + "integrity": "sha512-s7aBuDNjVr7EcSEHcCkpWCow90BMUlj9LgPXRmO7oAZVnb/7cMl+x9ucAn3lWRttIXqBCIIPK49EaIyZNfjWDg==", + "dependencies": { + "@aws-sdk/signature-v4-multi-region": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@aws-sdk/util-format-url": "3.914.0", + "@smithy/middleware-endpoint": "^4.3.5", + "@smithy/protocol-http": "^5.3.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.916.0.tgz", + "integrity": "sha512-fuzUMo6xU7e0NBzBA6TQ4FUf1gqNbg4woBSvYfxRRsIfKmSMn9/elXXn4sAE5UKvlwVQmYnb6p7dpVRPyFvnQA==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/protocol-http": "^5.3.3", + "@smithy/signature-v4": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.916.0.tgz", + "integrity": "sha512-13GGOEgq5etbXulFCmYqhWtpcEQ6WI6U53dvXbheW0guut8fDFJZmEv7tKMTJgiybxh7JHd0rWcL9JQND8DwoQ==", + "dependencies": { + "@aws-sdk/core": "3.916.0", + "@aws-sdk/nested-clients": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.914.0.tgz", + "integrity": "sha512-kQWPsRDmom4yvAfyG6L1lMmlwnTzm1XwMHOU+G5IFlsP4YEaMtXidDzW/wiivY0QFrhfCz/4TVmu0a2aPU57ug==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.893.0.tgz", + "integrity": "sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.916.0.tgz", + "integrity": "sha512-bAgUQwvixdsiGNcuZSDAOWbyHlnPtg8G8TyHD6DTfTmKTHUW6tAn+af/ZYJPXEzXhhpwgJqi58vWnsiDhmr7NQ==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "@smithy/util-endpoints": "^3.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.914.0.tgz", + "integrity": "sha512-QpdkoQjvPaYyzZwgk41vFyHQM5s0DsrsbQ8IoPUggQt4HaJUvmL1ShwMcSldbgdzwiRMqXUK8q7jrqUvkYkY6w==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/querystring-builder": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.914.0.tgz", + "integrity": "sha512-rMQUrM1ECH4kmIwlGl9UB0BtbHy6ZuKdWFrIknu8yGTRI/saAucqNTh5EI1vWBxZ0ElhK5+g7zOnUuhSmVQYUA==", + "dependencies": { + "@aws-sdk/types": "3.914.0", + "@smithy/types": "^4.8.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.916.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.916.0.tgz", + "integrity": "sha512-CwfWV2ch6UdjuSV75ZU99N03seEUb31FIUrXBnwa6oONqj/xqXwrxtlUMLx6WH3OJEE4zI3zt5PjlTdGcVwf4g==", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.916.0", + "@aws-sdk/types": "3.914.0", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.914.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.914.0.tgz", + "integrity": "sha512-k75evsBD5TcIjedycYS7QXQ98AmOtbnxRJOPtCo0IwYRmy7UvqgS/gBL5SmrIqeV6FDSYRQMgdBxSMp6MLmdew==", + "dependencies": { + "@smithy/types": "^4.8.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.0.1.tgz", + "integrity": "sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==" + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz", + "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==", + "dependencies": { + "state-local": "^1.0.6" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz", + "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==", + "dependencies": { + "@monaco-editor/loader": "^1.5.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz", + "integrity": "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.4.tgz", + "integrity": "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.4.tgz", + "integrity": "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.4.tgz", + "integrity": "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.4.tgz", + "integrity": "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.4.tgz", + "integrity": "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.4.tgz", + "integrity": "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.4.tgz", + "integrity": "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.4.tgz", + "integrity": "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/client": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.3.tgz", + "integrity": "sha512-JfNfAtXG+/lIopsvoZlZiH2k5yNx87mcTS4t9/S5oufM1nKdXYxOvpDC1XoTCFBa5cQh7uXnbMPsmZrwZY80xw==", + "hasInstallScript": true, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.3.tgz", + "integrity": "sha512-VlsLnG4oOuKGGMToEeVaRhoTBZu5H3q51jTQXb/diRags3WV0+BQK5MolJTtP6G7COlzoXmWeS11rNBtvg+qFQ==", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.16.12", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.3.tgz", + "integrity": "sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA==" + }, + "node_modules/@prisma/engines": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.3.tgz", + "integrity": "sha512-b+Rl4nzQDcoqe6RIpSHv8f5lLnwdDGvXhHjGDiokObguAAv/O1KaX1Oc69mBW/GFWKQpCkOraobLjU6s1h8HGg==", + "hasInstallScript": true, + "dependencies": { + "@prisma/debug": "6.16.3", + "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "@prisma/fetch-engine": "6.16.3", + "@prisma/get-platform": "6.16.3" + } + }, + "node_modules/@prisma/engines-version": { + "version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a.tgz", + "integrity": "sha512-fftRmosBex48Ph1v2ll1FrPpirwtPZpNkE5CDCY1Lw2SD2ctyrLlVlHiuxDAAlALwWBOkPbAll4+EaqdGuMhJw==" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.3.tgz", + "integrity": "sha512-bUoRIkVaI+CCaVGrSfcKev0/Mk4ateubqWqGZvQ9uCqFv2ENwWIR3OeNuGin96nZn5+SkebcD7RGgKr/+mJelw==", + "dependencies": { + "@prisma/debug": "6.16.3", + "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", + "@prisma/get-platform": "6.16.3" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.3.tgz", + "integrity": "sha512-X1LxiFXinJ4iQehrodGp0f66Dv6cDL0GbRlcCoLtSu6f4Wi+hgo7eND/afIs5029GQLgNWKZ46vn8hjyXTsHLA==", + "dependencies": { + "@prisma/debug": "6.16.3" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==" + }, + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==" + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.3.tgz", + "integrity": "sha512-xWL9Mf8b7tIFuAlpjKtRPnHrR8XVrwTj5NPYO/QwZPtc0SDLsPxb56V5tzi5yspSMytISHybifez+4jlrx0vkQ==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz", + "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz", + "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==", + "dependencies": { + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.0.tgz", + "integrity": "sha512-Kkmz3Mup2PGp/HNJxhCWkLNdlajJORLSjwkcfrj0E7nu6STAEdcMR1ir5P9/xOmncx8xXfru0fbUYLlZog/cFg==", + "dependencies": { + "@smithy/node-config-provider": "^4.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.3", + "@smithy/util-middleware": "^4.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.17.1.tgz", + "integrity": "sha512-V4Qc2CIb5McABYfaGiIYLTmo/vwNIK7WXI5aGveBd9UcdhbOMwcvIMxIw/DJj1S9QgOMa/7FBkarMdIC0EOTEQ==", + "dependencies": { + "@smithy/middleware-serde": "^4.2.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-stream": "^4.5.4", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.3.tgz", + "integrity": "sha512-hA1MQ/WAHly4SYltJKitEsIDVsNmXcQfYBRv2e+q04fnqtAX5qXaybxy/fhUeAMCnQIdAjaGDb04fMHQefWRhw==", + "dependencies": { + "@smithy/node-config-provider": "^4.3.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.3.tgz", + "integrity": "sha512-rcr0VH0uNoMrtgKuY7sMfyKqbHc4GQaQ6Yp4vwgm+Z6psPuOgL+i/Eo/QWdXRmMinL3EgFM0Z1vkfyPyfzLmjw==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.8.0", + "@smithy/util-hex-encoding": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.3.tgz", + "integrity": "sha512-EcS0kydOr2qJ3vV45y7nWnTlrPmVIMbUFOZbMG80+e2+xePQISX9DrcbRpVRFTS5Nqz3FiEbDcTCAV0or7bqdw==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.3.tgz", + "integrity": "sha512-GewKGZ6lIJ9APjHFqR2cUW+Efp98xLu1KmN0jOWxQ1TN/gx3HTUPVbLciFD8CfScBj2IiKifqh9vYFRRXrYqXA==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.3.tgz", + "integrity": "sha512-uQobOTQq2FapuSOlmGLUeGTpvcBLE5Fc7XjERUSk4dxEi4AhTwuyHYZNAvL4EMUp7lzxxkKDFaJ1GY0ovrj0Kg==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.3.tgz", + "integrity": "sha512-QIvH/CKOk1BZPz/iwfgbh1SQD5Y0lpaw2kLA8zpLRRtYMPXeYUEWh+moTaJyqDaKlbrB174kB7FSRFiZ735tWw==", + "dependencies": { + "@smithy/eventstream-codec": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.4.tgz", + "integrity": "sha512-bwigPylvivpRLCm+YK9I5wRIYjFESSVwl8JQ1vVx/XhCw0PtCi558NwTnT2DaVCl5pYlImGuQTSwMsZ+pIavRw==", + "dependencies": { + "@smithy/protocol-http": "^5.3.3", + "@smithy/querystring-builder": "^4.2.3", + "@smithy/types": "^4.8.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.4.tgz", + "integrity": "sha512-W7eIxD+rTNsLB/2ynjmbdeP7TgxRXprfvqQxKFEfy9HW2HeD7t+g+KCIrY0pIn/GFjA6/fIpH+JQnfg5TTk76Q==", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.2.0", + "@smithy/chunked-blob-reader-native": "^4.2.1", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.3.tgz", + "integrity": "sha512-6+NOdZDbfuU6s1ISp3UOk5Rg953RJ2aBLNLLBEcamLjHAg1Po9Ha7QIB5ZWhdRUVuOUrT8BVFR+O2KIPmw027g==", + "dependencies": { + "@smithy/types": "^4.8.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.3.tgz", + "integrity": "sha512-EXMSa2yiStVII3x/+BIynyOAZlS7dGvI7RFrzXa/XssBgck/7TXJIvnjnCu328GY/VwHDC4VeDyP1S4rqwpYag==", + "dependencies": { + "@smithy/types": "^4.8.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.3.tgz", + "integrity": "sha512-Cc9W5DwDuebXEDMpOpl4iERo8I0KFjTnomK2RMdhhR87GwrSmUmwMxS4P5JdRf+LsjOdIqumcerwRgYMr/tZ9Q==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.3.tgz", + "integrity": "sha512-5+4bUEJQi/NRgzdA5SVXvAwyvEnD0ZAiKzV3yLO6dN5BG8ScKBweZ8mxXXUtdxq+Dx5k6EshKk0XJ7vgvIPSnA==", + "dependencies": { + "@smithy/types": "^4.8.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.3.tgz", + "integrity": "sha512-/atXLsT88GwKtfp5Jr0Ks1CSa4+lB+IgRnkNrrYP0h1wL4swHNb0YONEvTceNKNdZGJsye+W2HH8W7olbcPUeA==", + "dependencies": { + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.5.tgz", + "integrity": "sha512-SIzKVTvEudFWJbxAaq7f2GvP3jh2FHDpIFI6/VAf4FOWGFZy0vnYMPSRj8PGYI8Hjt29mvmwSRgKuO3bK4ixDw==", + "dependencies": { + "@smithy/core": "^3.17.1", + "@smithy/middleware-serde": "^4.2.3", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "@smithy/url-parser": "^4.2.3", + "@smithy/util-middleware": "^4.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.5.tgz", + "integrity": "sha512-DCaXbQqcZ4tONMvvdz+zccDE21sLcbwWoNqzPLFlZaxt1lDtOE2tlVpRSwcTOJrjJSUThdgEYn7HrX5oLGlK9A==", + "dependencies": { + "@smithy/node-config-provider": "^4.3.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/service-error-classification": "^4.2.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-retry": "^4.2.3", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.3.tgz", + "integrity": "sha512-8g4NuUINpYccxiCXM5s1/V+uLtts8NcX4+sPEbvYQDZk4XoJfDpq5y2FQxfmUL89syoldpzNzA0R9nhzdtdKnQ==", + "dependencies": { + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.3.tgz", + "integrity": "sha512-iGuOJkH71faPNgOj/gWuEGS6xvQashpLwWB1HjHq1lNNiVfbiJLpZVbhddPuDbx9l4Cgl0vPLq5ltRfSaHfspA==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.3.tgz", + "integrity": "sha512-NzI1eBpBSViOav8NVy1fqOlSfkLgkUjUTlohUSgAEhHaFWA3XJiLditvavIP7OpvTjDp5u2LhtlBhkBlEisMwA==", + "dependencies": { + "@smithy/property-provider": "^4.2.3", + "@smithy/shared-ini-file-loader": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.3.tgz", + "integrity": "sha512-MAwltrDB0lZB/H6/2M5PIsISSwdI5yIh6DaBB9r0Flo9nx3y0dzl/qTMJPd7tJvPdsx6Ks/cwVzheGNYzXyNbQ==", + "dependencies": { + "@smithy/abort-controller": "^4.2.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/querystring-builder": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.3.tgz", + "integrity": "sha512-+1EZ+Y+njiefCohjlhyOcy1UNYjT+1PwGFHCxA/gYctjg3DQWAU19WigOXAco/Ql8hZokNehpzLd0/+3uCreqQ==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.3.tgz", + "integrity": "sha512-Mn7f/1aN2/jecywDcRDvWWWJF4uwg/A0XjFMJtj72DsgHTByfjRltSqcT9NyE9RTdBSN6X1RSXrhn/YWQl8xlw==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.3.tgz", + "integrity": "sha512-LOVCGCmwMahYUM/P0YnU/AlDQFjcu+gWbFJooC417QRB/lDJlWSn8qmPSDp+s4YVAHOgtgbNG4sR+SxF/VOcJQ==", + "dependencies": { + "@smithy/types": "^4.8.0", + "@smithy/util-uri-escape": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.3.tgz", + "integrity": "sha512-cYlSNHcTAX/wc1rpblli3aUlLMGgKZ/Oqn8hhjFASXMCXjIqeuQBei0cnq2JR8t4RtU9FpG6uyl6PxyArTiwKA==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.3.tgz", + "integrity": "sha512-NkxsAxFWwsPsQiwFG2MzJ/T7uIR6AQNh1SzcxSUnmmIqIQMlLRQDKhc17M7IYjiuBXhrQRjQTo3CxX+DobS93g==", + "dependencies": { + "@smithy/types": "^4.8.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.3.3.tgz", + "integrity": "sha512-9f9Ixej0hFhroOK2TxZfUUDR13WVa8tQzhSzPDgXe5jGL3KmaM9s8XN7RQwqtEypI82q9KHnKS71CJ+q/1xLtQ==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.3.tgz", + "integrity": "sha512-CmSlUy+eEYbIEYN5N3vvQTRfqt0lJlQkaQUIf+oizu7BbDut0pozfDjBGecfcfWf7c62Yis4JIEgqQ/TCfodaA==", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.3", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.1.tgz", + "integrity": "sha512-Ngb95ryR5A9xqvQFT5mAmYkCwbXvoLavLFwmi7zVg/IowFPCfiqRfkOKnbc/ZRL8ZKJ4f+Tp6kSu6wjDQb8L/g==", + "dependencies": { + "@smithy/core": "^3.17.1", + "@smithy/middleware-endpoint": "^4.3.5", + "@smithy/middleware-stack": "^4.2.3", + "@smithy/protocol-http": "^5.3.3", + "@smithy/types": "^4.8.0", + "@smithy/util-stream": "^4.5.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.8.0.tgz", + "integrity": "sha512-QpELEHLO8SsQVtqP+MkEgCYTFW0pleGozfs3cZ183ZBj9z3VC1CX1/wtFMK64p+5bhtZo41SeLK1rBRtd25nHQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.3.tgz", + "integrity": "sha512-I066AigYvY3d9VlU3zG9XzZg1yT10aNqvCaBTw9EPgu5GrsEl1aUkcMvhkIXascYH1A8W0LQo3B1Kr1cJNcQEw==", + "dependencies": { + "@smithy/querystring-parser": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.4.tgz", + "integrity": "sha512-qI5PJSW52rnutos8Bln8nwQZRpyoSRN6k2ajyoUHNMUzmWqHnOJCnDELJuV6m5PML0VkHI+XcXzdB+6awiqYUw==", + "dependencies": { + "@smithy/property-provider": "^4.2.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.6.tgz", + "integrity": "sha512-c6M/ceBTm31YdcFpgfgQAJaw3KbaLuRKnAz91iMWFLSrgxRpYm03c3bu5cpYojNMfkV9arCUelelKA7XQT36SQ==", + "dependencies": { + "@smithy/config-resolver": "^4.4.0", + "@smithy/credential-provider-imds": "^4.2.3", + "@smithy/node-config-provider": "^4.3.3", + "@smithy/property-provider": "^4.2.3", + "@smithy/smithy-client": "^4.9.1", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.3.tgz", + "integrity": "sha512-aCfxUOVv0CzBIkU10TubdgKSx5uRvzH064kaiPEWfNIvKOtNpu642P4FP1hgOFkjQIkDObrfIDnKMKkeyrejvQ==", + "dependencies": { + "@smithy/node-config-provider": "^4.3.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.3.tgz", + "integrity": "sha512-v5ObKlSe8PWUHCqEiX2fy1gNv6goiw6E5I/PN2aXg3Fb/hse0xeaAnSpXDiWl7x6LamVKq7senB+m5LOYHUAHw==", + "dependencies": { + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.3.tgz", + "integrity": "sha512-lLPWnakjC0q9z+OtiXk+9RPQiYPNAovt2IXD3CP4LkOnd9NpUsxOjMx1SnoUVB7Orb7fZp67cQMtTBKMFDvOGg==", + "dependencies": { + "@smithy/service-error-classification": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.4.tgz", + "integrity": "sha512-+qDxSkiErejw1BAIXUFBSfM5xh3arbz1MmxlbMCKanDDZtVEQ7PSKW9FQS0Vud1eI/kYn0oCTVKyNzRlq+9MUw==", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.4", + "@smithy/node-http-handler": "^4.4.3", + "@smithy/types": "^4.8.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.3.tgz", + "integrity": "sha512-5+nU///E5sAdD7t3hs4uwvCTWQtTR8JwKwOCSJtBRx0bY1isDo1QwH87vRK86vlFLBTISqoDA2V6xvP6nF1isQ==", + "dependencies": { + "@smithy/abort-controller": "^4.2.3", + "@smithy/types": "^4.8.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==" + }, + "node_modules/@supabase/auth-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.76.1.tgz", + "integrity": "sha512-bxmcgPuyjTUBg7+jAohJ15TDh3ph4hXcv7QkRsQgnIpszurD5LYaJPzX638ETQ8zDL4fvHZRHfGrcmHV8C91jA==", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.76.1.tgz", + "integrity": "sha512-+zJym/GC1sofm5QYKGxHSszCpMW4Ao2dj/WC3YlffAGuIlIhUtWTJvKsv5q7sWaSKUKdDhGpWhZ2OD++fW5BtQ==", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.76.1.tgz", + "integrity": "sha512-QJ1Cwim6L9gzWKP8U4Lgw9x/4lMWkZSVMDRYFCH+vVGitVbtfU885swTiioOjjUe4EYGZm+Xktg90twzSVv6IA==", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.76.1.tgz", + "integrity": "sha512-B5Lfmprea2fx2FS7obp4uAWiRUlEa6j9J3+BvvETGp/2LdkSRBaLEJCBylfcZTXk67ajNPX6ppvKvAZsckqXYg==", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.76.1.tgz", + "integrity": "sha512-OJiNT8tocI9tcTjTjv1SBVLabzgEnS1NorZuqivkiJ0gTYmeg2c2PFmqCARhoQ4whF6zR9MVsX/Mtj2oSv4i/w==", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.76.1", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.76.1.tgz", + "integrity": "sha512-dYMh9EsTVXZ6WbQ0QmMGIhbXct5+x636tXXaaxUmwjj3kY1jyBTQU8QehxAIfjyRu1mWGV07hoYmTYakkxdSGQ==", + "dependencies": { + "@supabase/auth-js": "2.76.1", + "@supabase/functions-js": "2.76.1", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "2.76.1", + "@supabase/realtime-js": "2.76.1", + "@supabase/storage-js": "2.76.1" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tiptap/core": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.6.5.tgz", + "integrity": "sha512-CgXuhevQbBcPfxaXzGZgIY9+aVMSAd68Q21g3EONz1iZBw026QgiaLhGK6jgGTErZL4GoNL/P+gC5nFCvN7+cA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^3.6.5" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.6.3.tgz", + "integrity": "sha512-jnRCBLmGw8DFKYeG+vLO9C3YD90UzJoloP/xWcNcuJXohOXTs5+UzkRfbWM9jvvDCs+HNT+qz3NtirdoWt8ilA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.6.3.tgz", + "integrity": "sha512-En57aNnhb6N6enoq2JhrTyDr1FfU/ZaKuJk5Vbw1S/eXjvSDKZz6puWA2LAFKpk6KnfVpoy1nv+hVt97y0s3Xw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.6.3.tgz", + "integrity": "sha512-xariDZbj/bjZbTWkB1isxIufA8pN+CTwiCZAiU8V3ViQZ/baNBcQ2lQckXIbFpb1UoaKnKd8XBkh8SkcXXE8Tw==", + "optional": true, + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.6.3.tgz", + "integrity": "sha512-SwTF/D5TYI0etjc0yt8eiSjMJ1fnu9w37Vis9ZwS+7VHIUIquSMon51YrXVLPA2+aBdTIMabevqtwyr3hh3CAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.6.3.tgz", + "integrity": "sha512-sbTCVW58gJY+1Z9685rCi3luFRmv6qqm1EGc5XWj3UlkLAatfpeq4+PKgY09f7w35hRU60RAWt0VIyysU/b8ZQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.6.3.tgz", + "integrity": "sha512-RKI64JiOmy/guUXLe5rh2jD4dPG5678Fixkn+gDklMzRPFCwa7lvhRpTIJIzqqaR3ApGSqOforWQZcsiC5vrwg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.6.3.tgz", + "integrity": "sha512-2GDXazz5NtFkmZ4z3h9vpQ2ngu/cVpmveqd6GFO4m8Zh40GOc3DvrZzAdHSHMJCf6ZB6ZIwOwretKJo4d9sLiA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.6.3.tgz", + "integrity": "sha512-3qlybvL9kSN4VUoxcmXJu5USoP/5P5OBqhAzPuE3UVFL9PZH/Zj6oY6ugXhUzLSpqPsd7117krLiXWuSWvR3fQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.6.3.tgz", + "integrity": "sha512-mE4MSkSOuFrvvKrI5CZFNRviJ8j1WfTJzXlXF8P8lqKtDAXveL2E2CuhSXAOoFuhgl1bHrLuZY46kveLZ4h8bg==", + "optional": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.6.3.tgz", + "integrity": "sha512-fwg/a4cC7pKrjBkqxwCoBj2qUzcN7/mS5eqDF44YJrVMqILu6OqaBoRkA+7qK+iojTx9LOe3ngIVn1dBUAgBOQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.6.3.tgz", + "integrity": "sha512-LlN35hr2/od0tbL3cqyCuO7ZhzRBXnlUrV/Exg8DYvGfrmeCzFlduTYyCAyJwxD7fprX6R7irWf0t0qTITVtQQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.6.3.tgz", + "integrity": "sha512-yJgc3Ohu1k8xbaYez7gYBJ/9rWDdBe3kKQkOlzd+b9ZQL6cBpaWIMS7Two5qKmLmtCCaNYPnALvVGnrEmwvQaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-highlight": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-3.6.3.tgz", + "integrity": "sha512-XTBqCN7vOjUDXBXQGvMHGbTDJoXHaD4v+2p/5ROKi6OzhJ4liuKfYqooir6SzNVwz7PgvzX2tsWzX2VAfLRj0g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.6.3.tgz", + "integrity": "sha512-7Ahasayoy73qpiKG85bdOiOUb5+FVe/zg2JOqwVyDVuRiW36xXPryD7k3WOIpyTBRPzdQ+rwDqwCBfHNeEwj/w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-image": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-3.6.3.tgz", + "integrity": "sha512-4CxAntkSLQQxVMcgPauGfnyrA7gzOBAAY6hHF49qAPPKNt4qpEbXny1SeUMm3bW/f592UiJ/XO45Fiv3lBd7EQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.6.3.tgz", + "integrity": "sha512-lq6yMG0rLQsVvfLrWL4Fb9dxmsGluehwduzbSPJjT1OZ+TGy/oPEhqteqsVej0sIP3V9byq55hfpuzrUi7NTSg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-link": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.6.3.tgz", + "integrity": "sha512-Lhv0HgoxCq6Y6ADS0273SAW79AyEs71CvLdZ8sf9ibinBHRBlBAHozUP8shYYXSurhPRMNJw0VmQqJZse/QZww==", + "dependencies": { + "linkifyjs": "^4.3.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-list": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.6.3.tgz", + "integrity": "sha512-IkcvIJSXSJGaOrH+SPVfpYB4bDQ9bxTkJwyLvnAXmNao4CfXRAQznOjuxVYm/FOjdnOFLTB9gdFGbKj1qeglpA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.6.3.tgz", + "integrity": "sha512-EL2xQfVwRbiz1lDZt63HAAkAFnzD1kyqIYS4hanfjtq7jg4b1sSplNq53Zy8fPMLtZOat9JQl/PNhfqRurQ5gw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-list-keymap": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.6.3.tgz", + "integrity": "sha512-bstO5HACdGR/6gVKkbFa+bn5e9sr0zOfbeYYePhKq2REX/hrJ/tpF+BaXgpEn8xtCCXOw0Zo3AwIIV9+LGlmcA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.6.3.tgz", + "integrity": "sha512-2WShxmzmqZVxWdACbTyqupDWLFCM7WI3dPisI1LVjjPeoKNqwdeAUqZSv5lXGA4HmxdOMbMI+qJ3j7zgQPx37g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.6.3.tgz", + "integrity": "sha512-E5HHEQFyEPVbZ5vyXo0CwxeNOBPyB+dEGUK5C8W5JFlWnO14kTtzuuHXkzOaCORoyQgUf/Z5SPLQEAIjLW2n6Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.6.3.tgz", + "integrity": "sha512-a2aaPIAhiiACT0I4MdAkhZEBxAlkHAh9JQlYiivUlVh0MyB2a4LRlq32/zGthJKScJAi+TdYhEWCPkGzKA0slg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.6.3.tgz", + "integrity": "sha512-+qA+fcO0Cyxjjw6/WkMysY1eFXpA7MMUxH7em6j7zmQUxy4HL1cb2YL4YpFPxJTKhTfbvJ6Muag4mJ8zxDFe5w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-table": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.6.3.tgz", + "integrity": "sha512-F5BtRIqGp2EZk1L9lqVNH/jKXWxaTHHesQow2KEKacR0SO2IcgQvZHYlac9CS6r94S8GiSkFLKlt3cdI0dnLeA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-table-cell": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-3.6.3.tgz", + "integrity": "sha512-FKdTNTu6Wi8kGNQdWaUa7zBT9niBEkwT5GHi3K/6DFB1ur3C9QxFfUr6xDPyRMGJd7QvDZ7eQ3KfVk4nvxJ05g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-table-header": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-3.6.3.tgz", + "integrity": "sha512-JU4P24Dp1di8WLtqzatnTFeRa20YcN/ulKEhUHrg7Zxszrm5y1GIv/zW6bPWLxsnWSEeN2jYE+/k8GEv8zTGAw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-table-row": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-3.6.3.tgz", + "integrity": "sha512-BC8Q4dcGbr6y2JjATzE+vH4sJcx8BRh3hJhyg+aE0SIAgbhvde2NqVgtiynnITZxMWG0XH1wkXcSVzXaM1H/Jg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-task-item": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-3.6.3.tgz", + "integrity": "sha512-uS6SqVZSPcOZqQ2S5hlr3lu0ObXqbMFyuzFVpuwblJcspaFPwYdiHSkqFBxNZxm2WWOA39tXvrfrlLlgV52o2A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-task-list": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-3.6.3.tgz", + "integrity": "sha512-TK7UT/Nm971e7oZhyCeAcJAbNw84IzlgqZOP7CXTCRSZbFR3w0EQVwzeF+XUvFD+49bRNlU9sXZVQPkMiIVa4A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.6.3.tgz", + "integrity": "sha512-HetVEdKcWD6ZewBf/tECtPe7hDFwBLaeGgT/ptFuxL8LhQhkmJxo7Re3YXFJ25zAOnRQkFFoG2pbL5yihKw4PA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-text-align": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.6.3.tgz", + "integrity": "sha512-7qXSxpf0o+fQcmBHdYZbevF8SFYw/YU0EjQqDgr67jzb/LBnB3EKhvQ1qEC3c6GbZI1/W7a1Of+wSjHVJiXqkQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.6.3.tgz", + "integrity": "sha512-2gU/uoK6ZVAPyRNky9e1plARuEHNAO+GesmawAAG7O8MCK7D4iVEmutQ/5nAw3/pRZg5H21bdcqgq1vjTJaFRA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3" + } + }, + "node_modules/@tiptap/extensions": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.6.3.tgz", + "integrity": "sha512-a38bFJ+g0BPoDXNwXIIK4oAM2pw34+AlIvrK9P9BFDammJXTskKPSwtN3sIWXEZpI1f/hoE4+1v64dGWAqrWvA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3" + } + }, + "node_modules/@tiptap/pm": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.6.5.tgz", + "integrity": "sha512-S+j6MPgUXRIQd5/mdaLjaJnOt4ptFwjqGjGMUfBbf9a3uKpXUXaCCzfuC6ZikwaUtoVh4KN9BU3HCYDtgtENPA==", + "dependencies": { + "prosemirror-changeset": "^2.3.0", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.24.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.4", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.38.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.6.3.tgz", + "integrity": "sha512-y9laShSXRoHIjf6UlWIEbGYk9knET3Zr+COjMOj9enAadXHDU8d18LaALMhRadJUVYpxs7sjsmrdIdME3T7WvA==", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "fast-deep-equal": "^3.1.3", + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "optionalDependencies": { + "@tiptap/extension-bubble-menu": "^3.6.3", + "@tiptap/extension-floating-menu": "^3.6.3" + }, + "peerDependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/pm": "^3.6.3", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.6.3.tgz", + "integrity": "sha512-GHQNUyBlhYjWzBLsyrnlQppeAnRCD9k45i4l93g2Re+WdqYrgfSPdbV5Ixhl+fDXVqs/s7sPqADFPbzKEwfkzA==", + "dependencies": { + "@tiptap/core": "^3.6.3", + "@tiptap/extension-blockquote": "^3.6.3", + "@tiptap/extension-bold": "^3.6.3", + "@tiptap/extension-bullet-list": "^3.6.3", + "@tiptap/extension-code": "^3.6.3", + "@tiptap/extension-code-block": "^3.6.3", + "@tiptap/extension-document": "^3.6.3", + "@tiptap/extension-dropcursor": "^3.6.3", + "@tiptap/extension-gapcursor": "^3.6.3", + "@tiptap/extension-hard-break": "^3.6.3", + "@tiptap/extension-heading": "^3.6.3", + "@tiptap/extension-horizontal-rule": "^3.6.3", + "@tiptap/extension-italic": "^3.6.3", + "@tiptap/extension-link": "^3.6.3", + "@tiptap/extension-list": "^3.6.3", + "@tiptap/extension-list-item": "^3.6.3", + "@tiptap/extension-list-keymap": "^3.6.3", + "@tiptap/extension-ordered-list": "^3.6.3", + "@tiptap/extension-paragraph": "^3.6.3", + "@tiptap/extension-strike": "^3.6.3", + "@tiptap/extension-text": "^3.6.3", + "@tiptap/extension-underline": "^3.6.3", + "@tiptap/extensions": "^3.6.3", + "@tiptap/pm": "^3.6.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@types/bcryptjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-3.0.0.tgz", + "integrity": "sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg==", + "deprecated": "This is a stub types definition. bcryptjs provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "bcryptjs": "*" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.12.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", + "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==" + }, + "node_modules/@types/react": { + "version": "18.3.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", + "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.12.tgz", + "integrity": "sha512-vAPMQdnyKCBtkmQA6FMCBvU9qFIppS3nzyXnEM+Lo2IAhG4Mpjv9cCxMudhgV3YdNNJv6TNqXy97dfRVL2LmaQ==", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bcryptjs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", + "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/c12/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001746", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001746.tgz", + "integrity": "sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/effect": { + "version": "3.16.12", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", + "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.230", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.230.tgz", + "integrity": "sha512-A6A6Fd3+gMdaed9wX83CvHYJb4UuapPD5X5SLq72VZJzxHSY0/LUweGXRWmQlh2ln7KV7iw7jnwXK7dlPoOnHQ==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/linkifyjs": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", + "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/lucide-react": { + "version": "0.544.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz", + "integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/monaco-editor": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.47.0.tgz", + "integrity": "sha512-VabVvHvQ9QmMwXu4du008ZDuyLnHs9j7ThVFsiJoXSOQk18+LF89N4ADzPbFenm0W4V2bGHnFBztIRQTgBfxzw==" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "15.5.4", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz", + "integrity": "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==", + "dependencies": { + "@next/env": "15.5.4", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.4", + "@next/swc-darwin-x64": "15.5.4", + "@next/swc-linux-arm64-gnu": "15.5.4", + "@next/swc-linux-arm64-musl": "15.5.4", + "@next/swc-linux-x64-gnu": "15.5.4", + "@next/swc-linux-x64-musl": "15.5.4", + "@next/swc-win32-arm64-msvc": "15.5.4", + "@next/swc-win32-x64-msvc": "15.5.4", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/nextjs-toploader": { + "version": "3.9.17", + "resolved": "https://registry.npmjs.org/nextjs-toploader/-/nextjs-toploader-3.9.17.tgz", + "integrity": "sha512-9OF0KSSLtoSAuNg2LZ3aTl4hR9mBDj5L9s9DZiFCbMlXehyICGjkIz5dVGzuATU2bheJZoBdFgq9w07AKSuQQw==", + "license": "MIT", + "dependencies": { + "nprogress": "^0.2.0", + "prop-types": "^15.8.1" + }, + "funding": { + "url": "https://buymeacoffee.com/thesgj" + }, + "peerDependencies": { + "next": ">= 6.0.0", + "react": ">= 16.0.0", + "react-dom": ">= 16.0.0" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==" + }, + "node_modules/node-html-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-7.0.1.tgz", + "integrity": "sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA==", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==" + }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prisma": { + "version": "6.16.3", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.3.tgz", + "integrity": "sha512-4tJq3KB9WRshH5+QmzOLV54YMkNlKOtLKaSdvraI5kC/axF47HuOw6zDM8xrxJ6s9o2WodY654On4XKkrobQdQ==", + "hasInstallScript": true, + "dependencies": { + "@prisma/config": "6.16.3", + "@prisma/engines": "6.16.3" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prosemirror-changeset": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", + "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", + "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz", + "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", + "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", + "dependencies": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", + "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.3.tgz", + "integrity": "sha512-dY2HdaNXlARknJbrManZ1WyUtos+AP97AmvqdOQtWtrrC5g4mohVX5DTi9rXNFSk09eczLq9GuNTtq3EfMeMGA==", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "dependencies": { + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", + "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.1.tgz", + "integrity": "sha512-DAgDoUYHCcc6tOGpLVPSU1k84kCUWTWnfWX3UDy2Delv4ryH0KqTD6RBI6k4yi9j9I8gl3j8MkPpRD/vWPZbug==", + "dependencies": { + "prosemirror-keymap": "^1.2.2", + "prosemirror-model": "^1.25.0", + "prosemirror-state": "^1.4.3", + "prosemirror-transform": "^1.10.3", + "prosemirror-view": "^1.39.1" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "dependencies": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz", + "integrity": "sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.2.tgz", + "integrity": "sha512-PGS/jETmh+Qjmre/6vcG7SNHAKiGc4vKOJmHMPRmvcUl7ISuVtrtHmH06UDUwaim4NDJfZfVMl7U7JkMMETa6g==", + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-remove-scroll": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.0", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.4", + "@img/sharp-darwin-x64": "0.34.4", + "@img/sharp-libvips-darwin-arm64": "1.2.3", + "@img/sharp-libvips-darwin-x64": "1.2.3", + "@img/sharp-libvips-linux-arm": "1.2.3", + "@img/sharp-libvips-linux-arm64": "1.2.3", + "@img/sharp-libvips-linux-ppc64": "1.2.3", + "@img/sharp-libvips-linux-s390x": "1.2.3", + "@img/sharp-libvips-linux-x64": "1.2.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", + "@img/sharp-linux-arm": "0.34.4", + "@img/sharp-linux-arm64": "0.34.4", + "@img/sharp-linux-ppc64": "0.34.4", + "@img/sharp-linux-s390x": "0.34.4", + "@img/sharp-linux-x64": "0.34.4", + "@img/sharp-linuxmusl-arm64": "0.34.4", + "@img/sharp-linuxmusl-x64": "0.34.4", + "@img/sharp-wasm32": "0.34.4", + "@img/sharp-win32-arm64": "0.34.4", + "@img/sharp-win32-ia32": "0.34.4", + "@img/sharp-win32-x64": "0.34.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ] + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", + "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", + "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/usehooks-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.1.tgz", + "integrity": "sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zustand": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.8.tgz", + "integrity": "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/nextjs/package.json b/nextjs/package.json new file mode 100644 index 0000000..6052bb1 --- /dev/null +++ b/nextjs/package.json @@ -0,0 +1,66 @@ +{ + "name": "notion-clone", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.918.0", + "@aws-sdk/s3-request-presigner": "^3.918.0", + "@monaco-editor/react": "^4.6.0", + "@prisma/client": "^6.16.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-slot": "^1.0.2", + "@supabase/supabase-js": "^2.76.1", + "@tiptap/core": "^3.6.3", + "@tiptap/extension-highlight": "^3.6.3", + "@tiptap/extension-image": "^3.6.3", + "@tiptap/extension-link": "^3.6.3", + "@tiptap/extension-placeholder": "^3.6.3", + "@tiptap/extension-strike": "^3.6.3", + "@tiptap/extension-table": "^3.6.3", + "@tiptap/extension-table-cell": "^3.6.3", + "@tiptap/extension-table-header": "^3.6.3", + "@tiptap/extension-table-row": "^3.6.3", + "@tiptap/extension-task-item": "^3.6.3", + "@tiptap/extension-task-list": "^3.6.3", + "@tiptap/extension-text-align": "^3.6.3", + "@tiptap/extension-underline": "^3.6.3", + "@tiptap/react": "^3.6.3", + "@tiptap/starter-kit": "^3.6.3", + "autoprefixer": "^10.4.21", + "bcryptjs": "^3.0.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "jsonwebtoken": "^9.0.2", + "lucide-react": "^0.544.0", + "monaco-editor": "^0.47.0", + "next": "^15.5.4", + "next-themes": "^0.4.6", + "nextjs-toploader": "^3.9.17", + "node-html-parser": "^7.0.1", + "prisma": "^6.16.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "tailwind-merge": "^2.3.0", + "tailwindcss-animate": "^1.0.7", + "usehooks-ts": "^3.1.0", + "zod": "^4.1.12", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@types/bcryptjs": "^3.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/node": "20.12.11", + "@types/react": "18.3.2", + "@types/react-dom": "^18", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } +} diff --git a/nextjs/postcss.config.mjs b/nextjs/postcss.config.mjs new file mode 100644 index 0000000..2ef30fc --- /dev/null +++ b/nextjs/postcss.config.mjs @@ -0,0 +1,9 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/nextjs/prisma/schema.prisma b/nextjs/prisma/schema.prisma new file mode 100644 index 0000000..eadc55f --- /dev/null +++ b/nextjs/prisma/schema.prisma @@ -0,0 +1,131 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" + output = "../node_modules/.prisma/client" +} + +datasource db { + provider = "mysql" + url = env("DATABASE_URL") +} + +// User model for authentication +model User { + id String @id @default(uuid()) + email String @unique + name String? + image String? + password String // Hashed password + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + documents Document[] + folders Folder[] + templates Template[] + + @@map("users") +} + +// Folder model for organizing documents +model Folder { + id String @id @default(uuid()) + name String + icon String? // Folder icon + color String? // Folder color + isArchived Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Hierarchy + parentId String? + parent Folder? @relation("FolderHierarchy", fields: [parentId], references: [id]) + children Folder[] @relation("FolderHierarchy") + + // Ownership + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + // Relations + documents Document[] + + // Indexes + @@index([userId]) + @@index([parentId]) + @@index([isArchived]) + @@map("folders") +} + +// Document model for Notion-like documents +model Document { + id String @id @default(uuid()) + title String + content Json? // JSON content for rich text + icon String? // Document icon + cover String? // Cover image URL + isPublished Boolean @default(false) + isArchived Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Document type + type DocumentType @default(PAGE) // PAGE, CODE_FILE + + // Code file specific fields + filePath String? // Path within the repository + fileContent String? // Raw file content + language String? // Programming language + fileSize Int? // File size in bytes + + // Hierarchy + parentId String? + parent Document? @relation("DocumentHierarchy", fields: [parentId], references: [id]) + children Document[] @relation("DocumentHierarchy") + + // Folder relationship + folderId String? + folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull) + + // Ownership + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + // Indexes + @@index([userId]) + @@index([parentId]) + @@index([folderId]) + @@index([isArchived]) + @@index([type]) + @@map("documents") +} + +// Template model for document templates +model Template { + id String @id @default(uuid()) + name String + description String? + category String @default("General") + title String + content Json // JSON content for rich text + isPublic Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Ownership + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + // Indexes + @@index([userId]) + @@index([category]) + @@index([isPublic]) + @@map("templates") +} + +// Document type enum +enum DocumentType { + PAGE + CODE_FILE +} diff --git a/nextjs/public/documents.png b/nextjs/public/documents.png new file mode 100644 index 0000000000000000000000000000000000000000..024d63d1f94138bd6003b42ad729184c5179a769 GIT binary patch literal 54914 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

jGDVt*N@+1!?Fgsm!g63;{ILdfJpB_Zt{ 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%0DYQiU})x0ceR}O{TmA` zmJ%-U<=}0WJo&tkl5fb*D1j3F0-_BwD7rpm`|nGDHg~lC=ma$qiHRC|L9B#4l|<>o zXgiW$+})Wu>Do1RtFX6`h-YE+&biym$Z+}ve`e72b^_^GW}t3O&kA0BKoolH1IVAo ziJ=@nTz)tu0~Mh0aAWU2Bd`aBrNl@MV8*iQ`*r5!^IV~|QP&Q0TQNqoHN|DzOLOK7 z-E^8oJi`bU3_^Tbb2l2ix!%7p{Ma$2k-LfY(5UnJ)n)}lviOT*$H-#)2g7^@we<DhyNHuk|jtr>xxiLws2K;^KP ze0w?1v+4?^&mpUyc47*9H5E|0EP1>(v5y0 zO}%zm_e1({4pFgj6HC5(E>|fLg7I9Fixo-t53R1d>rm=>)AK9r30toa`aFCZFOlrNS!M3Zh_0LC0>C@)8iV zo?}4%)hkP1wXQ@ohjM3?Od|HDiXZ^fIV(AAlb{@&a2aDV-1hq2gTat7k8pJ1=xu6qvH8|s9=PJRn9Pvotap=LvV`lb8tmU1>=)zIDJXYJs>og zQSKM_)Xs`ajmY8vJ8Ck%QnT#4aOA#rZ!KenqDsqvEBmc9hk9NT!c;hwEDczFnI@jV zC{zad1+3={XW=68TNaX<*|nje%T9IMHv9JQ zOdd_{D@8n5pJg>=W`DM1)v0vVaPqzE1plH5rBGpAj~@D`FW1m6qd10mIx}k31K5TK z!TVFvCle}$ZBtouYxu-cUnyfG^x1=Q#Y+LgW1D=w8u*~FU-``0Nz<+dbf25?KkWNc z7}&08r=9X&@BdH+kdcvzg&H}Bdci`yH9dp9uOBi+c|~Ozc@-H2MF#~1O(kVb6;&yD zc};nF42yl={}Vh4^m^bE@xKM@7TXlp0`UL+5c=SecStDg5&VB^+FU*?U2Dk9jI0bB I4LlP51H&oxaR2}S literal 0 HcmV?d00001 diff --git a/nextjs/public/documents_dark.png b/nextjs/public/documents_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9cf4806619968d3f9f999591c109f13b7aa0991a GIT binary patch literal 61572 zcmbSy1yo#1vo3Cd;7)+R46cK_%i!(=cOM4#Ac5e6ySs(p9unN$g1ZC>4k5`S=bZn) z_q}!Rdw0EFi(${+)m2}8RbA72_wFb)6*(*nG7LC4I4rQdv<4g;!WkSKyc-(Q^O=aT zJ%#6g=&thm?r?A~@c;b5!)0cZz`-F;+iB@R^^}zaEnJ+~%q(5Zt=PPsT%V=k;Dp7z zUCk^Utf189RyKCdA~fe6Jv7vImLfE|Jjxu(u2NREcJjUuD@|V&Eel@<3js?SF;Qw^ zZ^35;PF7GeYHue;XLmtw5t_gB3O*nIIn7Q({g(*TL4-!)k3niZWi@Ik7l;+L02?Q( z1qTO+nooeu(%g*8(u~WThlLu%0peok1hI4SuyS$;a)Si9_^AJBG|vVhmeztA(z5@U zd;TUuV+)143bM0%d3mvUak05TY}h#k1O(VQK$3!_yN@%}%$wEOo%UZEq^;a7 zAa<@$I~Ql_KN`)F zh~r3}^_cOP zvsznoSa5UknOpMnbNtEYzfwd{-p>6wcs~D(5KSw$e~ujOsQ=0eK{Ja#*)Bq3@h8ky zmNfsIw)-#m_#avRr@xo2)w9z7OYr};?(Sj@^)iE4N!UDd_diH4_WusPyP4hd_CJN@@4&GCpE3LE+J7oa{}O+$bbk*2 zU1guY{JTzDIX|n0JXhiCqUk_5xMO{=w1k#-_O~1>QvzM$h`hB{<}iSK!seL{LpTPj zQ-M}R$8*#0x=T%EDq+#M;~m;f0m?@LptzQ+%v>XpWkqX9S4Cwd#0AuB9>(MhdOzWH`* zZS!~U8IoR#!3+vzYVB%sw$Y_e&KSm`qLB*#n6%g9bXM~{;t#!H1?&1$e;4R7_Zi)D z!@~W<&1Q}CAw)G}kPN#_o90N~1qH&thTbgKn`fkD*cHQstYV?BuWvUGj0VQEL|8kNW-dG3 z3r4F=g9^(gb4?UEsf1-qP4DizU#w#|>(C1!*2Bs@85R=h~>g z@_WaTW5%+tl~(2|Oiz4hTP*1=G5@D`a5%crFej4Qn7OD0TSsO!GYs8m#G9q~JN3Dy z@25Le2tK($Vh!cZk_bvex^@hR4IJ`Us=W+&xnmuNs_~HOrRN+hOGW3(wG;BNsxvz2 z&myMLU(W){CtL*YV_zQ0C8}fmMHj?&HtU3+JjnBc=zLKic18<9Aj$Ah0oRKw$KHZu z*a*c{D4ujFj=Ap=wf-99OfzJkOoRX2zM$_A5xKq=SRLIGHZQk(2U_1I5q+I(_&{%i}Yt=Q@CpEO@BCwgFIxKKO+d~)`LZ)3qFs6GY zb@ zaIaN7k~5mQUOu<7$uJ=QhRIjDE{W|805uIW+tpD~r zN{I>GW32NBkKf6|H(-8$%nwmaBRh_NZ1aXon2xbF18&g@WZTA3s_`+3ZivL{AEp_s=r`qF>PQ;q|AbiY))0Y0-n-vL3 z6Qi$5{3Ih8HYKUwqOc?psh%YHPhXs6@yO{CW~0({1RBFn==h&h;1g_PKz}o3unT8K zfH=)M;nuqdjft1reAJGh#o9?{A9w-%v;3*%o|vClY1dKgyL&QLp&&r_-fL86h9USJCTp z6q93IqB}GiKrLTj^#p~RVdOck>1AoKF~8i{=cg&}QwhXfg`&8p(i z>w)xe%RkOM@zsM;^4h|}W46dl)fBzTBOpxZ{jvhRtT1D`q*Si6lyB4{=?i~q!KFzt z?fE4TEIi~^Z6VYaBWPJI0o>CI@&AnG5OVus*rC2N!CVX_1w~BDxhyIQ?2g;l&$8_p zcwl>0fFo}qVk~ce6eqy&8WpV|Y?DZzkcBQSo#?%KO|7(*{Pth8Kedod-gT-Fc)4R< zz543NLYI2Ry39(?#DMZN{JBoX2yb*r(K|Yv(`hgt3F%K1AI=lT9G-@7pFZOXYmH)C zA#*gBw0pquVuX-jaIz3=u#U(BYs24L>iRvja7rc~Vc0$MNFDK_H4aI``#m3{$mUlM z0!|F7N`qn-RM^WtwU`i@gH@VX@4}@G8Yg0SbXf+_bLfV9sDdVT?0q!{UI>4w6}(;g z?Abn>n=`)FB*=(VI21zU79NJj!U|hNF%?5@?0qY&ZK*Pvp8nMFeTQKGlB_FZ6sfji zwlOqzBdQ>%;kG)^6R~Ef*y`h`R@pho@_H5Nl96s9@{0E_Q)zH{XrjrN z?)*%}-94&tZxLQ6&uSo_drm{<(;*Ci88ls`zXB+PzAGKLYdBCJd%_P>Ew^?3?L@%Q z-A@7Mpb3xEr1wUCNzUq-vy_H+Xtb29``LfoiC0tEH6K9e@Oh_eY(S=Dg}N3=-~Tno zJ%r|4*!FYo_94kE88|)<02Mo>a2PBK*^I`vjQ#U z`Pm%)<$#!AB962EU7UA>ehn>{^IX3YbE`OGe*{Il;-QzljZJQX>MCIZGwZX*y+4O+ zJVa&`chp$$Fj9c|kq5jcl@%BY2vd@Az$8B7>w%1RjlfQ11C%91+2Xexu|ImK#AxL6 z`9u!oRRwV)Qv7`KOFFE~ae6T~0dzBn<-0G|EmZKS)=0+=ELSKH2D;J_Snkzi8G2c# zx^uXFo73Ickp#WZj-1Kvf|y@J0g0CFvq@)R3kK;5HqOyEqka5Ohr{2q<%9e~oW^z) zQ+)_5+JoIm28fCTmn<)rRn3olX0X zdBz*slL$SCBLR_`6WlhW#9y?TNm4HN;hB=%{pPK)l_U1Wkz+vz-~@@cdIB>n8&Zs) zWSE4ON5eZMKxLN-FK(9lxbP196Jso?CBzwDJfu@$k(tRth(cnD0$x47B^?4|TA}r0 zkp%4w!Mz>sn~|JIc&^$qAFqb!a?w=F29vI7rkE!8li+S$)O(Jy;$_+N*~$4IfPNYuC@Z9wkeHHMr0AZdBWX$&$)A3NX*bQ|k8n0F+oE&gi$SNcUr@U)D28l?|x1 z;5Qf8z0Etod6eMl!(~TeQb;0?jlz*V5jW^9c%?rk$;;!KwpPNo=uY(O6O~baW#%bo zj1|Tp9u|uYW0LK=CVf!O0lZo9j0QT|`*Qnwd!+=a;De~qzdR#{^ZHKa$+W5`>-X-3 zU4P1$BY#Q#NcfiC$H>uoa7~zQ;#zw7!6VoepzXw{>@v?9{m>adoI&+hKr?*6W}V?yk8S`esS(j zYr&s$*EPeAKgl1j2+pseJ=Y{O)Eig%Wr@fb@$M?jm3MI(D|mTz%z!#Xonmwg0B`6M zpTR;mTi*hg^|hz9^aB-IDaqjsX3eWH(Mv-PSr6i8?o=Bxd17`MwwF)#6WQH}+=M?p zNzu%$_GNH57ZRs@vwUHw-*4S4s8ltL#F@fO`tlPm<(45{+uJBi8cOofhp>n0>UmEb z+|3H?chLlhoM;BNkm7`ZMu+-s;1P*hX&?95Z==fl+(f7u1yzU7t_tNgvfu^70V%(W zgE>-4vc|;G({%AL@e86f$$cq-Tz3JoV1Lm~x7!Qc*$?&cV){eoIt$-N(ST@~!>fB5 z(r6`GxE9h|7%jLz4yE|p#@9jVvmiSEFUr#HpuF}R#2u`-1BO!0w3f~puB1{8S@aJD zQCG*1UQAh65HSZ{FjM!Qgbo5nsMS-i4&->=tY5)BcJ*qggit~YZQLcC8O)T9}HvBJ>pP|f;2b|4!>P=KOnr?_^UiB9h6Y1iQq z1X|DsYY*O3%I`i9Vc>CA#2fkBv+j{vtt7QZ`E*LMe;RO%+mp8L;9*_N5w|V9k3_iL z2@R)_G#Hy*gY)X6gQ*H8BKiD9vtytc&=o@@%k>*`Cqm4QfNGF5U4#alG->7ZXX>*9 zuiWAnYM+U-hw7hp2P|lliyk85(ZUTR+}DfVn*W(y#mWbLMFMd=ingkdwl&_)q0eQf zKGbhl5R`#g_ekNOLiPtwpZU>Qi-qu(W#2!YG68v=e(=qN+Lh(<$hCJRv93* z>q@#Y9e%>FbwfLIO`UV!xBU72?@QukoX z^7_?C2=yg8pfSUsTA7WIGG*lon687g9i5_}@V#HgkReg6t1=HP7RD(&>SjZ!;ZuaY3!6ay7lTc!m(ZyCL>(R z)8_em*5^S%!_~92HpElw4fxM9V7{YIR!^U3*jp}f%Q!;Z@0Xo|yn^?#`v$M~%?n%G z(2Iibi-rf1;E2Q?K`A>911Aq-JFoUzuQ!{g64@yF)vx>BK~gVyHUvxVY9zT$XzIAB zQ=$HbEFDUsPDU(E2dXX+9C5#({M77KuY|Ob1Xty;r7e?Wh&uFpJv|dOEDpW4>&rUq zR=dF1&O4w|j*Y4sf-C+awCzBmR(-C9%%W!~q44o^TdTHu43O|$fCZ>#ver{~u=0gJZLq#tm!Ha@MD>xC-5jb=B`tZ8@@RH(1fj8r& z6u+&r;3whD8S*P`qyx}i=Xx99Dxr1XYf3X_IMT=B5fAL_eJkP%!6Lasi`!Hhz(*%& z2(x+`u+|vzIy!s66UT7_B*@c%0g2M|zBpgxv=VxOYDGl|#&%cmT) zcizcgNQSrr_eSYn^`yD$54@6g!yde(FyYmtC>-w9TBN>ox7!-e`xUcEBD*j)b8tZ{ z_WhO6F(*f_^lS#8eJ0BiMuCpZ%MsngVjd8ROoNA(|FBv%TTV?T)S6+=ADnw#MBH^G zj?jxbw)B;eI;V!kjCqtSBVvpuqTJV9i&h{h`Vd=-BP%as(3+1H&T)x>F8U^J@)uH4 zWH_sq8$lWV=vp;h!tk{X=SEuz`JXH$9mm-Wto9#xr(_XM{B>pWmA@1T`^PwCfND$LjrtKB zV~=qatUJH~>+z1xljmwoql>i|j3ZRc*+8DkbcXJGKPKrl@Z_CdTapj*@43co;;B$4 zq9LGFk~*a&DbodgjJ0wEu7&#-ibBmu@JW>osk8X*SCW$4Lp2m4OM^j$%ODnFnKBPb?Tox^CT>b%Hh9w(1&Q&o9D? zC-=@1bNScuV=Jw*))(vF+ee&Ojcm;5%dC_S8GL=3e=~Tb^D|!rLT4y;;*6zJ-E7~5 zkP~-UaMviAbzRmyZ{w?ScZ{LDK;6$c)E|gc*}^u*HX2v2&#b?#S4#5kCT=0KX4a{C|E$F_sfl7S|#irs}eOzsZfa;RwCnK5!gqM zmO?DyMem#nDvAKc*}8T;Cy!{r5j>V=!~&xv!`zU#XR) z>QUJ)a0X6qwm*<~o*#!Z<)eGC>I@!}va014l_;D}@%ieX+ZOzqxwdY9Szy3)WPLg{ zd)h20`j)uQUghs115*=E5ag#5~Xl7e|bcC&!H=U}3zjg`xp4Sk7XRNI4d*(7-WEt8e+B`AGLHw^V962yJu1!)n{^429b_cOBg41&1>^{1WTPs15B2gk2{r*hfnq-*>0wYR3WWy3VveqPh@(+sD6qHJB_i zHd_0Ae1EMpUZ&PXU!ldvu$0f`SfY7Tvx93;AqGu>QEV77R!Gi*WX}q}3 z5nUKdW&B>=vVYO4?GDbBSPreQ#vOAa1q&|h#eFQG^D3(!jgwJyyl^-#|0IX_3 zgU$RU$4-O4LvJdI334o_ma*nSSGHR_j(p_?1w^z|G}@S;1!}0L3EVQ}Etl76Z*S5; z#yNC6rA5!)5Cgz`6pd?gbqXU>TW_2K3N?UW6UJun;E(c}iRrQxZ3~0jLwIDKuSO?9 z#t2RF8f}n9)je6*mDUr)kiV1Q{x@uReoh12Cshuf#r%rMAg(HJo$LML91|Je%gDe8&w}kO0Gz}@uw>H0-nw>)ZNm6qk&){k4nWKsCLC?5Ch2uhcwX{I|bVT zW}EjXm)XTBO))>*VJf$fs`?c+yM}^58m!?{nDrr+wm>N;6j}!Xu+D-hRRtH=@n0!6 z<}pj2JJc1<8whEYfGO>;X6t9pX3$~0 zs#36G(qBudaEgl(Anr3HKI~!oNs&aF#`{6FRW!MAbacO~Mid6nKISZ&?(M}ZvAB*5 z)U_K2j1hI!RwzJk_9l~w65auvsy$4oQlSNDhOu+j;3{EglZWvHjN2rBw6-Yh@kj_v z+TId18(XXBHF!Pd^{6FtTxU*Q8p%yjRpt9)rzB!iegw?5% z^H?CWP7d0-()cNbt6!u|c_z-_MN~^=tv00vP@cI&(1@)Is0nbI$$_!W35+COC(a_p z@&P5!6=CnSDia@-mycHgBCiEC&gYceo#&Fs0;lrr!kQIUj?=?cwZ&dvrxsJ~)lvVX zwkw^=fTgy&pN^wx?~sh60^nUBQnY?VZj9R5qiITe*zC85=tSQMXh}XVcJ?{&3>#XI ze$k4UK@P^a{qSD@Y1mrobNO$(u&Jao0FD&*9zlH+frh+Tal=<)#E>RPt)-de&(d~A zT12!G50M9*n9?vNnh!8p6BQf2+4~Cpm2m$F`cQK8URgZjhXKa#^;G~j8XFLt33Xae zdM}?xU)a<* zqNy>j#i$v5-5F=+Dp>{Ga|HVwA2sel!FAp>UDUu6s7Rd=c)4lirW8}RzWCIj_WU}n zRyU|gyS(bnI%Rav8<^!RTu#lIGo`>Am-(2*7W?+c#T^HtT4dO|dTTcfAi@$Br}dm? zjZ>D|<$?;gh~PW{gqgTG_K%8>`CEb9lU9!{iXU>-!vRM=d_=x9H#x-~WP3M5lij{w zx4v}fCqYw+yB?+a%Io~L#(smM7Pv-qrIH=ODQ7 z(4;q08iWe4Z!m>S)^)SsS&J5h6ef*!9sAPK6SACQv-j5@3$SNSe7}qnM)0<)xZ9g| z930bl*qWZB0)AGwzN%3G=Z%;!NH_qEfdq9Pus8UEGBct#1okDm+WW2eLENjvE^jh_ zzgL>ei!*#k$fDgu>!M{m56-taAHwOX)&fs5$>V2IoL!zL7QH$vj7_S`5WK|kYsp}# zP}<3Ej(L7axMTLVZhKyT2O5z(_s-zl`ydIUQLE1OqiCwux?|$VYu}3X4s+dt<|FL! zxqxHFHNMls@E7xpK9!(Oua|>8eq0_M_|2{F?;gMrLz7Fh zgJz2~Usj!r6vSN_C(1$V*nyos&Q(=b;p35a87rc8VXQJ5_mwXB&0M{pA@(ut&st+1 z6yuQvx_~NF=-YO|vz0Hf-9o>b16VnFy9)iWU{_6>L5)b<-A?<^!ponvlh>_mGq}eU zVS;ZzbkaL{bXyArYNkAD>b72c-6mFcxvHdS?S4S$0s4buss!4q(WAyv21zWkg0Bf2t8-c)l8^r{pT-gpGb?{=2p)pz2OQ6;a;phc{SfT<82 zB!O=BqDYosriemIW0bd)39~(qNo9K-#zllZQ=w~5pR$Bek?`c`1!q!kuc;FmBrhtK zg)(ggL7%@@M6zfsOJGzu0&*xuI<=O*rcoM=p+n(J#jfsyePWaMt4gUf!3U)NZ3wNS z>M>mL9o}ga5$;s3*jN1FFNU|#b9XT|U*~S?52$^L#Uj#yci&wHpik+El(7t^n`O}P zxt+OWj{v*ow-09hLBnq2%_jnN?7&6(1AbsHBn|k+%fv(Zv0Samf>4ObSl|XFM?a+; z>}#-b%x*O&_}lz+!Mv-&51J9D>(bA||Jb7hgE}>2Tf7AUe%5MeAJ!mBUI!3Xg=7{w z+{AQGF_l#9=3CkXS!m`iIOML+A_^*gNhwAP-9Ik!XzuoEC09K0_zK_UsOOw^-KZ9} zU_SsqEB5PAc7|BesY!hX8o+8-r$X#22{RhTUZ&tX+Mp$Bnoew&il!Jyx)^dAb(;_k%$wBvZ|>{$pt;TE zMj9D2jXGC1;kk?Bg31>2+MLcxrWDNJ_Ku8+OGdDZZDV(Ga;4(QLyaC`0U&mYv0c&S zn7&4LK;kIz_du=r=^|M`6}?Bp#2gy1^>EEI|9X+uK=(>9w}NYKrDg}QNpFvg&T_sy z6i*qdnZa9LGxhwFlEP#c8&T!^QTA~vWq5qQ4g4F5zKE1l@PkKDD98Gz&Ix7w$J!Y6 zjAEY%Adbkj)dvjAMb`EXx6jfkE%MX|s3pt7%S`;q4Zv(Bh?&Zs|ZLH=(R86Q!(!`;?b^%OQHKEc*s^0o?5xHGHX@1JE*r%`@1PaK=<3Sv*Jrh`@nauPh`}J1 z@Ix_)QbmJ0*8;tqGMTvVDaP&|_FN*{&b*(VBSg#U5B$=oF%zv~=zm>RjNiHHELWoF zyK!>Br{F09oYOt343vtR!iUX3b;b!>WvC8`Je<_x^US%`=#TA1icA`H{Iq928P{lK zraGkN&U(w7Kx(QV=v1i$X2P>ip zxm)iB|0ePghb0$KLGx5}gb=xPvNG6zNzKQ$+tn5Suor!IEInSE!T7T#4rC*%*hvda zKF~UexBT#bOxTyr;L@ND{IC5dU=*nO#nWxXqW=V2_+Wk z8o#W>Q2#h^jJa0Y(j@;?TkZTqILV}Sb6k} zv!l~^X2*=&`Y8(2a0Nw8sxt@g@$HLrfhmWmgv?SF$<=(8Y1a*cJZ&N-GUY|Ghn8za zi#H7;fG$t9zu|jOk!B>tPb&hJ{5BmSk|O8P6gXniW*dB`=;7`X#&q!MP%;~ z4EJAB9Wa<^gx5k_u(%}WJ^Ef@no`$sM)4>wfFje-5OZytuS?z`5Km(W)v2$467>=8 zwORcngT$4bcb|^BY-UOoK~jF=G5{gJ^OkVgv4mHbPEv0GQrV79Bbn0U1S^EaVldTf zN|1I`P^U>c?rKOgG8Q+GW*MHI!6Dc>tVU6UVV`77h;)vkuPRU+T%sR*$Vl?eP0AR? z>g*MybH`pZ+p~SMZ{7@f*+4SRBfM#L;wkzi4diR_I*tJW4G`w~7X5WH+NPE$7xmtE zUr3Y-l%1;ffbBEmE=bg~14}Ab^7pHwDlKpjkHB{wn1$yxH(TQ!%<9$+>_&J%l39v z53u5to7IKa289$q=S*Q!?Lf&cZrQX$-nD`%Xokw-Cn<)U^Jv(r+w6-u86JUy4PM)j zCc$rmcSt>^$}qF0Mrvd)NmPyzbQ>K;Z)xmw1`bTLwha^k|HB<$Kjvr3gmmG8GP zqziB)(jqcfbdv7~H+0s(0;Jal zBWhbtk`_5b;|EWVqr_|^VVS7>6myFjgv5(#BdOf_teuT2JEEdcOctA|#n zH5djt_9zvcA2wr3`E+-n7ah}Em&m_}P2=yj1nq+Rdp*+^3K5&u` zs)RmquO=duRCvmsFRZZmh-j*JHY+}^eTa+?1saWNm(qr_sh1SD?A76Pu`||9s5kVK z+P?P>d#qGre1CUIcwvM9?Pi-PY1d^xF%Br8;!zB;FIljQzP0W7sO>85!C|Or9&h-_ z{W}A%!Ux9W(L5^G=mj8WaHK}t!Ya#pur4A?;_m9LCjDKeao!aC{lPF!JG_`Gi~lxm z&Ul3#yt2~hGe{<&z#EV0{iSp2+aix7vzCwsje!F&XKT;%XQSSXN}bAYrNl-VH_5aL zr5PcNL>X0irfDD+1#z`D(@#_+6dkejwW5NnS~-Jf92GOV*GKLTFV+AZ#n^<@&^$*bZ3yCE0Q-4Qhc{b+ zhYoy0g&N_AX8p&M+BJi!8iUG>CWU1fCA8<&Ea6AH>MbT~ynY9YHCy-?e4nsfamutS zyDq<`!uZ)TUTFb=w)s-lc&_oTvzaLDqcJIG$~^&H5MKIl9p&ND5FvC2?Q?4$71*vY zRe|Z^DxVk&f3(JV1Amf%mN?RVMWa_`V0z?))dlfwluan{*VeSe?9V!9yNut2doz+D zJa^yeqrN$8w*CyBkN$~(R=t^tJ`*h)fQ5e=RoVvSSW_n^N598z4<*YmqdV#?EU2F%I)} zs4GT@H%aagEVa(P5+A&feQ)Nc&>g{j(o{2X-IbrJI(G$Izw+%MR)mpj!jzMWw2F`0 z3l7awz`hgVCg)X^mj(hU;vUmSj~e72?*`j*Q|G+5KlJQTf}>Ym`oF5S1#wMYu(?uT zFLub;bXy8;eNvzk8nK<1%hw#{h@`HJ3t(9t@>2GV&~*n+`ng^EQtMC_U|ryi3eQ0~ zYeJ0HZ^Y$N(k6wo$vZ25n|i{#H7Tr@z(u|BC%-GBZE@v+3+-G`;1P3YzTi$nba92( zS1R@>lGA74r2bUiJb<&pkxHI1t|4m1wC0nZBr<0pa_hxIz(OARdTC8|%r2vp)|ony zwk@-!(|f9gi0(W0Fr5Fuyd`hpxItBASySAgGq#WY>Am~o3jD^0<8Zz+Rdki0 z;VItZZQzO<^CbRfP5&_kme_^5rUa!-IghujNI23A=+gKKel*}hW;5s)jL7jZOH$P< zZf4>4xkSOEJ#s=gl5_Akj^xkpE9NGQ&igB4Q(CUU?_9oK9aX=Fmk}OI(&DLPjt70V z7bVn$e!6q=&Z8AM2YEHbonubTlAN|8N&(PHllv?o~30Ku*5wwQzfHIj?S8I zEwiAlUJy7f3-jD55$&XiVMofk2D2zZpY6NAy7gI2Ps0?vN!ZYR&fM)7lq5TDrNp8h)NSnh z?Px+=`R<}}FD4uXfZZ97Ihohw(iow?3;~s^k#cv&%j{u~xbPZ*)&1>aX|^BPL|-n4 z>uyf@bBpR;i@e-M|8>2z$ve??4cBcQ@y>Ugd0f`qI+SuC(g8`ZgqlC8vmy`r2y-eH z8mRmc?2Xsyyjt+~q~49kW;(h`e|2cxFXQlXgIru_VhievXlf(&V`)T1V_B6g!xDB% zB0we2*}@gwLJH`iT2AN<+B99&+@d! z!7U;6TGHc_($te2e|FKjWwL_BV!WAABr@HO%#_T0TbM$Ui`t8ndcZ%P)+l+C~ zYdI=?kXmB7^blcb)XjkPE4@YiM%2D4${u*}xIr?qGS4X#E+H3`8vva&Q7{I!?V zyYO4fL>ad5;zYTZjE*$1!tcrNe>#_7P(5;V*uC|GlZM{q{H#7oYXN!MIqlQ#i@>xln+jQ)V_oQR+Z|00N=_qlE!y1iX$wk=Q-NWFNGgsj{ zT?UmQ)ikF0bof09mMe4ftsekw`n(%0O`CT?KTso*amCgZ7eDfjtD9WA_^8c%Ht1>A z1^zrteQ6@YWKiIIBdGrXd*jr6C0*Vjs*_RNm03x0Gkw&qu4>!N%Y2YuEz!bP$SiBJ z@U5esj^|yT%B-I8uD5P=>6YzcQZnOFDBT=ZR=EPWhyN_6Zl$8kx2k8LG8B)nQat>5 zU1YqV4g$>Cb7mfQxA^s9#$@Bz4tq5I;RvN>&g+WXutoY1*_Ad7x1Nm^wUsNW;*?z0bFz)*}b4~s=W>mt^ro)F&b2=dUU8P;50#` zCq-w2Cve7vqv|%Dy^CPqAeg4kSarIh*Uu?EovBsVY+)ss^b+Hs z${f3*xFJVNry=^M$_c08hb=|F>ZOzEdj@*S#v5tMJ+e)q+D+D{^gyHRyNAeokiIBwgL?KMQhKoCE1-6x>($v!b_J_0(j$-pNO`CTSjo=RBXHW3TS)& z1DgHrEKtKmX}QR|q}TyqyGpL1UzN_7D-rXM1*^Ve2@<*IdpN4Mt)WTY@fz*3(F?)h zRTn#hbSw>RqoNp*#a*+hKMAHXz2nV&jLoocRPaW-Ruq5&Jf#8HKbD8tcoQdlZ_TUR zhZ1Dqr=c{3x#G1A6vOy0ckzDhT5L)gd?ygO4{k69oztevgFH>qxcF!H^kU#xf~kno zP(*u`8_-JK#I(?Mkl4(i4OTy*1{YngG)KI`W}|95hr>JjNn=p+spMKS#yPWvz9R?j z;DJB{{!x3-(8NP5c9Co3R&zokmq-v{rmFOBo+Xc9-(9dqzQg53T5 z`1b4>Y>;kccEE1*jfR~vm9WBU(%1!+z@8m%L&jii9Gb_rga`NM4>;4m@)sBtv7hb%o8wOwAJx0BbJU-NJ z;lO|Q3ZoAKfAx^SIqofH^wX?O3V6qnO}>N}v#C75l^4|swvlbGIC7MQ2d-Mk8`+U8 zg7OqIHia&R7dBkjN+ptcx?ljDx zK;Oy|{#Dm1lOz2Ll9LXPh;AIsfT4dXUy5Wj&z%lh5W;8-q2nHgmgOS~map00K zC>2|yIE8!7jOKUoXk+WqZ58>Kc?_H3UZHs~WA-psTd_ESp-S1_(QCU?@6YZR1;P&% zNhC185DVoje{y7c2#*e?L_Kxb+m}VS5AY6_iOVlZ(^qPdy+m@_1fK~oC^`_YTSAIX zq~~3TGQiDM zCQ&7-<0+~DzaDDEvW5;sVK&{<-q#$~VY(<|HzQb>fnv&WuNa6;9M}#1)?IubR+ELQ zH|lc@Ocl=$#?%32ZwU{!Vb$6o^Dlrk;D4hW%O})`O40fqvULPkMrWnoL$?lj4OqeLqrthDQ!1gg3(QTGZziVH!ZB_%OP}vL zAtL1y$AxFdMH0s)xyQB6$29=uxk;FYN4jpUN4BSep!%WK_#%XL@g>;Pior0v2>}wr zwk4uK2&=ss(H9sce_pX#_->bQwm?%--WvD5^=eLsL4z4cSgy;;suS>SCSd)@)2K=(>XO`JnwA7&h_F>C$hG;M zjwSjjPQ|_xuHD-vU9P^!Jo`e@PZL;%Y9~GYVo61grZuUkwPV^J;59?6XD%L*%G+tL z29DAIdEeZJKtwbf)xogu&a%WPx-|(fw~GCVe<1ko~fL(o2g!jDyY7s)ii2ogLhvoO$Zv1^au#5v~qcAmKgl%hW?3RAC?_ zFfR+!`dB_erM1=V@VqlGD^I=CaMC{Ts(xyZ8tYB~|2`e98F!rIX=#8pX4l`G*k<$h7s)2Hvx4 z>(!eVynh#EhC#(KeBpSW;%G`S{E6%NjX(tq?`%>3(X}Op(qxc=tpSeym*V=Am)F!o z(WCuvSrwlL6PH>q@&%DnmWBZF;nn7)7KC=9x^Qyy7=c0~d(uNTm+xmWWHr4bzsGDk zm(HEMn8gmtPk_QPkqv8|E7GXVd@@n)Le1o6$M^0j)ym+jkj8r63%b?hxx*hL`Fy)W z&qNAWZHXxMAv%gej=F_2q)JcYpgu}ihT}p@WTWE?!^C$zRB=M8OFRpQUmB?b^IsTu z{cGvcV9FL{C z{0T`Ach734I|_6ANCs|CZ#g7~2_sm<(TY5p(VC~(z!|0prVj}LEUZ?T@~tOzfQG*~ zmhK7nW5!upb`|)|OLfGu)iORz!!vjWwOTy3@v#qHf*aCrmnkO7ZUP;i6d!*dNeJn1 zV2h1Jl`wyRxwc=4OuD|(|72=Ck5BK-w-!v=x#`BvvTCZ9eJ&y_fn36)4&T&ObLYye z+d%G(O(Mk|es5a#R)eV?Pn@CqKB?DP_lbcWuh89u7%Nn8i9D~hwT1W_MZdUj&8 zrnmw9P!&(DU*vhwFMyVDC1Nh4PW9spld;Pw{OLA-e$rw>U8NH+p+wKJZ`Z&)MqFfc;LJJ1tQI-5mkWI zKL!kC>hmPx%-9HK$UWEzweL~g@;9Yj^i|8ceBSt*Jt$Zy@K(WJ-+&A6Y)i{`B18FG z0b*h>6|Xcku9mvw^Im6MaY1&(7SglO?kpC(quoX;=Bf4tqPvSC!Zp$nT#Df-6a*g~ zHR<3Nq71p}1J=}UC*YRS2hDFkX1(>L&-xa3H)G*IIV6S6P_W2hK{7ozAy~evY1*l| ztYkAVO;`>Q(3YV89ISMgW2n5d?ti_zX3cR*xH>`mtyF~kWcZ0Q$E9;AP}dYy>fvoc zBkFtffq0e(b!pC$)!{G6@HQNSiP`y?wv?apKxeKkn65cWG@syD;dTUI)SE=P`@A1X zHB=j&&@=8$W$y9cVizXkJbkc`xi{TW45ZJ^!aQEw_(qTX+o05+m=tM|sb`VD7r+rb zygK&o>3;#>Kp(%xpDbeuKkx)Y8<n3!~jQ;s-VZV>#UM*}eE^ee*&o_9DjTWA%H+i_yRb?U~^c=W}v&% zmMr!G-5NZ~halR}hvT?{C;5V(`HSUz%@dqX4+@#V)r@BZFE;QNRlqKwV-sq7y2oGS z0z=%$t&+PzI33Pn_lSN}A8JJm=-u#Y!L<8yUp1m)X2aJGKx^d(wdz zO4&yilX#FxgmVX7xsEhW=R#l(j~UX3h$d%|sf(^u;Y%6ORPqr=F_a5<_@KQ`Cz>Us zV*$$Wr;I54DFbX&;)e}?<};6RT*UPT_70YD2ECl}3+A$!z6Xum0|_LKL|T(Td%6%u zdtz$hE3?_kA8ceBDWtNOVwYO}gDLc&0~?Jxl{(qQ8pbk!PHb}dm=Cy&XwKnnc9ZD# zpel(zE{ELJO$GbuS!eiMwckz&uez+OI@;Ftbiy^5#=Uvy&J|wKyO&>>#TK^l2pxeX z?8TQ*B8VW1TwbRiLmd0==W@RGN-vx#p}MkVJ9e{(G_puz4C}}t1RMKFW({rd;Z7Fu z2v$xenP+$yA5yu_AkT{^NA3<|s33?Ee6a#)+{>Uk+(=L6cI>=_jX>FiD6V7#yyAtl8B)jt%<{*d>$kh*u-aCP7-JFFzwuS zVF=+w4~@Hxe5hkpAeeIjSi^E4j6}llrwTu+2*g4(Wfb8{9-AByw&4s1Y)x^ZHH~}o zaGp~Tj4@=eoMp^JV6`qGa+tl>?j^C3{qr#!_vgZoeyfj~Plh#`Hk8`i(JhOTYwp$I6a3LnZ@L=newGNEL# zl|QMZGbeK#cJ5~>fq*Eaia?49qLKitL{pB1GAyhipZ1Jyz>~>+Hj_KROUv z;~BM|mmMyHFK`;sT*)_0N009SAue)u5AT8;1lZ1_;h zVooOqh$9Ku+mv)6rg3i$+Ht0V+HCkx#SY$LD;4WTcm~HzR?&$8^`!MOjuq@9ff2-z4ft^ax6`#I ztjw7Zx;VzT8+n6UiRX5g7cT$CMmhF646{3gkida%v(U!j0=$HG0O&|$9mo0t!L)IV z``Zx(Y-vhnAk(-v2V)O%`)dk$?53Q-_+Y`8;T*@?Y-0ea_^^Omfvs%iBMv8*A2^0s zAf8@)%tVrz;$dipt1Jgv@Z&go*0f^b0w%DOnQX(4a?0_;ik(XQfC7B5 znI+D9qIoIde&&)I(?CSR&vczprTy|Cx^+(WWmU`VdAKzSs!_ zstCqL6{~p2@dgryFYs4W%D$M!y*Y3#fqz|;QAjz<$!8mDID%BlA9Lm=e@V5c=3=)w*{*nx#$ zR@0S%Oa-1|Dey2KQ|MvHcWv@1F<{nRRPhy0(~fIs1w4)qek|mARv>Pn8?ccON13}w zBI!#g4--H+Fqm`rnfX-Wi;rU*UqCslD4{cb`PJk8{hxKfAg9l{Y^0l;&X7%GF=Zss z$IHeY=5Zkwj^KM>0SlOV&>n@XWIZoBjc|AK6i*OPtC&f{e8tU8aXGAm5rm=xGJzh> zy}&P3snI>QwckdI%VNE>pQ{JNsUlBr2X7Lth z0V&L24qLDiik(EZGmO8OOeGeM=P1^21KSx$nj^?LoC>Bhfq_gjtkiTvi^K;A zAKEQ*d62}rgVi9&$@({UX^Db}&(T1H>-iOL=wPlgt4FNTy(f|pFQjalK+;|&WLtB-xm z1BNmlsNxx3;dM^sXht!f3weg6EUUvrmU7!csmAIf*AZN21g#klEUmQ&`Xt8#@Dg*} z&@`M5z*2TKr5mPk_dY$E>?w0Ju(9IV8% zoHg_$pLphS5vOq(d-27_R}|5^SxSTS=3JnhHk`{a3P@rPvFs(25(}k}OG{_7iKtqcMz@exZzWM<`5oxtRw2Bm@d=e!ITe5muH;g_;Ac_~D9Ldk zE4bCg#a>s6bGXW6IsvntTp_RJ0swxkBSNAfsso;WYg%lIY23X}q6bE1B*+ua9mpY-B6g9?Zc6zcxZJHA8%^UD;#tg{ z*cr;D6qAmPQrb{SPclfLCzk*Z^R8EWG0PAwF`SN%Q?~B1TABIs`PA`%`kLy5X+Dnm zbsx^bsO7&p@1I|B+{2LoX8Y<82%T( zi~?f47NGZk7PA64#<9ZTdJ^Mzc+;i*wi}kOGmvwDT}}(!(|8boeca`inQrUI(ci=j zpXQvq_i?SldEFezY5YJ8XS0cC8Osu4u&@swN_dNQbfA(l?q)xm8H|nRvD25|>CPrb zvKBFvA2^Pm`IwU!!bC5JF&)b(!27&T7cOHeJNbeXIOQy@IDuXG z5r{A0gb)dw%TOYTA&L-uu~Nnd++c8o@;cTsioKhO zp~H{=KH52^L>j`lRLo~F3YbyzyE&4l2?NUOO?6!#V`&F$<>#h##5C^Sr*4Db8qp-; zOEBSlLJW)OK@s8PF_a^nez5m*7Qb*Nb`r>DJ$*fg+Ce3VtSIodIoToSB-lN z_Yue%z5uQwkK4G3rBtzwWHw=;6*tkHMO@rXg;);uUe8Cqw3o$4`p zF%Uo?zWDMv3n-)v8v*!W$Bvy~?AWjn2?QDJ8@`%+4y(0rZvzq$S!|<_Ty~MoGBz5% z&S7INqZo5g%~Ip}k=tp-<$PbquP1>HB+`ri^ubOTcFK5{$EXA{xtczWrXc9-l)%9g zI&&AWgXxaXlX#2PfVhJhZt9v0!1qq!X>MT}ckh$#k=ONM%wqws@h187X9t0_riAkt zOFAEL2JL|)uHZH@XiaPU@nt(hSxq>p#1hJKda{`^-eCYoGQf*--Pbb&c$8eAirWd} zN}l633djZeaTv$4nrTf*g5)+cxx|fBQ}vNbDf@Yn^Vvf#XK^kc*HJWKAQ7x10}G-U zUwjE53lM<_3snRle5u4nC4oR`Q~Z`2U>m7~aX%ZeIVvzE^C}iD;TMnI99>}!caX#Y z7I?Xx&HTu@jASUkIc@Dq502qz+8#9d>0h&;zME6|xRDizK@4h|Pf9HUc$^NvOOD_8 zDZEZ3Aa3HBI`+5X0|a2hj`e^A-9d~7%K5&joiUBO_mM~QtH~s@fj6n5J=^F&Dh1rc zSW=lvzZ%c=&II!XS8^$9DWw(5i31|oOCU+45kdkxDI<&%yk^{w;9B6Lnu}i4n9JqOV%lLYUl9WEgJU`iSwn9&I9>Zxa!DY@>!ux6u$KOe^}2C~nVd@i7t|Q{ zK+fgiddiX%u*&JvU!2P)j`{k!iQo>VdF(H93sZqvybJ_!BexL(6mc8x(ud=S#|H}) zgb+q9p~T<^gi}r>{w(8lr#R!Ov;nr)lepUzyk5QBlzz%{sq%V#+@eqoRGfP0I3;PA zZjrP{hwCuK=^~X#D%VuC(fQgg=_kc2NyjQt37Vk6>Z3jyr%~#u&YB_VHwAm;EF-l< zQnm)v+8UxSBxUJzg=(^TE2{eE51 z9`$dE3MG|jsE}39JGAEN1fk(t=fW@Uf*M_IwNaAvVAK0!ddqm9-5!>o7))zg(TYIQ z38$Fxz$X-vMn_UPlV7=rzZl9KUZI!?+)g>gv?Gz#_)tMtwo^a_5iA6T)l)*iQ|@Ib z@WcV{1;w1hSH$oRXEKv@29&*aon<`l(eYJ0!+Jy%R(z=-ko8l!dm8 zB3;7n<=t8!dBB#W@!{`oV zdXjO;oR;xEMeL%d2gmym!(N09J6Vk6C|2*XOTG5KF#PA(Oyu#INVGcf& zGn6%iv4v>z>C6&(kWCE77*KxtKu+dL;2WMj=$lf`$B*NAj}{deVIm)0NZ}1E6 zu>v~~h>aYg$l^CnC6py>ql7fJuo@9Y1wI6k@9=5&!Ac1}R1iQV{#4;hFvZyDM<5s& zF!MM2S;18LI2rf#7=<7<(tO$T)|}C zHPE53ZmRg6qiM|zj-a4bOr$?)E+@pz;UX6DV1s47+tmDTl*|3<$0rVdoX*_MwfHfg zx0uKBnn$9ITlks)b`wt!1+=A@JR&J%FGZ9e;A?a~gMm^$bGZj~U>f)4U^R%X_fqd+loXw|<=5e+gnp355zUNcUZt~FqOkyb4vY9H12qXeKRdgbe zA|7Q0f%s5JI2MG3V#n~#}gZQcDa|*kO zW&l6b+AD}eI?<7~w52CW#A2n4Lelt?&sa(d+Z!l8T^}>Jf}ylyw*lwTFkf&vJvob6 zjxyM#{Nch;K28hE@3Dx7In9Nm;vGqb8>25DIO-(_l)AsJ0V+{a-a z)vj&L>)gO{{IEN!F%1DWu!BHC01I~fsKi1DK2%Xc7*+US!3LBNLJpCXyf9(a@Nv^v0e{lg8e+t ztN8H{OB($Zhmgz&!s&xQzwl+viqCe={Rj_SI~yO2D+_X$N9i&?rUVf6wc%`hVmvSdsxEEJ$CSLgO8oY3F8j# zWj%ouW1}@AfQ62_s1*cLh47=8ApEE#8ariFVg;;(lScp*_~J`Gft*Y*@Qd3cV^`Qr z3jK&8t7gkCpf921)odweHs6!WZql(CSiU2lAL+vh&0yT&ZKiNEU3rAF>ij;EI6Bgg zK_t_GD96?=eCM=J6`%1FCvgRX8)zx8&VnGd8N(+B<&GM`Ko5T7M{zy?uQxclcLCE| zrg@m@l%b??@_EbYH8Pz_S|bLspI|=XQ!*(<6cSGcomojdLF}N4OniWJy0D8pBFQF{ z9M;j1eEi8Fgdny7BMdvQX*>>Oa*+$gCw6fzt7*rV&5()2nU8ChshUbh9-}oy1YqTG zlE`BTe)!;nFLp;QrWkyv!bTNE1W`pL5m>MhLMwdn0sQI6NFb-_VJQu=kJTjA%HqC~ z3feeL7(f9p@G772Cn=;GTAAq=#ArGisIfjOd58kwjDw~=dh-%L^BceNBad+k{cB7+ zWFHhko6kFpV;ZyT_2KewbiHN(AJvf-Fqnyr99KVKJVFq#iKm;a!+~ksn};oKc#2dq zn>xnCY7G-C7zLN#zqys z#4v{nAjzQnKAP$HQNgwK#P&teuhyT(CQfEG?fAG^&3lOfdF&Io5Gyu(83+8vD*Oo` zkYK{_!58quhblrTB9IaS2_TzdDzH+HFBbC2;&?g(GuiHOf9hr>(BJ9v4$|@Ca4)r1 zn+2>O&V%<;cUZ(LfR#rX?X)$Vd$@ul=}X&#!Uh*}W1Wc?iui))7WIP)f#18!UgMQ=_OCr9sV>el((wP)e$fq|IBv4KgyMX9AYd5+} zKi(l0c#Kc#+2ci4@PU)}0c_)Jw$PCeJ*ZCQK0iC$(LCX3+L1{+`T(=>p@MS!@S~6_ z3b9Z^F&6T%JDl7~2p|wY$|%D|F+mJx5>U$99`~g_7DBDZW-6<|BR5>vspLEG$Scep z9_1$>k{6xgQ%mb`S|}lf_qm*NSkr*EHDpr7)tttI%wZ=PHFc0KV;;Y9S3UXnM|0dk z+iX?EA^^kWYRY-SzN?8Zt0g>1n>HdcH|Bc3SADPlU2e9X_ZVjos)gaKhh zG&LDf4PE$zF2IKkWT^JR%4x)Ks?&?_TBh+1eRzq9%~JLcAdBBg_E1L{Q`kxm!bo8& z<%Cg2v16>~k1rOA@xzY_N&pL?R8UF`LfEik`f1x6qNHOki9sGqRiyc!DZJXM7vOvl!uO1{1|3U^N*vQK$ukQjQ-! z^?7I6i$TqwEMnFw}JKqxN|!;L^N&+`(mGlu0v5Q-n0@h2C5atJ1qer%*4 zYw;zNB8IbtWD4lV)eHe3nxU*GgYJ&Rv_39`LN`Qf-e(-Jh)WvG4xYjkE+^~&&w)s$ z0&mw7%I+OJt7TtJ0)6R&jUVx+luCRN5tI=^0T!(IQ-TE_0;s}KI*jUI!4s$Z@n@FRp!=^lu(v z&bilzg(H9!9L)?$h~-Rv;0wlilty+9x4IC+cP!8!U$Pj+TaK6b)?CC<%%(r3zvF;scHb)^kCv62Ntl z&fQ#BvwBd?84P2YQ9oc8@pMuKz>gCMC5?U9u;7CgUn&8AEPyZBHBOPi_)&@wRao(% z9TyP^%s1wBy8-?LNA;d+vRMPH1~83# zeRO0fu$+0E%mhB7kU*v~iyt_f;3jMRkb4^4CxUa>NG^j|PZ-xa=BwLrHJ7rMKoZF& ziF9n(@h2G{k|-me-|2!MAq?U{deD`jv~to~MmPK@p%qZ#K{cKTKH(@}BhwCArVL?3 zqt_;$>wwq1UfRK#2!mP(Uo}xrJky!jq(MKEE=T!K85l z$5GBFoW;Y8=Er(G(mkb$%b5fC@M0ZHn+Fok2qtnm&+#eW@+;>$j5JhNvKmKwN~k0Z zUqaYJFr6vIij`gD^8{1*5gQgRVJ3ZmGIkM79w{W^Lor44Cyc&8A%7x%Jm8H**s<|< ziNGq#__`)ic`#2A2yEsK`}pVK42%U2ql|wJnSey`~^=_LIm6KBN!h?ivJ*r8Om=A&G8oguBu}xt$%(*TPO4*GFqj_+;NAvfP#@z~mNB8(7E=L6@T&(8NC_E1VNh3sZ2KY49g^)n_j#K|{g96wXR zaMpUEt?PK2N?zteim+g3JSTA&ffN%$A&>Gcl~i&V57U-QJPakPk6wI6FCd>w>&V37 zODw&Krw8rnN+%+m92tZ^}$R9E3lWT zE+tcN6|d)D{-?^jlJ=@gt!@4ElrkNemzU`}wQiDTtFBg2BYB-m^oqJ@lsajYl6Ah) z9NVAKKt=0t_0c#bX@HW|OMTTzZFIciHAS7(UZYiVkiJXRMqSlLL$yNECdD+V=W+T* zlC)hz>e=ITN#(k-UJZw-T+&HizIO-8H7;b*cAZkarNcE=UDZcD)L*^TM}yT@gVkR> zH9$QzNd44DeU+?pwX;qgg?d#Ty>hNsO1jkPb8GFDbgtp;#HoW~b-6Mnth;2jHA6QO+Db730k0(I{q4}NmI|7Jwx@oq!b;k ze(IxGouF_Xt6mzZI3=mOqLri|^^l*=(IQFGMvWF4rg%+Il6tANI_n|XC6#KdTm3&) zdnHK)8gJ~C@wv~y2gSdLL>?ua1-y*&tId9X=3DYfB$@<{;V1&w^dk0J`_ zbBSULFS*%gfG&K@k-%=wt9N{{j(m>gI4mr#V|5{vH|fmRJV5ilFkVM*1GV|mi$7UU zC}5`wEB@H9<3~B6*r~#YGHgV0E)Nr3rw)GxGoIhbG_YUQRB}G$PAeLvjHWwTO^16;|OB$7uf5;=xm*x5@SIsD1bSZPlXJs3@Jwk{em1y=6!d|+OK^1){C6r2nSi%ou&V^INl&0DCS0^*P%?~UN@6D7kIvo%;(w6m!s))e~RPrki63cozv5<2(0bjo5N4I(l(1R}+0_^6j21_3N$!;bxo;VgA zvgKJu?8O}_@ zy}|RDLK5%STze7E(FD{=XyGY0aus`+kLXM2Rk3#pC)wvxi(1mn*M_&8Nq?Zr{G_Op}Ec79_vAMzw~YJInv-t?ps9r%#;6w;nu zbfgdnr8OB8(wZEsM3Tx{`qG}(Y-A@r*-U@7az7^#0?grZH~he+@fNLs0xmW_FOO;5 z>%yPM=}aDXIVE9orkKC@k`+YLj%X%uGDncZHn-X+;wR>lM=Qde921NAnR|JHFIhw> ztq3HZc9S&m~p%hX@0C~iaNoO|VPdH&@@GXC^nq}{KjhRL=ptFP|n$~=7aP8Q?S;sn#CjcvB zX~ROt?`|sth{DQ#HuDSL@ER}iEblX$zYe+@VlxwnrWc3t12)nb$xdP^C6_GP06s)e zKnA_ZVIJ8mWFC<$CmCN}<~S_Ca?Wvi=n}|1JW3c)$PIj8+{O4Cb3wH(Ml%;bzGF%w zqn$uTaR$eb2o!TvlNQNh=|(TwVxyRCY-giWn{9|D20PiLQcN6QJEmKTd5T9F!DhOU zj)flVCW2jbBZm+&@FS5uln_Z3#pH7stFhCOWxT}M6fxY*N3^LUKp8^*ATaZWi3n}=7q)DS%-Y$KMvr0_ZGiJ%xCpo&7rBAqBFf}u>}s5;-s z{?Ag*p#!t9vWgLg2Xl?*SMG9(8;)ZUT{zFcI#~X^&bg%WG(S;F7{0WpACnm12$0&! zEBr_hz7)}qU{;dJP-arZ2(M(aujXi8aU?FA%XN<7OC+s{W*<2exS-((-lZLo%Pc-Bzh(!84Gphwh6eU+@SYNM{|s7^Xs-IS~@8mImmtYnQ; zH?`Fm4OAx$Q8y*%WEDu7D}T3Iz0tA!J5Qb6IBJqIC4Hwj$LISb*>s%OuhD@LpkJH1 za(V!-s;`dGICWQd4N(sb)F|~-KXuoYI$iBFO!sP`iW||Ar{@$a1pGfvPR z&8bzc`g2Ji8K%FzhG?9=l~kq0x>$Xbte)zj?m9`&Xp7@Kf77Mvt)A+qZc0{yhAUUn z30}R|Bel%Y`qn1?(gtd^Lqn-%>r)-CAsVD$b<_a$))8u_HX5UNwbD>^)Z5yuvYI>l zwpzK|&S6^NIBK`XcttMi*YW`hhD&2>||&?lQ>2a%NsS0j-PQKSp*S5 zDIG|`LJ;K)B4r(h+_{il=BsRfs1&{<@UmPz!BX2375O+zBqx8X~l0$ zBb`(D3=7Y2qgxt`pbd)*DczjKWo*J1D;6rN|8@wVm|)-&{P>eGBsQWWg&DkEGj@H2 z%YY-jP@C#2CNR)xn(!K?vzZYFlqV16LCzo!JB5T{1&a8UZ`ni{WFEm;(6|ELNrB3?qyodB5WyJXv1#Su#qB`VW*M|qOeoI za6YMVuwBf<%mM-!MrV3DGSoz{pFMndz7(t*@NRKDXXETA6;)g%NN(H`DAnXKC zN!La)nP>19U-J`b#1i88WrYAVxx#Bh{J<0rb21uBDWfxk40wzT<2rWo4t@mDla2%u z%48<9fX`V;4pxfzg6|l`71%Sit89cC=f(HAkI;V^$`YqS8i*K1tSEezVuC#Lc{rJ<9 zV9KauGa+mNU^hXu=6Uw>6OhO9gN!>hCHIDM8D}`wW47^tHx^NyF^&6yTtr*oLpOeg zed&V?_j;(Ge6C;$^Pl zU1stOMQkLUud#AC$J2{`yvPzBWeYx3;X@(8RAHeAU&N_Ey7#6a9CSP&i%=MMGMuL! znV@%^-o4#BH>~|XVG|u7pkXDCBy!Q~# zu$<}i1K>JR>BNsL!%iBpWD`m(srV5}1#QUYHl`8_%;GVZ^ta|=E&||pE@p#AeT^j$ znAJemckfbZ$k^CQG8^%86qXLe4?n`G#6mek9DhZ#9Pd+~avDpSMqSHU$v{5EzyRWb z-J}}Oy924fFuj(mW*M8{f8LPw<$>lI3Yx~<87tQl z4SeWEc@7JQ18bUn%HcPT;a1Kg5@^R&oWUC2CXHQmWj&j*5keqA4C4$(5#X7e=h6bx z;Y_D5VB=Np^YG8HJ1-E$ZfC9okUIG!*2m*u4W&EGtDB?t?Fr6jrCxJc&JW7K25(`(*iF-JK zFPTF=J`}Nr#VjI*Jy@gkenP0^S04*O9}% zJx2pJcJKEdrPwLmlUvS#Ze{h%Gn za%{KjBSpBN&rcUASCW*kYd!8=gl0)9*U2q(b*kkp_dFi!Axp=rw+5?^2569askgc* zS%bB>#&zy+M|-!|{2n57q@L9rrK?zWCr#`0oAM=Pc)<~}TKx2j{!&oQXRE%Fbf#|P|X|$5nO#{?jy){@}HCP?hPrcPkz0_T8^@wbeUiRWW{#(9m@E&g0 z!%A}O8KO?=tR9M1NP`+rlT@i2l%S59q^|0$!_`H{sJBj3j-*wZs@58#b&|HKO+8vV zDP7Xn3TuXIP$TBZ{r~uLFJZu&WVmtE5k!#3+BEH#<_KO~0_XvZ|prfVJEFflcCKco4Ib*yC>Ye+S8LB5i2 zd4gUwh0E>y#T5E@s5O#%NMb%asH83Zi6)3R?&M-V;wy3xp_F2Gyw_N%q8J-za}z$y z<1SB6s!_t}(ct%;xPx=}oGh|3wWN%~8XZXDyUC6eaX3K?;hJ5^O{?C_cVywGzW z4bkITqJjfPDwWF6d|jkyA=FvV>UV9>?|MhW57ObQD;?SOq!$%yK(B6*B+XEu7tYun zX|1iU4$m85wXW3=4ODw2X{fHyDoN4;y(~$(*Xe#-S1TK2iDv5s-L5-zx2EfBEz{mw zzl$pE(;s?O*J`vnE7Xv)Zl`^^&gpX>6>6QL>b*uIbfkJUqSH@vB)z3E>ZraNtK)RH z=4rnq=}Qe#FZI$;^->QFR$ui{XT|FQRZ806RsdX6rEkrfYQtn|rlz^{8$VrkRq6r7 zX|&pDfOUR0H&dFr5%YO4WCleD3pe5)4yA}Lh~&2SZJ#0+Bkn;?p-R73?NMUd|9W`Tw6-S_X0xjW3vPS3qFgZex#W#`5@=bn4-xhFoK=VReg zN{Sk)lIp3c$}2%DbU>T6OIwW|VSl~h5X1ebMmULw)z`BcE=k&=hcw;<^}eh1o|3dg zL#($7@QHg(jDWO98+Aens;dTyku*nFDoG1eR_oMXJ0%U%-Rdk!%FrxzP*ojLS0}5O zQmUdlYO3~Xqq+{!c%)n%(QfV4A??;CozMwoC{A(86)I4Q;uWJbB`Zc!tP&NYlZsWg zGL@@iI;q1tZuid^q61D=-e2lmwbr&`S5#jkb&(oNI;xv}m;krZ=W4CPdQG#nS>+X@ zY}HW{Ro7Pisu-oJK-o%Co=ylg(d{}<(pp_rqb0;t5rrf>Ly7aXuOuHs-#gGsREttq5b$sBbBc+^+y0D3>D%0l0-G% z1z;kv0iE?CaDc`UFTF3;XPZm!Wt+Vh5zo!+GPZt5EmQIv#BpE`EhB#ALZsSf#zR4I zVS$spZ@8R)3BZrE;#K>;PiTjj3KVjIhmw_`Ef@0|e{h(*kV}}&CKmDyqq)?LT6_<7 z(bQ#IMIPb+aGa^k1AZXJVQ(VUIg?S0<`!z&&-joWU>jd@Jw0ek6B<#MN;IV@wP{Er z>d>5ld}fRUr`zYbt>!%e*Vy%5(`(LgU>J31$YAPFpYAlE2Mwr7Z~g+{Dr(b%R@C8A z3V|_BcefN}sY(K36ae>ysV0Q}n{zM1*}6*7M%^7ypS6aDO8O~)s77VgM9WMKcIF@Y z8?l^Dp|-jh5h$P3Lz1LbdRpUT#!#-O#wb-ey2+CGKY=4d_h_02Wp#g%rI9MHp=zTP z#p#6h>qm{V>)Jn{)@q?a>S?Tf{Go?5Pm(lW=O{+?Jf^x-OEp#rs;fq7rzUEmnkp0I zdzqyAs&9B`?$c7u)no^ut~q+o#m;@0o=`Jo>SKMboqAr^E1Rn#sW zRs}Utva;1qLse6Cl&sRq)sq@;*xxlW?P~qNe~r5&mDdw0p+ddpX3**lLsVDtQ*E!L z25PYSs!YjFf7r2pD#mdyb*q}e3 zJ_zvx1-wiL(@N0DSY~|4!mA9950fA8u)PR>`V34s$Ox7OH@WPY>~^bpOyqt}0`sU( zWg60#yBNzVhwyTficODQ%no21chP`)G~;dHAeSlWm z0Io2iP3W2(#cm82mWuorlo z#x$TGwP{XOhR~S4RN*#qf!`TSO?uIgmNcS1OMnwJL`-l_&7n=O^e{7cnxV9#I%Oz90%?5a@&M1J z6e5Xv7zJVOC6i2*dCKCSqi0t#8cpFlRhF_Jb^raWixBKv@STtjtA z@FK94(JogKLwOq0kuLP4CACbl_6eK~?ABiXVy@u{Fqj|N#4h%-fmQrUTZHHioa7=Z zaX!g(qYgu9t^MHsKdjX$u^cU ziy2I1o`doYJxt2IzOl&kE^(G$X>dG~KLcz4;74lsyzZq&eP8Z&|4kGC z6Da91g;La@BR#l)t~B<`-Asr&yv#8GGI-4G5v94o_~7U97;%Us-T;pAC^e`@UD`YJ zG7m9^!PKEVwHU

<99h$XV2)3lB4x;Z%>{-Sf^qPEWW$nCNhJd1}*`N|drY8r=b` zWeD}C$RL`~h3Yh+0e2c7@~0@pRn(*&=hBHL)M6`;Nh1&CdkZjk1own-@8|F!or||b zk-j03W=)m=@P7fHITV0fy&iKtaFSoSnW|3PeNE(q!uCAD3=TPXM7rW2uh?JFMCNkB zAqspbtj=rz#zx$--5b-mi|u~D{=0e5XHT@6@kz_(29L+sKDrOO-B+21S;}s*$fS@g zjj;R8+O{u`GA*WEAqZ^)c+9A1G~7ID%7S4jd{^1`&^!)C$*?S3ohk* zW3;)P+o?$#Ze$x7CXVo|U~jVgzOOcTf9u}^CewwcTue0@(1JF!=MuYR*^3OM6n!{@ zdNidqZI}%l_GlY)BVewdZb@FSPrjw|Cr{JP(U0cey`Y+)H`Pv3mUgL>*99+El+@jl zR_kl8M@`TYoz!+0zqHxe(X|isKn2wA;IIh<}shpWU1hqv3kn;hyc#Bl^-y z2@mQPJJ}CZgZk$n$*G7+=1h z861H3=+%HPD_M7p;ZBYNZwFD&EN2JD$#v+TAK*$4IhLXvi*<)^M;i19^c3>@K#{oW**^alN13gb&$!fxcH6+#NC0I6sG-tYaTX z97>YGqofr(qlLrV@);J@d`>8=q8q%CrG@=8IXhv^Zase+GzPv~Hk)brA z2{$o?XNhmMnY=&1emh=9TB15TfVZi^*)*p$ExFcs#^-YuHCPG!N&{-piS{($ zYj}R?(BXN=cH?B)zIRewwZQdKonC6!VI#p$H7bws0B;_eyi5jjum85*F&^-ODoyt@< z%0TgsZVvE_3-p7>ea$pS<#dsLQ<`chRv)XOVzgFo>T4a7bcw!^v_hAvvUVs*J9WKY zk@T|e^^jt+{#H{J>U>QJu$=y(yt?T^^;0!TQijGy`fD2<>}@xOI>Cp2_|rWDz(oP( zQjuu@eCD@3K}p*24D%g&b0^utcphdL?I`2qP5Uwc_Xk*}7=9){L~X($hN8!3VOTJZ zE*2TzZFKSn?M@z$&(C(9$iP{F=Z&!BFv&sPF%%9a512!Jn$U#CG@&J3X+;AX(wW5^ zV*;1bjyiN?w6Ttm%R6+YF+CX%ycEH@_RUuU?6)7Mg_qRYlfemkF@*oI9w=lHH#r!@ zCh`J>zy!{uG<|8nQlP*~VD1n?HsyYJt^cMb$Nh%w(vfEikS%{@FoEBd6Fam(LgT0u4NUl)vKwqZEEZb%WEQm zGkA?VB6lmIj};kh?<3D=u!lxCp7B67T>?tG5Dvc@`L-_TZh&61arl*vS$0kq+c=9kr-W3!2cD)^w&Zt!YAY+S7zl8~|WHA8`rw zXw6Nm1hRN6s%@Y|k-m@rSW9VY7#3boKn}-Q##u&c$;@XC@ieCw6%jS5NHVd+IEQ1R$G7jYl+|S!4%k z3R#7*0374Gpw2(NnZ&mMtoG=;dY7@>?afTl7u&EK2yOvhh*Z9CY0?V$AGK&sC)(4R z*0iA+?P*G9+R>98z*?SV0QKp{Xu~UD5@$rPru}1_;R)@ zJarQ3TM~^t*De*1&TB41(Hg7=)*4!X{&Fag&nTbArE;gyb2`FjbPJ--*O}eGaRwLL z^C?HDPHRpWP0q)L>-BGB2c>G+%kU7`#MwdB^6Ac@Mkm1iILXGx0LWrc2>Cn;z-B{} z-xE_k*l09#vc9q5cB<2owsfL3?PyI$n$wwXw51dGaV5QI%GtcYIsoQzZd7_3yE2wZ z0XFV4NJQLZSo9a+Q#T*$Gu@v5w{c`c&fzTXW1i7yk8ykSZHNZ!2MQSxo;r#2Es0K+ zWF(u6o3fHC9A=Z>0rCP~O1+ss{5YpEKLAj`4{pZ{{&5ILfW!24+FG66OhF{^8##PM zCh#}i5Yx%>=u_wIifoO>FBTYfoeoSioc|iq=^Npc4lgF(zr!{RjgElm$9c}19XWG-6HngEJeR+9#SVs=W3ze(l;)9Kh|tz=zwBWSyR+O zdD^9Xr72%oij!2JMCGYKC6%Y6O4E6|O3ftwu6Ol=@`EgO_)!qB>zvIPIbAO*PRWW> zta6m?R`Pp}hN+pP3QAEOmC^yB41M5~BX-xMM-{6Q+O5XguXH7;P)oH*OC+7pR&|n8 zCD4lt5)t{zo-S<4yT<(Y3ErU}+kxelsB5%iEdamKz=YIpp%7SR53nHKB*U1!?@k_* z5d&BbWO9N-0R>a&!5;t|=JKd_Yq5$&I)d9BYFNnLcRR&cV$sJM)S)%)!xm^GRK^-BK>p*= zpz?`xbC-*k<<$S3c{>2p!t>^YA&b+TJsE4n;K>3`(%*tSIvaWwpZF~q<%>@OFvA$k zr?QsW#zIj7^EpNXM18|j;D}2T<(a8GVpxbQJ`I-GtYdpa#iU4^q!itGlF9tZ6s~u< zha-$np(k_Gc+TQxA2aH{*xN}Daf*lgc`E=vQj7XDrwvW$Ky#YYfv)tRCGBWu%(L%g z8Cy6^1}E6Z-4U;Ee;CKO02}x1e8zCU?9j|(b-o~*k4#E!6vMokUWV_oPG@%GV`KTu z3I~LWECgVTAAJJ1E?6!HO;EvSdnhYuLd zLoY;a9%nW=4vohDoQ`d1=)8Mcc)bHCE@Y8RnSflvTJV{J6veM@R#D0tW|gl}mqs+D zHLdANE1J@gGiXgaI?|ly*vA3VIm!+;8PEL8(`1D9D#745a~a1o45PJIsW!8iOjpx_ zPkst4cUfI?p!FB?PvPZk;%f_ReM=f9b>mI$L6kD=exE};2lPY4(2eG_BZtZMjV1a4skQ~e%M z*?6^s-N)Es9fi9AIKbI7qzCP3Nn6^`j^?zcHLYkvE1J`g!3^g*-sWpo1F$XxKilv! zxW>H*1srD?AM+yj(1!Y?1sF})6JsewRXTGe5AYIWdD~~$7ysFc{lEcF;eY;HQ1usI zYPzy4&^vrs7fV{9J4}u=c|v!nf(Gb*)mCR6(rQUHHAyGbMJv@y^|VEj{8+k;*Oj_o zjU?shTRml*_wPk5)s-Zz)jhgZNs^>|t=DQT)ee2{5+S$12wvDkac=5*u-Z$K);Mh~ zshib8E%lPywqmwG^N72o||rzS6bx_g)eXsI5rtkEeI{Dd1570g8CrO&Gm-W5rr9A!6 zL=`0!sDTDZlJ@C)P0-&S8=qRP6;2;%Gyrs+0) zp%_Wkb+6`Xld(NXZ>zPWJ$ge0YO1qTQmJaF7{x1Dr4*|~RdlkM+NnP^MZb6z#f>(Y z69HJV32Ilc|0+(K4wDhmS0^p8f+w1U?k;U;?EDz3*nSU>f`op zPXSQKO^Cr1c$k>T;V>JS%#)lQ#qpLrv%L`^DO!<7PfM=5Hq!z4!qpcd(l_Ma&8`#x zn|+3H3x##KgG*dQy;4}}hmFkrlTw)B zMzcM^VFr0I0|F>rOM9TjDI{YHpKWW-KP3iHk5AdicDAvNHLT(frtv;^a}{UO%&i;L z>B0tVv$}l_5zkw6<>id^wb{;wtC7AT|7OPW4G_3YuNiy^?~e1rCd8D@SSJ<9|0rHC zUez2A;Zgiyf94sf?D61@9A{__0_^660L0zCGS1pTN6Oj_1b=m~a4JnjDpHYDN|6w? z@oocUSwnz1dNIc`<Cj1HEte=wsJ+r0_` zhsyiO2NqGQXiKDT$iJEQ0`P7`@-D+_j`;Yjq_G&7{Ez9`nZ=HVQ`?Ck0!CM4FdrJ{ z13cyR=om&D2B=2jSVzhN4QbIxt3o4 z)uglY)CVNex8vW-Bz_0-Oo(3^C@atm@h0A5ND6Tq0GEWlgwf5?hHW~07l3DJ4BdEw zU)W)P)eCvU4_oSXOmLB{${~|{V73RLff9yZXHhPnP}bxcXyh=(6U!@}?5xAi!A{O( z(Fph64(74Bqvv>}Z^yrv9moK-1Rx$Go2rb;iKamNHx8I3zKIc)JFxMUrwFrL(sLc~kH7?=>rn82<9OgL7c&V7L zV|5<2&$0td3nQ;UW!@?@3i%@{U1_ z{@Sla`eyuFSrqKy0>6&#ZKx1BV@-%E6$62(Zf0B=UT#-fd9ILw~s@-ydpk=p&9 zEDAZuYQEtdH&*RJRN)D}4#Ih;I)izS4fe%TfMwhjqRyl@CNq~cM&q8q9}t2`sEw5w zz$l*Qe!7G>iPYGLWEQ=6EyTL&1#G94KgWia(SHn zoS<{WYb~1Cm_r`!OAZ@&mwV_%jR0h09|GX0TTj#k>e7*syv)z+CbQW3%U-_YX1BI8 zRxpN1oHRNX?a5|OP;Pk5`PyjMxAGq6P>B?(FdrBj($q|usP|JH9`YS{7TDq2E$u&5 zNO$O{hT5(LZsRGMgA|pJB*pqXGEL1r>`7K?h^6>bTh&)peJE1q=pA)Zif+`x5cB&d z;S81YuqROs)lgEl_GyE5X}#@h89vy>|-UxZM)qk2`JC^>`_ ztVU;z3o(V)b&gu;Mm_5Nu>Tr&S2WUd8mN*g)bn~Iq{qw~@)aYggv$67bWJl9x{D*$ zc)@}}vToL4eXd`0qx$G;A4gBnb?UAW`bcww&hejy-iq;YM6&9rj--*24(Yfuv|0Og zK104>ch-yQA!&zR*GD?;uxGe>NSYmD=_YBe&I&ONE74Jj$_*)n1A129>Q;TL z)n1Pad5G}OVoer144|xY7Oui};Ft%|C`Xnw!lSu^<9vB}nsXMzIhR(H@tJBJ3OPU; z{ejQ@DDQdX1D{$}AEz5D8PP_AMFz*oBacJu;UGsi-8-3X8(}=+zegeGZ{h0rH?v6;& z+eQy6TYFSbLp8;soU(OHQkv>%iH{>QwOyS(?6dXUD`|iRsIzJ*L6VfOwfanBocctr z*rU-(QkMSKX7yD~pZ&kzG)KL4f!@$kA4mQ>(9(#;6fBD3@{|wYoFlqae|f#D;ldtC zjU-8_k}{O<=XuTbjLwtvyB^a#mwjdRvKlE*Pnr< z3Gq@4|26K8xLxNeUt3jIpK70;P+OJOF-vmFG+xriK93x!As+WtQd8ZnfvTY#t<(nX zRF+~?MQ7<{Rnt9QQq9%llB7dgq)XLJ-})%U3B9LYO4D_^)n|$S4QOLxurz;BQT6m& z*mHG<-IDQfE0Fx2Vz@z%sk#p9X^km1kyAn+>Ox5$XuKq;jk>9)Qng!O1~pAHR`oU7 zj}@)RptH~S%{R7dsLv3YCJYe%DeO)<@CFrWgUxwolY>B#*?b>>$v%eH133ibyLDoM zMH~T+^D_OYOC>6kM12M`2bkbzIWEFKZ4jG%ZF&H@;{RO6FfqiTd2Uc=tuQgTawx1v z7E=*oB=D^tXO!n704BRNn=H>{049<^5<{5kAeENuQ{K+gJ$fg^dt@EvTkMHoFbr9o zCM?MuV7c859Do(H^s^k5 z*}+c3YS}yckqf+SS&f`Ntm)!96h0IW))xt;u!?1rLR^YJ`bd3Q4jklWw^sO74W*uG z)ZtRQ;^sQO;&m1Rn}eK%kL4{2BXpm^RCa~2(?sPXd2H;5Z0sh(E#xMmqcq$mczm|i; z(E_+ds9wqDFqTOirZ(byY>j&|<*7*n>QRx>Bsd(K$ekPlW_VCUX=xY?%-{wi@Zd4N zU@)l&(TpQx(9h^>X09IS5&{2jJ0DSE62%DPv zPsU>|D)R)J9UhR0w5Bt!7gHPrC}clx`HYfk<0bgx$|OW54q&AX(dokHt$p*o;?{^? zy%5g<-4H`4WFz0QkOO3pNd|{m$1l9Y<%XM6BaX0?%RG3_b~5~Yck&mxzm?0TOWmRvHBbYc)Nbuk zzN9o&Qe*Yg&Dy1T`awUbl`=e-C5+GusxAptQ4Jl|r}|LqT#hKO-P#&LNq^Q~x<@yu zYzS$Xk9H~*uRFBTxLS?A0Zg$p*XHa8JjFzR0m$YuH+zNv$GC(RbfyVc zaWUO!PFvd3fL09R4DMh&JAr*Z=F)G&7LDnByv6b?Vg))ekaOv0S(x9`gUvV`sSY2I zMc0Vefat_YyJh}T&ZQ|8C`Ae>RG?;hfy6xU z%&xrV5W*z#*y`t~IwV@2!D+$&0f!yqh9kZP{?F1}PeCD(*g@ssen=sG_m0WxV?mFNwEfI-)2%O+T zW6vwVSDZz8I#HPx4C8xN6f>>c%=Lch1KO6pYO|aDZiI;9Xvv*SaL~x!!S&$`6c&|y zIXrK_M`X|`qSxQhkf2Vd8L1p#g@?Ymjqbcx+cD36HOm<0_G49zIe^*kU~NY56>rC|kQi@Q{d-DEO| z2K1mV=Q!AH6mWt=93qcAppd;h7Jw$_umJs z4zuiyY0LoDGaeX%_>1j+8PcBOxoj}5V-KS|m^rpEOd{WOvb-^e@zmfO%m*gBRCOEjIYI-=b02EVT<&mEd2YZV4j7X)WtjtHFaRMQ047kL z_SB^j)fvSfOyn(I=2qHq5f{;%etg6x00#M8jvFX)MrpuMzG96BH=C<1uaRhHTQ?pD z;YK74BHsrNaR!~S^*(VlccwT5 zN{j>!SQ6jXi54e+8gKvwRf2dTc$7%IG_I1 zqCbsjNE4b;lkQZe6?btZ_wzB|vxcKUb^s=1%{j(V#xRS0ULVOtcEiknD{rv&o%a)0 zMCj@Vk_}vgsK_>!lgvxxxmd9GwU^R0wrVU-7<(poc{cAhKA-<*Vbg94GZI<&7h*F6 zTAci8!0&+HibWKE7ps?3i&)7XTwt-iCvzhiZXGvTlED@_QJ>D#VK7bTMnCT1Jyx^T z=n>hF#h-rIzleA$(1k~t;`c1%-vn|Ic9^f~LIrtNR z&Kx$i%g1h@J3^FkvD_)*MZlNTrZG)vMSWV+ie<$fnw4BlTOZ4*F_h(8o@EMK$q(p} z3`F4dpT}~n4)vWj1-YCRfvdj=I6*t(*Hyr6oC93%a$HM3W*sNNCGu{0F6Kfnkz~6V zGwnyh;K6xS#O_@YtTnV2QLCF4E?lNGZPbr0TkEThj%iVt%CJ_q>wqMwp{D3TrRk_v zxjnL-q^)YHd{tJGQdFR3YAq>Gxyn_c@+3)h)kj-BX!RwlnaI5i_ z+Czf^I{u%94r&e;dDl(M}E4A?2u<%aJQJQXTZY%IL$lRdtJF^0lqz(mwyL(atC|XxugbbuZFHq(=@X|j z%c`ZCsG+*6k;m|G{vlSES*CIy{b*@u=0_f9s=0?QfK{lZ_L4re|K6)v8m2t`=6IIVFBgRosIG*eY1mD6S==zzAWrsDOJnrN5Ob+^hXRZ^aI zN=i^!)lhZyS7TLDbJOniV0G1elhQi95U-w*E`l9pb-nHkYmN<7P3cbZ03YfKba03WeT+OM=zw}_t;^A^G++5@r!CN4=by-aH-B zEUnW{?bAtB*Cu7FjMCLuiE64c>Z>|RaY~~=SxT{VMmAkNe1zuxXQGS#h^n#f{dzHs zxxJwK^s~;E?N7JKf4I1crU98%Y3bb8YbXe&sR5?{r8O7=2Vokf$Ln)f4ZDB8|Bu&*E zov$m^$=-ucP*q(jNjjlCN&9q2nW~`%O7O589_P^ew+3Z(;lHwR9~x!v%QYHfW#iz2 zLgPPQsHo3WQ%~qgNm7CC*RMKHwbVy_RM9XUu;BuoD@j5h>8`M9UDk_&rd_I|RzU?3 z^b^tbu$qn1x<^;5rV6x3-)fPz>VSO~J3+~cvCHW?Vz8uN!ZP#c4#)JFzEw+IuCr82 zsSbN=O?Grhmk!hWPOs^|0VUKm(nWAV6ZO~Fu;o@LDNZpyd+s-@rlblE=S|miNndG* zOLydZqjCRM*PB{W-)Ir${M;i+9sXi@K=Sk(AD!*I|QmDN(xT&oM` z6**e0#VW7*I#Xw=wyId(7Y`IIb+O)zbRoiws%jAFA{4_Nni{qqZ?2@WD(O{+JXVkC zaZT16T3Kx0L;6Msowj_V5js;+B_%1x)Ux_Qt1cG%;KLr=iW!3sJ5gGb#hqY zk5d_Cdwm@SYl=3gW3i7xwm(_zvV1;_=XoSlUUR8~AhkTojDm+WG(TlMH7zK*xhcadd0F_a*cG`@_mcOCc>-s7Le zPa<96ZZX-TE5F(7Odgqb|I|~Ar>`ME@BpyHqa2t!#_%}+KZNNTY&^q|+O{Dlf?>3C zX>Q$h{xdyP+v-zQkrX2-$H88`qWY-1+N-66;;-$xymY6`VlAL?5#bMAeWpkLjXM@Ad=ht+@9 zJrZ<#)Hvf?k6tPh=^}W*d13qP%#_r@rLS4TFe;3bl&gUOi(6!Ax}>58Hynsn->~K7 z8_irkmL|g1q@SnP|1okA_aMUT2{$p~Nqqm|lA8Xg6PQofMuVpJ9xB)Pok|6G)|a&9zaT&~Jt z$tOc^N*d-gg|fs+ZANPB(rCu`oDCpze7@cm6P7h*S5leYN#BgU5;!{4&z87nbBmE z$t%=$n__i#0=p?2mhz{vCDOOb1)Hd5&9&Nk=zFzP(pgGTx^B=WNsk7xFcMkB>0t*w zi&Mzi>vFvrroKdQ*ca&n7^th^kuHMesH%36E`m>78K%ip^pI95 zP47EN<`(LRj=3DUU9amxO;II1s(zZSyR}$Pt7fqjD=Agd7O%1f=AoOL5=0i&O`Gy_ zLDBTfEJ+>IMAAlGr(=rI)4Iu;EG@!Cy1>m=blAsv9gM2AP0CDHmZZ6QQs{a;8zn31 z?huY>HU8mBCwa4fB089={f(@ccOR@?7NqJ9+jP6q)llPo1e-Xa`*oSx>o;}N9G$CM zl&Oa`Uk|#hXw_7jq@5nLp3Fv%s52Nzwn|yPsB!;Z+ZAt^RL$0n%2tBj(rwmcY5~gY zez)rc`9AbdhUqtbqLPxjshy756)xV?Xi4{kRWCa*>OxH%>!Ts2RFL`FdA9^qflQS^cHa4h>p+#Yoy{Wr6KTR=2R^ z6Bw*AL$}Y+ybJ84hVknT@_~GA56e7Q==`6D`K*)l^mtA@|DynaM-VRp(;W6D^C|$Z zkQni+bH@hk3&(_@Uzi!Cbz}|`_$ksA>=&}=7RFk+m0aL&TKGJ&7E^$asEiQx`G6C^ ze%_=lBAF#XKK;T{>Q>}L_9nT-UzD)oYDEtc5TXycz-{(j_W_W7S~TyC*x{kt(rNAC zoFv`=wsQ~rIKm*71GhLGk!DCmjiFS;udq0)urmygoqx!tYsBlrIyUA&q$}7@yb;!V zxss#62F~(%WNBUkR@xiz&Ws@)$ly~RA`|$#*mA5j92L>~;|Y%9h9*+v@FnFDar^}Q zO{%dgmgfOD$#r3=_E7km$7%2Vi5Vj4fdTeya+%6qoaD*-Hsz3t8EKa+@8~rBWyPYib;l{+qZ6xE5~;L zOrcW5uhW?^{A%qJ7ZCRQF+4wA`Cz0gHvrrp)|#oyQUD5hpYlGBZo&`1Vh1D2X8dB5 zdq3~e-*RKf22nc(d&P?D6>EVV)J2GKz;Y_scgOGy0ELVTlND+({M1XOEhfe7Ib~T1 z3^9IHV<~W<+apUD+UbALAmUf*%x|rI-U7s<5w8zxn8>V1S8V`TX_d{i8=lE3hnyGF z*XJ1}7{y-T4P$Mu9;*S^N+tlSd75t4%s(T<_2IuEeqs`F=3lS42Y{y$qAn}!e;4ry zL&|=d@d1c7It%X?ue4YX=Zyk>wL2>HWV+FhFU~Y$a%LUfBYw4xj21U08#Yii;x%Fg z8%1qz&pjRwORc2vI2kTEXE54BSIUvi`4QO4H8f)$0Ly7i7v5nz0J+TP3EETAf>KWj z@2v;`n;g2-rcsn-IdIfiY41uV*_`ck(Cy>`@R!HM$w=}uua)+e$MYJo569km4UeAz z5zqetu!nOae!Zu7x5W=!posppnP7Nrq^mVREb^m)4VA6<*+cI0Ip1d=G?^P%55{Eb ze)}{{bw=<#hXKfD9?x^8sq+Pm+)xXdRvj^=aH_~0FlSlmexl} zZui0_LKpxM9Vc_Q-p~j zOI=1O-Z+Hy08FG}#IIfSH(rtGL9_-I51wcE7#T(*3b@FUx~R%)hVkM|BgA|wUS*9j zXnN9SYf`& zO3@!z0olcnO{}ZqjBhuK^F`M4ZY(vL!i=5$)($>T}h+`0c z7%Bha)nY6Lkw$M~sl?TM!ZtVEj}y%2cDu}pjj{CQBTfPvd6bqelQd?q3hOMXX*1E^ z?5jTYXDSl`_`%0C#pT9wN+vHx)Ga@r?|oL+OFmN>3cv>e<($kjxHW<`VmAGG#zMhJZm=ljOj9Pv zI`E~js+G^DH1Xq%5r8{)K!2x+DsVN^$pyCarq@}7Kp1Clv7#B@n{>5yx>oJ?0F3uB z_m#qZ#!7iQ4+pRyX&z&YafUbS^C`#EoTES{usq-;(&kJ6a=A1DS8rn-!|fv!nBQj% zWPv)``H<H@8p@L4V|6z9tgIQt`$*++U=??ejW>5E zPka)Hq}zR|C^gd?67rQr2jiJ)X+3SE9Admhsjv26is+lMbmd(R8R;xwq~HDS&g21$ zOqs5YH8ITP`xe!)xyUkm9;EoDvU~x+YI^%PxdLw*!`58JhgpyANWEHl^ zvF`%~3=OCRx04SnjG$g*q9NN9ZI~Rf8ZnnO*lTG$O(d40i3}?cOt&M3_IzVEFy6v_ z#XMfT(WXT8OvLY;>wWYj2p(-1Y3`L54>^^tYc)qNsF^0|IlZPFk8wT@>2{6RbLy%D z4OI`lr#F;tQA`n6wDEbwF-`Yz#9%d7hQ5*Xq&ljtUeijg_cQ++^@8HGS2q-k92q_o zMf52&HBM0I=&E-5JJN-aBvn-#)lqdNs!)fNp`$vi-8!lxUY_bxXrl6#mTtZZCC$`U zi^8m3rZE9U+Ktx`-KDlFB}v+@clBvN!5k~;Vo90yXlBuZ3!*M+swbFTPKTC$Ak%o% zP?hV%Yyf_uosaKBD!1BuIIFnI#KDxeJm>rT3QqAcRg}bRV65@0A4hB*FfQxBMEsv83FIrkh+4M5heGSGUAfKYVHj}UDBq)^HY@gZx=DmkG3LOFw0ycP{$wb$pO|Fizg}E$wnZH zx2WYKnTC99e~td+M$2z+b3Y`2d@XdIOCdN+#n@!HKJ#PsU=&$EcEs)6Q;o(w`mokC zJBQ$ShTk&1ne1ROlleccp$l~#CL!XOX=N3$!@h*y!7_h^m43{-C)14&*keCu3AY60 zD;dY{K=fHlU1w3 z{#fSI`ei(@#6d_Qj+X&f!Q9_s z(;WHXOyZmyyP7pn%~X&x++)P~eZUDOalS)r&&@nRiy&TeUo%g>dhY9e z&KSM{Y%O+F6P5$%9wMKO|Og+Q(!ae1s^S2BSUeme1_kV131 zaT9MagH;aAowdkw63;I06w}CDxc1$vaVa0M-QGYI@E7+6B*5X0z=ZZ@qUDAYwv6pmGT_kafq7c)quC1O?ic#My9(N$Mv+QD#-yf(2cp4`3_>A`}v0J zXc>~ZWGq#vMFWq0_Z2=@oKsi~eC~1oc^m^)IJjl?HsntCGT5w&H-R<$@Y0PWMn$An zI&&Dv3{kc88jI`3H9}aD#kM&`C}bNSaFt;&VHTT_4y1?Kk^2{`^_H{r_ z?q<6Eo1eoj7VsVK^C~U<%p!%(yvP!}4J{nyci!bT&I&N3a#=cY6B9YWR_YkR0bQ}m z51sW(D5TJ|r&Bf6*I;!}WmQsX zC8|Itbe}#5z*j0&t#z(?sFhOe+j4bK+q6w9wNr<6K!5>%ihr6@t=R9Y2O zOZC)7^;A`fk{0M$O_g+q9#=W1Tqf!PZS+x+Wc{Sxnx(T;;N_^Z^@%EJv4-d-J)&4i zQ*?*61#rdIql{hQ%KcfH8Q_ocC1$)?RD8! zR)4CY1$pIYy;f?rmT8SnT9Ce!qFL%7X}HE)l728KsR`di~PS$RIM_#91@G(undIIh1wP;D(&Qzc4z zN28SMGwtx=Y)y5k!)U`~ofnaO2kS#sHvV3uuQa|`Q|cXEG{d12Vm{KfPFdQgOzl#h z_G+6>C{qvVGShO%)iLeVBF)ztZL(M*qpyBclGf==?XfhUKya(xigXcz#5#2~OT@)@ z<6cTr)l1S2ZO|;O)m9x+rt%acDPAR%rdq14t~x`%=nhFzTm4VV^pe+98>+4I;8d5q(xez)ozX{p{h#MVIA~+v67_kbdgr5yE1$pSzFiZLB(pf zp3~cYrXEh*ujeCO1Rpq}u70can2Qd2R%h8ieOt6x6E#QjHG-m(hS9`v#!zQ%JM1NwNV=-eWf@hsIsamSyfe0 zWR+8h8KZ z+@&(=sE(?mW@@5RMlZWSc{-%E+NQs>URi3d3)N3~`b;lJsK4eLZ|PQTS5NKm^Y~al z`+DI=qGqX!X{kM}OVq%$)J|codg!nP>H3F?x=5F)i&Gcoq?T&7e$^Ts@Oai@)v~Zu z>or)}N>mG#Q>^N!f|8Z2LS?H^B~)4^RaGUFtYjTms*Wp0IVx0~3Up9eLaUUhgG$#i z?b2=?RGzZUnxzc_wh55A>Jz~-IO7b>P->(L5dvPw{b5*NmWvs(iEo{9aol) zs)jnMh1#pRQnXuN=rgTT86A(xMzNvhsiHp7$VeB&1e~GCs$^Pf=c$dJG%YnpT&>S6 zN!MSLQfu|ndFtRKjGU$2TBVtqscpqZaUC>UB`qw`x4P8J-WbIzO^J$EqOz5u6O!^( zs8|*1r1BKw$GTGZP*StiLDE(FJkmw6<0})_F5IEOVZ>zxe$^mzK9s(vWt@@eVlh%) z@2Q=RX{W~ON6poKwb58@*ZpP`&U9R)ijv>6^U;lwCN}NTc5Tr8mNaRX>zjx!MW4_- z&C{Fep>FD_R!Wm(TiS1+^L1S7^oM3>l@8fUd8VaJyR^pZUX&NXu}+}qs#cP==$A+r z#EwC_(9-nRs+OgT?NSp})^0Nr3bb)|#Zg_U%G$1-#;b9Mo>hv@4%1RjV5q8VB+0M& z_Gm{vooQlfIV#jT{ivZPrdfm@Y7qsYJ2Ld6epHfLs*}!A2URnAUuo*3PWqqrXth>p zjn?S6`dM0%T>Wlo`r*ZuN|ZD%pr9aDqKuwWvW4mAYP@cs{4ROSM!t zwNiCsPc>CjKS{YdVezZGEo#@J0!MuflypMhOG;Lvjz_vcx=bA`O@FPbn{^^l2anuk?KvQLcGdtV5QjA5L7VijscSVo7)CD@*&#{-CDrmLwHgwzxY% z%ZhpUn2+w}Bok`S{S@xebCMQnq{FKcP3W(V#$Ts<&%K^rQ(03}+@mZ>Ir>2TEr`e3 zRA=g2(^Cx{x!S0W`bMQxN8Qv~{Zv&YERRRK+~V}Zhmtx+Ql36gp`^;{qpI2((Gopm zjAvslx{F6OQ3YWbpO|FiY*r=Qsh1R|rMfbTywn^Kud9u}@*^11+6+|D8){;5nne=@ zGqu*_lx-MpNvdYygjVT&-J%}qt+Tb#;=E>AntnLZPn{(#Fs>+FDHaD5_g$W=EY4w) zRtk?MwC16*DwvUsIgR^py{H(i(8WHLT_S}p8esgDAB5IO^q`@}X|U<37CC7h)yJl% zElFqDM@`X;eOjzphM}QV1_4Kusj^D5cB zBy$!!y`qjeHEBlUezrbTqIT)3sBPM%>+BwYxlyp}6D$VlC-pEr)xBC^|N9$D2G*&T z*x^`#&T1@4mTC4>({Ea>rTSejsFy`~ga<8kmZUxQb(#$-u;AJBA0te)A9IIAnlC9F z)^>@}(ztigM@rQ(U1!b;uO(>V(A&kU8f5gMj2_o`Q*C65u+pJH->Y#JRFjD$u6B?HE{HmHN8d=%HJYg>ENXb>JJ}X|VTsLh zWBasNG$UE9ElvNVZd6YV)t&lWJC&qI45__n#tjVH5P8aA$eXKSX zrGL`JyKuE75>PR^Jj&&XC8>!aG-efcYOLmHg8olesh`$Ly2NtpoKR3w&*?4Iv&$!+ z!XVX`G}mE5Pns=7NJG7y-CV*te60P(Ux$??Ta+W~P~D6r)zBWTN7YZ#n?B@yBaO3F zC(=a-66JJ>zSmgwv@nltTH&(gD@(>UJuUk@nTNJ2ZE5;T9W1rhYqg{jO0+b`P|#7+ z^nl`(QOv$9PM1h3(0fi(ob!~c{w5k%`-=oUYPl!HUQM$9eL&f=dV05t8QqLf8u#0E zpQPz}Ec9Ynh!QSe_1FkJe!-xwZq;OcqjN2g;&sHdVoqIijfEp~k)}Zwq-riqavt%B znGS!~RA))sdSlRfC*6cb z%Qj5D%*MHfXjil%&0=eh0w>9^A*vzg=019GhJMfss%re2UhD&Ov63Zy>hk7iYO)e7 zmhCEzx?%8$&vJ^}mKzo&opzxo5p3gLT`#MwGIVD^p)$gcIE{4q!p2$L6Aldx^ss)? zj~Z>5d#w&$|n2$x?;V9i�`AZee&U_V-rsz>#c`bk=< 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 mS@lwymT0vJrT-8ALi|5i!t#A7Fjcq!0000Vob7 literal 0 HcmV?d00001 diff --git a/nextjs/public/notionIcon.png b/nextjs/public/notionIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..c3951a8d759987b9ea7cf86c77d5b0118a2c3edf GIT binary patch literal 142554 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 z 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

<|2%g}Gg%3=I; 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%0A+9B;h0E%UCve$vuuo0Fj6Y>aw3bg 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/nextjs/src/app/globals.css b/nextjs/src/app/globals.css new file mode 100644 index 0000000..5890da7 --- /dev/null +++ b/nextjs/src/app/globals.css @@ -0,0 +1,321 @@ +@tailwind base; + @tailwind components; + @tailwind utilities; + + /* Hide scrollbar but keep functionality */ + .scrollbar-hide { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } + .scrollbar-hide::-webkit-scrollbar { + display: none; /* Chrome, Safari and Opera */ + } + + html, + body, + :root { + height: 100%; + } + + @layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + } + } + + @layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } + } + + /* Tiptap Editor Styles */ + .ProseMirror { + outline: none; + min-height: 200px; + color: #1f2937; /* Default text color for light theme */ + } + + /* Dark theme text color */ + .dark .ProseMirror, + .dark .ProseMirror p, + .dark .ProseMirror div, + .dark .ProseMirror span { + color: #ffffff !important; /* 완전한 하얀색 강제 적용 */ + } + + .ProseMirror p.is-editor-empty:first-child::before { + color: #adb5bd; + content: attr(data-placeholder); + float: left; + height: 0; + pointer-events: none; + } + + /* Dark theme placeholder */ + .dark .ProseMirror p.is-editor-empty:first-child::before { + color: #6b7280; + } + + .ProseMirror h1 { + font-size: 2em; + font-weight: bold; + margin: 0.67em 0; + color: #111827; + } + + .ProseMirror h2 { + font-size: 1.5em; + font-weight: bold; + margin: 0.83em 0; + color: #111827; + } + + .ProseMirror h3 { + font-size: 1.17em; + font-weight: bold; + margin: 1em 0; + color: #111827; + } + + /* Dark theme headings */ + .dark .ProseMirror h1, + .dark .ProseMirror h2, + .dark .ProseMirror h3 { + color: #f9fafb; + } + + .ProseMirror ul, + .ProseMirror ol { + padding-left: 1.5em; + color: inherit; + } + + .ProseMirror li { + color: inherit; + } + + .ProseMirror blockquote { + border-left: 3px solid #e2e8f0; + padding-left: 1rem; + margin: 1rem 0; + font-style: italic; + color: #6b7280; + } + + /* Dark theme blockquote */ + .dark .ProseMirror blockquote { + color: #ffffff; /* 완전한 하얀색 */ + } + + .ProseMirror code { + background-color: #f1f5f9; + border-radius: 0.25rem; + padding: 0.125rem 0.25rem; + font-family: 'Courier New', monospace; + color: #374151; + } + + /* Dark theme inline code */ + .dark .ProseMirror code { + background-color: #374151; + color: #f3f4f6; + } + + .ProseMirror pre { + background-color: #1e293b; + color: #e2e8f0; + border-radius: 0.5rem; + padding: 1rem; + overflow-x: auto; + margin: 1rem 0; + } + + .ProseMirror pre code { + background: none; + padding: 0; + color: inherit; + } + + .ProseMirror table { + border-collapse: collapse; + margin: 1rem 0; + width: 100%; + } + + .ProseMirror th, + .ProseMirror td { + border: 1px solid #e2e8f0; + padding: 0.5rem; + text-align: left; + } + + .ProseMirror th { + background-color: #f8fafc; + font-weight: bold; + } + + .ProseMirror img { + max-width: 100%; + height: auto; + border-radius: 0.5rem; + } + + .ProseMirror a { + color: #3b82f6; + text-decoration: underline; + } + + /* Dark theme links */ + .dark .ProseMirror a { + color: #60a5fa; + } + + .ProseMirror mark { + background-color: #fef08a; + padding: 0.125rem 0.25rem; + border-radius: 0.25rem; + } + + /* Dark theme highlight */ + .dark .ProseMirror mark { + background-color: #fbbf24; + color: #111827; + } + + .ProseMirror ul[data-type="taskList"] { + list-style: none; + padding: 0; + } + + .ProseMirror ul[data-type="taskList"] li { + display: flex; + align-items: flex-start; + } + + .ProseMirror ul[data-type="taskList"] li > label { + flex: 0 0 auto; + margin-right: 0.5rem; + user-select: none; + } + + .ProseMirror ul[data-type="taskList"] li > div { + flex: 1 1 auto; + } + + .ProseMirror ul[data-type="taskList"] input[type="checkbox"] { + cursor: pointer; + } + + /* Dark mode styles */ + .dark .ProseMirror blockquote { + border-left-color: #475569; + } + + .dark .ProseMirror code { + background-color: #334155; + } + + .dark .ProseMirror th { + background-color: #1e293b; + } + + .dark .ProseMirror th, + .dark .ProseMirror td { + border-color: #475569; + } + + /* Line clamp utilities */ + .line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + } + + /* Code block styles */ + pre { + display: block; + overflow-x: auto; + padding: 1rem; + background: #1e1e1e; + color: #d4d4d4; + border-radius: 0.5rem; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 0.875rem; + line-height: 1.5; + } + + /* Light mode code block */ + .light pre { + background: #f8f8f8; + color: #333; + } \ No newline at end of file diff --git a/nextjs/src/app/providers/auth-provider.tsx b/nextjs/src/app/providers/auth-provider.tsx new file mode 100644 index 0000000..1f9a536 --- /dev/null +++ b/nextjs/src/app/providers/auth-provider.tsx @@ -0,0 +1,72 @@ +"use client" + +import { createContext, useContext, useEffect, useState } from "react" +import { useRouter } from "next/navigation" +import type { User, AuthContextType } from "@/shared/types" + +const AuthContext = createContext(undefined) + +export function AuthProvider({ children }: { children: React.ReactNode }) { + const [user, setUser] = useState(null) + const [isLoading, setIsLoading] = useState(true) + const router = useRouter() + + useEffect(() => { + // Check for existing session via API + checkAuth() + }, []) + + const checkAuth = async () => { + try { + const response = await fetch('/api/auth/me', { + credentials: 'include', + }) + + if (response.ok) { + const userData = await response.json() + setUser(userData) + } else { + setUser(null) + } + } catch (error) { + console.error("Error checking auth:", error) + setUser(null) + } finally { + setIsLoading(false) + } + } + + const login = async (token: string, userData: User) => { + // Token is already set in cookie by login API + setUser(userData) + } + + const logout = async () => { + try { + // Clear auth cookie by calling logout API + await fetch('/api/auth/logout', { + method: 'POST', + credentials: 'include', + }) + } catch (error) { + console.error("Error during logout:", error) + } + setUser(null) + router.push("/home") + } + + return ( + + {children} + + ) +} + +export function useAuth() { + const context = useContext(AuthContext) + if (context === undefined) { + throw new Error("useAuth must be used within an AuthProvider") + } + return context +} + diff --git a/nextjs/src/app/providers/theme-provider.tsx b/nextjs/src/app/providers/theme-provider.tsx new file mode 100644 index 0000000..7a48ad0 --- /dev/null +++ b/nextjs/src/app/providers/theme-provider.tsx @@ -0,0 +1,10 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" +import { type ThemeProviderProps } from "next-themes" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} + diff --git a/nextjs/src/entities/document/api/index.ts b/nextjs/src/entities/document/api/index.ts new file mode 100644 index 0000000..bddafae --- /dev/null +++ b/nextjs/src/entities/document/api/index.ts @@ -0,0 +1,67 @@ +import type { Document, DocumentWithRelations } from '../model/types'; +import type { DocumentInput } from '../model/validation'; +import { apiGet, apiPost, apiPut, apiDelete } from '@/shared/api'; + +// Document API functions +export const documentApi = { + // Get all documents + getDocuments: async (): Promise => { + try { + return await apiGet('/api/documents'); + } catch (error) { + console.error('Failed to fetch documents:', error); + throw error; + } + }, + + // Get a specific document + getDocument: async (id: string): Promise => { + try { + return await apiGet(`/api/documents/${id}`); + } catch (error) { + console.error('Failed to fetch document:', error); + throw error; + } + }, + + // Create a new document + createDocument: async (newDocument: DocumentInput): Promise => { + try { + return await apiPost('/api/documents', newDocument); + } catch (error) { + console.error('Failed to create document:', error); + throw error; + } + }, + + // Update a document + updateDocument: async (id: string, updateData: Partial): Promise => { + try { + return await apiPut(`/api/documents/${id}`, updateData); + } catch (error) { + console.error('Failed to update document:', error); + throw error; + } + }, + + // Delete a document + deleteDocument: async (id: string): Promise => { + try { + await apiDelete(`/api/documents/${id}`); + } catch (error) { + console.error('Failed to delete document:', error); + throw error; + } + }, + + // Get public document + getPublicDocument: async (id: string): Promise => { + try { + return await apiGet(`/api/documents/${id}/public`); + } catch (error) { + console.error('Failed to fetch public document:', error); + throw error; + } + }, +}; + diff --git a/nextjs/src/entities/document/index.ts b/nextjs/src/entities/document/index.ts new file mode 100644 index 0000000..3062c4b --- /dev/null +++ b/nextjs/src/entities/document/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/entities/document/model/index.ts b/nextjs/src/entities/document/model/index.ts new file mode 100644 index 0000000..5b7b829 --- /dev/null +++ b/nextjs/src/entities/document/model/index.ts @@ -0,0 +1,4 @@ +export * from './types'; +export * from './store'; +export * from './validation'; + diff --git a/nextjs/src/entities/document/model/store.ts b/nextjs/src/entities/document/model/store.ts new file mode 100644 index 0000000..bbb59f2 --- /dev/null +++ b/nextjs/src/entities/document/model/store.ts @@ -0,0 +1,36 @@ +import { create } from 'zustand'; +import { DocumentWithRelations, DocumentState, DocumentActions } from './types'; + +// Document state management store +export const useDocumentStore = create((set) => ({ + documents: [], + currentDocument: null, + isLoading: true, + + readDocuments: (documents: DocumentWithRelations[]) => set({ documents }), + + setCurrentDocument: (document: DocumentWithRelations | null) => set({ currentDocument: document }), + + createDocument: (newDocument: DocumentWithRelations) => set((state) => ({ + documents: [newDocument, ...state.documents] + })), + + updateDocument: (updatedDocument: DocumentWithRelations) => set((state) => ({ + documents: state.documents.map(doc => + doc.id === updatedDocument.id ? updatedDocument : doc + ), + currentDocument: state.currentDocument?.id === updatedDocument.id + ? updatedDocument + : state.currentDocument + })), + + deleteDocument: (documentId: string) => set((state) => ({ + documents: state.documents.filter(doc => doc.id !== documentId), + currentDocument: state.currentDocument?.id === documentId + ? null + : state.currentDocument + })), + + setLoading: (isLoading: boolean) => set({ isLoading }), +})); + diff --git a/nextjs/src/entities/document/model/types.ts b/nextjs/src/entities/document/model/types.ts new file mode 100644 index 0000000..84c5f9d --- /dev/null +++ b/nextjs/src/entities/document/model/types.ts @@ -0,0 +1,70 @@ +// Document entity types +export type DocumentType = 'PAGE' | 'CODE_FILE'; + +export interface Document { + id: string; + title: string; + content?: any; // JSON content for rich text + icon?: string; + cover?: string; + isPublished: boolean; + isArchived: boolean; + createdAt: Date | string; + updatedAt: Date | string; + type: DocumentType; + filePath?: string; + fileContent?: string; + language?: string; + fileSize?: number; + parentId?: string; + folderId?: string; + userId: string; +} + +export interface DocumentWithRelations extends Document { + parent?: Document; + children?: Document[]; + folder?: { + id: string; + name: string; + icon?: string; + }; + user?: any; + _count?: { + documents: number; + }; +} + +export interface DocumentListItem { + id: string; + title: string; + icon?: string; + updatedAt: string; +} + +export interface HeadingItem { + id: string; + text: string; + level: number; + element?: HTMLElement; + children?: HeadingItem[]; + isExpanded?: boolean; +} + +// Document state +export interface DocumentState { + documents: DocumentWithRelations[]; + currentDocument: DocumentWithRelations | null; + isLoading: boolean; +} + +// Document actions +export interface DocumentActions { + readDocuments: (documents: DocumentWithRelations[]) => void; + setCurrentDocument: (document: DocumentWithRelations | null) => void; + createDocument: (document: DocumentWithRelations) => void; + updateDocument: (updatedDocument: DocumentWithRelations) => void; + deleteDocument: (documentId: string) => void; + setLoading: (isLoading: boolean) => void; +} + diff --git a/nextjs/src/entities/document/model/validation.ts b/nextjs/src/entities/document/model/validation.ts new file mode 100644 index 0000000..ae7cd80 --- /dev/null +++ b/nextjs/src/entities/document/model/validation.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; + +// Document validation schemas +export const documentSchema = z.object({ + title: z.string().min(1, 'Title is required').max(200, 'Title is too long'), + content: z.any().optional(), + icon: z.string().optional(), + cover: z.string().optional(), + isPublished: z.boolean().default(false), + isArchived: z.boolean().default(false), + type: z.enum(['PAGE', 'CODE_FILE']).default('PAGE'), + filePath: z.string().optional(), + fileContent: z.string().optional(), + language: z.string().optional(), + fileSize: z.number().optional(), + parentId: z.string().optional(), + folderId: z.string().optional(), +}); + +export type DocumentInput = z.infer; + diff --git a/nextjs/src/entities/document/ui/DocumentItem.tsx b/nextjs/src/entities/document/ui/DocumentItem.tsx new file mode 100644 index 0000000..fd8a231 --- /dev/null +++ b/nextjs/src/entities/document/ui/DocumentItem.tsx @@ -0,0 +1,45 @@ +import { DocumentWithRelations } from '../model/types'; +import { cn } from '@/shared/lib/utils'; +import { FileText, Calendar, Folder } from 'lucide-react'; +import Link from 'next/link'; + +interface DocumentItemProps { + document: DocumentWithRelations; + className?: string; +} + +export const DocumentItem = ({ document, className }: DocumentItemProps) => { + const Icon = document.icon ? + {document.icon} : + ; + + return ( + +

+
+

{document.title}

+
+ {document.folder && ( +
+ + {document.folder.name} +
+ )} +
+ + {new Date(document.updatedAt).toLocaleDateString()} +
+
+
+ + ); +}; + diff --git a/nextjs/src/entities/document/ui/index.ts b/nextjs/src/entities/document/ui/index.ts new file mode 100644 index 0000000..df03843 --- /dev/null +++ b/nextjs/src/entities/document/ui/index.ts @@ -0,0 +1,2 @@ +export * from './DocumentItem'; + diff --git a/nextjs/src/entities/folder/api/index.ts b/nextjs/src/entities/folder/api/index.ts new file mode 100644 index 0000000..f425727 --- /dev/null +++ b/nextjs/src/entities/folder/api/index.ts @@ -0,0 +1,57 @@ +import type { Folder, FolderWithRelations } from '../model/types'; +import type { FolderInput } from '../model/validation'; +import { apiGet, apiPost, apiPut, apiDelete } from '@/shared/api'; + +// Folder API functions +export const folderApi = { + // Get all folders + getFolders: async (): Promise => { + try { + return await apiGet('/api/folders'); + } catch (error) { + console.error('Failed to fetch folders:', error); + throw error; + } + }, + + // Get a specific folder + getFolder: async (id: string): Promise => { + try { + return await apiGet(`/api/folders/${id}`); + } catch (error) { + console.error('Failed to fetch folder:', error); + throw error; + } + }, + + // Create a new folder + createFolder: async (newFolder: FolderInput): Promise => { + try { + return await apiPost('/api/folders', newFolder); + } catch (error) { + console.error('Failed to create folder:', error); + throw error; + } + }, + + // Update a folder + updateFolder: async (id: string, updateData: Partial): Promise => { + try { + return await apiPut(`/api/folders/${id}`, updateData); + } catch (error) { + console.error('Failed to update folder:', error); + throw error; + } + }, + + // Delete a folder + deleteFolder: async (id: string): Promise => { + try { + await apiDelete(`/api/folders/${id}`); + } catch (error) { + console.error('Failed to delete folder:', error); + throw error; + } + }, +}; + diff --git a/nextjs/src/entities/folder/index.ts b/nextjs/src/entities/folder/index.ts new file mode 100644 index 0000000..3062c4b --- /dev/null +++ b/nextjs/src/entities/folder/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/entities/folder/model/index.ts b/nextjs/src/entities/folder/model/index.ts new file mode 100644 index 0000000..5b7b829 --- /dev/null +++ b/nextjs/src/entities/folder/model/index.ts @@ -0,0 +1,4 @@ +export * from './types'; +export * from './store'; +export * from './validation'; + diff --git a/nextjs/src/entities/folder/model/store.ts b/nextjs/src/entities/folder/model/store.ts new file mode 100644 index 0000000..6b91ab6 --- /dev/null +++ b/nextjs/src/entities/folder/model/store.ts @@ -0,0 +1,36 @@ +import { create } from 'zustand'; +import { FolderWithRelations, FolderState, FolderActions } from './types'; + +// Folder state management store +export const useFolderStore = create((set) => ({ + folders: [], + currentFolder: null, + isLoading: true, + + readFolders: (folders: FolderWithRelations[]) => set({ folders }), + + setCurrentFolder: (folder: FolderWithRelations | null) => set({ currentFolder: folder }), + + createFolder: (newFolder: FolderWithRelations) => set((state) => ({ + folders: [newFolder, ...state.folders] + })), + + updateFolder: (updatedFolder: FolderWithRelations) => set((state) => ({ + folders: state.folders.map(folder => + folder.id === updatedFolder.id ? updatedFolder : folder + ), + currentFolder: state.currentFolder?.id === updatedFolder.id + ? updatedFolder + : state.currentFolder + })), + + deleteFolder: (folderId: string) => set((state) => ({ + folders: state.folders.filter(folder => folder.id !== folderId), + currentFolder: state.currentFolder?.id === folderId + ? null + : state.currentFolder + })), + + setLoading: (isLoading: boolean) => set({ isLoading }), +})); + diff --git a/nextjs/src/entities/folder/model/types.ts b/nextjs/src/entities/folder/model/types.ts new file mode 100644 index 0000000..3d71ef8 --- /dev/null +++ b/nextjs/src/entities/folder/model/types.ts @@ -0,0 +1,44 @@ +// Folder entity types +export interface Folder { + id: string; + name: string; + icon?: string; + color?: string; + isArchived: boolean; + createdAt: Date | string; + updatedAt: Date | string; + parentId?: string; + userId: string; +} + +export interface FolderWithRelations extends Folder { + documents: Array<{ + id: string; + title: string; + icon?: string; + updatedAt: string; + }>; + children: FolderWithRelations[]; + _count: { + documents: number; + children: number; + }; +} + +// Folder state +export interface FolderState { + folders: FolderWithRelations[]; + currentFolder: FolderWithRelations | null; + isLoading: boolean; +} + +// Folder actions +export interface FolderActions { + readFolders: (folders: FolderWithRelations[]) => void; + setCurrentFolder: (folder: FolderWithRelations | null) => void; + createFolder: (folder: FolderWithRelations) => void; + updateFolder: (updatedFolder: FolderWithRelations) => void; + deleteFolder: (folderId: string) => void; + setLoading: (isLoading: boolean) => void; +} + diff --git a/nextjs/src/entities/folder/model/validation.ts b/nextjs/src/entities/folder/model/validation.ts new file mode 100644 index 0000000..039a2cf --- /dev/null +++ b/nextjs/src/entities/folder/model/validation.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +// Folder validation schemas +export const folderSchema = z.object({ + name: z.string().min(1, 'Name is required').max(100, 'Name is too long'), + icon: z.string().optional(), + color: z.string().optional(), + isArchived: z.boolean().default(false), + parentId: z.string().optional(), +}); + +export type FolderInput = z.infer; + diff --git a/nextjs/src/entities/folder/ui/FolderItem.tsx b/nextjs/src/entities/folder/ui/FolderItem.tsx new file mode 100644 index 0000000..f72c0d9 --- /dev/null +++ b/nextjs/src/entities/folder/ui/FolderItem.tsx @@ -0,0 +1,40 @@ +import { FolderWithRelations } from '../model/types'; +import { cn } from '@/shared/lib/utils'; +import { Folder, Calendar } from 'lucide-react'; +import Link from 'next/link'; + +interface FolderItemProps { + folder: FolderWithRelations; + className?: string; +} + +export const FolderItem = ({ folder, className }: FolderItemProps) => { + const Icon = folder.icon ? + {folder.icon} : + ; + + return ( + +
+ {Icon} +
+
+

{folder.name}

+
+ {folder._count.documents} documents +
+ + {new Date(folder.updatedAt).toLocaleDateString()} +
+
+
+ + ); +}; + diff --git a/nextjs/src/entities/folder/ui/index.ts b/nextjs/src/entities/folder/ui/index.ts new file mode 100644 index 0000000..686b265 --- /dev/null +++ b/nextjs/src/entities/folder/ui/index.ts @@ -0,0 +1,2 @@ +export * from './FolderItem'; + diff --git a/nextjs/src/entities/index.ts b/nextjs/src/entities/index.ts new file mode 100644 index 0000000..08e2f3b --- /dev/null +++ b/nextjs/src/entities/index.ts @@ -0,0 +1,6 @@ +// Export all entities +export * from './document'; +export * from './folder'; +export * from './user'; +export * from './template'; + diff --git a/nextjs/src/entities/template/api/index.ts b/nextjs/src/entities/template/api/index.ts new file mode 100644 index 0000000..e4dab92 --- /dev/null +++ b/nextjs/src/entities/template/api/index.ts @@ -0,0 +1,56 @@ +import type { DatabaseTemplate } from '../model/types'; +import { apiGet, apiPost, apiPut, apiDelete } from '@/shared/api'; + +// Template API functions +export const templateApi = { + // Get all templates + getTemplates: async (): Promise => { + try { + return await apiGet('/api/templates'); + } catch (error) { + console.error('Failed to fetch templates:', error); + throw error; + } + }, + + // Get public templates + getPublicTemplates: async (): Promise => { + try { + return await apiGet('/api/templates?public=true'); + } catch (error) { + console.error('Failed to fetch public templates:', error); + throw error; + } + }, + + // Create a new template + createTemplate: async (newTemplate: Partial): Promise => { + try { + return await apiPost('/api/templates', newTemplate); + } catch (error) { + console.error('Failed to create template:', error); + throw error; + } + }, + + // Update a template + updateTemplate: async (id: string, updateData: Partial): Promise => { + try { + return await apiPut(`/api/templates/${id}`, updateData); + } catch (error) { + console.error('Failed to update template:', error); + throw error; + } + }, + + // Delete a template + deleteTemplate: async (id: string): Promise => { + try { + await apiDelete(`/api/templates/${id}`); + } catch (error) { + console.error('Failed to delete template:', error); + throw error; + } + }, +}; + diff --git a/nextjs/src/entities/template/index.ts b/nextjs/src/entities/template/index.ts new file mode 100644 index 0000000..3062c4b --- /dev/null +++ b/nextjs/src/entities/template/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/entities/template/model/index.ts b/nextjs/src/entities/template/model/index.ts new file mode 100644 index 0000000..5b7b829 --- /dev/null +++ b/nextjs/src/entities/template/model/index.ts @@ -0,0 +1,4 @@ +export * from './types'; +export * from './store'; +export * from './validation'; + diff --git a/nextjs/src/entities/template/model/store.ts b/nextjs/src/entities/template/model/store.ts new file mode 100644 index 0000000..601aa96 --- /dev/null +++ b/nextjs/src/entities/template/model/store.ts @@ -0,0 +1,36 @@ +import { create } from 'zustand'; +import { DatabaseTemplate, TemplateState, TemplateActions } from './types'; + +// Template state management store +export const useTemplateStore = create((set) => ({ + templates: [], + currentTemplate: null, + isLoading: true, + + readTemplates: (templates: DatabaseTemplate[]) => set({ templates }), + + setCurrentTemplate: (template: DatabaseTemplate | null) => set({ currentTemplate: template }), + + createTemplate: (newTemplate: DatabaseTemplate) => set((state) => ({ + templates: [newTemplate, ...state.templates] + })), + + updateTemplate: (updatedTemplate: DatabaseTemplate) => set((state) => ({ + templates: state.templates.map(template => + template.id === updatedTemplate.id ? updatedTemplate : template + ), + currentTemplate: state.currentTemplate?.id === updatedTemplate.id + ? updatedTemplate + : state.currentTemplate + })), + + deleteTemplate: (templateId: string) => set((state) => ({ + templates: state.templates.filter(template => template.id !== templateId), + currentTemplate: state.currentTemplate?.id === templateId + ? null + : state.currentTemplate + })), + + setLoading: (isLoading: boolean) => set({ isLoading }), +})); + diff --git a/nextjs/src/entities/template/model/types.ts b/nextjs/src/entities/template/model/types.ts new file mode 100644 index 0000000..e2648d8 --- /dev/null +++ b/nextjs/src/entities/template/model/types.ts @@ -0,0 +1,49 @@ +// Template entity types +export interface Template { + id: string; + name: string; + description?: string; + icon: React.ReactElement | string; + content: any; +} + +export interface DatabaseTemplate { + id: string; + name: string; + description?: string; + category: string; + title: string; + content: any; + isPublic: boolean; + createdAt: string; + updatedAt: string; + userId: string; +} + +export interface TemplateBrowserProps { + isOpen: boolean; + onClose: () => void; + onSelectTemplate: (template: DatabaseTemplate) => void; +} + +export interface TemplateSelectorProps { + onSelectTemplate: (template: Template | DatabaseTemplate) => void; +} + +// Template state +export interface TemplateState { + templates: DatabaseTemplate[]; + currentTemplate: DatabaseTemplate | null; + isLoading: boolean; +} + +// Template actions +export interface TemplateActions { + readTemplates: (templates: DatabaseTemplate[]) => void; + setCurrentTemplate: (template: DatabaseTemplate | null) => void; + createTemplate: (template: DatabaseTemplate) => void; + updateTemplate: (updatedTemplate: DatabaseTemplate) => void; + deleteTemplate: (templateId: string) => void; + setLoading: (isLoading: boolean) => void; +} + diff --git a/nextjs/src/entities/template/model/validation.ts b/nextjs/src/entities/template/model/validation.ts new file mode 100644 index 0000000..aeda0a1 --- /dev/null +++ b/nextjs/src/entities/template/model/validation.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; + +// Template validation schemas +export const templateSchema = z.object({ + name: z.string().min(1, 'Name is required').max(200, 'Name is too long'), + description: z.string().optional(), + category: z.string().default('General'), + title: z.string().min(1, 'Title is required').max(200, 'Title is too long'), + content: z.any().optional(), + isPublic: z.boolean().default(false), +}); + +export type TemplateInput = z.infer; + diff --git a/nextjs/src/entities/template/ui/index.ts b/nextjs/src/entities/template/ui/index.ts new file mode 100644 index 0000000..2b69f60 --- /dev/null +++ b/nextjs/src/entities/template/ui/index.ts @@ -0,0 +1,6 @@ +// Template UI components would be defined here +// export * from './TemplateCard'; +// export * from './TemplateSelector'; + +export {}; + diff --git a/nextjs/src/entities/todo/api/index.ts b/nextjs/src/entities/todo/api/index.ts new file mode 100644 index 0000000..3c1e547 --- /dev/null +++ b/nextjs/src/entities/todo/api/index.ts @@ -0,0 +1,170 @@ +import type { Todo, CreateTodoData, UpdateTodoData } from '../model/types' + +const TODO_API_URL = process.env.NEXT_PUBLIC_TODO_API_URL || 'http://localhost:3002' + +// API 응답 타입 +interface ApiTodo { + id: number + title: string + description?: string | null + completed: boolean + createdAt: string + updatedAt: string +} + +interface ApiResponse { + success: boolean + data?: T + error?: string +} + +// 백엔드 Todo를 프론트엔드 Todo로 변환 +const mapApiTodoToTodo = (apiTodo: ApiTodo): Todo => { + return { + id: String(apiTodo.id), + title: apiTodo.title, + description: apiTodo.description || undefined, + completed: apiTodo.completed, + createdAt: new Date(apiTodo.createdAt), + updatedAt: new Date(apiTodo.updatedAt), + } +} + +/** + * 모든 TODO 가져오기 + */ +export const fetchTodos = async (): Promise => { + try { + const response = await fetch(`${TODO_API_URL}/api/todos`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + const result: ApiResponse = await response.json() + + if (!result.success || !result.data) { + throw new Error(result.error || 'Failed to fetch todos') + } + + return result.data.map(mapApiTodoToTodo) + } catch (error) { + console.error('Error fetching todos:', error) + throw error + } +} + +/** + * TODO 생성 + */ +export const createTodo = async (data: CreateTodoData): Promise => { + try { + const response = await fetch(`${TODO_API_URL}/api/todos`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify({ + title: data.title, + description: data.description || null, + completed: false, + }), + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + const result: ApiResponse = await response.json() + + if (!result.success || !result.data) { + throw new Error(result.error || 'Failed to create todo') + } + + return mapApiTodoToTodo(result.data) + } catch (error) { + console.error('Error creating todo:', error) + throw error + } +} + +/** + * TODO 업데이트 + */ +export const updateTodo = async (id: string, data: UpdateTodoData): Promise => { + try { + const response = await fetch(`${TODO_API_URL}/api/todos/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + body: JSON.stringify({ + title: data.title, + description: data.description, + completed: data.completed, + }), + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + const result: ApiResponse = await response.json() + + if (!result.success || !result.data) { + throw new Error(result.error || 'Failed to update todo') + } + + return mapApiTodoToTodo(result.data) + } catch (error) { + console.error('Error updating todo:', error) + throw error + } +} + +/** + * TODO 삭제 + */ +export const deleteTodo = async (id: string): Promise => { + try { + const response = await fetch(`${TODO_API_URL}/api/todos/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + }) + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) + } + + const result: ApiResponse = await response.json() + + if (!result.success) { + throw new Error(result.error || 'Failed to delete todo') + } + } catch (error) { + console.error('Error deleting todo:', error) + throw error + } +} + +/** + * Todo API + */ +export const todoApi = { + fetchTodos, + createTodo, + updateTodo, + deleteTodo, +} + diff --git a/nextjs/src/entities/todo/index.ts b/nextjs/src/entities/todo/index.ts new file mode 100644 index 0000000..52b492c --- /dev/null +++ b/nextjs/src/entities/todo/index.ts @@ -0,0 +1,3 @@ +export * from './model' +export * from './api' + diff --git a/nextjs/src/entities/todo/model/index.ts b/nextjs/src/entities/todo/model/index.ts new file mode 100644 index 0000000..e3d98e3 --- /dev/null +++ b/nextjs/src/entities/todo/model/index.ts @@ -0,0 +1,3 @@ +export * from './types' +export * from './store' + diff --git a/nextjs/src/entities/todo/model/store.ts b/nextjs/src/entities/todo/model/store.ts new file mode 100644 index 0000000..69bf818 --- /dev/null +++ b/nextjs/src/entities/todo/model/store.ts @@ -0,0 +1,133 @@ +import { create } from 'zustand' +import { Todo, CreateTodoData, UpdateTodoData, TodoStore, TodoFilter } from './types' +import { fetchTodos, createTodo, updateTodo, deleteTodo } from '../api' + +export const useTodoStore = create()((set, get) => ({ + // State + todos: [], + filter: 'all', + isLoading: false, + error: null, + + // Actions + addTodo: async (data: CreateTodoData) => { + if (!data.title?.trim()) { + console.warn('Todo title is required') + return + } + + try { + const newTodo = await createTodo(data) + set((state) => ({ + todos: [newTodo, ...state.todos] + })) + } catch (error) { + console.error('Failed to create todo:', error) + set({ error: 'Failed to create todo' }) + } + }, + + updateTodo: async (id: string, data: UpdateTodoData) => { + if (!id) { + console.warn('Todo ID is required for update') + return + } + + try { + const updatedTodo = await updateTodo(id, data) + set((state) => ({ + todos: state.todos.map((todo) => + todo.id === id ? updatedTodo : todo + ) + })) + } catch (error) { + console.error('Failed to update todo:', error) + set({ error: 'Failed to update todo' }) + } + }, + + deleteTodo: async (id: string) => { + if (!id) { + console.warn('Todo ID is required for deletion') + return + } + + try { + await deleteTodo(id) + set((state) => ({ + todos: state.todos.filter((todo) => todo.id !== id) + })) + } catch (error) { + console.error('Failed to delete todo:', error) + set({ error: 'Failed to delete todo' }) + } + }, + + toggleTodo: async (id: string) => { + if (!id) { + console.warn('Todo ID is required for toggle') + return + } + + const todo = get().todos.find((t) => t.id === id) + if (!todo) return + + try { + await get().updateTodo(id, { completed: !todo.completed }) + } catch (error) { + console.error('Failed to toggle todo:', error) + } + }, + + loadTodos: async () => { + set({ isLoading: true, error: null }) + try { + const todos = await fetchTodos() + set({ todos, isLoading: false }) + } catch (error) { + console.error('Failed to load todos:', error) + set({ error: 'Failed to load todos', isLoading: false }) + } + }, + + setFilter: (filter: TodoFilter) => { + set({ filter }) + }, + + clearCompleted: async () => { + const completedTodos = get().todos.filter((todo) => todo.completed) + + try { + await Promise.all(completedTodos.map((todo) => deleteTodo(todo.id))) + set((state) => ({ + todos: state.todos.filter((todo) => !todo.completed) + })) + } catch (error) { + console.error('Failed to clear completed todos:', error) + set({ error: 'Failed to clear completed todos' }) + } + }, +})) + +// Selectors +export const useFilteredTodos = () => { + const { todos, filter } = useTodoStore() + + if (!Array.isArray(todos)) { + return [] + } + + return todos.filter((todo) => { + if (!todo || typeof todo !== 'object') { + return false + } + + const matchesFilter = + filter === 'all' || + (filter === 'active' && !todo.completed) || + (filter === 'completed' && todo.completed) + + return matchesFilter + }) +} + diff --git a/nextjs/src/entities/todo/model/types.ts b/nextjs/src/entities/todo/model/types.ts new file mode 100644 index 0000000..6e7a14c --- /dev/null +++ b/nextjs/src/entities/todo/model/types.ts @@ -0,0 +1,42 @@ +export interface Todo { + id: string + title: string + description?: string + completed: boolean + createdAt: Date + updatedAt: Date +} + +export interface CreateTodoData { + title: string + description?: string +} + +export interface UpdateTodoData { + title?: string + description?: string + completed?: boolean +} + +export type TodoFilter = 'all' | 'active' | 'completed' + +// Store types +export interface TodoState { + todos: Todo[] + filter: TodoFilter + isLoading: boolean + error: string | null +} + +export interface TodoActions { + addTodo: (data: CreateTodoData) => Promise + updateTodo: (id: string, data: UpdateTodoData) => Promise + deleteTodo: (id: string) => Promise + toggleTodo: (id: string) => Promise + loadTodos: () => Promise + setFilter: (filter: TodoFilter) => void + clearCompleted: () => Promise +} + +export type TodoStore = TodoState & TodoActions + diff --git a/nextjs/src/entities/todo/ui/TodoItem.tsx b/nextjs/src/entities/todo/ui/TodoItem.tsx new file mode 100644 index 0000000..bcc9d01 --- /dev/null +++ b/nextjs/src/entities/todo/ui/TodoItem.tsx @@ -0,0 +1,132 @@ +'use client' + +import { Todo } from '../model/types' +import { Checkbox } from '@/shared/ui/checkbox' +import { Button } from '@/shared/ui/button' +import { Trash2, Edit2 } from 'lucide-react' +import { cn } from '@/shared/lib/utils' +import { useState } from 'react' +import { Input } from '@/shared/ui/input' + +interface TodoItemProps { + todo: Todo + onToggle: (id: string) => void + onDelete: (id: string) => void + onUpdate: (id: string, title: string, description?: string) => void +} + +export function TodoItem({ todo, onToggle, onDelete, onUpdate }: TodoItemProps) { + const [isEditing, setIsEditing] = useState(false) + const [editTitle, setEditTitle] = useState(todo.title) + const [editDescription, setEditDescription] = useState(todo.description || '') + + const handleSave = () => { + if (editTitle.trim()) { + onUpdate(todo.id, editTitle, editDescription) + setIsEditing(false) + } + } + + const handleCancel = () => { + setEditTitle(todo.title) + setEditDescription(todo.description || '') + setIsEditing(false) + } + + if (isEditing) { + return ( +
+ setEditTitle(e.target.value)} + placeholder="Todo 제목" + className="font-medium" + autoFocus + onKeyDown={(e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSave() + } else if (e.key === 'Escape') { + handleCancel() + } + }} + /> + setEditDescription(e.target.value)} + placeholder="설명 (선택사항)" + onKeyDown={(e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSave() + } else if (e.key === 'Escape') { + handleCancel() + } + }} + /> +
+ + +
+
+ ) + } + + return ( +
+ onToggle(todo.id)} + className="mt-0.5" + /> + +
+
+ {todo.title} +
+ {todo.description && ( +
+ {todo.description} +
+ )} +
+ {new Date(todo.createdAt).toLocaleDateString('ko-KR')} +
+
+ +
+ + +
+
+ ) +} + diff --git a/nextjs/src/entities/todo/ui/TodoList.tsx b/nextjs/src/entities/todo/ui/TodoList.tsx new file mode 100644 index 0000000..6855da1 --- /dev/null +++ b/nextjs/src/entities/todo/ui/TodoList.tsx @@ -0,0 +1,53 @@ +'use client' + +import { TodoItem } from './TodoItem' +import { useTodoStore, useFilteredTodos } from '../model/store' +import { Spinner } from '@/shared/ui/spinner' + +export function TodoList() { + const { updateTodo, deleteTodo, toggleTodo, isLoading, error } = useTodoStore() + const filteredTodos = useFilteredTodos() + + if (isLoading) { + return ( +
+ +
+ ) + } + + if (error) { + return ( +
+ {error} +
+ ) + } + + if (filteredTodos.length === 0) { + return ( +
+ 할 일이 없습니다 +
+ ) + } + + const handleUpdate = async (id: string, title: string, description?: string) => { + await updateTodo(id, { title, description }) + } + + return ( +
+ {filteredTodos.map((todo) => ( + + ))} +
+ ) +} + diff --git a/nextjs/src/entities/todo/ui/index.ts b/nextjs/src/entities/todo/ui/index.ts new file mode 100644 index 0000000..9c1247c --- /dev/null +++ b/nextjs/src/entities/todo/ui/index.ts @@ -0,0 +1,3 @@ +export * from './TodoItem' +export * from './TodoList' + diff --git a/nextjs/src/entities/user/api/index.ts b/nextjs/src/entities/user/api/index.ts new file mode 100644 index 0000000..6cac96f --- /dev/null +++ b/nextjs/src/entities/user/api/index.ts @@ -0,0 +1,53 @@ +import type { User } from '../model/types'; +import { apiGet, apiPost } from '@/shared/api'; + +// User API functions +export const userApi = { + // Get current user + getCurrentUser: async (): Promise => { + try { + return await apiGet('/api/auth/me'); + } catch (error) { + console.error('Failed to fetch user:', error); + throw error; + } + }, + + // Login + login: async (email: string, password: string): Promise<{ user: User; token: string }> => { + try { + return await apiPost<{ user: User; token: string }>('/api/auth/login', { + email, + password, + }); + } catch (error) { + console.error('Failed to login:', error); + throw error; + } + }, + + // Register + register: async (email: string, password: string, name?: string): Promise<{ user: User; token: string }> => { + try { + return await apiPost<{ user: User; token: string }>('/api/auth/register', { + email, + password, + name, + }); + } catch (error) { + console.error('Failed to register:', error); + throw error; + } + }, + + // Logout + logout: async (): Promise => { + try { + await apiPost('/api/auth/logout'); + } catch (error) { + console.error('Failed to logout:', error); + throw error; + } + }, +}; + diff --git a/nextjs/src/entities/user/index.ts b/nextjs/src/entities/user/index.ts new file mode 100644 index 0000000..3062c4b --- /dev/null +++ b/nextjs/src/entities/user/index.ts @@ -0,0 +1,4 @@ +export * from './api'; +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/entities/user/model/index.ts b/nextjs/src/entities/user/model/index.ts new file mode 100644 index 0000000..5b7b829 --- /dev/null +++ b/nextjs/src/entities/user/model/index.ts @@ -0,0 +1,4 @@ +export * from './types'; +export * from './store'; +export * from './validation'; + diff --git a/nextjs/src/entities/user/model/store.ts b/nextjs/src/entities/user/model/store.ts new file mode 100644 index 0000000..56d978c --- /dev/null +++ b/nextjs/src/entities/user/model/store.ts @@ -0,0 +1,13 @@ +import { create } from 'zustand'; +import { UserState, UserActions, User } from './types'; + +// User state management store +export const useUserStore = create((set) => ({ + user: null, + isLoading: true, + + setUser: (user: User | null) => set({ user }), + + setLoading: (isLoading: boolean) => set({ isLoading }), +})); + diff --git a/nextjs/src/entities/user/model/types.ts b/nextjs/src/entities/user/model/types.ts new file mode 100644 index 0000000..8b7c328 --- /dev/null +++ b/nextjs/src/entities/user/model/types.ts @@ -0,0 +1,27 @@ +// User entity types +export interface User { + id: string; + email: string; + name?: string; + image?: string; +} + +export interface AuthContextType { + user: User | null; + isLoading: boolean; + login: (token: string, user: User) => void; + logout: () => void; +} + +// User state +export interface UserState { + user: User | null; + isLoading: boolean; +} + +// User actions +export interface UserActions { + setUser: (user: User | null) => void; + setLoading: (isLoading: boolean) => void; +} + diff --git a/nextjs/src/entities/user/model/validation.ts b/nextjs/src/entities/user/model/validation.ts new file mode 100644 index 0000000..dee4d27 --- /dev/null +++ b/nextjs/src/entities/user/model/validation.ts @@ -0,0 +1,11 @@ +import { z } from 'zod'; + +// User validation schemas +export const userSchema = z.object({ + email: z.string().email('Invalid email address'), + name: z.string().optional(), + image: z.string().url().optional(), +}); + +export type UserInput = z.infer; + diff --git a/nextjs/src/entities/user/ui/index.ts b/nextjs/src/entities/user/ui/index.ts new file mode 100644 index 0000000..c70b0d9 --- /dev/null +++ b/nextjs/src/entities/user/ui/index.ts @@ -0,0 +1,6 @@ +// User UI components would be defined here +// export * from './UserAvatar'; +// export * from './UserProfile'; + +export {}; + diff --git a/nextjs/src/features/document-edit/index.ts b/nextjs/src/features/document-edit/index.ts new file mode 100644 index 0000000..7a689d5 --- /dev/null +++ b/nextjs/src/features/document-edit/index.ts @@ -0,0 +1,3 @@ +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/features/document-edit/model/index.ts b/nextjs/src/features/document-edit/model/index.ts new file mode 100644 index 0000000..b8d7e86 --- /dev/null +++ b/nextjs/src/features/document-edit/model/index.ts @@ -0,0 +1,9 @@ +export * from './store'; +export * from './use-document-data'; +export * from './use-document-save'; +export * from './use-document-actions'; +export * from './use-document-headings'; +export * from './use-document-utils'; +export * from './use-document-templates'; +export * from './use-sidebar-search'; + diff --git a/nextjs/src/features/document-edit/model/store.ts b/nextjs/src/features/document-edit/model/store.ts new file mode 100644 index 0000000..dd8a451 --- /dev/null +++ b/nextjs/src/features/document-edit/model/store.ts @@ -0,0 +1,70 @@ +import { useCallback } from 'react'; +import { documentApi } from '@/entities/document/api'; +import { useDocumentStore } from '@/entities/document/model/store'; +import type { DocumentWithRelations, DocumentInput } from '@/entities/document/model'; + +// API 호출과 전역 상태 관리를 통합하는 훅 +export const useDocumentEditStore = () => { + const entityStore = useDocumentStore.getState(); + + const readDocuments = useCallback(async () => { + entityStore.setLoading(true); + try { + entityStore.readDocuments(await documentApi.getDocuments()); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const readDocument = useCallback(async (documentId: string) => { + entityStore.setLoading(true); + try { + const document = await documentApi.getDocument(documentId); + entityStore.setCurrentDocument(document); + return document; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const createDocument = useCallback(async (newDocument: DocumentInput) => { + entityStore.setLoading(true); + try { + const created = await documentApi.createDocument(newDocument); + entityStore.createDocument(created as DocumentWithRelations); + return created; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const updateDocument = useCallback(async (documentId: string, updateData: Partial) => { + entityStore.setLoading(true); + try { + const updated = await documentApi.updateDocument(documentId, updateData); + entityStore.updateDocument(updated as DocumentWithRelations); + return updated; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const deleteDocument = useCallback(async (documentId: string) => { + entityStore.setLoading(true); + try { + await documentApi.deleteDocument(documentId); + entityStore.deleteDocument(documentId); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + return { + readDocuments, + readDocument, + createDocument, + updateDocument, + deleteDocument, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-actions.tsx b/nextjs/src/features/document-edit/model/use-document-actions.tsx new file mode 100644 index 0000000..d94749d --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-actions.tsx @@ -0,0 +1,75 @@ +import { useState, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { documentApi } from "@/entities/document/api"; + +interface UseDocumentActionsProps { + documentId: string; + onPublishChange?: (isPublished: boolean) => void; +} + +/** + * 문서 액션 (공유, 삭제 등) + */ +export const useDocumentActions = ({ + documentId, + onPublishChange +}: UseDocumentActionsProps) => { + const router = useRouter(); + const [isDeleting, setIsDeleting] = useState(false); + + // Delete document + const deleteDocument = useCallback(async () => { + if (!confirm("Are you sure you want to delete this document?")) return; + + try { + setIsDeleting(true); + await documentApi.deleteDocument(documentId); + router.push("/documents"); + } catch (error) { + console.error("Error deleting document:", error); + } finally { + setIsDeleting(false); + } + }, [documentId, router]); + + // Share document + const shareDocument = useCallback(async () => { + try { + await documentApi.updateDocument(documentId, { + isPublished: true, + }); + + const shareUrl = `${window.location.origin}/share/${documentId}`; + + alert('문서가 공개되었습니다!\n\n공유 링크:\n' + shareUrl); + + onPublishChange?.(true); + } catch (error) { + console.error('Error sharing document:', error); + alert('문서 공유에 실패했습니다'); + } + }, [documentId, onPublishChange]); + + // Unshare document + const unshareDocument = useCallback(async () => { + try { + await documentApi.updateDocument(documentId, { + isPublished: false, + }); + + alert('Document is no longer shared!'); + onPublishChange?.(false); + } catch (error) { + console.error('Error unsharing document:', error); + alert('Failed to unshare document'); + } + }, [documentId, onPublishChange]); + + return { + deleteDocument, + shareDocument, + unshareDocument, + isDeleting, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-data.tsx b/nextjs/src/features/document-edit/model/use-document-data.tsx new file mode 100644 index 0000000..04f5611 --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-data.tsx @@ -0,0 +1,98 @@ +import { useState, useEffect, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { documentApi } from "@/entities/document/api"; +import type { DocumentWithRelations, DocumentListItem } from "@/entities/document/model"; + +interface UseDocumentDataProps { + documentId: string; +} + +/** + * 문서 데이터 조회 및 기본 상태 관리 + */ +export const useDocumentData = ({ documentId }: UseDocumentDataProps) => { + const router = useRouter(); + const [document, setDocument] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [title, setTitle] = useState(""); + const [content, setContent] = useState(null); + const [availableDocuments, setAvailableDocuments] = useState([]); + + // Fetch document + const fetchDocument = useCallback(async () => { + try { + const data = await documentApi.getDocument(documentId); + setDocument(data); + setTitle(data.title); + setContent(data.content || { + type: 'doc', + content: [ + { + type: 'paragraph', + content: [ + { + type: 'text', + text: 'Start writing...', + }, + ], + }, + ], + }); + } catch (error: any) { + console.error("Error fetching document:", error); + if (error.message?.includes('404')) { + router.push("/documents"); + } + } finally { + setIsLoading(false); + } + }, [documentId, router]); + + // Fetch available documents for linking + const fetchAvailableDocuments = useCallback(async () => { + try { + const documents = await documentApi.getDocuments(); + const filteredDocs = documents + .filter((doc: DocumentWithRelations) => doc.id !== documentId) + .map((doc: DocumentWithRelations) => ({ + id: doc.id, + title: doc.title, + updatedAt: typeof doc.updatedAt === 'string' ? doc.updatedAt : new Date(doc.updatedAt).toISOString() + })); + setAvailableDocuments(filteredDocs); + } catch (error) { + console.error("Error fetching available documents:", error); + } + }, [documentId]); + + // Refresh document data + const refreshDocument = useCallback(() => { + setIsLoading(true); + fetchDocument(); + }, [fetchDocument]); + + // Update local document state + const updateDocument = useCallback((updatedDoc: DocumentWithRelations) => { + setDocument(updatedDoc); + }, []); + + useEffect(() => { + if (documentId) { + fetchDocument(); + fetchAvailableDocuments(); + } + }, [documentId, fetchDocument, fetchAvailableDocuments]); + + return { + document, + isLoading, + title, + setTitle, + content, + setContent, + availableDocuments, + refreshDocument, + updateDocument, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-headings.tsx b/nextjs/src/features/document-edit/model/use-document-headings.tsx new file mode 100644 index 0000000..787c363 --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-headings.tsx @@ -0,0 +1,219 @@ +import { useState, useEffect } from 'react'; +import type { HeadingItem } from '@/shared/types'; + +export const useDocumentHeadings = (content: any) => { + const [headingInstances] = useState>(new Map()); + const [headings, setHeadings] = useState([]); + const [treeHeadings, setTreeHeadings] = useState([]); + const [activeHeading, setActiveHeading] = useState(""); + + // Convert flat headings to tree structure + const buildHeadingTree = (flatHeadings: HeadingItem[]): HeadingItem[] => { + if (flatHeadings.length === 0) return []; + + const tree: HeadingItem[] = []; + const stack: HeadingItem[] = []; + + flatHeadings.forEach(heading => { + const newHeading = { ...heading, children: [], isExpanded: true }; + + // Find the correct parent by looking at the stack + while (stack.length > 0 && stack[stack.length - 1].level >= heading.level) { + stack.pop(); + } + + if (stack.length === 0) { + // This is a root level heading + tree.push(newHeading); + } else { + // This is a child of the last heading in stack + const parent = stack[stack.length - 1]; + if (!parent.children) parent.children = []; + parent.children.push(newHeading); + } + + stack.push(newHeading); + }); + + return tree; + }; + + // Extract headings from content + useEffect(() => { + if (!content?.content) return; + + const extractHeadings = (node: any, level = 0): HeadingItem[] => { + if (!node) return []; + + let result: HeadingItem[] = []; + + if (node.type === 'heading' && node.attrs?.level) { + const text = node.content?.map((c: any) => c.text || '').join('') || ''; + // Keep alphanumeric characters (including Korean), spaces become hyphens + const id = text.toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with hyphens + .replace(/[^a-z0-9\u3131-\u3163\uac00-\ud7a3-]+/g, '') // Keep only letters, numbers, Korean chars, and hyphens + .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen + .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens + result.push({ + id, + text, + level: node.attrs.level + }); + } + + if (node.content) { + node.content.forEach((child: any) => { + result.push(...extractHeadings(child, level)); + }); + } + + return result; + }; + + const extractedHeadings = extractHeadings(content); + + // Ensure unique IDs by adding a counter suffix if duplicates exist + const idCounts = new Map(); + const uniqueHeadings = extractedHeadings.map((heading, index) => { + const baseId = heading.id || 'heading'; + + // Count how many times we've seen this base ID + const count = idCounts.get(baseId) || 0; + idCounts.set(baseId, count + 1); + + // If this is the first occurrence, use the base ID + // Otherwise, append a suffix + const uniqueId = count === 0 ? baseId : `${baseId}-${count}`; + + return { + ...heading, + id: uniqueId, + _index: index // Add sequential index for reference + }; + }); + + setHeadings(uniqueHeadings); + setTreeHeadings(buildHeadingTree(uniqueHeadings)); + }, [content]); + + // Track active heading based on scroll position + useEffect(() => { + const handleScroll = () => { + const headingElements = headings.map(h => { + const element = document.querySelector(`[data-heading-id="${h.id}"]`); + return { ...h, element: element as HTMLElement }; + }).filter(h => h.element); + + let currentHeading = ""; + const scrollPosition = window.scrollY + 100; + + for (let i = headingElements.length - 1; i >= 0; i--) { + const heading = headingElements[i]; + if (heading.element && heading.element.offsetTop <= scrollPosition) { + currentHeading = heading.id; + break; + } + } + + setActiveHeading(currentHeading); + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, [headings]); + + const toggleHeadingExpansion = (headingId: string) => { + const updateHeadingExpansion = (headings: HeadingItem[]): HeadingItem[] => { + return headings.map(heading => { + if (heading.id === headingId) { + return { ...heading, isExpanded: !heading.isExpanded }; + } + if (heading.children) { + return { ...heading, children: updateHeadingExpansion(heading.children) }; + } + return heading; + }); + }; + + setTreeHeadings(updateHeadingExpansion(treeHeadings)); + }; + + const scrollToHeading = (headingId: string) => { + const selector1 = `[data-heading-id="${headingId}"]`; + const allMatches = document.querySelectorAll(selector1); + + // Find the position of this heading in the tree structure + let targetIndex = 0; + + const findHeadingInTree = (items: HeadingItem[], targetId: string, path: number[] = []): number[] | null => { + for (let i = 0; i < items.length; i++) { + const currentPath = [...path, i]; + if (items[i].id === targetId) { + return currentPath; + } + if (items[i].children) { + const result = findHeadingInTree(items[i].children!, targetId, currentPath); + if (result) return result; + } + } + return null; + }; + + const targetPath = findHeadingInTree(treeHeadings, headingId); + + if (targetPath && targetPath.length > 0) { + // Count how many headings with the same ID appear before this position + let count = 0; + + const countBefore = (items: HeadingItem[], targetId: string, targetPath: number[], currentPath: number[] = []): number => { + let count = 0; + for (let i = 0; i < items.length; i++) { + const path = [...currentPath, i]; + + // Check if this is before the target path + if (items[i].id === targetId) { + let isBefore = true; + for (let j = 0; j < Math.min(path.length, targetPath.length); j++) { + if (path[j] > targetPath[j]) { + isBefore = false; + break; + } else if (path[j] < targetPath[j]) { + break; + } + } + if (isBefore && JSON.stringify(path) !== JSON.stringify(targetPath)) { + count++; + } + } + + if (items[i].children) { + count += countBefore(items[i].children!, targetId, targetPath, path); + } + } + return count; + }; + + targetIndex = countBefore(treeHeadings, headingId, targetPath); + } + + // Get the element at the calculated index + if (allMatches.length > 0 && targetIndex < allMatches.length) { + const element = allMatches[targetIndex] as HTMLElement; + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } else if (allMatches.length > 0) { + // Fallback to first match + const element = allMatches[0] as HTMLElement; + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + return { + headings, + treeHeadings, + activeHeading, + toggleHeadingExpansion, + scrollToHeading, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-save.tsx b/nextjs/src/features/document-edit/model/use-document-save.tsx new file mode 100644 index 0000000..fc74b88 --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-save.tsx @@ -0,0 +1,78 @@ +import { useState, useEffect, useCallback } from "react"; +import { documentApi } from "@/entities/document/api"; +import type { DocumentWithRelations } from "@/entities/document/model"; + +interface UseDocumentSaveProps { + documentId: string; + title: string; + content: any; + onSaveSuccess?: (document: DocumentWithRelations) => void; +} + +/** + * 문서 저장 로직 (수동 저장, 자동 저장) + */ +export const useDocumentSave = ({ + documentId, + title, + content, + onSaveSuccess +}: UseDocumentSaveProps) => { + const [isSaving, setIsSaving] = useState(false); + const [isAutoSaving, setIsAutoSaving] = useState(false); + const [lastSaved, setLastSaved] = useState(null); + + // Save document + const saveDocument = useCallback(async () => { + try { + setIsSaving(true); + const updatedDocument = await documentApi.updateDocument(documentId, { + title: title || "Untitled", + content: content, + }); + setLastSaved(new Date()); + onSaveSuccess?.(updatedDocument as DocumentWithRelations); + } catch (error) { + console.error("Error saving document:", error); + } finally { + setIsSaving(false); + } + }, [documentId, title, content, onSaveSuccess]); + + // Auto-save function + const autoSave = useCallback(async () => { + if (!title.trim() && !content) return; + + try { + setIsAutoSaving(true); + await documentApi.updateDocument(documentId, { + title: title || "Untitled", + content: content, + }); + setLastSaved(new Date()); + } catch (error) { + console.error("Error auto-saving document:", error); + } finally { + setIsAutoSaving(false); + } + }, [documentId, title, content]); + + // Auto-save effect + useEffect(() => { + if (!title.trim() && !content) return; + + const timeoutId = setTimeout(() => { + autoSave(); + }, 2000); // Auto-save after 2 seconds of inactivity + + return () => clearTimeout(timeoutId); + }, [title, content, autoSave]); + + return { + saveDocument, + isSaving, + isAutoSaving, + lastSaved, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-templates.tsx b/nextjs/src/features/document-edit/model/use-document-templates.tsx new file mode 100644 index 0000000..35c0d7c --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-templates.tsx @@ -0,0 +1,40 @@ +import { useCallback } from "react"; +import { apiPost } from "@/shared/lib/api-client"; + +interface UseDocumentTemplatesProps { + onApply?: (content: any, title?: string) => void; +} + +/** + * 템플릿 생성 및 적용 + */ +export const useDocumentTemplates = ({ onApply }: UseDocumentTemplatesProps = {}) => { + // Create template from document + const createTemplate = useCallback(async (templateData: any) => { + try { + const result = await apiPost('/api/templates', templateData); + console.log('Template created successfully:', result); + + alert(`Template "${templateData.name}" created successfully!`); + + } catch (error) { + console.error('Error creating template:', error); + throw error; + } + }, []); + + // Apply template to document + const applyTemplate = useCallback((template: any) => { + if (template.content) { + const title = template.title || undefined; + onApply?.(template.content, title); + alert(`Template "${template.name}" applied successfully!`); + } + }, [onApply]); + + return { + createTemplate, + applyTemplate, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-document-utils.tsx b/nextjs/src/features/document-edit/model/use-document-utils.tsx new file mode 100644 index 0000000..caf7266 --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-document-utils.tsx @@ -0,0 +1,37 @@ +import { useCallback } from "react"; + +/** + * 문서 관련 유틸리티 함수 + */ +export const useDocumentUtils = () => { + // Calculate word count + const getWordCount = useCallback((content: any): number => { + if (!content?.content) return 0; + + const extractText = (node: any): string => { + if (node.type === 'text') return node.text || ''; + if (node.content) return node.content.map(extractText).join(' '); + return ''; + }; + + const text = content.content.map(extractText).join(' '); + return text.trim().split(/\s+/).filter((word: string) => word.length > 0).length; + }, []); + + // Format date helper + const formatDate = useCallback((date: Date): string => { + const now = new Date(); + const diffInMinutes = Math.floor((now.getTime() - date.getTime()) / (1000 * 60)); + + if (diffInMinutes < 1) return "Just now"; + if (diffInMinutes < 60) return `${diffInMinutes}m ago`; + if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)}h ago`; + return date.toLocaleDateString(); + }, []); + + return { + getWordCount, + formatDate, + }; +}; + diff --git a/nextjs/src/features/document-edit/model/use-sidebar-search.tsx b/nextjs/src/features/document-edit/model/use-sidebar-search.tsx new file mode 100644 index 0000000..0decf4e --- /dev/null +++ b/nextjs/src/features/document-edit/model/use-sidebar-search.tsx @@ -0,0 +1,204 @@ +import { useState } from 'react'; + +export interface SearchResult { + type: string; + text: string; + id?: string; + path?: string; +} + +export const useSidebarSearch = (content: any) => { + const [searchQuery, setSearchQuery] = useState(''); + const [searchResults, setSearchResults] = useState([]); + const [showSearchResults, setShowSearchResults] = useState(false); + + // Search function to extract text from content + const extractTextFromNode = (node: any, path: string = ''): SearchResult[] => { + if (!node) return []; + + let results: SearchResult[] = []; + + // Extract text from various node types + if (node.content) { + const text = node.content.map((c: any) => c.text || '').join(''); + if (text.trim()) { + let id; + if (node.type === 'heading' && node.attrs?.level) { + // Keep alphanumeric characters (including Korean), spaces become hyphens + const headingText = text.toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with hyphens + .replace(/[^a-z0-9\u3131-\u3163\uac00-\ud7a3-]+/g, '') // Keep only letters, numbers, Korean chars, and hyphens + .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen + .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens + id = headingText; + } + results.push({ + text, + type: node.type, + id, + path + }); + } + } + + // Recursively process children + if (node.content && Array.isArray(node.content)) { + node.content.forEach((child: any, index: number) => { + const childPath = path ? `${path}.${node.type}[${index}]` : `${node.type}[${index}]`; + results.push(...extractTextFromNode(child, childPath)); + }); + } + + return results; + }; + + // Handle search + const handleSearch = () => { + if (!searchQuery.trim()) { + setSearchResults([]); + setShowSearchResults(false); + return; + } + + if (!content?.content) { + setSearchResults([]); + setShowSearchResults(false); + return; + } + + const query = searchQuery.toLowerCase(); + const extractedTexts = extractTextFromNode(content); + + // Count occurrences for unique IDs (same as document-overview) + const idCounts = new Map(); + const matches = extractedTexts + .filter(item => item.text.toLowerCase().includes(query)) + .map(item => { + // Ensure unique IDs for search results + if (item.id) { + const count = idCounts.get(item.id) || 0; + idCounts.set(item.id, count + 1); + const uniqueId = count === 0 ? item.id : `${item.id}-${count}`; + return { + ...item, + id: uniqueId + }; + } + return item; + }); + + setSearchResults(matches); + setShowSearchResults(true); + }; + + // Handle keyboard events + const handleSearchKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handleSearch(); + } + }; + + // Clear search + const handleClearSearch = () => { + setSearchQuery(''); + setSearchResults([]); + setShowSearchResults(false); + }; + + // Navigate to search result (using same algorithm as Document Overview) + const handleNavigateToResult = (result: SearchResult) => { + // Try to find using data-heading-id attribute first (for headings) + if (result.id) { + const element = document.querySelector(`[data-heading-id="${result.id}"]`); + if (element) { + scrollAndHighlight(element as HTMLElement); + return; + } + + // Also check data-node-view-wrapper which wraps the actual heading + const proseMirror = document.querySelector('.ProseMirror'); + if (proseMirror) { + const allHeadings = proseMirror.querySelectorAll('h1, h2, h3, h4, h5, h6'); + for (const heading of Array.from(allHeadings)) { + const wrapper = heading.closest('[data-node-view-wrapper]'); + if (wrapper) { + const wrapperId = wrapper.getAttribute('data-heading-id'); + if (wrapperId === result.id) { + scrollAndHighlight(wrapper as HTMLElement); + return; + } + } + + // Also check text-based matching with same ID logic + const headingText = heading.textContent?.toLowerCase() + .replace(/\s+/g, '-') + .replace(/[^a-z0-9\u3131-\u3163\uac00-\ud7a3-]+/g, '') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') || ''; + if (headingText === result.id) { + scrollAndHighlight(heading as HTMLElement); + return; + } + } + } + } + + // Try to find in ProseMirror editor content by text + const proseMirror = document.querySelector('.ProseMirror'); + + if (proseMirror) { + const allElements = proseMirror.querySelectorAll('h1, h2, h3, h4, h5, h6, p, li, blockquote'); + + // Try to find by text content match + for (const el of Array.from(allElements)) { + const elementText = el.textContent || ''; + if (elementText.trim() === result.text.trim()) { + scrollAndHighlight(el as HTMLElement); + return; + } + } + } + }; + + const scrollAndHighlight = (element: HTMLElement) => { + // Simple and reliable scroll (same as Document Overview) + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + + // Add highlight effect + element.classList.add('bg-yellow-200', 'dark:bg-yellow-900', 'ring-2', 'ring-yellow-400', 'transition-all', 'duration-300', 'rounded'); + + setTimeout(() => { + element.classList.remove('bg-yellow-200', 'dark:bg-yellow-900', 'ring-2', 'ring-yellow-400'); + }, 3000); + }; + + // Highlight matching text + const highlightMatch = (text: string, query: string) => { + if (!query.trim()) return text; + + const regex = new RegExp(`(${query})`, 'gi'); + const parts = text.split(regex); + + return parts.map((part, index) => + regex.test(part) ? ( + {part} + ) : ( + {part} + ) + ); + }; + + return { + searchQuery, + setSearchQuery, + searchResults, + showSearchResults, + setShowSearchResults, + handleSearch, + handleSearchKeyDown, + handleClearSearch, + handleNavigateToResult, + highlightMatch, + }; +}; + diff --git a/nextjs/src/features/document-edit/ui/index.ts b/nextjs/src/features/document-edit/ui/index.ts new file mode 100644 index 0000000..82f6347 --- /dev/null +++ b/nextjs/src/features/document-edit/ui/index.ts @@ -0,0 +1,5 @@ +// Document edit UI components +// export * from './DocumentEditor'; + +export {}; + diff --git a/nextjs/src/features/document-management/index.ts b/nextjs/src/features/document-management/index.ts new file mode 100644 index 0000000..7a689d5 --- /dev/null +++ b/nextjs/src/features/document-management/index.ts @@ -0,0 +1,3 @@ +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/features/document-management/model/index.ts b/nextjs/src/features/document-management/model/index.ts new file mode 100644 index 0000000..84908d3 --- /dev/null +++ b/nextjs/src/features/document-management/model/index.ts @@ -0,0 +1,2 @@ +export * from './store'; + diff --git a/nextjs/src/features/document-management/model/store.ts b/nextjs/src/features/document-management/model/store.ts new file mode 100644 index 0000000..998c662 --- /dev/null +++ b/nextjs/src/features/document-management/model/store.ts @@ -0,0 +1,153 @@ +import { useCallback, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { documentApi } from '@/entities/document/api'; +import { useDocumentStore } from '@/entities/document/model/store'; +import type { DocumentWithRelations, DocumentInput } from '@/entities/document/model'; + +// Document management feature store +export const useDocumentManagementStore = () => { + const entityStore = useDocumentStore.getState(); + const router = useRouter(); + const [isCreating, setIsCreating] = useState(false); + + const fetchDocuments = useCallback(async () => { + entityStore.setLoading(true); + try { + const data = await documentApi.getDocuments(); + entityStore.readDocuments(data); + } catch (error) { + console.error("Error fetching documents:", error); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const fetchDocumentsInFolder = useCallback(async (folderId: string) => { + try { + const data = await documentApi.getDocuments(); + // Filter by folder and code files + return data.filter((doc: any) => + doc.folderId === folderId && doc.type !== 'CODE_FILE' + ); + } catch (error) { + console.error("Error fetching documents in folder:", error); + return []; + } + }, []); + + const createDocument = useCallback(async (folderId?: string | null) => { + if (isCreating) { + console.log("Document creation already in progress"); + return; + } + + try { + setIsCreating(true); + const newDocument: DocumentInput = { + title: "Untitled", + type: 'PAGE', + isPublished: false, + isArchived: false, + folderId: folderId || undefined, + }; + const created = await documentApi.createDocument(newDocument); + await fetchDocuments(); + router.push(`/documents/${created.id}`); + return created; + } catch (error) { + console.error("Error creating document:", error); + throw error; + } finally { + setIsCreating(false); + } + }, [router, fetchDocuments, isCreating]); + + const deleteDocumentFromFolder = useCallback(async (documentId: string) => { + try { + await documentApi.deleteDocument(documentId); + await fetchDocuments(); + } catch (error) { + console.error("Error deleting document:", error); + throw error; + } + }, [fetchDocuments]); + + const updateDocumentInStore = useCallback((documentId: string, updates: Partial) => { + entityStore.updateDocument({ + ...entityStore.documents.find(d => d.id === documentId)!, + ...updates + } as DocumentWithRelations); + }, [entityStore]); + + const searchDocuments = useCallback(async (query: string) => { + entityStore.setLoading(true); + try { + const documents = await documentApi.getDocuments(); + // Filter documents by query + const filtered = documents.filter(doc => + doc.title.toLowerCase().includes(query.toLowerCase()) + ); + entityStore.readDocuments(filtered); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const archiveDocument = useCallback(async (documentId: string) => { + entityStore.setLoading(true); + try { + await documentApi.updateDocument(documentId, { isArchived: true }); + const documents = await documentApi.getDocuments(); + entityStore.readDocuments(documents); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const restoreDocument = useCallback(async (documentId: string) => { + entityStore.setLoading(true); + try { + await documentApi.updateDocument(documentId, { isArchived: false }); + const documents = await documentApi.getDocuments(); + entityStore.readDocuments(documents); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const duplicateDocument = useCallback(async (documentId: string) => { + entityStore.setLoading(true); + try { + const original = await documentApi.getDocument(documentId); + const newDocument: DocumentInput = { + title: `${original.title} (Copy)`, + content: original.content, + icon: original.icon, + cover: original.cover, + type: original.type, + isPublished: false, + isArchived: false, + folderId: original.folderId, + }; + const created = await documentApi.createDocument(newDocument); + entityStore.createDocument(created as DocumentWithRelations); + return created; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + return { + fetchDocuments, + fetchDocumentsInFolder, + createDocument, + deleteDocumentFromFolder, + updateDocumentInStore, + searchDocuments, + archiveDocument, + restoreDocument, + duplicateDocument, + isCreating, + }; +}; + diff --git a/nextjs/src/features/document-management/ui/index.ts b/nextjs/src/features/document-management/ui/index.ts new file mode 100644 index 0000000..2ad3a6b --- /dev/null +++ b/nextjs/src/features/document-management/ui/index.ts @@ -0,0 +1,6 @@ +// Document management UI components +// export * from './DocumentList'; +// export * from './DocumentSearch'; + +export {}; + diff --git a/nextjs/src/features/folder-management/index.ts b/nextjs/src/features/folder-management/index.ts new file mode 100644 index 0000000..7a689d5 --- /dev/null +++ b/nextjs/src/features/folder-management/index.ts @@ -0,0 +1,3 @@ +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/features/folder-management/model/index.ts b/nextjs/src/features/folder-management/model/index.ts new file mode 100644 index 0000000..84908d3 --- /dev/null +++ b/nextjs/src/features/folder-management/model/index.ts @@ -0,0 +1,2 @@ +export * from './store'; + diff --git a/nextjs/src/features/folder-management/model/store.ts b/nextjs/src/features/folder-management/model/store.ts new file mode 100644 index 0000000..e6a85c5 --- /dev/null +++ b/nextjs/src/features/folder-management/model/store.ts @@ -0,0 +1,143 @@ +import { useCallback, useState } from 'react'; +import { folderApi } from '@/entities/folder/api'; +import { useFolderStore } from '@/entities/folder/model/store'; +import type { FolderWithRelations, FolderInput } from '@/entities/folder/model'; + +// Folder management feature store +export const useFolderManagementStore = () => { + const entityStore = useFolderStore.getState(); + const [isCreating, setIsCreating] = useState(false); + + const fetchFolders = useCallback(async () => { + entityStore.setLoading(true); + try { + const data = await folderApi.getFolders(); + entityStore.readFolders(data); + } catch (error) { + console.error("Error fetching folders:", error); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const fetchFolder = useCallback(async (folderId: string) => { + try { + return await folderApi.getFolder(folderId); + } catch (error) { + console.error("Error fetching folder:", error); + return null; + } + }, []); + + const createFolder = useCallback(async (name: string, parentId?: string | null) => { + if (isCreating) { + console.log("Folder creation already in progress, skipping duplicate call"); + return null; + } + + try { + setIsCreating(true); + const newFolder: FolderInput = { + name: name.trim(), + icon: undefined, + color: undefined, + isArchived: false, + parentId: parentId || undefined, + }; + const created = await folderApi.createFolder(newFolder); + await fetchFolders(); + return created; + } catch (error) { + console.error("Error creating folder:", error); + return null; + } finally { + setIsCreating(false); + } + }, [isCreating, fetchFolders]); + + const updateFolder = useCallback(async (folderId: string, name: string) => { + try { + await folderApi.updateFolder(folderId, { name: name.trim() }); + await fetchFolders(); + } catch (error) { + console.error("Error updating folder:", error); + } + }, [fetchFolders]); + + const deleteFolderFromList = useCallback(async (folderId: string) => { + try { + await folderApi.deleteFolder(folderId); + await fetchFolders(); + return true; + } catch (error) { + console.error("Error deleting folder:", error); + return false; + } + }, [fetchFolders]); + + const archiveFolder = useCallback(async (folderId: string) => { + entityStore.setLoading(true); + try { + await folderApi.updateFolder(folderId, { isArchived: true }); + const folders = await folderApi.getFolders(); + entityStore.readFolders(folders); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const restoreFolder = useCallback(async (folderId: string) => { + entityStore.setLoading(true); + try { + await folderApi.updateFolder(folderId, { isArchived: false }); + const folders = await folderApi.getFolders(); + entityStore.readFolders(folders); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const moveFolder = useCallback(async (folderId: string, parentId: string | undefined) => { + entityStore.setLoading(true); + try { + await folderApi.updateFolder(folderId, { parentId }); + const folders = await folderApi.getFolders(); + entityStore.readFolders(folders); + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const duplicateFolder = useCallback(async (folderId: string) => { + entityStore.setLoading(true); + try { + const original = await folderApi.getFolder(folderId); + const newFolder: FolderInput = { + name: `${original.name} (Copy)`, + icon: original.icon, + color: original.color, + isArchived: false, + parentId: original.parentId, + }; + const created = await folderApi.createFolder(newFolder); + entityStore.createFolder(created as FolderWithRelations); + return created; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + return { + fetchFolders, + fetchFolder, + createFolder, + updateFolder, + deleteFolderFromList, + archiveFolder, + restoreFolder, + moveFolder, + duplicateFolder, + isCreating, + }; +}; + diff --git a/nextjs/src/features/folder-management/ui/index.ts b/nextjs/src/features/folder-management/ui/index.ts new file mode 100644 index 0000000..736fa00 --- /dev/null +++ b/nextjs/src/features/folder-management/ui/index.ts @@ -0,0 +1,6 @@ +// Folder management UI components +// export * from './FolderTree'; +// export * from './FolderActions'; + +export {}; + diff --git a/nextjs/src/features/index.ts b/nextjs/src/features/index.ts new file mode 100644 index 0000000..aea3315 --- /dev/null +++ b/nextjs/src/features/index.ts @@ -0,0 +1,6 @@ +// Export all features +export * from './document-edit'; +export * from './document-management'; +export * from './folder-management'; +export * from './template-apply'; + diff --git a/nextjs/src/features/template-apply/index.ts b/nextjs/src/features/template-apply/index.ts new file mode 100644 index 0000000..7a689d5 --- /dev/null +++ b/nextjs/src/features/template-apply/index.ts @@ -0,0 +1,3 @@ +export * from './model'; +export * from './ui'; + diff --git a/nextjs/src/features/template-apply/model/index.ts b/nextjs/src/features/template-apply/model/index.ts new file mode 100644 index 0000000..84908d3 --- /dev/null +++ b/nextjs/src/features/template-apply/model/index.ts @@ -0,0 +1,2 @@ +export * from './store'; + diff --git a/nextjs/src/features/template-apply/model/store.ts b/nextjs/src/features/template-apply/model/store.ts new file mode 100644 index 0000000..3c31421 --- /dev/null +++ b/nextjs/src/features/template-apply/model/store.ts @@ -0,0 +1,42 @@ +import { useCallback } from 'react'; +import { templateApi } from '@/entities/template/api'; +import { useTemplateStore } from '@/entities/template/model/store'; +import type { DatabaseTemplate } from '@/entities/template/model'; + +// Template apply feature store +export const useTemplateApplyStore = () => { + const entityStore = useTemplateStore.getState(); + + const applyTemplate = useCallback(async (documentId: string, template: DatabaseTemplate) => { + entityStore.setLoading(true); + try { + // Apply template content to document + await templateApi.updateTemplate(template.id, { + // Template application logic + }); + return template; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + const createTemplateFromDocument = useCallback(async (documentId: string, templateData: Partial) => { + entityStore.setLoading(true); + try { + const template = await templateApi.createTemplate({ + ...templateData, + content: templateData.content || {}, + }); + entityStore.createTemplate(template); + return template; + } finally { + entityStore.setLoading(false); + } + }, [entityStore]); + + return { + applyTemplate, + createTemplateFromDocument, + }; +}; + diff --git a/nextjs/src/features/template-apply/ui/index.ts b/nextjs/src/features/template-apply/ui/index.ts new file mode 100644 index 0000000..b8d9b97 --- /dev/null +++ b/nextjs/src/features/template-apply/ui/index.ts @@ -0,0 +1,6 @@ +// Template apply UI components +// export * from './TemplateBrowser'; +// export * from './TemplateSelector'; + +export {}; + diff --git a/nextjs/src/features/todo-management/index.ts b/nextjs/src/features/todo-management/index.ts new file mode 100644 index 0000000..e963376 --- /dev/null +++ b/nextjs/src/features/todo-management/index.ts @@ -0,0 +1,2 @@ +export * from './ui' + diff --git a/nextjs/src/features/todo-management/ui/TodoCreateForm.tsx b/nextjs/src/features/todo-management/ui/TodoCreateForm.tsx new file mode 100644 index 0000000..d491149 --- /dev/null +++ b/nextjs/src/features/todo-management/ui/TodoCreateForm.tsx @@ -0,0 +1,68 @@ +'use client' + +import { useState } from 'react' +import { Button } from '@/shared/ui/button' +import { Input } from '@/shared/ui/input' +import { Plus } from 'lucide-react' +import { useTodoStore } from '@/entities/todo' + +export function TodoCreateForm() { + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [isExpanded, setIsExpanded] = useState(false) + const { addTodo } = useTodoStore() + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + + if (!title.trim()) return + + await addTodo({ + title: title.trim(), + description: description.trim() || undefined, + }) + + setTitle('') + setDescription('') + setIsExpanded(false) + } + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + handleSubmit(e) + } else if (e.key === 'Escape') { + setIsExpanded(false) + setTitle('') + setDescription('') + } + } + + return ( +
+
+ setTitle(e.target.value)} + onFocus={() => setIsExpanded(true)} + onKeyDown={handleKeyDown} + placeholder="새로운 할 일 추가..." + className="flex-1" + /> + +
+ + {isExpanded && ( + setDescription(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="설명 (선택사항)" + /> + )} +
+ ) +} + diff --git a/nextjs/src/features/todo-management/ui/TodoFilter.tsx b/nextjs/src/features/todo-management/ui/TodoFilter.tsx new file mode 100644 index 0000000..f7b70df --- /dev/null +++ b/nextjs/src/features/todo-management/ui/TodoFilter.tsx @@ -0,0 +1,52 @@ +'use client' + +import { Button } from '@/shared/ui/button' +import { useTodoStore } from '@/entities/todo' +import { TodoFilter as TodoFilterType } from '@/entities/todo' + +export function TodoFilter() { + const { filter, setFilter, clearCompleted, todos } = useTodoStore() + + const completedCount = todos.filter(t => t.completed).length + const activeCount = todos.filter(t => !t.completed).length + + return ( +
+
+ + + +
+ + {completedCount > 0 && ( + + )} +
+ ) +} + diff --git a/nextjs/src/features/todo-management/ui/index.ts b/nextjs/src/features/todo-management/ui/index.ts new file mode 100644 index 0000000..aec6bae --- /dev/null +++ b/nextjs/src/features/todo-management/ui/index.ts @@ -0,0 +1,3 @@ +export * from './TodoCreateForm' +export * from './TodoFilter' + diff --git a/nextjs/src/shared/api/client.ts b/nextjs/src/shared/api/client.ts new file mode 100644 index 0000000..34e6b3c --- /dev/null +++ b/nextjs/src/shared/api/client.ts @@ -0,0 +1,65 @@ +// API client with automatic cookie handling (credentials: 'include') + +export const apiFetch = async (url: string, options: RequestInit = {}) => { + return fetch(url, { + ...options, + credentials: 'include', // Automatically include cookies + }) +} + +export const apiGet = async (url: string): Promise => { + const response = await apiFetch(url) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPost = async (url: string, data?: any): Promise => { + const response = await apiFetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: data ? JSON.stringify(data) : undefined, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPut = async (url: string, data?: any): Promise => { + const response = await apiFetch(url, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: data ? JSON.stringify(data) : undefined, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiDelete = async (url: string): Promise => { + const response = await apiFetch(url, { + method: 'DELETE', + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPostFormData = async (url: string, formData: FormData): Promise => { + const response = await apiFetch(url, { + method: 'POST', + body: formData, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} diff --git a/nextjs/src/shared/api/index.ts b/nextjs/src/shared/api/index.ts new file mode 100644 index 0000000..83dae76 --- /dev/null +++ b/nextjs/src/shared/api/index.ts @@ -0,0 +1 @@ +export * from './client' diff --git a/nextjs/src/shared/config/s3.ts b/nextjs/src/shared/config/s3.ts new file mode 100644 index 0000000..849aa7f --- /dev/null +++ b/nextjs/src/shared/config/s3.ts @@ -0,0 +1,20 @@ +// S3 설정 +export const S3_CONFIG = { + BUCKET_NAME: process.env.AWS_S3_BUCKET_NAME || 'jooeng', + REGION: process.env.AWS_REGION || 'ap-northeast-2', + ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || '', + SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY || '', + BUCKET_URL: process.env.AWS_S3_BUCKET_URL || 'https://jooeng.s3.ap-northeast-2.amazonaws.com', +} as const; + +// S3 클라이언트 인스턴스 (서버 사이드에서만 사용) +import { S3Client } from '@aws-sdk/client-s3'; + +export const s3Client = new S3Client({ + region: S3_CONFIG.REGION, + credentials: { + accessKeyId: S3_CONFIG.ACCESS_KEY_ID, + secretAccessKey: S3_CONFIG.SECRET_ACCESS_KEY, + }, +}); + diff --git a/nextjs/src/shared/hooks/index.ts b/nextjs/src/shared/hooks/index.ts new file mode 100644 index 0000000..ebcfd9e --- /dev/null +++ b/nextjs/src/shared/hooks/index.ts @@ -0,0 +1,2 @@ +export * from './use-scroll-top'; +export * from './use-folder-navigation'; diff --git a/nextjs/src/shared/hooks/use-folder-navigation.tsx b/nextjs/src/shared/hooks/use-folder-navigation.tsx new file mode 100644 index 0000000..cce17e7 --- /dev/null +++ b/nextjs/src/shared/hooks/use-folder-navigation.tsx @@ -0,0 +1,42 @@ +import { useState, useCallback } from "react"; +import { FolderWithRelations } from "@/entities/folder/model"; + +export const useFolderNavigation = () => { + const [currentFolder, setCurrentFolder] = useState(null); + const [folderHistory, setFolderHistory] = useState([]); + + const navigateToFolder = useCallback((folder: FolderWithRelations | null) => { + if (folder) { + setFolderHistory(prev => [...prev, folder.id]); + } else { + setFolderHistory([]); + } + setCurrentFolder(folder); + }, []); + + const goBack = useCallback(() => { + if (currentFolder?.parentId) { + // Will navigate to parent, component will handle fetching + return currentFolder.parentId; + } else { + // Go to root + setCurrentFolder(null); + setFolderHistory([]); + return null; + } + }, [currentFolder]); + + const goToRoot = useCallback(() => { + setCurrentFolder(null); + setFolderHistory([]); + }, []); + + return { + currentFolder, + folderHistory, + navigateToFolder, + goBack, + goToRoot, + }; +}; + diff --git a/nextjs/src/shared/hooks/use-scroll-top.tsx b/nextjs/src/shared/hooks/use-scroll-top.tsx new file mode 100644 index 0000000..3158ca4 --- /dev/null +++ b/nextjs/src/shared/hooks/use-scroll-top.tsx @@ -0,0 +1,21 @@ +import { useState, useEffect } from "react"; + +export const useScrollTop = (threshold = 10) => { + const [scrolled,setScrolled] = useState(false); + + useEffect(() => { + const handleScroll = () => { + if(window.scrollY > threshold){ + setScrolled(true); + } + else{ + setScrolled(false); + } + }; + + window.addEventListener("scroll",handleScroll); + return () => window.removeEventListener("scroll", handleScroll); + }, [threshold]); + + return scrolled; +} \ No newline at end of file diff --git a/nextjs/src/shared/index.ts b/nextjs/src/shared/index.ts new file mode 100644 index 0000000..a41686e --- /dev/null +++ b/nextjs/src/shared/index.ts @@ -0,0 +1,6 @@ +// Shared layer barrel exports +export * from './ui' +export * from './lib' +export * from './api' +export * from './types' + diff --git a/nextjs/src/shared/lib/api-client.ts b/nextjs/src/shared/lib/api-client.ts new file mode 100644 index 0000000..d2c32a2 --- /dev/null +++ b/nextjs/src/shared/lib/api-client.ts @@ -0,0 +1,66 @@ +// API client with automatic cookie handling (credentials: 'include') + +export const apiFetch = async (url: string, options: RequestInit = {}) => { + return fetch(url, { + ...options, + credentials: 'include', // Automatically include cookies + }) +} + +export const apiGet = async (url: string): Promise => { + const response = await apiFetch(url) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPost = async (url: string, data?: any): Promise => { + const response = await apiFetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: data ? JSON.stringify(data) : undefined, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPut = async (url: string, data?: any): Promise => { + const response = await apiFetch(url, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: data ? JSON.stringify(data) : undefined, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiDelete = async (url: string): Promise => { + const response = await apiFetch(url, { + method: 'DELETE', + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + +export const apiPostFormData = async (url: string, formData: FormData): Promise => { + const response = await apiFetch(url, { + method: 'POST', + body: formData, + }) + if (!response.ok) { + throw new Error(`API request failed: ${response.statusText}`) + } + return response.json() +} + diff --git a/nextjs/src/shared/lib/auth.ts b/nextjs/src/shared/lib/auth.ts new file mode 100644 index 0000000..743a5ea --- /dev/null +++ b/nextjs/src/shared/lib/auth.ts @@ -0,0 +1,59 @@ +import jwt from 'jsonwebtoken' +import bcrypt from 'bcryptjs' +import { db } from './db' + +const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production' + +export interface JWTPayload { + userId: string + email: string +} + +export async function hashPassword(password: string): Promise { + return bcrypt.hash(password, 12) +} + +export async function verifyPassword(password: string, hashedPassword: string): Promise { + return bcrypt.compare(password, hashedPassword) +} + +export function generateToken(payload: JWTPayload): string { + return jwt.sign(payload, JWT_SECRET, { expiresIn: '7d' }) +} + +export function verifyToken(token: string): JWTPayload | null { + try { + return jwt.verify(token, JWT_SECRET) as JWTPayload + } catch { + return null + } +} + +export async function createUser(email: string, password: string, name?: string) { + const hashedPassword = await hashPassword(password) + + return db.user.create({ + data: { + email, + password: hashedPassword, + name, + }, + }) +} + +export async function authenticateUser(email: string, password: string) { + const user = await db.user.findUnique({ + where: { email }, + }) + + if (!user) { + return null + } + + const isValid = await verifyPassword(password, user.password) + if (!isValid) { + return null + } + + return user +} diff --git a/nextjs/src/shared/lib/db.ts b/nextjs/src/shared/lib/db.ts new file mode 100644 index 0000000..3f64c49 --- /dev/null +++ b/nextjs/src/shared/lib/db.ts @@ -0,0 +1,18 @@ +import { PrismaClient } from '@prisma/client' + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const db = + globalForPrisma.prisma ?? + new PrismaClient({ + datasources: { + db: { + url: process.env.DATABASE_URL + "?connection_limit=5&pool_timeout=20" + } + }, + log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'], + }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db diff --git a/nextjs/src/shared/lib/index.ts b/nextjs/src/shared/lib/index.ts new file mode 100644 index 0000000..0b1cd4a --- /dev/null +++ b/nextjs/src/shared/lib/index.ts @@ -0,0 +1,2 @@ +export * from './utils' +export * from './s3' diff --git a/nextjs/src/shared/lib/metadata-extractor.ts b/nextjs/src/shared/lib/metadata-extractor.ts new file mode 100644 index 0000000..6ea4f85 --- /dev/null +++ b/nextjs/src/shared/lib/metadata-extractor.ts @@ -0,0 +1,186 @@ +import { parse } from 'node-html-parser'; + +export interface BookmarkMetadata { + title?: string; + description?: string; + image?: string; + url: string; + domain?: string; + author?: string; +} + +function extractMetaContent(doc: any, property: string, name?: string): string { + // Try Open Graph first + let element = doc.querySelector(`meta[property="${property}"]`); + if (element) { + return element.getAttribute('content') || ''; + } + + // Try Twitter Card + if (property.startsWith('og:')) { + const twitterProperty = property.replace('og:', 'twitter:'); + element = doc.querySelector(`meta[name="${twitterProperty}"]`); + if (element) { + return element.getAttribute('content') || ''; + } + } + + // Try standard meta name + if (name) { + element = doc.querySelector(`meta[name="${name}"]`); + if (element) { + return element.getAttribute('content') || ''; + } + } + + return ''; +} + +function extractTitle(doc: any): string { + // Try title tag first + const titleElement = doc.querySelector('title'); + if (titleElement) { + const title = titleElement.textContent?.trim(); + if (title && title.length > 0) { + return title; + } + } + + // Try Open Graph title + const ogTitle = extractMetaContent(doc, 'og:title'); + if (ogTitle) return ogTitle; + + // Try Twitter title + const twitterTitle = extractMetaContent(doc, 'twitter:title'); + if (twitterTitle) return twitterTitle; + + return ''; +} + +function extractDescription(doc: any): string { + // Try Open Graph description + const ogDesc = extractMetaContent(doc, 'og:description'); + if (ogDesc) return ogDesc; + + // Try Twitter description + const twitterDesc = extractMetaContent(doc, 'twitter:description'); + if (twitterDesc) return twitterDesc; + + // Try standard meta description + const metaDesc = extractMetaContent(doc, 'description'); + if (metaDesc) return metaDesc; + + return ''; +} + +function extractImage(doc: any, baseUrl: string): string { + // Try Open Graph image + let image = extractMetaContent(doc, 'og:image'); + if (image) { + // Convert relative URLs to absolute + if (image.startsWith('//')) { + image = 'https:' + image; + } else if (image.startsWith('/')) { + image = new URL(image, baseUrl).toString(); + } + return image; + } + + // Try Twitter image + image = extractMetaContent(doc, 'twitter:image'); + if (image) { + // Convert relative URLs to absolute + if (image.startsWith('//')) { + image = 'https:' + image; + } else if (image.startsWith('/')) { + image = new URL(image, baseUrl).toString(); + } + return image; + } + + return ''; +} + +function extractAuthor(doc: any): string { + // Try Open Graph site_name as author fallback + const siteName = extractMetaContent(doc, 'og:site_name'); + if (siteName) return siteName; + + // Try author meta + const author = extractMetaContent(doc, 'author'); + if (author) return author; + + return ''; +} + +export async function extractBookmarkMetadata(url: string): Promise { + try { + console.log('Extracting metadata for URL:', url); + + // Validate URL + new URL(url); + + // Fetch the webpage + const response = await fetch(url, { + method: 'GET', + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; Jotion/1.0; +https://jotion.com)', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + }, + }); + + console.log('Response status:', response.status); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + const html = await response.text(); + console.log('HTML length:', html.length); + + const doc = parse(html); + + // Extract metadata + const title = extractTitle(doc); + const description = extractDescription(doc); + const image = extractImage(doc, url); + const author = extractAuthor(doc); + + // Extract domain from URL + const domain = new URL(url).hostname; + + const metadata = { + title: title || '', + description: description || '', + image: image || '', + url, + domain, + author: author || '', + }; + + console.log('Extracted metadata:', metadata); + return metadata; + } catch (error) { + console.error('Error extracting bookmark metadata:', error); + + // Return basic info even if metadata extraction fails + const domain = new URL(url).hostname; + return { + title: '', + description: '', + image: '', + url, + domain, + author: '', + }; + } +} + +export function isValidUrl(string: string): boolean { + try { + new URL(string); + return true; + } catch (_) { + return false; + } +} diff --git a/nextjs/src/shared/lib/middleware.ts b/nextjs/src/shared/lib/middleware.ts new file mode 100644 index 0000000..ae83cfc --- /dev/null +++ b/nextjs/src/shared/lib/middleware.ts @@ -0,0 +1,45 @@ +import { NextRequest, NextResponse } from 'next/server' +import { verifyToken } from './auth' + +export function withAuth(handler: (req: NextRequest, userId: string) => Promise) { + return async (req: NextRequest) => { + // Handle CORS preflight requests + if (req.method === 'OPTIONS') { + return new NextResponse(null, { + status: 200, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + }) + } + + // Get token from cookie + const token = req.cookies.get('auth-token')?.value + + if (!token) { + const response = NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + // Add CORS headers for error responses + response.headers.set('Access-Control-Allow-Origin', '*') + return response + } + + const payload = verifyToken(token) + if (!payload) { + const response = NextResponse.json({ error: 'Invalid token' }, { status: 401 }) + // Add CORS headers for error responses + response.headers.set('Access-Control-Allow-Origin', '*') + return response + } + + const result = await handler(req, payload.userId) + + // Add CORS headers to successful responses + result.headers.set('Access-Control-Allow-Origin', '*') + result.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') + result.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization') + + return result + } +} diff --git a/nextjs/src/shared/lib/prisma.ts b/nextjs/src/shared/lib/prisma.ts new file mode 100644 index 0000000..850ca56 --- /dev/null +++ b/nextjs/src/shared/lib/prisma.ts @@ -0,0 +1,18 @@ +import { PrismaClient } from '@prisma/client' + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined +} + +export const prisma = + globalForPrisma.prisma ?? + new PrismaClient({ + datasources: { + db: { + url: process.env.DATABASE_URL + "?connection_limit=5&pool_timeout=20" + } + }, + log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'], + }) + +if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma diff --git a/nextjs/src/shared/lib/s3.ts b/nextjs/src/shared/lib/s3.ts new file mode 100644 index 0000000..70ae432 --- /dev/null +++ b/nextjs/src/shared/lib/s3.ts @@ -0,0 +1,168 @@ +import { DeleteObjectCommand, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; +import { S3_CONFIG, s3Client } from '@/shared/config/s3'; + +/** + * Upload a file to S3 (Server-side) + * @param file - The file to upload (File or Buffer) + * @param folder - The folder path (e.g., 'images', 'audio', 'documents') + * @returns The public URL and key of the uploaded file + */ +export async function uploadFileServer( + file: File | Buffer, + fileName: string, + fileType: string, + folder: 'images' | 'audio' | 'documents' = 'documents' +): Promise<{ url: string; path: string }> { + try { + const fileExt = fileName.split('.').pop(); + const uniqueFileName = `${Date.now()}-${Math.random().toString(36).substring(2)}.${fileExt}`; + const fileKey = `jotion-uploads/${folder}/${uniqueFileName}`; + + // Convert File to Buffer if needed + let fileBuffer: Buffer; + if (file instanceof File) { + const arrayBuffer = await file.arrayBuffer(); + fileBuffer = Buffer.from(arrayBuffer); + } else { + fileBuffer = file; + } + + // Upload directly to S3 + const command = new PutObjectCommand({ + Bucket: S3_CONFIG.BUCKET_NAME, + Key: fileKey, + Body: fileBuffer, + ContentType: fileType, + }); + + await s3Client.send(command); + + // Return the public URL + const publicUrl = `${S3_CONFIG.BUCKET_URL}/${fileKey}`; + + return { + url: publicUrl, + path: fileKey, + }; + } catch (error: any) { + console.error('S3 upload error:', error); + throw new Error(`Failed to upload file: ${error.message}`); + } +} + +/** + * Upload a file to S3 (Client-side using presigned URL) + * @param file - The file to upload + * @param folder - The folder path (e.g., 'images', 'audio', 'documents') + * @returns The public URL and key of the uploaded file + */ +export async function uploadFile( + file: File, + folder: 'images' | 'audio' | 'documents' = 'documents' +): Promise<{ url: string; path: string }> { + try { + const fileExt = file.name.split('.').pop(); + const fileName = `${Date.now()}-${Math.random().toString(36).substring(2)}.${fileExt}`; + const fileKey = `jotion-uploads/${folder}/${fileName}`; + + // Get upload URL + const uploadUrlResponse = await fetch('/api/upload-url', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + fileName, + fileType: file.type, + folder: `jotion-uploads/${folder}`, + }), + }); + + if (!uploadUrlResponse.ok) { + throw new Error('Failed to get upload URL'); + } + + const { uploadUrl, fileKey: returnedFileKey } = await uploadUrlResponse.json(); + const finalFileKey = returnedFileKey || fileKey; + + // Upload to S3 using presigned URL + const uploadResponse = await fetch(uploadUrl, { + method: 'PUT', + body: file, + headers: { + 'Content-Type': file.type, + }, + }); + + if (!uploadResponse.ok) { + throw new Error(`Failed to upload file: ${uploadResponse.statusText}`); + } + + // Return the public URL + const publicUrl = `${S3_CONFIG.BUCKET_URL}/${finalFileKey}`; + + return { + url: publicUrl, + path: finalFileKey, + }; + } catch (error: any) { + console.error('S3 upload error:', error); + throw new Error(`Failed to upload file: ${error.message}`); + } +} + +/** + * Delete a file from S3 + * @param path - The file key to delete + */ +export async function deleteFile(path: string): Promise { + try { + const command = new DeleteObjectCommand({ + Bucket: S3_CONFIG.BUCKET_NAME, + Key: path, + }); + + await s3Client.send(command); + } catch (error: any) { + console.error('S3 delete error:', error); + throw new Error(`Failed to delete file: ${error.message}`); + } +} + +/** + * Get public URL for a file in S3 + * @param path - The file key + * @returns The public URL + */ +export function getFileUrl(path: string): string { + return `${S3_CONFIG.BUCKET_URL}/${path}`; +} + +/** + * Get signed download URL for a file in S3 + * @param path - The file key + * @returns The signed download URL + */ +export async function getDownloadUrl(path: string): Promise { + try { + const response = await fetch('/api/download-url', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ fileKey: path }), + }); + + if (!response.ok) { + throw new Error('Failed to get download URL'); + } + + const { downloadUrl } = await response.json(); + return downloadUrl; + } catch (error: any) { + console.error('Failed to get download URL:', error); + throw new Error(`Failed to get download URL: ${error.message}`); + } +} + diff --git a/nextjs/src/shared/lib/supabase.ts b/nextjs/src/shared/lib/supabase.ts new file mode 100644 index 0000000..c6a18b7 --- /dev/null +++ b/nextjs/src/shared/lib/supabase.ts @@ -0,0 +1,94 @@ +import { createClient } from '@supabase/supabase-js'; + +// Support both server-side and client-side environment variables +const supabaseUrl = + process.env.NEXT_PUBLIC_SUPABASE_URL || + process.env.SUPABASE_URL || + ''; + +const supabaseAnonKey = + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || + process.env.SUPABASE_ANON_KEY || + ''; + +if (!supabaseUrl || !supabaseAnonKey) { + console.warn('Supabase credentials are not set. Please set SUPABASE_URL and SUPABASE_ANON_KEY (or NEXT_PUBLIC_* variants) in your environment variables.'); + console.warn('Current values:', { + supabaseUrl: supabaseUrl ? 'set' : 'not set', + supabaseAnonKey: supabaseAnonKey ? 'set' : 'not set', + }); +} + +export const supabase = createClient(supabaseUrl, supabaseAnonKey); + +// Server-side Supabase client with service role (bypasses RLS) +// NEVER expose this to the client! +const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY || ''; +export const supabaseAdmin = supabaseServiceRoleKey + ? createClient(supabaseUrl, supabaseServiceRoleKey, { + auth: { + autoRefreshToken: false, + persistSession: false + } + }) + : null; + +// Storage bucket name for file uploads +export const STORAGE_BUCKET = 'jotion-files'; + +/** + * Upload a file to Supabase Storage + * @param file - The file to upload + * @param folder - The folder path (e.g., 'images', 'audio', 'documents') + * @returns The public URL of the uploaded file + */ +export async function uploadFile( + file: File, + folder: 'images' | 'audio' | 'documents' = 'documents' +): Promise<{ url: string; path: string }> { + const fileExt = file.name.split('.').pop(); + const fileName = `${Date.now()}-${Math.random().toString(36).substring(2)}.${fileExt}`; + const filePath = `${folder}/${fileName}`; + + // Use admin client to bypass RLS, fallback to regular client + const client = supabaseAdmin || supabase; + + const { data, error } = await client.storage + .from(STORAGE_BUCKET) + .upload(filePath, file, { + cacheControl: '3600', + upsert: false, + }); + + if (error) { + console.error('Supabase upload error:', error); + throw new Error(`Failed to upload file: ${error.message}`); + } + + const { data: { publicUrl } } = client.storage + .from(STORAGE_BUCKET) + .getPublicUrl(filePath); + + return { + url: publicUrl, + path: filePath, + }; +} + +/** + * Delete a file from Supabase Storage + * @param path - The file path to delete + */ +export async function deleteFile(path: string): Promise { + // Use admin client to bypass RLS, fallback to regular client + const client = supabaseAdmin || supabase; + + const { error } = await client.storage + .from(STORAGE_BUCKET) + .remove([path]); + + if (error) { + throw new Error(`Failed to delete file: ${error.message}`); + } +} + diff --git a/nextjs/src/shared/lib/utils.ts b/nextjs/src/shared/lib/utils.ts new file mode 100644 index 0000000..d084cca --- /dev/null +++ b/nextjs/src/shared/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/nextjs/src/shared/types/bookmark.ts b/nextjs/src/shared/types/bookmark.ts new file mode 100644 index 0000000..de9805b --- /dev/null +++ b/nextjs/src/shared/types/bookmark.ts @@ -0,0 +1,27 @@ +// Bookmark related types +export interface BookmarkAttributes { + url: string; + title?: string; + description?: string; + image?: string; + domain?: string; + author?: string; + loading?: boolean; + error?: string; +} + +export interface BookmarkMetadata { + url: string; + title?: string; + description?: string; + image?: string; + domain?: string; + author?: string; +} + +export interface BookmarkModalProps { + isOpen: boolean; + onClose: () => void; + onAddBookmark: (metadata: BookmarkMetadata) => void; +} + diff --git a/nextjs/src/shared/types/document.ts b/nextjs/src/shared/types/document.ts new file mode 100644 index 0000000..119757c --- /dev/null +++ b/nextjs/src/shared/types/document.ts @@ -0,0 +1,53 @@ +// Document related types +export type DocumentType = 'PAGE' | 'CODE_FILE'; + +export interface Document { + id: string; + title: string; + content?: any; // JSON content for rich text + icon?: string; + cover?: string; + isPublished: boolean; + isArchived: boolean; + createdAt: Date | string; + updatedAt: Date | string; + type: DocumentType; + filePath?: string; + fileContent?: string; + language?: string; + fileSize?: number; + parentId?: string; + folderId?: string; + userId: string; +} + +export interface DocumentWithRelations extends Document { + parent?: Document; + children?: Document[]; + folder?: { + id: string; + name: string; + icon?: string; + }; + user?: any; + _count?: { + documents: number; + }; +} + +export interface DocumentListItem { + id: string; + title: string; + icon?: string; + updatedAt: string; +} + +export interface HeadingItem { + id: string; + text: string; + level: number; + element?: HTMLElement; + children?: HeadingItem[]; + isExpanded?: boolean; +} + diff --git a/nextjs/src/shared/types/editor.ts b/nextjs/src/shared/types/editor.ts new file mode 100644 index 0000000..29c8b13 --- /dev/null +++ b/nextjs/src/shared/types/editor.ts @@ -0,0 +1,42 @@ +// Editor related types +import type { DocumentListItem } from './document'; + +export interface RichTextEditorProps { + content?: any; + onChange?: (content: any) => void; + placeholder?: string; + editable?: boolean; + readOnly?: boolean; + availableDocuments?: DocumentListItem[]; +} + +export interface DocumentSidebarProps { + content: any; + title: string; + lastSaved?: Date; + wordCount: number; + documentId?: string; + published?: boolean; + onShare?: () => void; + onUnshare?: () => void; + onCreateTemplate?: (templateData: any) => void | Promise; + onApplyTemplate?: (template: any) => void; +} + +export interface NotionBlockSelectorProps { + isOpen: boolean; + onClose: () => void; + onSelect: (blockType: string) => void; + position: { x: number; y: number }; +} + +export interface NotionFloatingToolbarProps { + isVisible: boolean; + position: { x: number; y: number }; + onFormat: (format: string) => void; + onClose: () => void; + activeFormats: string[]; + onSetTextColor?: (color: string) => void; + onSetFontFamily?: (fontFamily: string) => void; +} + diff --git a/nextjs/src/shared/types/folder.ts b/nextjs/src/shared/types/folder.ts new file mode 100644 index 0000000..c68f037 --- /dev/null +++ b/nextjs/src/shared/types/folder.ts @@ -0,0 +1,27 @@ +// Folder related types +export interface Folder { + id: string; + name: string; + icon?: string; + color?: string; + isArchived: boolean; + createdAt: Date | string; + updatedAt: Date | string; + parentId?: string; + userId: string; +} + +export interface FolderWithRelations extends Folder { + documents: Array<{ + id: string; + title: string; + icon?: string; + updatedAt: string; + }>; + children: FolderWithRelations[]; + _count: { + documents: number; + children: number; + }; +} + diff --git a/nextjs/src/shared/types/index.ts b/nextjs/src/shared/types/index.ts new file mode 100644 index 0000000..6c6f899 --- /dev/null +++ b/nextjs/src/shared/types/index.ts @@ -0,0 +1,7 @@ +// Export all types +export * from './document' +export * from './folder' +export * from './user' +export * from './template' +export * from './bookmark' +export * from './editor' \ No newline at end of file diff --git a/nextjs/src/shared/types/template.ts b/nextjs/src/shared/types/template.ts new file mode 100644 index 0000000..b523f59 --- /dev/null +++ b/nextjs/src/shared/types/template.ts @@ -0,0 +1,32 @@ +// Template related types +export interface Template { + id: string; + name: string; + description: string; + icon: React.ReactElement | string; + content: any; +} + +export interface DatabaseTemplate { + id: string; + name: string; + description: string; + category: string; + title: string; + content: any; + isPublic: boolean; + createdAt: string; + updatedAt: string; + userId: string; +} + +export interface TemplateBrowserProps { + isOpen: boolean; + onClose: () => void; + onSelectTemplate: (template: DatabaseTemplate) => void; +} + +export interface TemplateSelectorProps { + onSelectTemplate: (template: Template | DatabaseTemplate) => void; +} + diff --git a/nextjs/src/shared/types/user.ts b/nextjs/src/shared/types/user.ts new file mode 100644 index 0000000..e2c9a4c --- /dev/null +++ b/nextjs/src/shared/types/user.ts @@ -0,0 +1,15 @@ +// User related types +export interface User { + id: string; + email: string; + name?: string; + image?: string; +} + +export interface AuthContextType { + user: User | null; + isLoading: boolean; + login: (token: string, user: User) => void; + logout: () => void; +} + diff --git a/nextjs/src/shared/ui/SignedImage.tsx b/nextjs/src/shared/ui/SignedImage.tsx new file mode 100644 index 0000000..0451745 --- /dev/null +++ b/nextjs/src/shared/ui/SignedImage.tsx @@ -0,0 +1,86 @@ +"use client"; + +import React, { useState, useEffect } from 'react'; + +interface SignedImageProps { + fileKey: string; + alt: string; + className?: string; + style?: React.CSSProperties; + onError?: () => void; +} + +const SignedImage: React.FC = ({ + fileKey, + alt, + className = "", + style, + onError +}) => { + const [signedUrl, setSignedUrl] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const getSignedUrl = async () => { + try { + const response = await fetch('/api/download-url', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + fileKey: fileKey, + }), + }); + + if (!response.ok) { + throw new Error('서명된 URL 생성에 실패했습니다.'); + } + + const { downloadUrl } = await response.json(); + setSignedUrl(downloadUrl); + } catch (error) { + console.error('서명된 URL 생성 실패:', error); + setError('이미지를 불러올 수 없습니다.'); + onError?.(); + } finally { + setIsLoading(false); + } + }; + + getSignedUrl(); + }, [fileKey, onError]); + + if (isLoading) { + return ( +
+
+
+ ); + } + + if (error || !signedUrl) { + return ( +
+ {error || '이미지 없음'} +
+ ); + } + + return ( + {alt} { + setError('이미지 로드 실패'); + onError?.(); + }} + /> + ); +}; + +export default SignedImage; + diff --git a/nextjs/src/shared/ui/button.tsx b/nextjs/src/shared/ui/button.tsx new file mode 100644 index 0000000..af239f1 --- /dev/null +++ b/nextjs/src/shared/ui/button.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "../lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/nextjs/src/shared/ui/checkbox.tsx b/nextjs/src/shared/ui/checkbox.tsx new file mode 100644 index 0000000..a2d8e46 --- /dev/null +++ b/nextjs/src/shared/ui/checkbox.tsx @@ -0,0 +1,51 @@ +import * as React from "react" +import { cn } from "../lib/utils" +import { Check } from "lucide-react" + +export interface CheckboxProps + extends Omit, 'type'> { + onCheckedChange?: (checked: boolean) => void +} + +const Checkbox = React.forwardRef( + ({ className, onCheckedChange, checked, ...props }, ref) => { + const handleChange = (e: React.ChangeEvent) => { + onCheckedChange?.(e.target.checked) + props.onChange?.(e) + } + + return ( +
+ +
+ +
+
+ ) + } +) +Checkbox.displayName = "Checkbox" + +export { Checkbox } + diff --git a/nextjs/src/shared/ui/dialog.tsx b/nextjs/src/shared/ui/dialog.tsx new file mode 100644 index 0000000..4c6f3cb --- /dev/null +++ b/nextjs/src/shared/ui/dialog.tsx @@ -0,0 +1,119 @@ +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" +import { cn } from "../lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/nextjs/src/shared/ui/dropdown-menu.tsx b/nextjs/src/shared/ui/dropdown-menu.tsx new file mode 100644 index 0000000..2da0501 --- /dev/null +++ b/nextjs/src/shared/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "../lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/nextjs/src/shared/ui/index.ts b/nextjs/src/shared/ui/index.ts new file mode 100644 index 0000000..2f4ab27 --- /dev/null +++ b/nextjs/src/shared/ui/index.ts @@ -0,0 +1,10 @@ +export * from './button' +export * from './checkbox' +export * from './dialog' +export * from './dropdown-menu' +export * from './input' +export * from './label' +export * from './textarea' +export * from './skeleton' +export * from './spinner' +export * from './mode-toggle' diff --git a/nextjs/src/shared/ui/input.tsx b/nextjs/src/shared/ui/input.tsx new file mode 100644 index 0000000..03f61d9 --- /dev/null +++ b/nextjs/src/shared/ui/input.tsx @@ -0,0 +1,24 @@ +import * as React from "react" +import { cn } from "../lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/nextjs/src/shared/ui/label.tsx b/nextjs/src/shared/ui/label.tsx new file mode 100644 index 0000000..395c742 --- /dev/null +++ b/nextjs/src/shared/ui/label.tsx @@ -0,0 +1,23 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "../lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/nextjs/src/shared/ui/mode-toggle.tsx b/nextjs/src/shared/ui/mode-toggle.tsx new file mode 100644 index 0000000..5636052 --- /dev/null +++ b/nextjs/src/shared/ui/mode-toggle.tsx @@ -0,0 +1,40 @@ +"use client" + +import * as React from "react" +import { Moon, Sun } from "lucide-react" +import { useTheme } from "next-themes" + +import { Button } from "./button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "./dropdown-menu" + +export function ModeToggle() { + const { setTheme } = useTheme() + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ) +} diff --git a/nextjs/src/shared/ui/skeleton.tsx b/nextjs/src/shared/ui/skeleton.tsx new file mode 100644 index 0000000..51eab5c --- /dev/null +++ b/nextjs/src/shared/ui/skeleton.tsx @@ -0,0 +1,218 @@ +import { cn } from "../lib/utils"; + +interface SkeletonProps { + className?: string; +} + +export const Skeleton = ({ className }: SkeletonProps) => { + return ( +
+ ); +}; + +// Document Card Skeleton +export const DocumentCardSkeleton = () => { + return ( +
+ + + +
+ ); +}; + +// Folder Card Skeleton +export const FolderCardSkeleton = () => { + return ( +
+ + +
+ ); +}; + +// Folder View Skeleton +export const FolderViewSkeleton = () => { + return ( +
+ {/* Folder header skeleton */} +
+ + +
+ + +
+
+ + {/* Subfolders section */} +
+ +
+ {Array.from({ length: 7 }).map((_, i) => ( + + ))} +
+
+ + {/* Documents section */} +
+ +
+ {Array.from({ length: 10 }).map((_, i) => ( + + ))} +
+
+
+ ); +}; + +// Documents Page Skeleton +export const DocumentsPageSkeleton = () => { + return ( +
+ {/* Folders section */} +
+
+ + +
+
+ {Array.from({ length: 7 }).map((_, i) => ( + + ))} +
+
+ + {/* Recent pages section */} +
+
+ + +
+
+ {Array.from({ length: 10 }).map((_, i) => ( + + ))} +
+
+
+ ); +}; + +// Document Detail Page Skeleton +export const DocumentDetailSkeleton = () => { + return ( +
+ {/* Header skeleton */} +
+
+
+
+ + +
+
+ + +
+
+
+
+ + {/* Content skeleton */} +
+
+ {/* Document header */} +
+
+ +
+ +
+ + +
+
+
+
+ + {/* Editor skeleton */} +
+
+ + + + + +
+ + +
+
+
+
+
+
+ ); +}; + +// Shared Document Page Skeleton +export const SharedDocumentSkeleton = () => { + return ( +
+ {/* Header skeleton */} +
+
+
+
+ +
+
+ +
+
+
+
+ + {/* Content skeleton */} +
+ {/* Document header */} +
+
+ +
+ +
+ + +
+
+
+
+ + {/* Content skeleton */} +
+
+ + + + +
+ + + +
+
+
+
+
+ ); +}; + diff --git a/nextjs/src/shared/ui/spinner.tsx b/nextjs/src/shared/ui/spinner.tsx new file mode 100644 index 0000000..92db7c4 --- /dev/null +++ b/nextjs/src/shared/ui/spinner.tsx @@ -0,0 +1,30 @@ +import { Loader } from "lucide-react"; +import { VariantProps,cva } from "class-variance-authority"; +import { cn } from "../lib/utils"; + +const spinnerVariants = cva( + "text-muted-foreground animate-spin", + { + variants: { + size: { + default: "h-4 w-4", + sm: "h-2 w-2", + lg: "h-6 w-6", + icon: "h-10 w-10" + } + }, + defaultVariants :{ + size: "default", + }, + }, +); + +interface SpinnerProps extends VariantProps {} + +export const Spinner = ({ + size, +}: SpinnerProps) => { + return ( + + ); +}; \ No newline at end of file diff --git a/nextjs/src/shared/ui/textarea.tsx b/nextjs/src/shared/ui/textarea.tsx new file mode 100644 index 0000000..850a3b7 --- /dev/null +++ b/nextjs/src/shared/ui/textarea.tsx @@ -0,0 +1,23 @@ +import * as React from "react" +import { cn } from "../lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +