From 789b8b36d81a53b0d935aba814de0ea3a6f45bf0 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 18 Aug 2025 22:30:22 -0700 Subject: [PATCH] Link route. --- package.json | 6 +- pnpm-lock.yaml | 104 ++++++++++++++-------------- src/app/(collect)/q/[slug]/route.ts | 37 ++++++++++ src/app/api/send/route.ts | 4 +- 4 files changed, 93 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index e62c41ec..590c9174 100644 --- a/package.json +++ b/package.json @@ -105,14 +105,14 @@ "is-ci": "^3.0.1", "is-docker": "^3.0.0", "is-localhost-ip": "^2.0.0", - "isbot": "^5.1.16", + "isbot": "^5.1.30", "jsonwebtoken": "^9.0.2", "jszip": "^3.10.1", "kafkajs": "^2.1.0", - "lucide-react": "^0.526.0", + "lucide-react": "^0.540.0", "maxmind": "^4.3.28", "md5": "^2.3.0", - "next": "15.4.6", + "next": "15.4.7", "node-fetch": "^3.2.8", "npm-run-all": "^4.1.5", "papaparse": "^5.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c00d5f28..7fb9a26e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -114,8 +114,8 @@ importers: specifier: ^2.0.0 version: 2.0.0 isbot: - specifier: ^5.1.16 - version: 5.1.29 + specifier: ^5.1.30 + version: 5.1.30 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 @@ -126,8 +126,8 @@ importers: specifier: ^2.1.0 version: 2.2.4 lucide-react: - specifier: ^0.526.0 - version: 0.526.0(react@19.1.1) + specifier: ^0.540.0 + version: 0.540.0(react@19.1.1) maxmind: specifier: ^4.3.28 version: 4.3.29 @@ -135,8 +135,8 @@ importers: specifier: ^2.3.0 version: 2.3.0 next: - specifier: 15.4.6 - version: 15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: 15.4.7 + version: 15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) node-fetch: specifier: ^3.2.8 version: 3.3.2 @@ -1382,56 +1382,56 @@ packages: resolution: {integrity: sha512-SXQY/nCiSOSAZWNls/DQxrICldUR7PHSMUw2J2/ZejH1dk12Vwd3+SzSihHrRW9PNcErZkC2g3seM7bWZlvBRg==} engines: {node: '>=18.0.0'} - '@next/env@15.4.6': - resolution: {integrity: sha512-yHDKVTcHrZy/8TWhj0B23ylKv5ypocuCwey9ZqPyv4rPdUdRzpGCkSi03t04KBPyU96kxVtUqx6O3nE1kpxASQ==} + '@next/env@15.4.7': + resolution: {integrity: sha512-PrBIpO8oljZGTOe9HH0miix1w5MUiGJ/q83Jge03mHEE0E3pyqzAy2+l5G6aJDbXoobmxPJTVhbCuwlLtjSHwg==} '@next/eslint-plugin-next@14.2.31': resolution: {integrity: sha512-ouaB+l8Cr/uzGxoGHUvd01OnfFTM8qM81Crw1AG0xoWDRN0DKLXyTWVe0FdAOHVBpGuXB87aufdRmrwzZDArIw==} - '@next/swc-darwin-arm64@15.4.6': - resolution: {integrity: sha512-667R0RTP4DwxzmrqTs4Lr5dcEda9OxuZsVFsjVtxVMVhzSpo6nLclXejJVfQo2/g7/Z9qF3ETDmN3h65mTjpTQ==} + '@next/swc-darwin-arm64@15.4.7': + resolution: {integrity: sha512-2Dkb+VUTp9kHHkSqtws4fDl2Oxms29HcZBwFIda1X7Ztudzy7M6XF9HDS2dq85TmdN47VpuhjE+i6wgnIboVzQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.6': - resolution: {integrity: sha512-KMSFoistFkaiQYVQQnaU9MPWtp/3m0kn2Xed1Ces5ll+ag1+rlac20sxG+MqhH2qYWX1O2GFOATQXEyxKiIscg==} + '@next/swc-darwin-x64@15.4.7': + resolution: {integrity: sha512-qaMnEozKdWezlmh1OGDVFueFv2z9lWTcLvt7e39QA3YOvZHNpN2rLs/IQLwZaUiw2jSvxW07LxMCWtOqsWFNQg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.6': - resolution: {integrity: sha512-PnOx1YdO0W7m/HWFeYd2A6JtBO8O8Eb9h6nfJia2Dw1sRHoHpNf6lN1U4GKFRzRDBi9Nq2GrHk9PF3Vmwf7XVw==} + '@next/swc-linux-arm64-gnu@15.4.7': + resolution: {integrity: sha512-ny7lODPE7a15Qms8LZiN9wjNWIeI+iAZOFDOnv2pcHStncUr7cr9lD5XF81mdhrBXLUP9yT9RzlmSWKIazWoDw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.6': - resolution: {integrity: sha512-XBbuQddtY1p5FGPc2naMO0kqs4YYtLYK/8aPausI5lyOjr4J77KTG9mtlU4P3NwkLI1+OjsPzKVvSJdMs3cFaw==} + '@next/swc-linux-arm64-musl@15.4.7': + resolution: {integrity: sha512-4SaCjlFR/2hGJqZLLWycccy1t+wBrE/vyJWnYaZJhUVHccpGLG5q0C+Xkw4iRzUIkE+/dr90MJRUym3s1+vO8A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.6': - resolution: {integrity: sha512-+WTeK7Qdw82ez3U9JgD+igBAP75gqZ1vbK6R8PlEEuY0OIe5FuYXA4aTjL811kWPf7hNeslD4hHK2WoM9W0IgA==} + '@next/swc-linux-x64-gnu@15.4.7': + resolution: {integrity: sha512-2uNXjxvONyRidg00VwvlTYDwC9EgCGNzPAPYbttIATZRxmOZ3hllk/YYESzHZb65eyZfBR5g9xgCZjRAl9YYGg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.6': - resolution: {integrity: sha512-XP824mCbgQsK20jlXKrUpZoh/iO3vUWhMpxCz8oYeagoiZ4V0TQiKy0ASji1KK6IAe3DYGfj5RfKP6+L2020OQ==} + '@next/swc-linux-x64-musl@15.4.7': + resolution: {integrity: sha512-ceNbPjsFgLscYNGKSu4I6LYaadq2B8tcK116nVuInpHHdAWLWSwVK6CHNvCi0wVS9+TTArIFKJGsEyVD1H+4Kg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.4.6': - resolution: {integrity: sha512-FxrsenhUz0LbgRkNWx6FRRJIPe/MI1JRA4W4EPd5leXO00AZ6YU8v5vfx4MDXTvN77lM/EqsE3+6d2CIeF5NYg==} + '@next/swc-win32-arm64-msvc@15.4.7': + resolution: {integrity: sha512-pZyxmY1iHlZJ04LUL7Css8bNvsYAMYOY9JRwFA3HZgpaNKsJSowD09Vg2R9734GxAcLJc2KDQHSCR91uD6/AAw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.6': - resolution: {integrity: sha512-T4ufqnZ4u88ZheczkBTtOF+eKaM14V8kbjud/XrAakoM5DKQWjW09vD6B9fsdsWS2T7D5EY31hRHdta7QKWOng==} + '@next/swc-win32-x64-msvc@15.4.7': + resolution: {integrity: sha512-HjuwPJ7BeRzgl3KrjKqD2iDng0eQIpIReyhpF5r4yeAHFwWRuAhfW92rWv/r3qeQHEwHsLRzFDvMqRjyM5DI6A==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4548,8 +4548,8 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isbot@5.1.29: - resolution: {integrity: sha512-DelDWWoa3mBoyWTq3wjp+GIWx/yZdN7zLUE7NFhKjAiJ+uJVRkbLlwykdduCE4sPUUy8mlTYTmdhBUYu91F+sw==} + isbot@5.1.30: + resolution: {integrity: sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA==} engines: {node: '>=18'} isexe@2.0.0: @@ -4996,8 +4996,8 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - lucide-react@0.526.0: - resolution: {integrity: sha512-uGWG/2RKuDLeQHCodn5cmJ9Zij80EstOdcBP+j//B2sr78w7woiEL4aMu6CRlRkyOyJ8sZry8QLhQTmZjynLdA==} + lucide-react@0.540.0: + resolution: {integrity: sha512-armkCAqQvO62EIX4Hq7hqX/q11WSZu0Jd23cnnqx0/49yIxGXyL/zyZfBxNN9YDx0ensPTb4L+DjTh3yQXUxtQ==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -5177,8 +5177,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - next@15.4.6: - resolution: {integrity: sha512-us++E/Q80/8+UekzB3SAGs71AlLDsadpFMXVNM/uQ0BMwsh9m3mr0UNQIfjKed8vpWXsASe+Qifrnu1oLIcKEQ==} + next@15.4.7: + resolution: {integrity: sha512-OcqRugwF7n7mC8OSYjvsZhhG1AYSvulor1EIUsIkbbEbf1qoE5EbH36Swj8WhF4cHqmDgkiam3z1c1W0J1Wifg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -8178,34 +8178,34 @@ snapshots: '@netlify/plugin-nextjs@5.12.0': {} - '@next/env@15.4.6': {} + '@next/env@15.4.7': {} '@next/eslint-plugin-next@14.2.31': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@15.4.6': + '@next/swc-darwin-arm64@15.4.7': optional: true - '@next/swc-darwin-x64@15.4.6': + '@next/swc-darwin-x64@15.4.7': optional: true - '@next/swc-linux-arm64-gnu@15.4.6': + '@next/swc-linux-arm64-gnu@15.4.7': optional: true - '@next/swc-linux-arm64-musl@15.4.6': + '@next/swc-linux-arm64-musl@15.4.7': optional: true - '@next/swc-linux-x64-gnu@15.4.6': + '@next/swc-linux-x64-gnu@15.4.7': optional: true - '@next/swc-linux-x64-musl@15.4.6': + '@next/swc-linux-x64-musl@15.4.7': optional: true - '@next/swc-win32-arm64-msvc@15.4.6': + '@next/swc-win32-arm64-msvc@15.4.7': optional: true - '@next/swc-win32-x64-msvc@15.4.6': + '@next/swc-win32-x64-msvc@15.4.7': optional: true '@nodelib/fs.scandir@2.1.5': @@ -9856,7 +9856,7 @@ snapshots: glob: 10.4.5 highlight.js: 11.11.1 lucide-react: 0.511.0(react@19.1.1) - next: 15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + next: 15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react: 19.1.1 react-aria-components: 1.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react-dom: 19.1.1(react@19.1.1) @@ -12128,7 +12128,7 @@ snapshots: isarray@2.0.5: {} - isbot@5.1.29: {} + isbot@5.1.30: {} isexe@2.0.0: {} @@ -12792,7 +12792,7 @@ snapshots: dependencies: react: 19.1.1 - lucide-react@0.526.0(react@19.1.1): + lucide-react@0.540.0(react@19.1.1): dependencies: react: 19.1.1 @@ -12959,9 +12959,9 @@ snapshots: neo-async@2.6.2: {} - next@15.4.6(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + next@15.4.7(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - '@next/env': 15.4.6 + '@next/env': 15.4.7 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001735 postcss: 8.4.31 @@ -12969,14 +12969,14 @@ snapshots: react-dom: 19.1.1(react@19.1.1) styled-jsx: 5.1.6(@babel/core@7.28.3)(react@19.1.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.6 - '@next/swc-darwin-x64': 15.4.6 - '@next/swc-linux-arm64-gnu': 15.4.6 - '@next/swc-linux-arm64-musl': 15.4.6 - '@next/swc-linux-x64-gnu': 15.4.6 - '@next/swc-linux-x64-musl': 15.4.6 - '@next/swc-win32-arm64-msvc': 15.4.6 - '@next/swc-win32-x64-msvc': 15.4.6 + '@next/swc-darwin-arm64': 15.4.7 + '@next/swc-darwin-x64': 15.4.7 + '@next/swc-linux-arm64-gnu': 15.4.7 + '@next/swc-linux-arm64-musl': 15.4.7 + '@next/swc-linux-x64-gnu': 15.4.7 + '@next/swc-linux-x64-musl': 15.4.7 + '@next/swc-win32-arm64-msvc': 15.4.7 + '@next/swc-win32-x64-msvc': 15.4.7 babel-plugin-react-compiler: 19.1.0-rc.2 sharp: 0.34.3 transitivePeerDependencies: diff --git a/src/app/(collect)/q/[slug]/route.ts b/src/app/(collect)/q/[slug]/route.ts index e69de29b..4c0f683c 100644 --- a/src/app/(collect)/q/[slug]/route.ts +++ b/src/app/(collect)/q/[slug]/route.ts @@ -0,0 +1,37 @@ +import { NextResponse } from 'next/server'; +import { notFound } from '@/lib/response'; +import { findLink } from '@/queries'; +import { POST } from '@/app/api/send/route'; + +export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { + const { slug } = await params; + + const link = await findLink({ + where: { + slug, + }, + }); + + if (!link) { + return notFound(); + } + + const payload = { + type: 'event', + payload: { + link: link.id, + url: request.url, + referrer: request.referrer, + }, + }; + + const req = new Request(request.url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + await POST(req); + + return NextResponse.redirect(link.url); +} diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index 0b177f08..652ff4f0 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -257,9 +257,7 @@ export async function POST(request: Request) { lifatid, twclid, }); - } - - if (type === COLLECTION_TYPE.identify) { + } else if (type === COLLECTION_TYPE.identify) { if (data) { await saveSessionData({ websiteId,