npm package: @pamstarter/epts-engine
Description: Platform engine for express typescript starter
Author: PAM Developer
Latest version: 2.0.8

# Epts-Engine (Express-Typescript-Engine)

**_NOTE:_** Libraries are created to help me speed up the process of creating projects that can be personalized, you can
like it or not, you can use it or ignore it, thanks.

Quickly create express apps, register routes and apply middleware right in the controller

## Installation

- With [npm](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

  ```bash 
  $ npm install @pamstarter/epts-engine
  ```

- With [yarn](https://yarnpkg.com/getting-started/install):

  ```bash 
  $ yarn add @pamstarter/epts-engine
  ```

## Quick Start

### Typescript

At file src/app.ts:

```ts
import EptsEngine from '@pamstarter/epts-engine';
import { controllers, expressConfig as express } from '~config/app.config';

const app = new EptsEngine({
   app: {
      port: 3000, // server will run at port
      url: 'http://localhost:3000' // config app url for getUrl helper
   },
   express,
   controllers,
});

// Initialize the application and start the server
app.init();
```

At file src/config/app.config.ts

```ts
import { IExpress, IRegisterController } from '@pamstarter/epts-engine';

import WelcomeController from '~controller/welcome.controller';

export const expressConfig: IExpress = {
   use: [
      // Use method like express.use()
   ],
   set: {
      // Use method like express.set()
   }
};

export const controllers: IRegisterController[] = [
   // Register controllers
   WelcomeController,
];
```

At file src/controllers/welcome.controller.ts

- Controller Config
    - **routePrefix**: set path start at
    - **routeMiddlewareGroups**: set of middleware grouped and used within the controller, possibly one or more group
      names
    - **routeMiddlewares**: separate set of middleware with different purposes used in controller, can be one or more
      middleware
    - **routes** method: return an object whose key is the route method and the value will be an object whose key is the
      path and its value can be one or more router handlers

```ts
import { Controller, IControllerArgs, IRoutes } from '@pamstarter/epts-engine';
import { Request, Response } from 'express';

class WelcomeController extends Controller {
   routePrefix: string = '/welcome'
   routeMiddlewareGroup: 'middleware_group_name' // or [...'middleware_group_name']
   routeMiddlewares: IControllerArgs | IControllerArgs[] = (req, res, next) => {
      next();
   };

   routes(): IRoutes {
      return {
         get: {
            '/': this.helloWorld, // [GET] /welcome/
         },
      };
   }

   helloWorld(req: Request, res: Response) {
      res.json({
         message: 'hello world',
      });
   }
}

export default new WelcomeController;
```

## API Reference

### Application

#### Types:

```ts
interface IEptsEngineConfigurations {
   app?: {
      port?: string | number
      url?: string
   };
   express?: IExpress;
   middlewareGroup?: IMiddlewareGroups;
   controllers?: IRegisterController[];
   custom?: {
      errorHandler?: IHandleError
   };

   [path: string]: any;
}
```

##### `IExpress` Type:

```ts
interface IExpress {
   use?: IExpressUse;
   set?: IExpressSet;

   [index: string]: any;
}
```

##### `IMiddlewareGroups` Type:

```ts
interface IMiddlewareGroups {
   [groupName: string]: IControllerArgs[];
}
```

##### `IRegisterController` Type:

```ts
interface IRegisterController extends IController {
}
```

##### `IHandleError` Type:

```ts
type IHandleError = (error: HttpError, request: Request, response: Response, next: NextFunction) => any
```

#### Methods

##### `init`:

Initialize the application and start the server

##### `start`:

Start the server

##### `stop`:

Stop the server

### Controller

#### Types:

```ts
interface IController {
   routePrefix?: string;
   routeMiddlewareGroup?: string | string[];
   routeMiddlewares?: IControllerArgs | IControllerArgs[];

   routes(): IRoutes;
}
```

##### `IControllerArgs` Type:

```ts
type IControllerArgs = (request: Request, response: Response, next: NextFunction) => any
```

##### `IRoutes` Type:

```ts
interface IRoutes {
   all?: IRouteOption;
   get?: IRouteOption;
   post?: IRouteOption;
   put?: IRouteOption;
   patch?: IRouteOption;
   delete?: IRouteOption;
   options?: IRouteOption;
   head?: IRouteOption;
}
```

##### `IRouteOption` Type:

```ts
interface IRouteOption {
   [path: string]: IControllerArgs | IControllerArgs[]
}
```

#### Properties

##### `routePrefix`:

Set route path starting from

- **@type**: `string` | `undefined`
- **@default**: `undefined`

##### `routeMiddlewareGroup`:

Use the middleware pool registered at the configuration app for the entire controller route

- **@type**: `string` | `string[]` | `undefined`
- **@default**: `undefined`

##### `routeMiddlewares`:

Use middleware for the whole controller route

- **@type**: `IControllerArgs` | `IControllerArgs[]` | `undefined`
- **@default**: `undefined`

#### Methods:

##### `routes`:

Register the routes

- **@return**: `IRoutes`

### Config

The config will be saved to the **/.epts-engine/config.json** file, the functions below only set the object, not save,
if you want to save, use the **save** method after **set**, **update** and **forget**

#### Types:

```ts
interface IConfig {
   all(): object;

   has(key: IConfigKeyParam): boolean;

   get<T = IConfigValueReturn>(key: IConfigKeyParam, defaultValue: T): T;

   set<T = IConfigValueReturn>(key: string | object, value: T): IConfig;

   update<T = IConfigValueReturn>(key: IConfigKeyParam, updater: IConfigUpdater<T>): IConfig;

   forget(key: IConfigKeyParam): IConfig;

   save(): void;
}
```

##### `IConfigKeyParam` Type:

```ts
type IConfigKeyParam = string | string[]
```

##### `IConfigValue` Type:

```ts
type IConfigValue = IConfigKey | number | boolean
```

##### `IConfigValueReturn` Type:

```ts
type IConfigValueReturn = IConfigValue | IConfigValue[]
```

##### `IConfigUpdater` Type:

```ts
type IConfigUpdater<T = any> = (value: T) => T
```

#### Methods

##### `get`

Get configuration value

- **@type**: `T` default `string`
- **@param**:
    - name: **key**
    - type: `string` | `string[]`
- **@param**:
    - name: **defaultValue**
    - type: `T`
    - default: `null`
- **@return**: `T`

##### `set`

Create or replace configuration

- **@type**: `T` default `string`
- **@param**:
    - name: key
    - type: `string` | `object`
- **@param**:
    - name: value
    - type: `T`
- **@return**: `IConfig`

##### `update`

Update an existing configuration

- **@type**: `T` default `string`
- **@param**:
    - name: **key**
    - type: `string` | `object`
- **@param**:
    - name: **updater**
    - type: `IConfigUpdater<T>`
- **@return**: `IConfig`

##### `has`

Check the configuration exists

- **@param**
    - name: **key**
    - type: `string` | `string[]`
- **@return**: `boolen`

##### `forget`

Delete a configuration

- **@param**
    - name: **key**
    - type: `string` | `string[]`
- **@return**: `boolen`

### Helper Methods

#### App

##### `getRootDirectory`

Get path from root directory

- rest **@param**:
    - name: **path**
    - type: `string`
- **@return** `string`

##### `getEnv`

Get the value configured in the environment variable

- **@param**:
    - name: **key**
    - type: `string`
- **@param**:
    - name: **defaultValue**
    - type: `string` | `null`
    - default: `null`
- **@return**: `string`

##### `getUrl`

Get path starting from url defined at `app.url`

- **@param**:
    - name: **path**
    - type: `string` | `null`
    - default: `null`
- **@return**: `string` | `null`

#### Configuration

The config will be saved to the **/.epts-engine/config.json** file, the functions below only set the object, not save,
if you want to save, use the **save** method after **updateConfig**, **setConfig** and **forgetConfig**

##### `getConfig`

Get configuration value

- **@type**: `T` default `string`
- **@param**:
    - name: **key**
    - type: `string` | `string[]`
- **@param**:
    - name: **defaultValue**
    - type: `T`
    - default: `null`
- **@return**: `T`

Example:

```ts 
import { getConfig } from '@pamstarter/epts-engine';

getConfig<string>('app.port') // return '3000'
```

##### `setConfig`

Create or replace configuration

- **@type**: `T` default `string`
- **@param**:
    - name: key
    - type: `string` | `object`
- **@param**:
    - name: value
    - type: `T`
- **@return**: `IConfig`

Example One:

```ts 
import { setConfig } from '@pamstarter/epts-engine';

setConfig<number>('app.port', 4000) // return IConfig
```

Example Two:

```ts 
import { setConfig } from '@pamstarter/epts-engine';

setConfig({
   app: {
      port: 4000
   }
})
```

Example for `save`:

```ts 
import { setConfig } from '@pamstarter/epts-engine';

setConfig<number>('app.port', 4000).save() // return void
```

##### `updateConfig`

Update an existing configuration

- **@type**: `T` default `string`
- **@param**:
    - name: **key**
    - type: `string` | `object`
- **@param**:
    - name: **updater**
    - type: `IConfigUpdater<T>`
- **@return**: `IConfig`

Updater type:

```typescript
type IConfigUpdater<T = any> = (value: T) => T
```

Example:

```ts 
import { updateConfig } from '@pamstarter/epts-engine';

// port 3000
updateConfig<number>('app.port', (port => {
   return port + 1 // 3001 
})) // return IConfig
```

Example for `save`:

```ts 
import { updateConfig } from '@pamstarter/epts-engine';

updateConfig<number>('app.port', (port /* 3000 */ => {
   return port + 1 // 3001 
})).save() // return IConfig
```

##### `hasConfig`

Check the configuration exists

- **@param**
    - name: **key**
    - type: `string` | `string[]`
- **@return**: `boolen`

Example:

```ts 
import { hasConfig } from '@pamstarter/epts-engine';

/*
  {
     app: {
        port: 3000,
        url: 'http://localhost:3000'
     }
  }
*/

hasConfig('app.port') // true
hasConfig('app.bar') // false
```

##### `forgetConfig`

Delete a configuration

- **@param**
    - name: **key**
    - type: `string` | `string[]`
- **@return**: `boolen`

Example:

```ts 
import { forgetConfig } from '@pamstarter/epts-engine';

/*
  {
     app: {
        port: 3000,
        url: 'http://localhost:3000',
     },
      foo: 'bar'
  }
*/

forgetConfig('foo')
```

Example for `save`:

```ts 
import { forgetConfig } from '@pamstarter/epts-engine';

/*
  {
     app: {
        port: 3000,
        url: 'http://localhost:3000',
     },
      foo: 'bar'
  }
*/

forgetConfig('foo').save()
```

#### Router

##### `wrapperRouteHandler`

Wrapper route handler to use when you want to wrap multiple route handlers

- rest **@param**:
    - name: **handlers**
    - type: `IRouteHandlerArgs`
- **@return**: `IRouteHandler`

`IRouteHandlerArgs` type:

```ts
type IRouteHandlerArgs = (IControllerArgs | IControllerArgs[])[]
```

`IRouteHandler` type:

```ts
type IRouteHandler = IControllerArgs | IControllerArgs[]
```