From a5c28ff3c3a8cb30d64a339cd9571edaeef454de Mon Sep 17 00:00:00 2001 From: ThisTimeNull Date: Wed, 28 Jan 2026 15:16:11 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[fix]=20Umami=20=EC=9B=B9=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.5 --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 4f90b57..57a21c3 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,7 @@ + Date: Wed, 28 Jan 2026 15:17:31 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[fix]=20Azure=20Application=20Insights?= =?UTF-8?q?=EC=97=90=EC=84=9C=20Sentry=EB=A1=9C=20=EB=AA=A8=EB=8B=88?= =?UTF-8?q?=ED=84=B0=EB=A7=81=20=EB=8F=84=EA=B5=AC=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sentry Browser SDK 및 Vite 플러그인 추가 - Web Vitals 수집 및 전송 구현 - Session Replay 기능 활성화 (개인정보 보호 모드) - 개발 환경 전용 Sentry 테스트 함수 추가 - Application Insights 코드 및 의존성 완전 제거 - Sourcemap 생성 활성화 (에러 디버깅 지원) Co-Authored-By: Claude Sonnet 4.5 --- package-lock.json | 1139 ++++++++++++++++++++---- package.json | 3 +- src/scripts/main.ts | 20 +- src/scripts/monitoring/app-insights.ts | 125 --- src/scripts/monitoring/monitoring.ts | 174 ++++ vite.config.ts | 48 +- 6 files changed, 1162 insertions(+), 347 deletions(-) delete mode 100644 src/scripts/monitoring/app-insights.ts create mode 100644 src/scripts/monitoring/monitoring.ts diff --git a/package-lock.json b/package-lock.json index 2ff192d..b801d4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,14 @@ "name": "docker-ko.github.io", "version": "0.0.0", "dependencies": { - "@microsoft/applicationinsights-web": "^3.3.9", + "@sentry/browser": "^10.37.0", + "@sentry/vite-plugin": "^4.8.0", "@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-vue": "^5.2.1", "marked": "^15.0.7", "tailwindcss": "^4.0.6", "vite-plugin-markdown": "^2.2.0", - "web-vitals": "^3.5.2" + "web-vitals": "^3.3.0" }, "devDependencies": { "@eslint/js": "^9.27.0", @@ -1055,6 +1056,23 @@ "url": "https://github.com/sponsors/nzakas" } }, + "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==", + "license": "ISC", + "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/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1100,174 +1118,16 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@microsoft/applicationinsights-analytics-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-3.3.11.tgz", - "integrity": "sha512-33fS5Y7uPgckP8yWqCAoWpWerA+d3RUC2lv6kkfJQM/V2KHeN4CGDtyXXWpq5vSZjE9BESXao13iBq4wiWit8Q==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-cfgsync-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-cfgsync-js/-/applicationinsights-cfgsync-js-3.3.11.tgz", - "integrity": "sha512-HdBc/ldMZpqGtzAFDs49o82wTdKRX2B0BzmjgS+D4MrS7CLth4MxLHJHOpmTI2bmc/S4T8n32LlFkaQCvWb9ig==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.4 < 2.x", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-channel-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-3.3.11.tgz", - "integrity": "sha512-0ex/mxTf5R+P5WSvdU8Hgbeg8VzQ0XvcnjKQdmQy05ycScnKevt8an3DEPikOFqOKDi59L5hUETZlcdhesnVtg==", + "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==", "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.4 < 2.x", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-common": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-3.3.11.tgz", - "integrity": "sha512-OIe5vL56lkmIsRsI21QqbGpF8gF/UzUP4mlEhGWyG2UMskdtWrY+c+xAynyNDsAjhKKge+Rrs/xkpC0Fo0QrhQ==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.11.tgz", - "integrity": "sha512-WlBY1sKDNL62T++NifgFCyDuOoNUNrVILfnHubOzgU/od7MFEQYWU8EZyDcBC/+Z8e3TD6jfixurYtWoUC+6Eg==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.4 < 2.x", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-dependencies-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-3.3.11.tgz", - "integrity": "sha512-+D7vBHvLWFveZmg1PCbDhpw/tiD+/AnptzEoV8IsM9wPbiHPGHdni9IDMrTJZdJZVafO0GxnxOJNpir8QTdO8g==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.4 < 2.x", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-properties-js": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-3.3.11.tgz", - "integrity": "sha512-GOyIV8QziFop/LelZW1LAKwhGvtjzN7d47NkSRh9ZyZPW/ahWifakdQ6mZfLcL2uTyTmpcK8JtMtfNADo77NZg==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz", - "integrity": "sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg==", - "license": "MIT", - "dependencies": { - "@nevware21/ts-utils": ">= 0.9.4 < 2.x" - } - }, - "node_modules/@microsoft/applicationinsights-web": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web/-/applicationinsights-web-3.3.11.tgz", - "integrity": "sha512-LEI6LhfLFzBfPJ4j5TTPNC8LxwDpiJZSeyD2VVU3EPN2RtK+15vEL0oONaSV/AsWnDrwH3DIku0Nm+EVRJ4pNQ==", - "license": "MIT", - "dependencies": { - "@microsoft/applicationinsights-analytics-js": "3.3.11", - "@microsoft/applicationinsights-cfgsync-js": "3.3.11", - "@microsoft/applicationinsights-channel-js": "3.3.11", - "@microsoft/applicationinsights-common": "3.3.11", - "@microsoft/applicationinsights-core-js": "3.3.11", - "@microsoft/applicationinsights-dependencies-js": "3.3.11", - "@microsoft/applicationinsights-properties-js": "3.3.11", - "@microsoft/applicationinsights-shims": "3.0.1", - "@microsoft/dynamicproto-js": "^2.0.3", - "@nevware21/ts-async": ">= 0.5.4 < 2.x", - "@nevware21/ts-utils": ">= 0.11.8 < 2.x" - }, - "peerDependencies": { - "tslib": ">= 1.0.0" - } - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz", - "integrity": "sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA==", - "license": "MIT", - "dependencies": { - "@nevware21/ts-utils": ">= 0.10.4 < 2.x" - } - }, - "node_modules/@nevware21/ts-async": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@nevware21/ts-async/-/ts-async-0.5.5.tgz", - "integrity": "sha512-vwqaL05iJPjLeh5igPi8MeeAu10i+Aq7xko1fbo9F5Si6MnVN5505qaV7AhSdk5MCBJVT/UYMk3kgInNjDb4Ig==", - "license": "MIT", - "dependencies": { - "@nevware21/ts-utils": ">= 0.12.2 < 2.x" + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@nevware21/ts-utils": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@nevware21/ts-utils/-/ts-utils-0.12.5.tgz", - "integrity": "sha512-JPQZWPKQJjj7kAftdEZL0XDFfbMgXCGiUAZe0d7EhLC3QlXTlZdSckGqqRIQ2QNl0VTEZyZUvRBw6Ednw089Fw==", - "license": "MIT" - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1599,6 +1459,324 @@ "win32" ] }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.37.0.tgz", + "integrity": "sha512-rqdESYaVio9Ktz55lhUhtBsBUCF3wvvJuWia5YqoHDd+egyIfwWxITTAa0TSEyZl7283A4WNHNl0hyeEMblmfA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.37.0.tgz", + "integrity": "sha512-P0PVlfrDvfvCYg2KPIS7YUG/4i6ZPf8z1MicXx09C9Cz9W9UhSBh/nii13eBdDtLav2BFMKhvaFMcghXHX03Hw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.37.0.tgz", + "integrity": "sha512-snuk12ZaDerxesSnetNIwKoth/51R0y/h3eXD/bGtXp+hnSkeXN5HanI/RJl297llRjn4zJYRShW9Nx86Ay0Dw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.37.0.tgz", + "integrity": "sha512-PyIYSbjLs+L5essYV0MyIsh4n5xfv2eV7l0nhUoPJv9Bak3kattQY3tholOj0EP3SgKgb+8HSZnmazgF++Hbog==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.8.0.tgz", + "integrity": "sha512-cy/9Eipkv23MsEJ4IuB4dNlVwS9UqOzI3Eu+QPake5BVFgPYCX0uP0Tr3Z43Ime6Rb+BiDnWC51AJK9i9afHYw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.37.0.tgz", + "integrity": "sha512-kheqJNqGZP5TSBCPv4Vienv1sfZwXKHQDYR+xrdHHYdZqwWuZMJJW/cLO9XjYAe+B9NnJ4UwJOoY4fPvU+HQ1Q==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry-internal/feedback": "10.37.0", + "@sentry-internal/replay": "10.37.0", + "@sentry-internal/replay-canvas": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.8.0.tgz", + "integrity": "sha512-QaXd/NzaZ2vmiA2FNu2nBkgQU+17N3fE+zVOTzG0YK54QDSJMd4n3AeJIEyPhSzkOob+GqtO22nbYf6AATFMAw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "4.8.0", + "@sentry/cli": "^2.57.0", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^10.5.0", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry/cli": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.4.tgz", + "integrity": "sha512-ArDrpuS8JtDYEvwGleVE+FgR+qHaOp77IgdGSacz6SZy6Lv90uX0Nu4UrHCQJz8/xwIcNxSqnN22lq0dH4IqTg==", + "hasInstallScript": true, + "license": "FSL-1.1-MIT", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.58.4", + "@sentry/cli-linux-arm": "2.58.4", + "@sentry/cli-linux-arm64": "2.58.4", + "@sentry/cli-linux-i686": "2.58.4", + "@sentry/cli-linux-x64": "2.58.4", + "@sentry/cli-win32-arm64": "2.58.4", + "@sentry/cli-win32-i686": "2.58.4", + "@sentry/cli-win32-x64": "2.58.4" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.4.tgz", + "integrity": "sha512-kbTD+P4X8O+nsNwPxCywtj3q22ecyRHWff98rdcmtRrvwz8CKi/T4Jxn/fnn2i4VEchy08OWBuZAqaA5Kh2hRQ==", + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.4.tgz", + "integrity": "sha512-rdQ8beTwnN48hv7iV7e7ZKucPec5NJkRdrrycMJMZlzGBPi56LqnclgsHySJ6Kfq506A2MNuQnKGaf/sBC9REA==", + "cpu": [ + "arm" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.4.tgz", + "integrity": "sha512-0g0KwsOozkLtzN8/0+oMZoOuQ0o7W6O+hx+ydVU1bktaMGKEJLMAWxOQNjsh1TcBbNIXVOKM/I8l0ROhaAb8Ig==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.4.tgz", + "integrity": "sha512-NseoIQAFtkziHyjZNPTu1Gm1opeQHt7Wm1LbLrGWVIRvUOzlslO9/8i6wETUZ6TjlQxBVRgd3Q0lRBG2A8rFYA==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.4.tgz", + "integrity": "sha512-d3Arz+OO/wJYTqCYlSN3Ktm+W8rynQ/IMtSZLK8nu0ryh5mJOh+9XlXY6oDXw4YlsM8qCRrNquR8iEI1Y/IH+Q==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.4.tgz", + "integrity": "sha512-bqYrF43+jXdDBh0f8HIJU3tbvlOFtGyRjHB8AoRuMQv9TEDUfENZyCelhdjA+KwDKYl48R1Yasb4EHNzsoO83w==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.4.tgz", + "integrity": "sha512-3triFD6jyvhVcXOmGyttf+deKZcC1tURdhnmDUIBkiDPJKGT/N5xa4qAtHJlAB/h8L9jgYih9bvJnvvFVM7yug==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.4.tgz", + "integrity": "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sentry/cli/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sentry/core": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.37.0.tgz", + "integrity": "sha512-hkRz7S4gkKLgPf+p3XgVjVm7tAfvcEPZxeACCC6jmoeKhGkzN44nXwLiqqshJ25RMcSrhfFvJa/FlBg6zupz7g==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/vite-plugin": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-4.8.0.tgz", + "integrity": "sha512-/YZJitGsx/o72FFQYy3tucUfs4w3COvSI1d2NYyAhIzay4tjLLRjpM5PdwFnoBT7Uj/7jSbuHkg87PAliLiu2g==", + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "4.8.0", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@tailwindcss/node": { "version": "4.1.18", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", @@ -2529,7 +2707,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2575,11 +2752,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "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==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -2591,6 +2779,31 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "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==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2611,7 +2824,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/baseline-browser-mapping": { @@ -2623,6 +2835,18 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2634,6 +2858,18 @@ "concat-map": "0.0.1" } }, + "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==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -2751,11 +2987,46 @@ "node": ">= 16" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "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==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2768,7 +3039,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/concat-map": { @@ -2788,7 +3058,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2949,12 +3218,36 @@ "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==", + "license": "BSD-2-Clause", + "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==", + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.279", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz", "integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==", "license": "ISC" }, + "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==", + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.18.4", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", @@ -3290,11 +3583,22 @@ "node": ">=16.0.0" } }, + "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==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -3328,6 +3632,22 @@ "dev": true, "license": "ISC" }, + "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==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/front-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", @@ -3382,6 +3702,26 @@ "node": ">=6.9.0" } }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "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", @@ -3389,10 +3729,34 @@ "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "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==", + "license": "MIT", + "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==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { @@ -3544,21 +3908,40 @@ "node": ">=0.8.19" } }, + "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==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "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==", + "license": "MIT", + "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==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -3567,6 +3950,15 @@ "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==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -3578,9 +3970,23 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -3982,7 +4388,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -4082,6 +4487,15 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4113,12 +4527,63 @@ "dev": true, "license": "MIT" }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/node-fetch/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==", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/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==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "license": "MIT" }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nwsapi": { "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", @@ -4148,7 +4613,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -4164,7 +4628,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -4176,6 +4639,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4206,7 +4675,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4216,12 +4684,33 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "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==", + "license": "BlueOak-1.0.0", + "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/path-scurry/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==", + "license": "ISC" + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -4398,6 +4887,21 @@ } } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4417,6 +4921,30 @@ "node": ">=0.10.0" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4511,7 +5039,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -4524,7 +5051,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4537,6 +5063,18 @@ "dev": true, "license": "ISC" }, + "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==", + "license": "ISC", + "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", @@ -4566,6 +5104,102 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/string-width-cjs/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4719,6 +5353,18 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", @@ -4762,7 +5408,9 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "dev": true, + "license": "0BSD", + "optional": true }, "node_modules/type-check": { "version": "0.4.0", @@ -4828,6 +5476,18 @@ "devOptional": true, "license": "MIT" }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -5104,6 +5764,21 @@ "node": ">=12" } }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "license": "MIT" + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -5146,7 +5821,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -5185,6 +5859,94 @@ "node": ">=0.10.0" } }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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-cjs/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ws": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", @@ -5234,7 +5996,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/package.json b/package.json index f3711be..3316e92 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "vitest": "^3.2.2" }, "dependencies": { - "@microsoft/applicationinsights-web": "^3.3.9", + "@sentry/browser": "^10.37.0", + "@sentry/vite-plugin": "^4.8.0", "@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-vue": "^5.2.1", "marked": "^15.0.7", diff --git a/src/scripts/main.ts b/src/scripts/main.ts index 5998bc5..2d8b2de 100644 --- a/src/scripts/main.ts +++ b/src/scripts/main.ts @@ -10,17 +10,17 @@ import { initializeBreadcrumb } from './breadcrumb'; import { getCurrentPageConfig } from './page-config'; import { toggleUIElements } from './ui-manager'; import { - initializeAppInsights, + initializeMonitoring, setupWebVitalsTracking, trackPageView, trackException, -} from './monitoring/app-insights'; +} from './monitoring/monitoring'; // 모니터링 초기화 -const appInsights = initializeAppInsights(); -if (appInsights) { - trackPageView(appInsights); - setupWebVitalsTracking(appInsights); +const monitoringEnabled = initializeMonitoring(); +if (monitoringEnabled) { + trackPageView(); + setupWebVitalsTracking(); } /** @@ -54,11 +54,7 @@ document.addEventListener('DOMContentLoaded', async () => { try { await initializePage(); } catch (error) { - trackException( - appInsights, - error as Error, - 'DOMContentLoaded.initializePage' - ); + trackException(error as Error, 'DOMContentLoaded.initializePage'); console.error('❌ main.ts: DOMContentLoaded : 페이지 초기화 실패!', error); } }); @@ -68,7 +64,7 @@ window.addEventListener('hashchange', async () => { await initializePage(); window.scrollTo(0, 0); // 페이지 이동 시 최상단으로 스크롤 이동 } catch (error) { - trackException(appInsights, error as Error, 'hashchange.initializePage'); + trackException(error as Error, 'hashchange.initializePage'); console.error('❌ main.ts: hashchange : 페이지 초기화 실패!', error); } }); diff --git a/src/scripts/monitoring/app-insights.ts b/src/scripts/monitoring/app-insights.ts deleted file mode 100644 index f912f3f..0000000 --- a/src/scripts/monitoring/app-insights.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Application Insights 모니터링 설정 및 유틸리티 - * - * 책임: - * - App Insights 초기화 및 설정 - * - Core Web Vitals 수집 및 전송 - * - 페이지뷰 및 예외 추적 - */ - -import { ApplicationInsights } from '@microsoft/applicationinsights-web'; -import type { ITelemetryItem } from '@microsoft/applicationinsights-web'; -import { onLCP, onCLS, onINP } from 'web-vitals'; -import type { Metric } from 'web-vitals'; -import { getCurrentPageConfig } from '../page-config'; - -/** - * Application Insights 인스턴스 초기화 및 설정 - * - * @returns ApplicationInsights 인스턴스 또는 null (연결 문자열 미설정 시) - */ -export function initializeAppInsights(): ApplicationInsights | null { - const connectionString = import.meta.env - .VITE_APPINSIGHTS_CONNECTION_STRING as string; - - if (!connectionString) { - console.warn( - '⚠️ VITE_APPINSIGHTS_CONNECTION_STRING not set. Monitoring disabled.' - ); - return null; - } - - const appInsights = new ApplicationInsights({ - config: { - connectionString, - enableAutoRouteTracking: true, - disableFetchTracking: false, - disableAjaxTracking: false, - disableExceptionTracking: false, - }, - }); - - // 텔레메트리 초기자: 모든 텔레메트리에 공통 메타데이터 주입 - appInsights.addTelemetryInitializer((envelope: ITelemetryItem) => { - try { - const baseData = envelope?.baseData; - if (baseData && 'properties' in baseData) { - baseData.properties = baseData.properties || {}; - baseData.properties.pageType = getCurrentPageConfig().type; - baseData.properties.site = 'docker-ko.github.io'; - } - } catch { - // Initializer must never throw - } - }); - - appInsights.loadAppInsights(); - return appInsights; -} - -/** - * Web Vitals 수집 및 전송 - * - * LCP, CLS, INP 메트릭을 자동으로 수집하여 App Insights로 전송합니다. - * - * @param appInsights - App Insights 인스턴스 - */ -export function setupWebVitalsTracking(appInsights: ApplicationInsights): void { - const sendVital = (metric: Metric) => { - try { - appInsights.trackMetric({ - name: metric.name, - average: metric.value, - properties: { - id: metric.id, - delta: metric.delta, - rating: metric.rating, - }, - }); - } catch { - // Monitoring failure should not break the app - } - }; - - onLCP(sendVital); - onCLS(sendVital); - onINP(sendVital); -} - -/** - * 페이지뷰 추적 - * - * @param appInsights - App Insights 인스턴스 - */ -export function trackPageView(appInsights: ApplicationInsights): void { - const config = getCurrentPageConfig(); - appInsights.trackPageView({ - name: document.title, - uri: window.location.href, - properties: { pageType: config.type }, - }); -} - -/** - * 예외 추적 헬퍼 - * - * @param appInsights - App Insights 인스턴스 (null 가능) - * @param error - 추적할 에러 객체 - * @param location - 에러 발생 위치 (예: 'DOMContentLoaded.initializePage') - */ -export function trackException( - appInsights: ApplicationInsights | null, - error: Error, - location: string -): void { - if (!appInsights) return; - - try { - appInsights.trackException({ - error, - properties: { location }, - }); - } catch { - // Monitoring failure should not break the app - } -} diff --git a/src/scripts/monitoring/monitoring.ts b/src/scripts/monitoring/monitoring.ts new file mode 100644 index 0000000..0a0b6fa --- /dev/null +++ b/src/scripts/monitoring/monitoring.ts @@ -0,0 +1,174 @@ +/** + * Sentry 모니터링 설정 및 유틸리티 + * + * 책임: + * - Sentry 초기화 및 설정 + * - Core Web Vitals 수집 및 전송 + * - 페이지뷰 및 예외 추적 + * - Session Replay (사용자 행동 녹화) + */ + +import * as Sentry from '@sentry/browser'; +import { onLCP, onCLS, onINP } from 'web-vitals'; +import type { Metric } from 'web-vitals'; +import { getCurrentPageConfig } from '../page-config'; + +/** + * Sentry 모니터링 초기화 + * + * @returns 초기화 성공 여부 + */ +export function initializeMonitoring(): boolean { + const dsn = import.meta.env.VITE_SENTRY_DSN as string; + + if (!dsn) { + console.warn('⚠️ VITE_SENTRY_DSN not set. Monitoring disabled.'); + return false; + } + + try { + Sentry.init({ + dsn, + environment: import.meta.env.PROD ? 'production' : 'development', + + // 성능 모니터링 샘플링 (프로덕션: 20%, 개발: 100%) + tracesSampleRate: import.meta.env.PROD ? 0.2 : 1.0, + + // Session Replay 샘플링 (프로덕션: 10%, 개발: 100%) + replaysSessionSampleRate: import.meta.env.PROD ? 0.1 : 1.0, + + // 에러 발생 시 Session Replay 샘플링 (100%) + replaysOnErrorSampleRate: 1.0, + + // 릴리스 버전 추적 + release: import.meta.env.VITE_APP_VERSION as string | undefined, + + // PII 전송 설정 (GDPR 준수) + sendDefaultPii: false, + + // 에러 필터링 + beforeSend(event, hint) { + // 브라우저 확장 프로그램 에러 제외 + const error = hint.originalException; + if (error && error.toString().includes('chrome-extension://')) { + return null; + } + return event; + }, + + // 초기 태그 설정 + initialScope: { + tags: { + site: 'docker-ko.github.io', + pageType: getCurrentPageConfig().type, + }, + }, + + // 통합 설정 + integrations: [ + Sentry.browserTracingIntegration({ + enableInp: true, // Interaction to Next Paint 추적 + }), + Sentry.replayIntegration({ + // Session Replay 개인정보 보호 설정 + maskAllText: false, // 모든 텍스트 마스킹 (개인정보 보호) + blockAllMedia: false, // 모든 미디어 차단 (프라이버시 보호) + }), + ], + }); + + console.log('✅ Sentry monitoring initialized'); + return true; + } catch (error) { + console.error('❌ Failed to initialize Sentry:', error); + return false; + } +} + +/** + * Web Vitals 수집 및 전송 + * + * LCP, CLS, INP 메트릭을 자동으로 수집하여 Sentry로 전송합니다. + */ +export function setupWebVitalsTracking(): void { + const sendVital = (metric: Metric) => { + try { + // Sentry 메트릭으로 전송 + Sentry.metrics.gauge(metric.name, metric.value); + + // 태그를 별도로 설정 + Sentry.setTag('metric_id', metric.id); + Sentry.setTag('metric_rating', metric.rating); + } catch { + // Monitoring failure should not break the app + } + }; + + onLCP(sendVital); + onCLS(sendVital); + onINP(sendVital); +} + +/** + * 페이지뷰 추적 + */ +export function trackPageView(): void { + try { + const config = getCurrentPageConfig(); + + // 페이지 컨텍스트 설정 + Sentry.setContext('page', { + url: window.location.href, + title: document.title, + pageType: config.type, + }); + + // 태그 설정 + Sentry.setTag('pageType', config.type); + + // 커스텀 이벤트로 페이지뷰 전송 + Sentry.captureMessage(`Page View: ${document.title}`, { + level: 'info', + tags: { + pageType: config.type, + }, + }); + } catch { + // Monitoring failure should not break the app + } +} + +/** + * 예외 추적 헬퍼 + * + * @param error - 추적할 에러 객체 + * @param location - 에러 발생 위치 (예: 'DOMContentLoaded.initializePage') + */ +export function trackException(error: Error, location: string): void { + try { + Sentry.captureException(error, { + tags: { + location, + pageType: getCurrentPageConfig().type, + }, + level: 'error', + }); + } catch { + // Monitoring failure should not break the app + } +} + +/** + * 개발 환경 전용: Sentry 동작 확인 + * + * 브라우저 콘솔에서 testSentry() 실행 + */ +if (import.meta.env.DEV) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (window as any).testSentry = () => { + Sentry.logger.info('User triggered test log', { log_source: 'sentry_test' }); + console.log('✅ Test sent. Check Sentry dashboard.'); + }; + + console.log('Run: testSentry()'); +} diff --git a/vite.config.ts b/vite.config.ts index ca74001..0269f36 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,23 +1,31 @@ +import { sentryVitePlugin } from '@sentry/vite-plugin'; /// -import tailwindcss from "@tailwindcss/vite"; -import { defineConfig } from "vite"; +import tailwindcss from '@tailwindcss/vite'; +import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [tailwindcss()], - base: './', - publicDir: 'public', - server: { - open: false, // 컨테이너 환경에서는 브라우저 자동 열기 비활성화 - host: true, // 네트워크에서 접근 가능하도록 설정 - }, - build: { - outDir: "dist", - emptyOutDir: true, - }, - test: { - // 테스트 환경 설정 - environment: 'jsdom', // 브라우저 환경 시뮬레이션 - // 테스트 파일 패턴 - include: ['tests/**/*.{test,spec}.{js,ts}'], - } -}); \ No newline at end of file + plugins: [ + tailwindcss(), + sentryVitePlugin({ + org: 'syungg', + project: 'javascript', + }), + ], + base: './', + publicDir: 'public', + server: { + open: false, // 컨테이너 환경에서는 브라우저 자동 열기 비활성화 + host: true, // 네트워크에서 접근 가능하도록 설정 + }, + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true, + }, + test: { + // 테스트 환경 설정 + environment: 'jsdom', // 브라우저 환경 시뮬레이션 + // 테스트 파일 패턴 + include: ['tests/**/*.{test,spec}.{js,ts}'], + }, +}); From 94ecec0222ca71b49e2899efabc65b5308804fa1 Mon Sep 17 00:00:00 2001 From: ThisTimeNull Date: Wed, 28 Jan 2026 15:19:50 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[fix]=20GitHub=20Actions=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EB=B3=80=EC=88=98=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - VITE_APPINSIGHTS_CONNECTION_STRING 제거 - VITE_SENTRY_DSN 및 SENTRY_AUTH_TOKEN 추가 Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/deploy.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e22d407..fe3d1cd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,7 +27,8 @@ jobs: - name: Vite 프로젝트 빌드 env: - VITE_APPINSIGHTS_CONNECTION_STRING: ${{ secrets.VITE_APPINSIGHTS_CONNECTION_STRING }} + VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} run: npm run build - name: GitHub Pages에 배포 From 057f5be2bbda380ec3896895282e1c4221dd629e Mon Sep 17 00:00:00 2001 From: ThisTimeNull Date: Wed, 28 Jan 2026 15:20:06 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[fix]=20Docker=20Compose=20=EB=B0=8F=20giti?= =?UTF-8?q?gnore=20=EC=84=A4=EC=A0=95=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Docker Compose: named volume에서 anonymous volume으로 변경 - node_modules 자동 정리 및 패키지 변경 시 자동 반영 지원 - version 필드 제거 (deprecated 경고 해결) - VITE_SENTRY_DSN 환경 변수 추가 - gitignore: .env.sentry-build-plugin 제외 추가 Co-Authored-By: Claude Sonnet 4.5 --- .gitignore | 3 +++ docker-compose.yml | 12 ++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 68ffd98..f6af3ac 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ dist-ssr *.njsproj *.sln *.sw? + +# Sentry Config File +.env.sentry-build-plugin diff --git a/docker-compose.yml b/docker-compose.yml index 593a746..abf2eb6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: "1.0.0" services: web: container_name: docker-ko-dev @@ -9,12 +8,9 @@ services: - "5173:5173" volumes: - ./:/app - # 호스트에 node_modules가 없을 경우 이미지에서 설치된 종속성을 - # 유지하기 위해 이름 있는 볼륨을 사용합니다. - - node_modules:/app/node_modules + # 익명 볼륨으로 node_modules 보호 + # 호스트의 node_modules가 컨테이너 것을 덮어쓰지 않도록 방지 + - /app/node_modules environment: - NODE_ENV=development - -volumes: - node_modules: - name: docker-ko-node_modules \ No newline at end of file + - VITE_SENTRY_DSN=${VITE_SENTRY_DSN} \ No newline at end of file From 2e2eaf18c254347b9623b61b69d1d9bc314d0917 Mon Sep 17 00:00:00 2001 From: ThisTimeNull Date: Wed, 28 Jan 2026 15:36:45 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[fix]=20prettier:write=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=8B=A4=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/scripts/monitoring/monitoring.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripts/monitoring/monitoring.ts b/src/scripts/monitoring/monitoring.ts index 0a0b6fa..966f731 100644 --- a/src/scripts/monitoring/monitoring.ts +++ b/src/scripts/monitoring/monitoring.ts @@ -166,7 +166,9 @@ export function trackException(error: Error, location: string): void { if (import.meta.env.DEV) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).testSentry = () => { - Sentry.logger.info('User triggered test log', { log_source: 'sentry_test' }); + Sentry.logger.info('User triggered test log', { + log_source: 'sentry_test', + }); console.log('✅ Test sent. Check Sentry dashboard.'); }; From 54644a06f6f893541725de8c76c211d221593d47 Mon Sep 17 00:00:00 2001 From: ThisTimeNull Date: Wed, 28 Jan 2026 16:09:40 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[docs]=20node=5Fmodules=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20docker=20volume=20=ED=8A=B8=EB=9F=AC=EB=B8=94?= =?UTF-8?q?=EC=8A=88=ED=8C=85=20=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/trouble-shooting/README.md | 12 + .../docker-volume-node-modules-issue.md | 213 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 public/trouble-shooting/docker-volume-node-modules-issue.md diff --git a/public/trouble-shooting/README.md b/public/trouble-shooting/README.md index 90dd650..d376da1 100644 --- a/public/trouble-shooting/README.md +++ b/public/trouble-shooting/README.md @@ -66,6 +66,18 @@ Docker 한국어 문서 프로젝트를 개발하면서 마주친 문제들과 --- +### 5. [Docker Compose Named Volume으로 인한 의존성 동기화 문제](./docker-volume-node-modules-issue.md) + +**문제**: Sentry 패키지 추가 후 Docker 컨테이너에서 `@sentry/vite-plugin`을 찾을 수 없음 + +- **원인**: Named volume이 영속적으로 유지되어 package.json 변경 시 자동 동기화 안 됨 +- **해결**: Named volume에서 Anonymous volume으로 변경, `docker-compose down` 시 자동 정리 +- **결과**: package.json 변경 시 수동 볼륨 삭제 불필요, 브랜치 전환 시 깨끗한 환경 보장 + +**핵심 교훈**: 개발 환경에서는 영속성보다 재현 가능성이 중요, 적재적소의 볼륨 타입 선택 + +--- + ## 🎯 공통 교훈 ### 1. 단순함의 가치 diff --git a/public/trouble-shooting/docker-volume-node-modules-issue.md b/public/trouble-shooting/docker-volume-node-modules-issue.md new file mode 100644 index 0000000..c7792d2 --- /dev/null +++ b/public/trouble-shooting/docker-volume-node-modules-issue.md @@ -0,0 +1,213 @@ +# 트러블슈팅: Docker Compose Named Volume으로 인한 의존성 동기화 문제 + +## 문제 상황 + +### 컨테이너에서 npm 패키지를 찾을 수 없음 + +Sentry 모니터링 도구를 추가한 후 Docker 컨테이너에서 개발 서버를 실행하려 하니 다음과 같은 에러가 발생했습니다: + +``` +failed to load config from /app/vite.config.ts + +error when starting dev server: + +Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sentry/vite-plugin' +imported from /app/node_modules/.vite-temp/vite.config.ts.timestamp-1769575784050-9b415a926660a.mjs + + at Object.getPackageJSONURL (node:internal/modules/package_json_reader:267:9) + at packageResolve (node:internal/modules/esm/resolve:768:81) + ... +``` + +**증상**: +- `package.json`에 `@sentry/vite-plugin` 패키지가 명확히 존재 +- 호스트에서는 `npm install`로 정상 설치됨 +- 컨테이너 내부에서만 패키지를 찾을 수 없음 +- 다른 기존 패키지들은 정상 작동 + +## 원인 분석 + +### Named Volume의 동작 방식 + +기존 `docker-compose.yml` 설정: + +```yaml +version: "1.0.0" +services: + web: + volumes: + - ./:/app + - node_modules:/app/node_modules + environment: + - NODE_ENV=development + - VITE_SENTRY_DSN=${VITE_SENTRY_DSN} + +volumes: + node_modules: + name: docker-ko-node_modules +``` + +**문제의 근본 원인**: + +1. **Named Volume의 영속성** + - `node_modules` named volume은 컨테이너 재시작 후에도 유지됨 + - 볼륨이 한 번 생성되면 내용이 업데이트되지 않음 + +2. **package.json 변경 시 동기화 실패** + - 호스트에서 `npm install`로 새 패키지 추가 + - 볼륨은 이전 상태를 유지 (새 패키지가 볼륨에 반영 안 됨) + - 컨테이너는 오래된 볼륨의 `node_modules`를 사용 + +3. **수동 관리 필요** + - 의존성이 변경될 때마다 `docker-compose down -v`로 볼륨 삭제 필요 + - 개발자가 이를 잊으면 의존성 불일치 발생 + +### Named Volume vs Anonymous Volume + +| 특성 | Named Volume | Anonymous Volume | +|------|-------------|------------------| +| 식별자 | 사용자 지정 이름 | Docker가 자동 생성 | +| 생명주기 | 컨테이너 삭제 후에도 유지 | `docker-compose down` 시 자동 삭제 | +| 의존성 동기화 | 수동 삭제 필요 | 자동 동기화 | +| 사용 사례 | DB 데이터 등 영속성 필요 | node_modules 등 빌드 산출물 | + +## 해결 방법 + +### 1. Named Volume을 Anonymous Volume으로 변경 + +**수정 전**: +```yaml +volumes: + - ./:/app + - node_modules:/app/node_modules + +volumes: + node_modules: + name: docker-ko-node_modules +``` + +**수정 후**: +```yaml +volumes: + - ./:/app + # 익명 볼륨으로 node_modules 보호 + # 호스트의 node_modules가 컨테이너 것을 덮어쓰지 않도록 방지 + - /app/node_modules +``` + +### 2. 기존 Named Volume 제거 및 재시작 + +```bash +# 1. 컨테이너와 볼륨 완전 제거 +docker-compose down -v + +# 2. 이미지 재빌드 및 컨테이너 시작 +docker-compose up --build -d + +# 3. 로그 확인 +docker-compose logs --tail=20 +``` + +### 3. 추가 개선: deprecated 경고 제거 + +```yaml +# version 필드 제거 (Docker Compose v2에서 불필요) +- version: "1.0.0" +services: + web: + ... +``` + +## 결과 + +### Before + +**문제점**: +- ❌ package.json 변경 시 수동으로 볼륨 삭제 필요 +- ❌ 브랜치 전환 시 의존성 충돌 가능 +- ❌ 팀원들이 볼륨 삭제를 잊어 에러 발생 +- ❌ `version` 필드로 인한 경고 메시지 + +**워크플로우**: +```bash +# package.json 변경 후 +npm install # 호스트에서 설치 +docker-compose down -v # 볼륨 삭제 (잊기 쉬움!) +docker-compose up --build # 재시작 +``` + +### After + +**개선 사항**: +- ✅ package.json 변경 시 자동 동기화 +- ✅ `docker-compose down` 시 볼륨 자동 정리 +- ✅ 브랜치별로 깨끗한 의존성 환경 +- ✅ 경고 메시지 없음 + +**워크플로우**: +```bash +# package.json 변경 후 +docker-compose up --build # 이것만으로 충분! +``` + +### 실제 빌드 로그 + +``` +✅ Sentry Vite 플러그인 정상 작동 +✅ Vite 개발 서버 시작 완료 (555ms) +✅ 접속 가능: http://localhost:5173/ +``` + +## 교훈 + +### 1. Docker Volume의 올바른 사용법 + +**Named Volume을 사용해야 하는 경우**: +- 데이터베이스 데이터 (PostgreSQL, MySQL 등) +- 영속적 스토리지가 필요한 경우 +- 여러 컨테이너 간 데이터 공유 + +**Anonymous Volume을 사용해야 하는 경우**: +- `node_modules`, `vendor` 등 빌드 산출물 +- 캐시 디렉토리 +- 일시적 파일 저장소 + +### 2. 개발 환경의 재현 가능성 + +개발 환경에서는 **재현 가능성**이 더 중요합니다: +- 브랜치를 전환할 때마다 깨끗한 환경 +- package.json 변경이 즉시 반영 +- 팀원 간 일관된 개발 환경 + +### 3. Docker Compose 버전 관리 + +Docker Compose v2부터는: +- `version` 필드가 더 이상 필요하지 않음 +- 명시하면 deprecated 경고 발생 +- 제거하는 것이 권장사항 + +### 4. Volume Mount 우선순위 + +Docker는 더 구체적인 마운트 경로가 우선순위를 가집니다: + +```yaml +volumes: + - ./:/app # 전체 디렉토리 마운트 + - /app/node_modules # node_modules만 보호 (우선순위 높음) +``` + +이를 통해 호스트의 빈 `node_modules`가 컨테이너의 것을 덮어쓰는 것을 방지합니다. + +## 참고 자료 + +- [Docker Compose - Volumes](https://docs.docker.com/compose/compose-file/07-volumes/) +- [Docker Compose version field (deprecated)](https://docs.docker.com/compose/compose-file/04-version-and-name/) +- [Anonymous vs Named Volumes](https://docs.docker.com/storage/volumes/) + +## 관련 커밋 + +``` +057f5be [fix] Docker Compose 및 gitignore 설정 업데이트 +- Docker Compose: named volume에서 anonymous volume으로 변경 +- node_modules 자동 정리 및 패키지 변경 시 자동 반영 지원 +``` \ No newline at end of file