Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Empty file removed src/problem4/.keep
Empty file.
52 changes: 52 additions & 0 deletions src/problem4/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Provide 3 unique implementations of the following function in JavaScript.
*
* **Input**: `n` - any integer
*
* *Assuming this input will always produce a result lesser than `Number.MAX_SAFE_INTEGER`*.
*
* **Output**: `return` - summation to `n`, i.e. `sum_to_n(5) === 1 + 2 + 3 + 4 + 5 === 15`.
*/

/**
* Implementation 1: Iterative approach
*
* Time Complexity: O(n)
* Space Complexity: O(1)
*/
var sum_to_n_a = function(n) {
let sum = 0;
for (let i = 1; i <= n; i++) {
sum += i;
}
return sum;
};

/**
* Implementation 2: Recursive approach
*
* Time Complexity: O(n)
* Space Complexity: O(n)
*/
var sum_to_n_b = function(n) {
if (n === 1) {
return 1;
}
return n + sum_to_n_b(n - 1);
};

/**
* Implementation 3: Formula approach: 1 + 2 + ... + n = n * (n + 1) / 2
*
* Time Complexity: O(1)
* Space Complexity: O(1)
*/
var sum_to_n_c = function(n) {
return (n * (n + 1)) / 2;
};

var a = sum_to_n_a(5); // 15
var b = sum_to_n_b(5); // 15
var c = sum_to_n_c(5); // 15

console.log(a, b, c); // 15 15 15
4 changes: 4 additions & 0 deletions src/problem4/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Command run
```code
node index
```
7 changes: 7 additions & 0 deletions src/problem5/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
.env
*.md
.git
.gitignore
docker-compose.yml
35 changes: 35 additions & 0 deletions src/problem5/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/linebreak-style': 0,
'@typescript-eslint/semi': 'off',
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
},
}
3 changes: 3 additions & 0 deletions src/problem5/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
dist
.env
Empty file removed src/problem5/.keep
Empty file.
6 changes: 6 additions & 0 deletions src/problem5/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": false,
"endOfLine": "auto",
"trailingComma": "all"
}
44 changes: 44 additions & 0 deletions src/problem5/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ---- build stage ----
FROM node:22-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY tsconfig.json ./
COPY src ./src
RUN npm run build

# ---- development stage ----
FROM node:22-alpine AS development

ENV NODE_ENV=development

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY --from=builder /app/dist ./dist

EXPOSE 3000

CMD ["node", "dist/index.js"]


# ---- production stage ----
FROM node:22-alpine AS production

ENV NODE_ENV=production

WORKDIR /app

COPY package*.json ./
RUN npm ci --omit=dev

COPY --from=builder /app/dist ./dist

EXPOSE 3000

CMD ["node", "dist/index.js"]
239 changes: 239 additions & 0 deletions src/problem5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# Resource CRUD API

REST API built with Express, TypeScript, TypeORM, and PostgreSQL.

## Stack

- **Runtime**: Node.js 22
- **Framework**: Express 5
- **ORM**: TypeORM 0.3
- **Database**: PostgreSQL 16
- **Language**: TypeScript 5

## Project Structure

```
src/
├── controllers/ # Route handlers, input validation
├── services/ # Business logic
├── repositories/ # Database queries
├── entities/ # TypeORM entities
├── dtos/ # Request/response data transfer objects
├── routes/ # Express routers
├── database/ # DataSource configuration and migrations
├── utils/ # Snowflake ID generator, response helpers
└── swagger.ts # OpenAPI 3.0 spec
```

---

## Setup

### Prerequisites

- Node.js 22+
- PostgreSQL 16+ (or Docker)

### Install dependencies

```sh
npm install
```

### Environment variables

Create a `.env` file in the project root:

```env
NODE_ENV=development
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=postgres
```

### Run locally

```sh
npm run build
npm run migration:run
npm start
```

Or in watch mode during development:

```sh
npm run dev
```

---

## Docker

### Run with Docker Compose

```sh
docker compose up --build
```

This starts two services:

| Service | Port |
|------------|--------|
| `api` | `3000` |
| `postgres` | `5432` |

The API waits for PostgreSQL to pass its healthcheck before starting.

### Stop

```sh
docker compose down
```

To also remove the database volume:

```sh
docker compose down -v
```

---

## API Documentation (Swagger)

Interactive API docs are available via Swagger UI once the server is running.

```
http://localhost:3000/docs
```

You can explore all endpoints, view request/response schemas, and execute requests directly from the browser.

---

## API Endpoints

Base URL: `http://localhost:3000`

### Create a resource

```
POST /resources
```

**Body**

```json
{
"name": "my-resource",
"status": "active"
}
```

`status` is optional, defaults to `active`.

**Response** `201`

```json
{
"id": "7318309505701888001",
"name": "my-resource",
"status": "active",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-01T00:00:00.000Z"
}
```

---

### List resources

```
GET /resources?page=1&limit=20&status=active
```

**Query parameters**

| Param | Type | Default | Description |
|----------|----------|----------|----------------------------------|
| `page` | integer | `1` | Page number |
| `limit` | integer | `20` | Items per page (max `100`) |
| `status` | `active` \| `inactive` | — | Filter by status |

**Response** `200`

```json
{
"data": [...],
"total": 42,
"page": 1,
"limit": 20
}
```

---

### Get a resource

```
GET /resources/:id
```

**Response** `200`

```json
{
"id": "7318309505701888001",
"name": "my-resource",
"status": "active",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-01T00:00:00.000Z"
}
```

---

### Update a resource

```
PATCH /resources/:id
```

**Body** (all fields optional)

```json
{
"name": "updated-name",
"status": "inactive"
}
```

**Response** `200` — updated resource object.

---

### Delete a resource

```
DELETE /resources/:id
```

**Response** `204 No Content`

---

## Error Responses

| Status | Description |
|--------|------------------------------------|
| `400` | Validation error |
| `404` | Resource not found |
| `500` | Internal server error |

```json
{
"message": "Resource with id 123 not found"
}
```
Loading