1
0

Kernel.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Puter.
  5. *
  6. * Puter is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. const { AdvancedBase } = require("puter-js-common");
  20. const { Context } = require('./util/context');
  21. class Kernel extends AdvancedBase {
  22. constructor () {
  23. super();
  24. this.modules = [];
  25. }
  26. add_module (module) {
  27. this.modules.push(module);
  28. }
  29. _runtime_init () {
  30. const kvjs = require('@heyputer/kv.js');
  31. const kv = new kvjs();
  32. global.kv = kv;
  33. global.cl = console.log;
  34. const { RuntimeEnvironment } = require('./boot/RuntimeEnvironment');
  35. const { BootLogger } = require('./boot/BootLogger');
  36. // Temporary logger for boot process;
  37. // LoggerService will be initialized in app.js
  38. const bootLogger = new BootLogger();
  39. // Determine config and runtime locations
  40. const runtimeEnv = new RuntimeEnvironment({
  41. logger: bootLogger,
  42. });
  43. runtimeEnv.init();
  44. // polyfills
  45. require('./polyfill/to-string-higher-radix');
  46. }
  47. boot () {
  48. this._runtime_init();
  49. // const express = require('express')
  50. // const app = express();
  51. const config = require('./config');
  52. globalThis.xtra_log = () => {};
  53. if ( config.env === 'dev' ) {
  54. globalThis.xtra_log = (...args) => {
  55. // append to file in temp
  56. const fs = require('fs');
  57. const path = require('path');
  58. const log_path = path.join('/tmp/xtra_log.txt');
  59. fs.appendFileSync(log_path, args.join(' ') + '\n');
  60. }
  61. }
  62. const { consoleLogManager } = require('./util/consolelog');
  63. consoleLogManager.initialize_proxy_methods();
  64. // TODO: temporary dependency inversion; requires moving:
  65. // - rm, so we can move mv
  66. // - mv, so we can move mkdir
  67. // - generate_default_fsentries, so we can move mkdir
  68. // - mkdir, which needs an fs provider
  69. // === START: Initialize Service Registry ===
  70. const { Container } = require('./services/Container');
  71. const services = new Container();
  72. this.services = services;
  73. // app.set('services', services);
  74. const root_context = Context.create({
  75. services,
  76. config,
  77. }, 'app');
  78. globalThis.root_context = root_context;
  79. root_context.arun(async () => {
  80. await this._install_modules();
  81. await this._boot_services();
  82. });
  83. // Error.stackTraceLimit = Infinity;
  84. Error.stackTraceLimit = 200;
  85. }
  86. async _install_modules () {
  87. const { services } = this;
  88. for ( const module of this.modules ) {
  89. await module.install(Context.get());
  90. }
  91. try {
  92. await services.init();
  93. } catch (e) {
  94. // First we'll try to mark the system as invalid via
  95. // SystemValidationService. This might fail because this service
  96. // may not be initialized yet.
  97. const svc_systemValidation = (() => {
  98. try {
  99. return services.get('system-validation');
  100. } catch (e) {
  101. return null;
  102. }
  103. })();
  104. if ( ! svc_systemValidation ) {
  105. // If we can't mark the system as invalid, we'll just have to
  106. // throw the error and let the server crash.
  107. throw e;
  108. }
  109. await svc_systemValidation.mark_invalid(
  110. 'failed to initialize services',
  111. e,
  112. );
  113. }
  114. for ( const module of this.modules ) {
  115. await module.install_legacy?.(Context.get());
  116. }
  117. services.ready.resolve();
  118. // provide services to helpers
  119. const { tmp_provide_services } = require('./helpers');
  120. tmp_provide_services(services);
  121. }
  122. async _boot_services () {
  123. const { services } = this;
  124. await services.ready;
  125. {
  126. const app = services.get('web-server').app;
  127. app.use(async (req, res, next) => {
  128. req.services = services;
  129. next();
  130. });
  131. await services.emit('boot.services-initialized');
  132. await services.emit('install.middlewares.context-aware', { app });
  133. await services.emit('install.routes', { app });
  134. await services.emit('install.routes-gui', { app });
  135. }
  136. // === END: Initialize Service Registry ===
  137. // self check
  138. (async () => {
  139. await services.ready;
  140. globalThis.services = services;
  141. const log = services.get('log-service').create('init');
  142. log.info('services ready');
  143. log.system('server ready', {
  144. deployment_type: globalThis.deployment_type,
  145. });
  146. })();
  147. await services.emit('start.webserver');
  148. await services.emit('ready.webserver');
  149. }
  150. }
  151. module.exports = { Kernel };