diff --git a/src/backend/exports.js b/src/backend/exports.js index 1766f7f16..e9a4fa3b1 100644 --- a/src/backend/exports.js +++ b/src/backend/exports.js @@ -42,6 +42,7 @@ const { EntityStoreModule } = require("./src/modules/entitystore/EntityStoreModu const { KVStoreModule } = require("./src/modules/kvstore/KVStoreModule.js"); const { DomainModule } = require("./src/modules/domain/DomainModule.js"); const { DNSModule } = require("./src/modules/dns/DNSModule.js"); +const { TestConfigModule } = require("./src/modules/test-config/TestConfigModule.js"); module.exports = { helloworld: () => { @@ -77,6 +78,7 @@ module.exports = { MemoryStorageModule, SelfHostedModule, TestDriversModule, + TestConfigModule, PuterAIModule, BroadcastModule, InternetModule, diff --git a/src/backend/src/config.js b/src/backend/src/config.js index 9eba02951..3bf55bfc7 100644 --- a/src/backend/src/config.js +++ b/src/backend/src/config.js @@ -219,8 +219,26 @@ const config_pointer = {}; const config_runtime_values = { $: 'runtime-values' }; + let initialPrototype = config_to_export; Object.setPrototypeOf(config_runtime_values, config_to_export); config_to_export = config_runtime_values + + config_to_export.__set_config_object__ = (object, options = {}) => { + // options for this method + const replacePrototype = options.replacePrototype ?? true; + const useInitialPrototype = options.useInitialPrototype ?? true; + + // maybe replace prototype + if ( replacePrototype ) { + const newProto = useInitialPrototype + ? initialPrototype + : Object.getPrototypeOf(config_runtime_values); + Object.setPrototypeOf(object, newProto); + } + + // use this object as the prototype + Object.setPrototypeOf(config_runtime_values, object); + }; // These can be difficult to find and cause painful // confusing issues, so we log any time this happens diff --git a/src/backend/src/modules/test-config/TestConfigModule.js b/src/backend/src/modules/test-config/TestConfigModule.js new file mode 100644 index 000000000..be6d0dab8 --- /dev/null +++ b/src/backend/src/modules/test-config/TestConfigModule.js @@ -0,0 +1,15 @@ +const { AdvancedBase } = require("@heyputer/putility"); + +class TestConfigModule extends AdvancedBase { + async install (context) { + const services = context.get('services'); + const TestConfigUpdateService = require('./TestConfigUpdateService'); + services.registerService('__test-config-update', TestConfigUpdateService); + const TestConfigReadService = require('./TestConfigReadService'); + services.registerService('__test-config-read', TestConfigReadService); + } +} + +module.exports = { + TestConfigModule, +}; diff --git a/src/backend/src/modules/test-config/TestConfigReadService.js b/src/backend/src/modules/test-config/TestConfigReadService.js new file mode 100644 index 000000000..d0d3c9bfc --- /dev/null +++ b/src/backend/src/modules/test-config/TestConfigReadService.js @@ -0,0 +1,11 @@ +const BaseService = require("../../services/BaseService"); + +class TestConfigReadService extends BaseService { + async _init () { + this.log.noticeme('test config value (should be abcdefg) is: ' + + this.global_config.testConfigValue, + ); + } +} + +module.exports = TestConfigReadService; diff --git a/src/backend/src/modules/test-config/TestConfigUpdateService.js b/src/backend/src/modules/test-config/TestConfigUpdateService.js new file mode 100644 index 000000000..b3a34d57a --- /dev/null +++ b/src/backend/src/modules/test-config/TestConfigUpdateService.js @@ -0,0 +1,12 @@ +const BaseService = require("../../services/BaseService"); + +class TestConfigUpdateService extends BaseService { + async _run_as_early_as_possible () { + const config = this.global_config; + config.__set_config_object__({ + testConfigValue: 'abcdefg' + }); + } +} + +module.exports = TestConfigUpdateService; diff --git a/src/backend/src/services/BaseService.js b/src/backend/src/services/BaseService.js index d48dc8030..475e3356b 100644 --- a/src/backend/src/services/BaseService.js +++ b/src/backend/src/services/BaseService.js @@ -54,7 +54,10 @@ class BaseService extends concepts.Service { this.global_config.server_id = 'local'; } } - + + async run_as_early_as_possible () { + await (this._run_as_early_as_possible || NOOP).call(this, this.args); + } /** * Creates the service's data structures and initial values. diff --git a/src/backend/src/services/Container.js b/src/backend/src/services/Container.js index 023fb891d..27af1f52a 100644 --- a/src/backend/src/services/Container.js +++ b/src/backend/src/services/Container.js @@ -173,6 +173,11 @@ class Container { * initialized or rejects if any service initialization fails. */ async init () { + for ( const k in this.instances_ ) { + if ( ! this.instances_[k]._run_as_early_as_possible ) continue; + this.logger.info(`very early hooks for ${k}`); + await this.instances_[k].run_as_early_as_possible(); + } for ( const k in this.instances_ ) { this.logger.info(`constructing ${k}`); await this.instances_[k].construct(); diff --git a/tools/run-selfhosted.js b/tools/run-selfhosted.js index 5db748d7b..d27f98523 100644 --- a/tools/run-selfhosted.js +++ b/tools/run-selfhosted.js @@ -87,6 +87,7 @@ const main = async () => { SelfHostedModule, BroadcastModule, TestDriversModule, + TestConfigModule, PuterAIModule, InternetModule, DevelopmentModule, @@ -105,6 +106,7 @@ const main = async () => { k.add_module(new SelfHostedModule()); k.add_module(new BroadcastModule()); k.add_module(new TestDriversModule()); + k.add_module(new TestConfigModule()); k.add_module(new PuterAIModule()); k.add_module(new InternetModule()); k.add_module(new DNSModule());