Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
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: 1 addition & 1 deletion apps/backend/db/.env.dev
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DATABASE_URL=postgresql://branch_dev:password@localhost:5432/branch_db
DATABASE_URL=postgresql://branch_dev:password@localhost:5433/branch_db
Copy link
Collaborator

Choose a reason for hiding this comment

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

Good catch!

4 changes: 2 additions & 2 deletions apps/backend/lambdas/users/db.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import { Kysely, PostgresDialect } from 'kysely'
import { Pool } from 'pg'
import type { DB } from './db-types'


const db = new Kysely<DB>({
dialect: new PostgresDialect({
pool: new Pool({
Expand All @@ -16,4 +16,4 @@ const db = new Kysely<DB>({
}),
})

export default db
export default db
54 changes: 51 additions & 3 deletions apps/backend/lambdas/users/handler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import db from './db';
import db from './db'


export const handler = async (event: any): Promise<APIGatewayProxyResult> => {
try {
Expand All @@ -10,6 +11,8 @@ export const handler = async (event: any): Promise<APIGatewayProxyResult> => {
const normalizedPath = rawPath.replace(/\/$/, '');
const method = (event.requestContext?.http?.method || event.httpMethod || 'GET').toUpperCase();

console.log('DEBUG - rawPath:', rawPath, 'normalizedPath:', normalizedPath, 'method:', method);

// Health check
if ((normalizedPath.endsWith('/health') || normalizedPath === '/health') && method === 'GET') {
return json(200, { ok: true, timestamp: new Date().toISOString() });
Expand All @@ -18,7 +21,51 @@ export const handler = async (event: any): Promise<APIGatewayProxyResult> => {
// >>> ROUTES-START (do not remove this marker)
// CLI-generated routes will be inserted here

// GET /{userId} (dev server strips /users prefix)

// GET /users
if ((normalizedPath === '/users' || normalizedPath === '' || normalizedPath === '/') && method === 'GET') {
// TODO: Add your business logic here
const queryParams = event.queryStringParameters || {};
const page = queryParams.page ? parseInt(queryParams.page, 10) : null;
const limit = queryParams.limit ? parseInt(queryParams.limit, 10) : null;

if (page && limit) {
const offset = (page - 1) * limit;

const totalCount = await db
.selectFrom('branch.users')
.select(db.fn.count('user_id').as('count'))
.executeTakeFirst();

const totalUsers = Number(totalCount?.count || 0);
const totalPages = Math.ceil(totalUsers / limit);

const users = await db
.selectFrom('branch.users')
.selectAll()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
.selectAll()
.selectAll()
.orderBy('user_id', 'asc')

Need this to make sure tests pass since it depends on users being ordered by id

.limit(limit)
.offset(offset)
.execute();
return json(200, {
users,
pagination: {
page,
limit,
totalUsers,
totalPages
}
});
}

const users = await db
.selectFrom('branch.users')
.selectAll()
.execute();

console.log(users);
return json(200, { users });
}

if (normalizedPath.startsWith('/') && normalizedPath.split('/').length === 2 && method === 'GET') {
const userId = normalizedPath.split('/')[1];
if (!userId) return json(400, { message: 'userId is required' });
Expand Down Expand Up @@ -65,6 +112,7 @@ export const handler = async (event: any): Promise<APIGatewayProxyResult> => {

return json(200, { ok: true, route: 'PATCH /users/{userId}', pathParams: { userId }, body: { email: updatedUser!.email, name: updatedUser!.name, isAdmin: updatedUser!.is_admin } });
}

// <<< ROUTES-END

return json(404, { message: 'Not Found', path: normalizedPath, method });
Expand All @@ -85,4 +133,4 @@ function json(statusCode: number, body: unknown): APIGatewayProxyResult {
},
body: JSON.stringify(body)
};
}
}
5 changes: 5 additions & 0 deletions apps/backend/lambdas/users/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
};
15 changes: 15 additions & 0 deletions apps/backend/lambdas/users/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ paths:
ok:
type: boolean

/users:
get:
summary: GET /users
parameters:
- name: page
in: query
schema:
type: integer
- name: limit
in: query
schema:
type: integer
responses:
'200':
description: OK
/users/{userId}:
patch:
summary: PATCH /users/{userId}
Expand Down
Loading