diff --git a/.github/workflows/pr-build-check.yml b/.github/workflows/pr-build-check.yml index 60aa64da..c01c4d87 100644 --- a/.github/workflows/pr-build-check.yml +++ b/.github/workflows/pr-build-check.yml @@ -16,6 +16,8 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 + with: + version: 9 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 @@ -26,14 +28,5 @@ jobs: - name: Install dependencies run: pnpm install - - name: Clear TypeScript build info - run: | - echo "TypeScript 빌드 캐시 삭제" - rm -rf node_modules/.tmp - rm -rf node_modules/.cache - - - name: Check TypeScript compilation - run: pnpm tsc -b - - name: Build project run: pnpm run build diff --git a/build/entitlements.mac.plist b/build/entitlements.mac.plist new file mode 100644 index 00000000..0b2a95cb --- /dev/null +++ b/build/entitlements.mac.plist @@ -0,0 +1,25 @@ + + + + + + com.apple.security.cs.allow-jit + + + + com.apple.security.cs.allow-unsigned-executable-memory + + + + com.apple.security.network.client + + + + + + + + + \ No newline at end of file diff --git a/electron-builder.json b/electron-builder.json new file mode 100644 index 00000000..8f455460 --- /dev/null +++ b/electron-builder.json @@ -0,0 +1,28 @@ +{ + "appId": "com.morib.client", + "productName": "Morib", + "icon": "public/logo_icon.png", + "files": [ + "dist-react", + "dist-electron" + ], + "extraResources": [ + "dist-electron/preload.cjs" + ], + "mac": { + "target": ["dmg"], + "hardenedRuntime": true, + "gatekeeperAssess": false, + "entitlements": "build/entitlements.mac.plist", + "entitlementsInherit": "build/entitlements.mac.plist", + "notarize": true + }, + "afterSign": "scripts/notarize.cjs", + "linux": { + "target": "AppImage", + "category": "Utility" + }, + "win": { + "target": ["portable","msi"] + } +} \ No newline at end of file diff --git a/index.html b/index.html index 729d447e..7460f899 100644 --- a/index.html +++ b/index.html @@ -34,6 +34,6 @@
- + diff --git a/package.json b/package.json index ebfd38ec..8f6360b3 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,31 @@ { - "name": "morib-client", + "name": "Morib", + "description": "Your complete immersion space. Morib", + "author": { + "name": "Morib", + "email": "morib0615@gmail.com", + "url": "https://morib.in" + }, "private": true, "version": "0.0.0", "type": "module", + "main": "dist-electron/main.js", "scripts": { - "dev": "vite", + "dev": "pnpm dev:react & pnpm dev:electron", + "dev:react": "vite", + "dev:electron": "pnpm transpile:electron && cross-env NODE_ENV=development electron .", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "preview": "vite preview", + "transpile:electron": "tsc --project src/electron/tsconfig.json", + "dist:mac": "pnpm transpile:electron && pnpm build && electron-builder --mac --arm64", + "dist:mac:intel": "pnpm transpile:electron && pnpm build && electron-builder --mac --x64", + "dist:mac:universal": "pnpm transpile:electron && pnpm build && electron-builder --mac --universal", + "dist:mac:notarize": "./scripts/build-mac.sh", + "dist:mac:intel:notarize": "./scripts/build-mac-intel.sh", + "dist:mac:universal:notarize": "./scripts/build-mac-universal.sh", + "dist:win": "pnpm transpile:electron && pnpm build && electron-builder --win --x64", + "dist:linux": "pnpm transpile:electron && pnpm build && electron-builder --linux --x64" }, "dependencies": { "@remix-run/router": "^1.17.0", @@ -39,6 +57,9 @@ "@typescript-eslint/parser": "^7.14.1", "@vitejs/plugin-react-swc": "^3.7.0", "autoprefixer": "^10.4.19", + "cross-env": "^7.0.3", + "electron": "^35.1.5", + "electron-builder": "^26.0.12", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsx-a11y": "^6.9.0", @@ -60,5 +81,7 @@ "public" ] }, - "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0" + "engines": { + "pnpm": "9" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7ad5ced..f6278e4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,6 +90,15 @@ importers: autoprefixer: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.39) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + electron: + specifier: ^35.1.5 + version: 35.1.5 + electron-builder: + specifier: ^26.0.12 + version: 26.0.12(electron-builder-squirrel-windows@26.0.12) eslint: specifier: ^8.57.0 version: 8.57.0 @@ -138,6 +147,9 @@ importers: packages: + 7zip-bin@5.2.0: + resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -254,6 +266,57 @@ packages: '@bundled-es-modules/tough-cookie@0.1.6': resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} + '@develar/schema-utils@2.6.5': + resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} + engines: {node: '>= 8.9.0'} + + '@electron/asar@3.2.18': + resolution: {integrity: sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/asar@3.4.1': + resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/fuses@1.8.0': + resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==} + hasBin: true + + '@electron/get@2.0.3': + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} + version: 10.2.0-electron.1 + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/notarize@2.5.0': + resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} + engines: {node: '>= 10.0.0'} + + '@electron/osx-sign@1.3.1': + resolution: {integrity: sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==} + engines: {node: '>=12.0.0'} + hasBin: true + + '@electron/rebuild@3.7.0': + resolution: {integrity: sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==} + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/universal@2.0.1': + resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} + engines: {node: '>=16.4'} + + '@electron/windows-sign@1.2.1': + resolution: {integrity: sha512-YfASnrhJ+ve6Q43ZiDwmpBgYgi2u0bYjeAVi2tDfN7YWAKO8X9EEOuPGtqbJpPLM6TfAHimghICjWe2eaJ8BAg==} + engines: {node: '>=14.14'} + hasBin: true + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -431,6 +494,9 @@ packages: '@floating-ui/utils@0.2.4': resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==} + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -486,6 +552,14 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@malept/cross-spawn-promise@2.0.0': + resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} + engines: {node: '>= 12.13.0'} + + '@malept/flatpak-bundler@0.4.0': + resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} + engines: {node: '>= 10.0.0'} + '@mswjs/interceptors@0.37.3': resolution: {integrity: sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==} engines: {node: '>=18'} @@ -502,6 +576,15 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -642,6 +725,10 @@ packages: peerDependencies: react: ^16.14.0 || 17.x || 18.x || 19.x + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -788,6 +875,10 @@ packages: '@swc/types@0.1.9': resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==} + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + '@tanstack/eslint-plugin-query@5.49.1': resolution: {integrity: sha512-pTaEvG3HC1y7BOsFJtZmi8dhWwML97zEBq4qLM6BaUSzZ4WlFyhmtG2sBVO0H+lP1WgnLpQclRQ+nFikTqoUfQ==} peerDependencies: @@ -810,6 +901,10 @@ packages: peerDependencies: react: ^18.0.0 + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@trivago/prettier-plugin-sort-imports@4.3.0': resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} peerDependencies: @@ -819,21 +914,42 @@ packages: '@vue/compiler-sfc': optional: true + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} '@types/event-source-polyfill@1.0.5': resolution: {integrity: sha512-iaiDuDI2aIFft7XkcwMzDWLqo7LVDixd2sR6B4wxJut9xcp/Ev9bO4EFg4rm6S9QxATLBj5OPxdeocgmhjwKaw==} + '@types/fs-extra@9.0.13': + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/lodash@4.17.7': resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@22.10.3': resolution: {integrity: sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==} + '@types/plist@3.0.5': + resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -849,12 +965,21 @@ packages: '@types/react@18.3.3': resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + '@types/statuses@2.0.5': resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/verror@1.10.11': + resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@typescript-eslint/eslint-plugin@7.14.1': resolution: {integrity: sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -948,6 +1073,13 @@ packages: peerDependencies: vite: ^4 || ^5 + '@xmldom/xmldom@0.8.10': + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -958,6 +1090,27 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -992,6 +1145,16 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + app-builder-bin@5.0.0-alpha.12: + resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==} + + app-builder-lib@26.0.12: + resolution: {integrity: sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==} + engines: {node: '>=14.0.0'} + peerDependencies: + dmg-builder: 26.0.12 + electron-builder-squirrel-windows: 26.0.12 + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1036,12 +1199,31 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-exit-hook@2.0.1: + resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} + engines: {node: '>=0.12.0'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + autoprefixer@10.4.19: resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -1069,10 +1251,20 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1088,6 +1280,34 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + builder-util-runtime@9.3.1: + resolution: {integrity: sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==} + engines: {node: '>=12.0.0'} + + builder-util@26.0.11: + resolution: {integrity: sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==} + + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -1119,6 +1339,33 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + chromium-pickle-js@0.2.0: + resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} @@ -1127,6 +1374,13 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1152,9 +1406,24 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + compare-version@0.1.2: + resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} + engines: {node: '>=0.10.0'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + config-file-ts@0.2.8-rc1: + resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -1166,6 +1435,9 @@ packages: resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -1175,10 +1447,25 @@ packages: typescript: optional: true + crc@3.8.0: + resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + + cross-dirname@0.1.0: + resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1217,6 +1504,10 @@ packages: supports-color: optional: true + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + deep-equal@2.2.3: resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} engines: {node: '>= 0.4'} @@ -1224,6 +1515,13 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -1236,9 +1534,19 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dir-compare@4.2.0: + resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1246,6 +1554,15 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dmg-builder@26.0.12: + resolution: {integrity: sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==} + + dmg-license@1.0.11: + resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==} + engines: {node: '>=8'} + os: [darwin] + hasBin: true + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1257,18 +1574,57 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-builder-squirrel-windows@26.0.12: + resolution: {integrity: sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==} + + electron-builder@26.0.12: + resolution: {integrity: sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==} + engines: {node: '>=14.0.0'} + hasBin: true + + electron-publish@26.0.11: + resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==} + electron-to-chromium@1.4.815: resolution: {integrity: sha512-OvpTT2ItpOXJL7IGcYakRjHCt8L5GrrN/wHCQsRB4PQa1X9fe+X9oen245mIId7s14xvArCGSTIq644yPUKKLg==} + electron-winstaller@5.4.0: + resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} + engines: {node: '>=8.0.0'} + + electron@35.1.5: + resolution: {integrity: sha512-LolvbKKQUSCGvEwbEQNt1cxD1t+YYClDNwBIjn4d28KM8FSqUn9zJuf6AbqNA7tVs9OFl/EQpmg/m4lZV1hH8g==} + engines: {node: '>= 12.20.55'} + hasBin: true + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + engine.io-client@6.5.4: resolution: {integrity: sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==} @@ -1280,6 +1636,13 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1317,6 +1680,9 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -1416,6 +1782,18 @@ packages: event-source-polyfill@1.0.31: resolution: {integrity: sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==} + exponential-backoff@3.1.2: + resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + extsprintf@1.4.1: + resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} + engines: {'0': node >=0.6.0} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1435,10 +1813,16 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1477,6 +1861,30 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1507,6 +1915,10 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -1528,6 +1940,15 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -1547,6 +1968,13 @@ packages: gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1590,6 +2018,48 @@ packages: hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + iconv-corefoundation@1.1.7: + resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} + engines: {node: ^8.11.2 || >=10} + os: [darwin] + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1602,6 +2072,13 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -1613,6 +2090,10 @@ packages: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -1643,6 +2124,10 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + is-core-module@2.14.0: resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} engines: {node: '>= 0.4'} @@ -1674,6 +2159,13 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -1721,6 +2213,10 @@ packages: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -1735,6 +2231,14 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + + isbinaryfile@5.0.4: + resolution: {integrity: sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==} + engines: {node: '>= 18.0.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1745,6 +2249,11 @@ packages: resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} engines: {node: '>=14'} + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} @@ -1771,6 +2280,9 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -1788,11 +2300,20 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -1807,6 +2328,9 @@ packages: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} + lazy-val@1.0.5: + resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1832,6 +2356,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -1842,6 +2370,10 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + lru-cache@10.3.0: resolution: {integrity: sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==} engines: {node: 14 || >=16.14} @@ -1849,6 +2381,22 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1865,17 +2413,86 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -1904,12 +2521,31 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-abi@3.74.0: + resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} + engines: {node: '>=10'} + + node-addon-api@1.7.2: + resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1918,6 +2554,10 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1961,13 +2601,25 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -1976,6 +2628,10 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} @@ -2013,6 +2669,13 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pe-library@0.4.1: + resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} + engines: {node: '>=12', npm: '>=6'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -2031,6 +2694,10 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + plist@3.1.0: + resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} + engines: {node: '>=10.4.0'} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -2076,6 +2743,11 @@ packages: resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} engines: {node: ^10 || ^12 || >=14} + postject@1.0.0-alpha.6: + resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} + engines: {node: '>=14.0.0'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2141,6 +2813,26 @@ packages: engines: {node: '>=14'} hasBin: true + proc-log@2.0.1: + resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -2150,6 +2842,9 @@ packages: psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2160,6 +2855,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + react-datepicker@7.3.0: resolution: {integrity: sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==} peerDependencies: @@ -2203,9 +2902,17 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + read-binary-file-arch@1.0.6: + resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} + hasBin: true + read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2228,6 +2935,13 @@ packages: requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resedit@1.7.2: + resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} + engines: {node: '>=12', npm: '>=6'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2240,15 +2954,35 @@ packages: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@2.6.3: + resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + rollup@4.18.0: resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2261,13 +2995,32 @@ packages: resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex-test@1.0.3: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sanitize-filename@1.6.3: + resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} + + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2277,6 +3030,10 @@ packages: engines: {node: '>=10'} hasBin: true + serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -2297,14 +3054,29 @@ packages: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -2316,14 +3088,40 @@ packages: resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} engines: {node: '>=10.0.0'} + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + + socks@2.8.4: + resolution: {integrity: sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + stat-mode@1.0.0: + resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} + engines: {node: '>= 6'} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -2361,6 +3159,9 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2378,6 +3179,10 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -2405,6 +3210,17 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + temp-file@3.4.0: + resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -2418,6 +3234,16 @@ packages: timezone@1.0.23: resolution: {integrity: sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA==} + tiny-async-pool@1.3.0: + resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} + + tmp-promise@3.0.3: + resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} + + tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -2430,6 +3256,9 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} + truncate-utf8-bytes@1.0.2: + resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -2446,6 +3275,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -2485,10 +3318,26 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + update-browserslist-db@1.0.16: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -2501,9 +3350,16 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + utf8-byte-length@1.0.5: + resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + verror@1.10.1: + resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} + engines: {node: '>=0.6.0'} + vite-plugin-svgr@4.2.0: resolution: {integrity: sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==} peerDependencies: @@ -2537,6 +3393,9 @@ packages: terser: optional: true + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -2588,6 +3447,10 @@ packages: utf-8-validate: optional: true + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + xmlhttprequest-ssl@2.0.0: resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} engines: {node: '>=0.4.0'} @@ -2599,6 +3462,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.4.5: resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} engines: {node: '>= 14'} @@ -2612,6 +3478,9 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2622,6 +3491,8 @@ packages: snapshots: + 7zip-bin@5.2.0: {} + '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': @@ -2801,6 +3672,121 @@ snapshots: '@types/tough-cookie': 4.0.5 tough-cookie: 4.1.4 + '@develar/schema-utils@2.6.5': + dependencies: + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + '@electron/asar@3.2.18': + dependencies: + commander: 5.1.0 + glob: 7.2.3 + minimatch: 3.1.2 + + '@electron/asar@3.4.1': + dependencies: + commander: 5.1.0 + glob: 7.2.3 + minimatch: 3.1.2 + + '@electron/fuses@1.8.0': + dependencies: + chalk: 4.1.2 + fs-extra: 9.1.0 + minimist: 1.2.8 + + '@electron/get@2.0.3': + dependencies: + debug: 4.3.5 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.2 + glob: 8.1.0 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + proc-log: 2.0.1 + semver: 7.6.2 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/notarize@2.5.0': + dependencies: + debug: 4.3.5 + fs-extra: 9.1.0 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@electron/osx-sign@1.3.1': + dependencies: + compare-version: 0.1.2 + debug: 4.3.5 + fs-extra: 10.1.0 + isbinaryfile: 4.0.10 + minimist: 1.2.8 + plist: 3.1.0 + transitivePeerDependencies: + - supports-color + + '@electron/rebuild@3.7.0': + dependencies: + '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 + '@malept/cross-spawn-promise': 2.0.0 + chalk: 4.1.2 + debug: 4.3.5 + detect-libc: 2.0.3 + fs-extra: 10.1.0 + got: 11.8.6 + node-abi: 3.74.0 + node-api-version: 0.2.1 + ora: 5.4.1 + read-binary-file-arch: 1.0.6 + semver: 7.6.2 + tar: 6.2.1 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/universal@2.0.1': + dependencies: + '@electron/asar': 3.2.18 + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.3.5 + dir-compare: 4.2.0 + fs-extra: 11.3.0 + minimatch: 9.0.5 + plist: 3.1.0 + transitivePeerDependencies: + - supports-color + + '@electron/windows-sign@1.2.1': + dependencies: + cross-dirname: 0.1.0 + debug: 4.3.5 + fs-extra: 11.3.0 + minimist: 1.2.8 + postject: 1.0.0-alpha.6 + transitivePeerDependencies: + - supports-color + optional: true + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -2918,6 +3904,8 @@ snapshots: '@floating-ui/utils@0.2.4': {} + '@gar/promisify@1.1.3': {} + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -2982,6 +3970,19 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@malept/cross-spawn-promise@2.0.0': + dependencies: + cross-spawn: 7.0.6 + + '@malept/flatpak-bundler@0.4.0': + dependencies: + debug: 4.3.5 + fs-extra: 9.1.0 + lodash: 4.17.21 + tmp-promise: 3.0.3 + transitivePeerDependencies: + - supports-color + '@mswjs/interceptors@0.37.3': dependencies: '@open-draft/deferred-promise': 2.2.0 @@ -3003,6 +4004,16 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@npmcli/fs@2.1.2': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.6.2 + + '@npmcli/move-file@2.0.1': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': @@ -3110,6 +4121,8 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 18.3.1 + '@sindresorhus/is@4.6.0': {} + '@socket.io/component-emitter@3.1.2': {} '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.24.7)': @@ -3234,6 +4247,10 @@ snapshots: dependencies: '@swc/counter': 0.1.3 + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + '@tanstack/eslint-plugin-query@5.49.1(eslint@8.57.0)(typescript@5.5.2)': dependencies: '@typescript-eslint/utils': 8.0.0-alpha.30(eslint@8.57.0)(typescript@5.5.2) @@ -3257,6 +4274,8 @@ snapshots: '@tanstack/query-core': 5.49.1 react: 18.3.1 + '@tootallnate/once@2.0.0': {} + '@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.3.2)': dependencies: '@babel/generator': 7.17.7 @@ -3269,18 +4288,47 @@ snapshots: transitivePeerDependencies: - supports-color + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 22.10.3 + '@types/responselike': 1.0.3 + '@types/cookie@0.6.0': {} + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + '@types/estree@1.0.5': {} '@types/event-source-polyfill@1.0.5': {} + '@types/fs-extra@9.0.13': + dependencies: + '@types/node': 22.10.3 + + '@types/http-cache-semantics@4.0.4': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.10.3 + '@types/lodash@4.17.7': {} + '@types/ms@2.1.0': {} + '@types/node@22.10.3': dependencies: undici-types: 6.20.0 + '@types/plist@3.0.5': + dependencies: + '@types/node': 22.10.3 + xmlbuilder: 15.1.1 + optional: true + '@types/prop-types@15.7.12': {} '@types/react-datepicker@6.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -3305,10 +4353,22 @@ snapshots: '@types/prop-types': 15.7.12 csstype: 3.1.3 + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.10.3 + '@types/statuses@2.0.5': {} '@types/tough-cookie@4.0.5': {} + '@types/verror@1.10.11': + optional: true + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.10.3 + optional: true + '@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -3437,12 +4497,37 @@ snapshots: transitivePeerDependencies: - '@swc/helpers' + '@xmldom/xmldom@0.8.10': {} + + abbrev@1.1.1: {} + acorn-jsx@5.3.2(acorn@8.12.0): dependencies: acorn: 8.12.0 acorn@8.12.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + agent-base@7.1.3: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -3475,6 +4560,49 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + app-builder-bin@5.0.0-alpha.12: {} + + app-builder-lib@26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12): + dependencies: + '@develar/schema-utils': 2.6.5 + '@electron/asar': 3.2.18 + '@electron/fuses': 1.8.0 + '@electron/notarize': 2.5.0 + '@electron/osx-sign': 1.3.1 + '@electron/rebuild': 3.7.0 + '@electron/universal': 2.0.1 + '@malept/flatpak-bundler': 0.4.0 + '@types/fs-extra': 9.0.13 + async-exit-hook: 2.0.1 + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 + chromium-pickle-js: 0.2.0 + config-file-ts: 0.2.8-rc1 + debug: 4.3.5 + dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) + dotenv: 16.5.0 + dotenv-expand: 11.0.7 + ejs: 3.1.10 + electron-builder-squirrel-windows: 26.0.12(dmg-builder@26.0.12) + electron-publish: 26.0.11 + fs-extra: 10.1.0 + hosted-git-info: 4.1.0 + is-ci: 3.0.1 + isbinaryfile: 5.0.4 + js-yaml: 4.1.0 + json5: 2.2.3 + lazy-val: 1.0.5 + minimatch: 10.0.1 + plist: 3.1.0 + resedit: 1.7.2 + semver: 7.6.2 + tar: 6.2.1 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + transitivePeerDependencies: + - bluebird + - supports-color + arg@5.0.2: {} argparse@2.0.1: {} @@ -3548,10 +4676,22 @@ snapshots: is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 + assert-plus@1.0.0: + optional: true + ast-types-flow@0.0.8: {} + astral-regex@2.0.0: + optional: true + + async-exit-hook@2.0.1: {} + + async@3.2.6: {} + asynckit@0.4.0: {} + at-least-node@1.0.0: {} + autoprefixer@10.4.19(postcss@8.4.39): dependencies: browserslist: 4.23.1 @@ -3587,8 +4727,19 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + binary-extensions@2.3.0: {} + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + boolean@3.2.0: + optional: true + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -3609,6 +4760,79 @@ snapshots: node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builder-util-runtime@9.3.1: + dependencies: + debug: 4.3.5 + sax: 1.4.1 + transitivePeerDependencies: + - supports-color + + builder-util@26.0.11: + dependencies: + 7zip-bin: 5.2.0 + '@types/debug': 4.1.12 + app-builder-bin: 5.0.0-alpha.12 + builder-util-runtime: 9.3.1 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.3.5 + fs-extra: 10.1.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-ci: 3.0.1 + js-yaml: 4.1.0 + sanitize-filename: 1.6.3 + source-map-support: 0.5.21 + stat-mode: 1.0.0 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + transitivePeerDependencies: + - supports-color + + cacache@16.1.3: + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.2.1 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 @@ -3648,14 +4872,40 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - cli-width@4.1.0: {} + chownr@2.0.0: {} - cliui@8.0.1: - dependencies: - string-width: 4.2.3 + chromium-pickle-js@0.2.0: {} + + ci-info@3.9.0: {} + + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + optional: true + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clone@1.0.4: {} + clsx@2.1.1: {} color-convert@1.9.3: @@ -3676,14 +4926,29 @@ snapshots: commander@4.1.1: {} + commander@5.1.0: {} + + commander@9.5.0: + optional: true + + compare-version@0.1.2: {} + concat-map@0.0.1: {} + config-file-ts@0.2.8-rc1: + dependencies: + glob: 10.4.2 + typescript: 5.5.2 + convert-source-map@2.0.0: {} cookie@0.7.2: {} core-js@2.6.12: {} + core-util-is@1.0.2: + optional: true + cosmiconfig@8.3.6(typescript@5.5.2): dependencies: import-fresh: 3.3.0 @@ -3693,12 +4958,30 @@ snapshots: optionalDependencies: typescript: 5.5.2 + crc@3.8.0: + dependencies: + buffer: 5.7.1 + optional: true + + cross-dirname@0.1.0: + optional: true + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + cssesc@3.0.0: {} csstype@3.1.3: {} @@ -3731,6 +5014,10 @@ snapshots: dependencies: ms: 2.1.2 + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + deep-equal@2.2.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -3754,6 +5041,12 @@ snapshots: deep-is@0.1.4: {} + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + defer-to-connect@2.0.1: {} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 @@ -3768,14 +5061,51 @@ snapshots: delayed-stream@1.0.0: {} + detect-libc@2.0.3: {} + + detect-node@2.1.0: + optional: true + didyoumean@1.2.2: {} + dir-compare@4.2.0: + dependencies: + minimatch: 3.1.2 + p-limit: 3.1.0 + dir-glob@3.0.1: dependencies: path-type: 4.0.0 dlv@1.1.3: {} + dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): + dependencies: + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 + fs-extra: 10.1.0 + iconv-lite: 0.6.3 + js-yaml: 4.1.0 + optionalDependencies: + dmg-license: 1.0.11 + transitivePeerDependencies: + - bluebird + - electron-builder-squirrel-windows + - supports-color + + dmg-license@1.0.11: + dependencies: + '@types/plist': 3.0.5 + '@types/verror': 1.10.11 + ajv: 6.12.6 + crc: 3.8.0 + iconv-corefoundation: 1.1.7 + plist: 3.1.0 + smart-buffer: 4.2.0 + verror: 1.10.1 + optional: true + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -3789,14 +5119,93 @@ snapshots: no-case: 3.0.4 tslib: 2.6.3 + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.5.0 + + dotenv@16.5.0: {} + eastasianwidth@0.2.0: {} + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12): + dependencies: + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + electron-winstaller: 5.4.0 + transitivePeerDependencies: + - bluebird + - dmg-builder + - supports-color + + electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): + dependencies: + app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 + chalk: 4.1.2 + dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) + fs-extra: 10.1.0 + is-ci: 3.0.1 + lazy-val: 1.0.5 + simple-update-notifier: 2.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - bluebird + - electron-builder-squirrel-windows + - supports-color + + electron-publish@26.0.11: + dependencies: + '@types/fs-extra': 9.0.13 + builder-util: 26.0.11 + builder-util-runtime: 9.3.1 + chalk: 4.1.2 + form-data: 4.0.0 + fs-extra: 10.1.0 + lazy-val: 1.0.5 + mime: 2.6.0 + transitivePeerDependencies: + - supports-color + electron-to-chromium@1.4.815: {} + electron-winstaller@5.4.0: + dependencies: + '@electron/asar': 3.4.1 + debug: 4.3.5 + fs-extra: 7.0.1 + lodash: 4.17.21 + temp: 0.9.4 + optionalDependencies: + '@electron/windows-sign': 1.2.1 + transitivePeerDependencies: + - supports-color + + electron@35.1.5: + dependencies: + '@electron/get': 2.0.3 + '@types/node': 22.10.3 + extract-zip: 2.0.1 + transitivePeerDependencies: + - supports-color + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + engine.io-client@6.5.4: dependencies: '@socket.io/component-emitter': 3.1.2 @@ -3813,6 +5222,10 @@ snapshots: entities@4.5.0: {} + env-paths@2.2.1: {} + + err-code@2.0.3: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -3921,6 +5334,9 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + es6-error@4.1.1: + optional: true + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -4088,6 +5504,21 @@ snapshots: event-source-polyfill@1.0.31: {} + exponential-backoff@3.1.2: {} + + extract-zip@2.0.1: + dependencies: + debug: 4.3.5 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + extsprintf@1.4.1: + optional: true + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -4108,10 +5539,18 @@ snapshots: dependencies: reusify: 1.0.4 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -4137,7 +5576,7 @@ snapshots: foreground-child@3.2.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 form-data@4.0.0: @@ -4148,6 +5587,41 @@ snapshots: fraction.js@4.3.7: {} + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -4176,6 +5650,10 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 @@ -4208,6 +5686,24 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.6.2 + serialize-error: 7.0.1 + optional: true + globals@11.12.0: {} globals@13.24.0: @@ -4232,6 +5728,22 @@ snapshots: dependencies: get-intrinsic: 1.2.4 + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} graphql@16.10.0: {} @@ -4264,6 +5776,62 @@ snapshots: dependencies: react-is: 16.13.1 + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + http-cache-semantics@4.1.1: {} + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.3 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.2 + + iconv-corefoundation@1.1.7: + dependencies: + cli-truncate: 2.1.0 + node-addon-api: 1.7.2 + optional: true + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + ignore@5.3.1: {} import-fresh@3.3.0: @@ -4273,6 +5841,10 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + + infer-owner@1.0.4: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -4286,6 +5858,11 @@ snapshots: hasown: 2.0.2 side-channel: 1.0.6 + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 @@ -4317,6 +5894,10 @@ snapshots: is-callable@1.2.7: {} + is-ci@3.0.1: + dependencies: + ci-info: 3.9.0 + is-core-module@2.14.0: dependencies: hasown: 2.0.2 @@ -4345,6 +5926,10 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-interactive@1.0.0: {} + + is-lambda@1.0.1: {} + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -4382,6 +5967,8 @@ snapshots: dependencies: which-typed-array: 1.1.15 + is-unicode-supported@0.1.0: {} + is-weakmap@2.0.2: {} is-weakref@1.0.2: @@ -4395,6 +5982,10 @@ snapshots: isarray@2.0.5: {} + isbinaryfile@4.0.10: {} + + isbinaryfile@5.0.4: {} + isexe@2.0.0: {} iterator.prototype@1.1.2: @@ -4411,6 +6002,13 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + javascript-natural-sort@0.7.1: {} jiti@1.21.6: {} @@ -4426,6 +6024,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsbn@1.1.0: {} + jsesc@2.5.2: {} json-buffer@3.0.1: {} @@ -4436,8 +6036,21 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-safe@5.0.1: + optional: true + json5@2.2.3: {} + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.8 @@ -4455,6 +6068,8 @@ snapshots: dependencies: language-subtag-registry: 0.3.23 + lazy-val@1.0.5: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4474,6 +6089,11 @@ snapshots: lodash@4.17.21: {} + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -4484,12 +6104,47 @@ snapshots: dependencies: tslib: 2.6.3 + lowercase-keys@2.0.0: {} + lru-cache@10.3.0: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + make-fetch-happen@10.2.1: + dependencies: + agentkeepalive: 4.6.0 + cacache: 16.1.3 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + matcher@3.0.0: + dependencies: + escape-string-regexp: 4.0.0 + optional: true + merge2@1.4.1: {} micromatch@4.0.7: @@ -4503,16 +6158,75 @@ snapshots: dependencies: mime-db: 1.52.0 + mime@2.6.0: {} + + mimic-fn@2.1.0: {} + + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 + minimist@1.2.8: {} + + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + + minipass-fetch@2.1.2: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + minipass@7.1.2: {} + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: {} + ms@2.1.2: {} msw@2.7.0(@types/node@22.10.3)(typescript@5.5.2): @@ -4552,17 +6266,36 @@ snapshots: natural-compare@1.4.0: {} + negotiator@0.6.4: {} + no-case@3.0.4: dependencies: lower-case: 2.0.2 tslib: 2.6.3 + node-abi@3.74.0: + dependencies: + semver: 7.6.2 + + node-addon-api@1.7.2: + optional: true + + node-api-version@0.2.1: + dependencies: + semver: 7.6.2 + node-releases@2.0.14: {} + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + normalize-path@3.0.0: {} normalize-range@0.1.2: {} + normalize-url@6.1.0: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -4612,6 +6345,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4621,8 +6358,22 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + outvariant@1.4.3: {} + p-cancelable@2.1.1: {} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -4631,6 +6382,10 @@ snapshots: dependencies: p-limit: 3.1.0 + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + package-json-from-dist@1.0.0: {} parent-module@1.0.1: @@ -4661,6 +6416,10 @@ snapshots: path-type@4.0.0: {} + pe-library@0.4.1: {} + + pend@1.2.0: {} + picocolors@1.0.1: {} picocolors@1.1.1: {} @@ -4671,6 +6430,12 @@ snapshots: pirates@4.0.6: {} + plist@3.1.0: + dependencies: + '@xmldom/xmldom': 0.8.10 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + possible-typed-array-names@1.0.0: {} postcss-import@15.1.0(postcss@8.4.39): @@ -4710,6 +6475,11 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 + postject@1.0.0-alpha.6: + dependencies: + commander: 9.5.0 + optional: true + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -4724,6 +6494,17 @@ snapshots: prettier@3.3.2: {} + proc-log@2.0.1: {} + + progress@2.0.3: {} + + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -4736,12 +6517,19 @@ snapshots: dependencies: punycode: 2.3.1 + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + punycode@2.3.1: {} querystringify@2.2.0: {} queue-microtask@1.2.3: {} + quick-lru@5.1.1: {} + react-datepicker@7.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@floating-ui/react': 0.26.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -4787,10 +6575,22 @@ snapshots: dependencies: loose-envify: 1.4.0 + read-binary-file-arch@1.0.6: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + read-cache@1.0.0: dependencies: pify: 2.3.0 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -4818,6 +6618,12 @@ snapshots: requires-port@1.0.0: {} + resedit@1.7.2: + dependencies: + pe-library: 0.4.1 + + resolve-alpn@1.2.1: {} + resolve-from@4.0.0: {} resolve@1.22.8: @@ -4832,12 +6638,37 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + retry@0.12.0: {} + reusify@1.0.4: {} + rimraf@2.6.3: + dependencies: + glob: 7.2.3 + rimraf@3.0.2: dependencies: glob: 7.2.3 + roarr@2.15.4: + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.4 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + optional: true + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 @@ -4871,20 +6702,40 @@ snapshots: has-symbols: 1.0.3 isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-regex-test@1.0.3: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 + safer-buffer@2.1.2: {} + + sanitize-filename@1.6.3: + dependencies: + truncate-utf8-bytes: 1.0.2 + + sax@1.4.1: {} + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 + semver-compare@1.0.0: + optional: true + + semver@5.7.2: {} + semver@6.3.1: {} semver@7.6.2: {} + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4914,10 +6765,25 @@ snapshots: get-intrinsic: 1.2.4 object-inspect: 1.13.2 + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + simple-update-notifier@2.0.0: + dependencies: + semver: 7.6.2 + slash@3.0.0: {} + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + optional: true + + smart-buffer@4.2.0: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -4941,10 +6807,38 @@ snapshots: transitivePeerDependencies: - supports-color + socks-proxy-agent@7.0.0: + dependencies: + agent-base: 6.0.2 + debug: 4.3.5 + socks: 2.8.4 + transitivePeerDependencies: + - supports-color + + socks@2.8.4: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + source-map-js@1.2.0: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} + + sprintf-js@1.1.3: {} + + ssri@9.0.1: + dependencies: + minipass: 3.3.6 + + stat-mode@1.0.0: {} + statuses@2.0.1: {} stop-iteration-iterator@1.0.0: @@ -5004,6 +6898,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -5024,6 +6922,12 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 + sumchecker@3.0.1: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -5070,6 +6974,25 @@ snapshots: transitivePeerDependencies: - ts-node + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + temp-file@3.4.0: + dependencies: + async-exit-hook: 2.0.1 + fs-extra: 10.1.0 + + temp@0.9.4: + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.3 + text-table@0.2.0: {} thenify-all@1.6.0: @@ -5082,6 +7005,16 @@ snapshots: timezone@1.0.23: {} + tiny-async-pool@1.3.0: + dependencies: + semver: 5.7.2 + + tmp-promise@3.0.3: + dependencies: + tmp: 0.2.3 + + tmp@0.2.3: {} + to-fast-properties@2.0.0: {} to-regex-range@5.0.1: @@ -5095,6 +7028,10 @@ snapshots: universalify: 0.2.0 url-parse: 1.5.10 + truncate-utf8-bytes@1.0.2: + dependencies: + utf8-byte-length: 1.0.5 + ts-api-utils@1.3.0(typescript@5.5.2): dependencies: typescript: 5.5.2 @@ -5107,6 +7044,9 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@0.13.1: + optional: true + type-fest@0.20.2: {} type-fest@0.21.3: {} @@ -5156,8 +7096,20 @@ snapshots: undici-types@6.20.0: {} + unique-filename@2.0.1: + dependencies: + unique-slug: 3.0.0 + + unique-slug@3.0.0: + dependencies: + imurmurhash: 0.1.4 + + universalify@0.1.2: {} + universalify@0.2.0: {} + universalify@2.0.1: {} + update-browserslist-db@1.0.16(browserslist@4.23.1): dependencies: browserslist: 4.23.1 @@ -5173,8 +7125,17 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 + utf8-byte-length@1.0.5: {} + util-deprecate@1.0.2: {} + verror@1.10.1: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.4.1 + optional: true + vite-plugin-svgr@4.2.0(rollup@4.18.0)(typescript@5.5.2)(vite@5.3.2(@types/node@22.10.3)): dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.18.0) @@ -5195,6 +7156,10 @@ snapshots: '@types/node': 22.10.3 fsevents: 2.3.3 + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -5261,12 +7226,16 @@ snapshots: ws@8.17.1: {} + xmlbuilder@15.1.1: {} + xmlhttprequest-ssl@2.0.0: {} y18n@5.0.8: {} yallist@3.1.1: {} + yallist@4.0.0: {} + yaml@2.4.5: {} yargs-parser@21.1.1: {} @@ -5281,6 +7250,11 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yocto-queue@0.1.0: {} yoctocolors-cjs@2.1.2: {} diff --git a/public/logo_icon.png b/public/logo_icon.png new file mode 100644 index 00000000..339d13d0 Binary files /dev/null and b/public/logo_icon.png differ diff --git a/public/logo_icon.svg b/public/logo_icon.svg index a2db73a7..8d53e970 100644 --- a/public/logo_icon.svg +++ b/public/logo_icon.svg @@ -1,8 +1,8 @@ - - - + + + - + diff --git a/scripts/build-mac-intel.sh b/scripts/build-mac-intel.sh new file mode 100755 index 00000000..3810fa9d --- /dev/null +++ b/scripts/build-mac-intel.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# macOS Intel 앱 빌드 및 공증 스크립트 + +# .env 파일이 있으면 로드 +if [ -f ".env" ]; then + echo "=== .env 파일에서 환경 변수 로드 ===" + export $(grep -v '^#' .env | xargs) +fi + +# 환경 변수 확인 +if [ -z "$APPLE_ID" ] || [ -z "$APPLE_APP_SPECIFIC_PASSWORD" ] || [ -z "$APPLE_TEAM_ID" ]; then + echo "=== 환경 변수 설정이 필요합니다 ===" + echo "다음 환경 변수를 .env 파일에 설정하세요:" + echo "- APPLE_ID: Apple 개발자 계정 이메일" + echo "- APPLE_APP_SPECIFIC_PASSWORD: 앱 특정 비밀번호 (https://appleid.apple.com에서 생성)" + echo "- APPLE_TEAM_ID: Apple 개발자 팀 ID (10자리 식별자)" + echo "" + echo "예시 .env 파일:" + echo "APPLE_ID=your.email@example.com" + echo "APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx" + echo "APPLE_TEAM_ID=ABCDE12345" + exit 1 +fi + +# electron-builder 환경 변수 설정 +export CSC_IDENTITY_AUTO_DISCOVERY=true + +# 타입스크립트 컴파일 및 빌드 +echo "=== Electron 소스 코드 트랜스파일 ===" +pnpm transpile:electron + +echo "=== React 앱 빌드 ===" +pnpm build + +echo "=== electron-builder 실행 (Intel Mac) ===" +echo "공증을 시작합니다. 시간이 오래 걸릴 수 있습니다..." +pnpm electron-builder --mac --x64 + +echo "=== 빌드 및 공증 완료 ===" +echo "앱 위치: ./dist/" \ No newline at end of file diff --git a/scripts/build-mac-universal.sh b/scripts/build-mac-universal.sh new file mode 100755 index 00000000..50a89406 --- /dev/null +++ b/scripts/build-mac-universal.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# macOS Universal 앱 빌드 및 공증 스크립트 +# Intel(x64) + Apple Silicon(arm64) 모두 지원하는 Universal 바이너리 생성 + +# .env 파일이 있으면 로드 +if [ -f ".env" ]; then + echo "=== .env 파일에서 환경 변수 로드 ===" + export $(grep -v '^#' .env | xargs) +fi + +# 환경 변수 확인 +if [ -z "$APPLE_ID" ] || [ -z "$APPLE_APP_SPECIFIC_PASSWORD" ] || [ -z "$APPLE_TEAM_ID" ]; then + echo "=== 환경 변수 설정이 필요합니다 ===" + echo "다음 환경 변수를 .env 파일에 설정하세요:" + echo "- APPLE_ID: Apple 개발자 계정 이메일" + echo "- APPLE_APP_SPECIFIC_PASSWORD: 앱 특정 비밀번호 (https://appleid.apple.com에서 생성)" + echo "- APPLE_TEAM_ID: Apple 개발자 팀 ID (10자리 식별자)" + echo "" + echo "예시 .env 파일:" + echo "APPLE_ID=your.email@example.com" + echo "APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx" + echo "APPLE_TEAM_ID=ABCDE12345" + exit 1 +fi + +# electron-builder 환경 변수 설정 +export CSC_IDENTITY_AUTO_DISCOVERY=true + +# 타입스크립트 컴파일 및 빌드 +echo "=== Electron 소스 코드 트랜스파일 ===" +pnpm transpile:electron + +echo "=== React 앱 빌드 ===" +pnpm build + +echo "=== electron-builder 실행 (Universal Mac) ===" +echo "공증을 시작합니다. 시간이 오래 걸릴 수 있습니다..." +pnpm electron-builder --mac --universal + +echo "=== 빌드 및 공증 완료 ===" +echo "앱 위치: ./dist/" \ No newline at end of file diff --git a/scripts/build-mac.sh b/scripts/build-mac.sh new file mode 100755 index 00000000..9f53447f --- /dev/null +++ b/scripts/build-mac.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# macOS 앱 빌드 및 공증 스크립트 + +# .env 파일이 있으면 로드 +if [ -f ".env" ]; then + echo "=== .env 파일에서 환경 변수 로드 ===" + export $(grep -v '^#' .env | xargs) +fi + +# 환경 변수 확인 +if [ -z "$APPLE_ID" ] || [ -z "$APPLE_APP_SPECIFIC_PASSWORD" ] || [ -z "$APPLE_TEAM_ID" ]; then + echo "=== 환경 변수 설정이 필요합니다 ===" + echo "다음 환경 변수를 .env 파일에 설정하세요:" + echo "- APPLE_ID: Apple 개발자 계정 이메일" + echo "- APPLE_APP_SPECIFIC_PASSWORD: 앱 특정 비밀번호 (https://appleid.apple.com에서 생성)" + echo "- APPLE_TEAM_ID: Apple 개발자 팀 ID (10자리 식별자)" + echo "" + echo "예시 .env 파일:" + echo "APPLE_ID=your.email@example.com" + echo "APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx" + echo "APPLE_TEAM_ID=ABCDE12345" + exit 1 +fi + +# electron-builder 환경 변수 설정 +export CSC_IDENTITY_AUTO_DISCOVERY=true + +# 타입스크립트 컴파일 및 빌드 +echo "=== Electron 소스 코드 트랜스파일 ===" +pnpm transpile:electron + +echo "=== React 앱 빌드 ===" +pnpm build + +echo "=== electron-builder 실행 ===" +echo "공증을 시작합니다. 시간이 오래 걸릴 수 있습니다..." +pnpm electron-builder --mac --arm64 + +echo "=== 빌드 및 공증 완료 ===" +echo "앱 위치: ./dist/" \ No newline at end of file diff --git a/scripts/notarize.cjs b/scripts/notarize.cjs new file mode 100644 index 00000000..cedaa12f --- /dev/null +++ b/scripts/notarize.cjs @@ -0,0 +1,57 @@ +/** + * macOS 앱 공증(notarization) 스크립트 + * + * electron-builder v24 이상에서 사용 + * 공식 문서: https://www.electron.build/configuration/configuration#AfterPackContext + */ + +exports.default = async function (context) { + const { electronPlatformName, appOutDir } = context; + + if (electronPlatformName !== 'darwin') { + console.log('macOS 빌드가 아니므로 공증을 건너뜁니다'); + return; + } + + // electron-builder가 자체적으로 notarize 설정을 처리할 수 있으나, + // 추가적인 처리가 필요한 경우를 위한 스크립트입니다. + console.log('afterSign 훅이 실행되었습니다'); + console.log('앱이 정상적으로 공증되도록 환경 변수를 확인하세요:'); + console.log('- APPLE_ID: Apple 개발자 계정 이메일'); + console.log('- APPLE_APP_SPECIFIC_PASSWORD: 앱 특정 비밀번호'); + console.log('- APPLE_TEAM_ID: Apple 개발자 팀 ID'); + + // electron-builder v24부터는 notarize: true 설정으로 자동 공증이 가능합니다. + // 만약 수동으로 공증 로직을 추가하고 싶다면 아래와 같이 사용할 수 있습니다: + + /* + const { notarize } = require('@electron/notarize'); + + // 환경 변수에서 인증 정보 가져오기 + const { APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID } = process.env; + + if (!APPLE_ID || !APPLE_APP_SPECIFIC_PASSWORD || !APPLE_TEAM_ID) { + console.warn('공증에 필요한 환경 변수가 설정되지 않았습니다. 공증을 건너뜁니다.'); + return; + } + + const appName = context.packager.appInfo.productFilename; + const appPath = `${appOutDir}/${appName}.app`; + + console.log(`공증 시작: ${appPath}`); + + try { + await notarize({ + appPath, + appBundleId: 'com.morib.client', + appleId: APPLE_ID, + appleIdPassword: APPLE_APP_SPECIFIC_PASSWORD, + teamId: APPLE_TEAM_ID, + }); + console.log('공증 완료'); + } catch (error) { + console.error('공증 실패:', error); + throw error; + } + */ +}; diff --git a/src/App.tsx b/src/app/App.tsx similarity index 100% rename from src/App.tsx rename to src/app/App.tsx diff --git a/src/index.css b/src/app/index.css similarity index 100% rename from src/index.css rename to src/app/index.css diff --git a/src/main.tsx b/src/app/main.tsx similarity index 100% rename from src/main.tsx rename to src/app/main.tsx diff --git a/src/mocks/browser.ts b/src/app/mocks/browser.ts similarity index 100% rename from src/mocks/browser.ts rename to src/app/mocks/browser.ts diff --git a/src/mocks/common/common.resolvers.ts b/src/app/mocks/common/common.resolvers.ts similarity index 100% rename from src/mocks/common/common.resolvers.ts rename to src/app/mocks/common/common.resolvers.ts diff --git a/src/mocks/common/common.responses.ts b/src/app/mocks/common/common.responses.ts similarity index 100% rename from src/mocks/common/common.responses.ts rename to src/app/mocks/common/common.responses.ts diff --git a/src/mocks/handlers.ts b/src/app/mocks/handlers.ts similarity index 100% rename from src/mocks/handlers.ts rename to src/app/mocks/handlers.ts diff --git a/src/mocks/home/home.resolvers.ts b/src/app/mocks/home/home.resolvers.ts similarity index 100% rename from src/mocks/home/home.resolvers.ts rename to src/app/mocks/home/home.resolvers.ts diff --git a/src/mocks/home/home.responses.ts b/src/app/mocks/home/home.responses.ts similarity index 100% rename from src/mocks/home/home.responses.ts rename to src/app/mocks/home/home.responses.ts diff --git a/src/mocks/onboarding/onboarding.resolvers.ts b/src/app/mocks/onboarding/onboarding.resolvers.ts similarity index 100% rename from src/mocks/onboarding/onboarding.resolvers.ts rename to src/app/mocks/onboarding/onboarding.resolvers.ts diff --git a/src/mocks/onboarding/onboarding.responses.ts b/src/app/mocks/onboarding/onboarding.responses.ts similarity index 100% rename from src/mocks/onboarding/onboarding.responses.ts rename to src/app/mocks/onboarding/onboarding.responses.ts diff --git a/src/pages/AllowedServicePage/AllowedServiceGroupDetail/AllowedServiceGroupDetail.tsx b/src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/AllowedServiceGroupDetail.tsx similarity index 100% rename from src/pages/AllowedServicePage/AllowedServiceGroupDetail/AllowedServiceGroupDetail.tsx rename to src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/AllowedServiceGroupDetail.tsx diff --git a/src/pages/AllowedServicePage/AllowedServiceGroupDetail/Content/AllowedServiceGroupDetailContent.tsx b/src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Content/AllowedServiceGroupDetailContent.tsx similarity index 100% rename from src/pages/AllowedServicePage/AllowedServiceGroupDetail/Content/AllowedServiceGroupDetailContent.tsx rename to src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Content/AllowedServiceGroupDetailContent.tsx diff --git a/src/pages/AllowedServicePage/AllowedServiceGroupDetail/Header/AllowedServiceGroupDetailHeader.tsx b/src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Header/AllowedServiceGroupDetailHeader.tsx similarity index 100% rename from src/pages/AllowedServicePage/AllowedServiceGroupDetail/Header/AllowedServiceGroupDetailHeader.tsx rename to src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Header/AllowedServiceGroupDetailHeader.tsx diff --git a/src/pages/AllowedServicePage/AllowedServiceGroupDetail/Tabs/AllowedServiceGroupDetailTabs.tsx b/src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Tabs/AllowedServiceGroupDetailTabs.tsx similarity index 100% rename from src/pages/AllowedServicePage/AllowedServiceGroupDetail/Tabs/AllowedServiceGroupDetailTabs.tsx rename to src/app/pages/AllowedServicePage/AllowedServiceGroupDetail/Tabs/AllowedServiceGroupDetailTabs.tsx diff --git a/src/pages/AllowedServicePage/AllowedServiceList/AllowedServiceList.tsx b/src/app/pages/AllowedServicePage/AllowedServiceList/AllowedServiceList.tsx similarity index 100% rename from src/pages/AllowedServicePage/AllowedServiceList/AllowedServiceList.tsx rename to src/app/pages/AllowedServicePage/AllowedServiceList/AllowedServiceList.tsx diff --git a/src/pages/AllowedServicePage/AllowedServicePage.tsx b/src/app/pages/AllowedServicePage/AllowedServicePage.tsx similarity index 99% rename from src/pages/AllowedServicePage/AllowedServicePage.tsx rename to src/app/pages/AllowedServicePage/AllowedServicePage.tsx index 352aaf8d..6633a14f 100644 --- a/src/pages/AllowedServicePage/AllowedServicePage.tsx +++ b/src/app/pages/AllowedServicePage/AllowedServicePage.tsx @@ -52,11 +52,10 @@ const AllowedServicePage = () => { const friendsModalRef = useRef(null); const requireTitleModalRef = useRef(null); - + const bellIconRef = useRef(null); const notificationPanelRef = useRef(null); - const handleChangeTitleInput = (e: ChangeEvent) => { setTitleInput(e.target.value); }; @@ -385,10 +384,9 @@ const AllowedServicePage = () => { {() => } - - - {isNotificationVisible && } + + {isNotificationVisible && } ); }; diff --git a/src/pages/AllowedServicePage/ModalContentsAlert/ModalContentsAlert.tsx b/src/app/pages/AllowedServicePage/ModalContentsAlert/ModalContentsAlert.tsx similarity index 100% rename from src/pages/AllowedServicePage/ModalContentsAlert/ModalContentsAlert.tsx rename to src/app/pages/AllowedServicePage/ModalContentsAlert/ModalContentsAlert.tsx diff --git a/src/pages/AllowedServicePage/RecommendService/RecommendService.tsx b/src/app/pages/AllowedServicePage/RecommendService/RecommendService.tsx similarity index 95% rename from src/pages/AllowedServicePage/RecommendService/RecommendService.tsx rename to src/app/pages/AllowedServicePage/RecommendService/RecommendService.tsx index 86996815..8f9f5a65 100644 --- a/src/pages/AllowedServicePage/RecommendService/RecommendService.tsx +++ b/src/app/pages/AllowedServicePage/RecommendService/RecommendService.tsx @@ -22,7 +22,7 @@ const RecommendServiceItem = ({ recommendSite, ...props }: RecommendServiceItemP alt={`${recommendSite.siteName} 아이콘`} className="h-[4.2rem] w-[4.2rem] rounded-full" /> -

{recommendSite.siteName}

+

{recommendSite.siteName}

); }; diff --git a/src/pages/HomePage/BoxAddCategory/BoxAddCategory.tsx b/src/app/pages/HomePage/BoxAddCategory/BoxAddCategory.tsx similarity index 100% rename from src/pages/HomePage/BoxAddCategory/BoxAddCategory.tsx rename to src/app/pages/HomePage/BoxAddCategory/BoxAddCategory.tsx diff --git a/src/pages/HomePage/BoxCategory/BoxCategory.tsx b/src/app/pages/HomePage/BoxCategory/BoxCategory.tsx similarity index 100% rename from src/pages/HomePage/BoxCategory/BoxCategory.tsx rename to src/app/pages/HomePage/BoxCategory/BoxCategory.tsx diff --git a/src/pages/HomePage/BoxCategory/BoxTodoInput/BoxTodoInput.tsx b/src/app/pages/HomePage/BoxCategory/BoxTodoInput/BoxTodoInput.tsx similarity index 100% rename from src/pages/HomePage/BoxCategory/BoxTodoInput/BoxTodoInput.tsx rename to src/app/pages/HomePage/BoxCategory/BoxTodoInput/BoxTodoInput.tsx diff --git a/src/pages/HomePage/BoxCategory/StatusDefaultBoxCategory/StatusDefaultBoxCategory.tsx b/src/app/pages/HomePage/BoxCategory/StatusDefaultBoxCategory/StatusDefaultBoxCategory.tsx similarity index 100% rename from src/pages/HomePage/BoxCategory/StatusDefaultBoxCategory/StatusDefaultBoxCategory.tsx rename to src/app/pages/HomePage/BoxCategory/StatusDefaultBoxCategory/StatusDefaultBoxCategory.tsx diff --git a/src/pages/HomePage/BoxCategory/hooks/useCreateTodo.ts b/src/app/pages/HomePage/BoxCategory/hooks/useCreateTodo.ts similarity index 100% rename from src/pages/HomePage/BoxCategory/hooks/useCreateTodo.ts rename to src/app/pages/HomePage/BoxCategory/hooks/useCreateTodo.ts diff --git a/src/pages/HomePage/BoxTodayTodo/BoxTodayTodo.tsx b/src/app/pages/HomePage/BoxTodayTodo/BoxTodayTodo.tsx similarity index 100% rename from src/pages/HomePage/BoxTodayTodo/BoxTodayTodo.tsx rename to src/app/pages/HomePage/BoxTodayTodo/BoxTodayTodo.tsx diff --git a/src/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/ButtonHomeSmall/ButtonHomeSmall.tsx b/src/app/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/ButtonHomeSmall/ButtonHomeSmall.tsx similarity index 100% rename from src/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/ButtonHomeSmall/ButtonHomeSmall.tsx rename to src/app/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/ButtonHomeSmall/ButtonHomeSmall.tsx diff --git a/src/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/StatusAddBoxTodayTodo.tsx b/src/app/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/StatusAddBoxTodayTodo.tsx similarity index 100% rename from src/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/StatusAddBoxTodayTodo.tsx rename to src/app/pages/HomePage/BoxTodayTodo/StatusAddBoxTodayTodo/StatusAddBoxTodayTodo.tsx diff --git a/src/pages/HomePage/BoxTodayTodo/StatusDefaultBoxTodayTodo/StatusDefaultBoxTodayTodo.tsx b/src/app/pages/HomePage/BoxTodayTodo/StatusDefaultBoxTodayTodo/StatusDefaultBoxTodayTodo.tsx similarity index 100% rename from src/pages/HomePage/BoxTodayTodo/StatusDefaultBoxTodayTodo/StatusDefaultBoxTodayTodo.tsx rename to src/app/pages/HomePage/BoxTodayTodo/StatusDefaultBoxTodayTodo/StatusDefaultBoxTodayTodo.tsx diff --git a/src/pages/HomePage/ButtonMoreFriends/ButtonMoreFriends.tsx b/src/app/pages/HomePage/ButtonMoreFriends/ButtonMoreFriends.tsx similarity index 100% rename from src/pages/HomePage/ButtonMoreFriends/ButtonMoreFriends.tsx rename to src/app/pages/HomePage/ButtonMoreFriends/ButtonMoreFriends.tsx diff --git a/src/pages/HomePage/ButtonUserProfile/ButtonUserProfile.tsx b/src/app/pages/HomePage/ButtonUserProfile/ButtonUserProfile.tsx similarity index 100% rename from src/pages/HomePage/ButtonUserProfile/ButtonUserProfile.tsx rename to src/app/pages/HomePage/ButtonUserProfile/ButtonUserProfile.tsx diff --git a/src/pages/HomePage/DatePicker/ButtonDate/ButtonDate.tsx b/src/app/pages/HomePage/DatePicker/ButtonDate/ButtonDate.tsx similarity index 100% rename from src/pages/HomePage/DatePicker/ButtonDate/ButtonDate.tsx rename to src/app/pages/HomePage/DatePicker/ButtonDate/ButtonDate.tsx diff --git a/src/pages/HomePage/DatePicker/DatePicker.tsx b/src/app/pages/HomePage/DatePicker/DatePicker.tsx similarity index 100% rename from src/pages/HomePage/DatePicker/DatePicker.tsx rename to src/app/pages/HomePage/DatePicker/DatePicker.tsx diff --git a/src/pages/HomePage/DatePicker/hooks/useDatePicker.ts b/src/app/pages/HomePage/DatePicker/hooks/useDatePicker.ts similarity index 100% rename from src/pages/HomePage/DatePicker/hooks/useDatePicker.ts rename to src/app/pages/HomePage/DatePicker/hooks/useDatePicker.ts diff --git a/src/pages/HomePage/HomePage.tsx b/src/app/pages/HomePage/HomePage.tsx similarity index 95% rename from src/pages/HomePage/HomePage.tsx rename to src/app/pages/HomePage/HomePage.tsx index 9181d23c..5fe3f6a1 100644 --- a/src/pages/HomePage/HomePage.tsx +++ b/src/app/pages/HomePage/HomePage.tsx @@ -3,7 +3,7 @@ import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; import { useEffect, useRef, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import AutoFixedGrid from '@/shared/components/AutoFixedGrid/AutoFixedGrid'; import ModalContentsFriends from '@/shared/components/ModalContentsFriends/ModalContentsFriends'; @@ -44,12 +44,17 @@ import ButtonMoreFriends from './ButtonMoreFriends/ButtonMoreFriends'; import ButtonUserProfile from './ButtonUserProfile/ButtonUserProfile'; import DatePicker from './DatePicker/DatePicker'; import TimerRestriction from './ModalContentsAlert/TimerRestriction/TimerRestriction'; +import ModalContentsTimerError from './ModalContentsTimerError/ModalContentsTimerError'; import StatusDefaultHome from './StatusDefaultHome/StatusDefaultHome'; dayjs.extend(utc); dayjs.extend(timezone); const HomePage = () => { + const { search } = useLocation(); + const params = new URLSearchParams(search); + const isTimerError = params.get('error') === 'true'; + const todayDate = dayjs().tz('Asia/Seoul'); const formattedTodayDate = todayDate.format('YYYY-MM-DD'); const categoryRef = useRef(null); @@ -59,6 +64,7 @@ const HomePage = () => { const notificationPanelRef = useRef(null); const bellIconRef = useRef(null); const timerRestrictionModalRef = useRef(null); + const timerErrorModalRef = useRef(null); const [isNotificationVisible, setIsNotificationVisible] = useState(false); @@ -155,6 +161,10 @@ const HomePage = () => { ); }; + const handleCloseTimerErrorModal = () => { + timerErrorModalRef.current?.close(); + }; + const handleOpenFriendsModal = () => { friendsModalRef.current?.open(); }; @@ -250,6 +260,12 @@ const HomePage = () => { handleCategoryScroll(); }, [isAddingCategory, dailyCategoryTask.length]); + useEffect(() => { + if (isTimerError) { + timerErrorModalRef.current?.open(); + } + }, [isTimerError]); + return ( { )} + + {() => } + + {isNotificationVisible && } ); diff --git a/src/pages/HomePage/ModalContentsAlert/ButtonAlert/ButtonAlert.tsx b/src/app/pages/HomePage/ModalContentsAlert/ButtonAlert/ButtonAlert.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/ButtonAlert/ButtonAlert.tsx rename to src/app/pages/HomePage/ModalContentsAlert/ButtonAlert/ButtonAlert.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/Complete/Complete.tsx b/src/app/pages/HomePage/ModalContentsAlert/Complete/Complete.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/Complete/Complete.tsx rename to src/app/pages/HomePage/ModalContentsAlert/Complete/Complete.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/DeleteAccount/DeleteAccount.tsx b/src/app/pages/HomePage/ModalContentsAlert/DeleteAccount/DeleteAccount.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/DeleteAccount/DeleteAccount.tsx rename to src/app/pages/HomePage/ModalContentsAlert/DeleteAccount/DeleteAccount.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/Logoout/Logout.tsx b/src/app/pages/HomePage/ModalContentsAlert/Logoout/Logout.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/Logoout/Logout.tsx rename to src/app/pages/HomePage/ModalContentsAlert/Logoout/Logout.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/ModalContentsAlert.tsx b/src/app/pages/HomePage/ModalContentsAlert/ModalContentsAlert.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/ModalContentsAlert.tsx rename to src/app/pages/HomePage/ModalContentsAlert/ModalContentsAlert.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/RegisterAllowedService/RegisterAllowedService.tsx b/src/app/pages/HomePage/ModalContentsAlert/RegisterAllowedService/RegisterAllowedService.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/RegisterAllowedService/RegisterAllowedService.tsx rename to src/app/pages/HomePage/ModalContentsAlert/RegisterAllowedService/RegisterAllowedService.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/TimerRestriction/TimerRestriction.tsx b/src/app/pages/HomePage/ModalContentsAlert/TimerRestriction/TimerRestriction.tsx similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/TimerRestriction/TimerRestriction.tsx rename to src/app/pages/HomePage/ModalContentsAlert/TimerRestriction/TimerRestriction.tsx diff --git a/src/pages/HomePage/ModalContentsAlert/types/index.ts b/src/app/pages/HomePage/ModalContentsAlert/types/index.ts similarity index 100% rename from src/pages/HomePage/ModalContentsAlert/types/index.ts rename to src/app/pages/HomePage/ModalContentsAlert/types/index.ts diff --git a/src/app/pages/HomePage/ModalContentsTimerError/ModalContentsTimerError.tsx b/src/app/pages/HomePage/ModalContentsTimerError/ModalContentsTimerError.tsx new file mode 100644 index 00000000..bfb2df0f --- /dev/null +++ b/src/app/pages/HomePage/ModalContentsTimerError/ModalContentsTimerError.tsx @@ -0,0 +1,29 @@ +import { forwardRef } from 'react'; + +import { ButtonRadius5 } from '@/shared/components/ButtonRadius5/ButtonRadius5'; + +interface ModalContentsTimerErrorProps { + onClick: () => void; +} + +const ModalContentsTimerError = forwardRef(({ onClick }, ref) => { + return ( +
+

+ 자정이 지나 할 일이 초기화되었어요. +
+ 다시 할 일을 선택하고 몰입해 볼까요? +

+ + 확인 + +
+ ); +}); + +ModalContentsTimerError.displayName = 'ModalContentsTimerError'; + +export default ModalContentsTimerError; diff --git a/src/pages/HomePage/StatusDefaultHome/StatusDefaultHome.tsx b/src/app/pages/HomePage/StatusDefaultHome/StatusDefaultHome.tsx similarity index 100% rename from src/pages/HomePage/StatusDefaultHome/StatusDefaultHome.tsx rename to src/app/pages/HomePage/StatusDefaultHome/StatusDefaultHome.tsx diff --git a/src/pages/HomePage/TooltipFriendInfo/TooltipFriendInfo.tsx b/src/app/pages/HomePage/TooltipFriendInfo/TooltipFriendInfo.tsx similarity index 100% rename from src/pages/HomePage/TooltipFriendInfo/TooltipFriendInfo.tsx rename to src/app/pages/HomePage/TooltipFriendInfo/TooltipFriendInfo.tsx diff --git a/src/pages/HomePage/hooks/useCalendar.ts b/src/app/pages/HomePage/hooks/useCalendar.ts similarity index 100% rename from src/pages/HomePage/hooks/useCalendar.ts rename to src/app/pages/HomePage/hooks/useCalendar.ts diff --git a/src/pages/LoginPage/LoginPage.tsx b/src/app/pages/LoginPage/LoginPage.tsx similarity index 89% rename from src/pages/LoginPage/LoginPage.tsx rename to src/app/pages/LoginPage/LoginPage.tsx index 4a9adb17..4d6ecd28 100644 --- a/src/pages/LoginPage/LoginPage.tsx +++ b/src/app/pages/LoginPage/LoginPage.tsx @@ -15,12 +15,17 @@ const defaultOptions = { }; const API_URL = `${import.meta.env.VITE_GOOGLE_URL}`; +const ELECTRON_URL = `${import.meta.env.VITE_ELECTRON_AUTH_URL}`; const LoginPage = () => { const { isAnimationComplete, lottieRef, handleAnimationComplete } = useLottieAnimation(); const handleClick = () => { - window.location.href = API_URL; + if (window.electron) { + window.open(ELECTRON_URL, '_blank'); + } else { + window.location.href = API_URL; + } }; const handleMouseEnter = () => { diff --git a/src/pages/LoginPage/hooks/useLottieAnimation.ts b/src/app/pages/LoginPage/hooks/useLottieAnimation.ts similarity index 100% rename from src/pages/LoginPage/hooks/useLottieAnimation.ts rename to src/app/pages/LoginPage/hooks/useLottieAnimation.ts diff --git a/src/pages/NotFoundPage/NotFoundPage.tsx b/src/app/pages/NotFoundPage/NotFoundPage.tsx similarity index 100% rename from src/pages/NotFoundPage/NotFoundPage.tsx rename to src/app/pages/NotFoundPage/NotFoundPage.tsx diff --git a/src/pages/OnboardingPage/ButtonSkip/ButtonSkip.tsx b/src/app/pages/OnboardingPage/ButtonSkip/ButtonSkip.tsx similarity index 100% rename from src/pages/OnboardingPage/ButtonSkip/ButtonSkip.tsx rename to src/app/pages/OnboardingPage/ButtonSkip/ButtonSkip.tsx diff --git a/src/pages/OnboardingPage/OnboardingPage.tsx b/src/app/pages/OnboardingPage/OnboardingPage.tsx similarity index 100% rename from src/pages/OnboardingPage/OnboardingPage.tsx rename to src/app/pages/OnboardingPage/OnboardingPage.tsx diff --git a/src/pages/OnboardingPage/StepField/StepField.tsx b/src/app/pages/OnboardingPage/StepField/StepField.tsx similarity index 100% rename from src/pages/OnboardingPage/StepField/StepField.tsx rename to src/app/pages/OnboardingPage/StepField/StepField.tsx diff --git a/src/pages/OnboardingPage/StepService/AllowedServices/AllowedServices.tsx b/src/app/pages/OnboardingPage/StepService/AllowedServices/AllowedServices.tsx similarity index 100% rename from src/pages/OnboardingPage/StepService/AllowedServices/AllowedServices.tsx rename to src/app/pages/OnboardingPage/StepService/AllowedServices/AllowedServices.tsx diff --git a/src/pages/OnboardingPage/StepService/ButtonService/ButtonService.tsx b/src/app/pages/OnboardingPage/StepService/ButtonService/ButtonService.tsx similarity index 100% rename from src/pages/OnboardingPage/StepService/ButtonService/ButtonService.tsx rename to src/app/pages/OnboardingPage/StepService/ButtonService/ButtonService.tsx diff --git a/src/pages/OnboardingPage/StepService/StepService.tsx b/src/app/pages/OnboardingPage/StepService/StepService.tsx similarity index 100% rename from src/pages/OnboardingPage/StepService/StepService.tsx rename to src/app/pages/OnboardingPage/StepService/StepService.tsx diff --git a/src/pages/OnboardingPage/StepService/Tabs/Tabs.tsx b/src/app/pages/OnboardingPage/StepService/Tabs/Tabs.tsx similarity index 100% rename from src/pages/OnboardingPage/StepService/Tabs/Tabs.tsx rename to src/app/pages/OnboardingPage/StepService/Tabs/Tabs.tsx diff --git a/src/pages/OnboardingPage/StepStart/StepStart.tsx b/src/app/pages/OnboardingPage/StepStart/StepStart.tsx similarity index 100% rename from src/pages/OnboardingPage/StepStart/StepStart.tsx rename to src/app/pages/OnboardingPage/StepStart/StepStart.tsx diff --git a/src/pages/OnboardingPage/hooks/useFunnel.tsx b/src/app/pages/OnboardingPage/hooks/useFunnel.tsx similarity index 100% rename from src/pages/OnboardingPage/hooks/useFunnel.tsx rename to src/app/pages/OnboardingPage/hooks/useFunnel.tsx diff --git a/src/pages/OnboardingPage/utils/serviceUrl.ts b/src/app/pages/OnboardingPage/utils/serviceUrl.ts similarity index 100% rename from src/pages/OnboardingPage/utils/serviceUrl.ts rename to src/app/pages/OnboardingPage/utils/serviceUrl.ts diff --git a/src/pages/RedirectPage/RedirectPage.tsx b/src/app/pages/RedirectPage/RedirectPage.tsx similarity index 96% rename from src/pages/RedirectPage/RedirectPage.tsx rename to src/app/pages/RedirectPage/RedirectPage.tsx index 1ae841d8..f8ee4bbb 100644 --- a/src/pages/RedirectPage/RedirectPage.tsx +++ b/src/app/pages/RedirectPage/RedirectPage.tsx @@ -12,7 +12,6 @@ const RedirectPage = () => { const navigate = useNavigate(); useEffect(() => { - // @ts-expect-error const params = window.electron ? new URLSearchParams(window.location.hash.split('?')[1]) : new URLSearchParams(search); @@ -34,7 +33,7 @@ const RedirectPage = () => { localStorage.setItem('isOnboardingCompleted', 온보딩완료여부); navigate(`${ROUTES_CONFIG.home.path}`, { replace: true }); } - }, [navigate, search]); + }, []); return ; }; diff --git a/src/pages/TimerPage/AllowedServices/AllowedServicesItem.tsx b/src/app/pages/TimerPage/AllowedServices/AllowedServicesItem.tsx similarity index 100% rename from src/pages/TimerPage/AllowedServices/AllowedServicesItem.tsx rename to src/app/pages/TimerPage/AllowedServices/AllowedServicesItem.tsx diff --git a/src/pages/TimerPage/AllowedServices/AllowedServicesPopover.tsx b/src/app/pages/TimerPage/AllowedServices/AllowedServicesPopover.tsx similarity index 100% rename from src/pages/TimerPage/AllowedServices/AllowedServicesPopover.tsx rename to src/app/pages/TimerPage/AllowedServices/AllowedServicesPopover.tsx diff --git a/src/pages/TimerPage/AllowedServices/AllowedServicesTitle.tsx b/src/app/pages/TimerPage/AllowedServices/AllowedServicesTitle.tsx similarity index 100% rename from src/pages/TimerPage/AllowedServices/AllowedServicesTitle.tsx rename to src/app/pages/TimerPage/AllowedServices/AllowedServicesTitle.tsx diff --git a/src/pages/TimerPage/AllowedServices/AllowedServicesTooltip.tsx b/src/app/pages/TimerPage/AllowedServices/AllowedServicesTooltip.tsx similarity index 100% rename from src/pages/TimerPage/AllowedServices/AllowedServicesTooltip.tsx rename to src/app/pages/TimerPage/AllowedServices/AllowedServicesTooltip.tsx diff --git a/src/pages/TimerPage/AllowedServices/Checkbox.tsx b/src/app/pages/TimerPage/AllowedServices/Checkbox.tsx similarity index 100% rename from src/pages/TimerPage/AllowedServices/Checkbox.tsx rename to src/app/pages/TimerPage/AllowedServices/Checkbox.tsx diff --git a/src/pages/TimerPage/Carousel/Carousel.tsx b/src/app/pages/TimerPage/Carousel/Carousel.tsx similarity index 100% rename from src/pages/TimerPage/Carousel/Carousel.tsx rename to src/app/pages/TimerPage/Carousel/Carousel.tsx diff --git a/src/pages/TimerPage/Carousel/CarouselFriend.tsx b/src/app/pages/TimerPage/Carousel/CarouselFriend.tsx similarity index 100% rename from src/pages/TimerPage/Carousel/CarouselFriend.tsx rename to src/app/pages/TimerPage/Carousel/CarouselFriend.tsx diff --git a/src/pages/TimerPage/MainTimer/MainTimer.tsx b/src/app/pages/TimerPage/MainTimer/MainTimer.tsx similarity index 100% rename from src/pages/TimerPage/MainTimer/MainTimer.tsx rename to src/app/pages/TimerPage/MainTimer/MainTimer.tsx diff --git a/src/pages/TimerPage/MainTimer/TimerDisplay/ButtonTimerPlay/ButtonTimerPlay.tsx b/src/app/pages/TimerPage/MainTimer/TimerDisplay/ButtonTimerPlay/ButtonTimerPlay.tsx similarity index 100% rename from src/pages/TimerPage/MainTimer/TimerDisplay/ButtonTimerPlay/ButtonTimerPlay.tsx rename to src/app/pages/TimerPage/MainTimer/TimerDisplay/ButtonTimerPlay/ButtonTimerPlay.tsx diff --git a/src/pages/TimerPage/MainTimer/TimerDisplay/ProgressCircle/ProgressCircle.tsx b/src/app/pages/TimerPage/MainTimer/TimerDisplay/ProgressCircle/ProgressCircle.tsx similarity index 100% rename from src/pages/TimerPage/MainTimer/TimerDisplay/ProgressCircle/ProgressCircle.tsx rename to src/app/pages/TimerPage/MainTimer/TimerDisplay/ProgressCircle/ProgressCircle.tsx diff --git a/src/pages/TimerPage/MainTimer/TimerDisplay/TimerDisplay.tsx b/src/app/pages/TimerPage/MainTimer/TimerDisplay/TimerDisplay.tsx similarity index 100% rename from src/pages/TimerPage/MainTimer/TimerDisplay/TimerDisplay.tsx rename to src/app/pages/TimerPage/MainTimer/TimerDisplay/TimerDisplay.tsx diff --git a/src/pages/TimerPage/MainTimer/TimerHeader/TimerHeader.tsx b/src/app/pages/TimerPage/MainTimer/TimerHeader/TimerHeader.tsx similarity index 100% rename from src/pages/TimerPage/MainTimer/TimerHeader/TimerHeader.tsx rename to src/app/pages/TimerPage/MainTimer/TimerHeader/TimerHeader.tsx diff --git a/src/pages/TimerPage/NavigationButtons/NavigationButtons.tsx b/src/app/pages/TimerPage/NavigationButtons/NavigationButtons.tsx similarity index 100% rename from src/pages/TimerPage/NavigationButtons/NavigationButtons.tsx rename to src/app/pages/TimerPage/NavigationButtons/NavigationButtons.tsx diff --git a/src/pages/TimerPage/SideMenuTimer/SideMenuTimer.tsx b/src/app/pages/TimerPage/SideMenuTimer/SideMenuTimer.tsx similarity index 100% rename from src/pages/TimerPage/SideMenuTimer/SideMenuTimer.tsx rename to src/app/pages/TimerPage/SideMenuTimer/SideMenuTimer.tsx diff --git a/src/pages/TimerPage/TimerPage.tsx b/src/app/pages/TimerPage/TimerPage.tsx similarity index 68% rename from src/pages/TimerPage/TimerPage.tsx rename to src/app/pages/TimerPage/TimerPage.tsx index 27d7a8be..b0e8b07b 100644 --- a/src/pages/TimerPage/TimerPage.tsx +++ b/src/app/pages/TimerPage/TimerPage.tsx @@ -2,14 +2,12 @@ import dayjs from 'dayjs'; import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; -import React, { useCallback, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { splitTasksByCompletion } from '@/shared/utils/timer'; -import { ROUTES_CONFIG } from '@/router/routesConfig'; - -import { useGetTimerTodos } from '@/shared/apisV2/timer/timer.queries'; +import { useGetSelectedTimerTask, useGetTimerTodos } from '@/shared/apisV2/timer/timer.queries'; import AllowedServicesPopover from './AllowedServices/AllowedServicesPopover'; import AllowedServicesTitle from './AllowedServices/AllowedServicesTitle'; @@ -29,7 +27,16 @@ dayjs.extend(timezone); */ const TimerPageContent = () => { const navigate = useNavigate(); - const { todayFormattedDate, isSidebarOpen, isAllowedServiceVisible, allowedServices, actions } = useTimerContext(); + const { + todayFormattedDate, + isSidebarOpen, + isAllowedServiceVisible, + allowedServices, + isPlaying, + selectedTask, + browserMonitor, + actions, + } = useTimerContext(); // 할일 데이터 조회 const { data: todosData } = useGetTimerTodos({ targetDate: todayFormattedDate }); @@ -41,7 +48,21 @@ const TimerPageContent = () => { return splitTasksByCompletion(todos); }, [todosData]); - const { isPlaying, selectedTask } = useTimerContext(); + const { data: selectedTimerTaskData, isError: isSelectedTimerTaskError } = useGetSelectedTimerTask({ + targetDate: todayFormattedDate, + }); + + // 허용되지 않은 URL 감지 시 처리 + const handleRegisterAllowedService = useCallback( + (url: string) => { + // 허용 서비스로 등록 + actions.registerAllowedService(url); + + // 허용 서비스 팝업 표시 + actions.showAllowedServices(); + }, + [actions], + ); // 홈 네비게이션 핸들러 const navigateToHome = useCallback(async () => { @@ -50,11 +71,31 @@ const TimerPageContent = () => { if (isPlaying && selectedTask.id !== null && actions.stopCurrentTimer) { await actions.stopCurrentTimer(selectedTask.id); } + + // URL 모니터링 중지 + if (browserMonitor.isActive) { + actions.stopUrlMonitoring(); + } + navigate('/home'); } catch (error) { console.error('홈으로 이동 중 오류 발생:', error); } - }, [isPlaying, selectedTask.id, actions, navigate]); + }, [isPlaying, selectedTask.id, browserMonitor.isActive, actions, navigate]); + + useEffect(() => { + if (isSelectedTimerTaskError || selectedTimerTaskData?.data.selectedTaskId === null) { + // Electron 시스템 알림 사용 + if (window.electron && window.electron.notification) { + window.electron.notification.showSystemNotification( + '타이머에서 선택된 할일이 초기화 되었어요.', + '다시 타이머를 실행해주세요.', + ); + } + + navigate('/home?error=true'); + } + }, [isSelectedTimerTaskError, navigate, selectedTimerTaskData?.data.selectedTaskId]); return (
diff --git a/src/pages/TimerPage/contexts/TimerContext.tsx b/src/app/pages/TimerPage/contexts/TimerContext.tsx similarity index 60% rename from src/pages/TimerPage/contexts/TimerContext.tsx rename to src/app/pages/TimerPage/contexts/TimerContext.tsx index ece3f26d..92014e51 100644 --- a/src/pages/TimerPage/contexts/TimerContext.tsx +++ b/src/app/pages/TimerPage/contexts/TimerContext.tsx @@ -1,10 +1,11 @@ import dayjs from 'dayjs'; -import React, { ReactNode, createContext, useContext } from 'react'; +import React, { ReactNode, createContext, useContext, useEffect } from 'react'; import { DATE_FORMAT, TIMEZONE } from '@/shared/constants/timerPageText'; import { useAllowedServices } from '../hooks/useAllowedServices'; +import { useBrowserMonitor } from '../hooks/useBrowserMonitor'; import { useTimerActions } from '../hooks/useTimerActions'; import { useTimerState } from '../hooks/useTimerState'; import { useUIState } from '../hooks/useUIState'; @@ -30,6 +31,11 @@ interface TimerContextType { allowedSiteUrls: string[]; baseUrls: string[]; }; + // URL 모니터링 상태 추가 + browserMonitor: { + isActive: boolean; + lastUnallowedUrl: string | null; + }; actions: { togglePlay: (isPlaying: boolean) => void; updateElapsedTime: (newTime: number) => void; @@ -38,6 +44,10 @@ interface TimerContextType { showAllowedServices: () => void; hideAllowedServices: () => void; stopCurrentTimer?: (taskId: number) => Promise; + // URL 모니터링 액션 추가 + startUrlMonitoring: () => void; + stopUrlMonitoring: () => void; + registerAllowedService: (url: string) => void; }; } @@ -87,6 +97,45 @@ export const TimerProvider: React.FC = ({ children }) => { isPlaying, }); + // 브라우저 URL 모니터링 훅 + // 허용 서비스 목록 처리 - 중복 제거 및 형식 통일 + const processedAllowedServices = [ + // 기본 도메인 배열 + ...allowedServices.baseUrls, + ]; + + // 브라우저 모니터링 훅 초기화 + const browserMonitor = useBrowserMonitor({ + allowedServices: processedAllowedServices, + isTimerActive: isPlaying, + onStopTimer: async () => { + // 타이머 정지 로직 + try { + // 타이머가 활성화 상태이고 선택된 작업이 있을 때만 실행 + if (isPlaying && selectedTask.id !== null) { + if (timerActions.stopCurrentTimer) { + console.log('타이머 중지 함수 호출 - 작업 ID:', selectedTask.id); + + // 타이머 중지 함수 동기적으로 호출 + const result = await timerActions.stopCurrentTimer(selectedTask.id); + console.log('타이머 중지 완료:', result); + return true; + } else { + console.error('타이머 중지 함수가 없습니다!'); + } + } else { + console.log('타이머를 중지할 필요가 없습니다. isPlaying:', isPlaying, 'selectedTask.id:', selectedTask.id); + } + } catch (error) { + console.error('타이머 중지 중 예외 발생:', error); + } + return false; + }, + onStartTimer: () => { + timerActions.togglePlay(true); + }, + }); + // Context 값 구성 const contextValue: TimerContextType = { todayFormattedDate, @@ -98,6 +147,10 @@ export const TimerProvider: React.FC = ({ children }) => { isSidebarOpen, isAllowedServiceVisible, allowedServices, + browserMonitor: { + isActive: browserMonitor.isActive, + lastUnallowedUrl: browserMonitor.lastUnallowedUrl, + }, actions: { togglePlay: timerActions.togglePlay, updateElapsedTime, @@ -106,6 +159,9 @@ export const TimerProvider: React.FC = ({ children }) => { showAllowedServices: uiActions.showAllowedServices, hideAllowedServices: uiActions.hideAllowedServices, stopCurrentTimer: timerActions.stopCurrentTimer, + startUrlMonitoring: browserMonitor.startMonitoring, + stopUrlMonitoring: browserMonitor.stopMonitoring, + registerAllowedService: browserMonitor.registerAllowedService, }, }; diff --git a/src/pages/TimerPage/hooks/useAllowedServices.ts b/src/app/pages/TimerPage/hooks/useAllowedServices.ts similarity index 100% rename from src/pages/TimerPage/hooks/useAllowedServices.ts rename to src/app/pages/TimerPage/hooks/useAllowedServices.ts diff --git a/src/app/pages/TimerPage/hooks/useBrowserMonitor.ts b/src/app/pages/TimerPage/hooks/useBrowserMonitor.ts new file mode 100644 index 00000000..2f07e23b --- /dev/null +++ b/src/app/pages/TimerPage/hooks/useBrowserMonitor.ts @@ -0,0 +1,249 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; + +import { useQueryClient } from '@tanstack/react-query'; + +import { usePostAddAllowedService } from '@/shared/apisV2/allowedService/allowedService.mutations'; +import { timerKeys } from '@/shared/apisV2/timer/timer.keys'; +import { useGetPopoverAllowedServiceList } from '@/shared/apisV2/timer/timer.queries'; + +interface UseBrowserMonitorProps { + allowedServices: string[]; + isTimerActive: boolean; + onStopTimer: () => void; + onStartTimer: () => void; +} + +/** + * 브라우저 URL 모니터링 훅 + * 허용된 서비스 외의 URL에 접속하면 타이머를 자동으로 정지 + */ +export function useBrowserMonitor(props: UseBrowserMonitorProps) { + const { allowedServices, isTimerActive, onStopTimer } = props; + + const [isActive, setIsActive] = useState(false); + const [lastUnallowedUrl, setLastUnallowedUrl] = useState(null); + + // 이벤트 처리 상태 관리 (타이머 리렌더링 이슈로 ref로 이벤트 임시 처리) + const isStoppingTimer = useRef(false); + + // useRef로 최신 값 참조를 위한 설정 + const listenersRegistered = useRef(false); + const currentOnStopTimer = useRef(onStopTimer); + const currentIsTimerActive = useRef(isTimerActive); + + // 최신 값으로 ref 업데이트 + useEffect(() => { + currentOnStopTimer.current = onStopTimer; + currentIsTimerActive.current = isTimerActive; + + // 타이머가 비활성화되면 정지 상태 초기화 + if (!isTimerActive) { + isStoppingTimer.current = false; + } + }, [onStopTimer, isTimerActive]); + + // 허용 서비스 목록 전처리 (도메인 형식으로 변환) + const processAllowedServices = useCallback(() => { + return allowedServices.filter((domain) => domain && domain.includes('.')); + }, [allowedServices]); + + // 브라우저 모니터링 시작 + const startMonitoring = useCallback(() => { + if (!window.electron?.browserMonitor) { + console.warn('브라우저 모니터링 API를 사용할 수 없습니다.'); + return; + } + + // 타이머가 정지 중이거나 정지 처리 중이면 모니터링 시작하지 않음 + if (!currentIsTimerActive.current || isStoppingTimer.current) { + console.log('타이머가 비활성 상태이거나 정지 처리 중이므로 모니터링을 시작하지 않습니다.'); + return; + } + + // 허용 서비스 목록 가공 + const domains = processAllowedServices(); + console.log('모니터링 시작. 허용 도메인:', domains); + + // 허용 서비스 목록을 메인 프로세스로 전송 + window.electron.browserMonitor.startMonitoring(domains); + setIsActive(true); + }, [processAllowedServices]); + + // 브라우저 모니터링 중지 + const stopMonitoring = useCallback(() => { + if (!window.electron?.browserMonitor) return; + + if (isActive) { + console.log('브라우저 모니터링 중지'); + window.electron.browserMonitor.stopMonitoring(); + setIsActive(false); + } + }, [isActive]); + + // 허용 서비스 등록 + const registerAllowedService = useCallback( + (url: string) => { + try { + // URL에서 호스트명 추출 + const hostname = new URL(url).hostname; + console.log('허용 서비스 등록 요청:', hostname); + + // 추후 구현: 허용 서비스 목록에 호스트명 추가하는 API 호출 + console.log('허용 서비스 등록:', hostname); + + // 모니터링 재시작 (새 허용 목록 반영) + if (isActive) { + stopMonitoring(); + // 약간의 지연 후 재시작 (상태 업데이트 반영 위해) + setTimeout(() => startMonitoring(), 100); + } + } catch (error) { + console.error('URL 파싱 오류:', error); + } + }, + [isActive, startMonitoring, stopMonitoring], + ); + + // 타이머 중지 함수를 호출하는 공통 함수 + const executeTimerStop = useCallback(() => { + // 이미 정지 중이면 중복 실행 방지 + if (isStoppingTimer.current) { + console.log('이미 타이머 정지 처리 중입니다.'); + return false; + } + + // 타이머가 비활성 상태면 실행하지 않음 + if (!currentIsTimerActive.current) { + console.log('타이머가 이미 정지 상태입니다.'); + return false; + } + + try { + // 정지 중 플래그 설정 + isStoppingTimer.current = true; + + // 모니터링 즉시 중지 (중복 이벤트 방지) + stopMonitoring(); + + // 타이머 정지 함수 실행 + console.log('타이머 중지 함수 실행'); + currentOnStopTimer.current(); + console.log('타이머 중지 함수 실행 완료'); + return true; + } catch (error) { + console.error('타이머 중지 함수 실행 중 오류:', error); + // 에러 발생 시에도 플래그는 초기화하지 않음 (타이머 상태 변경 시 초기화됨) + return false; + } + }, [stopMonitoring]); + + // 허용서비스 그룹 목록 쿼리 + const { data: allowedServiceList } = useGetPopoverAllowedServiceList(); + // 허용서비스 추가 mutation + const { mutate: postAddAllowedService } = usePostAddAllowedService(); + const queryClient = useQueryClient(); + + // 시스템 알림 띄우기 함수 + const showSystemNotification = (title: string, message: string) => { + if ('Notification' in window) { + new window.Notification(title, { body: message }); + } + }; + + // 허용되지 않은 URL 발견 시 처리와 타이머 중지 처리 + useEffect(() => { + if (!window.electron?.browserMonitor || listenersRegistered.current) return; + + // 명시적인 타입 단언 사용 + const browserMonitor = window.electron?.browserMonitor; + + // 1. 타이머 중지 전용 이벤트 리스너 + console.log('타이머 중지 전용 이벤트 리스너 등록'); + const unsubscribeTimerStop = browserMonitor.onTimerStop((data: { url: string; timestamp: number }) => { + console.log('타이머 중지 이벤트 수신:', data); + + // URL 상태 업데이트 (UI 표시용) + setLastUnallowedUrl(data.url); + + // 타이머 중지 함수 실행 + executeTimerStop(); + }); + + // 2. 일반 허용되지 않은 URL 감지 이벤트 리스너 + console.log('허용되지 않은 URL 이벤트 리스너 등록'); + const unsubscribe = browserMonitor.onUnallowedUrl((url: string, action?: string) => { + console.log('허용되지 않은 URL 감지:', url, '액션:', action); + setLastUnallowedUrl(url); + + // 타이머 중지 함수 실행 + executeTimerStop(); + }); + + // 3. 알림 액션 이벤트 처리 + console.log('알림 액션 이벤트 리스너 등록'); + const unsubscribeNotification = browserMonitor.onNotificationAction((action, url) => { + console.log('알림 액션 수신:', action, url); + if (action === 'register') { + const selectedGroups = allowedServiceList?.data.filter((group) => group.selected) ?? []; + if (selectedGroups.length > 0) { + postAddAllowedService( + { allowedGroupId: selectedGroups[0].id, siteUrl: url }, + { + onSuccess: () => { + const queryKey = timerKeys.popover(); + queryClient.invalidateQueries({ queryKey }); + props.onStartTimer(); + + showSystemNotification('허용서비스에 추가에 성공했어요.', `허용서비스 세트에 ${url}이 추가되었어요.`); + }, + onError: () => { + showSystemNotification('허용서비스 추가에 실패했어요.', '다시 시도해주세요.'); + }, + }, + ); + } else { + showSystemNotification('허용서비스 추가에 실패했어요.', '타이머에서 허용 서비스 세트를 먼저 선택해주세요.'); + } + } + }); + + // 리스너 등록 완료 표시 + listenersRegistered.current = true; + + return () => { + console.log('URL 이벤트 리스너 해제'); + if (unsubscribe && typeof unsubscribe === 'function') { + unsubscribe(); + } + if (unsubscribeNotification && typeof unsubscribeNotification === 'function') { + unsubscribeNotification(); + } + if (unsubscribeTimerStop && typeof unsubscribeTimerStop === 'function') { + unsubscribeTimerStop(); + } + listenersRegistered.current = false; + }; + // 의존성 배열에 executeTimerStop 추가 + }, [executeTimerStop]); + + // 타이머 상태에 따라 자동 모니터링 시작/중지 + useEffect(() => { + console.log('타이머 상태 변경:', isTimerActive, '모니터링 상태:', isActive); + + if (isTimerActive && !isActive && !isStoppingTimer.current) { + console.log('타이머 시작으로 인한 모니터링 시작'); + startMonitoring(); + } else if (!isTimerActive && isActive) { + console.log('타이머 중지로 인한 모니터링 중지'); + stopMonitoring(); + } + }, [isTimerActive, isActive, startMonitoring, stopMonitoring]); + + return { + isActive, + lastUnallowedUrl, + startMonitoring, + stopMonitoring, + registerAllowedService, + }; +} diff --git a/src/pages/TimerPage/hooks/useTimerActions.ts b/src/app/pages/TimerPage/hooks/useTimerActions.ts similarity index 100% rename from src/pages/TimerPage/hooks/useTimerActions.ts rename to src/app/pages/TimerPage/hooks/useTimerActions.ts diff --git a/src/pages/TimerPage/hooks/useTimerCount.ts b/src/app/pages/TimerPage/hooks/useTimerCount.ts similarity index 100% rename from src/pages/TimerPage/hooks/useTimerCount.ts rename to src/app/pages/TimerPage/hooks/useTimerCount.ts diff --git a/src/pages/TimerPage/hooks/useTimerState.ts b/src/app/pages/TimerPage/hooks/useTimerState.ts similarity index 100% rename from src/pages/TimerPage/hooks/useTimerState.ts rename to src/app/pages/TimerPage/hooks/useTimerState.ts diff --git a/src/pages/TimerPage/hooks/useUIState.ts b/src/app/pages/TimerPage/hooks/useUIState.ts similarity index 100% rename from src/pages/TimerPage/hooks/useUIState.ts rename to src/app/pages/TimerPage/hooks/useUIState.ts diff --git a/src/pages/TimerPage/hooks/useUrlHandler.ts b/src/app/pages/TimerPage/hooks/useUrlHandler.ts similarity index 100% rename from src/pages/TimerPage/hooks/useUrlHandler.ts rename to src/app/pages/TimerPage/hooks/useUrlHandler.ts diff --git a/src/pages/TimerPage/utils/timeFormat.ts b/src/app/pages/TimerPage/utils/timeFormat.ts similarity index 100% rename from src/pages/TimerPage/utils/timeFormat.ts rename to src/app/pages/TimerPage/utils/timeFormat.ts diff --git a/src/router/ProtectedRoute.tsx b/src/app/router/ProtectedRoute.tsx similarity index 100% rename from src/router/ProtectedRoute.tsx rename to src/app/router/ProtectedRoute.tsx diff --git a/src/router/Router.tsx b/src/app/router/Router.tsx similarity index 90% rename from src/router/Router.tsx rename to src/app/router/Router.tsx index 978bae9f..66aee15e 100644 --- a/src/router/Router.tsx +++ b/src/app/router/Router.tsx @@ -1,7 +1,7 @@ import type { Router } from '@remix-run/router'; import { Suspense, lazy } from 'react'; -import { Outlet, createBrowserRouter } from 'react-router-dom'; +import { Outlet, createBrowserRouter, createHashRouter } from 'react-router-dom'; import ErrorBoundary from '@/shared/components/ErrorBoundary/ErrorBoundary'; import HeartBeatBoundary from '@/shared/components/HeartBeatBoundary/HeartBeatBoundary'; @@ -20,7 +20,7 @@ const RedirectPage = lazy(() => import('@/pages/RedirectPage/RedirectPage')); const OnboardingPage = lazy(() => import('@/pages/OnboardingPage/OnboardingPage')); const TimerPage = lazy(() => import('@/pages/TimerPage/TimerPage')); -const router: Router = createBrowserRouter([ +const routerInfo = [ { //public 라우트들 path: '/', @@ -40,11 +40,7 @@ const router: Router = createBrowserRouter([ }, { path: ROUTES_CONFIG.redirect.path, - element: ( - }> - - - ), + element: , }, ], }, @@ -104,6 +100,8 @@ const router: Router = createBrowserRouter([ ), }, -]); +]; + +const router: Router = window.electron ? createHashRouter(routerInfo) : createBrowserRouter(routerInfo); export default router; diff --git a/src/router/routesConfig.ts b/src/app/router/routesConfig.ts similarity index 100% rename from src/router/routesConfig.ts rename to src/app/router/routesConfig.ts diff --git a/src/shared/apisV2/allowedService/allowedService.api.ts b/src/app/shared/apisV2/allowedService/allowedService.api.ts similarity index 100% rename from src/shared/apisV2/allowedService/allowedService.api.ts rename to src/app/shared/apisV2/allowedService/allowedService.api.ts diff --git a/src/shared/apisV2/allowedService/allowedService.keys.ts b/src/app/shared/apisV2/allowedService/allowedService.keys.ts similarity index 100% rename from src/shared/apisV2/allowedService/allowedService.keys.ts rename to src/app/shared/apisV2/allowedService/allowedService.keys.ts diff --git a/src/shared/apisV2/allowedService/allowedService.mutations.ts b/src/app/shared/apisV2/allowedService/allowedService.mutations.ts similarity index 100% rename from src/shared/apisV2/allowedService/allowedService.mutations.ts rename to src/app/shared/apisV2/allowedService/allowedService.mutations.ts diff --git a/src/shared/apisV2/allowedService/allowedService.queries.ts b/src/app/shared/apisV2/allowedService/allowedService.queries.ts similarity index 100% rename from src/shared/apisV2/allowedService/allowedService.queries.ts rename to src/app/shared/apisV2/allowedService/allowedService.queries.ts diff --git a/src/shared/apisV2/auth/auth.api.ts b/src/app/shared/apisV2/auth/auth.api.ts similarity index 55% rename from src/shared/apisV2/auth/auth.api.ts rename to src/app/shared/apisV2/auth/auth.api.ts index 20a6c2f0..e50d9545 100644 --- a/src/shared/apisV2/auth/auth.api.ts +++ b/src/app/shared/apisV2/auth/auth.api.ts @@ -1,24 +1,30 @@ import axios from 'axios'; -import { getAccessToken } from '@/shared/utils/auth'; +import { getAccessToken, getRefreshToken } from '@/shared/utils/auth'; import { reissueRes } from '@/shared/types/api/auth'; import { authClient } from '@/shared/apisV2/client'; const AUTH_ENDPOINT = { - POST_REISSUE_TOKEN: 'api/v2/users/reissue', + POST_REISSUE_TOKEN: 'api/v2/users/reissue/tmp', // NOTE: 임시 토큰 해결방식 POST_LOGOUT: 'api/v2/users/logout', }; export const postReissueToken = async (): Promise => { const accessToken = getAccessToken(); - const { data } = await axios.post(AUTH_ENDPOINT.POST_REISSUE_TOKEN, { - headers: { - Authorization: `Bearer ${accessToken}`, + const { data } = await axios.post( + AUTH_ENDPOINT.POST_REISSUE_TOKEN, + { + refreshToken: getRefreshToken(), }, - }); + { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }, + ); return data; }; diff --git a/src/shared/apisV2/auth/auth.queries.ts b/src/app/shared/apisV2/auth/auth.queries.ts similarity index 100% rename from src/shared/apisV2/auth/auth.queries.ts rename to src/app/shared/apisV2/auth/auth.queries.ts diff --git a/src/shared/apisV2/client.ts b/src/app/shared/apisV2/client.ts similarity index 93% rename from src/shared/apisV2/client.ts rename to src/app/shared/apisV2/client.ts index 17907303..3dd2d432 100644 --- a/src/shared/apisV2/client.ts +++ b/src/app/shared/apisV2/client.ts @@ -1,6 +1,6 @@ import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'; -import { getAccessToken, reloginWithoutLogout, setAccessToken } from '@/shared/utils/auth'; +import { getAccessToken, reloginWithoutLogout, setAccessToken, setRefreshToken } from '@/shared/utils/auth'; import { postReissueToken } from '@/shared/apisV2/auth/auth.api'; @@ -42,7 +42,10 @@ const addAuthInterceptor = (axiosClient: AxiosInstance) => { try { // NOTE: 추후에 로컬스토리지에 저장된 refreshToken을 사용하게끔 고치는 것이 필요할수있음 const { data } = await postReissueToken(); + setAccessToken(data.accessToken); + setRefreshToken(data.refreshToken); + return axiosClient(prevRequest); } catch (reissueError) { reloginWithoutLogout(); diff --git a/src/shared/apisV2/common/common.api.ts b/src/app/shared/apisV2/common/common.api.ts similarity index 100% rename from src/shared/apisV2/common/common.api.ts rename to src/app/shared/apisV2/common/common.api.ts diff --git a/src/shared/apisV2/common/common.keys.ts b/src/app/shared/apisV2/common/common.keys.ts similarity index 100% rename from src/shared/apisV2/common/common.keys.ts rename to src/app/shared/apisV2/common/common.keys.ts diff --git a/src/shared/apisV2/common/common.mutations.ts b/src/app/shared/apisV2/common/common.mutations.ts similarity index 100% rename from src/shared/apisV2/common/common.mutations.ts rename to src/app/shared/apisV2/common/common.mutations.ts diff --git a/src/shared/apisV2/common/common.queries.ts b/src/app/shared/apisV2/common/common.queries.ts similarity index 100% rename from src/shared/apisV2/common/common.queries.ts rename to src/app/shared/apisV2/common/common.queries.ts diff --git a/src/shared/apisV2/friends/friends.api.ts b/src/app/shared/apisV2/friends/friends.api.ts similarity index 100% rename from src/shared/apisV2/friends/friends.api.ts rename to src/app/shared/apisV2/friends/friends.api.ts diff --git a/src/shared/apisV2/friends/friends.keys.ts b/src/app/shared/apisV2/friends/friends.keys.ts similarity index 100% rename from src/shared/apisV2/friends/friends.keys.ts rename to src/app/shared/apisV2/friends/friends.keys.ts diff --git a/src/shared/apisV2/friends/friends.mutations.ts b/src/app/shared/apisV2/friends/friends.mutations.ts similarity index 100% rename from src/shared/apisV2/friends/friends.mutations.ts rename to src/app/shared/apisV2/friends/friends.mutations.ts diff --git a/src/shared/apisV2/friends/friends.queries.ts b/src/app/shared/apisV2/friends/friends.queries.ts similarity index 100% rename from src/shared/apisV2/friends/friends.queries.ts rename to src/app/shared/apisV2/friends/friends.queries.ts diff --git a/src/shared/apisV2/home/home.api.ts b/src/app/shared/apisV2/home/home.api.ts similarity index 100% rename from src/shared/apisV2/home/home.api.ts rename to src/app/shared/apisV2/home/home.api.ts diff --git a/src/shared/apisV2/home/home.keys.ts b/src/app/shared/apisV2/home/home.keys.ts similarity index 100% rename from src/shared/apisV2/home/home.keys.ts rename to src/app/shared/apisV2/home/home.keys.ts diff --git a/src/shared/apisV2/home/home.mutations.ts b/src/app/shared/apisV2/home/home.mutations.ts similarity index 100% rename from src/shared/apisV2/home/home.mutations.ts rename to src/app/shared/apisV2/home/home.mutations.ts diff --git a/src/shared/apisV2/home/home.queries.ts b/src/app/shared/apisV2/home/home.queries.ts similarity index 100% rename from src/shared/apisV2/home/home.queries.ts rename to src/app/shared/apisV2/home/home.queries.ts diff --git a/src/shared/apisV2/onboarding/onboarding.api.ts b/src/app/shared/apisV2/onboarding/onboarding.api.ts similarity index 100% rename from src/shared/apisV2/onboarding/onboarding.api.ts rename to src/app/shared/apisV2/onboarding/onboarding.api.ts diff --git a/src/shared/apisV2/onboarding/onboarding.keys.ts b/src/app/shared/apisV2/onboarding/onboarding.keys.ts similarity index 100% rename from src/shared/apisV2/onboarding/onboarding.keys.ts rename to src/app/shared/apisV2/onboarding/onboarding.keys.ts diff --git a/src/shared/apisV2/onboarding/onboarding.mutations.ts b/src/app/shared/apisV2/onboarding/onboarding.mutations.ts similarity index 100% rename from src/shared/apisV2/onboarding/onboarding.mutations.ts rename to src/app/shared/apisV2/onboarding/onboarding.mutations.ts diff --git a/src/shared/apisV2/onboarding/onboarding.queries.ts b/src/app/shared/apisV2/onboarding/onboarding.queries.ts similarity index 100% rename from src/shared/apisV2/onboarding/onboarding.queries.ts rename to src/app/shared/apisV2/onboarding/onboarding.queries.ts diff --git a/src/shared/apisV2/queryClient.ts b/src/app/shared/apisV2/queryClient.ts similarity index 100% rename from src/shared/apisV2/queryClient.ts rename to src/app/shared/apisV2/queryClient.ts diff --git a/src/shared/apisV2/setting/setting.api.ts b/src/app/shared/apisV2/setting/setting.api.ts similarity index 100% rename from src/shared/apisV2/setting/setting.api.ts rename to src/app/shared/apisV2/setting/setting.api.ts diff --git a/src/shared/apisV2/setting/setting.keys.ts b/src/app/shared/apisV2/setting/setting.keys.ts similarity index 100% rename from src/shared/apisV2/setting/setting.keys.ts rename to src/app/shared/apisV2/setting/setting.keys.ts diff --git a/src/shared/apisV2/setting/setting.mutations.ts b/src/app/shared/apisV2/setting/setting.mutations.ts similarity index 100% rename from src/shared/apisV2/setting/setting.mutations.ts rename to src/app/shared/apisV2/setting/setting.mutations.ts diff --git a/src/shared/apisV2/setting/setting.queries.ts b/src/app/shared/apisV2/setting/setting.queries.ts similarity index 100% rename from src/shared/apisV2/setting/setting.queries.ts rename to src/app/shared/apisV2/setting/setting.queries.ts diff --git a/src/shared/apisV2/timer/timer.api.ts b/src/app/shared/apisV2/timer/timer.api.ts similarity index 100% rename from src/shared/apisV2/timer/timer.api.ts rename to src/app/shared/apisV2/timer/timer.api.ts diff --git a/src/shared/apisV2/timer/timer.keys.ts b/src/app/shared/apisV2/timer/timer.keys.ts similarity index 100% rename from src/shared/apisV2/timer/timer.keys.ts rename to src/app/shared/apisV2/timer/timer.keys.ts diff --git a/src/shared/apisV2/timer/timer.mutations.ts b/src/app/shared/apisV2/timer/timer.mutations.ts similarity index 100% rename from src/shared/apisV2/timer/timer.mutations.ts rename to src/app/shared/apisV2/timer/timer.mutations.ts diff --git a/src/shared/apisV2/timer/timer.queries.ts b/src/app/shared/apisV2/timer/timer.queries.ts similarity index 99% rename from src/shared/apisV2/timer/timer.queries.ts rename to src/app/shared/apisV2/timer/timer.queries.ts index 5ff1fe2a..4a812d3a 100644 --- a/src/shared/apisV2/timer/timer.queries.ts +++ b/src/app/shared/apisV2/timer/timer.queries.ts @@ -54,6 +54,7 @@ export const useGetSelectedTimerTask = ( return useQuery({ queryKey: timerKeys.selectedTimerTask({ targetDate }), queryFn: () => getSelectedTimerTask({ targetDate }), + throwOnError: false, staleTime: 5000, // 5초 동안 캐시 데이터 사용 ...options, }); diff --git a/src/shared/assets/images/example.jpg b/src/app/shared/assets/images/example.jpg similarity index 100% rename from src/shared/assets/images/example.jpg rename to src/app/shared/assets/images/example.jpg diff --git a/src/shared/assets/images/img_timer_bg.png b/src/app/shared/assets/images/img_timer_bg.png similarity index 100% rename from src/shared/assets/images/img_timer_bg.png rename to src/app/shared/assets/images/img_timer_bg.png diff --git a/src/shared/assets/images/login_background.png b/src/app/shared/assets/images/login_background.png similarity index 100% rename from src/shared/assets/images/login_background.png rename to src/app/shared/assets/images/login_background.png diff --git a/src/shared/assets/images/profile_image1.png b/src/app/shared/assets/images/profile_image1.png similarity index 100% rename from src/shared/assets/images/profile_image1.png rename to src/app/shared/assets/images/profile_image1.png diff --git a/src/shared/assets/images/profile_image2.png b/src/app/shared/assets/images/profile_image2.png similarity index 100% rename from src/shared/assets/images/profile_image2.png rename to src/app/shared/assets/images/profile_image2.png diff --git a/src/shared/assets/images/profile_image3.png b/src/app/shared/assets/images/profile_image3.png similarity index 100% rename from src/shared/assets/images/profile_image3.png rename to src/app/shared/assets/images/profile_image3.png diff --git a/src/shared/assets/images/profile_image4.png b/src/app/shared/assets/images/profile_image4.png similarity index 100% rename from src/shared/assets/images/profile_image4.png rename to src/app/shared/assets/images/profile_image4.png diff --git a/src/shared/assets/lotties/loading.json b/src/app/shared/assets/lotties/loading.json similarity index 100% rename from src/shared/assets/lotties/loading.json rename to src/app/shared/assets/lotties/loading.json diff --git a/src/shared/assets/lotties/morib_logo_motion.json b/src/app/shared/assets/lotties/morib_logo_motion.json similarity index 100% rename from src/shared/assets/lotties/morib_logo_motion.json rename to src/app/shared/assets/lotties/morib_logo_motion.json diff --git a/src/shared/assets/svgs/404.svg b/src/app/shared/assets/svgs/404.svg similarity index 100% rename from src/shared/assets/svgs/404.svg rename to src/app/shared/assets/svgs/404.svg diff --git a/src/shared/assets/svgs/add_btn.svg b/src/app/shared/assets/svgs/add_btn.svg similarity index 100% rename from src/shared/assets/svgs/add_btn.svg rename to src/app/shared/assets/svgs/add_btn.svg diff --git a/src/shared/assets/svgs/arrow_circle_up_right.svg b/src/app/shared/assets/svgs/arrow_circle_up_right.svg similarity index 100% rename from src/shared/assets/svgs/arrow_circle_up_right.svg rename to src/app/shared/assets/svgs/arrow_circle_up_right.svg diff --git a/src/shared/assets/svgs/arrow_right.svg b/src/app/shared/assets/svgs/arrow_right.svg similarity index 100% rename from src/shared/assets/svgs/arrow_right.svg rename to src/app/shared/assets/svgs/arrow_right.svg diff --git a/src/shared/assets/svgs/bell.svg b/src/app/shared/assets/svgs/bell.svg similarity index 100% rename from src/shared/assets/svgs/bell.svg rename to src/app/shared/assets/svgs/bell.svg diff --git a/src/shared/assets/svgs/btn_add.svg b/src/app/shared/assets/svgs/btn_add.svg similarity index 100% rename from src/shared/assets/svgs/btn_add.svg rename to src/app/shared/assets/svgs/btn_add.svg diff --git a/src/shared/assets/svgs/btn_arrow.svg b/src/app/shared/assets/svgs/btn_arrow.svg similarity index 100% rename from src/shared/assets/svgs/btn_arrow.svg rename to src/app/shared/assets/svgs/btn_arrow.svg diff --git a/src/shared/assets/svgs/btn_arrow_bgNone.svg b/src/app/shared/assets/svgs/btn_arrow_bgNone.svg similarity index 100% rename from src/shared/assets/svgs/btn_arrow_bgNone.svg rename to src/app/shared/assets/svgs/btn_arrow_bgNone.svg diff --git a/src/shared/assets/svgs/btn_cal.svg b/src/app/shared/assets/svgs/btn_cal.svg similarity index 100% rename from src/shared/assets/svgs/btn_cal.svg rename to src/app/shared/assets/svgs/btn_cal.svg diff --git a/src/shared/assets/svgs/btn_cal_black.svg b/src/app/shared/assets/svgs/btn_cal_black.svg similarity index 100% rename from src/shared/assets/svgs/btn_cal_black.svg rename to src/app/shared/assets/svgs/btn_cal_black.svg diff --git a/src/shared/assets/svgs/btn_hamburger.svg b/src/app/shared/assets/svgs/btn_hamburger.svg similarity index 100% rename from src/shared/assets/svgs/btn_hamburger.svg rename to src/app/shared/assets/svgs/btn_hamburger.svg diff --git a/src/shared/assets/svgs/btn_home.svg b/src/app/shared/assets/svgs/btn_home.svg similarity index 100% rename from src/shared/assets/svgs/btn_home.svg rename to src/app/shared/assets/svgs/btn_home.svg diff --git a/src/shared/assets/svgs/btn_inputClear.svg b/src/app/shared/assets/svgs/btn_inputClear.svg similarity index 100% rename from src/shared/assets/svgs/btn_inputClear.svg rename to src/app/shared/assets/svgs/btn_inputClear.svg diff --git a/src/shared/assets/svgs/btn_list.svg b/src/app/shared/assets/svgs/btn_list.svg similarity index 100% rename from src/shared/assets/svgs/btn_list.svg rename to src/app/shared/assets/svgs/btn_list.svg diff --git a/src/shared/assets/svgs/btn_moribset_active.svg b/src/app/shared/assets/svgs/btn_moribset_active.svg similarity index 100% rename from src/shared/assets/svgs/btn_moribset_active.svg rename to src/app/shared/assets/svgs/btn_moribset_active.svg diff --git a/src/shared/assets/svgs/btn_moribset_default.svg b/src/app/shared/assets/svgs/btn_moribset_default.svg similarity index 100% rename from src/shared/assets/svgs/btn_moribset_default.svg rename to src/app/shared/assets/svgs/btn_moribset_default.svg diff --git a/src/shared/assets/svgs/btn_today.svg b/src/app/shared/assets/svgs/btn_today.svg similarity index 100% rename from src/shared/assets/svgs/btn_today.svg rename to src/app/shared/assets/svgs/btn_today.svg diff --git a/src/shared/assets/svgs/button_inputSuccess.svg b/src/app/shared/assets/svgs/button_inputSuccess.svg similarity index 100% rename from src/shared/assets/svgs/button_inputSuccess.svg rename to src/app/shared/assets/svgs/button_inputSuccess.svg diff --git a/src/shared/assets/svgs/check_box_blank.svg b/src/app/shared/assets/svgs/check_box_blank.svg similarity index 100% rename from src/shared/assets/svgs/check_box_blank.svg rename to src/app/shared/assets/svgs/check_box_blank.svg diff --git a/src/shared/assets/svgs/check_box_fill.svg b/src/app/shared/assets/svgs/check_box_fill.svg similarity index 100% rename from src/shared/assets/svgs/check_box_fill.svg rename to src/app/shared/assets/svgs/check_box_fill.svg diff --git a/src/shared/assets/svgs/common/ic_logo.svg b/src/app/shared/assets/svgs/common/ic_logo.svg similarity index 100% rename from src/shared/assets/svgs/common/ic_logo.svg rename to src/app/shared/assets/svgs/common/ic_logo.svg diff --git a/src/shared/assets/svgs/common/ic_meatball_default.svg b/src/app/shared/assets/svgs/common/ic_meatball_default.svg similarity index 100% rename from src/shared/assets/svgs/common/ic_meatball_default.svg rename to src/app/shared/assets/svgs/common/ic_meatball_default.svg diff --git a/src/shared/assets/svgs/connection_icon.svg b/src/app/shared/assets/svgs/connection_icon.svg similarity index 100% rename from src/shared/assets/svgs/connection_icon.svg rename to src/app/shared/assets/svgs/connection_icon.svg diff --git a/src/shared/assets/svgs/default_profile.svg b/src/app/shared/assets/svgs/default_profile.svg similarity index 100% rename from src/shared/assets/svgs/default_profile.svg rename to src/app/shared/assets/svgs/default_profile.svg diff --git a/src/shared/assets/svgs/default_url_favicon.svg b/src/app/shared/assets/svgs/default_url_favicon.svg similarity index 100% rename from src/shared/assets/svgs/default_url_favicon.svg rename to src/app/shared/assets/svgs/default_url_favicon.svg diff --git a/src/shared/assets/svgs/defaultpause.svg b/src/app/shared/assets/svgs/defaultpause.svg similarity index 100% rename from src/shared/assets/svgs/defaultpause.svg rename to src/app/shared/assets/svgs/defaultpause.svg diff --git a/src/shared/assets/svgs/defaultplay.svg b/src/app/shared/assets/svgs/defaultplay.svg similarity index 100% rename from src/shared/assets/svgs/defaultplay.svg rename to src/app/shared/assets/svgs/defaultplay.svg diff --git a/src/shared/assets/svgs/description.svg b/src/app/shared/assets/svgs/description.svg similarity index 100% rename from src/shared/assets/svgs/description.svg rename to src/app/shared/assets/svgs/description.svg diff --git a/src/shared/assets/svgs/disabled_dropdown.svg b/src/app/shared/assets/svgs/disabled_dropdown.svg similarity index 100% rename from src/shared/assets/svgs/disabled_dropdown.svg rename to src/app/shared/assets/svgs/disabled_dropdown.svg diff --git a/src/shared/assets/svgs/dropIcon.svg b/src/app/shared/assets/svgs/dropIcon.svg similarity index 100% rename from src/shared/assets/svgs/dropIcon.svg rename to src/app/shared/assets/svgs/dropIcon.svg diff --git a/src/shared/assets/svgs/elipse.svg b/src/app/shared/assets/svgs/elipse.svg similarity index 100% rename from src/shared/assets/svgs/elipse.svg rename to src/app/shared/assets/svgs/elipse.svg diff --git a/src/shared/assets/svgs/error.svg b/src/app/shared/assets/svgs/error.svg similarity index 100% rename from src/shared/assets/svgs/error.svg rename to src/app/shared/assets/svgs/error.svg diff --git a/src/shared/assets/svgs/error_input.svg b/src/app/shared/assets/svgs/error_input.svg similarity index 100% rename from src/shared/assets/svgs/error_input.svg rename to src/app/shared/assets/svgs/error_input.svg diff --git a/src/shared/assets/svgs/friend_delBtn.svg b/src/app/shared/assets/svgs/friend_delBtn.svg similarity index 100% rename from src/shared/assets/svgs/friend_delBtn.svg rename to src/app/shared/assets/svgs/friend_delBtn.svg diff --git a/src/shared/assets/svgs/friend_setting.svg b/src/app/shared/assets/svgs/friend_setting.svg similarity index 100% rename from src/shared/assets/svgs/friend_setting.svg rename to src/app/shared/assets/svgs/friend_setting.svg diff --git a/src/shared/assets/svgs/google_login.svg b/src/app/shared/assets/svgs/google_login.svg similarity index 100% rename from src/shared/assets/svgs/google_login.svg rename to src/app/shared/assets/svgs/google_login.svg diff --git a/src/shared/assets/svgs/gradient_circle.svg b/src/app/shared/assets/svgs/gradient_circle.svg similarity index 100% rename from src/shared/assets/svgs/gradient_circle.svg rename to src/app/shared/assets/svgs/gradient_circle.svg diff --git a/src/shared/assets/svgs/header_delBtn.svg b/src/app/shared/assets/svgs/header_delBtn.svg similarity index 100% rename from src/shared/assets/svgs/header_delBtn.svg rename to src/app/shared/assets/svgs/header_delBtn.svg diff --git a/src/shared/assets/svgs/home/ic_box.svg b/src/app/shared/assets/svgs/home/ic_box.svg similarity index 100% rename from src/shared/assets/svgs/home/ic_box.svg rename to src/app/shared/assets/svgs/home/ic_box.svg diff --git a/src/shared/assets/svgs/home/ic_plus.svg b/src/app/shared/assets/svgs/home/ic_plus.svg similarity index 100% rename from src/shared/assets/svgs/home/ic_plus.svg rename to src/app/shared/assets/svgs/home/ic_plus.svg diff --git a/src/shared/assets/svgs/home_default_icon.svg b/src/app/shared/assets/svgs/home_default_icon.svg similarity index 100% rename from src/shared/assets/svgs/home_default_icon.svg rename to src/app/shared/assets/svgs/home_default_icon.svg diff --git a/src/shared/assets/svgs/hoverpause.svg b/src/app/shared/assets/svgs/hoverpause.svg similarity index 100% rename from src/shared/assets/svgs/hoverpause.svg rename to src/app/shared/assets/svgs/hoverpause.svg diff --git a/src/shared/assets/svgs/hoverplay.svg b/src/app/shared/assets/svgs/hoverplay.svg similarity index 100% rename from src/shared/assets/svgs/hoverplay.svg rename to src/app/shared/assets/svgs/hoverplay.svg diff --git a/src/shared/assets/svgs/ic_back_btn.svg b/src/app/shared/assets/svgs/ic_back_btn.svg similarity index 100% rename from src/shared/assets/svgs/ic_back_btn.svg rename to src/app/shared/assets/svgs/ic_back_btn.svg diff --git a/src/shared/assets/svgs/ic_delete_alert.svg b/src/app/shared/assets/svgs/ic_delete_alert.svg similarity index 100% rename from src/shared/assets/svgs/ic_delete_alert.svg rename to src/app/shared/assets/svgs/ic_delete_alert.svg diff --git a/src/shared/assets/svgs/ic_description.svg b/src/app/shared/assets/svgs/ic_description.svg similarity index 100% rename from src/shared/assets/svgs/ic_description.svg rename to src/app/shared/assets/svgs/ic_description.svg diff --git a/src/shared/assets/svgs/ic_folder.svg b/src/app/shared/assets/svgs/ic_folder.svg similarity index 100% rename from src/shared/assets/svgs/ic_folder.svg rename to src/app/shared/assets/svgs/ic_folder.svg diff --git a/src/shared/assets/svgs/ic_gear.svg b/src/app/shared/assets/svgs/ic_gear.svg similarity index 100% rename from src/shared/assets/svgs/ic_gear.svg rename to src/app/shared/assets/svgs/ic_gear.svg diff --git a/src/shared/assets/svgs/ic_line.svg b/src/app/shared/assets/svgs/ic_line.svg similarity index 100% rename from src/shared/assets/svgs/ic_line.svg rename to src/app/shared/assets/svgs/ic_line.svg diff --git a/src/shared/assets/svgs/ic_logo.svg b/src/app/shared/assets/svgs/ic_logo.svg similarity index 100% rename from src/shared/assets/svgs/ic_logo.svg rename to src/app/shared/assets/svgs/ic_logo.svg diff --git a/src/shared/assets/svgs/ic_minus.svg b/src/app/shared/assets/svgs/ic_minus.svg similarity index 100% rename from src/shared/assets/svgs/ic_minus.svg rename to src/app/shared/assets/svgs/ic_minus.svg diff --git a/src/shared/assets/svgs/ic_pencil.svg b/src/app/shared/assets/svgs/ic_pencil.svg similarity index 100% rename from src/shared/assets/svgs/ic_pencil.svg rename to src/app/shared/assets/svgs/ic_pencil.svg diff --git a/src/shared/assets/svgs/ic_service_design.svg b/src/app/shared/assets/svgs/ic_service_design.svg similarity index 100% rename from src/shared/assets/svgs/ic_service_design.svg rename to src/app/shared/assets/svgs/ic_service_design.svg diff --git a/src/shared/assets/svgs/ic_service_design_sm.svg b/src/app/shared/assets/svgs/ic_service_design_sm.svg similarity index 100% rename from src/shared/assets/svgs/ic_service_design_sm.svg rename to src/app/shared/assets/svgs/ic_service_design_sm.svg diff --git a/src/shared/assets/svgs/icon_clock.svg b/src/app/shared/assets/svgs/icon_clock.svg similarity index 100% rename from src/shared/assets/svgs/icon_clock.svg rename to src/app/shared/assets/svgs/icon_clock.svg diff --git a/src/shared/assets/svgs/large_plus.svg b/src/app/shared/assets/svgs/large_plus.svg similarity index 100% rename from src/shared/assets/svgs/large_plus.svg rename to src/app/shared/assets/svgs/large_plus.svg diff --git a/src/shared/assets/svgs/logo_icon.svg b/src/app/shared/assets/svgs/logo_icon.svg similarity index 100% rename from src/shared/assets/svgs/logo_icon.svg rename to src/app/shared/assets/svgs/logo_icon.svg diff --git a/src/shared/assets/svgs/mail.svg b/src/app/shared/assets/svgs/mail.svg similarity index 100% rename from src/shared/assets/svgs/mail.svg rename to src/app/shared/assets/svgs/mail.svg diff --git a/src/shared/assets/svgs/mingcute_time-fill.svg b/src/app/shared/assets/svgs/mingcute_time-fill.svg similarity index 100% rename from src/shared/assets/svgs/mingcute_time-fill.svg rename to src/app/shared/assets/svgs/mingcute_time-fill.svg diff --git a/src/shared/assets/svgs/mingcute_time-line.svg b/src/app/shared/assets/svgs/mingcute_time-line.svg similarity index 100% rename from src/shared/assets/svgs/mingcute_time-line.svg rename to src/app/shared/assets/svgs/mingcute_time-line.svg diff --git a/src/shared/assets/svgs/minus_btn.svg b/src/app/shared/assets/svgs/minus_btn.svg similarity index 100% rename from src/shared/assets/svgs/minus_btn.svg rename to src/app/shared/assets/svgs/minus_btn.svg diff --git a/src/shared/assets/svgs/more_friend.svg b/src/app/shared/assets/svgs/more_friend.svg similarity index 100% rename from src/shared/assets/svgs/more_friend.svg rename to src/app/shared/assets/svgs/more_friend.svg diff --git a/src/shared/assets/svgs/moribSet.svg b/src/app/shared/assets/svgs/moribSet.svg similarity index 100% rename from src/shared/assets/svgs/moribSet.svg rename to src/app/shared/assets/svgs/moribSet.svg diff --git a/src/shared/assets/svgs/onboarding/ic_business.svg b/src/app/shared/assets/svgs/onboarding/ic_business.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_business.svg rename to src/app/shared/assets/svgs/onboarding/ic_business.svg diff --git a/src/shared/assets/svgs/onboarding/ic_design.svg b/src/app/shared/assets/svgs/onboarding/ic_design.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_design.svg rename to src/app/shared/assets/svgs/onboarding/ic_design.svg diff --git a/src/shared/assets/svgs/onboarding/ic_development.svg b/src/app/shared/assets/svgs/onboarding/ic_development.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_development.svg rename to src/app/shared/assets/svgs/onboarding/ic_development.svg diff --git a/src/shared/assets/svgs/onboarding/ic_marketing.svg b/src/app/shared/assets/svgs/onboarding/ic_marketing.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_marketing.svg rename to src/app/shared/assets/svgs/onboarding/ic_marketing.svg diff --git a/src/shared/assets/svgs/onboarding/ic_planning.svg b/src/app/shared/assets/svgs/onboarding/ic_planning.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_planning.svg rename to src/app/shared/assets/svgs/onboarding/ic_planning.svg diff --git a/src/shared/assets/svgs/onboarding/ic_studying.svg b/src/app/shared/assets/svgs/onboarding/ic_studying.svg similarity index 100% rename from src/shared/assets/svgs/onboarding/ic_studying.svg rename to src/app/shared/assets/svgs/onboarding/ic_studying.svg diff --git a/src/shared/assets/svgs/onboarding_image.svg b/src/app/shared/assets/svgs/onboarding_image.svg similarity index 100% rename from src/shared/assets/svgs/onboarding_image.svg rename to src/app/shared/assets/svgs/onboarding_image.svg diff --git a/src/shared/assets/svgs/plus.svg b/src/app/shared/assets/svgs/plus.svg similarity index 100% rename from src/shared/assets/svgs/plus.svg rename to src/app/shared/assets/svgs/plus.svg diff --git a/src/shared/assets/svgs/popover_add_category.svg b/src/app/shared/assets/svgs/popover_add_category.svg similarity index 100% rename from src/shared/assets/svgs/popover_add_category.svg rename to src/app/shared/assets/svgs/popover_add_category.svg diff --git a/src/shared/assets/svgs/popover_add_todo.svg b/src/app/shared/assets/svgs/popover_add_todo.svg similarity index 100% rename from src/shared/assets/svgs/popover_add_todo.svg rename to src/app/shared/assets/svgs/popover_add_todo.svg diff --git a/src/shared/assets/svgs/react.svg b/src/app/shared/assets/svgs/react.svg similarity index 100% rename from src/shared/assets/svgs/react.svg rename to src/app/shared/assets/svgs/react.svg diff --git a/src/shared/assets/svgs/selected_number_icon.svg b/src/app/shared/assets/svgs/selected_number_icon.svg similarity index 100% rename from src/shared/assets/svgs/selected_number_icon.svg rename to src/app/shared/assets/svgs/selected_number_icon.svg diff --git a/src/shared/assets/svgs/setting.svg b/src/app/shared/assets/svgs/setting.svg similarity index 100% rename from src/shared/assets/svgs/setting.svg rename to src/app/shared/assets/svgs/setting.svg diff --git a/src/shared/assets/svgs/timer/ic_check_box_active.svg b/src/app/shared/assets/svgs/timer/ic_check_box_active.svg similarity index 100% rename from src/shared/assets/svgs/timer/ic_check_box_active.svg rename to src/app/shared/assets/svgs/timer/ic_check_box_active.svg diff --git a/src/shared/assets/svgs/timer/ic_check_box_inactive.svg b/src/app/shared/assets/svgs/timer/ic_check_box_inactive.svg similarity index 100% rename from src/shared/assets/svgs/timer/ic_check_box_inactive.svg rename to src/app/shared/assets/svgs/timer/ic_check_box_inactive.svg diff --git a/src/shared/assets/svgs/timer/ic_deactivated_clock.svg b/src/app/shared/assets/svgs/timer/ic_deactivated_clock.svg similarity index 100% rename from src/shared/assets/svgs/timer/ic_deactivated_clock.svg rename to src/app/shared/assets/svgs/timer/ic_deactivated_clock.svg diff --git a/src/shared/assets/svgs/timer/ic_online.svg b/src/app/shared/assets/svgs/timer/ic_online.svg similarity index 100% rename from src/shared/assets/svgs/timer/ic_online.svg rename to src/app/shared/assets/svgs/timer/ic_online.svg diff --git a/src/shared/assets/svgs/timer/ic_timer_inner_circle.svg b/src/app/shared/assets/svgs/timer/ic_timer_inner_circle.svg similarity index 100% rename from src/shared/assets/svgs/timer/ic_timer_inner_circle.svg rename to src/app/shared/assets/svgs/timer/ic_timer_inner_circle.svg diff --git a/src/shared/assets/svgs/todo_meatball_press.svg b/src/app/shared/assets/svgs/todo_meatball_press.svg similarity index 100% rename from src/shared/assets/svgs/todo_meatball_press.svg rename to src/app/shared/assets/svgs/todo_meatball_press.svg diff --git a/src/shared/assets/svgs/todo_toggle.svg b/src/app/shared/assets/svgs/todo_toggle.svg similarity index 100% rename from src/shared/assets/svgs/todo_toggle.svg rename to src/app/shared/assets/svgs/todo_toggle.svg diff --git a/src/shared/assets/svgs/tooltip_triangle.svg b/src/app/shared/assets/svgs/tooltip_triangle.svg similarity index 100% rename from src/shared/assets/svgs/tooltip_triangle.svg rename to src/app/shared/assets/svgs/tooltip_triangle.svg diff --git a/src/shared/assets/svgs/triangle.svg b/src/app/shared/assets/svgs/triangle.svg similarity index 100% rename from src/shared/assets/svgs/triangle.svg rename to src/app/shared/assets/svgs/triangle.svg diff --git a/src/shared/assets/svgs/upIcon.svg b/src/app/shared/assets/svgs/upIcon.svg similarity index 100% rename from src/shared/assets/svgs/upIcon.svg rename to src/app/shared/assets/svgs/upIcon.svg diff --git a/src/shared/assets/svgs/user_circle.svg b/src/app/shared/assets/svgs/user_circle.svg similarity index 100% rename from src/shared/assets/svgs/user_circle.svg rename to src/app/shared/assets/svgs/user_circle.svg diff --git a/src/shared/components/AutoFixedGrid/AutoFixedGrid.tsx b/src/app/shared/components/AutoFixedGrid/AutoFixedGrid.tsx similarity index 100% rename from src/shared/components/AutoFixedGrid/AutoFixedGrid.tsx rename to src/app/shared/components/AutoFixedGrid/AutoFixedGrid.tsx diff --git a/src/shared/components/BoxTodo/BoxTodo.tsx b/src/app/shared/components/BoxTodo/BoxTodo.tsx similarity index 100% rename from src/shared/components/BoxTodo/BoxTodo.tsx rename to src/app/shared/components/BoxTodo/BoxTodo.tsx diff --git a/src/shared/components/ButtonArrowSVG/ButtonArrowSVG.tsx b/src/app/shared/components/ButtonArrowSVG/ButtonArrowSVG.tsx similarity index 100% rename from src/shared/components/ButtonArrowSVG/ButtonArrowSVG.tsx rename to src/app/shared/components/ButtonArrowSVG/ButtonArrowSVG.tsx diff --git a/src/shared/components/ButtonDropdownOptions/ButtonDropdownOptions.tsx b/src/app/shared/components/ButtonDropdownOptions/ButtonDropdownOptions.tsx similarity index 100% rename from src/shared/components/ButtonDropdownOptions/ButtonDropdownOptions.tsx rename to src/app/shared/components/ButtonDropdownOptions/ButtonDropdownOptions.tsx diff --git a/src/shared/components/ButtonHomeLarge/ButtonHomeLarge.tsx b/src/app/shared/components/ButtonHomeLarge/ButtonHomeLarge.tsx similarity index 100% rename from src/shared/components/ButtonHomeLarge/ButtonHomeLarge.tsx rename to src/app/shared/components/ButtonHomeLarge/ButtonHomeLarge.tsx diff --git a/src/shared/components/ButtonRadius5/ButtonRadius5.tsx b/src/app/shared/components/ButtonRadius5/ButtonRadius5.tsx similarity index 100% rename from src/shared/components/ButtonRadius5/ButtonRadius5.tsx rename to src/app/shared/components/ButtonRadius5/ButtonRadius5.tsx diff --git a/src/shared/components/ButtonRadius8/ButtonRadius8.tsx b/src/app/shared/components/ButtonRadius8/ButtonRadius8.tsx similarity index 100% rename from src/shared/components/ButtonRadius8/ButtonRadius8.tsx rename to src/app/shared/components/ButtonRadius8/ButtonRadius8.tsx diff --git a/src/shared/components/ButtonStatusToggle/ButtonStatusToggle.tsx b/src/app/shared/components/ButtonStatusToggle/ButtonStatusToggle.tsx similarity index 100% rename from src/shared/components/ButtonStatusToggle/ButtonStatusToggle.tsx rename to src/app/shared/components/ButtonStatusToggle/ButtonStatusToggle.tsx diff --git a/src/shared/components/ButtonTodayToggle/ButtonTodoToggle.tsx b/src/app/shared/components/ButtonTodayToggle/ButtonTodoToggle.tsx similarity index 100% rename from src/shared/components/ButtonTodayToggle/ButtonTodoToggle.tsx rename to src/app/shared/components/ButtonTodayToggle/ButtonTodoToggle.tsx diff --git a/src/shared/components/Calendar/ButtonCalendarAddRoutine/ButtonCalendarAddRoutine.tsx b/src/app/shared/components/Calendar/ButtonCalendarAddRoutine/ButtonCalendarAddRoutine.tsx similarity index 100% rename from src/shared/components/Calendar/ButtonCalendarAddRoutine/ButtonCalendarAddRoutine.tsx rename to src/app/shared/components/Calendar/ButtonCalendarAddRoutine/ButtonCalendarAddRoutine.tsx diff --git a/src/shared/components/Calendar/Calendar.tsx b/src/app/shared/components/Calendar/Calendar.tsx similarity index 100% rename from src/shared/components/Calendar/Calendar.tsx rename to src/app/shared/components/Calendar/Calendar.tsx diff --git a/src/shared/components/Calendar/HeaderCalendar/HeaderCalendar.tsx b/src/app/shared/components/Calendar/HeaderCalendar/HeaderCalendar.tsx similarity index 100% rename from src/shared/components/Calendar/HeaderCalendar/HeaderCalendar.tsx rename to src/app/shared/components/Calendar/HeaderCalendar/HeaderCalendar.tsx diff --git a/src/shared/components/Calendar/calendar.css b/src/app/shared/components/Calendar/calendar.css similarity index 100% rename from src/shared/components/Calendar/calendar.css rename to src/app/shared/components/Calendar/calendar.css diff --git a/src/shared/components/CircleColorIcon/CircleColorIcon.tsx b/src/app/shared/components/CircleColorIcon/CircleColorIcon.tsx similarity index 100% rename from src/shared/components/CircleColorIcon/CircleColorIcon.tsx rename to src/app/shared/components/CircleColorIcon/CircleColorIcon.tsx diff --git a/src/shared/components/ColorPallete/ColorPallete.tsx b/src/app/shared/components/ColorPallete/ColorPallete.tsx similarity index 100% rename from src/shared/components/ColorPallete/ColorPallete.tsx rename to src/app/shared/components/ColorPallete/ColorPallete.tsx diff --git a/src/shared/components/Dropdown/Dropdown.tsx b/src/app/shared/components/Dropdown/Dropdown.tsx similarity index 100% rename from src/shared/components/Dropdown/Dropdown.tsx rename to src/app/shared/components/Dropdown/Dropdown.tsx diff --git a/src/shared/components/ErrorBoundary/ErrorBoundary.tsx b/src/app/shared/components/ErrorBoundary/ErrorBoundary.tsx similarity index 100% rename from src/shared/components/ErrorBoundary/ErrorBoundary.tsx rename to src/app/shared/components/ErrorBoundary/ErrorBoundary.tsx diff --git a/src/shared/components/FallbackApiError/FallbackApiError.tsx b/src/app/shared/components/FallbackApiError/FallbackApiError.tsx similarity index 100% rename from src/shared/components/FallbackApiError/FallbackApiError.tsx rename to src/app/shared/components/FallbackApiError/FallbackApiError.tsx diff --git a/src/shared/components/FaviconImage/FaviconImage.tsx b/src/app/shared/components/FaviconImage/FaviconImage.tsx similarity index 100% rename from src/shared/components/FaviconImage/FaviconImage.tsx rename to src/app/shared/components/FaviconImage/FaviconImage.tsx diff --git a/src/shared/components/HeartBeatBoundary/HeartBeatBoundary.tsx b/src/app/shared/components/HeartBeatBoundary/HeartBeatBoundary.tsx similarity index 100% rename from src/shared/components/HeartBeatBoundary/HeartBeatBoundary.tsx rename to src/app/shared/components/HeartBeatBoundary/HeartBeatBoundary.tsx diff --git a/src/shared/components/LoadingOverlay/LoadingOverlay.tsx b/src/app/shared/components/LoadingOverlay/LoadingOverlay.tsx similarity index 100% rename from src/shared/components/LoadingOverlay/LoadingOverlay.tsx rename to src/app/shared/components/LoadingOverlay/LoadingOverlay.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendRequest/ButtonRequestAction/ButtonRequestAction.tsx b/src/app/shared/components/ModalContentsFriends/FriendRequest/ButtonRequestAction/ButtonRequestAction.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendRequest/ButtonRequestAction/ButtonRequestAction.tsx rename to src/app/shared/components/ModalContentsFriends/FriendRequest/ButtonRequestAction/ButtonRequestAction.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendRequest/FriendsListRequested/FriendsListRequested.tsx b/src/app/shared/components/ModalContentsFriends/FriendRequest/FriendsListRequested/FriendsListRequested.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendRequest/FriendsListRequested/FriendsListRequested.tsx rename to src/app/shared/components/ModalContentsFriends/FriendRequest/FriendsListRequested/FriendsListRequested.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendRequest/FriendsRequest.tsx b/src/app/shared/components/ModalContentsFriends/FriendRequest/FriendsRequest.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendRequest/FriendsRequest.tsx rename to src/app/shared/components/ModalContentsFriends/FriendRequest/FriendsRequest.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendUserProfile/FriendUserProfile.tsx b/src/app/shared/components/ModalContentsFriends/FriendUserProfile/FriendUserProfile.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendUserProfile/FriendUserProfile.tsx rename to src/app/shared/components/ModalContentsFriends/FriendUserProfile/FriendUserProfile.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendsList/FriendsInfo/FriendInfo.tsx b/src/app/shared/components/ModalContentsFriends/FriendsList/FriendsInfo/FriendInfo.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendsList/FriendsInfo/FriendInfo.tsx rename to src/app/shared/components/ModalContentsFriends/FriendsList/FriendsInfo/FriendInfo.tsx diff --git a/src/shared/components/ModalContentsFriends/FriendsList/FriendsList.tsx b/src/app/shared/components/ModalContentsFriends/FriendsList/FriendsList.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/FriendsList/FriendsList.tsx rename to src/app/shared/components/ModalContentsFriends/FriendsList/FriendsList.tsx diff --git a/src/shared/components/ModalContentsFriends/ModalContentsFriends.tsx b/src/app/shared/components/ModalContentsFriends/ModalContentsFriends.tsx similarity index 100% rename from src/shared/components/ModalContentsFriends/ModalContentsFriends.tsx rename to src/app/shared/components/ModalContentsFriends/ModalContentsFriends.tsx diff --git a/src/shared/components/ModalWrapper/ModalWrapper.tsx b/src/app/shared/components/ModalWrapper/ModalWrapper.tsx similarity index 100% rename from src/shared/components/ModalWrapper/ModalWrapper.tsx rename to src/app/shared/components/ModalWrapper/ModalWrapper.tsx diff --git a/src/shared/components/ModalWrapper/styles/dialog.css b/src/app/shared/components/ModalWrapper/styles/dialog.css similarity index 100% rename from src/shared/components/ModalWrapper/styles/dialog.css rename to src/app/shared/components/ModalWrapper/styles/dialog.css diff --git a/src/shared/components/NotificationPanel/NotificationPanel.tsx b/src/app/shared/components/NotificationPanel/NotificationPanel.tsx similarity index 100% rename from src/shared/components/NotificationPanel/NotificationPanel.tsx rename to src/app/shared/components/NotificationPanel/NotificationPanel.tsx diff --git a/src/shared/components/Portal/Portal.tsx b/src/app/shared/components/Portal/Portal.tsx similarity index 100% rename from src/shared/components/Portal/Portal.tsx rename to src/app/shared/components/Portal/Portal.tsx diff --git a/src/shared/components/Spacer/Spacer.tsx b/src/app/shared/components/Spacer/Spacer.tsx similarity index 100% rename from src/shared/components/Spacer/Spacer.tsx rename to src/app/shared/components/Spacer/Spacer.tsx diff --git a/src/shared/components/TextField/TextField.tsx b/src/app/shared/components/TextField/TextField.tsx similarity index 100% rename from src/shared/components/TextField/TextField.tsx rename to src/app/shared/components/TextField/TextField.tsx diff --git a/src/shared/constants/btnText.ts b/src/app/shared/constants/btnText.ts similarity index 100% rename from src/shared/constants/btnText.ts rename to src/app/shared/constants/btnText.ts diff --git a/src/shared/constants/colorPalette.ts b/src/app/shared/constants/colorPalette.ts similarity index 100% rename from src/shared/constants/colorPalette.ts rename to src/app/shared/constants/colorPalette.ts diff --git a/src/shared/constants/emailRegex.ts b/src/app/shared/constants/emailRegex.ts similarity index 100% rename from src/shared/constants/emailRegex.ts rename to src/app/shared/constants/emailRegex.ts diff --git a/src/shared/constants/error.ts b/src/app/shared/constants/error.ts similarity index 100% rename from src/shared/constants/error.ts rename to src/app/shared/constants/error.ts diff --git a/src/shared/constants/fields.ts b/src/app/shared/constants/fields.ts similarity index 100% rename from src/shared/constants/fields.ts rename to src/app/shared/constants/fields.ts diff --git a/src/shared/constants/timerPageText.ts b/src/app/shared/constants/timerPageText.ts similarity index 100% rename from src/shared/constants/timerPageText.ts rename to src/app/shared/constants/timerPageText.ts diff --git a/src/shared/constants/weekDays.ts b/src/app/shared/constants/weekDays.ts similarity index 100% rename from src/shared/constants/weekDays.ts rename to src/app/shared/constants/weekDays.ts diff --git a/src/shared/hocs/withAuthProtection.tsx b/src/app/shared/hocs/withAuthProtection.tsx similarity index 100% rename from src/shared/hocs/withAuthProtection.tsx rename to src/app/shared/hocs/withAuthProtection.tsx diff --git a/src/shared/hooks/useCarousel.ts b/src/app/shared/hooks/useCarousel.ts similarity index 100% rename from src/shared/hooks/useCarousel.ts rename to src/app/shared/hooks/useCarousel.ts diff --git a/src/shared/hooks/useClickOutside.ts b/src/app/shared/hooks/useClickOutside.ts similarity index 100% rename from src/shared/hooks/useClickOutside.ts rename to src/app/shared/hooks/useClickOutside.ts diff --git a/src/shared/layout/Layout.tsx b/src/app/shared/layout/Layout.tsx similarity index 100% rename from src/shared/layout/Layout.tsx rename to src/app/shared/layout/Layout.tsx diff --git a/src/shared/layout/Sidebar/ModalContentsSetting/AccountContent/AccountContent.tsx b/src/app/shared/layout/Sidebar/ModalContentsSetting/AccountContent/AccountContent.tsx similarity index 100% rename from src/shared/layout/Sidebar/ModalContentsSetting/AccountContent/AccountContent.tsx rename to src/app/shared/layout/Sidebar/ModalContentsSetting/AccountContent/AccountContent.tsx diff --git a/src/shared/layout/Sidebar/ModalContentsSetting/ModalContentsSetting.tsx b/src/app/shared/layout/Sidebar/ModalContentsSetting/ModalContentsSetting.tsx similarity index 100% rename from src/shared/layout/Sidebar/ModalContentsSetting/ModalContentsSetting.tsx rename to src/app/shared/layout/Sidebar/ModalContentsSetting/ModalContentsSetting.tsx diff --git a/src/shared/layout/Sidebar/ModalContentsSetting/Tabs/Tabs.tsx b/src/app/shared/layout/Sidebar/ModalContentsSetting/Tabs/Tabs.tsx similarity index 100% rename from src/shared/layout/Sidebar/ModalContentsSetting/Tabs/Tabs.tsx rename to src/app/shared/layout/Sidebar/ModalContentsSetting/Tabs/Tabs.tsx diff --git a/src/shared/layout/Sidebar/ModalContentsSetting/WorkspaceSettingContent/WorkspaceSettingContent.tsx b/src/app/shared/layout/Sidebar/ModalContentsSetting/WorkspaceSettingContent/WorkspaceSettingContent.tsx similarity index 100% rename from src/shared/layout/Sidebar/ModalContentsSetting/WorkspaceSettingContent/WorkspaceSettingContent.tsx rename to src/app/shared/layout/Sidebar/ModalContentsSetting/WorkspaceSettingContent/WorkspaceSettingContent.tsx diff --git a/src/shared/layout/Sidebar/Sidebar.tsx b/src/app/shared/layout/Sidebar/Sidebar.tsx similarity index 100% rename from src/shared/layout/Sidebar/Sidebar.tsx rename to src/app/shared/layout/Sidebar/Sidebar.tsx diff --git a/src/shared/mocks/categoryData.ts b/src/app/shared/mocks/categoryData.ts similarity index 100% rename from src/shared/mocks/categoryData.ts rename to src/app/shared/mocks/categoryData.ts diff --git a/src/shared/mocks/faviconData.ts b/src/app/shared/mocks/faviconData.ts similarity index 100% rename from src/shared/mocks/faviconData.ts rename to src/app/shared/mocks/faviconData.ts diff --git a/src/shared/mocks/homeData.ts b/src/app/shared/mocks/homeData.ts similarity index 100% rename from src/shared/mocks/homeData.ts rename to src/app/shared/mocks/homeData.ts diff --git a/src/shared/mocks/urlData.ts b/src/app/shared/mocks/urlData.ts similarity index 100% rename from src/shared/mocks/urlData.ts rename to src/app/shared/mocks/urlData.ts diff --git a/src/shared/mocks/userData.ts b/src/app/shared/mocks/userData.ts similarity index 100% rename from src/shared/mocks/userData.ts rename to src/app/shared/mocks/userData.ts diff --git a/src/shared/types/SSEEvent.ts b/src/app/shared/types/SSEEvent.ts similarity index 100% rename from src/shared/types/SSEEvent.ts rename to src/app/shared/types/SSEEvent.ts diff --git a/src/shared/types/allowedService.ts b/src/app/shared/types/allowedService.ts similarity index 100% rename from src/shared/types/allowedService.ts rename to src/app/shared/types/allowedService.ts diff --git a/src/shared/types/allowedSites.ts b/src/app/shared/types/allowedSites.ts similarity index 100% rename from src/shared/types/allowedSites.ts rename to src/app/shared/types/allowedSites.ts diff --git a/src/shared/types/api/allowedService.ts b/src/app/shared/types/api/allowedService.ts similarity index 100% rename from src/shared/types/api/allowedService.ts rename to src/app/shared/types/api/allowedService.ts diff --git a/src/shared/types/api/auth.ts b/src/app/shared/types/api/auth.ts similarity index 81% rename from src/shared/types/api/auth.ts rename to src/app/shared/types/api/auth.ts index 5c848197..b82e73b6 100644 --- a/src/shared/types/api/auth.ts +++ b/src/app/shared/types/api/auth.ts @@ -3,5 +3,6 @@ export interface reissueRes { message: string; data: { accessToken: string; + refreshToken: string; }; } diff --git a/src/shared/types/api/common.ts b/src/app/shared/types/api/common.ts similarity index 100% rename from src/shared/types/api/common.ts rename to src/app/shared/types/api/common.ts diff --git a/src/shared/types/api/error.ts b/src/app/shared/types/api/error.ts similarity index 100% rename from src/shared/types/api/error.ts rename to src/app/shared/types/api/error.ts diff --git a/src/shared/types/api/friends.ts b/src/app/shared/types/api/friends.ts similarity index 100% rename from src/shared/types/api/friends.ts rename to src/app/shared/types/api/friends.ts diff --git a/src/shared/types/api/home.ts b/src/app/shared/types/api/home.ts similarity index 100% rename from src/shared/types/api/home.ts rename to src/app/shared/types/api/home.ts diff --git a/src/shared/types/api/onboarding.ts b/src/app/shared/types/api/onboarding.ts similarity index 100% rename from src/shared/types/api/onboarding.ts rename to src/app/shared/types/api/onboarding.ts diff --git a/src/shared/types/api/setting.ts b/src/app/shared/types/api/setting.ts similarity index 100% rename from src/shared/types/api/setting.ts rename to src/app/shared/types/api/setting.ts diff --git a/src/shared/types/api/timer.ts b/src/app/shared/types/api/timer.ts similarity index 100% rename from src/shared/types/api/timer.ts rename to src/app/shared/types/api/timer.ts diff --git a/src/shared/types/common/index.tsx b/src/app/shared/types/common/index.tsx similarity index 100% rename from src/shared/types/common/index.tsx rename to src/app/shared/types/common/index.tsx diff --git a/src/shared/types/fileds.ts b/src/app/shared/types/fileds.ts similarity index 100% rename from src/shared/types/fileds.ts rename to src/app/shared/types/fileds.ts diff --git a/src/shared/types/friend.ts b/src/app/shared/types/friend.ts similarity index 100% rename from src/shared/types/friend.ts rename to src/app/shared/types/friend.ts diff --git a/src/shared/types/global.ts b/src/app/shared/types/global.ts similarity index 100% rename from src/shared/types/global.ts rename to src/app/shared/types/global.ts diff --git a/src/shared/types/home/index.tsx b/src/app/shared/types/home/index.tsx similarity index 100% rename from src/shared/types/home/index.tsx rename to src/app/shared/types/home/index.tsx diff --git a/src/shared/types/profile.ts b/src/app/shared/types/profile.ts similarity index 100% rename from src/shared/types/profile.ts rename to src/app/shared/types/profile.ts diff --git a/src/shared/types/tasks.ts b/src/app/shared/types/tasks.ts similarity index 100% rename from src/shared/types/tasks.ts rename to src/app/shared/types/tasks.ts diff --git a/src/shared/types/todoData.ts b/src/app/shared/types/todoData.ts similarity index 100% rename from src/shared/types/todoData.ts rename to src/app/shared/types/todoData.ts diff --git a/src/shared/types/userData.ts b/src/app/shared/types/userData.ts similarity index 100% rename from src/shared/types/userData.ts rename to src/app/shared/types/userData.ts diff --git a/src/shared/utils/auth.ts b/src/app/shared/utils/auth.ts similarity index 61% rename from src/shared/utils/auth.ts rename to src/app/shared/utils/auth.ts index 2e83abb6..84d44f77 100644 --- a/src/shared/utils/auth.ts +++ b/src/app/shared/utils/auth.ts @@ -11,7 +11,17 @@ export const setAccessToken = (accessToken: string) => { export const reloginWithoutLogout = () => { localStorage.removeItem('accessToken'); - location.href = ROUTES_CONFIG.login.path; + localStorage.removeItem('refreshToken'); + localStorage.removeItem('isOnboardingCompleted'); + + // electron 환경인지 확인 + if (window.electron?.auth) { + // electron IPC 통신을 통해 메인 프로세스에 메시지 전송 + window.electron.auth.relogin(); + } else { + // 일반 브라우저 환경인 경우 기존 방식대로 처리 + location.href = ROUTES_CONFIG.login.path; + } }; export const getRefreshToken = () => { diff --git a/src/shared/utils/calendar/index.ts b/src/app/shared/utils/calendar/index.ts similarity index 100% rename from src/shared/utils/calendar/index.ts rename to src/app/shared/utils/calendar/index.ts diff --git a/src/shared/utils/date/index.ts b/src/app/shared/utils/date/index.ts similarity index 100% rename from src/shared/utils/date/index.ts rename to src/app/shared/utils/date/index.ts diff --git a/src/shared/utils/error.ts b/src/app/shared/utils/error.ts similarity index 100% rename from src/shared/utils/error.ts rename to src/app/shared/utils/error.ts diff --git a/src/shared/utils/path.ts b/src/app/shared/utils/path.ts similarity index 100% rename from src/shared/utils/path.ts rename to src/app/shared/utils/path.ts diff --git a/src/shared/utils/tasks.ts b/src/app/shared/utils/tasks.ts similarity index 100% rename from src/shared/utils/tasks.ts rename to src/app/shared/utils/tasks.ts diff --git a/src/shared/utils/time/index.ts b/src/app/shared/utils/time/index.ts similarity index 100% rename from src/shared/utils/time/index.ts rename to src/app/shared/utils/time/index.ts diff --git a/src/shared/utils/timer/index.ts b/src/app/shared/utils/timer/index.ts similarity index 100% rename from src/shared/utils/timer/index.ts rename to src/app/shared/utils/timer/index.ts diff --git a/src/shared/utils/url.ts b/src/app/shared/utils/url.ts similarity index 100% rename from src/shared/utils/url.ts rename to src/app/shared/utils/url.ts diff --git a/src/shared/utils/url/index.ts b/src/app/shared/utils/url/index.ts similarity index 100% rename from src/shared/utils/url/index.ts rename to src/app/shared/utils/url/index.ts diff --git a/src/shared/utils/validation.ts b/src/app/shared/utils/validation.ts similarity index 100% rename from src/shared/utils/validation.ts rename to src/app/shared/utils/validation.ts diff --git a/src/app/vite-env.d.ts b/src/app/vite-env.d.ts new file mode 100644 index 00000000..ff71c620 --- /dev/null +++ b/src/app/vite-env.d.ts @@ -0,0 +1,32 @@ +/// + +interface ImportMetaEnv { + readonly VITE_BASE_URL: string; + readonly VITE_GOOGLE_URL: string; + readonly VITE_ELECTRON_URL: string; + readonly VITE_SENTRY_DSN: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} + +interface Window { + electron?: { + openExternal: (url: string) => void; + browserMonitor?: { + startMonitoring: (allowedServices: string[]) => void; + stopMonitoring: () => void; + onUnallowedUrl: (callback: (url: string, action?: string) => void) => (() => void) | undefined; + onTimerStop: (callback: (data: { url: string; timestamp: number }) => void) => (() => void) | undefined; + onNotificationAction: (callback: (action: 'timer' | 'register', url: string) => void) => (() => void) | undefined; + }; + auth?: { + relogin: () => void; + }; + + notification?: { + showSystemNotification: (title: string, body: string) => void; + }; + }; +} diff --git a/src/electron/browserMonitor.ts b/src/electron/browserMonitor.ts new file mode 100644 index 00000000..74486bcc --- /dev/null +++ b/src/electron/browserMonitor.ts @@ -0,0 +1,322 @@ +import { execFileSync } from 'child_process'; +import { BrowserWindow, Notification, app } from 'electron'; +import path from 'path'; + +// 현재 활성화된 브라우저의 URL 가져오기 (AppleScript 사용) +function getFocusedBrowserURL(): string { + try { + // 현재 활성 앱 확인 + const activeApp = execFileSync('osascript', [ + '-e', + 'tell application "System Events" to return name of first process whose frontmost is true', + ]) + .toString() + .trim(); + + // 브라우저별 URL 추출 스크립트 + let url = ''; + switch (activeApp) { + case 'Safari': + url = execFileSync('osascript', ['-e', 'tell application "Safari" to return URL of front document']) + .toString() + .trim(); + break; + + case 'Google Chrome': + case 'Microsoft Edge': + case 'Brave Browser': + case 'Vivaldi': + url = execFileSync('osascript', [ + '-e', + `tell application "${activeApp}" to return URL of active tab of front window`, + ]) + .toString() + .trim(); + break; + + case 'Firefox': + url = execFileSync('osascript', [ + '-e', + `tell application "System Events" + tell process "Firefox" + set urlBox to text field 1 of toolbar 1 of window 1 + return value of attribute "AXValue" of urlBox + end tell + end tell`, + ]) + .toString() + .trim(); + break; + + case 'Arc': + url = execFileSync('osascript', [ + '-e', + `tell application "System Events" + tell process "Arc" + set urlBox to first UI element of first group of first group of toolbar 1 of window 1 + return value of attribute "AXValue" of urlBox + end tell + end tell`, + ]) + .toString() + .trim(); + break; + } + + return url; + } catch (error) { + console.error('브라우저 URL 가져오기 오류:', error); + return ''; + } +} + +// URL이 허용된 서비스 목록에 있는지 확인 +function isAllowedURL(url: string, allowedServices: string[]): boolean { + try { + if (!url || !allowedServices.length) return false; + + // 브라우저 새 탭 페이지 확인 (차단에서 제외) + if (isBrowserNewTabPage(url)) { + console.log('브라우저 새 탭으로 감지되어 허용됨:', url); + return true; + } + + // 현재 URL 분석 + const currentUrl = new URL(url); + const currentHostname = currentUrl.hostname.toLowerCase(); + const currentPathname = currentUrl.pathname.toLowerCase(); + const currentFullPath = currentHostname + currentPathname; + + // 디버깅용 + console.log('Checking URL:', url); + console.log('Current hostname:', currentHostname); + console.log('Current pathname:', currentPathname); + console.log('Allowed services:', allowedServices); + + // 호스트명이나 전체 경로가 허용 서비스 목록과 일치하는지 확인 + return allowedServices.some((service) => { + // 서비스 도메인 정규화 + const serviceDomain = service.toLowerCase().trim(); + + // URL 형식인 경우 처리 + if (serviceDomain.startsWith('http://') || serviceDomain.startsWith('https://')) { + try { + // URL 객체로 파싱하여 호스트명과 경로 추출 + const serviceUrl = new URL(serviceDomain); + const serviceHostname = serviceUrl.hostname; + const servicePathname = serviceUrl.pathname; + + // 경로가 있는 경우 호스트명+경로까지 비교, 없는 경우 호스트명만 비교 + if (servicePathname && servicePathname !== '/') { + return currentFullPath.includes(serviceHostname + servicePathname); + } else { + return currentHostname === serviceHostname || currentHostname.endsWith('.' + serviceHostname); + } + } catch (e) { + console.warn('허용 서비스 URL 파싱 오류:', e); + } + } else if (serviceDomain.includes('/')) { + // 프로토콜이 없지만 경로가 포함된 경우 (예: youtube.com/watch) + return currentFullPath.includes(serviceDomain); + } + + // 단순 도메인만 있는 경우 (예: youtube.com) + return currentHostname === serviceDomain || currentHostname.endsWith('.' + serviceDomain); + }); + } catch (error) { + console.error('URL 검증 오류:', error); + return false; + } +} + +// 브라우저 새 탭 페이지인지 확인하는 함수 +function isBrowserNewTabPage(url: string): boolean { + try { + // 주요 브라우저의 새 탭 URL 패턴 + const newTabPatterns = [ + 'chrome://newtab', // Chrome + 'chrome://new-tab-page', // Chrome + 'about:newtab', // Firefox + 'edge://newtab', // Edge + 'brave://newtab', // Brave + 'vivaldi://newtab', // Vivaldi + 'about:start', // Some browsers + 'about:blank', // 공통 + 'about:home', // Firefox home + 'favorites://', // Safari favorites + 'safari-resource://', // Safari resources + 'arc://', // Arc browser + ]; + + // 패턴 매칭 + if (newTabPatterns.some((pattern) => url.startsWith(pattern))) { + return true; + } + + // Safari의 일부 새 탭 페이지 확인 (빈 URL이거나 'data:' 형식인 경우) + if (url === '' || url.startsWith('data:')) { + return true; + } + + // 로컬 파일 URI도 허용 + if (url.startsWith('file://')) { + return true; + } + + return false; + } catch (error) { + console.error('새 탭 확인 오류:', error); + return false; + } +} + +// 상태 관리 변수 +let monitoringInterval: ReturnType | null = null; +let allowedServicesList: string[] = []; +let lastCheckedURL: string = ''; +let mainWindow: BrowserWindow | null = null; + +// 모니터링 시작 +export function startBrowserMonitoring(win: BrowserWindow, allowedServices: string[]) { + // 기존 모니터링이 있다면 중지 + if (monitoringInterval) { + clearInterval(monitoringInterval); + } + + mainWindow = win; + allowedServicesList = allowedServices; + lastCheckedURL = ''; + + console.log('브라우저 모니터링 시작. 허용 서비스 목록:', allowedServices); + + // 500ms 간격으로 브라우저 URL 확인 + monitoringInterval = setInterval(() => { + const currentURL = getFocusedBrowserURL(); + + // URL이 있고, 이전과 다른 경우만 처리 + if (currentURL && currentURL !== lastCheckedURL) { + console.log('브라우저 URL 변경 감지:', currentURL); + lastCheckedURL = currentURL; + + // 허용되지 않은 URL인 경우 알림 표시 + const isAllowed = isAllowedURL(currentURL, allowedServicesList); + console.log('허용 여부:', isAllowed); + + if (!isAllowed) { + console.log('허용되지 않은 URL 감지:', currentURL); + + // 검증에 실패한 모든 서비스 목록과 실패 이유 상세 로깅 + console.log('상세 검증 결과:'); + try { + const currentUrl = new URL(currentURL); + const currentHostname = currentUrl.hostname.toLowerCase(); + const currentPathname = currentUrl.pathname.toLowerCase(); + + allowedServicesList.forEach((service) => { + let result = '불일치'; + let reason = ''; + + if (service.includes('/')) { + // 경로 포함된 서비스 + const fullPath = currentHostname + currentPathname; + const serviceMatches = fullPath.includes(service.toLowerCase()); + + if (serviceMatches) { + result = '일치'; + } else { + reason = `"${fullPath}"에 "${service}"가 포함되지 않음`; + } + } else { + // 도메인만 있는 서비스 + const hostnameMatches = + currentHostname === service.toLowerCase() || currentHostname.endsWith('.' + service.toLowerCase()); + + if (hostnameMatches) { + result = '일치'; + } else { + reason = `호스트명 "${currentHostname}"이 "${service}"와 일치하지 않음`; + } + } + + console.log(`검증: "${service}" - ${result}${reason ? ' (' + reason + ')' : ''}`); + }); + } catch (error) { + console.error('상세 검증 로깅 중 오류:', error); + } + + // 알림 표시 + showNotification(currentURL); + + // 렌더러에 타이머 중지 이벤트 전송 + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('timer:stop-by-url', { + url: currentURL, + timestamp: Date.now(), + }); + console.log('타이머 중지 신호 전송 완료'); + } + } + } + }, 500); +} + +// 모니터링 중지 +export function stopBrowserMonitoring() { + if (monitoringInterval) { + clearInterval(monitoringInterval); + monitoringInterval = null; + } +} + +// 시스템 알림 표시 +function showNotification(url: string) { + try { + const hostname = new URL(url).hostname; + const iconPath = path.join(app.getAppPath(), 'dist-electron/morib_logo.png'); + console.log('알림 아이콘 경로:', iconPath); + + const notification = new Notification({ + title: '허용 서비스에서 벗어나 타이머가 중지됩니다.', + body: `이 사이트를 허용 서비스로 등록할까요?`, + icon: iconPath, + actions: [ + { type: 'button', text: '타이머로 돌아가기' }, + { type: 'button', text: '허용서비스 추가' }, + ], + silent: false, + closeButtonText: '닫기', + }); + + // 알림 클릭 시 메인 윈도우 포커스 + notification.on('click', () => { + focusMainWindow(); + }); + + // 알림 액션 버튼 클릭 시 처리 + notification.on('action', (_, index) => { + if (mainWindow && !mainWindow.isDestroyed()) { + if (index === 0) { + focusMainWindow(); + mainWindow.webContents.send('browser-monitor:notification-action', 'timer', url); + } else if (index === 1) { + mainWindow.webContents.send('browser-monitor:notification-action', 'register', url); + } + } + }); + + notification.show(); + console.log('알림 표시 완료'); + } catch (error) { + console.error('알림 표시 오류:', error); + } +} + +// 메인 윈도우 포커스 함수 (코드 재사용을 위한 분리) +function focusMainWindow() { + if (mainWindow && !mainWindow.isDestroyed()) { + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.focus(); + } else { + console.warn('메인 윈도우가 없거나 파괴되어 포커스할 수 없습니다.'); + } +} diff --git a/src/electron/main.ts b/src/electron/main.ts new file mode 100644 index 00000000..8289bd79 --- /dev/null +++ b/src/electron/main.ts @@ -0,0 +1,382 @@ +import { BrowserWindow, Notification, app, ipcMain, screen, shell } from 'electron'; +import path from 'path'; + +import { startBrowserMonitoring, stopBrowserMonitoring } from './browserMonitor.js'; +import { getAuthenticatedWindowPath, getPreloadPath, parseTokensFromUrl } from './pathResolver.js'; +import { isDev } from './util.js'; + +let mainWindow: BrowserWindow | null = null; +let authWindow: BrowserWindow | null = null; +// 앱 종료 상태를 추적하는 변수 +let isAppQuitting = false; + +// NOTE: 기본 프로토콜 설정 (morib://) +if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient('morib', process.execPath, [path.resolve(process.argv[1])]); + } +} else { + app.setAsDefaultProtocolClient('morib'); +} + +// NOTE: 싱글 인스턴스 Local Lock 설정 +const gotTheLock = app.requestSingleInstanceLock(); + +if (!gotTheLock) { + app.quit(); +} else { + app.on('second-instance', (event: any, commandLine: string[], workingDirectory: string) => { + // Someone tried to run a second instance, we should focus our window. + if (mainWindow && !mainWindow.isDestroyed()) { + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.focus(); + } + + // NOTE: 디버깅용 Dialog 주석 처리 + // const lastArg = commandLine.length > 0 ? commandLine.pop()?.slice(0, -1) : ''; + // dialog.showErrorBox('Welcome Back', `You arrived from: ${lastArg}`); + }); + + // Create mainWindow, load the rest of the app, etc... + app.whenReady().then(() => { + createWindow(); + + // 인증 관련 IPC 핸들러 설정 + setupAuthHandlers(); + + // macOS에서 dock 아이콘 클릭 시 창 복원 + app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } else { + // 숨겨진 창이 있다면 표시하기 + if (authWindow && !authWindow.isDestroyed() && !authWindow.isVisible()) { + authWindow.show(); + } else if (mainWindow && !mainWindow.isDestroyed() && !mainWindow.isVisible()) { + mainWindow.show(); + } + } + }); + }); + + app.on('open-url', (event: any, url: string) => { + if (authWindow && !authWindow.isDestroyed()) { + if (authWindow.isMinimized()) authWindow.restore(); + authWindow.focus(); + } else { + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow?.close(); + } + + event.preventDefault(); + const { accessToken, refreshToken, isOnboardingCompleted } = parseTokensFromUrl(url); + + // dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`); // NOTE: 디버깅용 Dialog 주석 처리 + createAuthenticatedWindow(accessToken, refreshToken, isOnboardingCompleted); + // 브라우저 URL 모니터링을 위한 IPC 핸들러 등록 + setupBrowserMonitorHandlers(); + } + }); +} + +// 인증 관련 IPC 핸들러 설정 +function setupAuthHandlers() { + // 로그인 페이지로 리디렉션 요청 + ipcMain.on('auth:relogin', () => { + console.log('로그인 페이지로 리디렉션 요청 수신'); + + // authWindow가 있으면 닫음 + if (authWindow && !authWindow.isDestroyed()) { + authWindow.close(); + authWindow = null; + } + + // mainWindow가 없으면 생성, 있으면 로그인 페이지로 이동 + if (!mainWindow || mainWindow.isDestroyed()) { + createWindow(); + } else { + // 로그인 페이지로 이동 + if (isDev()) { + mainWindow.loadURL('http://localhost:5173/'); + } else { + mainWindow.loadFile(path.join(app.getAppPath(), 'dist-react/index.html')); + } + + // 창이 숨겨져 있으면 표시 + if (!mainWindow.isVisible()) { + mainWindow.show(); + } + mainWindow.focus(); + } + }); +} + +// 브라우저 URL 모니터링 IPC 핸들러 설정 +function setupBrowserMonitorHandlers() { + // 모니터링 시작 요청 + ipcMain.on('browser-monitor:start', (_, allowedServices: string[]) => { + console.log('브라우저 URL 모니터링 시작 요청 수신:', allowedServices); + + // 도메인 형식 확인 및 정제 (경로 정보 유지) + const processedServices = allowedServices + .map((service) => { + // 빈 서비스 또는 유효하지 않은 형식 제외 + if (!service || service.trim() === '') { + return ''; + } + + // URL 형식인 경우 프로토콜만 제거 (경로는 유지) + if (service.startsWith('http://') || service.startsWith('https://')) { + try { + // URL 객체로 파싱 + const url = new URL(service); + // 호스트명과 경로 유지 (프로토콜만 제거) + return url.hostname + url.pathname; + } catch (e) { + console.warn('허용 서비스 URL 파싱 오류:', e); + return service; + } + } + return service; + }) + .filter((s) => s.length > 0); // 빈 항목 제거 + + if (authWindow && !authWindow.isDestroyed()) { + console.log(`${processedServices.length}개의 허용 서비스로 모니터링 시작:`, processedServices); + startBrowserMonitoring(authWindow, processedServices); + } else { + console.error('메인 창이 없어 모니터링을 시작할 수 없습니다.'); + } + }); + + // 모니터링 중지 요청 + ipcMain.on('browser-monitor:stop', () => { + console.log('브라우저 URL 모니터링 중지 요청 수신'); + stopBrowserMonitoring(); + }); +} + +// 화면 해상도 확인 및 줌 레벨 설정 함수 +function adjustZoomLevelIfNeeded(window: BrowserWindow | null) { + if (!window) return; + + // 맥북 14인치 해상도 기준 (3024x1964) + const MAC14_WIDTH = 3024; + const MAC14_HEIGHT = 1964; + + const display = screen.getPrimaryDisplay(); + + const pixelWidth = display.workAreaSize.width * display.scaleFactor; + const pixelHeight = display.workAreaSize.height * display.scaleFactor; + + // 해상도가 맥북 14인치보다 작은 경우 + if (pixelWidth < MAC14_WIDTH || pixelHeight < MAC14_HEIGHT) { + // 콘텐츠가 로드된 후 줌 레벨 설정 + window.webContents.once('did-finish-load', () => { + // 화면 비율 80%로 설정 (줌 레벨 -1.0은 약 80%에 해당) + window.webContents.setZoomLevel(-1.0); + }); + } +} + +function createWindow() { + mainWindow = new BrowserWindow({ + webPreferences: { + preload: getPreloadPath(), + devTools: false, // 개발자 도구 비활성화 + }, + width: 1440, + height: 920, + show: false, // 초기에는 창을 표시하지 않음 + backgroundColor: '#181C22', // 배경색 설정 (어두운 색상 예시) + }); + + // 콘텐츠가 준비되면 창 표시 + mainWindow.once('ready-to-show', () => { + mainWindow?.show(); + }); + + // 화면 해상도에 따라 줌 레벨 조정 + adjustZoomLevelIfNeeded(mainWindow); + + // 줌 관련 설정 + mainWindow.webContents.on('zoom-changed', (event, zoomDirection) => { + // cmd+ 또는 cmd- 키를 사용한 줌만 허용 + if (zoomDirection !== 'in' && zoomDirection !== 'out') { + event.preventDefault(); + } + }); + + // 마우스 휠로 인한 줌 변경 방지 (pinch-to-zoom) + mainWindow.webContents.on('before-input-event', (event, input) => { + // 개발자 도구를 열 수 있는 모든 단축키 차단 + if ( + // cmd + option + i (macOS) + (input.key === 'i' && input.meta && input.alt) || + // F12 + input.key === 'F12' || + // cmd + shift + i (macOS), ctrl + shift + i (Windows/Linux) + (input.key === 'i' && input.shift && (input.meta || input.control)) || + // cmd + shift + c (macOS), ctrl + shift + c (Windows/Linux) + (input.key === 'c' && input.shift && (input.meta || input.control)) || + // cmd + shift + j (macOS), ctrl + shift + j (Windows/Linux) + (input.key === 'j' && input.shift && (input.meta || input.control)) || + // 줌 관련 키 중 cmd+ 및 cmd- 외의 다른 키 차단 (ctrl+0 등) + (input.key === '0' && (input.meta || input.control)) + ) { + event.preventDefault(); + } + }); + + mainWindow.webContents.setWindowOpenHandler((details) => { + shell.openExternal(details.url); // Open URL in user's browser. + return { action: 'deny' }; // Prevent the app from opening the URL. + }); + + // 닫기 버튼 클릭 시 앱을 종료하지 않고 숨김(hide) 처리 + mainWindow.on('close', (event) => { + // 앱이 실제로 종료되려는 경우는 처리하지 않음 + if (!isAppQuitting && authWindow !== null && !authWindow.isDestroyed() && mainWindow && !mainWindow.isDestroyed()) { + event.preventDefault(); + + // 전체화면 상태인지 확인 + if (mainWindow.isFullScreen()) { + // 전체화면 상태면 먼저 전체화면 해제 후 숨김 + mainWindow.setFullScreen(false); + // 전체화면 해제 애니메이션 완료 후 숨김 처리 + } else { + // 전체화면이 아니면 바로 숨김 + mainWindow.hide(); + } + + return false; + } + + return true; + }); + + if (isDev()) { + mainWindow.loadURL('http://localhost:5173/'); + } else { + mainWindow.loadFile(path.join(app.getAppPath(), 'dist-react/index.html')); + } +} + +function createAuthenticatedWindow( + accessToken: string | null, + refreshToken: string | null, + isOnboardingCompleted: string | null, +) { + authWindow = new BrowserWindow({ + webPreferences: { + preload: getPreloadPath(), + devTools: false, // 개발자 도구 비활성화 + }, + width: 1440, + height: 920, + show: false, // 초기에는 창을 표시하지 않음 + backgroundColor: '#181C22', // 배경색 설정 (어두운 색상 예시) + }); + + // 콘텐츠가 준비되면 창 표시 + authWindow.once('ready-to-show', () => { + authWindow?.show(); + }); + + // 화면 해상도에 따라 줌 레벨 조정 + adjustZoomLevelIfNeeded(authWindow); + + // 줌 관련 설정 + authWindow.webContents.on('zoom-changed', (event, zoomDirection) => { + // cmd+ 또는 cmd- 키를 사용한 줌만 허용 + if (zoomDirection !== 'in' && zoomDirection !== 'out') { + event.preventDefault(); + } + }); + + // 마우스 휠로 인한 줌 변경 방지 및 개발자 도구 단축키 차단 + authWindow.webContents.on('before-input-event', (event, input) => { + // 개발자 도구를 열 수 있는 모든 단축키 차단 + if ( + // cmd + option + i (macOS) + (input.key === 'i' && input.meta && input.alt) || + // F12 + input.key === 'F12' || + // cmd + shift + i (macOS), ctrl + shift + i (Windows/Linux) + (input.key === 'i' && input.shift && (input.meta || input.control)) || + // cmd + shift + c (macOS), ctrl + shift + c (Windows/Linux) + (input.key === 'c' && input.shift && (input.meta || input.control)) || + // cmd + shift + j (macOS), ctrl + shift + j (Windows/Linux) + (input.key === 'j' && input.shift && (input.meta || input.control)) || + // 줌 관련 키 중 cmd+ 및 cmd- 외의 다른 키 차단 (ctrl+0 등) + (input.key === '0' && (input.meta || input.control)) + ) { + event.preventDefault(); + } + }); + + // 닫기 버튼 클릭 시 앱을 종료하지 않고 숨김 처리 + authWindow.on('close', (event) => { + // 앱이 실제로 종료되려는 경우는 처리하지 않음 + if (!isAppQuitting && authWindow && !authWindow.isDestroyed()) { + event.preventDefault(); + + // 전체화면 상태인지 확인 + if (authWindow.isFullScreen()) { + // 전체화면 상태면 먼저 전체화면 해제 후 숨김 + authWindow.setFullScreen(false); + // 전체화면 해제 애니메이션 완료 후 숨김 처리 + } else { + // 전체화면이 아니면 바로 숨김 + authWindow.hide(); + } + + return false; + } + + return true; + }); + + authWindow.loadURL(getAuthenticatedWindowPath(accessToken || '', refreshToken || '', isOnboardingCompleted || '')); +} + +// Quit when all windows are closed, except on macOS. There, it's common +// for applications and their menu bar to stay active until the user quits +// explicitly with Cmd + Q. +app.on('window-all-closed', function () { + if (process.platform !== 'darwin') app.quit(); +}); + +// 실제 앱 종료 처리 +app.on('before-quit', () => { + // 앱 종료 플래그를 true로 설정 + isAppQuitting = true; +}); + +// 앱 종료 시 모니터링 중지 +app.on('will-quit', () => { + stopBrowserMonitoring(); +}); + +// Handle window controls via IPC +ipcMain.on('shell:open', () => { + const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked'); + const pagePath = path.join('file://', pageDirectory, 'index.html'); + shell.openExternal(pagePath); +}); + +// 시스템 알림 표시 IPC 핸들러 +ipcMain.on('notification:show', (_, { title, body }) => { + const iconPath = path.join(app.getAppPath(), 'dist-electron/morib_logo.png'); + + const notification = new Notification({ + title, + body, + icon: iconPath, + silent: false, + }); + + notification.show(); +}); diff --git a/src/electron/pathResolver.ts b/src/electron/pathResolver.ts new file mode 100644 index 00000000..c2b00bc6 --- /dev/null +++ b/src/electron/pathResolver.ts @@ -0,0 +1,40 @@ +import { app } from 'electron'; +import path from 'path'; +import { pathToFileURL } from 'url'; + +import { isDev } from './util.js'; + +export const LOCAL_HOST = 'http://localhost:5173'; +export const INDEX_PATH = path.join(app.getAppPath(), 'dist-react', 'index.html'); + +export function getPreloadPath() { + return path.join(app.getAppPath(), isDev() ? '.' : '..', '/dist-electron/preload.cjs'); +} + +export function getFilePath() { + return pathToFileURL(INDEX_PATH).toString(); +} + +export function parseTokensFromUrl(raw: string) { + try { + const u = new URL(raw); // morib://callback?accessToken=…&… + return { + accessToken: u.searchParams.get('accessToken'), + refreshToken: u.searchParams.get('refreshToken'), + isOnboardingCompleted: u.searchParams.get('isOnboardingCompleted'), + }; + } catch (e) { + console.error('[parseTokensFromUrl]', e); + return { accessToken: '', refreshToken: '', isOnboardingCompleted: '' }; + } +} + +export function getTitleBarPath() { + return path.join(isDev() ? '.' : '..', 'dist-electron/ui/titleBar.html'); +} + +export function getAuthenticatedWindowPath(accessToken: string, refreshToken: string, isOnboardingCompleted: string) { + return isDev() + ? `${LOCAL_HOST}#/auth/redirect?accessToken=${encodeURIComponent(accessToken || '')}&refreshToken=${encodeURIComponent(refreshToken || '')}&isOnboardingCompleted=${encodeURIComponent(isOnboardingCompleted || '')}` + : `${getFilePath()}#/auth/redirect?accessToken=${encodeURIComponent(accessToken || '')}&refreshToken=${encodeURIComponent(refreshToken || '')}&isOnboardingCompleted=${encodeURIComponent(isOnboardingCompleted || '')}`; +} diff --git a/src/electron/preload.cts b/src/electron/preload.cts new file mode 100644 index 00000000..54810a9a --- /dev/null +++ b/src/electron/preload.cts @@ -0,0 +1,54 @@ +const { contextBridge, ipcRenderer } = require('electron'); + +// 렌더러 프로세스에 노출할 API 정의 +contextBridge.exposeInMainWorld('electron', { + // 브라우저 URL 모니터링 API 추가 + browserMonitor: { + // 허용 서비스 목록 설정 및 모니터링 시작 + startMonitoring: (allowedServices: string[]) => { + ipcRenderer.send('browser-monitor:start', allowedServices); + }, + + // 모니터링 중지 + stopMonitoring: () => { + ipcRenderer.send('browser-monitor:stop'); + }, + + // 허용되지 않은 URL 발견 시 이벤트 리스너 + onUnallowedUrl: (callback: (url: string, action?: string) => void) => { + const handler = (_: any, url: string, action?: string) => callback(url, action); + ipcRenderer.on('browser-monitor:unallowed-url', handler); + return () => ipcRenderer.removeListener('browser-monitor:unallowed-url', handler); + }, + + // 알림 액션 이벤트 (타이머로 돌아가기, 허용 서비스 등록하기) + onNotificationAction: (callback: (action: 'timer' | 'register', url: string) => void) => { + const handler = (_: any, action: 'timer' | 'register', url: string) => callback(action, url); + ipcRenderer.on('browser-monitor:notification-action', handler); + return () => ipcRenderer.removeListener('browser-monitor:notification-action', handler); + }, + + // 타이머 정지 이벤트 리스너 - URL로 인한 타이머 정지 + onTimerStop: (callback: (data: { url: string; timestamp: number }) => void) => { + const handler = (_: any, data: { url: string; timestamp: number }) => callback(data); + ipcRenderer.on('timer:stop-by-url', handler); + return () => ipcRenderer.removeListener('timer:stop-by-url', handler); + }, + }, + + // 인증 관련 API 추가 + auth: { + // 로그인 페이지로 리디렉션하는 함수 + relogin: () => { + ipcRenderer.send('auth:relogin'); + }, + }, + + // 시스템 알림 관련 API 추가 + notification: { + // 시스템 알림 표시 함수 + showSystemNotification: (title: string, body: string) => { + ipcRenderer.send('notification:show', { title, body }); + }, + }, +}); diff --git a/src/electron/tsconfig.json b/src/electron/tsconfig.json new file mode 100644 index 00000000..88b155c5 --- /dev/null +++ b/src/electron/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "strict": false, + "target": "ESNext", + "module": "NodeNext", + "outDir": "../../dist-electron", + "skipLibCheck": true, + } +} \ No newline at end of file diff --git a/src/electron/util.ts b/src/electron/util.ts new file mode 100644 index 00000000..9db04899 --- /dev/null +++ b/src/electron/util.ts @@ -0,0 +1,3 @@ +export function isDev(): boolean { + return process.env.NODE_ENV === 'development'; +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts deleted file mode 100644 index cc927f2e..00000000 --- a/src/vite-env.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// - -interface ImportMetaEnv { - readonly VITE_BASE_URL: string; - readonly VITE_GOOGLE_URL: string; - readonly VITE_SENTRY_DSN: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} diff --git a/tsconfig.app.json b/tsconfig.app.json index 497f2255..7efe41b9 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -26,7 +26,7 @@ /* 절대경로 */ "baseUrl": ".", "paths": { - "@/*": ["src/*"] + "@/*": ["src/app/*"] }, /*svg 모듈 */ diff --git a/tsconfig.node.json b/tsconfig.node.json index 6dc4f9d6..9375319c 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -12,7 +12,7 @@ /* 절대경로 */ "baseUrl": ".", "paths": { - "@/*": ["src/*"] + "@/*": ["src/app/*"] }, /*svg 모듈 */ diff --git a/vite.config.ts b/vite.config.ts index 3008826a..380bf862 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -6,6 +6,14 @@ import svgr from 'vite-plugin-svgr'; export default defineConfig({ plugins: [react(), svgr()], resolve: { - alias: [{ find: '@', replacement: '/src' }], + alias: [{ find: '@', replacement: '/src/app' }], + }, + base: './', + build: { + outDir: 'dist-react', + }, + server: { + port: 5173, + strictPort: true, }, });