Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/app/src/actions/runtime-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This file contains shared configuration for server actions
export const runtime = "nodejs";
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { Departments } from "@bubba/db";

/** Fetcher function, same as before */
async function fetchEmployees(
input: EmployeesInput,
input: EmployeesInput
): Promise<EmployeesResponse> {
const result = await getEmployees(input);

Expand Down Expand Up @@ -52,9 +52,9 @@ export function useEmployees() {
["employees", { search, role, page, per_page }],
() => fetchEmployees({ search, role, page, per_page }),
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
},
revalidateOnFocus: true,
revalidateOnReconnect: true,
}
);

/** Track local mutation (creating an employee) loading state */
Expand Down Expand Up @@ -101,7 +101,7 @@ export function useEmployees() {
setIsMutating(false);
}
},
[revalidateEmployees],
[revalidateEmployees]
);

return {
Expand Down
1 change: 1 addition & 0 deletions apps/app/src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { handlers } from "@/auth";

export const runtime = "nodejs";
export const { GET, POST } = handlers;
1 change: 1 addition & 0 deletions apps/app/src/app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { openai } from "@ai-sdk/openai";
import { convertToCoreMessages, streamText } from "ai";

export const runtime = "nodejs";
export const maxDuration = 30;

export async function POST(req: Request) {
Expand Down
6 changes: 3 additions & 3 deletions apps/app/src/app/api/generate/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { Ratelimit } from "@upstash/ratelimit";
import { streamText } from "ai";
import { match } from "ts-pattern";

export const runtime = "edge";
export const runtime = "nodejs";

export async function POST(req: Request): Promise<Response> {
if (!env.OPENAI_API_KEY || env.OPENAI_API_KEY === "") {
return new Response(
"Missing OPENAI_API_KEY - make sure to add it to your .env file.",
{
status: 400,
},
}
);
}

Expand All @@ -25,7 +25,7 @@ export async function POST(req: Request): Promise<Response> {
});

const { success, limit, reset, remaining } = await ratelimit.limit(
`novel_ratelimit_${ip}`,
`novel_ratelimit_${ip}`
);

if (!success) {
Expand Down
167 changes: 167 additions & 0 deletions apps/app/src/app/api/v1/employees/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { db } from "@bubba/db";
import { NextResponse, type NextRequest } from "next/server";
import { getOrganizationFromApiKey } from "@/lib/api-key";

// Configure this route to use Node.js runtime instead of Edge
export const runtime = "nodejs";

/**
* GET /api/v1/employees/:id
*
* Get a single employee by ID for the organization associated with the API key
*
* Headers:
* - Authorization: Bearer {api_key} or X-API-Key: {api_key}
*
* Path Parameters:
* - id: string - The ID of the employee to fetch
*
* Returns:
* - 200: { success: true, data: Employee }
* - 401: { success: false, error: "Invalid or missing API key" }
* - 404: { success: false, error: "Employee not found" }
* - 500: { success: false, error: "Failed to fetch employee" }
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
Comment on lines +25 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix the params type - it shouldn't be a Promise.

The type for params is defined as Promise<{ id: string }>, which is unusual. Typically, route parameters in Next.js are not promises.

export async function GET(
  request: NextRequest,
-  { params }: { params: Promise<{ id: string }> }
+  { params }: { params: { id: string } }
)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {

// Get the organization ID from the API key
const { organizationId, errorResponse } =
await getOrganizationFromApiKey(request);

// If there's an error response, return it
if (errorResponse) {
return errorResponse;
}

try {
const employeeId = (await params).id;

Comment on lines +38 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unnecessary await for params.

Since params should not be a Promise (as noted in the previous comment), you don't need to await it.

- const employeeId = (await params).id;
+ const employeeId = params.id;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
const employeeId = (await params).id;
try {
- const employeeId = (await params).id;
+ const employeeId = params.id;

// Fetch the employee
const employee = await db.employee.findFirst({
where: {
id: employeeId,
organizationId: organizationId!,
},
select: {
id: true,
name: true,
email: true,
department: true,
isActive: true,
externalEmployeeId: true,
createdAt: true,
updatedAt: true,
},
});

// If employee not found, return 404
if (!employee) {
return NextResponse.json(
{
success: false,
error: "Employee not found",
},
{ status: 404 }
);
}

// Format dates for JSON response
const formattedEmployee = {
...employee,
createdAt: employee.createdAt.toISOString(),
updatedAt: employee.updatedAt.toISOString(),
};

return NextResponse.json({
success: true,
data: formattedEmployee,
});
} catch (error) {
console.error("Error fetching employee:", error);
return NextResponse.json(
{
success: false,
error: "Failed to fetch employee",
},
{ status: 500 }
);
}
}

/**
* DELETE /api/v1/employees/:id
*
* Delete an employee by ID for the organization associated with the API key
*
* Headers:
* - Authorization: Bearer {api_key} or X-API-Key: {api_key}
*
* Path Parameters:
* - id: string - The ID of the employee to delete
*
* Returns:
* - 200: { success: true, data: { message: string } }
* - 401: { success: false, error: string }
* - 404: { success: false, error: string }
* - 500: { success: false, error: string }
*/
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
Comment on lines +110 to +113

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix the params type in DELETE method.

Similar to the GET method, the params parameter is incorrectly typed as a Promise.

export async function DELETE(
  request: NextRequest,
-  { params }: { params: Promise<{ id: string }> }
+  { params }: { params: { id: string } }
)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
export async function DELETE(
request: NextRequest,
{ params }: { params: { id: string } }
) {

// Get the organization ID from the API key
const { organizationId, errorResponse } =
await getOrganizationFromApiKey(request);

// If there's an error response, return it
if (errorResponse) {
return errorResponse;
}

try {
const employeeId = (await params).id;

Comment on lines +123 to +125

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unnecessary await for params in DELETE method.

Since params should not be a Promise, you don't need to await it here either.

- const employeeId = (await params).id;
+ const employeeId = params.id;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
const employeeId = (await params).id;
try {
- const employeeId = (await params).id;
+ const employeeId = params.id;

// Check if the employee exists and belongs to the organization
const existingEmployee = await db.employee.findFirst({
where: {
id: employeeId,
organizationId: organizationId!,
},
});

if (!existingEmployee) {
return NextResponse.json(
{
success: false,
error: "Employee not found",
},
{ status: 404 }
);
}

// Delete the employee
await db.employee.delete({
where: {
id: employeeId,
},
});
Comment on lines +144 to +149

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security issue: Missing organization ID in deletion criteria.

The deletion query only filters by employee ID, not by organization ID. This could potentially allow deletion of employees from other organizations if the ID is known.

- // Delete the employee
- await db.employee.delete({
-   where: {
-     id: employeeId,
-   },
- });

+ // Delete the employee, ensuring it belongs to the correct organization
+ await db.employee.delete({
+   where: {
+     id: employeeId,
+     organizationId: organizationId!,
+   },
+ });

Note: If you implement the optimization from the previous comment, this issue would be resolved automatically.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Delete the employee
await db.employee.delete({
where: {
id: employeeId,
},
});
// Delete the employee, ensuring it belongs to the correct organization
await db.employee.delete({
where: {
id: employeeId,
organizationId: organizationId!,
},
});


return NextResponse.json({
success: true,
data: {
message: "Employee deleted successfully",
},
});
} catch (error) {
console.error("Error deleting employee:", error);
return NextResponse.json(
{
success: false,
error: "Failed to delete employee",
},
{ status: 500 }
);
}
}
66 changes: 0 additions & 66 deletions apps/app/src/app/api/v1/employees/add/route.ts

This file was deleted.

Loading