From d5f3c2b2af2f4888cafb82e6bedf7434259ac399 Mon Sep 17 00:00:00 2001 From: swh00tw Date: Wed, 28 Feb 2024 15:22:20 -0500 Subject: [PATCH 1/6] feat: add ga --- apps/recnet/src/app/layout.tsx | 4 ++++ package.json | 1 + pnpm-lock.yaml | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/apps/recnet/src/app/layout.tsx b/apps/recnet/src/app/layout.tsx index 10664296..db7e7240 100644 --- a/apps/recnet/src/app/layout.tsx +++ b/apps/recnet/src/app/layout.tsx @@ -11,6 +11,7 @@ import "@radix-ui/themes/styles.css"; import "tailwindcss/tailwind.css"; import { MobileNavigator } from "./MobileNavigator"; import { ProgressbarProvider } from "./Progressbar"; +import { GoogleAnalytics } from "@next/third-parties/google"; const sfpro = localFont({ src: [ @@ -121,6 +122,9 @@ export default async function RootLayout({ const user = await getUserServerSide(); return ( + diff --git a/package.json b/package.json index 23033b07..eed8d65f 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "private": true, "dependencies": { "@hookform/resolvers": "^3.3.4", + "@next/third-parties": "^14.1.0", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "@radix-ui/themes": "^2.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 152d06af..d8cae272 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ dependencies: '@hookform/resolvers': specifier: ^3.3.4 version: 3.3.4(react-hook-form@7.50.0) + '@next/third-parties': + specifier: ^14.1.0 + version: 14.1.0(next@14.1.0)(react@18.2.0) '@radix-ui/react-icons': specifier: ^1.3.0 version: 1.3.0(react@18.2.0) @@ -3083,6 +3086,17 @@ packages: requiresBuild: true optional: true + /@next/third-parties@14.1.0(next@14.1.0)(react@18.2.0): + resolution: {integrity: sha512-f55SdvQ1WWxi4mb5QqtYQh5wRzbm1XaeP7s39DPn4ks3re+n9VlFccbMxBRHqkE62zAyIKmvkUB2cByT/gugGA==} + peerDependencies: + next: ^13.0.0 || ^14.0.0 + react: ^18.2.0 + dependencies: + next: 14.1.0(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + third-party-capital: 1.0.20 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -14529,6 +14543,10 @@ packages: dependencies: any-promise: 1.3.0 + /third-party-capital@1.0.20: + resolution: {integrity: sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA==} + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true From ea17b867be62d00da189e2a53931057b0fd11ad0 Mon Sep 17 00:00:00 2001 From: swh00tw Date: Wed, 28 Feb 2024 15:41:38 -0500 Subject: [PATCH 2/6] feat: use zod to parse client env vars --- apps/recnet/src/clientConfig.ts | 6 ------ apps/recnet/src/clientEnv.ts | 32 ++++++++++++++++++++++++++++++ apps/recnet/src/firebase/client.ts | 4 ++-- 3 files changed, 34 insertions(+), 8 deletions(-) delete mode 100644 apps/recnet/src/clientConfig.ts create mode 100644 apps/recnet/src/clientEnv.ts diff --git a/apps/recnet/src/clientConfig.ts b/apps/recnet/src/clientConfig.ts deleted file mode 100644 index 1c82b0f9..00000000 --- a/apps/recnet/src/clientConfig.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const clientConfig = { - apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, - authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, - projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, - appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID, -}; diff --git a/apps/recnet/src/clientEnv.ts b/apps/recnet/src/clientEnv.ts new file mode 100644 index 00000000..41cbb362 --- /dev/null +++ b/apps/recnet/src/clientEnv.ts @@ -0,0 +1,32 @@ +import { z } from "zod"; + +export const clientEnvSchema = z.object({ + NEXT_PUBLIC_FIREBASE_API_KEY: z.string(), + NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: z.string(), + NEXT_PUBLIC_FIREBASE_PROJECT_ID: z.string(), + NEXT_PUBLIC_FIREBASE_APP_ID: z.string(), + NEXT_PUBLIC_GA_TRACKING_ID: z.string(), +}); + +const clientEnvRes = clientEnvSchema.safeParse({ + NEXT_PUBLIC_FIREBASE_API_KEY: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, + NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: + process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, + NEXT_PUBLIC_FIREBASE_PROJECT_ID: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, + NEXT_PUBLIC_FIREBASE_APP_ID: process.env.NEXT_PUBLIC_FIREBASE_APP_ID, + NEXT_PUBLIC_GA_TRACKING_ID: process.env.NEXT_PUBLIC_GA_TRACKING_ID, +}); + +if (!clientEnvRes.success) { + // console.error(clientEnvRes.error.issues); + throw new Error("There is an error with the CLIENT environment variables"); +} + +export const clientEnv = clientEnvRes.data; + +export const firebaseClientEnv = { + apiKey: clientEnvRes.data.NEXT_PUBLIC_FIREBASE_API_KEY, + authDomain: clientEnvRes.data.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, + projectId: clientEnvRes.data.NEXT_PUBLIC_FIREBASE_PROJECT_ID, + appId: clientEnvRes.data.NEXT_PUBLIC_FIREBASE_APP_ID, +}; diff --git a/apps/recnet/src/firebase/client.ts b/apps/recnet/src/firebase/client.ts index 4c7c397b..a794b183 100644 --- a/apps/recnet/src/firebase/client.ts +++ b/apps/recnet/src/firebase/client.ts @@ -1,13 +1,13 @@ import { initializeApp, getApp, getApps } from "firebase/app"; import { getAuth } from "firebase/auth"; -import { clientConfig } from "@/clientConfig"; +import { firebaseClientEnv } from "@/clientEnv"; export const getFirebaseApp = () => { if (getApps().length) { return getApp(); } - const app = initializeApp(clientConfig); + const app = initializeApp(firebaseClientEnv); return app; }; From 0d20f7cfb1dd3e60d3bba3dc30a409b97e911f79 Mon Sep 17 00:00:00 2001 From: swh00tw Date: Wed, 28 Feb 2024 15:55:03 -0500 Subject: [PATCH 3/6] feat: use zod to parse server env --- apps/recnet/src/serverConfig.ts | 45 ++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/apps/recnet/src/serverConfig.ts b/apps/recnet/src/serverConfig.ts index 79843d07..dc024f75 100644 --- a/apps/recnet/src/serverConfig.ts +++ b/apps/recnet/src/serverConfig.ts @@ -1,17 +1,48 @@ -export const serverConfig = { - useSecureCookies: process.env.USE_SECURE_COOKIES === "true", - firebaseApiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!, +import { z } from "zod"; + +const serverConfigSchema = z.object({ + USE_SECURE_COOKIES: z.coerce.boolean(), + COOKIE_SIGNATURE_KEY: z.string(), + FIREBASE_PRIVATE_KEY: z.string().transform((s) => s.replace(/\\n/gm, "\n")), + FIREBASE_CLIENT_EMAIL: z.string(), + CRON_SECRET: z.string(), + NEXT_PUBLIC_FIREBASE_API_KEY: z.string(), + NEXT_PUBLIC_FIREBASE_PROJECT_ID: z.string(), +}); + +const serverConfigRes = serverConfigSchema.safeParse({ + USE_SECURE_COOKIES: process.env.USE_SECURE_COOKIES, + COOKIE_SIGNATURE_KEY: process.env.COOKIE_SIGNATURE_KEY, + FIREBASE_PRIVATE_KEY: process.env.FIREBASE_PRIVATE_KEY, + FIREBASE_CLIENT_EMAIL: process.env.FIREBASE_CLIENT_EMAIL, + CRON_SECRET: process.env.CRON_SECRET, + NEXT_PUBLIC_FIREBASE_API_KEY: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, + NEXT_PUBLIC_FIREBASE_PROJECT_ID: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, +}); + +if (!serverConfigRes.success) { + console.error(serverConfigRes.error.issues); + throw new Error("There is an error with the SERVER environment variables"); + process.exit(1); +} + +export const serverEnv = serverConfigRes.data; + +const serverConfig = { + useSecureCookies: serverConfigRes.data.USE_SECURE_COOKIES, + firebaseApiKey: serverConfigRes.data.NEXT_PUBLIC_FIREBASE_API_KEY, serviceAccount: { - projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!, - clientEmail: process.env.FIREBASE_CLIENT_EMAIL!, - privateKey: process.env.FIREBASE_PRIVATE_KEY!.replace(/\\n/gm, "\n"), + projectId: serverConfigRes.data.NEXT_PUBLIC_FIREBASE_PROJECT_ID, + clientEmail: serverConfigRes.data.FIREBASE_CLIENT_EMAIL, + privateKey: serverConfigRes.data.FIREBASE_PRIVATE_KEY, }, + cookieSignatureKey: serverConfigRes.data.COOKIE_SIGNATURE_KEY, }; export const authConfig = { apiKey: serverConfig.firebaseApiKey, cookieName: "AuthToken", - cookieSignatureKeys: [process.env.COOKIE_SIGNATURE_KEY!], + cookieSignatureKeys: [serverConfig.cookieSignatureKey], cookieSerializeOptions: { path: "/", httpOnly: true, From 6c40903f55475b98491bd4f8d36ec3cbffd0941f Mon Sep 17 00:00:00 2001 From: swh00tw Date: Wed, 28 Feb 2024 15:55:54 -0500 Subject: [PATCH 4/6] refactor: rename server env file --- apps/recnet/src/middleware.ts | 2 +- apps/recnet/src/{serverConfig.ts => serverEnv.ts} | 0 apps/recnet/src/utils/getUserServerSide.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename apps/recnet/src/{serverConfig.ts => serverEnv.ts} (100%) diff --git a/apps/recnet/src/middleware.ts b/apps/recnet/src/middleware.ts index 197b7743..9eb75a4d 100644 --- a/apps/recnet/src/middleware.ts +++ b/apps/recnet/src/middleware.ts @@ -1,6 +1,6 @@ import { NextRequest } from "next/server"; import { authMiddleware } from "next-firebase-auth-edge"; -import { authConfig } from "./serverConfig"; +import { authConfig } from "./serverEnv"; export async function middleware(request: NextRequest) { return authMiddleware(request, { diff --git a/apps/recnet/src/serverConfig.ts b/apps/recnet/src/serverEnv.ts similarity index 100% rename from apps/recnet/src/serverConfig.ts rename to apps/recnet/src/serverEnv.ts diff --git a/apps/recnet/src/utils/getUserServerSide.ts b/apps/recnet/src/utils/getUserServerSide.ts index ff00636f..ed3b13e4 100644 --- a/apps/recnet/src/utils/getUserServerSide.ts +++ b/apps/recnet/src/utils/getUserServerSide.ts @@ -1,7 +1,7 @@ import "server-only"; import { Tokens, getTokens } from "next-firebase-auth-edge"; import { cookies } from "next/headers"; -import { authConfig } from "@/serverConfig"; +import { authConfig } from "@/serverEnv"; import { User } from "@/types/user"; import { getUserByEmail } from "@/server/user"; From efca7487745bce334e6b16edcc051b2ce6f8adfb Mon Sep 17 00:00:00 2001 From: swh00tw Date: Wed, 28 Feb 2024 16:49:30 -0500 Subject: [PATCH 5/6] fix: suppress weird error (import stuff from client component in RSC) --- apps/recnet/src/app/error.tsx | 3 +-- apps/recnet/src/app/not-found.tsx | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/recnet/src/app/error.tsx b/apps/recnet/src/app/error.tsx index 0f2ca065..b8e6cdb8 100644 --- a/apps/recnet/src/app/error.tsx +++ b/apps/recnet/src/app/error.tsx @@ -3,8 +3,7 @@ import { cn } from "@/utils/cn"; import { Flex, Text } from "@radix-ui/themes"; import { RecNetLink } from "@/components/Link"; - -export const ReportEmailAccount = "lil.recnet@gmail.com"; +import { ReportEmailAccount } from "./not-found"; export default function NotFoundPage() { return ( diff --git a/apps/recnet/src/app/not-found.tsx b/apps/recnet/src/app/not-found.tsx index 5d0e5407..e7b4f7c6 100644 --- a/apps/recnet/src/app/not-found.tsx +++ b/apps/recnet/src/app/not-found.tsx @@ -1,7 +1,8 @@ import { cn } from "@/utils/cn"; import { Flex, Text } from "@radix-ui/themes"; import { RecNetLink } from "@/components/Link"; -import { ReportEmailAccount } from "@/app/error"; + +export const ReportEmailAccount = "lil.recnet@gmail.com"; export default function NotFoundPage() { return ( From b81f166818b70ee6aa4c316f38d4caa9cb98bbb6 Mon Sep 17 00:00:00 2001 From: swh00tw Date: Thu, 29 Feb 2024 00:52:04 -0500 Subject: [PATCH 6/6] fix: remove email testing list --- apps/recnet/src/app/api/sendDigest/route.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/recnet/src/app/api/sendDigest/route.ts b/apps/recnet/src/app/api/sendDigest/route.ts index 28f695f7..c754ee6f 100644 --- a/apps/recnet/src/app/api/sendDigest/route.ts +++ b/apps/recnet/src/app/api/sendDigest/route.ts @@ -8,7 +8,7 @@ import WeeklyDigest from "../../../../emails/WeeklyDigest"; import { render } from "@react-email/render"; import { NextRequest, NextResponse } from "next/server"; -const TEST_USER_IDS = ["GoXnHBhgK8QhcZpki0la"]; +// const TEST_USER_IDS = ["GoXnHBhgK8QhcZpki0la"]; export async function GET(request: NextRequest) { if ( @@ -39,9 +39,9 @@ export async function GET(request: NextRequest) { const user = res.data; // test within certain user ids - if (!TEST_USER_IDS.includes(user.id)) { - return; - } + // if (!TEST_USER_IDS.includes(user.id)) { + // return; + // } const recs = await getFeedsRecs(user?.id, getLatestCutOff().getTime()); const recsWithUsers = await getRecsWithUsers(recs);