fix(runtime): enforce session and environment contracts
This commit is contained in:
+6
-2
@@ -2,6 +2,10 @@
|
|||||||
"name": "cozsweet-frontend-nextjs",
|
"name": "cozsweet-frontend-nextjs",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"packageManager": "pnpm@10.30.3",
|
||||||
|
"engines": {
|
||||||
|
"node": "24.x"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
@@ -37,7 +41,7 @@
|
|||||||
"@xstate/react": "^5",
|
"@xstate/react": "^5",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"dexie": "^4.4.3",
|
"dexie": "^4.4.3",
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.28.0",
|
||||||
"lucide-react": "^1.18.0",
|
"lucide-react": "^1.18.0",
|
||||||
"next": "16.2.7",
|
"next": "16.2.7",
|
||||||
"next-auth": "^4.24.14",
|
"next-auth": "^4.24.14",
|
||||||
@@ -55,7 +59,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.61.1",
|
"@playwright/test": "^1.61.1",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^24",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"@vitest/coverage-v8": "^4.1.8",
|
"@vitest/coverage-v8": "^4.1.8",
|
||||||
|
|||||||
Generated
+144
-144
@@ -13,10 +13,10 @@ importers:
|
|||||||
version: 5.2.0
|
version: 5.2.0
|
||||||
'@sentry/nextjs':
|
'@sentry/nextjs':
|
||||||
specifier: ^10.61.0
|
specifier: ^10.61.0
|
||||||
version: 10.61.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.108.0(esbuild@0.25.12))
|
version: 10.61.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.108.0(esbuild@0.28.1))
|
||||||
'@serwist/turbopack':
|
'@serwist/turbopack':
|
||||||
specifier: ^9.0.0
|
specifier: ^9.0.0
|
||||||
version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
version: 9.5.11(esbuild@0.28.1)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
|
||||||
'@stripe/react-stripe-js':
|
'@stripe/react-stripe-js':
|
||||||
specifier: ^6.6.0
|
specifier: ^6.6.0
|
||||||
version: 6.6.0(@stripe/stripe-js@9.8.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
version: 6.6.0(@stripe/stripe-js@9.8.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
@@ -33,8 +33,8 @@ importers:
|
|||||||
specifier: ^4.4.3
|
specifier: ^4.4.3
|
||||||
version: 4.4.3
|
version: 4.4.3
|
||||||
esbuild:
|
esbuild:
|
||||||
specifier: ^0.25.0
|
specifier: ^0.28.0
|
||||||
version: 0.25.12
|
version: 0.28.1
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^1.18.0
|
specifier: ^1.18.0
|
||||||
version: 1.18.0(react@19.2.4)
|
version: 1.18.0(react@19.2.4)
|
||||||
@@ -82,8 +82,8 @@ importers:
|
|||||||
specifier: ^4
|
specifier: ^4
|
||||||
version: 4.3.0
|
version: 4.3.0
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20
|
specifier: ^24
|
||||||
version: 20.19.41
|
version: 24.13.3
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19
|
specifier: ^19
|
||||||
version: 19.2.16
|
version: 19.2.16
|
||||||
@@ -116,7 +116,7 @@ importers:
|
|||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.1.8
|
specifier: ^4.1.8
|
||||||
version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))
|
version: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -274,158 +274,158 @@ packages:
|
|||||||
'@emnapi/wasi-threads@1.2.1':
|
'@emnapi/wasi-threads@1.2.1':
|
||||||
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
|
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.12':
|
'@esbuild/aix-ppc64@0.28.1':
|
||||||
resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
|
resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [aix]
|
os: [aix]
|
||||||
|
|
||||||
'@esbuild/android-arm64@0.25.12':
|
'@esbuild/android-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
|
resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/android-arm@0.25.12':
|
'@esbuild/android-arm@0.28.1':
|
||||||
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
|
resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/android-x64@0.25.12':
|
'@esbuild/android-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
|
resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@esbuild/darwin-arm64@0.25.12':
|
'@esbuild/darwin-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
|
resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@esbuild/darwin-x64@0.25.12':
|
'@esbuild/darwin-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
|
resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@esbuild/freebsd-arm64@0.25.12':
|
'@esbuild/freebsd-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
|
resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@esbuild/freebsd-x64@0.25.12':
|
'@esbuild/freebsd-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
|
resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@esbuild/linux-arm64@0.25.12':
|
'@esbuild/linux-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
|
resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-arm@0.25.12':
|
'@esbuild/linux-arm@0.28.1':
|
||||||
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
|
resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-ia32@0.25.12':
|
'@esbuild/linux-ia32@0.28.1':
|
||||||
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
|
resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-loong64@0.25.12':
|
'@esbuild/linux-loong64@0.28.1':
|
||||||
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
|
resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [loong64]
|
cpu: [loong64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-mips64el@0.25.12':
|
'@esbuild/linux-mips64el@0.28.1':
|
||||||
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
|
resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [mips64el]
|
cpu: [mips64el]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-ppc64@0.25.12':
|
'@esbuild/linux-ppc64@0.28.1':
|
||||||
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
|
resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-riscv64@0.25.12':
|
'@esbuild/linux-riscv64@0.28.1':
|
||||||
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
|
resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-s390x@0.25.12':
|
'@esbuild/linux-s390x@0.28.1':
|
||||||
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
|
resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [s390x]
|
cpu: [s390x]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/linux-x64@0.25.12':
|
'@esbuild/linux-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
|
resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@esbuild/netbsd-arm64@0.25.12':
|
'@esbuild/netbsd-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
|
resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [netbsd]
|
os: [netbsd]
|
||||||
|
|
||||||
'@esbuild/netbsd-x64@0.25.12':
|
'@esbuild/netbsd-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
|
resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [netbsd]
|
os: [netbsd]
|
||||||
|
|
||||||
'@esbuild/openbsd-arm64@0.25.12':
|
'@esbuild/openbsd-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
|
resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openbsd]
|
os: [openbsd]
|
||||||
|
|
||||||
'@esbuild/openbsd-x64@0.25.12':
|
'@esbuild/openbsd-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
|
resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [openbsd]
|
os: [openbsd]
|
||||||
|
|
||||||
'@esbuild/openharmony-arm64@0.25.12':
|
'@esbuild/openharmony-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
|
resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [openharmony]
|
os: [openharmony]
|
||||||
|
|
||||||
'@esbuild/sunos-x64@0.25.12':
|
'@esbuild/sunos-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
|
resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [sunos]
|
os: [sunos]
|
||||||
|
|
||||||
'@esbuild/win32-arm64@0.25.12':
|
'@esbuild/win32-arm64@0.28.1':
|
||||||
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
|
resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@esbuild/win32-ia32@0.25.12':
|
'@esbuild/win32-ia32@0.28.1':
|
||||||
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
|
resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@esbuild/win32-x64@0.25.12':
|
'@esbuild/win32-x64@0.28.1':
|
||||||
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
|
resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -1471,8 +1471,8 @@ packages:
|
|||||||
'@types/json5@0.0.29':
|
'@types/json5@0.0.29':
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
|
|
||||||
'@types/node@20.19.41':
|
'@types/node@24.13.3':
|
||||||
resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==}
|
resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==}
|
||||||
|
|
||||||
'@types/react-dom@19.2.3':
|
'@types/react-dom@19.2.3':
|
||||||
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
|
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
|
||||||
@@ -2180,8 +2180,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
|
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
esbuild@0.25.12:
|
esbuild@0.28.1:
|
||||||
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
|
resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -3716,8 +3716,8 @@ packages:
|
|||||||
uncrypto@0.1.3:
|
uncrypto@0.1.3:
|
||||||
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
|
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
|
||||||
|
|
||||||
undici-types@6.21.0:
|
undici-types@7.18.2:
|
||||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
|
||||||
|
|
||||||
undici@7.27.2:
|
undici@7.27.2:
|
||||||
resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==}
|
resolution: {integrity: sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==}
|
||||||
@@ -4220,82 +4220,82 @@ snapshots:
|
|||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.12':
|
'@esbuild/aix-ppc64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm64@0.25.12':
|
'@esbuild/android-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-arm@0.25.12':
|
'@esbuild/android-arm@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/android-x64@0.25.12':
|
'@esbuild/android-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-arm64@0.25.12':
|
'@esbuild/darwin-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/darwin-x64@0.25.12':
|
'@esbuild/darwin-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-arm64@0.25.12':
|
'@esbuild/freebsd-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/freebsd-x64@0.25.12':
|
'@esbuild/freebsd-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm64@0.25.12':
|
'@esbuild/linux-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-arm@0.25.12':
|
'@esbuild/linux-arm@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ia32@0.25.12':
|
'@esbuild/linux-ia32@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-loong64@0.25.12':
|
'@esbuild/linux-loong64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-mips64el@0.25.12':
|
'@esbuild/linux-mips64el@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-ppc64@0.25.12':
|
'@esbuild/linux-ppc64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-riscv64@0.25.12':
|
'@esbuild/linux-riscv64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-s390x@0.25.12':
|
'@esbuild/linux-s390x@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/linux-x64@0.25.12':
|
'@esbuild/linux-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-arm64@0.25.12':
|
'@esbuild/netbsd-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/netbsd-x64@0.25.12':
|
'@esbuild/netbsd-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-arm64@0.25.12':
|
'@esbuild/openbsd-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openbsd-x64@0.25.12':
|
'@esbuild/openbsd-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/openharmony-arm64@0.25.12':
|
'@esbuild/openharmony-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/sunos-x64@0.25.12':
|
'@esbuild/sunos-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-arm64@0.25.12':
|
'@esbuild/win32-arm64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-ia32@0.25.12':
|
'@esbuild/win32-ia32@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@esbuild/win32-x64@0.25.12':
|
'@esbuild/win32-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))':
|
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))':
|
||||||
@@ -4810,7 +4810,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@sentry/core': 10.61.0
|
'@sentry/core': 10.61.0
|
||||||
|
|
||||||
'@sentry/nextjs@10.61.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.108.0(esbuild@0.25.12))':
|
'@sentry/nextjs@10.61.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.108.0(esbuild@0.28.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@opentelemetry/api': 1.9.1
|
'@opentelemetry/api': 1.9.1
|
||||||
'@rollup/plugin-commonjs': 28.0.1(rollup@4.62.2)
|
'@rollup/plugin-commonjs': 28.0.1(rollup@4.62.2)
|
||||||
@@ -4822,7 +4822,7 @@ snapshots:
|
|||||||
'@sentry/opentelemetry': 10.61.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))
|
'@sentry/opentelemetry': 10.61.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))
|
||||||
'@sentry/react': 10.61.0(react@19.2.4)
|
'@sentry/react': 10.61.0(react@19.2.4)
|
||||||
'@sentry/vercel-edge': 10.61.0
|
'@sentry/vercel-edge': 10.61.0
|
||||||
'@sentry/webpack-plugin': 5.3.0(webpack@5.108.0(esbuild@0.25.12))
|
'@sentry/webpack-plugin': 5.3.0(webpack@5.108.0(esbuild@0.28.1))
|
||||||
next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
next: 16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||||
rollup: 4.62.2
|
rollup: 4.62.2
|
||||||
stacktrace-parser: 0.1.11
|
stacktrace-parser: 0.1.11
|
||||||
@@ -4903,10 +4903,10 @@ snapshots:
|
|||||||
'@opentelemetry/api': 1.9.1
|
'@opentelemetry/api': 1.9.1
|
||||||
'@sentry/core': 10.61.0
|
'@sentry/core': 10.61.0
|
||||||
|
|
||||||
'@sentry/webpack-plugin@5.3.0(webpack@5.108.0(esbuild@0.25.12))':
|
'@sentry/webpack-plugin@5.3.0(webpack@5.108.0(esbuild@0.28.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sentry/bundler-plugin-core': 5.3.0
|
'@sentry/bundler-plugin-core': 5.3.0
|
||||||
webpack: 5.108.0(esbuild@0.25.12)
|
webpack: 5.108.0(esbuild@0.28.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -4925,7 +4925,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- browserslist
|
- browserslist
|
||||||
|
|
||||||
'@serwist/turbopack@9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)':
|
'@serwist/turbopack@9.5.11(esbuild@0.28.1)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@serwist/build': 9.5.11(browserslist@4.28.2)(typescript@5.9.3)
|
'@serwist/build': 9.5.11(browserslist@4.28.2)(typescript@5.9.3)
|
||||||
'@serwist/utils': 9.5.11(browserslist@4.28.2)
|
'@serwist/utils': 9.5.11(browserslist@4.28.2)
|
||||||
@@ -4939,7 +4939,7 @@ snapshots:
|
|||||||
serwist: 9.5.11(browserslist@4.28.2)(typescript@5.9.3)
|
serwist: 9.5.11(browserslist@4.28.2)(typescript@5.9.3)
|
||||||
zod: 4.4.1
|
zod: 4.4.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
esbuild: 0.25.12
|
esbuild: 0.28.1
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@swc/helpers'
|
- '@swc/helpers'
|
||||||
@@ -5119,9 +5119,9 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json5@0.0.29': {}
|
'@types/json5@0.0.29': {}
|
||||||
|
|
||||||
'@types/node@20.19.41':
|
'@types/node@24.13.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 7.18.2
|
||||||
|
|
||||||
'@types/react-dom@19.2.3(@types/react@19.2.16)':
|
'@types/react-dom@19.2.3(@types/react@19.2.16)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5312,7 +5312,7 @@ snapshots:
|
|||||||
obug: 2.1.2
|
obug: 2.1.2
|
||||||
std-env: 4.1.0
|
std-env: 4.1.0
|
||||||
tinyrainbow: 3.1.0
|
tinyrainbow: 3.1.0
|
||||||
vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))
|
vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0))
|
||||||
|
|
||||||
'@vitest/expect@4.1.8':
|
'@vitest/expect@4.1.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5323,13 +5323,13 @@ snapshots:
|
|||||||
chai: 6.2.2
|
chai: 6.2.2
|
||||||
tinyrainbow: 3.1.0
|
tinyrainbow: 3.1.0
|
||||||
|
|
||||||
'@vitest/mocker@4.1.8(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))':
|
'@vitest/mocker@4.1.8(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/spy': 4.1.8
|
'@vitest/spy': 4.1.8
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)
|
vite: 8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)
|
||||||
|
|
||||||
'@vitest/pretty-format@4.1.8':
|
'@vitest/pretty-format@4.1.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5358,7 +5358,7 @@ snapshots:
|
|||||||
sirv: 3.0.2
|
sirv: 3.0.2
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
tinyrainbow: 3.1.0
|
tinyrainbow: 3.1.0
|
||||||
vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))
|
vitest: 4.1.8(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0))
|
||||||
|
|
||||||
'@vitest/utils@4.1.8':
|
'@vitest/utils@4.1.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5936,34 +5936,34 @@ snapshots:
|
|||||||
is-date-object: 1.1.0
|
is-date-object: 1.1.0
|
||||||
is-symbol: 1.1.1
|
is-symbol: 1.1.1
|
||||||
|
|
||||||
esbuild@0.25.12:
|
esbuild@0.28.1:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@esbuild/aix-ppc64': 0.25.12
|
'@esbuild/aix-ppc64': 0.28.1
|
||||||
'@esbuild/android-arm': 0.25.12
|
'@esbuild/android-arm': 0.28.1
|
||||||
'@esbuild/android-arm64': 0.25.12
|
'@esbuild/android-arm64': 0.28.1
|
||||||
'@esbuild/android-x64': 0.25.12
|
'@esbuild/android-x64': 0.28.1
|
||||||
'@esbuild/darwin-arm64': 0.25.12
|
'@esbuild/darwin-arm64': 0.28.1
|
||||||
'@esbuild/darwin-x64': 0.25.12
|
'@esbuild/darwin-x64': 0.28.1
|
||||||
'@esbuild/freebsd-arm64': 0.25.12
|
'@esbuild/freebsd-arm64': 0.28.1
|
||||||
'@esbuild/freebsd-x64': 0.25.12
|
'@esbuild/freebsd-x64': 0.28.1
|
||||||
'@esbuild/linux-arm': 0.25.12
|
'@esbuild/linux-arm': 0.28.1
|
||||||
'@esbuild/linux-arm64': 0.25.12
|
'@esbuild/linux-arm64': 0.28.1
|
||||||
'@esbuild/linux-ia32': 0.25.12
|
'@esbuild/linux-ia32': 0.28.1
|
||||||
'@esbuild/linux-loong64': 0.25.12
|
'@esbuild/linux-loong64': 0.28.1
|
||||||
'@esbuild/linux-mips64el': 0.25.12
|
'@esbuild/linux-mips64el': 0.28.1
|
||||||
'@esbuild/linux-ppc64': 0.25.12
|
'@esbuild/linux-ppc64': 0.28.1
|
||||||
'@esbuild/linux-riscv64': 0.25.12
|
'@esbuild/linux-riscv64': 0.28.1
|
||||||
'@esbuild/linux-s390x': 0.25.12
|
'@esbuild/linux-s390x': 0.28.1
|
||||||
'@esbuild/linux-x64': 0.25.12
|
'@esbuild/linux-x64': 0.28.1
|
||||||
'@esbuild/netbsd-arm64': 0.25.12
|
'@esbuild/netbsd-arm64': 0.28.1
|
||||||
'@esbuild/netbsd-x64': 0.25.12
|
'@esbuild/netbsd-x64': 0.28.1
|
||||||
'@esbuild/openbsd-arm64': 0.25.12
|
'@esbuild/openbsd-arm64': 0.28.1
|
||||||
'@esbuild/openbsd-x64': 0.25.12
|
'@esbuild/openbsd-x64': 0.28.1
|
||||||
'@esbuild/openharmony-arm64': 0.25.12
|
'@esbuild/openharmony-arm64': 0.28.1
|
||||||
'@esbuild/sunos-x64': 0.25.12
|
'@esbuild/sunos-x64': 0.28.1
|
||||||
'@esbuild/win32-arm64': 0.25.12
|
'@esbuild/win32-arm64': 0.28.1
|
||||||
'@esbuild/win32-ia32': 0.25.12
|
'@esbuild/win32-ia32': 0.28.1
|
||||||
'@esbuild/win32-x64': 0.25.12
|
'@esbuild/win32-x64': 0.28.1
|
||||||
|
|
||||||
escalade@3.2.0: {}
|
escalade@3.2.0: {}
|
||||||
|
|
||||||
@@ -6568,7 +6568,7 @@ snapshots:
|
|||||||
|
|
||||||
jest-worker@27.5.1:
|
jest-worker@27.5.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.19.41
|
'@types/node': 24.13.3
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
|
|
||||||
@@ -6782,15 +6782,15 @@ snapshots:
|
|||||||
|
|
||||||
minimist@1.2.8: {}
|
minimist@1.2.8: {}
|
||||||
|
|
||||||
minimizer-webpack-plugin@5.6.1(esbuild@0.25.12)(webpack@5.108.0(esbuild@0.25.12)):
|
minimizer-webpack-plugin@5.6.1(esbuild@0.28.1)(webpack@5.108.0(esbuild@0.28.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.31
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
jest-worker: 27.5.1
|
jest-worker: 27.5.1
|
||||||
schema-utils: 4.3.3
|
schema-utils: 4.3.3
|
||||||
terser: 5.48.0
|
terser: 5.48.0
|
||||||
webpack: 5.108.0(esbuild@0.25.12)
|
webpack: 5.108.0(esbuild@0.28.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
esbuild: 0.25.12
|
esbuild: 0.28.1
|
||||||
|
|
||||||
minipass@7.1.3: {}
|
minipass@7.1.3: {}
|
||||||
|
|
||||||
@@ -7619,7 +7619,7 @@ snapshots:
|
|||||||
|
|
||||||
uncrypto@0.1.3: {}
|
uncrypto@0.1.3: {}
|
||||||
|
|
||||||
undici-types@6.21.0: {}
|
undici-types@7.18.2: {}
|
||||||
|
|
||||||
undici@7.27.2: {}
|
undici@7.27.2: {}
|
||||||
|
|
||||||
@@ -7683,7 +7683,7 @@ snapshots:
|
|||||||
|
|
||||||
uuid@8.3.2: {}
|
uuid@8.3.2: {}
|
||||||
|
|
||||||
vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0):
|
vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
lightningcss: 1.32.0
|
lightningcss: 1.32.0
|
||||||
picomatch: 4.0.4
|
picomatch: 4.0.4
|
||||||
@@ -7691,16 +7691,16 @@ snapshots:
|
|||||||
rolldown: 1.0.3
|
rolldown: 1.0.3
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 20.19.41
|
'@types/node': 24.13.3
|
||||||
esbuild: 0.25.12
|
esbuild: 0.28.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
jiti: 2.7.0
|
jiti: 2.7.0
|
||||||
terser: 5.48.0
|
terser: 5.48.0
|
||||||
|
|
||||||
vitest@4.1.8(@opentelemetry/api@1.9.1)(@types/node@20.19.41)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)):
|
vitest@4.1.8(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/coverage-v8@4.1.8)(@vitest/ui@4.1.8)(jsdom@29.1.1)(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/expect': 4.1.8
|
'@vitest/expect': 4.1.8
|
||||||
'@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0))
|
'@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0))
|
||||||
'@vitest/pretty-format': 4.1.8
|
'@vitest/pretty-format': 4.1.8
|
||||||
'@vitest/runner': 4.1.8
|
'@vitest/runner': 4.1.8
|
||||||
'@vitest/snapshot': 4.1.8
|
'@vitest/snapshot': 4.1.8
|
||||||
@@ -7717,11 +7717,11 @@ snapshots:
|
|||||||
tinyexec: 1.2.4
|
tinyexec: 1.2.4
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
tinyrainbow: 3.1.0
|
tinyrainbow: 3.1.0
|
||||||
vite: 8.0.16(@types/node@20.19.41)(esbuild@0.25.12)(jiti@2.7.0)(terser@5.48.0)
|
vite: 8.0.16(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.48.0)
|
||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@opentelemetry/api': 1.9.1
|
'@opentelemetry/api': 1.9.1
|
||||||
'@types/node': 20.19.41
|
'@types/node': 24.13.3
|
||||||
'@vitest/coverage-v8': 4.1.8(vitest@4.1.8)
|
'@vitest/coverage-v8': 4.1.8(vitest@4.1.8)
|
||||||
'@vitest/ui': 4.1.8(vitest@4.1.8)
|
'@vitest/ui': 4.1.8(vitest@4.1.8)
|
||||||
jsdom: 29.1.1
|
jsdom: 29.1.1
|
||||||
@@ -7744,7 +7744,7 @@ snapshots:
|
|||||||
|
|
||||||
webpack-sources@3.5.0: {}
|
webpack-sources@3.5.0: {}
|
||||||
|
|
||||||
webpack@5.108.0(esbuild@0.25.12):
|
webpack@5.108.0(esbuild@0.28.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.9
|
'@types/estree': 1.0.9
|
||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
@@ -7762,7 +7762,7 @@ snapshots:
|
|||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
loader-runner: 4.3.2
|
loader-runner: 4.3.2
|
||||||
mime-db: 1.54.0
|
mime-db: 1.54.0
|
||||||
minimizer-webpack-plugin: 5.6.1(esbuild@0.25.12)(webpack@5.108.0(esbuild@0.25.12))
|
minimizer-webpack-plugin: 5.6.1(esbuild@0.28.1)(webpack@5.108.0(esbuild@0.28.1))
|
||||||
neo-async: 2.6.2
|
neo-async: 2.6.2
|
||||||
schema-utils: 4.3.3
|
schema-utils: 4.3.3
|
||||||
tapable: 2.3.3
|
tapable: 2.3.3
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { getApiConfig } from "@/core/net/config/api_config";
|
||||||
|
|
||||||
|
const CONFIG_ENV_KEYS = [
|
||||||
|
"NEXT_PUBLIC_API_BASE_URL",
|
||||||
|
"NEXT_PUBLIC_WS_BASE_URL",
|
||||||
|
"NEXT_PUBLIC_API_CONNECT_TIMEOUT",
|
||||||
|
"NEXT_PUBLIC_API_RECEIVE_TIMEOUT",
|
||||||
|
"NEXT_PUBLIC_API_SEND_TIMEOUT",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllEnvs();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getApiConfig", () => {
|
||||||
|
it("keeps local defaults in development", () => {
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "development");
|
||||||
|
unsetConfigEnv();
|
||||||
|
|
||||||
|
expect(getApiConfig()).toEqual({
|
||||||
|
baseUrl: "http://172.16.48.49:3002",
|
||||||
|
wsUrl: "ws://172.16.48.49:3002/ws",
|
||||||
|
connectTimeout: 30_000,
|
||||||
|
receiveTimeout: 60_000,
|
||||||
|
sendTimeout: 30_000,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(["test", "production"])(
|
||||||
|
"requires explicit service URLs in %s",
|
||||||
|
(appEnv) => {
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_APP_ENV", appEnv);
|
||||||
|
unsetConfigEnv();
|
||||||
|
|
||||||
|
expect(() => getApiConfig()).toThrow(
|
||||||
|
`[ApiConfig] Invalid ${appEnv} configuration`,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("parses an explicit non-development configuration", () => {
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "https://api.example.test");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "wss://api.example.test/ws");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_CONNECT_TIMEOUT", "1000");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_RECEIVE_TIMEOUT", "2000");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_SEND_TIMEOUT", "3000");
|
||||||
|
|
||||||
|
expect(getApiConfig()).toEqual({
|
||||||
|
baseUrl: "https://api.example.test",
|
||||||
|
wsUrl: "wss://api.example.test/ws",
|
||||||
|
connectTimeout: 1000,
|
||||||
|
receiveTimeout: 2000,
|
||||||
|
sendTimeout: 3000,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(["not-a-number", "0", "-1", "1.5"])(
|
||||||
|
"rejects invalid timeout %s",
|
||||||
|
(timeout) => {
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "test");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "https://api.example.test");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "wss://api.example.test/ws");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_CONNECT_TIMEOUT", timeout);
|
||||||
|
|
||||||
|
expect(() => getApiConfig()).toThrow(/connectTimeout/);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("rejects URLs with the wrong protocol", () => {
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_API_BASE_URL", "ftp://api.example.test");
|
||||||
|
vi.stubEnv("NEXT_PUBLIC_WS_BASE_URL", "https://api.example.test/ws");
|
||||||
|
|
||||||
|
expect(() => getApiConfig()).toThrow(/baseUrl.*wsUrl/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function unsetConfigEnv(): void {
|
||||||
|
for (const key of CONFIG_ENV_KEYS) vi.stubEnv(key, undefined);
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
* 通过环境变量配置后端服务地址与超时时间。
|
* 通过环境变量配置后端服务地址与超时时间。
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
import { AppEnvUtil, type AppEnv } from "@/utils/app-env";
|
import { AppEnvUtil, type AppEnv } from "@/utils/app-env";
|
||||||
|
|
||||||
export type { AppEnv };
|
export type { AppEnv };
|
||||||
@@ -30,6 +32,29 @@ export class TimeoutConstants {
|
|||||||
static readonly longTimeout = 60000;
|
static readonly longTimeout = 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEVELOPMENT_API_BASE_URL = "http://172.16.48.49:3002";
|
||||||
|
const DEVELOPMENT_WS_BASE_URL = "ws://172.16.48.49:3002/ws";
|
||||||
|
|
||||||
|
const ApiConfigSchema = z.object({
|
||||||
|
baseUrl: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1)
|
||||||
|
.refine((value) => hasProtocol(value, ["http:", "https:"]), {
|
||||||
|
message: "must be an http(s) URL",
|
||||||
|
}),
|
||||||
|
wsUrl: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1)
|
||||||
|
.refine((value) => hasProtocol(value, ["ws:", "wss:"]), {
|
||||||
|
message: "must be a ws(s) URL",
|
||||||
|
}),
|
||||||
|
connectTimeout: z.coerce.number().int().positive(),
|
||||||
|
receiveTimeout: z.coerce.number().int().positive(),
|
||||||
|
sendTimeout: z.coerce.number().int().positive(),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析当前环境
|
* 解析当前环境
|
||||||
*/
|
*/
|
||||||
@@ -41,29 +66,40 @@ export function getAppEnv(): AppEnv {
|
|||||||
* 获取当前 API 配置
|
* 获取当前 API 配置
|
||||||
*/
|
*/
|
||||||
export function getApiConfig(): ApiConfig {
|
export function getApiConfig(): ApiConfig {
|
||||||
const baseUrl =
|
const appEnv = getAppEnv();
|
||||||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://172.16.48.49:3002";
|
const allowDevelopmentDefaults = appEnv === "development";
|
||||||
const wsUrl =
|
const result = ApiConfigSchema.safeParse({
|
||||||
process.env.NEXT_PUBLIC_WS_BASE_URL ?? "ws://172.16.48.49:3002/ws";
|
baseUrl:
|
||||||
|
process.env.NEXT_PUBLIC_API_BASE_URL ??
|
||||||
|
(allowDevelopmentDefaults ? DEVELOPMENT_API_BASE_URL : undefined),
|
||||||
|
wsUrl:
|
||||||
|
process.env.NEXT_PUBLIC_WS_BASE_URL ??
|
||||||
|
(allowDevelopmentDefaults ? DEVELOPMENT_WS_BASE_URL : undefined),
|
||||||
|
connectTimeout:
|
||||||
|
process.env.NEXT_PUBLIC_API_CONNECT_TIMEOUT ??
|
||||||
|
TimeoutConstants.shortTimeout,
|
||||||
|
receiveTimeout:
|
||||||
|
process.env.NEXT_PUBLIC_API_RECEIVE_TIMEOUT ??
|
||||||
|
TimeoutConstants.longTimeout,
|
||||||
|
sendTimeout:
|
||||||
|
process.env.NEXT_PUBLIC_API_SEND_TIMEOUT ??
|
||||||
|
TimeoutConstants.shortTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
const connectTimeout = Number.parseInt(
|
if (!result.success) {
|
||||||
process.env.NEXT_PUBLIC_API_CONNECT_TIMEOUT ?? "30000",
|
const issues = result.error.issues
|
||||||
10
|
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||||
);
|
.join("; ");
|
||||||
const receiveTimeout = Number.parseInt(
|
throw new Error(`[ApiConfig] Invalid ${appEnv} configuration: ${issues}`);
|
||||||
process.env.NEXT_PUBLIC_API_RECEIVE_TIMEOUT ?? "60000",
|
}
|
||||||
10
|
|
||||||
);
|
|
||||||
const sendTimeout = Number.parseInt(
|
|
||||||
process.env.NEXT_PUBLIC_API_SEND_TIMEOUT ?? "30000",
|
|
||||||
10
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return result.data;
|
||||||
baseUrl,
|
}
|
||||||
wsUrl,
|
|
||||||
connectTimeout,
|
function hasProtocol(value: string, protocols: readonly string[]): boolean {
|
||||||
receiveTimeout,
|
try {
|
||||||
sendTimeout,
|
return protocols.includes(new URL(value).protocol);
|
||||||
};
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,4 +112,27 @@ describe("AuthRepository facebook identity", () => {
|
|||||||
expect(storage.setDeviceId).toHaveBeenCalledWith("device-1");
|
expect(storage.setDeviceId).toHaveBeenCalledWith("device-1");
|
||||||
expect(userStorage.setUserId).toHaveBeenCalledWith("guest-1");
|
expect(userStorage.setUserId).toHaveBeenCalledWith("guest-1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not report guest psid login success when session persistence fails", async () => {
|
||||||
|
const storageError = new Error("guest token write failed");
|
||||||
|
const facebookPsidLogin = vi.fn(async () =>
|
||||||
|
FacebookPsidLoginResponse.fromJson({
|
||||||
|
token: "guest-token",
|
||||||
|
matchedBy: "psid_incomplete",
|
||||||
|
fbPsid: "psid-1",
|
||||||
|
hasCompleteFacebookIdentity: false,
|
||||||
|
isGuest: true,
|
||||||
|
userId: "guest-1",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const { repository, storage } = createRepository({ facebookPsidLogin });
|
||||||
|
vi.mocked(storage.setGuestToken).mockResolvedValueOnce(
|
||||||
|
Result.err(storageError),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await repository.facebookPsidLogin({ psid: "psid-1" });
|
||||||
|
|
||||||
|
expect(Result.isErr(result)).toBe(true);
|
||||||
|
expect(storage.setLoginProvider).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
GuestLoginResponse,
|
GuestLoginResponse,
|
||||||
|
LoginResponse,
|
||||||
|
LoginStatus,
|
||||||
RefreshTokenResponse,
|
RefreshTokenResponse,
|
||||||
} from "@/data/dto/auth";
|
} from "@/data/dto/auth";
|
||||||
import { AuthRepository } from "@/data/repositories/auth_repository";
|
import { AuthRepository } from "@/data/repositories/auth_repository";
|
||||||
@@ -27,6 +29,7 @@ function createRepository(input: {
|
|||||||
...input.storage,
|
...input.storage,
|
||||||
} as unknown as IAuthStorage;
|
} as unknown as IAuthStorage;
|
||||||
const userStorage = {
|
const userStorage = {
|
||||||
|
setUser: vi.fn(async () => Result.ok(undefined)),
|
||||||
setUserId: vi.fn(async () => Result.ok(undefined)),
|
setUserId: vi.fn(async () => Result.ok(undefined)),
|
||||||
clearUserData: vi.fn(async () => Result.ok(undefined)),
|
clearUserData: vi.fn(async () => Result.ok(undefined)),
|
||||||
...input.userStorage,
|
...input.userStorage,
|
||||||
@@ -49,6 +52,12 @@ afterEach(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("AuthRepository session Result handling", () => {
|
describe("AuthRepository session Result handling", () => {
|
||||||
|
const loginResponse = LoginResponse.from({
|
||||||
|
token: "login-token",
|
||||||
|
refreshToken: "refresh-token",
|
||||||
|
user: { id: "user-1", username: "Elio" },
|
||||||
|
});
|
||||||
|
|
||||||
it("returns a failed auth cleanup Result while still attempting user cleanup", async () => {
|
it("returns a failed auth cleanup Result while still attempting user cleanup", async () => {
|
||||||
const clearError = new Error("auth cleanup failed");
|
const clearError = new Error("auth cleanup failed");
|
||||||
const { repository, userStorage } = createRepository({
|
const { repository, userStorage } = createRepository({
|
||||||
@@ -149,4 +158,83 @@ describe("AuthRepository session Result handling", () => {
|
|||||||
);
|
);
|
||||||
expect(storage.setLoginProvider).not.toHaveBeenCalled();
|
expect(storage.setLoginProvider).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not report email login success when the login token cannot be stored", async () => {
|
||||||
|
const storageError = new Error("login token write failed");
|
||||||
|
const { repository, storage, userStorage } = createRepository({
|
||||||
|
api: { emailLogin: vi.fn(async () => loginResponse) },
|
||||||
|
storage: {
|
||||||
|
setLoginToken: vi.fn(async () => Result.err(storageError)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await repository.emailLogin({
|
||||||
|
email: "elio@example.test",
|
||||||
|
password: "password",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(Result.isErr(result)).toBe(true);
|
||||||
|
expect(Result.isErr(result) && result.error.message).toBe(
|
||||||
|
storageError.message,
|
||||||
|
);
|
||||||
|
expect(storage.setRefreshToken).not.toHaveBeenCalled();
|
||||||
|
expect(userStorage.setUserId).not.toHaveBeenCalled();
|
||||||
|
expect(storage.setLoginProvider).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("writes the provider only after all other session identity fields", async () => {
|
||||||
|
const storageError = new Error("user id write failed");
|
||||||
|
const { repository, storage, userStorage } = createRepository({
|
||||||
|
api: { emailLogin: vi.fn(async () => loginResponse) },
|
||||||
|
userStorage: {
|
||||||
|
setUserId: vi.fn(async () => Result.err(storageError)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await repository.emailLogin({
|
||||||
|
email: "elio@example.test",
|
||||||
|
password: "password",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(Result.isErr(result)).toBe(true);
|
||||||
|
expect(storage.setLoginToken).toHaveBeenCalledWith("login-token");
|
||||||
|
expect(storage.setRefreshToken).toHaveBeenCalledWith("refresh-token");
|
||||||
|
expect(userStorage.setUserId).toHaveBeenCalledWith("user-1");
|
||||||
|
expect(storage.setLoginProvider).not.toHaveBeenCalled();
|
||||||
|
expect(userStorage.setUser).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps login successful when the non-critical user cache fails", async () => {
|
||||||
|
const cacheError = new Error("user cache write failed");
|
||||||
|
const { repository, storage, userStorage } = createRepository({
|
||||||
|
api: { emailLogin: vi.fn(async () => loginResponse) },
|
||||||
|
userStorage: {
|
||||||
|
setUser: vi.fn(async () => Result.err(cacheError)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await repository.emailLogin({
|
||||||
|
email: "elio@example.test",
|
||||||
|
password: "password",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual(Result.ok(loginResponse));
|
||||||
|
expect(storage.setLoginProvider).toHaveBeenCalledWith(LoginStatus.Email);
|
||||||
|
expect(userStorage.setUser).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps a current-user response successful when its cache write throws", async () => {
|
||||||
|
const { repository } = createRepository({
|
||||||
|
api: { getCurrentUser: vi.fn(async () => loginResponse.user) },
|
||||||
|
userStorage: {
|
||||||
|
setUser: vi.fn(async () => {
|
||||||
|
throw new Error("storage unavailable");
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await repository.getCurrentUser();
|
||||||
|
|
||||||
|
expect(result).toEqual(Result.ok(loginResponse.user));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -284,15 +284,21 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (data.isGuest || !data.hasCompleteFacebookIdentity) {
|
if (data.isGuest || !data.hasCompleteFacebookIdentity) {
|
||||||
await this.storage.setGuestToken(data.token);
|
const tokenResult = await this.storage.setGuestToken(data.token);
|
||||||
await this.storage.setLoginProvider(LoginStatus.Guest);
|
if (Result.isErr(tokenResult)) throw tokenResult.error;
|
||||||
if (input.deviceId) {
|
if (input.deviceId) {
|
||||||
await this.storage.setDeviceId(input.deviceId);
|
const deviceResult = await this.storage.setDeviceId(input.deviceId);
|
||||||
|
if (Result.isErr(deviceResult)) throw deviceResult.error;
|
||||||
}
|
}
|
||||||
const userId = data.userId || data.user?.id || "";
|
const userId = data.userId || data.user?.id || "";
|
||||||
if (userId) {
|
if (userId) {
|
||||||
await this.userStorage.setUserId(userId);
|
const userIdResult = await this.userStorage.setUserId(userId);
|
||||||
|
if (Result.isErr(userIdResult)) throw userIdResult.error;
|
||||||
}
|
}
|
||||||
|
const providerResult = await this.storage.setLoginProvider(
|
||||||
|
LoginStatus.Guest,
|
||||||
|
);
|
||||||
|
if (Result.isErr(providerResult)) throw providerResult.error;
|
||||||
return LoginStatus.Guest;
|
return LoginStatus.Guest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,13 +351,7 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
async getCurrentUser(): Promise<Result<User>> {
|
async getCurrentUser(): Promise<Result<User>> {
|
||||||
return Result.wrap(async () => {
|
return Result.wrap(async () => {
|
||||||
const user = await this.api.getCurrentUser();
|
const user = await this.api.getCurrentUser();
|
||||||
const writeResult = await this.userStorage.setUser(user.toJson());
|
await this._cacheUser(user);
|
||||||
if (!writeResult.success) {
|
|
||||||
log.warn(
|
|
||||||
"[AuthRepository] failed to cache current user",
|
|
||||||
writeResult.error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -360,7 +360,7 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 社交登录的公共包装:调 API → 调 `_saveLoginData` 持久化。
|
* 社交登录的公共包装:调 API → 调 `_saveLoginData` 持久化。
|
||||||
* `_saveLoginData` 内部全部 best-effort,存储写失败不抛错。
|
* 会话关键数据写入失败时,登录 Result 必须失败。
|
||||||
*/
|
*/
|
||||||
private async _socialLogin(
|
private async _socialLogin(
|
||||||
provider: LoginStatusT,
|
provider: LoginStatusT,
|
||||||
@@ -374,35 +374,42 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 持久化登录态:login token → refresh token → User 对象 → userId。
|
* 持久化登录态:login token → refresh token → userId → provider。
|
||||||
* 全部 best-effort,错误用 `Logger.warn` 记录但不让登录「失败」——
|
* 这些字段共同决定会话是否可恢复,任一写入失败都会让登录 Result 失败;
|
||||||
* 调用方已经从 API 拿到了 LoginResponse,缓存只是离线加速。
|
* provider 最后写入,作为会话完成标记。完整 User 对象仅用于离线展示,
|
||||||
|
* 缓存失败只记录告警,不影响已经建立的会话。
|
||||||
*/
|
*/
|
||||||
private async _saveLoginData(
|
private async _saveLoginData(
|
||||||
data: LoginResponse,
|
data: LoginResponse,
|
||||||
provider: LoginStatusT,
|
provider: LoginStatusT,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const r1 = await this.storage.setLoginToken(data.token);
|
const tokenResult = await this.storage.setLoginToken(data.token);
|
||||||
if (!r1.success) {
|
if (Result.isErr(tokenResult)) throw tokenResult.error;
|
||||||
log.warn("[AuthRepository] setLoginToken failed", r1.error);
|
|
||||||
}
|
|
||||||
const providerResult = await this.storage.setLoginProvider(provider);
|
|
||||||
if (!providerResult.success) {
|
|
||||||
log.warn("[AuthRepository] setLoginProvider failed", providerResult.error);
|
|
||||||
}
|
|
||||||
if (data.refreshToken) {
|
if (data.refreshToken) {
|
||||||
const r2 = await this.storage.setRefreshToken(data.refreshToken);
|
const refreshTokenResult = await this.storage.setRefreshToken(
|
||||||
if (!r2.success) {
|
data.refreshToken,
|
||||||
log.warn("[AuthRepository] setRefreshToken failed", r2.error);
|
);
|
||||||
|
if (Result.isErr(refreshTokenResult)) throw refreshTokenResult.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userIdResult = await this.userStorage.setUserId(data.user.id);
|
||||||
|
if (Result.isErr(userIdResult)) throw userIdResult.error;
|
||||||
|
|
||||||
|
const providerResult = await this.storage.setLoginProvider(provider);
|
||||||
|
if (Result.isErr(providerResult)) throw providerResult.error;
|
||||||
|
|
||||||
|
await this._cacheUser(data.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _cacheUser(user: User): Promise<void> {
|
||||||
|
try {
|
||||||
|
const userResult = await this.userStorage.setUser(user.toJson());
|
||||||
|
if (Result.isErr(userResult)) {
|
||||||
|
log.warn("[AuthRepository] setUser failed", userResult.error);
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
const r3 = await this.userStorage.setUser(data.user.toJson());
|
log.warn("[AuthRepository] setUser threw", error);
|
||||||
if (!r3.success) {
|
|
||||||
log.warn("[AuthRepository] setUser failed", r3.error);
|
|
||||||
}
|
|
||||||
const r4 = await this.userStorage.setUserId(data.user.id);
|
|
||||||
if (!r4.success) {
|
|
||||||
log.warn("[AuthRepository] setUserId failed", r4.error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user