# API Reference

## Hapiness
The Hapiness object is used to bootstrap a module as Web Server.

### bootstrap(module, [ Extensions ])
Bootstrap a module and start the web server.

## HapinessModule
Declare an Hapiness module with the providers, routes and libs.

```javascript
    @HapinessModule({metadata})
    class MyClass {}
```

- metadata

    - `version` - module version
    - `options`
        - bootstrapped module :
            - `host` - server host
            - `port` - http server port
            - `socketPort` - websocket server port
    - `declarations` - Routes | Libs to declare in the module
    - `providers` - Providers to add in the DI
    - `imports` - Modules to import
    - `exports` - Providers to export and will be available in the module that import it

- interfaces
    - `OnStart` - Only for the bootstrapped module, called when the web server is started.
    - `OnError` - Only for the bootstrapped module, it is the error handler.
        - arguments: (error: Error)
    - `OnRegister` - Called when the module is registered
    - `OnModuleResolved` - Called when imported module is resolved
        - arguments: (module: string)

## Provide config through a module
When you import a module, you can provide data.

```javascript

  // external-module.ts
  import {
    HapinessModule,
    CoreModuleWithProviders,
    InjectionToken,
    Inject,
    Optional,
  } from '@hapiness/core';

  const CONFIG = new InjectionToken('config');
  interface Config {
    baseUrl: string;
  }

    @HapinessModule({
        ...
    })

    export class ExternalModule {
        static setConfig(config: Config): CoreModuleWithProviders {
            return {
                module: ExternalModule,
                providers: [{ provide: CONFIG, useValue: config }]
            };
        }
    }

    export class Service {
      constructor(@Optional() @Inject(CONFIG) config) { // @Optional to not throw errors if config is not passed
        ...
      }
    }
```
```javascript

    // main-module.ts
    import {
      HapinessModule,
    } from '@hapiness/core';
    import { ExternalModule } from 'external-module';

    @HapinessModule({
        ...
        imports: [ ExternalModule.setConfig({ hello: 'world!' }) ]
    })
    ...
```

## Injectable
Declare an injectable provider

```javascript
    @Injectable()
    class MyService {}
```

## Lib
Declare an empty component for any use

```javascript
    @Lib()
    class MyLib {}
```

## Optional
When you ask for a dependency, Optional tell to the DI to not throw an error if the dependency is not available.

```javascript
    ...
    constructor(@Optional() dep: MyDep) {
        if (dep) {
            ...
        }
    }
    ...
```

## Inject & InjectionToken
Create custom token for the DI

```javascript
    const MY_CUSTOM_TOKEN = new InjectionToken('my-token');

    @HapinessModule({
        ...
        imports: [{ provide: MY_CUSTOM_TOKEN, useValue: 'abcdef' }]
        ...
    })
    class MyModule {
        constructor(@Inject(MY_CUSTOM_TOKEN) myValue) {
            console.log(myValue) // ouput: 'abcdef'
        }
    }
```

## Extensions

An extension is a class provided to the boostrap.

```javascript
    class ExampleExt implements OnExtensionLoad {

        public static setConfig(config: any): ExtensionWithConfig {
            return {
                token: HttpServerExt,
                config
            };
        }

        onExtensionLoad(module: CoreModule, config: any) {
            ...
        }

    }
```

Methods to implement:
- `onExtensionLoad` - Called while bootstrapping
    - arguments: (module: CoreModule, config: any)
    - returns: Observable<Extension>
- `OnModuleInstantiated` - (Optional) Called once the bootstrapped module is instanciated
    - arguments: (module: CoreModule, extension value)
    - returns: void
- `OnShutdown` - (Optional) Called once the process catch a `SIGTERM` or a `SIGINT` event
    - arguments: (module: CoreModule, extension value)
    - returns: ExtensionShutdown {
        priority: ExtensionShutdownPriority.IMPORTANT | ExtensionShutdownPriority.NORMAL,
        resolver: Observable<boolean>
    }

The shutdown feature allow to stop gracefully the service.
the `IMPORTANT` priority is for the extensions that needs to process ongoing requests.
The `NORMAL` priority is for extensions that can be stopped directly.

Extension:
```javascript
    {
        value: any;
        instance: any;
        token: Type<any>;
    }
```
- `value` - It's the value provided through the DI
- `instance` - Extension instance, `this`
- `token` - Class token (ex: ExampleExt)


# HTTP Server Extension

See the documentation: [here](src/extensions/http-server/README.md)

# Socket Server Extension

See the documentation: [here](src/extensions/socket-server/README.md)

# EventManager Extension

See the documentation: [here](src/extensions/event-manager/README.md)