Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
chore: 🔧 merge 'main' into enrollment-history
Browse files Browse the repository at this point in the history
  • Loading branch information
ecxyzzy committed Nov 15, 2023
2 parents 71358c4 + f0bf098 commit 9462d93
Show file tree
Hide file tree
Showing 19 changed files with 247 additions and 248 deletions.
11 changes: 2 additions & 9 deletions apps/api/bronya.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { join, resolve } from "node:path";
import { Api, type ApiConstructProps } from "@bronya.js/api-construct";
import { createApiCliPlugins } from "@bronya.js/api-construct/plugins/cli";
import { isCdk } from "@bronya.js/core";
import { logger } from "@libs/lambda";
import { logger, warmingRequestBody } from "@libs/lambda";
import { LambdaIntegration, ResponseType } from "aws-cdk-lib/aws-apigateway";
import { Certificate } from "aws-cdk-lib/aws-certificatemanager";
import { RuleTargetInput, Rule, Schedule } from "aws-cdk-lib/aws-events";
Expand Down Expand Up @@ -79,21 +79,14 @@ const prismaSchema = resolve(libsDbDirectory, "prisma", prismaSchemaFile);
*/
const prismaQueryEngineFile = "libquery_engine-linux-arm64-openssl-1.0.x.so.node";

/**
* The body of a warming request.
*
* TODO: actually recognize warming requests in the route handlers.
*/
const warmingRequestBody = { body: "warming request" };

/**
* Shared ESBuild options.
*/
export const esbuildOptions: BuildOptions = {
format: "esm",
platform: "node",
bundle: true,
minify: true,
// minify: true,
banner: { js },

/**
Expand Down
6 changes: 5 additions & 1 deletion apps/api/src/routes/v1/graphql/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { join, resolve } from "node:path";

import { ApiPropsOverride } from "@bronya.js/api-construct";

import { esbuildOptions } from "../../../../bronya.config";
import { esbuildOptions, constructs } from "../../../../bronya.config";

export const overrides: ApiPropsOverride = {
esbuild: {
Expand All @@ -27,4 +27,8 @@ export const overrides: ApiPropsOverride = {
},
],
},
constructs: {
functionPlugin: constructs.functionPlugin,
restApiProps: constructs.restApiProps,
},
};
42 changes: 18 additions & 24 deletions apps/api/src/routes/v1/rest/calendar/+endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
import { PrismaClient } from "@libs/db";
import { createOKResult, createErrorResult } from "@libs/lambda";
import { createHandler } from "@libs/lambda";
import { getTermDateData } from "@libs/uc-irvine-api/registrar";
import type { Quarter, QuarterDates } from "@peterportal-api/types";
import type { APIGatewayProxyHandler } from "aws-lambda";
import { ZodError } from "zod";

import { QuerySchema } from "./schema";

const prisma = new PrismaClient();

export const GET: APIGatewayProxyHandler = async (event, context) => {
async function onWarm() {
await prisma.$connect();
}

export const GET = createHandler(async (event, context, res) => {
const headers = event.headers;
const query = event.queryStringParameters;
const requestId = context.awsRequestId;

/**
* TODO: handle warmer requests.
*/

// if (request.isWarmerRequest) {
// try {
// await prisma.$connect();
// return createOKResult("Warmed", headers, requestId);
// } catch (e) {
// createErrorResult(500, e, requestId);
// }
// }

try {
const where = QuerySchema.parse(query);

const res = await prisma.calendarTerm.findFirst({
const result = await prisma.calendarTerm.findFirst({
where,
select: {
instructionStart: true,
Expand All @@ -40,8 +30,8 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
},
});

if (res) {
return createOKResult<QuarterDates>(res, headers, requestId);
if (result) {
return res.createOKResult<QuarterDates>(result, headers, requestId);
}

const termDateData = await getTermDateData(
Expand All @@ -57,19 +47,23 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
});

if (!Object.keys(termDateData).length) {
return createErrorResult(
return res.createErrorResult(
400,
`The requested term, ${where.year} ${where.quarter}, is currently unavailable.`,
requestId,
);
}

return createOKResult(termDateData[[where.year, where.quarter].join(" ")], headers, requestId);
return res.createOKResult(
termDateData[[where.year, where.quarter].join(" ")],
headers,
requestId,
);
} catch (error) {
if (error instanceof ZodError) {
const messages = error.issues.map((issue) => issue.message);
return createErrorResult(400, messages.join("; "), requestId);
return res.createErrorResult(400, messages.join("; "), requestId);
}
return createErrorResult(400, error, requestId);
return res.createErrorResult(400, error, requestId);
}
};
}, onWarm);
33 changes: 12 additions & 21 deletions apps/api/src/routes/v1/rest/courses/+endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,37 @@
import { PrismaClient } from "@libs/db";
import { createErrorResult, createOKResult } from "@libs/lambda";
import type { APIGatewayProxyHandler } from "aws-lambda";
import { createHandler } from "@libs/lambda";
import { ZodError } from "zod";

import { constructPrismaQuery, normalizeCourse } from "./lib";
import { QuerySchema } from "./schema";

const prisma = new PrismaClient();

export const GET: APIGatewayProxyHandler = async (event, context) => {
async function onWarm() {
await prisma.$connect();
}

export const GET = createHandler(async (event, context, res) => {
const headers = event.headers;
const query = event.queryStringParameters;
const requestId = context.awsRequestId;

/**
* TODO: handle warmer requests.
*/

// if (request.isWarmerRequest) {
// try {
// await prisma.$connect();
// return createOKResult("Warmed", headers, requestId);
// } catch (e) {
// createErrorResult(500, e, requestId);
// }
// }

try {
const parsedQuery = QuerySchema.parse(query);

// The query object being empty shouldn't return all courses, since there's /courses/all for that.
if (!Object.keys(parsedQuery).length) {
return createErrorResult(400, "Course number not provided", requestId);
return res.createErrorResult(400, "Course number not provided", requestId);
}

const courses = await prisma.course.findMany({ where: constructPrismaQuery(parsedQuery) });

return createOKResult(courses.map(normalizeCourse), headers, requestId);
return res.createOKResult(courses.map(normalizeCourse), headers, requestId);
} catch (error) {
if (error instanceof ZodError) {
const messages = error.issues.map((issue) => issue.message);
return createErrorResult(400, messages.join("; "), requestId);
return res.createErrorResult(400, messages.join("; "), requestId);
}
return createErrorResult(400, error, requestId);
return res.createErrorResult(400, error, requestId);
}
};
}, onWarm);
32 changes: 11 additions & 21 deletions apps/api/src/routes/v1/rest/courses/{id}/+endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,30 @@
import { PrismaClient } from "@libs/db";
import { createErrorResult, createOKResult } from "@libs/lambda";
import type { APIGatewayProxyHandler } from "aws-lambda";
import { createHandler } from "@libs/lambda";

import { normalizeCourse } from "../lib";

const prisma = new PrismaClient();

export const GET: APIGatewayProxyHandler = async (event, context) => {
async function onWarm() {
await prisma.$connect();
}

export const GET = createHandler(async (event, context, res) => {
const headers = event.headers;
const requestId = context.awsRequestId;
const params = event.pathParameters;

/**
* TODO: handle warmer requests.
*/

// if (request.isWarmerRequest) {
// try {
// await prisma.$connect();
// return createOKResult("Warmed", headers, requestId);
// } catch (e) {
// createErrorResult(500, e, requestId);
// }
// }

if (params?.id == null) {
return createErrorResult(400, "Course number not provided", requestId);
return res.createErrorResult(400, "Course number not provided", requestId);
}

if (params?.id === "all") {
const courses = await prisma.course.findMany();
return createOKResult(courses.map(normalizeCourse), headers, requestId);
return res.createOKResult(courses.map(normalizeCourse), headers, requestId);
}

try {
return createOKResult(
return res.createOKResult(
normalizeCourse(
await prisma.course.findFirstOrThrow({
where: { id: decodeURIComponent(params.id) },
Expand All @@ -44,6 +34,6 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
requestId,
);
} catch {
return createErrorResult(404, `Course ${params.id} not found`, requestId);
return res.createErrorResult(404, `Course ${params.id} not found`, requestId);
}
};
}, onWarm);
50 changes: 20 additions & 30 deletions apps/api/src/routes/v1/rest/grades/{id}/+endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { PrismaClient } from "@libs/db";
import { createErrorResult, createOKResult, logger } from "@libs/lambda";
import { logger, createHandler } from "@libs/lambda";
import type {
AggregateGradesByCourse,
AggregateGradesByOffering,
GradesOptions,
RawGrades,
} from "@peterportal-api/types";
import type { APIGatewayProxyHandler } from "aws-lambda";
import { ZodError } from "zod";

import {
Expand All @@ -21,45 +20,36 @@ import { QuerySchema } from "./schema";

const prisma = new PrismaClient();

export const GET: APIGatewayProxyHandler = async (event, context) => {
async function onWarm() {
await prisma.$connect();
}

export const GET = createHandler(async (event, context, res) => {
const { headers, pathParameters: params, queryStringParameters: query } = event;
const { awsRequestId: requestId } = context;

/**
* TODO: handle warmer requests.
*/

// if (request.isWarmerRequest) {
// try {
// await prisma.$connect();
// return createOKResult("Warmed", headers, requestId);
// } catch (e) {
// createErrorResult(500, e, requestId);
// }
// }

try {
const parsedQuery = QuerySchema.parse(query);
switch (params?.id) {
case "raw":
case "aggregate":
{
const res = (
const result = (
await prisma.gradesSection.findMany({
where: constructPrismaQuery(parsedQuery),
include: { instructors: true },
})
).map(transformRow);
switch (params.id) {
case "raw":
return createOKResult<RawGrades>(res, headers, requestId);
return res.createOKResult<RawGrades>(result, headers, requestId);
case "aggregate":
return createOKResult(aggregateGrades(res), headers, requestId);
return res.createOKResult(aggregateGrades(result), headers, requestId);
}
}
break;
case "options": {
const res = await prisma.gradesSection.findMany({
const result = await prisma.gradesSection.findMany({
where: constructPrismaQuery(parsedQuery),
select: {
year: true,
Expand All @@ -73,7 +63,7 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
const departments = new Set<string>();
const courseNumbers = new Set<string>();
const sectionCodes = new Set<string>();
res.forEach(({ year, department, courseNumber, sectionCode }) => {
result.forEach(({ year, department, courseNumber, sectionCode }) => {
years.add(year);
departments.add(department);
courseNumbers.add(courseNumber);
Expand All @@ -88,7 +78,7 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
}),
sectionCodes: Array.from(sectionCodes).sort(),
};
return createOKResult<GradesOptions>(
return res.createOKResult<GradesOptions>(
{
...ret,
instructors: parsedQuery.instructor
Expand All @@ -111,7 +101,7 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
);
}
case "aggregateByCourse": {
return createOKResult<AggregateGradesByCourse>(
return res.createOKResult<AggregateGradesByCourse>(
aggregateByCourse(
(
await prisma.gradesSection.findMany({
Expand All @@ -125,7 +115,7 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
);
}
case "aggregateByOffering": {
return createOKResult<AggregateGradesByOffering>(
return res.createOKResult<AggregateGradesByOffering>(
aggregateByOffering(
(
await prisma.gradesSection.findMany({
Expand All @@ -139,28 +129,28 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
);
}
}
return createErrorResult(
return res.createErrorResult(
400,
params?.id ? `Invalid operation ${params.id}` : "Operation name not provided",
requestId,
);
} catch (e) {
if (e instanceof ZodError) {
const messages = e.issues.map((issue) => issue.message);
return createErrorResult(400, messages.join("; "), requestId);
return res.createErrorResult(400, messages.join("; "), requestId);
}
if (e instanceof Error) {
logger.error(e.message);
// findMany failing due to too many placeholders
if (e.message.includes("1390")) {
return createErrorResult(
return res.createErrorResult(
400,
"Your query returned too many entries. Please refine your search.",
requestId,
);
}
return createErrorResult(400, e.message, requestId);
return res.createErrorResult(400, e.message, requestId);
}
return createErrorResult(400, e, requestId);
return res.createErrorResult(400, e, requestId);
}
};
}, onWarm);
Loading

0 comments on commit 9462d93

Please sign in to comment.