aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--middleware/package.json1
-rw-r--r--middleware/pnpm-lock.yaml15
-rw-r--r--middleware/src/app/api/notifications/get/route.ts26
-rw-r--r--middleware/src/app/api/notifications/set/route.ts30
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 });
+}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage