# Puter Kernel Moduels and Services

## Modules

A Puter kernel module is simply a collection of services that run when
the module is installed. You can find an example of this in the
`run-selfhosted.js` script at the root of the Puter monorepo.

Here is the relevant excerpt in `run-selfhosted.js` at the time of
writing this documentation:

```javascript
const {
    Kernel,
    CoreModule,
    DatabaseModule,
    LocalDiskStorageModule,
    SelfHostedModule
} = (await import('@heyputer/backend')).default;

const k = new Kernel();
k.add_module(new CoreModule());
k.add_module(new DatabaseModule());
k.add_module(new LocalDiskStorageModule());
k.add_module(new SelfHostedModule());
k.boot();
```

A few modules are added to Puter before booting. If you want to install
your own modules into Puter you can edit this file for self-hosted runs
or create your own script that boots Puter. This makes it possible to
have deployments of Puter with custom functionality.

To function properly, Puter needs **CoreModule**, a database module,
and a storage module.

A module extends
[AdvancedBase](../../../putility/README.md)
and implements
an `install` method. The install method has one parameter, a
[Context](../../src/util/context.js)
object containing all the values kernel modules have access to. This
includes the `services`
[Container](../../src/services/Container.js`).

A module adds services to Puter.eA typical module may look something
like this:

```javascript
class MyPuterModule extends AdvancedBase {
    async install (context) {
        const services = context.get('services');

        const MyService = require('./path/to/MyService.js');
        services.registerService('my-service', MyService, {
            some_options: 'for-my-service',
        });
    }
}
```

## Services

Services extend
[BaseService](../../src/services/BaseService.js)
and provide additional functionality for Puter. They can add HTTP
endpoints and register objects with other services.

When implementing a service it is important to understand
Puter's [boot sequence](./boot-sequence.md)

A typical service may look like this:

```javascript
class MyService extends BaseService {
    static MODULES = {
        // Use node's `require` function to populate this object;
        // this makes these available to `this.require` and offers
        // dependency-injection for unit testing.
        ['some-module']: require('some-module')
    }

    // Do not override the constructor of BaseService - use this instead!
    async _construct () {
        this.my_list = [];
    }

    // This method is called after _construct has been called on all
    // other services.
    async _init () {
        const services = this.services;

        // We can get the instances of other services here
        const svc_otherService = services.get('other-service');
    }

    // The service container can listen on the "service event bus"
    async ['__on_boot.consolidation'] () {}
    async ['__on_boot.activation'] () {}
    async ['__on_start.webserver'] () {}
    async ['__on_install.routes'] () {}
}
```
