From ea9c222c0965f478b5f89b30dca3b43620b7d3b4 Mon Sep 17 00:00:00 2001
From: KernelDeimos <7225168+KernelDeimos@users.noreply.github.com>
Date: Thu, 9 Oct 2025 18:59:48 -0400
Subject: [PATCH] devex: minimal initialization logs
---
src/backend/exports.js | 2 +-
src/backend/src/Extension.js | 25 +++++++++
src/backend/src/Kernel.js | 7 +--
src/backend/src/boot/BootLogger.js | 5 --
src/backend/src/boot/RuntimeEnvironment.js | 2 +-
.../src/modules/broadcast/BroadcastService.js | 5 --
.../ComplainAboutVersionsService.js | 15 ++----
.../modules/selfhosted/DevWatcherService.js | 21 +++++++-
.../modules/selfhosted/SelfHostedModule.js | 4 +-
.../src/modules/web/WebServerService.js | 29 +++++-----
src/backend/src/services/BaseService.js | 4 +-
src/backend/src/services/DevConsoleService.js | 13 ++++-
src/backend/src/services/DevTODService.js | 54 +++++++++++--------
src/putility/src/libs/string.js | 33 +++++++++++-
14 files changed, 149 insertions(+), 70 deletions(-)
diff --git a/src/backend/exports.js b/src/backend/exports.js
index e9a4fa3b1..ef002e174 100644
--- a/src/backend/exports.js
+++ b/src/backend/exports.js
@@ -63,7 +63,7 @@ module.exports = {
HostOSModule,
CoreModule,
WebModule,
- TemplateModule,
+ // TemplateModule,
AppsModule,
CaptchaModule,
EntityStoreModule,
diff --git a/src/backend/src/Extension.js b/src/backend/src/Extension.js
index f40a21c46..8e3b9d1ab 100644
--- a/src/backend/src/Extension.js
+++ b/src/backend/src/Extension.js
@@ -36,6 +36,20 @@ class Extension extends AdvancedBase {
]
}),
];
+
+ randomBrightColor() {
+ // Bright colors in ANSI (foreground codes 90–97)
+ const brightColors = [
+ // 91, // Bright Red
+ 92, // Bright Green
+ // 93, // Bright Yellow
+ 94, // Bright Blue
+ 95, // Bright Magenta
+ // 96, // Bright Cyan
+ ];
+
+ return brightColors[Math.floor(Math.random() * brightColors.length)];
+ }
constructor (...a) {
super(...a);
@@ -43,6 +57,9 @@ class Extension extends AdvancedBase {
this.log = null;
this.ensure_service_();
+ // this.terminal_color = this.randomBrightColor();
+ this.terminal_color = 94;
+
this.log = (...a) => {
this.log_context.info(a.join(' '));
};
@@ -260,6 +277,14 @@ class Extension extends AdvancedBase {
}
this.only_one_init_fn = callback;
}
+
+ get console () {
+ const extensionConsole = Object.create(console);
+ extensionConsole.log = (...a) => {
+ console.log(`\x1B[${this.terminal_color};1m(extension/${this.name})\x1B[0m`, ...a);
+ };
+ return extensionConsole;
+ }
/**
* This method will create the "default service" for an extension.
diff --git a/src/backend/src/Kernel.js b/src/backend/src/Kernel.js
index 0557b28d0..daaa41784 100644
--- a/src/backend/src/Kernel.js
+++ b/src/backend/src/Kernel.js
@@ -218,8 +218,6 @@ class Kernel extends AdvancedBase {
await services.ready;
globalThis.services = services;
const log = services.get('log-service').create('init');
- log.info('services ready');
-
log.system('server ready', {
deployment_type: globalThis.deployment_type,
});
@@ -411,6 +409,7 @@ class Kernel extends AdvancedBase {
`const { use: puter } = globalThis.__puter_extension_globals__.useapi;`,
`const extension = globalThis.__puter_extension_globals__` +
`.extensionObjectRegistry[${JSON.stringify(extension_id)}];`,
+ `const console = extension.console;`,
`const runtime = extension.runtime;`,
`const config = extension.config;`,
`const registry = extension.registry;`,
@@ -465,6 +464,8 @@ class Kernel extends AdvancedBase {
},
});
+ mod.extension.name = packageJSON.name;
+
const maybe_promise = (typ => typ.trim().toLowerCase())(packageJSON.type ?? '') === 'module'
? await import(path_.join(require_dir, packageJSON.main ?? 'index.js'))
: require(require_dir);
@@ -577,7 +578,7 @@ class Kernel extends AdvancedBase {
async run_npm_install (path) {
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
- const proc = spawn(npmCmd, ["install"], { cwd: path, shell: true, stdio: "pipe" });
+ const proc = spawn(npmCmd, ["install"], { cwd: path, stdio: "pipe" });
let buffer = '';
diff --git a/src/backend/src/boot/BootLogger.js b/src/backend/src/boot/BootLogger.js
index 0cad37dc7..4dabe0b8d 100644
--- a/src/backend/src/boot/BootLogger.js
+++ b/src/backend/src/boot/BootLogger.js
@@ -17,11 +17,6 @@
* along with this program. If not, see .
*/
class BootLogger {
- constructor () {
- console.log(
- `\x1B[36;1mBoot logger started :)\x1B[0m`,
- );
- }
info (...args) {
console.log(
'\x1B[36;1m[BOOT/INFO]\x1B[0m',
diff --git a/src/backend/src/boot/RuntimeEnvironment.js b/src/backend/src/boot/RuntimeEnvironment.js
index be547202d..3d05ea842 100644
--- a/src/backend/src/boot/RuntimeEnvironment.js
+++ b/src/backend/src/boot/RuntimeEnvironment.js
@@ -381,7 +381,7 @@ class RuntimeEnvironment extends AdvancedBase {
if ( ! checks_pass ) continue;
this.logger.info(
- `${hl('USING')} ${quot(entry.path)} for ${meta.pathFor}.`
+ `${hl(meta.pathFor)} ${quot(entry.path)}`
)
return entry;
diff --git a/src/backend/src/modules/broadcast/BroadcastService.js b/src/backend/src/modules/broadcast/BroadcastService.js
index 5b7a7cbfa..bd9bfdabe 100644
--- a/src/backend/src/modules/broadcast/BroadcastService.js
+++ b/src/backend/src/modules/broadcast/BroadcastService.js
@@ -102,11 +102,6 @@ class BroadcastService extends BaseService {
});
});
});
-
-
- this.log.noticeme(
- require('node:util').inspect(this.config)
- );
}
_register_commands (commands) {
diff --git a/src/backend/src/modules/selfhosted/ComplainAboutVersionsService.js b/src/backend/src/modules/selfhosted/ComplainAboutVersionsService.js
index d28957666..ed0011a21 100644
--- a/src/backend/src/modules/selfhosted/ComplainAboutVersionsService.js
+++ b/src/backend/src/modules/selfhosted/ComplainAboutVersionsService.js
@@ -54,7 +54,7 @@ class ComplainAboutVersionsService extends BaseService {
const cur_date_obj = new Date();
if ( cur_date_obj < eol_date ) {
- this.log.info('node.js version looks good');
+ this.log.debug('node.js version looks good');
return;
}
@@ -75,22 +75,13 @@ class ComplainAboutVersionsService extends BaseService {
return str;
})();
- const svc_devConsole = this.services.get('dev-console');
- svc_devConsole.add_widget(() => {
- const widget_lines = [];
- widget_lines.push(
- `Node.js version ${major} is past EOL by ${timeago};`,
- `Everything should work, but you should still upgrade.`,
- );
- surrounding_box('31;1', widget_lines);
- return widget_lines;
- });
+ this.log.warn(`Node.js version ${major} is past EOL by ${timeago}`);
}
async get_eol_data_ () {
const require = this.require;
const axios = require('axios');
- const url = 'https://endoflife.date/api/nodejs.json'
+ const url = 'https://endoflife.date/api/nodejs.json';
let data;
try {
({ data } = await axios.get(url));
diff --git a/src/backend/src/modules/selfhosted/DevWatcherService.js b/src/backend/src/modules/selfhosted/DevWatcherService.js
index f3623200a..a3fac7c18 100644
--- a/src/backend/src/modules/selfhosted/DevWatcherService.js
+++ b/src/backend/src/modules/selfhosted/DevWatcherService.js
@@ -176,7 +176,14 @@ class DevWatcherService extends BaseService {
const webpacker = webpack(webpackConfig);
+ let errorAfterLastEnd = false;
+ let firstEvent = true;
webpacker.watch({}, (err, stats) => {
+ let hideSuccess = false;
+ if ( firstEvent ) {
+ firstEvent = false;
+ hideSuccess = true;
+ }
if (err || stats.hasErrors()) {
this.log.error(`error information: ${entry.directory} using Webpack`, {
err,
@@ -187,7 +194,9 @@ class DevWatcherService extends BaseService {
// Normally success messages aren't important, but sometimes it takes
// a little bit for the bundle to update so a developer probably would
// like to have a visual indication in the console when it happens.
- this.log.info(`✅ updated ${entry.directory} using Webpack`);
+ if ( ! hideSuccess ) {
+ this.log.info(`✅ updated ${entry.directory} using Webpack`);
+ }
}
});
}
@@ -244,13 +253,21 @@ class DevWatcherService extends BaseService {
const watcher = rollupModule.watch(rollupConfig);
let errorAfterLastEnd = false;
+ let firstEvent = true;
watcher.on('event', (event) => {
if ( event.code === 'END' ) {
+ let hideSuccess = false;
+ if ( firstEvent ) {
+ firstEvent = false;
+ hideSuccess = true;
+ }
if ( errorAfterLastEnd ) {
errorAfterLastEnd = false;
return;
}
- this.log.info(`✅ updated ${entry.directory} using Rollup`);
+ if ( ! hideSuccess ) {
+ this.log.info(`✅ updated ${entry.directory} using Rollup`);
+ }
} else if ( event.code === 'ERROR' ) {
this.log.error(`error information: ${entry.directory} using Rollup`, {
event,
diff --git a/src/backend/src/modules/selfhosted/SelfHostedModule.js b/src/backend/src/modules/selfhosted/SelfHostedModule.js
index 9fc7f5271..4273f52b1 100644
--- a/src/backend/src/modules/selfhosted/SelfHostedModule.js
+++ b/src/backend/src/modules/selfhosted/SelfHostedModule.js
@@ -41,8 +41,8 @@ class SelfHostedModule extends AdvancedBase {
const { DBKVServiceWrapper } = require("../../services/repositories/DBKVStore/index.mjs");
services.registerService('puter-kvstore', DBKVServiceWrapper);
- const MinLogService = require('./MinLogService');
- services.registerService('min-log', MinLogService);
+ // const MinLogService = require('./MinLogService');
+ // services.registerService('min-log', MinLogService);
// TODO: sucks
const RELATIVE_PATH = '../../../../../';
diff --git a/src/backend/src/modules/web/WebServerService.js b/src/backend/src/modules/web/WebServerService.js
index 5a06322b1..4f8290876 100644
--- a/src/backend/src/modules/web/WebServerService.js
+++ b/src/backend/src/modules/web/WebServerService.js
@@ -117,7 +117,7 @@ class WebServerService extends BaseService {
const services = this.services;
await services.emit('start.webserver');
await services.emit('ready.webserver');
- this.print_puter_logo_();
+ // this.print_puter_logo_();
}
@@ -223,21 +223,13 @@ class WebServerService extends BaseService {
console.log('Error opening browser', e);
}
}
- /**
- * Starts the HTTP server.
- *
- * This method sets up the Express server, initializes middleware, and starts the HTTP server.
- * It handles error handling, authentication, and other necessary configurations.
- *
- * @returns {Promise} A Promise that resolves when the server is listening.
- */
+
+ const link = `\x1B[34;1m${strutil.osclink(url)}\x1B[0m`;
+ const lines = [
+ `Puter is now live at: ${link}`,
+ ];
this.startup_widget = () => {
- const link = `\x1B[34;1m${strutil.osclink(url)}\x1B[0m`;
- const lines = [
- `Puter is now live at: ${link}`,
- `Type web:dismiss to un-stick this message`,
- ];
const lengths = [
(`Puter is now live at: `).length + url.length,
lines[1].length,
@@ -245,9 +237,16 @@ class WebServerService extends BaseService {
surrounding_box('34;1', lines, lengths);
return lines;
};
- {
+ if ( this.config.old_widget_behavior ) {
const svc_devConsole = this.services.get('dev-console', { optional: true });
if ( svc_devConsole ) svc_devConsole.add_widget(this.startup_widget);
+ } else {
+ const svc_devConsole = this.services.get('dev-console', { optional: true });
+ svc_devConsole.notice({
+ colors: { bg: '38;2;0;0;0;48;2;0;202;252;1', bginv: '38;2;0;202;252' },
+ title: 'Puter is live!',
+ lines,
+ });
}
server.timeout = 1000 * 60 * 60 * 2; // 2 hours
diff --git a/src/backend/src/services/BaseService.js b/src/backend/src/services/BaseService.js
index 9b1cc225c..36c572019 100644
--- a/src/backend/src/services/BaseService.js
+++ b/src/backend/src/services/BaseService.js
@@ -50,7 +50,9 @@ class BaseService extends concepts.Service {
Object.defineProperty(this, 'config', {
get: () => configOverride ?? config.services?.[name] ?? {},
set: why => {
- console.warn('replacing config like this is probably a bad idea');
+ // TODO: uncomment and fix these in legacy services
+ // (not very important; low priority)
+ // console.warn('replacing config like this is probably a bad idea');
configOverride = why;
},
});
diff --git a/src/backend/src/services/DevConsoleService.js b/src/backend/src/services/DevConsoleService.js
index 24c532078..cd9898dc4 100644
--- a/src/backend/src/services/DevConsoleService.js
+++ b/src/backend/src/services/DevConsoleService.js
@@ -90,7 +90,18 @@ class DevConsoleService extends BaseService {
this.widgets = this.widgets.filter(w => w !== id_or_outputter);
this.mark_updated();
}
+
+ notice ({ colors, title, lines }) {
+ colors = colors ?? {
+ bg: '46',
+ bginv: '36',
+ };
+ console.log(`\x1B[${colors.bginv}m▐\x1B[0m\x1B[${colors.bg}m ${title} \x1B[0m`);
+ for ( const line of lines ) {
+ console.log(`\x1B[${colors.bginv}m▐▌\x1B[0m${line}\x1B[0m`);
+ }
+ }
/**
* Updates the displayed output based on the current state of widgets.
@@ -142,7 +153,7 @@ class DevConsoleService extends BaseService {
for ( let i = this.widgets.length-1 ; i >= 0 ; i-- ) {
if ( size_ok() ) break;
const w = this.widgets[i];
- if ( w.critical ) continue;
+ if ( w.critical ) continue;
n_hidden++;
const [start, length] = positions[i];
this.static_lines.splice(start, length);
diff --git a/src/backend/src/services/DevTODService.js b/src/backend/src/services/DevTODService.js
index f4e799c55..6f24ecf5c 100644
--- a/src/backend/src/services/DevTODService.js
+++ b/src/backend/src/services/DevTODService.js
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
+const putility = require("@heyputer/putility");
const { surrounding_box } = require("../fun/dev-console-ui-utils");
const BaseService = require("./BaseService");
@@ -88,28 +89,39 @@ class DevTODService extends BaseService {
*/
async ['__on_boot.consolidation'] () {
let random_tip = tips[Math.floor(Math.random() * tips.length)];
- random_tip = wordwrap(
- random_tip,
- process.stdout.columns
- ? process.stdout.columns - 6 : 50
- );
- this.tod_widget = () => {
- const lines = [
- ...random_tip,
- ];
- if ( ! this.global_config.minimal_console ) {
- lines.unshift("\x1B[1mTip of the Day\x1B[0m");
- lines.push("Type tod:dismiss to un-stick this message");
- }
- surrounding_box('33;1', lines);
- return lines;
+ if ( this.config.old_widget_behavior ) {
+ random_tip = wordwrap(
+ random_tip,
+ process.stdout.columns
+ ? process.stdout.columns - 6 : 50,
+ );
+
+ this.tod_widget = () => {
+ const lines = [
+ ...random_tip,
+ ];
+ if ( ! this.global_config.minimal_console ) {
+ lines.unshift("\x1B[1mTip of the Day\x1B[0m");
+ lines.push("Type tod:dismiss to un-stick this message");
+ }
+ surrounding_box('33;1', lines);
+ return lines;
+ };
+
+ this.tod_widget.unimportant = true;
+
+ const svc_devConsole = this.services.get('dev-console', { optional: true });
+ if ( ! svc_devConsole ) return;
+ svc_devConsole.add_widget(this.tod_widget);
+ } else {
+ const svc_devConsole = this.services.get('dev-console', { optional: true });
+ if ( ! svc_devConsole ) return;
+ svc_devConsole.notice({
+ colors: { bg: '38;2;0;0;0;48;2;255;255;0;1', bginv: '38;2;255;255;0' },
+ title: 'Tip of the Day',
+ lines: putility.libs.string.wrap_text(random_tip),
+ });
}
-
- this.tod_widget.unimportant = true;
-
- const svc_devConsole = this.services.get('dev-console', { optional: true });
- if ( ! svc_devConsole ) return;
- svc_devConsole.add_widget(this.tod_widget);
}
_register_commands (commands) {
diff --git a/src/putility/src/libs/string.js b/src/putility/src/libs/string.js
index 8e85524aa..9f8d2a6f7 100644
--- a/src/putility/src/libs/string.js
+++ b/src/putility/src/libs/string.js
@@ -68,9 +68,40 @@ const format_as_usd = (amount) => {
return '$' + amount.toFixed(2);
}
+// wrap.js
+const wrap_text = (text, width = 71) => {
+ const out = [];
+ const paras = text.split(/\r?\n\s*\r?\n/); // split on blank lines
+
+ for (const p of paras) {
+ const words = p.trim().replace(/\s+/g, ' ').split(' ');
+ if (words.length === 1 && words[0] === '') { out.push(''); continue; }
+
+ let line = '';
+ for (const w of words) {
+ if (line.length === 0) {
+ // start new line; do NOT split long words
+ line = w;
+ } else if (line.length + 1 + w.length <= width) {
+ line += ' ' + w;
+ } else {
+ out.push(line);
+ line = w; // put word on its own new line (even if > width)
+ }
+ }
+ if (line) out.push(line);
+ out.push(''); // blank line between paragraphs
+ }
+
+ // remove the extra trailing blank line
+ if (out.length && out[out.length - 1] === '') out.pop();
+
+ return out;
+};
+
module.exports = {
quot,
osclink,
format_as_usd,
+ wrap_text,
};
-