From e301247bfc5a7cf3aa9b3fd87271a74e31770614 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Thu, 5 Dec 2024 16:57:28 -0500 Subject: [PATCH] dev: add an example module and service --- src/backend/exports.js | 2 + src/backend/src/modules/template/README.md | 56 +++++++++++ .../src/modules/template/TemplateModule.js | 53 ++++++++++ .../src/modules/template/TemplateService.js | 99 +++++++++++++++++++ .../src/modules/template/lib/__lib__.js | 3 + .../src/modules/template/lib/hello_world.js | 10 ++ 6 files changed, 223 insertions(+) create mode 100644 src/backend/src/modules/template/README.md create mode 100644 src/backend/src/modules/template/TemplateModule.js create mode 100644 src/backend/src/modules/template/TemplateService.js create mode 100644 src/backend/src/modules/template/lib/__lib__.js create mode 100644 src/backend/src/modules/template/lib/hello_world.js diff --git a/src/backend/exports.js b/src/backend/exports.js index 558ab3f7..e8b257d0 100644 --- a/src/backend/exports.js +++ b/src/backend/exports.js @@ -30,6 +30,7 @@ const { PuterAIModule } = require("./src/modules/puterai/PuterAIModule.js"); const { BroadcastModule } = require("./src/modules/broadcast/BroadcastModule.js"); const { WebModule } = require("./src/modules/web/WebModule.js"); const { Core2Module } = require("./src/modules/core/Core2Module.js"); +const { TemplateModule } = require("./src/modules/template/TemplateModule.js"); module.exports = { @@ -49,6 +50,7 @@ module.exports = { Core2Module, CoreModule, WebModule, + TemplateModule, ], // Pre-built modules diff --git a/src/backend/src/modules/template/README.md b/src/backend/src/modules/template/README.md new file mode 100644 index 00000000..e272a18f --- /dev/null +++ b/src/backend/src/modules/template/README.md @@ -0,0 +1,56 @@ +# TemplateModule + +This is a template module that you can copy and paste to create new modules. + +This module is also included in `EssentialModules`, which means it will load +when Puter boots. If you're just testing something, you can add it here +temporarily. + +## Services + +### TemplateService + +This is a template service that you can copy and paste to create new services. +You can also add to this service temporarily to test something. + +#### Listeners + +##### `install.routes` + +TemplateService listens to this event to provide an example endpoint + +##### `boot.consolidation` + +TemplateService listens to this event to provide an example event + +##### `boot.activation` + +TemplateService listens to this event to show you that it's here + +##### `start.webserver` + +TemplateService listens to this event to show you that it's here + +## Libraries + +### hello_world + +#### Functions + +##### `hello_world` + +This is a simple function that returns a string. +You can probably guess what string it returns. + +## Notes + +### Outside Imports + +This module has external relative imports. When these are +removed it may become possible to move this module to an +extension. + +**Imports:** +- `../../util/context.js` +- `../../services/BaseService` (use.BaseService) +- `../../util/expressutil` diff --git a/src/backend/src/modules/template/TemplateModule.js b/src/backend/src/modules/template/TemplateModule.js new file mode 100644 index 00000000..5e22fd36 --- /dev/null +++ b/src/backend/src/modules/template/TemplateModule.js @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 Puter Technologies Inc. + * + * This file is part of Puter. + * + * Puter is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +const { AdvancedBase } = require("@heyputer/putility"); + +/** + * This is a template module that you can copy and paste to create new modules. + * + * This module is also included in `EssentialModules`, which means it will load + * when Puter boots. If you're just testing something, you can add it here + * temporarily. + */ +class TemplateModule extends AdvancedBase { + async install (context) { + // === LIBS === // + const useapi = context.get('useapi'); + + const lib = require('./lib/__lib__.js'); + + // In extensions: use('workinprogress').hello_world(); + // In services classes: see TemplateService.js + useapi.def(`workinprogress`, lib, { assign: true }); + + useapi.def('core.context', require('../../util/context.js').Context); + + // === SERVICES === // + const services = context.get('services'); + + const { TemplateService } = require('./TemplateService.js'); + services.registerService('template-service', TemplateService); + } + +} + +module.exports = { + TemplateModule +}; diff --git a/src/backend/src/modules/template/TemplateService.js b/src/backend/src/modules/template/TemplateService.js new file mode 100644 index 00000000..e079ac2c --- /dev/null +++ b/src/backend/src/modules/template/TemplateService.js @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2024 Puter Technologies Inc. + * + * This file is part of Puter. + * + * Puter is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +// TODO: import via `USE` static member +const BaseService = require("../../services/BaseService"); +const { Endpoint } = require("../../util/expressutil"); + +/** + * This is a template service that you can copy and paste to create new services. + * You can also add to this service temporarily to test something. + */ +class TemplateService extends BaseService { + static USE = { + // - Defined by lib/__lib__.js, + // - Exposed to `useapi` by TemplateModule.js + workinprogress: 'workinprogress' + } + + _construct () { + // Use this override to initialize instance variables. + } + + async _init () { + // This is where you initialize the service and prepare + // for the consolidation phase. + this.log.info("I am the template service."); + } + + /** + * TemplateService listens to this event to provide an example endpoint + */ + ['__on_install.routes'] (_, { app }) { + this.log.info("TemplateService get the event for installing endpoint."); + Endpoint({ + route: '/example-endpoint', + methods: ['GET'], + handler: async (req, res) => { + res.send(this.workinprogress.hello_world()); + } + }).attach(app); + // ^ Don't forget to attach the endpoint to the app! + // it's very easy to forget this step. + } + + /** + * TemplateService listens to this event to provide an example event + */ + ['__on_boot.consolidation'] () { + // At this stage, all services have been initialized and it is + // safe to start emitting events. + this.log.info("TemplateService sees consolidation boot phase."); + + const svc_event = this.services.get('event'); + + svc_event.on('template-service.hello', (_eventid, event_data) => { + this.log.info('template-service said hello to itself; this is expected', { + event_data, + }); + }); + + svc_event.emit('template-service.hello', { + message: 'Hello all you other services! I am the template service.' + }); + } + /** + * TemplateService listens to this event to show you that it's here + */ + ['__on_boot.activation'] () { + this.log.info("TemplateService sees activation boot phase."); + } + + /** + * TemplateService listens to this event to show you that it's here + */ + ['__on_start.webserver'] () { + this.log.info("TemplateService sees it's time to start web servers."); + } +} + +module.exports = { + TemplateService +}; + diff --git a/src/backend/src/modules/template/lib/__lib__.js b/src/backend/src/modules/template/lib/__lib__.js new file mode 100644 index 00000000..51104b7b --- /dev/null +++ b/src/backend/src/modules/template/lib/__lib__.js @@ -0,0 +1,3 @@ +module.exports = { + hello_world: require('./hello_world.js'), +}; diff --git a/src/backend/src/modules/template/lib/hello_world.js b/src/backend/src/modules/template/lib/hello_world.js new file mode 100644 index 00000000..cbef6e3f --- /dev/null +++ b/src/backend/src/modules/template/lib/hello_world.js @@ -0,0 +1,10 @@ + +/** + * This is a simple function that returns a string. + * You can probably guess what string it returns. + */ +const hello_world = () => { + return "Hello, world!"; +} + +module.exports = hello_world;