Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ea3fbc5
added config service
ZibanPirate Apr 4, 2021
068b613
refactored loaders folder
ZibanPirate Apr 4, 2021
e0c2a6d
added docs for api folder
ZibanPirate Apr 4, 2021
32cf8d6
moved old code under app
ZibanPirate Apr 4, 2021
bd494a7
removed redoundant config/index
ZibanPirate Apr 4, 2021
52d9682
used routing-controllers & created a controller
ZibanPirate Apr 4, 2021
9bc41c3
added github service
ZibanPirate Apr 4, 2021
55163a8
used Github service in Contributors controller
ZibanPirate Apr 4, 2021
9d3038a
loaded old endpoints & put new ones under /v2
ZibanPirate Apr 4, 2021
882bb77
added error handeler and refactored middlewares
ZibanPirate Apr 5, 2021
9fbcff4
renamed vultr to oracle-cloud
ZibanPirate Apr 5, 2021
e057043
added 100% unit test coverage for GithubService
ZibanPirate Apr 5, 2021
af635d0
100% unit test coverage for ContributorController
ZibanPirate Apr 5, 2021
9f29ff7
ignoring test files
ZibanPirate Apr 5, 2021
debbe8a
ignored covering some dirs & fixed build issue
ZibanPirate Apr 5, 2021
6f94fdb
100% unit test coverage for ConfigService
ZibanPirate Apr 7, 2021
f6d20a8
added swagger UI docs
ZibanPirate Apr 7, 2021
9ac2d00
changed ENV to ENVDto
ZibanPirate Apr 7, 2021
3a29107
added OpenAPI docs to ContributorController
ZibanPirate Apr 7, 2021
989ee7f
updated api url & added all 3 local urls in readme
ZibanPirate Apr 7, 2021
8427b93
fixed linting issues
ZibanPirate Apr 7, 2021
143f18a
moved swagger docs to /v2/docs
ZibanPirate Apr 8, 2021
470701b
fixed husy not working after yarn install
ZibanPirate Apr 8, 2021
b87ab05
added LoggerService
ZibanPirate Apr 8, 2021
9ee591a
used LoggerService instead of console
ZibanPirate Apr 8, 2021
65f0c9c
fixed linting issues
ZibanPirate Apr 8, 2021
44ec2d0
added readme docs for API folder
ZibanPirate Apr 8, 2021
1a2b2cb
removed redoundant ToC
ZibanPirate Apr 8, 2021
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ node_modules
yarn-error.log

.idea/
.env
31 changes: 9 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,12 @@ The code for [dzcode.io](https://dzcode.io), a website for Algerian open-source

You can find more about each folder by clicking on the folder name

| Folder | Coverage | Production URL | Staging URL |
| :------------------- | :----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------: | ---------------------------------------------------: |
| [./web](./web) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=web)](https://codecov.io/gh/dzcode-io/dzcode.io) | [dzcode.io](https://dzcode.io) | [stage.dzcode.io](https://stage.dzcode.io) |
| [./data](./data) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=data)](https://codecov.io/gh/dzcode-io/dzcode.io) | [data.dzcode.io](https://data.dzcode.io) | [data.stage.dzcode.io](https://data.stage.dzcode.io) |
| [./api](./api) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=api)](https://codecov.io/gh/dzcode-io/dzcode.io) | [api.dzcode.io](https://api.dzcode.io) | [api_stage.dzcode.io](https://api_stage.dzcode.io) |
| [./common](./common) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=common)](https://codecov.io/gh/dzcode-io/dzcode.io) | | |

## Table of Content

- [dzCode.io](#dzcodeio)
- [Meta](#meta)
- [Table of Content](#table-of-content)
- [Get Started](#get-started)
- [Perquisites](#perquisites)
- [Run it locally](#run-it-locally)
- [Contributing](#contributing)
- [Before You Create a Pull Request](#before-you-create-a-pull-request)
- [List Your Project or Add/Edit Article](#list-your-project-or-addedit-article)
- [License](#license)
| Folder | Coverage | Production URL | Staging URL | Local URL |
| :------------------- | :----------------------------------------------------------------------------------------------------------------------------- | -----------------------------------------------------: | -----------------------------------------------------------------: | ------------------------------------------------------: |
| [./web](./web) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=web)](https://codecov.io/gh/dzcode-io/dzcode.io) | [dzcode.io](https://dzcode.io) | [stage.dzcode.io](https://stage.dzcode.io) | [localhost:8080](http://localhost:8080) |
| [./data](./data) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=data)](https://codecov.io/gh/dzcode-io/dzcode.io) | [data.dzcode.io](https://data.dzcode.io) | [data.stage.dzcode.io](https://data.stage.dzcode.io) | [localhost:9090](http://localhost:9090) |
| [./api](./api) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=api)](https://codecov.io/gh/dzcode-io/dzcode.io) | [api.dzcode.io/v2/docs](https://api.dzcode.io/v2/docs) | [api_stage.dzcode.io/v2/docs](https://api_stage.dzcode.io/v2/docs) | [localhost:7070/v2/docs](http://localhost:7070/v2/docs) |
| [./common](./common) | [![codecov](https://codecov.io/gh/dzcode-io/dzcode.io/graph/badge.svg?flag=common)](https://codecov.io/gh/dzcode-io/dzcode.io) | | | |

## Get Started

Expand Down Expand Up @@ -64,16 +51,16 @@ yarn
yarn dev
```

- For web server to <http://localhost:8080>
- For web server go to <http://localhost:8080>
- For data server go to <http://localhost:9090>
- For api server go to <http://localhost:7070>
- For api server go to <http://localhost:7070/v2/docs>

## Contributing

To get started see [the contributing guidelines](https://github.com/dzcode-io/dzcode.io/blob/master/.github/CONTRIBUTING.md).


### Before You Create a Pull Request

- If you already forked the repository, please make sure your fork is up-to-date, following [this simple steps](https://www.dzcode.io/Learn/Git_Basics/Syncing_An_Old_Forked_Repository_With_Upstream).
- Please make sure your code follows the style guideline defined in this repo, for that simply run `yarn lint:fix` to ensure the conformity. This process should happen automatically whenever you commit your changes, but you can always do it manually when your Pull Request checks are failing due to linting errors.

Expand Down
2 changes: 1 addition & 1 deletion api/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
node_modules/
coverage
dist
vultr/build
oracle-cloud/build
*.*
!*.tsx
!*.ts
Expand Down
2 changes: 1 addition & 1 deletion api/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dist
coverage
vultr/build
oracle-cloud/build

# logs
**.tsbuildinfo
Expand Down
7 changes: 6 additions & 1 deletion api/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
node_modules/
coverage
dist
vultr/build
oracle-cloud/build

.*
*.tsbuildinfo
*.log
*.svg
*.jpeg
*.png
*.ico
23 changes: 23 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# API code

## Folder structure

The app is split into modules, each module (any folder directly under `api/src`) can have service(s) and/or controller(s)

- example of a service is [./src/github/service.ts](./src/github/service.ts)
- example of a controller is [./contributor/controller.ts](./contributor/controller.ts)

There is still temporary old code inside:

- [./src/app/controllers](./src/app/controllers)
- [./src/app/loaders](./src/app/loaders)
- [./src/app/routes](./src/app/routes)
- [./src/app/services](./src/app/services)

## Dependency injection

We use typedi for dependency injection, please check their docs.

We use it in both services and controllers.

**Note:** if the readme is still unclear, please create a PR with your suggested changes/additions
25 changes: 25 additions & 0 deletions api/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
testEnvironment: "node",
collectCoverageFrom: ["src/**/*.ts"],
// coverageThreshold: {
// global: {
// branches: 80,
// functions: 80,
// lines: 80,
// statements: 80,
// },
// },
transform: {
"^.+\\.(ts)?$": "ts-jest",
},
coveragePathIgnorePatterns: [
"node_modules",
"dist",
"src/app/index.ts",
// temporarily until we migrate all endpoints to v2
"src/app/controllers",
"src/app/routes",
"src/app/services",
"src/app/loaders",
],
};
3 changes: 3 additions & 0 deletions api/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"watch": ["dist", ".env"]
}
File renamed without changes.
24 changes: 16 additions & 8 deletions api/vultr/deploy.js → api/oracle-cloud/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ const cp = require("child_process");

// Coping files
console.log("⚙️ Preparing files ...");
fse.copySync("../package.json", "./vultr/build/package.json");
fse.copySync("../common/package.json", "./vultr/build/common/package.json");
fse.copySync("../common/dist", "./vultr/build/common/dist");
fse.copySync("./package.json", "./vultr/build/api/package.json");
fse.copySync("./dist", "./vultr/build/api/dist");
fse.copySync("./vultr/docker-compose.yml", "./vultr/build/docker-compose.yml");
fse.copySync("./vultr/Dockerfile", "./vultr/build/Dockerfile");
fse.copySync("../package.json", "./oracle-cloud/build/package.json");
fse.copySync(
"../common/package.json",
"./oracle-cloud/build/common/package.json",
);
fse.copySync("../common/dist", "./oracle-cloud/build/common/dist");
fse.copySync("./package.json", "./oracle-cloud/build/api/package.json");
fse.copySync("./dist", "./oracle-cloud/build/api/dist");
fse.copySync(
"./oracle-cloud/docker-compose.yml",
"./oracle-cloud/build/docker-compose.yml",
);
fse.copySync("./oracle-cloud/Dockerfile", "./oracle-cloud/build/Dockerfile");
console.log("✅ files copied\n");

// Deploying with ssh
Expand Down Expand Up @@ -48,7 +54,9 @@ logs = cp.execSync(sshPrefix + '"rm -f -r ' + appPath + '"');
logs = cp.execSync(sshPrefix + '"mkdir ' + appPath + '"');

console.log("⤴️ Uploading new code ...");
logs = cp.execSync("rsync -r vultr/build/* " + sshServer + ":" + appPath);
logs = cp.execSync(
"rsync -r oracle-cloud/build/* " + sshServer + ":" + appPath,
);
console.log("✅ New code uploaded.");

console.log("\n⚙️ Starting up the app");
Expand Down
File renamed without changes.
33 changes: 24 additions & 9 deletions api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dzcode.io/api",
"version": "1.0.0",
"version": "2.0.0",
"description": "dzCode.io api code",
"scripts": {
"lint:check": "yarn prettier:check && yarn eslint:check",
Expand All @@ -10,15 +10,15 @@
"prettier:check": "prettier \"**/*.*\" --check --ignore-path ./.prettierignore",
"prettier:fix": "prettier \"**/*.*\" --write --ignore-path ./.prettierignore",
"test": "jest src",
"test:watch": "jest src --watchAll",
"test:watch": "jest --watchAll",
"test:cov": "jest src --coverage",
"test:cov:watch": "jest src --coverage --watchAll",
"test:cov:watch": "jest --coverage --watchAll",
"build": "tsc",
"build:watch": "tsc --watch",
"dev": "nodemon dist/index.js",
"start": "node dist/index.js",
"deploy": "yarn build && rimraf ./vultr/build && node vultr/deploy.js production",
"deploy:stg": "yarn build && rimraf ./vultr/build && node vultr/deploy.js staging"
"dev": "nodemon dist/app/index.js",
"start": "node dist/app/index.js",
"deploy": "yarn build && rimraf ./oracle-cloud/build && node oracle-cloud/deploy.js production",
"deploy:stg": "yarn build && rimraf ./oracle-cloud/build && node oracle-cloud/deploy.js staging"
},
"repository": {
"type": "git",
Expand All @@ -39,19 +39,34 @@
"dependencies": {
"@dzcode.io/common": "1.0.0",
"axios": "^0.21.1",
"body-parser": "^1.19.0",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"class-validator-jsonschema": "^3.0.1",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"morgan": "^1.10.0"
"express-rate-limit": "^5.2.6",
"helmet": "^4.4.1",
"morgan": "^1.10.0",
"reflect-metadata": "^0.1.13",
"routing-controllers": "^0.9.0",
"routing-controllers-openapi": "^3.0.0",
"swagger-ui-express": "^4.1.6",
"typedi": "^0.10.0",
"winston": "^3.3.3"
},
"devDependencies": {
"@types/body-parser": "^1.19.0",
"@types/cors": "^2.8.9",
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.9",
"@types/express-rate-limit": "^5.1.1",
"@types/morgan": "^1.9.2",
"@types/node": "^14.14.16",
"@types/swagger-ui-express": "^4.1.2",
"eslint-config-prettier": "^7.1.0",
"fs-extra": "^9.0.1",
"jest-mock-extended": "^1.0.13",
"lint-staged": "^10.5.3",
"nodemon": "^2.0.6",
"typescript": "^4.1.3"
Expand Down
File renamed without changes.
45 changes: 45 additions & 0 deletions api/src/app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import "reflect-metadata";

import { createExpressServer, useContainer } from "routing-controllers";
import { Application } from "express";
import { ConfigService } from "../config/service";
import Container from "typedi";
import { ContributorController } from "../contributor/controller";
import { DocsMiddleware } from "./middlewares/docs";
import { ErrorMiddleware } from "./middlewares/error";
import { LoggerMiddleware } from "./middlewares/logger";
import { LoggerService } from "../logger/service";
import { SecurityMiddleware } from "./middlewares/security";
import { fsConfig } from "@dzcode.io/common/dist/config";
import router from "./routes/api";

// Use typedi container
useContainer(Container);

// Create the app:
export const routingControllersOptions = {
controllers: [ContributorController],
middlewares: [
// middlewares:
SecurityMiddleware,
ErrorMiddleware,
LoggerMiddleware,
DocsMiddleware,
],
routePrefix: "/v2",
defaultErrorHandler: false,
cors: Container.get(SecurityMiddleware).cors(),
};
const app: Application = createExpressServer(routingControllersOptions);

// Load old code to the app, temporarily until we migrate all endpoints
app.use("/", router);

const { ENV, PORT } = Container.get(ConfigService).env();
const logger = Container.get(LoggerService);

// Start it
app.listen(PORT, () => {
const commonConfig = fsConfig(ENV);
logger.info({ message: `API Server up on: ${commonConfig.api.url}/v2/docs` });
});
8 changes: 8 additions & 0 deletions api/src/app/loaders/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Router } from "express";
import { parserLoader } from "./parser";

export const rootLoader: Loader = (params) => {
parserLoader(params);
};

export type Loader = (params: { app: Router }) => void;
8 changes: 8 additions & 0 deletions api/src/app/loaders/parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { json, urlencoded } from "express";

import { Loader } from ".";

export const parserLoader: Loader = ({ app }) => {
app.use(json());
app.use(urlencoded());
};
39 changes: 39 additions & 0 deletions api/src/app/middlewares/docs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ExpressMiddlewareInterface, Middleware } from "routing-controllers";
import { RequestHandler, Router } from "express";
import { serve, setup } from "swagger-ui-express";

import { Service } from "typedi";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { defaultMetadataStorage } = require("class-transformer/cjs/storage");
import { getMetadataArgsStorage } from "routing-controllers";
import { routingControllersOptions } from "..";
import { routingControllersToSpec } from "routing-controllers-openapi";
import { validationMetadatasToSchemas } from "class-validator-jsonschema";

@Service()
@Middleware({ type: "after" })
export class DocsMiddleware implements ExpressMiddlewareInterface {
constructor() {
// Parse class-validator classes into JSON Schema:
const schemas = validationMetadatasToSchemas({
refPointerPrefix: "#/components/schemas/",
classTransformerMetadataStorage: defaultMetadataStorage,
});
// Parse routing-controllers classes into OpenAPI spec:
const storage = getMetadataArgsStorage();
const spec = routingControllersToSpec(storage, routingControllersOptions, {
components: { schemas },
info: {
description: "swagger documentation for version 2 of dzcode.io API",
title: "dzcode.io API v2",
version: "2.0.0",
},
});

this.router.use("/v2/docs", serve, setup(spec));
}

private router = Router();

use: RequestHandler = this.router;
}
38 changes: 38 additions & 0 deletions api/src/app/middlewares/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
ExpressErrorMiddlewareInterface,
Middleware,
} from "routing-controllers";
import { ErrorRequestHandler } from "express";
import { GeneralResponseDto } from "../types";
import { LoggerService } from "../../logger/service";
import { Service } from "typedi";

@Service()
@Middleware({ type: "after" })
export class ErrorMiddleware implements ExpressErrorMiddlewareInterface {
constructor(private loggerService: LoggerService) {}

error: ErrorRequestHandler<never, GeneralResponseDto, unknown> = (
err,
req,
res,
next,
) => {
// Logs error
this.loggerService.error({
message: "Internal Server Error",
error: err?.message,
});

// Skip if headers are already sent
if (res.headersSent) {
return next(err);
}

// return a general error response
return res.status(500).json({
code: 500,
msg: err?.message,
});
};
}
Loading