diff --git a/README.md b/README.md index a5480d6..f543c8e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ a Page to view some global statistics about [Modrinth](https://modrinth.com/) ```dotenv # example .env -NUXT_MONGODB_DATABASE_NAME= -NUXT_MONGODB_CONNECTION_STRING= +NUXT_UPSTASH_REDIS_REST_URL= +NUXT_UPSTASH_REDIS_REST_TOKEN= NUXT_PUBLIC_UMAMI_ID= ``` diff --git a/nuxt.config.ts b/nuxt.config.ts index 0f71255..52a1837 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -52,12 +52,14 @@ export default defineNuxtConfig({ urls: urls, }, runtimeConfig: { - mongodb: { - databaseName: "", - connectionString: "", + upstash: { + redis: { + restUrl: undefined, + restToken: undefined, + }, }, public: { - umamiID: "", + umamiID: undefined, }, }, nitro: { diff --git a/package.json b/package.json index 89b262c..33de67b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dependencies": { "@nuxtjs/sitemap": "^7.4.3", "@tailwindcss/vite": "^4.1.12", + "@upstash/redis": "^1.35.3", "chart.js": "^4.5.0", "consola": "^3.4.2", "mongodb": "^6.18.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 26469c6..a28219f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@tailwindcss/vite': specifier: ^4.1.12 version: 4.1.12(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@upstash/redis': + specifier: ^1.35.3 + version: 1.35.3 chart.js: specifier: ^4.5.0 version: 4.5.0 @@ -25,13 +28,13 @@ importers: version: 6.18.0 nuxt: specifier: ^4.0.3 - version: 4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1) + version: 4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@upstash/redis@1.35.3)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1) tailwindcss: specifier: ^4.1.12 version: 4.1.12 unstorage: specifier: ^1.16.1 - version: 1.16.1(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0) + version: 1.16.1(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0) vue: specifier: ^3.5.18 version: 3.5.18(typescript@5.9.2) @@ -68,13 +71,13 @@ importers: version: 2.0.0(magicast@0.3.5)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2)) '@nuxt/scripts': specifier: ^0.11.10 - version: 0.11.10(@netlify/blobs@9.1.2)(@unhead/vue@2.0.14(vue@3.5.18(typescript@5.9.2)))(db0@0.3.2)(ioredis@5.7.0)(magicast@0.3.5)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)) + version: 0.11.10(@netlify/blobs@9.1.2)(@unhead/vue@2.0.14(vue@3.5.18(typescript@5.9.2)))(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0)(magicast@0.3.5)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)) '@nuxtjs/tailwindcss': specifier: 7.0.0-beta.0 version: 7.0.0-beta.0(magicast@0.3.5)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@vueuse/nuxt': specifier: ^13.6.0 - version: 13.6.0(magicast@0.3.5)(nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2)) + version: 13.6.0(magicast@0.3.5)(nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@upstash/redis@1.35.3)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2)) vue-tsc: specifier: ^3.0.5 version: 3.0.5(typescript@5.9.2) @@ -1527,6 +1530,9 @@ packages: peerDependencies: vue: '>=3.5.18' + '@upstash/redis@1.35.3': + resolution: {integrity: sha512-hSjv66NOuahW3MisRGlSgoszU2uONAY2l5Qo3Sae8OT3/Tng9K+2/cBRuyPBX8egwEGcNNCF9+r0V6grNnhL+w==} + '@vercel/nft@0.29.4': resolution: {integrity: sha512-6lLqMNX3TuycBPABycx7A9F1bHQR7kiQln6abjFbPrf5C/05qHM9M5E4PeTE59c7z8g6vHnx1Ioihb2AQl7BTA==} engines: {node: '>=18'} @@ -5148,7 +5154,7 @@ snapshots: std-env: 3.9.0 ufo: 1.6.1 - '@nuxt/scripts@0.11.10(@netlify/blobs@9.1.2)(@unhead/vue@2.0.14(vue@3.5.18(typescript@5.9.2)))(db0@0.3.2)(ioredis@5.7.0)(magicast@0.3.5)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))': + '@nuxt/scripts@0.11.10(@netlify/blobs@9.1.2)(@unhead/vue@2.0.14(vue@3.5.18(typescript@5.9.2)))(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0)(magicast@0.3.5)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))': dependencies: '@nuxt/kit': 4.0.3(magicast@0.3.5) '@unhead/vue': 2.0.14(vue@3.5.18(typescript@5.9.2)) @@ -5165,7 +5171,7 @@ snapshots: std-env: 3.9.0 ufo: 1.6.1 unplugin: 2.3.5 - unstorage: 1.16.1(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0) + unstorage: 1.16.1(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0) valibot: 1.1.0(typescript@5.9.2) transitivePeerDependencies: - '@azure/app-configuration' @@ -5813,6 +5819,10 @@ snapshots: unhead: 2.0.14 vue: 3.5.18(typescript@5.9.2) + '@upstash/redis@1.35.3': + dependencies: + uncrypto: 0.1.3 + '@vercel/nft@0.29.4(rollup@4.46.2)': dependencies: '@mapbox/node-pre-gyp': 2.0.0 @@ -6009,13 +6019,13 @@ snapshots: '@vueuse/metadata@13.6.0': {} - '@vueuse/nuxt@13.6.0(magicast@0.3.5)(nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2))': + '@vueuse/nuxt@13.6.0(magicast@0.3.5)(nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@upstash/redis@1.35.3)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2))': dependencies: '@nuxt/kit': 4.0.3(magicast@0.3.5) '@vueuse/core': 13.6.0(vue@3.5.18(typescript@5.9.2)) '@vueuse/metadata': 13.6.0 local-pkg: 1.1.1 - nuxt: 4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1) + nuxt: 4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@upstash/redis@1.35.3)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1) vue: 3.5.18(typescript@5.9.2) transitivePeerDependencies: - magicast @@ -7329,7 +7339,7 @@ snapshots: p-wait-for: 5.0.2 qs: 6.14.0 - nitropack@2.12.4(@netlify/blobs@9.1.2): + nitropack@2.12.4(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 '@netlify/functions': 3.1.10(rollup@4.46.2) @@ -7397,7 +7407,7 @@ snapshots: unenv: 2.0.0-rc.19 unimport: 5.2.0 unplugin-utils: 0.2.5 - unstorage: 1.16.1(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0) + unstorage: 1.16.1(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0) untyped: 2.0.0 unwasm: 0.3.9 youch: 4.1.0-beta.8 @@ -7512,7 +7522,7 @@ snapshots: - magicast - vue - nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1): + nuxt@4.0.3(@biomejs/biome@2.2.0)(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.2.1)(@upstash/redis@1.35.3)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(ioredis@5.7.0)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.46.2)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.2.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vue-tsc@3.0.5(typescript@5.9.2))(yaml@2.8.1): dependencies: '@nuxt/cli': 3.28.0(magicast@0.3.5) '@nuxt/devalue': 2.0.2 @@ -7547,7 +7557,7 @@ snapshots: mlly: 1.7.4 mocked-exports: 0.1.1 nanotar: 0.2.0 - nitropack: 2.12.4(@netlify/blobs@9.1.2) + nitropack: 2.12.4(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3) nypm: 0.6.1 ofetch: 1.4.1 ohash: 2.0.11 @@ -7572,7 +7582,7 @@ snapshots: unimport: 5.2.0 unplugin: 2.3.5 unplugin-vue-router: 0.15.0(@vue/compiler-sfc@3.5.18)(typescript@5.9.2)(vue-router@4.5.1(vue@3.5.18(typescript@5.9.2)))(vue@3.5.18(typescript@5.9.2)) - unstorage: 1.16.1(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0) + unstorage: 1.16.1(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0) untyped: 2.0.0 vue: 3.5.18(typescript@5.9.2) vue-bundle-renderer: 2.1.2 @@ -8580,7 +8590,7 @@ snapshots: picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 - unstorage@1.16.1(@netlify/blobs@9.1.2)(db0@0.3.2)(ioredis@5.7.0): + unstorage@1.16.1(@netlify/blobs@9.1.2)(@upstash/redis@1.35.3)(db0@0.3.2)(ioredis@5.7.0): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -8592,6 +8602,7 @@ snapshots: ufo: 1.6.1 optionalDependencies: '@netlify/blobs': 9.1.2 + '@upstash/redis': 1.35.3 db0: 0.3.2 ioredis: 5.7.0 diff --git a/scripts/migrate.ts b/scripts/migrate.ts index aac6835..af3b7e4 100644 --- a/scripts/migrate.ts +++ b/scripts/migrate.ts @@ -1,5 +1,6 @@ import { createStorage } from "unstorage"; import mongodbDriver from "unstorage/drivers/mongodb"; +import upstashDriver from "unstorage/drivers/upstash"; // globalStatistics const fromGlobalStatistics = createStorage({ @@ -11,10 +12,10 @@ const fromGlobalStatistics = createStorage({ }); const toGlobalStatistics = createStorage({ - driver: mongodbDriver({ - connectionString: process.env.connectionString!, - databaseName: process.env.databaseNameTo!, - collectionName: "globalStatistics", + driver: upstashDriver({ + url: process.env.UPSTASH_REDIS_REST_URL!, + token: process.env.UPSTASH_REDIS_REST_TOKEN!, + base: "globalStatistics", }), }); @@ -28,10 +29,10 @@ const fromProjectStatistics = createStorage({ }); const toProjectStatistics = createStorage({ - driver: mongodbDriver({ - connectionString: process.env.connectionString!, - databaseName: process.env.databaseNameTo!, - collectionName: "projectStatistics", + driver: upstashDriver({ + url: process.env.UPSTASH_REDIS_REST_URL!, + token: process.env.UPSTASH_REDIS_REST_TOKEN!, + base: "projectStatistics", }), }); @@ -45,10 +46,10 @@ const fromMetadata = createStorage({ }); const toMetadata = createStorage({ - driver: mongodbDriver({ - connectionString: process.env.connectionString!, - databaseName: process.env.databaseNameTo!, - collectionName: "metadata", + driver: upstashDriver({ + url: process.env.UPSTASH_REDIS_REST_URL!, + token: process.env.UPSTASH_REDIS_REST_TOKEN!, + base: "metadata", }), }); @@ -58,6 +59,7 @@ function chunkArray(array: T[], size: number): T[][] { ); } +//todo dont use foreach since it is not awaitable chunkArray(await fromGlobalStatistics.getKeys(), 100).forEach( async (keys, index) => { const values = await fromGlobalStatistics.getItems(keys); diff --git a/scripts/package.json b/scripts/package.json index e3b1b95..ddec15e 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -5,10 +5,11 @@ "@types/node": "latest" }, "dependencies": { - "unstorage": "^1.16.1" + "unstorage": "^1.16.1", + "@upstash/redis": "^1.35.3" }, "scripts": { - "migrate": "node migrate.ts", - "db-fix": "node db-fix.ts" + "migrate": "node run migrate.ts", + "db-fix": "node run db-fix.ts" } } diff --git a/scripts/pnpm-lock.yaml b/scripts/pnpm-lock.yaml index cdf4a19..49f1209 100644 --- a/scripts/pnpm-lock.yaml +++ b/scripts/pnpm-lock.yaml @@ -8,9 +8,12 @@ importers: .: dependencies: + '@upstash/redis': + specifier: ^1.35.3 + version: 1.35.3 unstorage: specifier: ^1.16.1 - version: 1.16.1 + version: 1.16.1(@upstash/redis@1.35.3) devDependencies: '@types/node': specifier: latest @@ -21,6 +24,9 @@ packages: '@types/node@24.2.1': resolution: {integrity: sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==} + '@upstash/redis@1.35.3': + resolution: {integrity: sha512-hSjv66NOuahW3MisRGlSgoszU2uONAY2l5Qo3Sae8OT3/Tng9K+2/cBRuyPBX8egwEGcNNCF9+r0V6grNnhL+w==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -148,6 +154,10 @@ snapshots: dependencies: undici-types: 7.10.0 + '@upstash/redis@1.35.3': + dependencies: + uncrypto: 0.1.3 + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -207,7 +217,7 @@ snapshots: undici-types@7.10.0: {} - unstorage@1.16.1: + unstorage@1.16.1(@upstash/redis@1.35.3): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -217,3 +227,5 @@ snapshots: node-fetch-native: 1.6.7 ofetch: 1.4.1 ufo: 1.6.1 + optionalDependencies: + '@upstash/redis': 1.35.3 diff --git a/server/plugins/storage.ts b/server/plugins/storage.ts index 6134d1d..fa0442e 100644 --- a/server/plugins/storage.ts +++ b/server/plugins/storage.ts @@ -1,30 +1,30 @@ -import mongodbDriver from "unstorage/drivers/mongodb"; +import upstashDriver from "unstorage/drivers/upstash"; export default defineNitroPlugin(() => { const storage = useStorage(); storage.mount( "globalStatistics", - mongodbDriver({ - connectionString: useRuntimeConfig().mongodb.connectionString, - databaseName: useRuntimeConfig().mongodb.databaseName, - collectionName: "globalStatistics", + upstashDriver({ + url: useRuntimeConfig().upstash.redis.restUrl, + token: useRuntimeConfig().upstash.redis.restToken, + base: "globalStatistics", }), ); storage.mount( "projectStatistics", - mongodbDriver({ - connectionString: useRuntimeConfig().mongodb.connectionString, - databaseName: useRuntimeConfig().mongodb.databaseName, - collectionName: "projectStatistics", + upstashDriver({ + url: useRuntimeConfig().upstash.redis.restUrl, + token: useRuntimeConfig().upstash.redis.restToken, + base: "projectStatistics", }), ); storage.mount( "metadata", - mongodbDriver({ - connectionString: useRuntimeConfig().mongodb.connectionString, - databaseName: useRuntimeConfig().mongodb.databaseName, - collectionName: "metadata", + upstashDriver({ + url: useRuntimeConfig().upstash.redis.restUrl, + token: useRuntimeConfig().upstash.redis.restToken, + base: "metadata", }), ); });