Skip to content

Commit

Permalink
Merge pull request #8 from blinkafrica/release
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
zerothebahdman authored Apr 6, 2024
2 parents 4a9e125 + 48687d1 commit 8e9f428
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ jobs:
yarn build
npm publish --access public
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
91 changes: 62 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,82 @@
# Blink Base Service
# Blink Octobus

## Description
![Github Actions](https://github.com/blinkafrica/octobus/actions/workflows/build-test.yml/badge.svg)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)

This is the base service for the Blink project. It acts as a template for other services to be built on top of. It provides a basic structure for a service, including a database connection, a message queue connection, and a basic REST API.
## About

## Tools
Octobus is a library that provides utility functions for building microservices such as:

- Docker
- RabbitMQ
- NestJS
- TypeORM
- PostgreSQL
- Interservice communication (via REST)
- Subscribing to events from RabbitMQ queues.
- Logging
- Authentication

## Installation
## Getting Started

These instructions will get you a copy of the project up and running on your local machine for development purposes.

### Prerequisites

The following are required for the best use of Octobus:

- Package Dependencies
- NodeJs (v14 or higher)
- Yarn
- Typescript (v4.4 or higher)
- A basic understanding of nodejs and typescript with a good knowledge of nestjs would be an added advantage.

### Installation

To install Octobus, run the following command in your terminal

```bash
yarn install
yarn install --save @blinkclaud/octobus reflect-metadata
```

## Running the app
To upgrade to a specific version run this command

```bash
# development
$ yarn run start
yarn upgrade @blinkclaud/octobus@version
```

To upgrade to latest version run this command

# watch mode
$ yarn run start:dev
```bash
yarn upgrade @blinkclaud/octobus --latest
```

# production mode
$ yarn run start:prod
> Note: Octobus requires Typescript (>= v4.4), as well as the `Decorator` experimental feature. Therefore, the following config options should be present in your `tsconfig.json` file:
```json
{
"compilerOptions": {
"target": "ES2017",
"lib": ["es2017", "esnext.asynciterable", "dom"],
"types": ["reflect-metadata"],
"module": "commonjs",
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
```

## Test
## Guides

```bash
# unit tests
$ yarn run test
Below are links to detailed explanations to the various features of Octobus as well as practical examples:

# e2e tests
$ yarn run test:e2e
- [HTTP (Interservice Comunication)](docs/HTTP.md)
- [QueueManager (subscribing to RabbitMQ queues)](docs/Manager.md)
- [Authentication](docs/Authentication.md)
- [Logging](docs/Logging.md)

# test coverage
$ yarn run test:cov
```
## References and Helpful Links

## License
The following links would further aid the understanding of Octobus

Blink is [MIT licensed](LICENSE).
- [Typescript Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
- [AMPQ Client docs for NodeJs](http://www.squaremobius.net/amqp.node/channel_api.html)
- [Bunyan](https://github.com/trentm/node-bunyan#readme)
- [Axios](https://axios-http.com/docs/intro)
- [RabbitMQ messaging queues](https://www.rabbitmq.com/)
2 changes: 1 addition & 1 deletion src/http/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class HttpAgent {
this.instance = axios.create({ ...defaultAxiosConfig, ...axiosConfig });
this.service = config.service;
this.authConfig = {
secret: new TextEncoder().encode(config.secret),
secret: config.secret,
scheme: config.scheme,
timeout: config.timeout ?? '10s',
};
Expand Down
93 changes: 52 additions & 41 deletions src/http/wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import {
APIError,
HttpError,
NoAuthorizationTokenError,
NoRequestIDError,
TimeoutError,
} from './errors';
import { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Request } from 'express';

import FormData from 'form-data';
import { Request } from 'express';
import { each } from 'lodash';
import { encode } from './jwt';
import qs from 'qs';
import { v4 } from 'uuid';

import { APIError, HttpError, NoRequestIDError, TimeoutError } from './errors';
// import { encode } from './jwt';

export interface AuthConfig {
scheme: string;
secret: Uint8Array;
secret: string;
timeout: string;
}

Expand All @@ -25,7 +33,7 @@ export type Action = () => Promise<void>;
*/
export type Plugin<T = any> = (
req: Partial<AxiosRequestConfig<T>>,
defer: (action: Action) => void,
defer: (action: Action) => void
) => void;

export type RequestData<T extends object> = T | FormData | string;
Expand All @@ -37,7 +45,7 @@ export class RequestWrapper<T extends object> {
protected instance: AxiosInstance,
protected service: string,
protected authConfig: AuthConfig,
protected request: Partial<AxiosRequestConfig<RequestData<T>>>,
protected request: Partial<AxiosRequestConfig<RequestData<T>>>
) {
this.request.headers = Object.assign({}, request.headers);
}
Expand Down Expand Up @@ -117,7 +125,7 @@ export class RequestWrapper<T extends object> {

Object.assign(
this.request.headers as object,
typeof key === 'string' ? { [key]: value } : key,
typeof key === 'string' ? { [key]: value } : key
);

return this;
Expand Down Expand Up @@ -145,38 +153,41 @@ export class RequestWrapper<T extends object> {
* Attach session information to the request
* @param reqSession authenticated express request or session object for headless request
*/
// auth(reqSession?: Request | any) {
// const isReq = reqSession && 'headers' in reqSession;

// if (isReq) {
// if (!reqSession.headers.authorization) {
// throw new NoAuthorizationTokenError(this.request.url);
// }

// Object.assign(this.request.headers, {
// Authorization: reqSession.headers.authorization,
// });

// return this;
// } else {
// if (!reqSession) {
// reqSession = { service: this.service, request_time: new Date() } as any;
// }

// // push till when the request is being made
// return this.defer(async () => {
// const token = await encode(
// this.authConfig.secret,
// this.authConfig.timeout,
// reqSession,
// );

// Object.assign(this.request.headers, {
// Authorization: `${this.authConfig.scheme} ${token}`,
// });
// });
// }
// }
auth(reqSession?: Request | any, payload?: Record<string, string>) {
const isReq = reqSession && 'headers' in reqSession;

if (isReq) {
if (!reqSession.headers.authorization) {
throw new NoAuthorizationTokenError(this.request.url);
}

Object.assign(this.request.headers, {
Authorization: reqSession.headers.authorization,
});

return this;
} else {
if (!reqSession) {
reqSession = {
service: this.service,
request_time: new Date(),
...payload,
} as any;
}

// push till when the request is being made
return this.defer(async () => {
const token = await encode(
this.authConfig.secret,
this.authConfig.timeout,
reqSession
);
Object.assign(this.request.headers, {
Authorization: `${this.authConfig.scheme} ${token}`,
});
});
}
}

/**
* Runs the API request and handles errors.
Expand All @@ -195,7 +206,7 @@ export class RequestWrapper<T extends object> {
throw new APIError(
err.config!.url as string,
err.response.status,
err.response.data,
err.response.data
);
} else if (err.request) {
if (
Expand All @@ -204,14 +215,14 @@ export class RequestWrapper<T extends object> {
) {
throw new TimeoutError(
err.config!.url as string,
err.config!.timeout as number,
err.config!.timeout as number
);
}
throw new HttpError(err.config!.url as string, err);
} else {
throw new Error(err.message);
}
},
}
);
}
}

0 comments on commit 8e9f428

Please sign in to comment.