mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-26 17:28:47 +08:00
105 lines
3.1 KiB
Markdown
105 lines
3.1 KiB
Markdown
|
# 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;
|
||
|
|
||
|
console.log('kerne', Kernel);
|
||
|
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](../../../puter-js-common/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'] () {}
|
||
|
}
|
||
|
```
|