Skip to content
Merged
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
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ workflows:
branches:
only:
- develop
- typescript
- PM-4478_add-ai-screening-phase-when-editing-after-launch
- review-context
- PM-4684_challenge-approval-flow
Expand Down
33 changes: 33 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.git
.gitignore
.github
.circleci
.factory
.vscode

node_modules
**/node_modules
dist
**/dist
coverage
**/coverage
.nyc_output
reports
**/reports

test
tests
**/test
**/tests

.env
.env.*
**/.env
**/.env.*
.npmrc
**/.npmrc
docs/*.env
docs/**/*.env

npm-debug.log*
pnpm-debug.log*
1 change: 0 additions & 1 deletion .eslintrc.yaml

This file was deleted.

10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ jspm_packages/

# TypeScript v1 declaration files
typings/
dist/
*.tsbuildinfo

# Optional npm cache directory
.npm

# Lockfiles for separately managed tooling remain outside the API package scope.
data-migration/pnpm-lock.yaml

# Optional eslint cache
.eslintcache

Expand All @@ -66,8 +71,5 @@ typings/
ecr-login.sh
test.js

# pnpm lock
pnpm-lock.yaml

.cursor
.idea
.idea
120 changes: 54 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@

This microservice provides access and interaction with all sorts of Challenge data.

## Devlopment status

[![Total alerts](https://img.shields.io/lgtm/alerts/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/alerts/)[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/context:javascript)
## Development status

### Deployment status

Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop) Prod: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master)

## Swagger definition

- [Swagger](https://api.topcoder.com/v5/challenges/docs/)
- [Swagger](https://api.topcoder.com/v6/challenges/api-docs/)

## Intended use

Expand All @@ -24,11 +22,27 @@ Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/d

## Prerequisites

- [NodeJS](https://nodejs.org/en/) (v18+)
- [Node.js](https://nodejs.org/en/) 22 (use the version in `.nvmrc`)
- [pnpm](https://pnpm.io/) 9.15.9
- [AWS S3](https://aws.amazon.com/s3/)
- [Docker](https://www.docker.com/)
- [Docker Compose](https://docs.docker.com/compose/)

## Technology

The API is written in TypeScript and runs on NestJS 11 with the Express adapter.
The adapter mounts the established Express middleware and route graph so existing
HTTP routes, validation, authentication, response bodies, and middleware ordering
remain compatible. Database access uses Prisma 7 with the PostgreSQL driver
adapter. Domain events continue to be sent through the existing Bus API wrapper;
this service does not connect to Kafka directly.

The API runtime client is Prisma 7. The checked-in
`packages/challenge-prisma-client` artifact remains on Prisma 6 for its existing
downstream consumers, so the root generation command intentionally targets only
the API client. Upgrading that shared artifact requires a coordinated downstream
release.

## Configuration

Configuration for the application is at `config/default.js`.
Expand Down Expand Up @@ -63,28 +77,34 @@ The following parameters can be set in config files or in env variables:
- SCOPES: the configurable M2M token scopes, refer `config/default.js` for more details
- M2M_AUDIT_HANDLE: the audit name used when perform create/update operation using M2M token
- FORUM_TITLE_LENGTH_LIMIT: the forum title length limit
- DATABASE_URL: PostgreSQL connection URL for the challenge database
- REVIEW_DB_URL: optional PostgreSQL connection URL for review data; existing
deployments may continue to omit it when review-database access is not used

You can find sample `.env` files inside the `/docs` directory.
The TypeScript, NestJS, and Prisma 7 migration does not introduce or rename any
configuration parameters.

## Available commands

Make sure you have set environment variable `DATABASE_URL` before any database operations.
Run `nvm use` before pnpm commands. Make sure `DATABASE_URL` is set before any
database operation or application startup.

1. Creating tables: `npm run create-tables`
2. Seed/Insert data to tables: `npm run seed-tables`
3. Start all the depending services for local deployment: `npm run services:up`
4. Stop all the depending services for local deployment: `npm run services:down`
5. Check the logs of all the depending services for local deployment: `npm run services:logs`
6. Initialize the local environments: `npm run local:init`
7. Reset the local environments: `npm run local:reset`
1. Install dependencies and generate the Prisma client: `pnpm install`
2. Build the API: `pnpm build`
3. Create or update local database tables: `pnpm create-tables`
4. Seed tables: `pnpm seed-tables`
5. Start local supporting services: `pnpm services:up`
6. Stop local supporting services: `pnpm services:down`
7. Check supporting-service logs: `pnpm services:logs`

### Notes

- The seed data are located in `src/scripts/seed`

## Local Deployment

0. Make sure to use Node v10+ by command `node -v`. We recommend using [NVM](https://github.com/nvm-sh/nvm) to quickly switch to the right version:
0. Select the repository's Node 22 version with

```bash
nvm use
Expand All @@ -102,20 +122,20 @@ Make sure you have set environment variable `DATABASE_URL` before any database o
AUTH0_CLIENT_SECRET=
```

- Values from this file would be automatically used by many `npm` commands.
- Values from this file are automatically used by the application and Prisma commands.
- ⚠️ Never commit this file or its copy to the repository!

Please make sure database url is configured before everything.
```bash
DATABASE_URL=
```

After that you can run `npm install` to install dependencies. And then prisma will setup clients automatically.
Then run `pnpm install`. The postinstall hook generates the Prisma 7 client.

2. 🚢 Start docker-compose with services which are required to start Topcoder Challenges API locally

```bash
npm run services:up
pnpm services:up
```
This command will start postgres with docker-compose.

Expand All @@ -131,7 +151,7 @@ Make sure you have set environment variable `DATABASE_URL` before any database o
```bash
export DATABASE_URL="postgresql://johndoe:mypassword@localhost:5432/challengedb?schema=public"
```
Be sure to run it before running `npm install`
Set it before running database commands or starting the API.


3. ♻ Running mock-api:
Expand Down Expand Up @@ -159,57 +179,25 @@ Make sure you have set environment variable `DATABASE_URL` before any database o

To create database tables, you can run:
```bash
npm run create-tables
pnpm create-tables
```

To create test data, you can run:
```bash
npm run seed-tables
```

To reset db structure and create testdata, you can run:
```bash
npm run local:init
pnpm seed-tables
```

5. Comment Code for M2M Token and postBusEvent
5. Configure external integrations

In local environment, you don't need to use M2M Token or bus API.

You can just comment them to make it working.

For M2M token, you need to comment `src/common/m2m-helper.js#L18`, just return an empty string.

The content will be like:
```js
getM2MToken() {
// return M2MHelper.m2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET);
return '';
}
```

For postBusEvent, you need to comment codes in `src/common/helper.js#L684`. The content will be like:
```js
async function postBusEvent(topic, payload, options = {}) {
// const client = getBusApiClient();
const message = {
topic,
originator: constants.EVENT_ORIGINATOR,
timestamp: new Date().toISOString(),
"mime-type": constants.EVENT_MIME_TYPE,
payload,
};
if (options.key) {
message.key = options.key;
}
// await client.postEvent(message);
}
```
Authenticated operations and event publication use the existing Auth0 and
Bus API settings. Configure `AUTH0_*` and `BUSAPI_URL` for environments that
exercise those paths. Topics disabled by the existing topic configuration are
skipped exactly as before; no local Kafka connection is required.

6. 🚀 Start Topcoder Challenge API

```bash
npm start
pnpm start
```

The Topcoder Challenge API will be served on `http://localhost:3000`
Expand All @@ -222,8 +210,8 @@ Make sure you have set environment variable `DATABASE_URL` before any database o

### Configuration

Test configuration is at `config/test.js`. You don't need to change them.
The following test parameters can be set in config file or in env variables:
Tests use `config/default.js` plus environment-variable overrides. The following
test parameters can be set with environment variables:

- ADMIN_TOKEN: admin token
- COPILOT_TOKEN: copilot token
Expand All @@ -248,27 +236,27 @@ Seeding db data is not needed.
To run unit tests alone

```bash
npm run test
pnpm test
```

To run unit tests with coverage report

```bash
npm run test:cov
pnpm test:cov
```

### Running integration tests

To run integration tests alone

```bash
npm run e2e
pnpm e2e
```

To run integration tests with coverage report

```bash
npm run e2e:cov
pnpm e2e:cov
```

## Verification
Expand All @@ -282,8 +270,8 @@ Refer to the verification document `Verification.md`
challenge also have attachments field linking to its attachments,
this will speed up challenge CRUDS operations.

- In the app-constants.js Topics field, the used topics are using a test topic,
the suggested ones are commented out, because these topics are not created in TC dev Kafka yet.
- Topic names are defined in `app-constants.ts`. Event envelopes are posted to
the Bus API, which owns Kafka integration for this service.

**Downstream Usage**

Expand Down
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions app-routes.js → app-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function isM2MAuthUser(authUser) {
/**
* Check whether an M2M caller has any scope required by the route definition.
*
* @param {Object} def route definition from src/routes.js
* @param {Object} def route definition from src/routes.ts
* @param {Object} authUser the decoded auth user from the authenticator
* @returns {Boolean} true when one required route scope is present
*/
Expand All @@ -80,7 +80,7 @@ function hasRequiredM2MScopes(def, authUser) {
/**
* Normalize a valid M2M caller to the shape expected by service authorization.
*
* @param {Object} def route definition from src/routes.js
* @param {Object} def route definition from src/routes.ts
* @param {Object} authUser the decoded auth user from the authenticator
* @returns {Boolean} true when the caller has required M2M scopes
*/
Expand Down Expand Up @@ -129,7 +129,7 @@ function configureRoutes(app) {
_.each(routes, (verbs, path) => {
_.each(verbs, (def, verb) => {
const controllerPath = `./src/controllers/${def.controller}`;
const method = require(controllerPath)[def.method]; // eslint-disable-line
const method = require(controllerPath)[def.method];
if (!method) {
throw new Error(`${def.method} is undefined`);
}
Expand Down Expand Up @@ -237,7 +237,7 @@ function configureRoutes(app) {
if (!hasToken) {
return next();
}
const interceptRes = {};
const interceptRes: any = {};
interceptRes.status = () => interceptRes;
interceptRes.json = () => interceptRes;
interceptRes.send = (payload) => {
Expand Down
Loading
Loading