From cb37233681162a0d2b09f31453def5f85ff16ac2 Mon Sep 17 00:00:00 2001 From: xKairu Date: Sat, 20 Jan 2024 03:37:07 +1300 Subject: [PATCH] refactor --- package.json | 43 ++- pnpm-lock.yaml | 633 ++++++++++++++++++++++++------------ src/api/artists.ts | 43 --- src/api/auth.ts | 43 --- src/api/news.ts | 97 ------ src/api/user.ts | 41 --- src/apis/artist.ts | 77 +++++ src/apis/auth.ts | 65 ++++ src/apis/news.ts | 140 ++++++++ src/{api => apis}/season.ts | 23 +- src/apis/user.ts | 60 ++++ src/client.ts | 73 +++++ src/config.ts | 11 + src/cosmo.ts | 78 ----- src/error.ts | 14 - src/errors.ts | 15 + src/index.ts | 3 +- src/interface.ts | 73 ----- src/router.ts | 119 ------- src/types.ts | 27 -- tests/artist.spec.ts | 21 ++ tests/artists.spec.ts | 15 - tests/auth.spec.ts | 38 ++- tests/mocks.ts | 162 +++++++-- tests/news.spec.ts | 49 ++- tests/season.spec.ts | 19 +- tests/user.spec.ts | 45 +-- tsconfig.json | 10 + tsup.config.ts | 11 + vite.config.ts | 10 + vitest.config.ts | 7 - 31 files changed, 1194 insertions(+), 871 deletions(-) delete mode 100644 src/api/artists.ts delete mode 100644 src/api/auth.ts delete mode 100644 src/api/news.ts delete mode 100644 src/api/user.ts create mode 100644 src/apis/artist.ts create mode 100644 src/apis/auth.ts create mode 100644 src/apis/news.ts rename src/{api => apis}/season.ts (51%) create mode 100644 src/apis/user.ts create mode 100644 src/client.ts create mode 100644 src/config.ts delete mode 100644 src/cosmo.ts delete mode 100644 src/error.ts create mode 100644 src/errors.ts delete mode 100644 src/interface.ts delete mode 100644 src/router.ts delete mode 100644 src/types.ts create mode 100644 tests/artist.spec.ts delete mode 100644 tests/artists.spec.ts create mode 100644 tsconfig.json create mode 100644 tsup.config.ts create mode 100644 vite.config.ts delete mode 100644 vitest.config.ts diff --git a/package.json b/package.json index a341ccd..05c0bc6 100644 --- a/package.json +++ b/package.json @@ -2,22 +2,43 @@ "name": "cosmo-ts", "version": "1.0.0", "description": "TypeScript library for interfacing with the Cosmo app API.", - "main": "index.js", "scripts": { - "dev": "tsup src/index.ts --watch --onSuccess 'node dist/index.js'", - "build": "tsup src/index.ts", - "test": "vitest" + "dev": "tsup --watch --clean=false", + "build": "tsup", + "test": "vitest", + "test:watch": "vitest watch" }, "keywords": [], "author": "", "license": "MIT", + "repository": "teamreflex/cosmo-ts", "devDependencies": { - "msw": "^2.0.8", - "tsup": "^7.2.0", - "typescript": "^5.2.2", - "vitest": "^0.34.5" + "@types/node": "^20.11.5", + "msw": "^2.1.2", + "tsup": "^8.0.1", + "typescript": "^5.3.3", + "vite": "^5.0.11", + "vitest": "^1.2.1" }, - "dependencies": { - "untypeable": "^0.2.1" - } + "type": "module", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": { + "node": "./dist/index.js", + "default": "./dist/index.js" + }, + "require": { + "node": "./dist/index.cjs", + "default": "./dist/index.cjs" + } + } + }, + "files": [ + "dist", + "README.md" + ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4fd648a..b726cb7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,24 +4,25 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - untypeable: - specifier: ^0.2.1 - version: 0.2.1 - devDependencies: + '@types/node': + specifier: ^20.11.5 + version: 20.11.5 msw: - specifier: ^2.0.8 - version: 2.0.8(typescript@5.2.2) + specifier: ^2.1.2 + version: 2.1.2(typescript@5.3.3) tsup: - specifier: ^7.2.0 - version: 7.2.0(typescript@5.2.2) + specifier: ^8.0.1 + version: 8.0.1(typescript@5.3.3) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 + vite: + specifier: ^5.0.11 + version: 5.0.11(@types/node@20.11.5) vitest: - specifier: ^0.34.5 - version: 0.34.5 + specifier: ^1.2.1 + version: 1.2.1(@types/node@20.11.5) packages: @@ -43,8 +44,17 @@ packages: statuses: 2.0.1 dev: true - /@esbuild/android-arm64@0.18.20: - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + /@esbuild/aix-ppc64@0.19.11: + resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.11: + resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -52,8 +62,8 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.18.20: - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + /@esbuild/android-arm@0.19.11: + resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -61,8 +71,8 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.18.20: - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + /@esbuild/android-x64@0.19.11: + resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -70,8 +80,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.18.20: - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + /@esbuild/darwin-arm64@0.19.11: + resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -79,8 +89,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.18.20: - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + /@esbuild/darwin-x64@0.19.11: + resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -88,8 +98,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.18.20: - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + /@esbuild/freebsd-arm64@0.19.11: + resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -97,8 +107,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.18.20: - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + /@esbuild/freebsd-x64@0.19.11: + resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -106,8 +116,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.18.20: - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + /@esbuild/linux-arm64@0.19.11: + resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -115,8 +125,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.18.20: - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + /@esbuild/linux-arm@0.19.11: + resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -124,8 +134,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.18.20: - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + /@esbuild/linux-ia32@0.19.11: + resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -133,8 +143,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.18.20: - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + /@esbuild/linux-loong64@0.19.11: + resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -142,8 +152,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.18.20: - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + /@esbuild/linux-mips64el@0.19.11: + resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -151,8 +161,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.18.20: - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + /@esbuild/linux-ppc64@0.19.11: + resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -160,8 +170,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.18.20: - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + /@esbuild/linux-riscv64@0.19.11: + resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -169,8 +179,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.18.20: - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + /@esbuild/linux-s390x@0.19.11: + resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -178,8 +188,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + /@esbuild/linux-x64@0.19.11: + resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -187,8 +197,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.18.20: - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + /@esbuild/netbsd-x64@0.19.11: + resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -196,8 +206,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.18.20: - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + /@esbuild/openbsd-x64@0.19.11: + resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -205,8 +215,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.18.20: - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + /@esbuild/sunos-x64@0.19.11: + resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -214,8 +224,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.18.20: - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + /@esbuild/win32-arm64@0.19.11: + resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -223,8 +233,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.18.20: - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + /@esbuild/win32-ia32@0.19.11: + resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -232,8 +242,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.18.20: - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + /@esbuild/win32-x64@0.19.11: + resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -283,15 +293,15 @@ packages: engines: {node: '>=18'} dev: true - /@mswjs/interceptors@0.25.12: - resolution: {integrity: sha512-a+zyoR01cPQeukSmaDEkE6aMwSjjfcT5ILzsyxmctEeCePnc2DMOd0X8Fn9bytq1IsAfMxJf/lu2aTfdivDbRg==} + /@mswjs/interceptors@0.25.14: + resolution: {integrity: sha512-2dnIxl+obqIqjoPXTFldhe6pcdOrqiz+GcLaQQ6hmL02OldAF7nIC+rUgTWm+iF6lvmyCVhFFqbgbapNhR8eag==} engines: {node: '>=18'} dependencies: '@open-draft/deferred-promise': 2.2.0 '@open-draft/logger': 0.3.0 '@open-draft/until': 2.1.0 is-node-process: 1.2.0 - outvariant: 1.4.0 + outvariant: 1.4.2 strict-event-emitter: 0.5.1 dev: true @@ -324,83 +334,184 @@ packages: resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} dependencies: is-node-process: 1.2.0 - outvariant: 1.4.0 + outvariant: 1.4.2 dev: true /@open-draft/until@2.1.0: resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} dev: true - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + /@rollup/rollup-android-arm-eabi@4.9.5: + resolution: {integrity: sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==} + cpu: [arm] + os: [android] + requiresBuild: true dev: true + optional: true - /@types/chai-subset@1.3.3: - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} - dependencies: - '@types/chai': 4.3.6 + /@rollup/rollup-android-arm64@4.9.5: + resolution: {integrity: sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.9.5: + resolution: {integrity: sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.9.5: + resolution: {integrity: sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.9.5: + resolution: {integrity: sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.9.5: + resolution: {integrity: sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.9.5: + resolution: {integrity: sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.9.5: + resolution: {integrity: sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.9.5: + resolution: {integrity: sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.9.5: + resolution: {integrity: sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.9.5: + resolution: {integrity: sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.9.5: + resolution: {integrity: sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==} + cpu: [ia32] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/chai@4.3.6: - resolution: {integrity: sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==} + /@rollup/rollup-win32-x64-msvc@4.9.5: + resolution: {integrity: sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==} + cpu: [x64] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/cookie@0.4.1: - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true /@types/js-levenshtein@1.1.3: resolution: {integrity: sha512-jd+Q+sD20Qfu9e2aEXogiO3vpOC1PYJOUdyN9gvs4Qrvkg4wF43L5OhqrPeokdv8TL0/mXoYfpkcoGZMNN2pkQ==} dev: true - /@types/node@20.7.0: - resolution: {integrity: sha512-zI22/pJW2wUZOVyguFaUL1HABdmSVxpXrzIqkjsHmyUjNhPoWM1CKfvVuXfetHhIok4RY573cqS0mZ1SJEnoTg==} + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + dependencies: + undici-types: 5.26.5 dev: true /@types/statuses@2.0.4: resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==} dev: true - /@vitest/expect@0.34.5: - resolution: {integrity: sha512-/3RBIV9XEH+nRpRMqDJBufKIOQaYUH2X6bt0rKSCW0MfKhXFLYsR5ivHifeajRSTsln0FwJbitxLKHSQz/Xwkw==} + /@vitest/expect@1.2.1: + resolution: {integrity: sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ==} dependencies: - '@vitest/spy': 0.34.5 - '@vitest/utils': 0.34.5 - chai: 4.3.8 + '@vitest/spy': 1.2.1 + '@vitest/utils': 1.2.1 + chai: 4.4.1 dev: true - /@vitest/runner@0.34.5: - resolution: {integrity: sha512-RDEE3ViVvl7jFSCbnBRyYuu23XxmvRTSZWW6W4M7eC5dOsK75d5LIf6uhE5Fqf809DQ1+9ICZZNxhIolWHU4og==} + /@vitest/runner@1.2.1: + resolution: {integrity: sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ==} dependencies: - '@vitest/utils': 0.34.5 - p-limit: 4.0.0 + '@vitest/utils': 1.2.1 + p-limit: 5.0.0 pathe: 1.1.1 dev: true - /@vitest/snapshot@0.34.5: - resolution: {integrity: sha512-+ikwSbhu6z2yOdtKmk/aeoDZ9QPm2g/ZO5rXT58RR9Vmu/kB2MamyDSx77dctqdZfP3Diqv4mbc/yw2kPT8rmA==} + /@vitest/snapshot@1.2.1: + resolution: {integrity: sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==} dependencies: - magic-string: 0.30.3 + magic-string: 0.30.5 pathe: 1.1.1 pretty-format: 29.7.0 dev: true - /@vitest/spy@0.34.5: - resolution: {integrity: sha512-epsicsfhvBjRjCMOC/3k00mP/TBGQy8/P0DxOFiWyLt55gnZ99dqCfCiAsKO17BWVjn4eZRIjKvcqNmSz8gvmg==} + /@vitest/spy@1.2.1: + resolution: {integrity: sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ==} dependencies: - tinyspy: 2.1.1 + tinyspy: 2.2.0 dev: true - /@vitest/utils@0.34.5: - resolution: {integrity: sha512-ur6CmmYQoeHMwmGb0v+qwkwN3yopZuZyf4xt1DBBSGBed8Hf9Gmbm/5dEWqgpLPdRx6Av6jcWXrjcKfkTzg/pw==} + /@vitest/utils@1.2.1: + resolution: {integrity: sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg==} dependencies: diff-sequences: 29.6.3 - loupe: 2.3.6 + estree-walker: 3.0.3 + loupe: 2.3.7 pretty-format: 29.7.0 dev: true - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} dev: true @@ -497,13 +608,13 @@ packages: ieee754: 1.2.1 dev: true - /bundle-require@4.0.2(esbuild@0.18.20): + /bundle-require@4.0.2(esbuild@0.19.11): resolution: {integrity: sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: esbuild: '>=0.17' dependencies: - esbuild: 0.18.20 + esbuild: 0.19.11 load-tsconfig: 0.2.5 dev: true @@ -512,12 +623,12 @@ packages: engines: {node: '>=8'} dev: true - /chai@4.3.8: - resolution: {integrity: sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==} + /chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} engines: {node: '>=4'} dependencies: assertion-error: 1.1.0 - check-error: 1.0.2 + check-error: 1.0.3 deep-eql: 4.1.3 get-func-name: 2.0.2 loupe: 2.3.6 @@ -537,8 +648,10 @@ packages: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true - /check-error@1.0.2: - resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 dev: true /chokidar@3.5.3: @@ -662,34 +775,35 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true - /esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + /esbuild@0.19.11: + resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 + '@esbuild/aix-ppc64': 0.19.11 + '@esbuild/android-arm': 0.19.11 + '@esbuild/android-arm64': 0.19.11 + '@esbuild/android-x64': 0.19.11 + '@esbuild/darwin-arm64': 0.19.11 + '@esbuild/darwin-x64': 0.19.11 + '@esbuild/freebsd-arm64': 0.19.11 + '@esbuild/freebsd-x64': 0.19.11 + '@esbuild/linux-arm': 0.19.11 + '@esbuild/linux-arm64': 0.19.11 + '@esbuild/linux-ia32': 0.19.11 + '@esbuild/linux-loong64': 0.19.11 + '@esbuild/linux-mips64el': 0.19.11 + '@esbuild/linux-ppc64': 0.19.11 + '@esbuild/linux-riscv64': 0.19.11 + '@esbuild/linux-s390x': 0.19.11 + '@esbuild/linux-x64': 0.19.11 + '@esbuild/netbsd-x64': 0.19.11 + '@esbuild/openbsd-x64': 0.19.11 + '@esbuild/sunos-x64': 0.19.11 + '@esbuild/win32-arm64': 0.19.11 + '@esbuild/win32-ia32': 0.19.11 + '@esbuild/win32-x64': 0.19.11 dev: true /escalade@3.1.1: @@ -702,6 +816,12 @@ packages: engines: {node: '>=0.8.0'} dev: true + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: true + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -717,6 +837,21 @@ packages: strip-final-newline: 2.0.0 dev: true + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.2.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -783,6 +918,11 @@ packages: engines: {node: '>=10'} dev: true + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -832,6 +972,11 @@ packages: engines: {node: '>=10.17.0'} dev: true + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -923,6 +1068,11 @@ packages: engines: {node: '>=8'} dev: true + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -960,9 +1110,12 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true - /local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} engines: {node: '>=14'} + dependencies: + mlly: 1.4.2 + pkg-types: 1.0.3 dev: true /lodash.sortby@4.7.0: @@ -983,12 +1136,19 @@ packages: /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 + dependencies: + get-func-name: 2.0.2 + dev: true + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: get-func-name: 2.0.2 dev: true - /magic-string@0.30.3: - resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==} + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 @@ -1016,6 +1176,11 @@ packages: engines: {node: '>=6'} dev: true + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -1035,13 +1200,13 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /msw@2.0.8(typescript@5.2.2): - resolution: {integrity: sha512-/5nQCotVka62lvubQ3tMfUS3TukyeBwvWyvAthcXvDlXGhkA/85HlEwZyFlJ3ZsPW45Ty+ao0S4oFvuM12R/kA==} + /msw@2.1.2(typescript@5.3.3): + resolution: {integrity: sha512-7OKbeZNFQTCPFe++o+zZHMkQRIUi4D/5N1dAD3lOlaV+2Wpv3Srp3VFrFeH+2ftZJbb4jAiC0caZoW1efr80KQ==} engines: {node: '>=18'} hasBin: true requiresBuild: true peerDependencies: - typescript: '>= 4.7.x <= 5.2.x' + typescript: '>= 4.7.x <= 5.3.x' peerDependenciesMeta: typescript: optional: true @@ -1050,9 +1215,9 @@ packages: '@bundled-es-modules/js-levenshtein': 2.0.1 '@bundled-es-modules/statuses': 1.0.1 '@mswjs/cookies': 1.1.0 - '@mswjs/interceptors': 0.25.12 + '@mswjs/interceptors': 0.25.14 '@open-draft/until': 2.1.0 - '@types/cookie': 0.4.1 + '@types/cookie': 0.6.0 '@types/js-levenshtein': 1.1.3 '@types/statuses': 2.0.4 chalk: 4.1.2 @@ -1062,11 +1227,11 @@ packages: inquirer: 8.2.6 is-node-process: 1.2.0 js-levenshtein: 1.1.6 - outvariant: 1.4.0 + outvariant: 1.4.2 path-to-regexp: 6.2.1 strict-event-emitter: 0.5.1 - type-fest: 2.19.0 - typescript: 5.2.2 + type-fest: 4.9.0 + typescript: 5.3.3 yargs: 17.7.2 dev: true @@ -1082,8 +1247,8 @@ packages: thenify-all: 1.6.0 dev: true - /nanoid@3.3.6: - resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: true @@ -1100,6 +1265,13 @@ packages: path-key: 3.1.1 dev: true + /npm-run-path@5.2.0: + resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1118,6 +1290,13 @@ packages: mimic-fn: 2.1.0 dev: true + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -1138,13 +1317,13 @@ packages: engines: {node: '>=0.10.0'} dev: true - /outvariant@1.4.0: - resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + /outvariant@1.4.2: + resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==} dev: true - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} dependencies: yocto-queue: 1.0.0 dev: true @@ -1159,6 +1338,11 @@ packages: engines: {node: '>=8'} dev: true + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + /path-to-regexp@6.2.1: resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} dev: true @@ -1214,11 +1398,11 @@ packages: yaml: 2.3.2 dev: true - /postcss@8.4.30: - resolution: {integrity: sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==} + /postcss@8.4.33: + resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.6 + nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.0.2 dev: true @@ -1284,11 +1468,26 @@ packages: engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true - /rollup@3.29.3: - resolution: {integrity: sha512-T7du6Hum8jOkSWetjRgbwpM6Sy0nECYrYRSmZjayFcOddtKJWU4d17AC3HNUk7HRuqy4p+G7aEZclSHytqUmEg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} + /rollup@4.9.5: + resolution: {integrity: sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + dependencies: + '@types/estree': 1.0.5 optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.9.5 + '@rollup/rollup-android-arm64': 4.9.5 + '@rollup/rollup-darwin-arm64': 4.9.5 + '@rollup/rollup-darwin-x64': 4.9.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.9.5 + '@rollup/rollup-linux-arm64-gnu': 4.9.5 + '@rollup/rollup-linux-arm64-musl': 4.9.5 + '@rollup/rollup-linux-riscv64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-musl': 4.9.5 + '@rollup/rollup-win32-arm64-msvc': 4.9.5 + '@rollup/rollup-win32-ia32-msvc': 4.9.5 + '@rollup/rollup-win32-x64-msvc': 4.9.5 fsevents: 2.3.3 dev: true @@ -1337,6 +1536,11 @@ packages: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -1363,8 +1567,8 @@ packages: engines: {node: '>= 0.8'} dev: true - /std-env@3.4.3: - resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==} + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} dev: true /strict-event-emitter@0.5.1: @@ -1398,6 +1602,11 @@ packages: engines: {node: '>=6'} dev: true + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + /strip-literal@1.3.0: resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} dependencies: @@ -1446,13 +1655,13 @@ packages: resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} dev: true - /tinypool@0.7.0: - resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} + /tinypool@0.8.2: + resolution: {integrity: sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==} engines: {node: '>=14.0.0'} dev: true - /tinyspy@2.1.1: - resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} engines: {node: '>=14.0.0'} dev: true @@ -1489,15 +1698,18 @@ packages: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true - /tsup@7.2.0(typescript@5.2.2): - resolution: {integrity: sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==} - engines: {node: '>=16.14'} + /tsup@8.0.1(typescript@5.3.3): + resolution: {integrity: sha512-hvW7gUSG96j53ZTSlT4j/KL0q1Q2l6TqGBFc6/mu/L46IoNWqLLUzLRLP1R8Q7xrJTmkDxxDoojV5uCVs1sVOg==} + engines: {node: '>=18'} hasBin: true peerDependencies: + '@microsoft/api-extractor': ^7.36.0 '@swc/core': ^1 postcss: ^8.4.12 - typescript: '>=4.1.0' + typescript: '>=4.5.0' peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true '@swc/core': optional: true postcss: @@ -1505,21 +1717,21 @@ packages: typescript: optional: true dependencies: - bundle-require: 4.0.2(esbuild@0.18.20) + bundle-require: 4.0.2(esbuild@0.19.11) cac: 6.7.14 chokidar: 3.5.3 debug: 4.3.4 - esbuild: 0.18.20 + esbuild: 0.19.11 execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 postcss-load-config: 4.0.1 resolve-from: 5.0.0 - rollup: 3.29.3 + rollup: 4.9.5 source-map: 0.8.0-beta.0 sucrase: 3.34.0 tree-kill: 1.2.2 - typescript: 5.2.2 + typescript: 5.3.3 transitivePeerDependencies: - supports-color - ts-node @@ -1535,13 +1747,13 @@ packages: engines: {node: '>=10'} dev: true - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} + /type-fest@4.9.0: + resolution: {integrity: sha512-KS/6lh/ynPGiHD/LnAobrEFq3Ad4pBzOlJ1wAnJx9N4EYoqFhMfLIBjUT2UEx4wg5ZE+cC1ob6DCSpppVo+rtg==} + engines: {node: '>=16'} dev: true - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true dev: true @@ -1550,25 +1762,24 @@ packages: resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==} dev: true - /untypeable@0.2.1: - resolution: {integrity: sha512-W+OJ8Ms6O27n6g/UjiZMtxEffC4j5xGwyCLu0p0gZoKQWFMwofbL3wKQC16fOQWv6BMNZRQ0my0+BegkyjurtQ==} - dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true - /vite-node@0.34.5(@types/node@20.7.0): - resolution: {integrity: sha512-RNZ+DwbCvDoI5CbCSQSyRyzDTfFvFauvMs6Yq4ObJROKlIKuat1KgSX/Ako5rlDMfVCyMcpMRMTkJBxd6z8YRA==} - engines: {node: '>=v14.18.0'} + /vite-node@1.2.1(@types/node@20.11.5): + resolution: {integrity: sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true dependencies: cac: 6.7.14 debug: 4.3.4 - mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.4.9(@types/node@20.7.0) + vite: 5.0.11(@types/node@20.11.5) transitivePeerDependencies: - '@types/node' - less @@ -1580,12 +1791,12 @@ packages: - terser dev: true - /vite@4.4.9(@types/node@20.7.0): - resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} - engines: {node: ^14.18.0 || >=16.0.0} + /vite@5.0.11(@types/node@20.11.5): + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - '@types/node': '>= 14' + '@types/node': ^18.0.0 || >=20.0.0 less: '*' lightningcss: ^1.21.0 sass: '*' @@ -1608,30 +1819,30 @@ packages: terser: optional: true dependencies: - '@types/node': 20.7.0 - esbuild: 0.18.20 - postcss: 8.4.30 - rollup: 3.29.3 + '@types/node': 20.11.5 + esbuild: 0.19.11 + postcss: 8.4.33 + rollup: 4.9.5 optionalDependencies: fsevents: 2.3.3 dev: true - /vitest@0.34.5: - resolution: {integrity: sha512-CPI68mmnr2DThSB3frSuE5RLm9wo5wU4fbDrDwWQQB1CWgq9jQVoQwnQSzYAjdoBOPoH2UtXpOgHVge/uScfZg==} - engines: {node: '>=v14.18.0'} + /vitest@1.2.1(@types/node@20.11.5): + resolution: {integrity: sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 happy-dom: '*' jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@types/node': + optional: true '@vitest/browser': optional: true '@vitest/ui': @@ -1640,36 +1851,28 @@ packages: optional: true jsdom: optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true dependencies: - '@types/chai': 4.3.6 - '@types/chai-subset': 1.3.3 - '@types/node': 20.7.0 - '@vitest/expect': 0.34.5 - '@vitest/runner': 0.34.5 - '@vitest/snapshot': 0.34.5 - '@vitest/spy': 0.34.5 - '@vitest/utils': 0.34.5 - acorn: 8.10.0 - acorn-walk: 8.2.0 + '@types/node': 20.11.5 + '@vitest/expect': 1.2.1 + '@vitest/runner': 1.2.1 + '@vitest/snapshot': 1.2.1 + '@vitest/spy': 1.2.1 + '@vitest/utils': 1.2.1 + acorn-walk: 8.3.2 cac: 6.7.14 - chai: 4.3.8 + chai: 4.4.1 debug: 4.3.4 - local-pkg: 0.4.3 - magic-string: 0.30.3 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.5 pathe: 1.1.1 picocolors: 1.0.0 - std-env: 3.4.3 + std-env: 3.7.0 strip-literal: 1.3.0 tinybench: 2.5.1 - tinypool: 0.7.0 - vite: 4.4.9(@types/node@20.7.0) - vite-node: 0.34.5(@types/node@20.7.0) + tinypool: 0.8.2 + vite: 5.0.11(@types/node@20.11.5) + vite-node: 1.2.1(@types/node@20.11.5) why-is-node-running: 2.2.2 transitivePeerDependencies: - less diff --git a/src/api/artists.ts b/src/api/artists.ts deleted file mode 100644 index 0e80c85..0000000 --- a/src/api/artists.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { initUntypeable } from "untypeable"; - -const u = initUntypeable().pushArg<"GET">(); -export const router = u.router({ - "/artist/v1": { - GET: u.output<{ artists: Artist[] }>(), - }, - - "/artist/v1/:artist": { - GET: u.input<{ artist: string }>().output<{ artist: ArtistWithMembers }>(), - }, -}); - -export const validArtists = ["artms", "tripleS"] as const; -export type ValidArtist = (typeof validArtists)[number]; - -export type Artist = { - name: string; - title: string; - logoImageUrl: string; - contracts: { - Como: string; - Objekt: string; - ObjektMinter: string; - Governor: string; - CommunityPool: string; - ComoMinter: string; - }; -}; - -export type Member = { - name: string; - artist: string; - units: string[]; - alias: string; - profileImageUrl: string; - mainObjektImageUrl: string; - order: number; -}; - -export type ArtistWithMembers = Artist & { - members: Member[]; -}; diff --git a/src/api/auth.ts b/src/api/auth.ts deleted file mode 100644 index f32c1ec..0000000 --- a/src/api/auth.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { initUntypeable } from "untypeable"; - -const u = initUntypeable().pushArg<"GET" | "POST">(); -export const router = u.router({ - "/auth/v1/signin": { - POST: u.input().output(), - }, - - "/auth/v1/refresh": { - POST: u.input().output(), - }, -}); - -export type LoginPayload = { - channel: "email"; - email: string; - accessToken: string; -}; - -export type LoginResult = { - user: { - id: number; - email: string; - nickname: string; - address: string; - profileImageUrl: string; - }; - credentials: { - accessToken: string; - refreshToken: string; - }; -}; - -export type RefreshPayload = { - refreshToken: string; -}; - -export type RefreshResult = { - credentials: { - refreshToken: string; - accessToken: string; - }; -}; diff --git a/src/api/news.ts b/src/api/news.ts deleted file mode 100644 index 21b0204..0000000 --- a/src/api/news.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { initUntypeable } from "untypeable"; -import { ValidArtist } from "./artists"; - -const u = initUntypeable().pushArg<"GET">(); -export const router = u.router({ - "/news/v1": { - GET: u.input<{ artist: ValidArtist }>().output(), - }, - - "/news/v1/feed": { - GET: u - .input() - .output>(), - }, - - "/news/v1/exclusive": { - GET: u - .input() - .output>(), - }, -}); - -export type NewsPayload = { - artist: ValidArtist; - start_after?: number; - limit?: number; -}; - -export type HomeNewsResult = { - sections: NewsSection[]; -}; - -export type NewsSectionBar = { - type: "bar"; - artist: ValidArtist; - contents: []; -}; - -export type NewsSectionBanner = { - type: "banner"; - artist: ValidArtist; - contents: NewsSectionBannerContent[]; -}; -export type NewsSectionBannerContent = { - id: number; - url: string; - createdAt: string; - label: "release" | "event" | "notice"; - order: number; - body: string; - imageUrl: string; -}; - -export type NewsSectionFeed = { - type: "feed"; - artist: ValidArtist; - title: string; - contents: NewsSectionFeedContent[]; -}; -export type NewsSectionFeedContent = { - id: number; - url: string; - createdAt: string; - artist: ValidArtist; - logoImageUrl: string; - body: string; - imageUrls: string[]; -}; - -export type NewsSectionExclusive = { - type: "exclusive"; - artist: ValidArtist; - title: string; - contents: NewsSectionExclusiveContent[]; -}; -export type NewsSectionExclusiveContent = { - id: number; - url: string; - createdAt: string; - title: string; - body: string; - thumbnailImageUrl: string; - nativeVideoUrl: string; -}; - -export type NewsSection = - | NewsSectionBar - | NewsSectionBanner - | NewsSectionFeed - | NewsSectionExclusive; - -export type NewsFeedResult = { - hasNext: boolean; - total: number; - nextStartAfter: string; - results: TPostType[]; -}; diff --git a/src/api/user.ts b/src/api/user.ts deleted file mode 100644 index 9daa6a1..0000000 --- a/src/api/user.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { initUntypeable } from "untypeable"; - -const u = initUntypeable().pushArg<"GET">(); -export const router = u.router({ - "/user/v1/me": { - GET: u.output<{ profile: User }>(), - }, - - "/user/v1/search": { - GET: u.input<{ query: string }>().output(), - }, -}); - -export type User = { - nickname: string; - address: string; - profileImageUrl: string; - artists: { - name: string; - title: string; - contracts: { - Como: string; - Objekt: string; - }; - assetBalance: { - totalComo: number; - totalObjekt: number; - }; - }[]; -}; - -export type SearchResponse = { - hasNext: boolean; - results: SearchResult[]; -}; - -export type SearchResult = { - nickname: string; - address: string; - profileImageUrl: string; -}; diff --git a/src/apis/artist.ts b/src/apis/artist.ts new file mode 100644 index 0000000..c14b83f --- /dev/null +++ b/src/apis/artist.ts @@ -0,0 +1,77 @@ +import { Config } from "../config"; +import { CosmoClient } from "../client"; + +export class ArtistAPI { + constructor(private config: Config) {} + + /** + * Get the list of artists available. + */ + async list(): Promise { + const response = await CosmoClient.request<{ + artists: Artist[]; + }>("/artist/v1", this.config); + + if (!response.artists) { + return []; + } + + return response.artists; + } + + /** + * Get a single artist. + */ + async get(artist: ValidArtist): Promise { + const response = await CosmoClient.request<{ + artist: ArtistWithMembers; + }>(`/artist/v1/${artist}`, this.config); + + if (!response.artist) { + throw new ArtistNotFoundError(artist); + } + + return response.artist; + } +} + +/** + * The list of artists available. + * + * `(string & {})` allows any string through while giving typesafety on known artists. + */ +export type ValidArtist = "tripleS" | "ARTMS" | (string & {}); + +export type Artist = { + name: string; + title: string; + logoImageUrl: string; + contracts: { + Como: string; + Objekt: string; + ObjektMinter: string; + Governor: string; + CommunityPool: string; + ComoMinter: string; + }; +}; + +export type Member = { + name: string; + artist: string; + units: string[]; + alias: string; + profileImageUrl: string; + mainObjektImageUrl: string; + order: number; +}; + +export type ArtistWithMembers = Artist & { + members: Member[]; +}; + +export class ArtistNotFoundError extends Error { + constructor(artist: string) { + super(`Artist not found: ${artist}`); + } +} diff --git a/src/apis/auth.ts b/src/apis/auth.ts new file mode 100644 index 0000000..1a23e94 --- /dev/null +++ b/src/apis/auth.ts @@ -0,0 +1,65 @@ +import { Config } from "../config"; +import { CosmoClient } from "../client"; + +export class AuthAPI { + constructor(private config: Config) {} + + /** + * Sign in with Ramper credentials. + */ + async signIn(payload: LoginPayload): Promise { + return await CosmoClient.request( + "/auth/v1/signin", + this.config, + { + method: "POST", + body: JSON.stringify(payload), + } + ); + } + + /** + * Refresh an access token. + */ + async refreshToken(payload: RefreshPayload): Promise { + return await CosmoClient.request( + "/auth/v1/refresh", + this.config, + { + method: "POST", + body: JSON.stringify(payload), + } + ); + } +} + +export type LoginPayload = { + channel: "email"; + email: string; + accessToken: string; +}; + +export type LoginResult = { + user: { + id: number; + email: string; + nickname: string; + address: string; + profileImageUrl: string; + }; + credentials: { + accessToken: string; + refreshToken: string; + }; +}; + +export type RefreshPayload = { + refreshToken: string; +}; + +export type RefreshResult = { + credentials: { + refreshToken: string; + accessToken: string; + }; +}; diff --git a/src/apis/news.ts b/src/apis/news.ts new file mode 100644 index 0000000..a74632a --- /dev/null +++ b/src/apis/news.ts @@ -0,0 +1,140 @@ +import { Config } from "../config"; +import { CosmoClient } from "../client"; +import { ValidArtist } from "./artist"; + +export class NewsAPI { + constructor(private config: Config) {} + + /** + * Get home page news sections for the given artist. + */ + async home(artist: ValidArtist): Promise { + return await CosmoClient.request<{ sections: NewsSection[] }>( + `/news/v1?artist=${artist}`, + this.config + ).then((res) => res.sections); + } + + /** + * Get the news feed for the given artist. + */ + async feed({ + artist, + startAfter, + limit, + }: NewsPayload): Promise> { + const params = new URLSearchParams({ + artist: artist, + }); + + if (startAfter) { + params.append("start_after", startAfter.toString()); + } + + if (limit) { + params.append("limit", limit.toString()); + } + + return await CosmoClient.request>( + `/news/v1/feed?${params.toString()}`, + this.config + ); + } + + /** + * Get the exclusive news feed for the given artist. + */ + async exclusive({ + artist, + startAfter, + limit, + }: NewsPayload): Promise> { + const params = new URLSearchParams({ + artist: artist, + }); + + if (startAfter) { + params.append("start_after", startAfter.toString()); + } + + if (limit) { + params.append("limit", limit.toString()); + } + + return await CosmoClient.request< + NewsFeedResult + >(`/news/v1/exclusive?${params.toString()}`, this.config); + } +} + +export type NewsPayload = { + artist: ValidArtist; + startAfter?: number; + limit?: number; +}; + +export type NewsSectionBar = { + type: "bar"; + artist: ValidArtist; + contents: []; +}; + +export type NewsSectionBanner = { + type: "banner"; + artist: ValidArtist; + contents: NewsSectionBannerContent[]; +}; +export type NewsSectionBannerContent = { + id: number; + url: string; + createdAt: string; + label: "release" | "event" | "notice"; + order: number; + body: string; + imageUrl: string; +}; + +export type NewsSectionFeed = { + type: "feed"; + artist: ValidArtist; + title: string; + contents: NewsSectionFeedContent[]; +}; +export type NewsSectionFeedContent = { + id: number; + url: string; + createdAt: string; + artist: ValidArtist; + logoImageUrl: string; + body: string; + imageUrls: string[]; +}; + +export type NewsSectionExclusive = { + type: "exclusive"; + artist: ValidArtist; + title: string; + contents: NewsSectionExclusiveContent[]; +}; +export type NewsSectionExclusiveContent = { + id: number; + url: string; + createdAt: string; + title: string; + body: string; + thumbnailImageUrl: string; + nativeVideoUrl: string; +}; + +export type NewsSection = + | NewsSectionBar + | NewsSectionBanner + | NewsSectionFeed + | NewsSectionExclusive; + +export type NewsFeedResult = { + hasNext: boolean; + total: number; + nextStartAfter: string; + results: TPostType[]; +}; diff --git a/src/api/season.ts b/src/apis/season.ts similarity index 51% rename from src/api/season.ts rename to src/apis/season.ts index 8a31b0a..7488a01 100644 --- a/src/api/season.ts +++ b/src/apis/season.ts @@ -1,11 +1,20 @@ -import { initUntypeable } from "untypeable"; +import { Config } from "../config"; +import { CosmoClient } from "../client"; +import { ValidArtist } from "./artist"; -const u = initUntypeable().pushArg<"GET">(); -export const router = u.router({ - "/season/v2/:artist": { - GET: u.input<{ artist: string }>().output(), - }, -}); +export class SeasonAPI { + constructor(private config: Config) {} + + /** + * Get the seasons for the given artist. + */ + async list(artist: ValidArtist): Promise { + return await CosmoClient.request( + `/season/v2/${artist}`, + this.config + ); + } +} export type OngoingSeason = { artist: string; diff --git a/src/apis/user.ts b/src/apis/user.ts new file mode 100644 index 0000000..b1edac6 --- /dev/null +++ b/src/apis/user.ts @@ -0,0 +1,60 @@ +import { Config } from "../config"; +import { CosmoClient } from "../client"; +import { Artist, ValidArtist } from "./artist"; + +export class UserAPI { + constructor(private config: Config) {} + + /** + * Get the currently authenticated user. + */ + async me(): Promise { + return await CosmoClient.request<{ profile: User }>( + `/user/v1/me`, + this.config + ).then((res) => res.profile); + } + + /** + * Search for users. + */ + async search(query: string): Promise { + return await CosmoClient.request( + `/user/v1/search?query=${query}`, + this.config + ); + } +} + +export type User = { + id: number; + email: string; + nickname: string; + address: string; + birth: string; + profileImageUrl: string; + isEligibleForWelcomeObjekt: boolean; + followingArtists: FollowedArtist[]; + lastViewedArtist: ValidArtist; + marketingConsentDate: string | null; + createdAt: string; +}; + +export type FollowedArtist = Artist & { + receivedWelcomeObjekt: boolean; + assetBalance: { + totalComo: number; + totalObjekt: number; + }; +}; + +export type SearchResponse = { + hasNext: boolean; + results: SearchResult[]; +}; + +export type SearchResult = { + nickname: string; + address: string; + profileImageUrl: string; +}; diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..8f2e90b --- /dev/null +++ b/src/client.ts @@ -0,0 +1,73 @@ +import { ArtistAPI } from "./apis/artist"; +import { AuthAPI } from "./apis/auth"; +import { NewsAPI } from "./apis/news"; +import { SeasonAPI } from "./apis/season"; +import { UserAPI } from "./apis/user"; +import { Config } from "./config"; +import { + CosmoError, + CosmoErrorResponse, + TokenExpiredError, + UnauthorizedError, +} from "./errors"; + +export class CosmoClient { + private config: Config; + public artists: ArtistAPI; + public auth: AuthAPI; + public seasons: SeasonAPI; + public users: UserAPI; + public news: NewsAPI; + + constructor(config: Config) { + this.config = { + baseUrl: "https://api.cosmo.fans", + ...config, + }; + + this.artists = new ArtistAPI(this.config); + this.auth = new AuthAPI(this.config); + this.seasons = new SeasonAPI(this.config); + this.users = new UserAPI(this.config); + this.news = new NewsAPI(this.config); + } + + static async request( + url: string, + config: Config, + options: RequestInit = {} + ) { + const response = await fetch(new URL(url, config.baseUrl), { + ...options, + headers: { + ...options.headers, + ...(config.accessToken + ? { Authorization: `Bearer ${config.accessToken}` } + : {}), + }, + }); + + if (response.ok === false) { + try { + const body: CosmoErrorResponse = await response.json(); + switch (response.status) { + case 401: + throw new UnauthorizedError(body.error.details); + case 403: + throw new TokenExpiredError(body.error.details); + } + } catch (err) { + if (err instanceof CosmoError) { + throw err; + } + throw new CosmoError(`status: ${response.status}, error: ${err}`); + } + } + + return response.json() as T; + } +} + +export function createClient(config: Config): CosmoClient { + return new CosmoClient(config); +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..45a9d7e --- /dev/null +++ b/src/config.ts @@ -0,0 +1,11 @@ +export type Config = { + /** + * Makes it possible to switch environments. + */ + baseUrl?: string; + + /** + * Some endpoints are public, but it's recommended to provide a token. + */ + accessToken?: string; +}; diff --git a/src/cosmo.ts b/src/cosmo.ts deleted file mode 100644 index c0b9eeb..0000000 --- a/src/cosmo.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { ValidArtist } from "./api/artists"; -import { LoginPayload, RefreshPayload } from "./api/auth"; -import { CosmoContract } from "./interface"; -import { createDefaultFetcher, typedRouter } from "./router"; - -type CosmoConfig = { - accessToken?: string; - maxRetries?: number; - fetcher?: ReturnType; -}; - -export class Cosmo implements CosmoContract { - private client: ReturnType; - - constructor({ accessToken, maxRetries, fetcher }: CosmoConfig = {}) { - this.client = typedRouter( - fetcher ?? createDefaultFetcher({ accessToken, maxRetries }) - ); - } - - async getArtists() { - const result = await this.client("/artist/v1", "GET"); - return result.artists; - } - - async getArtist(artist: ValidArtist) { - const result = await this.client("/artist/v1/:artist", "GET", { artist }); - return result.artist; - } - - async getUser() { - const result = await this.client("/user/v1/me", "GET"); - return result.profile; - } - - async searchUser(query: string) { - const result = await this.client("/user/v1/search", "GET", { query }); - return result.results; - } - - async login(payload: LoginPayload) { - return await this.client("/auth/v1/signin", "POST", payload); - } - - async refreshToken(payload: RefreshPayload) { - return await this.client("/auth/v1/refresh", "POST", payload); - } - - async getHomeNews(artist: ValidArtist) { - return await this.client("/news/v1", "GET", { artist }); - } - - async getAtmosphereFeed( - artist: ValidArtist, - options?: { startAfter?: number; limit?: number } - ) { - return await this.client("/news/v1/feed", "GET", { - artist, - start_after: options?.startAfter, - limit: options?.limit, - }); - } - - async getExclusiveFeed( - artist: ValidArtist, - options?: { startAfter?: number; limit?: number } - ) { - return await this.client("/news/v1/exclusive", "GET", { - artist, - start_after: options?.startAfter, - limit: options?.limit, - }); - } - - async getSeasons(artist: ValidArtist) { - return await this.client("/season/v2/:artist", "GET", { artist }); - } -} diff --git a/src/error.ts b/src/error.ts deleted file mode 100644 index ed7d11a..0000000 --- a/src/error.ts +++ /dev/null @@ -1,14 +0,0 @@ -export class CosmoUnauthenticatedError extends Error { - constructor() { - super("Cosmo: User is not authenticated."); - } -} - -export class HTTPError extends Error {} - -export type CosmoJsonError = { - error: { - message: string; - details: string; - }; -}; diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 0000000..cab5f05 --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,15 @@ +export type CosmoErrorResponse = { + error: { + message: string; + details: string; + }; +}; + +export class CosmoError extends Error { + constructor(reason: string) { + super(reason); + } +} + +export class UnauthorizedError extends CosmoError {} +export class TokenExpiredError extends CosmoError {} diff --git a/src/index.ts b/src/index.ts index 6e36e56..da6c2d5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1 @@ -export { Cosmo } from "./cosmo"; -export * from "./types"; +export { createClient } from "./client"; diff --git a/src/interface.ts b/src/interface.ts deleted file mode 100644 index 7e3d2e9..0000000 --- a/src/interface.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Artist, ArtistWithMembers, ValidArtist } from "./api/artists"; -import { - LoginPayload, - LoginResult, - RefreshPayload, - RefreshResult, -} from "./api/auth"; -import { SearchResult, User } from "./api/user"; -import { - HomeNewsResult, - NewsFeedResult, - NewsSectionExclusiveContent, - NewsSectionFeedContent, - SeasonResponse, -} from "./types"; - -export interface CosmoContract { - /** - * Fetch all artists within Cosmo. - */ - getArtists(): Promise; - - /** - * Fetch a single artist and its members. - */ - getArtist(artist: ValidArtist): Promise; - - /** - * Fetch the currently authenticated user. - */ - getUser(): Promise; - - /** - * Search for users. - */ - searchUser(query: string): Promise; - - /** - * Log into Cosmo using an email and Ramper access token. - */ - login(payload: LoginPayload): Promise; - - /** - * Log into Cosmo using an email and Ramper access token. - */ - refreshToken(payload: RefreshPayload): Promise; - - /** - * Fetch news on the home page for the given artist. - */ - getHomeNews(artist: ValidArtist): Promise; - - /** - * Fetch the news feed for the given artist. - */ - getAtmosphereFeed( - artist: ValidArtist, - options?: { startAfter?: number; limit?: number } - ): Promise>; - - /** - * Fetch the exclusive feed for the given artist. - */ - getExclusiveFeed( - artist: ValidArtist, - options?: { startAfter?: number; limit?: number } - ): Promise>; - - /** - * Get the past and current seasons for the given artist. - */ - getSeasons(artist: ValidArtist): Promise; -} diff --git a/src/router.ts b/src/router.ts deleted file mode 100644 index 3a126b6..0000000 --- a/src/router.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { createTypeLevelClient } from "untypeable"; -import { CosmoUnauthenticatedError, HTTPError } from "./error"; -import { router as artistRouter } from "./api/artists"; -import { router as userRouter } from "./api/user"; -import { router as authRouter } from "./api/auth"; -import { router as newsRouter } from "./api/news"; -import { router as seasonRouter } from "./api/season"; - -export type FetcherOptions = { - accessToken?: string; - maxRetries?: number; -}; - -const COSMO_ENDPOINT = "https://api.cosmo.fans"; - -export const router = artistRouter - .merge(userRouter) - .merge(authRouter) - .merge(newsRouter) - .merge(seasonRouter); - -export function createDefaultFetcher(options: FetcherOptions = {}) { - return (path: string, method: "GET" | "POST", input: ValidInput = {}) => { - const pathWithParams = path.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => - input[key].toString() - ); - - let resolvedPath = pathWithParams; - let init: RequestInit = { - method, - headers: { - "Content-Type": "application/json", - ...(options.accessToken - ? { Authorization: `Bearer ${options.accessToken}` } - : {}), - }, - }; - - switch (method) { - case "GET": - const params = parseParams(path, input); - resolvedPath += `?${params.toString()}`; - break; - case "POST": - init = { - ...init, - body: JSON.stringify(input), - }; - } - - return makeFetch( - `${COSMO_ENDPOINT}${resolvedPath}`, - init, - 0, - options.maxRetries ?? 3 - ); - }; -} - -type ValidInput = Record; - -/** - * Prevent any path replacements from also being in the query string. - */ -function parseParams(path: string, input: ValidInput): URLSearchParams { - const params = new URLSearchParams(); - - // get clean path params - const segments = (path.match(/:(\w+)/g) ?? []).map((s: string) => s.slice(1)); - - // add any inputs that don't exist as path params, into query params - for (const [key, value] of Object.entries(input)) { - if (segments.includes(key) || value === undefined) { - continue; - } - params.set(key, value.toString()); - } - - return params; -} - -function makeFetch( - url: string, - init: RequestInit, - currentRetry: number, - maxRetries: number -) { - try { - return fetch(url, init).then((res) => { - // success with body - if (res.status === 200) { - return res.json(); - } - // success without body - if (res.status >= 201 && res.status < 300) { - return true; - } - // unauthenticated or unauthorized - if (res.status >= 400 && res.status < 403) { - throw new CosmoUnauthenticatedError(); - } - // default - throw new HTTPError(res.statusText); - }); - } catch (err) { - const isRetryable = err instanceof HTTPError; - if (isRetryable && currentRetry <= maxRetries) { - return makeFetch(url, init, currentRetry + 1, maxRetries); - } - - throw err; - } -} - -export const typedRouter = ( - fetcher: ReturnType -) => { - return createTypeLevelClient(fetcher); -}; diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 3db3660..0000000 --- a/src/types.ts +++ /dev/null @@ -1,27 +0,0 @@ -export { FetcherOptions } from "./router"; -export { ValidArtist, Artist, Member, ArtistWithMembers } from "./api/artists"; -export { User, SearchResponse, SearchResult } from "./api/user"; -export { - LoginPayload, - LoginResult, - RefreshPayload, - RefreshResult, -} from "./api/auth"; -export { - HomeNewsResult, - NewsFeedResult, - NewsSection, - NewsSectionBanner, - NewsSectionBannerContent, - NewsSectionBar, - NewsSectionExclusive, - NewsSectionExclusiveContent, - NewsSectionFeed, - NewsSectionFeedContent, -} from "./api/news"; -export { - OngoingSeason, - EndedSeason, - Season, - SeasonResponse, -} from "./api/season"; diff --git a/tests/artist.spec.ts b/tests/artist.spec.ts new file mode 100644 index 0000000..27d5cb3 --- /dev/null +++ b/tests/artist.spec.ts @@ -0,0 +1,21 @@ +import { describe, it, expect, beforeEach } from "vitest"; +import { CosmoClient } from "../src/client"; +import { json } from "./mocks"; + +describe("ArtistAPI", () => { + let cosmo: CosmoClient; + + beforeEach(() => { + cosmo = new CosmoClient({}); + }); + + it("should list artists", async () => { + const response = await cosmo.artists.list(); + expect(response).toEqual(json.getArtists.artists); + }); + + it("should return a single artist with its members", async () => { + const response = await cosmo.artists.get("ARTMS"); + expect(response).toEqual(json.getArtist.artist); + }); +}); diff --git a/tests/artists.spec.ts b/tests/artists.spec.ts deleted file mode 100644 index d24ed2f..0000000 --- a/tests/artists.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { expect, test } from "vitest"; -import { Cosmo } from "../src"; -import { json } from "./mocks"; - -test("fetches artists", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getArtists(); - expect(result).toEqual(json.getArtists.artists); -}); - -test("fetches a single artist", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getArtist("artms"); - expect(result).toEqual(json.getArtist.artist); -}); diff --git a/tests/auth.spec.ts b/tests/auth.spec.ts index 40e4c63..fa10468 100644 --- a/tests/auth.spec.ts +++ b/tests/auth.spec.ts @@ -1,19 +1,29 @@ -import { expect, test } from "vitest"; -import { Cosmo } from "../src"; +import { describe, it, expect, beforeEach } from "vitest"; +import { CosmoClient } from "../src/client"; import { json } from "./mocks"; -test("logs the user in", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.login({ - channel: "email", - email: "test@example.com", - accessToken: "accessToken", +describe("AuthAPI", () => { + let cosmo: CosmoClient; + + beforeEach(() => { + cosmo = new CosmoClient({}); }); - expect(result).toEqual(json.login); -}); -test("refreshes a token", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.refreshToken({ refreshToken: "refreshToken" }); - expect(result).toEqual(json.refreshToken); + it("should sign in successfully", async () => { + const response = await cosmo.auth.signIn({ + channel: "email", + email: "email@example.com", + accessToken: "ramperIdToken", + }); + + expect(response).toEqual(json.login); + }); + + it("should refresh the token successfully", async () => { + const response = await cosmo.auth.refreshToken({ + refreshToken: "someRefeshToken", + }); + + expect(response).toEqual(json.refreshToken); + }); }); diff --git a/tests/mocks.ts b/tests/mocks.ts index e69a6ae..0c615d4 100644 --- a/tests/mocks.ts +++ b/tests/mocks.ts @@ -1,6 +1,6 @@ import { http, HttpResponse } from "msw"; -export const cosmo = (path: string) => `https://api.cosmo.fans${path}`; +const cosmo = (path: string) => `https://api.cosmo.fans${path}`; // default handlers export const handlers = [ @@ -26,12 +26,32 @@ export const handlers = [ ), // season - http.get(cosmo("/season/v2/*"), () => HttpResponse.json(json.getSeason)), + http.get(cosmo("/season/v2/*"), () => HttpResponse.json(json.getSeasons)), ]; // conditional handlers export const getUserUnauthorized = http.get(cosmo("/user/v1/me"), () => - HttpResponse.json({ error: "Unauthorized" }, { status: 401 }) + HttpResponse.json( + { + error: { + message: "unauthorized", + details: "missing Authorization header", + }, + }, + { status: 401 } + ) +); +export const getFeedNewsParams = http.get( + cosmo("/news/v1/feed"), + ({ request }) => { + const url = new URL(request.url); + const startAfter = url.searchParams.get("start_after"); + const parsed = parseInt(startAfter ?? "0"); + return HttpResponse.json({ + ...json.newsFeed, + nextStartAfter: (parsed + 3).toString(), + }); + } ); export const json = { @@ -131,23 +151,36 @@ export const json = { getUser: { profile: { - nickname: "test", - address: "0xtest", + id: 970613, + email: "email@example.com", + nickname: "Example", + address: "0xABCDEF", + birth: "1997-06-13", profileImageUrl: "", - artists: [ + isEligibleForWelcomeObjekt: false, + followingArtists: [ { name: "artms", title: "ARTMS", + logoImageUrl: "https://static.cosmo.fans/assets/artms-logo.png", contracts: { - Como: "0xComo", - Objekt: "0xObjekt", + Como: "0x8254D8D2903B20187cBC4Dd833d49cECc219F32E", + Objekt: "0x0fB69F54bA90f17578a59823E09e5a1f8F3FA200", + CommunityPool: "0x07F93cCc90aF32E4d6ea70A93F36DF9F58C97087", + ComoMinter: "0xBda6B6C34b27D54EAaAf555e458199467E77Bb18", + ObjektMinter: "0x9009e2b4fc02eb18e41994d235a78504600AC87c", + Governor: "0x8466e6E218F0fe438Ac8f403f684451D20E59Ee3", }, + receivedWelcomeObjekt: true, assetBalance: { - totalComo: 1, - totalObjekt: 2, + totalComo: 123, + totalObjekt: 456, }, }, ], + lastViewedArtist: "artms", + marketingConsentDate: "2023-01-01T00:00:00.000Z", + createdAt: "2022-01-01T00:00:00.000Z", }, }, @@ -155,8 +188,8 @@ export const json = { hasNext: false, results: [ { - nickname: "Kairu", - address: "0xcaB3C85ac8f4aE0153B7cF2Bbf1378397890848b", + nickname: "Example", + address: "0xABCDEF", profileImageUrl: "", }, ], @@ -164,26 +197,111 @@ export const json = { login: { user: { - id: 1, - email: "test@example.com", - nickname: "test", - address: "0xTest", + id: 970613, + email: "email@example.com", + nickname: "example", + address: "0xABCDEF", profileImageUrl: "", }, credentials: { - accessToken: "accessToken", - refreshToken: "refreshToken", + accessToken: "access-token", + refreshToken: "refresh-token", }, }, refreshToken: { credentials: { - accessToken: "accessToken", - refreshToken: "refreshToken", + refreshToken: "newRefreshToken", + accessToken: "newAccessToken", }, }, - newsHome: {}, + newsHome: { + sections: [ + { + artist: "ARTMS", + type: "bar", + contents: [], + }, + { + artist: "ARTMS", + type: "banner", + contents: [ + { + id: 80, + url: "https://twitter.com/official_artms/status/1740009651671015782", + createdAt: "2023-12-28T08:01:23.660Z", + label: "notice", + order: 1, + body: "OEC in US, Mexico, Japan!", + imageUrl: + "https://static.cosmo.fans/admin/uploads/01a3a715-3edc-4aac-b7a8-30e48e9bcd2e.jpg", + }, + { + id: 61, + url: "https://www.melon.com/album/detail.htm?albumId=11376620", + createdAt: "2023-12-15T07:03:27.735Z", + label: "release", + order: 2, + body: "Stream 'The Carol 3.0' on Melon", + imageUrl: + "https://static.cosmo.fans/admin/uploads/e1285c2e-1000-49be-8351-c690fabf9156.png", + }, + { + id: 60, + url: "https://open.spotify.com/track/4ggzfyKGny5dVjxPIgvQQO", + createdAt: "2023-12-15T06:58:35.875Z", + label: "release", + order: 1, + body: "Stream 'The Carol 3.0' on Spotify!", + imageUrl: + "https://static.cosmo.fans/admin/uploads/c26f640c-a033-42d0-b347-1bc73bfeaff8.png", + }, + ], + }, + { + artist: "ARTMS", + type: "feed", + title: "Today’s Atmosphere", + contents: [ + { + id: 384, + url: "https://www.instagram.com/official_artms/", + createdAt: "2024-01-18T04:22:18.461Z", + artist: "ARTMS", + logoImageUrl: "https://static.cosmo.fans/assets/artms-logo.png", + body: "Choerry's Photo Diary (˵ •̀ ᴗ - ˵ ) ✧", + imageUrls: [ + "https://static.cosmo.fans/admin/uploads/b803546e-1dd8-41a4-ab9b-e38708a1b125.png", + ], + }, + ], + }, + { + artist: "ARTMS", + type: "exclusive", + title: "COSMO Exclusive", + contents: [ + { + id: 36, + url: "https://www.youtube.com/watch?v=l6p8FDJqUj4", + createdAt: "2023-10-23T03:18:18.595Z", + title: "HeeJin 'Algorithm' (MV Ver.)", + body: "#ARTMS #HeeJin #희진 #K #Algorithm", + thumbnailImageUrl: + "https://static.cosmo.fans/admin/uploads/86763077-0431-41af-af8f-aae1676402e8.jpg", + nativeVideoUrl: "", + }, + ], + }, + { + artist: "ARTMS", + type: "event", + title: "Event", + contents: [], + }, + ], + }, newsFeed: { hasNext: true, @@ -303,7 +421,7 @@ export const json = { ], }, - getSeason: { + getSeasons: { seasons: [ { artist: "artms", diff --git a/tests/news.spec.ts b/tests/news.spec.ts index c9fb602..528a18c 100644 --- a/tests/news.spec.ts +++ b/tests/news.spec.ts @@ -1,21 +1,36 @@ -import { expect, test } from "vitest"; -import { Cosmo } from "../src"; -import { json } from "./mocks"; +import { describe, it, expect, beforeEach } from "vitest"; +import { CosmoClient } from "../src/client"; +import { getFeedNewsParams, json } from "./mocks"; +import { server } from "./setup"; -test("fetches home page news", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getHomeNews("artms"); - expect(result).toEqual(json.newsHome); -}); +describe("NewsAPI", () => { + let cosmo: CosmoClient; -test("fetches atmosphere feed", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getAtmosphereFeed("artms", { limit: 3 }); - expect(result).toEqual(json.newsFeed); -}); + beforeEach(() => { + cosmo = new CosmoClient({}); + }); + + it("should list the home page news", async () => { + const response = await cosmo.news.home("ARTMS"); + expect(response).toEqual(json.newsHome.sections); + }); + + it("should list the news feed", async () => { + const response = await cosmo.news.feed({ artist: "ARTMS" }); + expect(response).toEqual(json.newsFeed); + }); + + it("should list the exclusive feed", async () => { + const response = await cosmo.news.exclusive({ artist: "ARTMS" }); + expect(response).toEqual(json.newsExclusive); + }); -test("fetches exclusive feed", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getExclusiveFeed("artms"); - expect(result).toEqual(json.newsExclusive); + it("should pass search params correctly", async () => { + server.use(getFeedNewsParams); + const response = await cosmo.news.feed({ artist: "ARTMS", startAfter: 3 }); + expect(response).toEqual({ + ...json.newsFeed, + nextStartAfter: "6", + }); + }); }); diff --git a/tests/season.spec.ts b/tests/season.spec.ts index 3f75529..b3938a0 100644 --- a/tests/season.spec.ts +++ b/tests/season.spec.ts @@ -1,9 +1,16 @@ -import { expect, test } from "vitest"; -import { Cosmo } from "../src"; +import { describe, it, expect, beforeEach } from "vitest"; +import { CosmoClient } from "../src/client"; import { json } from "./mocks"; -test("fetches seasons", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.getSeasons("artms"); - expect(result).toEqual(json.getSeason); +describe("SeasonAPI", () => { + let cosmo: CosmoClient; + + beforeEach(() => { + cosmo = new CosmoClient({}); + }); + + it("should list seasons", async () => { + const response = await cosmo.seasons.list("ARTMS"); + expect(response).toEqual(json.getSeasons); + }); }); diff --git a/tests/user.spec.ts b/tests/user.spec.ts index 82d19c4..1b57df8 100644 --- a/tests/user.spec.ts +++ b/tests/user.spec.ts @@ -1,26 +1,31 @@ -import { expect, test } from "vitest"; -import { Cosmo } from "../src"; -import { server } from "./setup"; +import { describe, it, expect, beforeEach } from "vitest"; +import { CosmoClient } from "../src/client"; import { getUserUnauthorized, json } from "./mocks"; -import { CosmoUnauthenticatedError } from "../src/error"; +import { server } from "./setup"; +import { UnauthorizedError } from "../src/errors"; -test("unauthenticated client should error when fetching user", async () => { - server.use(getUserUnauthorized); +describe("UserAPI", () => { + let cosmo: CosmoClient; - const cosmo = new Cosmo(); - expect(() => cosmo.getUser()).rejects.toThrowError( - new CosmoUnauthenticatedError() - ); -}); + beforeEach(() => { + cosmo = new CosmoClient({}); + }); -test("fetches the user", async () => { - const cosmo = new Cosmo({ accessToken: "accessToken" }); - const result = await cosmo.getUser(); - expect(result).toEqual(json.getUser.profile); -}); + it("should get the currently authenticated user", async () => { + const response = await cosmo.users.me(); + expect(response).toEqual(json.getUser.profile); + }); + + it("should error when unauthenticated", async () => { + server.use(getUserUnauthorized); + + expect(() => cosmo.users.me()).rejects.toThrowError( + new UnauthorizedError("missing Authorization header") + ); + }); -test("searches for users", async () => { - const cosmo = new Cosmo(); - const result = await cosmo.searchUser("kairu"); - expect(result).toEqual(json.search.results); + it("should search for users", async () => { + const response = await cosmo.users.search("example"); + expect(response).toEqual(json.search); + }); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..fc7d90c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..3885bda --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + splitting: true, + sourcemap: true, + clean: true, + dts: true, + format: ["esm", "cjs"], + skipNodeModulesBundle: true, +}); diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..83610a7 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "vite"; +import { UserConfig } from "vitest/config"; + +export default defineConfig({ + test: { + globals: true, + environment: "node", + setupFiles: "./tests/setup.ts", + }, +} as UserConfig); diff --git a/vitest.config.ts b/vitest.config.ts deleted file mode 100644 index 066466d..0000000 --- a/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - setupFiles: "./tests/setup.ts", - }, -});