diff --git a/server/.env.local b/server/.env.local new file mode 100644 index 00000000..8408bb3f --- /dev/null +++ b/server/.env.local @@ -0,0 +1,33 @@ +POSTGRES_HOST= +POSTGRES_DB=comm_ng +POSTGRES_SSL=true +AWS_REGION="us-east-1" +DB_SECRET_ID= +DB_SECRET_REFRESH_INTERVAL_MS=30000 +# uncomment if using drizzle studio / if you want to not use secrets manager +# POSTGRES_USER=comm_ng_dev_user +# POSTGRES_PASSWORD= + + +# local pg (user either these 3, or the above 6, but not both) +# POSTGRES_USER=commng-pg-user +# POSTGRES_PASSWORD= +# POSTGRES_DB=comm_ng + +BETTER_AUTH_SECRET= + +S3_BUCKET_NAME= +AWS_REGION=us-east-1 +USE_PRESIGNED_UPLOADS=true + +BACKEND_URL=http://localhost:3000 + +VAPID_PUBLIC_KEY= +VAPID_PRIVATE_KEY= +VAPID_CONTACT_EMAIL=mailto:admin@example.com + +PORT=3000 +LOG_LEVEL=debug + +# add this if you don't have aws signed in, if this varible is not added/is set to true, it assumes aws exists and is enabled +EMBEDDINGS_ENABLED=false \ No newline at end of file diff --git a/server/package.json b/server/package.json index 0e6a5cca..a7319c8a 100644 --- a/server/package.json +++ b/server/package.json @@ -39,7 +39,7 @@ "@aws-sdk/s3-request-presigner": "^3.937.0", "@trpc/client": "^11.6.0", "@trpc/server": "^11.6.0", - "better-auth": "^1.3.27", + "better-auth": "1.4", "cors": "^2.8.5", "drizzle-orm": "^0.44.6", "express": "^5.1.0", @@ -52,6 +52,7 @@ "trpc-to-openapi": "^3.1.0", "tsx": "^4.20.6", "web-push": "^3.6.7", - "zod": "^4.1.13" + "zod": "^4.3.6", + "zod-openapi": "^5.4.6" } } diff --git a/server/scripts/create-user.ts b/server/scripts/create-user.ts index b7854b51..5be0ab5b 100644 --- a/server/scripts/create-user.ts +++ b/server/scripts/create-user.ts @@ -1,91 +1,103 @@ import { auth } from "../src/auth.js"; -import { connectPostgres, shutdownPostgres } from "../src/data/db/sql.js"; +import { connectPostgres, db, shutdownPostgres } from "../src/data/db/sql.js"; +import { users } from "../src/data/db/schema.js"; +import { eq } from "drizzle-orm"; /** - * Script to create a new user account using better-auth - * - * Edit the userData object below with the user details you want to create. - * - * Usage: - * cd server - * npx tsx --env-file=.env scripts/create-user.ts - */ + * Script to create a new user account using better-auth + * + * Edit the userData object below with the user details you want to create. + * + * Usage: + *   cd server + *   npx tsx --env-file=.env scripts/create-user.ts + */ async function createUser() { - // Ensure the DB pool is connected (uses Secrets Manager if enabled) - await connectPostgres(); - // Edit this object to create a new user - const userData = { - email: "basic@basic.basic", - password: "password", - name: "Basic User", - phoneNumber: "555-123-1234", // optional - rank: "Captain", // optional - department: "Engineering", // optional - branch: "Army", // optional - positionType: "active", - civilianCareer: "Engineering Manager", - signalVisibility: "public", - emailVisibility: "public", - interests: '"Engineering, Technology"', - location: "Boston", - about: "I am an engineer with a passion for technology.", - }; +  // Ensure the DB pool is connected (uses Secrets Manager if enabled) +  await connectPostgres(); +  // Edit this object to create a new user +  const userData = { +    email: "basic@basic.basic", +    password: "password", +    name: "Basic User", +    phoneNumber: "555-123-1234", // optional +    rank: "Captain", // optional +    department: "Engineering", // optional +    branch: "Army", // optional +    positionType: "active", +    civilianCareer: "Engineering Manager", +    signalVisibility: "public", +    emailVisibility: "public", +    interests: '"Engineering, Technology"', +    location: "Boston", +    about: "I am an engineer with a passion for technology.", +  }; - console.log("Creating user with the following details:"); - console.log(` Email: ${userData.email}`); - console.log(` Name: ${userData.name}`); - if (userData.phoneNumber) console.log(` Phone: ${userData.phoneNumber}`); - if (userData.rank) console.log(` Rank: ${userData.rank}`); - if (userData.department) console.log(` Department: ${userData.department}`); - if (userData.branch) console.log(` Branch: ${userData.branch}`); - console.log(""); +  console.log("Creating user with the following details:"); +  console.log(`  Email: ${userData.email}`); +  console.log(`  Name: ${userData.name}`); +  if (userData.phoneNumber) console.log(`  Phone: ${userData.phoneNumber}`); +  if (userData.rank) console.log(`  Rank: ${userData.rank}`); +  if (userData.department) console.log(`  Department: ${userData.department}`); +  if (userData.branch) console.log(`  Branch: ${userData.branch}`); +  console.log(""); - try { - // Use better-auth's internal API to create the user - const result = await auth.api.signUpEmail({ - body: { - email: userData.email.toLowerCase().trim(), - password: userData.password, - name: userData.name.trim(), - phoneNumber: userData.phoneNumber, - rank: userData.rank, - department: userData.department, - branch: userData.branch, - positionType: userData.positionType, - civilianCareer: userData.civilianCareer, - signalVisibility: userData.signalVisibility, - emailVisibility: userData.emailVisibility, - location: userData.location, - about: userData.about, - }, - }); +  try { +    // Use better-auth's internal API to create the user +    // Note: We exclude enum fields (positionType, signalVisibility, emailVisibility) +    // because better-auth wraps them in objects when validators are present +    const result = await auth.api.signUpEmail({ +      body: { +        email: userData.email.toLowerCase().trim(), +        password: userData.password, +        name: userData.name.trim(), +        phoneNumber: userData.phoneNumber, +        rank: userData.rank, +        department: userData.department, +        branch: userData.branch, +        civilianCareer: userData.civilianCareer, +        location: userData.location, +        about: userData.about, +      }, +    }); - if (!result || "error" in result) { - console.error("Failed to create user:"); - console.error(result); - process.exit(1); - } +    if (!result || "error" in result) { +      console.error("Failed to create user:"); +      console.error(result); +      process.exit(1); +    } - console.log("✓ Successfully created user!"); - console.log(` User ID: ${result.user.id}`); - console.log(` Email: ${result.user.email}`); - console.log(` Name: ${result.user.name}`); - } catch (error) { - console.error("Error creating user:", error); - throw error; - } +    console.log("✓ Successfully created user!"); +    // Update enum fields separately to avoid better-auth wrapping them in objects +    await db +      .update(users) +      .set({ +        positionType: userData.positionType as "active" | "part-time", +        signalVisibility: userData.signalVisibility as "private" | "public", +        emailVisibility: userData.emailVisibility as "private" | "public", +        interests: userData.interests ? JSON.parse(userData.interests) : [], +      }) +      .where(eq(users.id, result.user.id)); + +    console.log(`  User ID: ${result.user.id}`); +    console.log(`  Email: ${result.user.email}`); +    console.log(`  Name: ${result.user.name}`); +  } catch (error) { +    console.error("Error creating user:", error); +    throw error; +  } } createUser() - .then(() => { - console.log("\nDone!"); - process.exit(0); - }) - .catch((error) => { - console.error("\nFailed to create user:", error); - process.exit(1); - }) - .finally(async () => { - await shutdownPostgres(); - }); +  .then(() => { +    console.log("\nDone!"); +    process.exit(0); +  }) +  .catch((error) => { +    console.error("\nFailed to create user:", error); +    process.exit(1); +  }) +  .finally(async () => { +    await shutdownPostgres(); +  }); \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index 033bec49..ef2c00ef 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -47,10 +47,10 @@ app.use( ); // This is what swagger hits -app.use( - "/api/openapi", - createOpenApiExpressMiddleware({ router: appRouter, createContext }), -); +// app.use( +// "/api/openapi", +// createOpenApiExpressMiddleware({ router: appRouter, createContext }), +// ); // OpenAPI swagger docs app.use("/api/docs", swaggerUi.serve); diff --git a/server/src/trpc/openapi.ts b/server/src/trpc/openapi.ts index 9a8a7270..d9532cf3 100644 --- a/server/src/trpc/openapi.ts +++ b/server/src/trpc/openapi.ts @@ -1,9 +1,11 @@ -import { generateOpenApiDocument } from "trpc-to-openapi"; -import * as packageJson from "../../package.json" with { type: "json" }; -import { appRouter } from "./app_router.js"; +// import { generateOpenApiDocument } from "trpc-to-openapi"; +// import * as packageJson from "../../package.json" with { type: "json" }; +// import { appRouter } from "./app_router.js"; -export const openApiDocument = generateOpenApiDocument(appRouter, { - title: "GuardConnect API", - baseUrl: `${process.env.BACKEND_URL ?? "http://localhost:3200"}/api/openapi`, - version: packageJson.default.version, -}); +// export const openApiDocument = generateOpenApiDocument(appRouter, { +// title: "GuardConnect API", +// baseUrl: `${process.env.BACKEND_URL ?? "http://localhost:3200"}/api/openapi`, +// version: packageJson.default.version, +// }); + +export const openApiDocument = null; \ No newline at end of file diff --git a/web/.env.local b/web/.env.local new file mode 100644 index 00000000..737d2afa --- /dev/null +++ b/web/.env.local @@ -0,0 +1,4 @@ +NEXT_PUBLIC_WEB_BASE_URL= +NEXT_PUBLIC_API_BASE_URL= +NEXT_PUBLIC_VAPID_PUBLIC_KEY= +PORT=3001 \ No newline at end of file diff --git a/web/next.config.ts b/web/next.config.ts index cc267097..309bb814 100644 --- a/web/next.config.ts +++ b/web/next.config.ts @@ -1,9 +1,8 @@ import type { NextConfig } from "next"; - const nextConfig: NextConfig = { typedRoutes: true, typescript: { - ignoreBuildErrors: true, // linter should take care of typing + ignoreBuildErrors: true, }, images: { remotePatterns: [ @@ -17,6 +16,13 @@ const nextConfig: NextConfig = { }, ], }, + async rewrites() { + return [ + { + source: "/api/:path*", + destination: "http://localhost:3000/api/:path*", + }, + ]; + }, }; - -export default nextConfig; +export default nextConfig; \ No newline at end of file