diff options
Diffstat (limited to 'middleware')
| -rw-r--r-- | middleware/package.json | 1 | ||||
| -rw-r--r-- | middleware/pnpm-lock.yaml | 15 | ||||
| -rw-r--r-- | middleware/src/app/api/notifications/get/route.ts | 26 | ||||
| -rw-r--r-- | middleware/src/app/api/notifications/set/route.ts | 30 |
4 files changed, 72 insertions, 0 deletions
diff --git a/middleware/package.json b/middleware/package.json index a4446e3..573ce36 100644 --- a/middleware/package.json +++ b/middleware/package.json @@ -13,6 +13,7 @@ "@types/node": "24.0.8", "@types/react": "19.1.8", "@types/react-dom": "19.1.6", + "@upstash/redis": "^1.35.4", "@vercel/analytics": "^1.5.0", "@vercel/og": "^0.6.8", "eslint": "9.30.0", diff --git a/middleware/pnpm-lock.yaml b/middleware/pnpm-lock.yaml index 99b252e..03cf243 100644 --- a/middleware/pnpm-lock.yaml +++ b/middleware/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@types/react-dom': specifier: 19.1.6 version: 19.1.6(@types/react@19.1.8) + '@upstash/redis': + specifier: ^1.35.4 + version: 1.35.4 '@vercel/analytics': specifier: ^1.5.0 version: 1.5.0(next@15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) @@ -513,6 +516,9 @@ packages: cpu: [x64] os: [win32] + '@upstash/redis@1.35.4': + resolution: {integrity: sha512-WE1ZnhFyBiIjTDW13GbO6JjkiMVVjw5VsvS8ENmvvJsze/caMQ5paxVD44+U68IUVmkXcbsLSoE+VIYsHtbQEw==} + '@vercel/analytics@1.5.0': resolution: {integrity: sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==} peerDependencies: @@ -1659,6 +1665,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@7.8.0: resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} @@ -2109,6 +2118,10 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.9.2': optional: true + '@upstash/redis@1.35.4': + dependencies: + uncrypto: 0.1.3 + '@vercel/analytics@1.5.0(next@15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)': optionalDependencies: next: 15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -3512,6 +3525,8 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + uncrypto@0.1.3: {} + undici-types@7.8.0: {} unicode-trie@2.0.0: diff --git a/middleware/src/app/api/notifications/get/route.ts b/middleware/src/app/api/notifications/get/route.ts new file mode 100644 index 0000000..344e41b --- /dev/null +++ b/middleware/src/app/api/notifications/get/route.ts @@ -0,0 +1,26 @@ +import { Redis } from "@upstash/redis"; + +export const runtime = "edge"; + +const redis = new Redis({ + url: process.env.KV_REST_API_URL!, + token: process.env.KV_REST_API_TOKEN!, +}); + +// /api/fcm/list?topic=<topic> +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const topic = searchParams.get("topic"); + + if (!topic) { + return new Response(JSON.stringify({ error: "Missing topic" }), { status: 400 }); + } + + const key = `fcm-${topic}`; + const tokens = await redis.smembers<string[]>(key); + + return new Response(JSON.stringify({ topic, tokens }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +} diff --git a/middleware/src/app/api/notifications/set/route.ts b/middleware/src/app/api/notifications/set/route.ts new file mode 100644 index 0000000..3a584fb --- /dev/null +++ b/middleware/src/app/api/notifications/set/route.ts @@ -0,0 +1,30 @@ +import { Redis } from "@upstash/redis"; + +export const runtime = "edge"; +const redis = new Redis({ + url: process.env.KV_REST_API_URL!, + token: process.env.KV_REST_API_TOKEN!, +}); + +// /api/fcm?topic=<topic>&token=<fcm_token>&action=subscribe|unsubscribe +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const topic = searchParams.get("topic"); + const token = searchParams.get("token"); + const action = searchParams.get("action"); // "subscribe" | "unsubscribe" + + if (!topic || !token || !action) { + return new Response(JSON.stringify({ error: "Missing params" }), { status: 400 }); + } + const key = `fcm-${topic}`; + + if (action === "subscribe") { + await redis.sadd(key, token); + } else if (action === "unsubscribe") { + await redis.srem(key, token); + } else { + return new Response(JSON.stringify({ error: "Invalid action" }), { status: 400 }); + } + + return new Response(JSON.stringify({ success: true }), { status: 200 }); +} |
