diff --git a/src/backend/src/services/CommandService.js b/src/backend/src/services/CommandService.js index 678647735..e41df75e7 100644 --- a/src/backend/src/services/CommandService.js +++ b/src/backend/src/services/CommandService.js @@ -78,20 +78,16 @@ class Command { */ class CommandService extends BaseService { /** - * Service for managing and executing commands in the system. - * Extends BaseService to provide command registration, execution and lookup functionality. - * Commands are stored internally with unique IDs and can be executed with arguments. - * Built-in 'help' command is registered during initialization. + * Initializes the command service's internal state + * Called during service construction to set up the empty commands array */ async _construct () { this.commands_ = []; } + /** - * Initializes the command service's internal state - * Called during service construction to set up the empty commands array - * @private - * @returns {Promise} - */ + * Add the help command to the list of commands on init + */ async _init () { this.commands_.push(new Command({ id: 'help', diff --git a/src/backend/src/services/CommentService.js b/src/backend/src/services/CommentService.js index 039fea695..287d770ef 100644 --- a/src/backend/src/services/CommentService.js +++ b/src/backend/src/services/CommentService.js @@ -36,13 +36,13 @@ const { DB_WRITE } = require("./database/consts"); * @extends BaseService */ class CommentService extends BaseService { - static MODULES = { - uuidv4: require('uuid').v4, - } /** * Static module dependencies used by the CommentService class * @property {Function} uuidv4 - UUID v4 generator function from the uuid package */ + static MODULES = { + uuidv4: require('uuid').v4, + } _init () { const svc_database = this.services.get('database'); this.db = svc_database.get(DB_WRITE, 'notification'); diff --git a/src/backend/src/services/ConfigurableCountingService.js b/src/backend/src/services/ConfigurableCountingService.js index 82e3383d7..08314b775 100644 --- a/src/backend/src/services/ConfigurableCountingService.js +++ b/src/backend/src/services/ConfigurableCountingService.js @@ -33,8 +33,8 @@ const hash = v => { * @class ConfigurableCountingService * @extends BaseService * @description The ConfigurableCountingService class extends BaseService and is responsible for managing and incrementing -* configurable counting types for different services. It handles the initialization of the database connection, -* defines counting types and SQL columns, and provides a method to increment counts based on specific service +* configurable counting types for different services. +* It defines counting types and SQL columns, and provides a method to increment counts based on specific service * types and values. This class is used to manage usage counts for various services, ensuring accurate tracking * and updating of counts in the database. */ @@ -86,7 +86,7 @@ class ConfigurableCountingService extends BaseService { /** - * Initializes the database connection for the ConfigurableCountingService. + * Initializes the database accessor for the ConfigurableCountingService. * This method sets up the database service for writing counting data. * * @async diff --git a/src/backend/src/services/Container.js b/src/backend/src/services/Container.js index 2c9f2c44e..023fb891d 100644 --- a/src/backend/src/services/Container.js +++ b/src/backend/src/services/Container.js @@ -67,7 +67,7 @@ class Container { } /** - * registerService registers a service with the servuces container. + * registerService registers a service with the services container. * * @param {String} name - the name of the service * @param {BaseService.constructor} cls - an implementation of BaseService @@ -134,13 +134,13 @@ class Container { throw new Error(`missing service: ${name}`); } } - has (name) { return !! this.instances_[name]; } /** * Checks if a service is registered in the container. * * @param {String} name - The name of the service to check. * @returns {Boolean} - Returns true if the service is registered, false otherwise. */ + has (name) { return !! this.instances_[name]; } get values () { const values = {}; for ( const k in this.instances_ ) { @@ -245,18 +245,18 @@ class ProxyContainer { } return this.delegate.get(name); } - has (name) { - if ( this.instances_.hasOwnProperty(name) ) { - return true; - } - return this.delegate.has(name); - } /** * Checks if the container has a service with the specified name. * * @param {string} name - The name of the service to check. * @returns {boolean} - Returns true if the service exists, false otherwise. */ + has (name) { + if ( this.instances_.hasOwnProperty(name) ) { + return true; + } + return this.delegate.has(name); + } get values () { const values = {}; Object.assign(values, this.delegate.values); diff --git a/src/backend/src/services/ContextInitService.js b/src/backend/src/services/ContextInitService.js index d44ac5aa2..4cc8c72ee 100644 --- a/src/backend/src/services/ContextInitService.js +++ b/src/backend/src/services/ContextInitService.js @@ -36,8 +36,6 @@ class ContextInitExpressMiddleware { * Manages a list of value initializers that populate the Context with * either static values or async-generated values when handling requests. * Part of DRY pattern with src/util/context.js. - * - * @class */ constructor () { this.value_initializers_ = []; @@ -91,16 +89,16 @@ class ContextInitService extends BaseService { key, value, }); } - register_async_factory (key, async_factory) { - this.mw.register_initializer({ - key, async_factory, - }); - } /** * Registers an asynchronous factory function to initialize a context value * @param {string} key - The key to store the value under in the context * @param {Function} async_factory - Async function that returns the value to store */ + register_async_factory (key, async_factory) { + this.mw.register_initializer({ + key, async_factory, + }); + } async ['__on_install.middlewares.context-aware'] (_, { app }) { this.mw.install(app); await this.services.emit('install.context-initializers'); diff --git a/src/backend/src/services/DetailProviderService.js b/src/backend/src/services/DetailProviderService.js index 3019663e5..417f92dcd 100644 --- a/src/backend/src/services/DetailProviderService.js +++ b/src/backend/src/services/DetailProviderService.js @@ -24,23 +24,7 @@ const BaseService = require("./BaseService") * detail providers. A detail provider is a function that takes an * input object and uses its values to populate another object. */ -/** -* @class DetailProviderService -* @extends BaseService -* @description This class manages a collection of detail providers, -* which are functions that accept an input object to populate another object -* with relevant details. It provides methods to register new providers and -* retrieve details using all registered providers in sequence. -*/ class DetailProviderService extends BaseService { - /** - * Retrieves detailed information by invoking all registered detail providers with the given context. - * Each provider is expected to modify the out object directly. - * - * @param {Object} context - The input context for the providers. - * @param {Object} [out={}] - An object to store the combined results from each provider. - * @returns {Object} The combined results populated by the detail providers. - */ _construct () { this.providers_ = []; } @@ -52,7 +36,7 @@ class DetailProviderService extends BaseService { /** * Asynchronously retrieves details by invoking registered detail providers - * in sequence. Populates the provided output object with the results of + * in list. Populates the provided output object with the results of * each provider. If no output object is provided, a new one is created * by default. * diff --git a/src/backend/src/services/DevConsoleService.js b/src/backend/src/services/DevConsoleService.js index aee1de619..24c532078 100644 --- a/src/backend/src/services/DevConsoleService.js +++ b/src/backend/src/services/DevConsoleService.js @@ -226,14 +226,9 @@ class DevConsoleService extends BaseService { /** - * Handles the initialization of the DevConsole service, setting up - * command line interface and managing input/output operations. + * _before_cmd - Handles operations needed before a command is executed. * - * This method creates a readline interface for user input, processes - * commands, and manages the display of command output in the console. - * - * @async - * @returns {Promise} A promise that resolves when the initialization is complete. + * (resets cursor to correct position, if I recall correctly) */ this._before_cmd = () => { rl.pause(); @@ -279,10 +274,8 @@ class DevConsoleService extends BaseService { /** - * Prepares the console for output by performing necessary actions - * such as clearing previous lines and setting up the environment - * for rendering new output. This method is called before new - * data is written to the console. + * Re-draws static lines and the input prompt (everything at the bottom of + * the dev console) when something is written. */ this._post_write = () => { this.update_(); @@ -337,9 +330,6 @@ class DevConsoleService extends BaseService { } }, 2000); - consoleLogManager.decorate_all(({ replace }, ...args) => { - this._pre_write(); - }); /** * Decorates all console log messages with the specified pre-write actions. * @@ -349,6 +339,10 @@ class DevConsoleService extends BaseService { * * It does not accept any parameters and does not return any value. */ + consoleLogManager.decorate_all(({ replace }, ...args) => { + this._pre_write(); + }); + consoleLogManager.post_all(() => { this._post_write(); }) diff --git a/src/backend/src/services/DevTODService.js b/src/backend/src/services/DevTODService.js index ac76782d5..f4e799c55 100644 --- a/src/backend/src/services/DevTODService.js +++ b/src/backend/src/services/DevTODService.js @@ -69,19 +69,21 @@ const wordwrap = (text, width) => { */ class DevTODService extends BaseService { /** - * DevTODService class - Manages "Tip of the Day" functionality for the developer console - * @extends BaseService - * @description Provides random development tips and console commands for managing tip display - * Integrates with the dev console to show helpful tips about source code and CLI usage + * Initializes the DevTODService by registering commands with the command service + * @private + * @async + * @returns {Promise} */ async _init () { const svc_commands = this.services.get('commands'); this._register_commands(svc_commands); } + /** - * Initializes the DevTODService by registering commands with the command service - * @private - * @async + * Handles the boot consolidation phase for the Tip of the Day service + * Selects a random tip, wraps it to fit the console width, and creates + * a widget function to display the formatted tip with optional header/footer + * * @returns {Promise} */ async ['__on_boot.consolidation'] () { @@ -91,13 +93,6 @@ class DevTODService extends BaseService { process.stdout.columns ? process.stdout.columns - 6 : 50 ); - /** - * Handles the boot consolidation phase for the Tip of the Day service - * Selects a random tip, wraps it to fit the console width, and creates - * a widget function to display the formatted tip with optional header/footer - * - * @returns {Promise} - */ this.tod_widget = () => { const lines = [ ...random_tip, diff --git a/src/backend/src/services/EntityStoreService.js b/src/backend/src/services/EntityStoreService.js index 76c299d06..334d09ca8 100644 --- a/src/backend/src/services/EntityStoreService.js +++ b/src/backend/src/services/EntityStoreService.js @@ -136,11 +136,11 @@ class EntityStoreService extends BaseService { // TODO: can replace these with MethodProxyFeature /** - * Retrieves an entity by its unique identifier. + * Create a new entity in the store. * - * @param {string} uid - The unique identifier of the entity to read. - * @returns {Promise} The entity object if found, otherwise null or throws an error. - * @throws {APIError} If the entity with the given uid does not exist. + * @param {Object} entity - The entity to add. + * @param {Object} options - Additional options for the update operation. + * @returns {Promise} The updated entity after the operation. */ async create (entity, options) { return await this.upstream.upsert(entity, { old_entity: null, options }); diff --git a/src/backend/src/services/EventService.js b/src/backend/src/services/EventService.js index 215fb02a3..1691f48c1 100644 --- a/src/backend/src/services/EventService.js +++ b/src/backend/src/services/EventService.js @@ -22,11 +22,10 @@ const BaseService = require("./BaseService"); /** -* EventService class extends BaseService to provide a mechanism for -* emitting and listening to events within the application. It manages -* event listeners scoped to specific keys and allows global listeners -* for broader event handling. -*/ + * A proxy to EventService or another scoped event bus, allowing for + * emitting or listening on a prefix (ex: `a.b.c`) without the user + * of the scoped bus needed to know what the prefix is. + */ class ScopedEventBus { constructor (event_bus, scope) { this.event_bus = event_bus; @@ -119,6 +118,17 @@ class EventService extends BaseService { } + /** + * Registers a callback function for the specified event selector. + * + * This method will push the provided callback onto the list of listeners + * for the event specified by the selector. It returns an object containing + * a detach method, which can be used to remove the listener. + * + * @param {string} selector - The event selector to listen for. + * @param {Function} callback - The function to be invoked when the event is emitted. + * @returns {Object} An object with a detach method to unsubscribe the listener. + */ on (selector, callback) { const listeners = this.listeners_[selector] || (this.listeners_[selector] = []); @@ -126,17 +136,6 @@ class EventService extends BaseService { listeners.push(callback); const det = { - /** - * Registers a callback function for the specified event selector. - * - * This method will push the provided callback onto the list of listeners - * for the event specified by the selector. It returns an object containing - * a detach method, which can be used to remove the listener. - * - * @param {string} selector - The event selector to listen for. - * @param {Function} callback - The function to be invoked when the event is emitted. - * @returns {Object} An object with a detach method to unsubscribe the listener. - */ detach: () => { const idx = listeners.indexOf(callback); if ( idx !== -1 ) { diff --git a/src/backend/src/services/FeatureFlagService.js b/src/backend/src/services/FeatureFlagService.js index 85b93b611..cc9f77b34 100644 --- a/src/backend/src/services/FeatureFlagService.js +++ b/src/backend/src/services/FeatureFlagService.js @@ -24,17 +24,17 @@ const { PermissionUtil } = require("./auth/PermissionService"); const BaseService = require("./BaseService"); /** + * @class FeatureFlagService + * @extends BaseService + * * FeatureFlagService is a way to let the client (frontend) know what features * are enabled or disabled for the current user. + * + * A service that manages feature flags to control feature availability across the application. + * Provides methods to register, check, and retrieve feature flags based on user permissions and configurations. + * Integrates with the permission system to determine feature access for different users. + * Supports both static configuration flags and dynamic function-based feature flags. */ -/** -* @class FeatureFlagService -* @extends BaseService -* @description A service that manages feature flags to control feature availability across the application. -* Provides methods to register, check, and retrieve feature flags based on user permissions and configurations. -* Integrates with the permission system to determine feature access for different users. -* Supports both static configuration flags and dynamic function-based feature flags. -*/ class FeatureFlagService extends BaseService { /** * Initializes the FeatureFlagService instance by setting up an empty Map for known flags @@ -44,21 +44,7 @@ class FeatureFlagService extends BaseService { _construct () { this.known_flags = new Map(); } - register (name, spec) { - this.known_flags.set(name, spec); - } - /** - * Registers a new feature flag with the service - * @param {string} name - The name/identifier of the feature flag - * @param {Object|boolean} spec - The specification for the flag. Can be a boolean value or an object with $ property indicating flag type - */ - async _init () { - const svc_detailProvider = this.services.get('whoami'); - svc_detailProvider.register_provider(async (context, out) => { - if ( ! context.actor ) return; - out.feature_flags = await this.get_summary(context.actor); - }); - } + /** * Initializes the feature flag service by registering a provider with the whoami service. * This provider adds feature flag information to user details when requested. @@ -67,17 +53,33 @@ class FeatureFlagService extends BaseService { * @private * @returns {Promise} */ + async _init () { + const svc_detailProvider = this.services.get('whoami'); + svc_detailProvider.register_provider(async (context, out) => { + if ( ! context.actor ) return; + out.feature_flags = await this.get_summary(context.actor); + }); + } + + /** + * Registers a new feature flag with the service + * @param {string} name - The name/identifier of the feature flag + * @param {Object|boolean} spec - The specification for the flag. Can be a boolean value or an object with $ property indicating flag type + */ + register (name, spec) { + this.known_flags.set(name, spec); + } + + /** + * checks is a feature flag is enabled for the current user + * @return {boolean} - true if the feature flag is enabled, false otherwise + * + * Usage: + * check({ actor }, 'flag-name') + */ async check (...a) { // allows binding call with multiple options objects; // the last argument is the permission to check - /** - * Checks if a feature flag is enabled for the given context - * @param {...Object} options - Configuration options objects that will be merged - * @param {string} permission - The feature flag name to check - * @returns {Promise} Whether the feature flag is enabled - * @description Processes multiple option objects and a permission string to determine - * if a feature flag is enabled. Handles config flags, function flags, and permission-based flags. - */ const { options, value: permission } = (() => { let value; const options = {}; diff --git a/src/backend/src/services/GetUserService.js b/src/backend/src/services/GetUserService.js index 1eb6e74b6..d3ca49c66 100644 --- a/src/backend/src/services/GetUserService.js +++ b/src/backend/src/services/GetUserService.js @@ -32,12 +32,6 @@ const { DB_READ } = require("./database/consts"); * * The original `get_user` function now uses this service. */ -/** -* Class representing a service to retrieve user information by various identifying properties. -* The GetUserService provides an interface for accessing user data while facilitating caching -* mechanisms to optimize database interactions, allowing for read operations against different -* identifiers such as username, email, UUID, and referral codes. -*/ class GetUserService extends BaseService { /** * Constructor for GetUserService. @@ -52,12 +46,7 @@ class GetUserService extends BaseService { this.id_properties.add('email'); this.id_properties.add('referral_code'); } - /** - * Initializes the GetUserService instance, setting up the - * identifying properties used for user retrieval. - */ - async _init () { - } + /** * Initializes the GetUserService instance. * This method prepares any necessary internal structures or states. @@ -65,14 +54,9 @@ class GetUserService extends BaseService { * * @returns {Promise} A promise that resolves when the initialization is complete. */ - async get_user (options) { - const user = await this.get_user_(options); - if ( ! user ) return null; - - const svc_whoami = this.services.get('whoami'); - await svc_whoami.get_details({ user }, user); - return user; + async _init () { } + /** * Retrieves a user object based on the provided options. * @@ -86,6 +70,15 @@ class GetUserService extends BaseService { * @param {boolean} [options.force=false] - Forces a read from the database regardless of cache. * @returns {Promise} The user object if found, else null. */ + async get_user (options) { + const user = await this.get_user_(options); + if ( ! user ) return null; + + const svc_whoami = this.services.get('whoami'); + await svc_whoami.get_details({ user }, user); + return user; + } + async get_user_ (options) { const services = this.services; diff --git a/src/backend/src/services/HostDiskUsageService.js b/src/backend/src/services/HostDiskUsageService.js index ae9271b5c..bd2cbe692 100644 --- a/src/backend/src/services/HostDiskUsageService.js +++ b/src/backend/src/services/HostDiskUsageService.js @@ -131,19 +131,19 @@ class HostDiskUsageService extends BaseService { // TODO: Implement for windows systems } - // Get the free space on the mountpoint/drive in mac os + // Get the total drive capacity on the mountpoint/drive in mac os get_disk_capacity_darwin(mountpoint) { const disk_info = execSync(`df -P "${mountpoint}" | awk 'NR==2 {print $2}'`, { encoding: 'utf-8' }).trim().split(' '); return parseInt(disk_info) * 512; } - // Get the free space on the mountpoint/drive in linux + // Get the total drive capacity on the mountpoint/drive in linux get_disk_capacity_linux(mountpoint) { const disk_info = execSync(`df -P "${mountpoint}" | awk 'NR==2 {print $2}'`, { encoding: 'utf-8' }).trim().split(' '); return parseInt(disk_info) * 1024; } - // Get the free space on the drive in windows + // Get the total drive capacity on the drive in windows get_disk_capacity_windows(drive) { // TODO: Implement for windows systems } diff --git a/src/backend/src/services/KernelInfoService.js b/src/backend/src/services/KernelInfoService.js index 6c36ee656..97679245f 100644 --- a/src/backend/src/services/KernelInfoService.js +++ b/src/backend/src/services/KernelInfoService.js @@ -38,24 +38,16 @@ const PERM_SEE_DRIVERS = 'kernel-info:see-all-drivers'; * @extends BaseService */ class KernelInfoService extends BaseService { - /** - * Service for providing kernel and service information - * Extends BaseService to provide system-level information about services, interfaces and drivers - * Handles permissions and access control for viewing service information - * Exposes endpoints for listing modules and service information - */ - async _init () { - // - } + async _init () {} + /** + * Installs routes for the kernel info service + * @param {*} _ Unused parameter + * @param {Object} param1 Object containing Express app instance + * @param {Express} param1.app Express application instance + * @private + */ ['__on_install.routes'] (_, { app }) { - /** - * Installs routes for the kernel info service - * @param {*} _ Unused parameter - * @param {Object} param1 Object containing Express app instance - * @param {Express} param1.app Express application instance - * @private - */ const router = (() => { const require = this.require; const express = require('express'); diff --git a/src/backend/src/services/LockService.js b/src/backend/src/services/LockService.js index ff214597c..600e913a0 100644 --- a/src/backend/src/services/LockService.js +++ b/src/backend/src/services/LockService.js @@ -20,12 +20,6 @@ const { RWLock } = require("../util/lockutil"); const BaseService = require("./BaseService"); -/** - * LockService implements robust critical sections when the behavior - * might return early or throw an error. - * - * This serivces uses RWLock but always locks in write mode. - */ /** * Represents the LockService class responsible for managing locks * using reader-writer locks (RWLock). This service ensures that @@ -111,17 +105,6 @@ class LockService extends BaseService { // TODO: verbose log option by service // console.log('LOCKING NAMES', names) const section = names.reduce((current_callback, name) => { - /** - * Acquires a lock for the specified name or names. - * - * If the name is an array, it locks each specified name in sequence. - * The method ensures that all specified locks are acquired before executing the callback. - * - * @param {string|string[]} name - The name(s) of the lock(s) to acquire. - * @param {Object} [opt_options={}] - Optional configuration for the lock operation. - * @param {Function} callback - Function to be executed once the lock is acquired. - * @returns {Promise} Resolves when the callback execution is complete. - */ return async () => { return await this.lock(name, opt_options, current_callback); }; @@ -142,17 +125,6 @@ class LockService extends BaseService { let timeout, timed_out; if ( opt_options.timeout ) { - /** - * Attempts to acquire a write lock on the specified name, executes the provided callback, - * and ensures the lock is released afterward. Supports options for timeout and handles - * multiple locks if the name parameter is an array. - * - * @param {string|string[]} name - The lock name(s) to acquire. - * @param {Object} [opt_options={}] - Optional configuration for the lock. - * @param {function} callback - The function to execute while holding the lock. - * @returns {Promise} The result of the callback execution. - * @throws {Error} If the lock acquisition times out. - */ timeout = setTimeout(() => { handle.unlock(); // TODO: verbose log option by service diff --git a/src/backend/src/services/MakeProdDebuggingLessAwfulService.js b/src/backend/src/services/MakeProdDebuggingLessAwfulService.js index eba9d5664..b5a6b5a5b 100644 --- a/src/backend/src/services/MakeProdDebuggingLessAwfulService.js +++ b/src/backend/src/services/MakeProdDebuggingLessAwfulService.js @@ -27,15 +27,6 @@ const BaseService = require("./BaseService"); * Consequentially, the value of X-PUTER-DEBUG will included in all * log messages produced by the request. */ -/** -* @class MakeProdDebuggingLessAwfulService -* @extends BaseService -* @description Service that improves production debugging by capturing and processing debug headers. -* Extends the base service to provide middleware functionality that captures the X-PUTER-DEBUG header -* value and incorporates it into the request's Context object. This enables detailed logging and -* debugging capabilities in production environments while maintaining system security. The service -* also handles the creation and management of debug-specific log files for better traceability. -*/ class MakeProdDebuggingLessAwfulService extends BaseService { static USE = { logutil: 'core.util.logutil', @@ -66,7 +57,9 @@ class MakeProdDebuggingLessAwfulService extends BaseService { /** * Installs the middleware into the Express application * - * @param {Express} app - The Express application instance + * @param {Object} req - Express request object containing headers + * @param {Object} res - Express response object + * @param {Function} next - Express next middleware function * @returns {void} */ async run (req, res, next) { @@ -75,13 +68,7 @@ class MakeProdDebuggingLessAwfulService extends BaseService { next(); } } - /** - * Handles the actual middleware execution for production debugging - * @param {Object} req - Express request object containing headers - * @param {Object} res - Express response object - * @param {Function} next - Express next middleware function - * @returns {Promise} - */ + async _init () { // Initialize express middleware this.mw = new this.constructor.ProdDebuggingMiddleware(); diff --git a/src/backend/src/services/NotificationService.js b/src/backend/src/services/NotificationService.js index 6026492e3..13dd72f16 100644 --- a/src/backend/src/services/NotificationService.js +++ b/src/backend/src/services/NotificationService.js @@ -73,7 +73,7 @@ class NotificationService extends BaseService { /** - * Initializes the NotificationService instance. + * Constructs the NotificationService instance. * This method sets up the initial state of the service, including any necessary * data structures or configurations. * @@ -185,10 +185,6 @@ class NotificationService extends BaseService { * * This method sets a timer to call `do_on_user_connected` after 2000 milliseconds. * If a timer already exists for the user, it clears the existing timer before setting a new one. - * - * @param {Object} params - The parameters object. - * @param {Object} params.user - The user object containing the user's UUID. - * @returns {Promise} A promise that resolves when the timer is set. */ setTimeout(() => this.do_on_user_connected({ user }), 2000); } diff --git a/src/backend/src/services/OperationTraceService.js b/src/backend/src/services/OperationTraceService.js index e14818a75..27cceb3f3 100644 --- a/src/backend/src/services/OperationTraceService.js +++ b/src/backend/src/services/OperationTraceService.js @@ -335,17 +335,7 @@ class BaseOperation extends AdvancedBase { // Run operation in new context try { - /** - * Runs an operation within a new context. - * - * This method sets up a new operation frame, updates the context, and runs the - * operation. It handles the operation's lifecycle, logging, and error handling. - * - * @async - * @function run - * @param {Object} values - The values to be passed to the operation. - * @returns {Promise<*>} The result of the operation. - */ + // Actual delegate call (this._run) with context and checkpoints return await x.arun(async () => { const x = Context.get(); const operationTraceSvc = x.get('services').get('operationTrace'); @@ -384,11 +374,12 @@ class BaseOperation extends AdvancedBase { /** - * Updates the checkpoint for the current operation frame. - * - * @param {string} name - The name of the checkpoint to set. - * @returns {void} - */ + * Actions to perform after running. + * + * If child operation frames think they're still pending, mark them as stuck; + * all child frames at least reach working state before the parent operation + * completes. + */ _post_run () { let any_async = false; for ( const child of this.frame.children ) { diff --git a/src/backend/src/services/PuterHomepageService.js b/src/backend/src/services/PuterHomepageService.js index b846ef8b6..551864052 100644 --- a/src/backend/src/services/PuterHomepageService.js +++ b/src/backend/src/services/PuterHomepageService.js @@ -25,23 +25,12 @@ const {is_valid_url} = require('../helpers'); * PuterHomepageService serves the initial HTML page that loads the Puter GUI * and all of its assets. */ -/** -* This class serves the initial HTML page that loads the Puter GUI and all of its assets. -* It extends the BaseService class to provide common functionality. -*/ class PuterHomepageService extends BaseService { static MODULES = { fs: require('node:fs'), } - /** - * This method sets a parameter for the GUI. - * It takes a key and value as arguments and adds them to the `gui_params` object. - * - * @param {string} key - The key for the parameter. - * @param {any} val - The value for the parameter. - */ _construct () { this.service_scripts = []; this.gui_params = {}; diff --git a/src/backend/src/services/ReferralCodeService.js b/src/backend/src/services/ReferralCodeService.js index 2aeab2ddf..e3c16e5b2 100644 --- a/src/backend/src/services/ReferralCodeService.js +++ b/src/backend/src/services/ReferralCodeService.js @@ -36,19 +36,6 @@ const { UserIDNotifSelector } = require('./NotificationService'); * unique and properly assigned during user interactions. */ class ReferralCodeService extends BaseService { - /** - * Generates a unique referral code for the specified user. - * The method attempts to create a referral code and store it - * in the database. It will retry up to a maximum number of - * attempts if a collision occurs. If the user is missing or - * not properly defined, an error is reported. - * - * @param {Object} user - The user object for whom the referral - * code is being generated. - * @returns {Promise} The generated referral code. - * @throws {Error} If the user is not defined or if an error - * occurs while writing to the database. - */ _construct () { this.REFERRAL_INCREASE_LEFT = 1 * 1024 * 1024 * 1024; // 1 GB this.REFERRAL_INCREASE_RIGHT = 1 * 1024 * 1024 * 1024; // 1 GB diff --git a/src/backend/src/services/RegistrantService.js b/src/backend/src/services/RegistrantService.js index 7bcaddc9e..a50f34abb 100644 --- a/src/backend/src/services/RegistrantService.js +++ b/src/backend/src/services/RegistrantService.js @@ -31,11 +31,8 @@ const BaseService = require("./BaseService"); */ class RegistrantService extends BaseService { /** - * Service class responsible for registering and managing property types and object mappings - * in the system registry. Extends BaseService to provide core functionality. - * - * @extends BaseService - */ + * If population fails, marks the system as invalid through system validation. + */ async _init () { const svc_systemValidation = this.services.get('system-validation'); try { @@ -50,8 +47,8 @@ class RegistrantService extends BaseService { /** * Initializes the registrant service by populating the registry. * Attempts to populate the registry with property types and mappings. - * If population fails, marks the system as invalid through system validation. - * @throws {Error} Propagates any errors from registry population to system validation + * If population fails, an error is thrown + * @throws {Error} Propagates any errors from registry population for system validation * @returns {Promise} */ async _populate_registry () { diff --git a/src/backend/src/services/RegistryService.js b/src/backend/src/services/RegistryService.js index 9c8293259..cfd9a2baf 100644 --- a/src/backend/src/services/RegistryService.js +++ b/src/backend/src/services/RegistryService.js @@ -25,7 +25,7 @@ const BaseService = require("./BaseService"); * @class MapCollection * @extends AdvancedBase * -* The `MapCollection` class extends the `AdvancedBase` class and is responsible for managing a collection of key-value pairs in a distributed system. +* The `MapCollection` class extends the `AdvancedBase` class and is responsible for managing a collection of key-value pairs. * It leverages the `kvjs` library for key-value storage and the `uuid` library for generating unique identifiers for each key-value pair. * This class provides methods for basic CRUD operations (create, read, update, delete) on the key-value pairs, as well as methods for checking the existence of a key and retrieving all keys in the collection. */ diff --git a/src/backend/src/services/SUService.js b/src/backend/src/services/SUService.js index 2cbaa348f..e89950f26 100644 --- a/src/backend/src/services/SUService.js +++ b/src/backend/src/services/SUService.js @@ -26,6 +26,9 @@ const BaseService = require("./BaseService"); /** +* "SUS"-Service (Super-User Service) +* Wherever you see this, be suspicious! (it escalates privileges) +* * SUService is a specialized service that extends BaseService, * designed to manage system user and actor interactions. It * handles the initialization of system-level user and actor @@ -42,20 +45,7 @@ class SUService extends BaseService { this.sys_user_ = new TeePromise(); this.sys_actor_ = new TeePromise(); } - /** - * Initializes the SUService by creating instances of TeePromise for system user and actor. - * This method is invoked during the construction of the SUService class. - */ - async ['__on_boot.consolidation'] () { - const sys_user = await get_user({ username: 'system' }); - this.sys_user_.resolve(sys_user); - const sys_actor = new Actor({ - type: new UserActorType({ - user: sys_user, - }), - }); - this.sys_actor_.resolve(sys_actor); - } + /** * Resolves the system actor and user upon booting the service. * This method fetches the system user and then creates an Actor @@ -66,9 +56,17 @@ class SUService extends BaseService { * @returns {Promise} A promise that resolves when both the * system user and actor have been set. */ - async get_system_actor () { - return this.sys_actor_; + async ['__on_boot.consolidation'] () { + const sys_user = await get_user({ username: 'system' }); + this.sys_user_.resolve(sys_user); + const sys_actor = new Actor({ + type: new UserActorType({ + user: sys_user, + }), + }); + this.sys_actor_.resolve(sys_actor); } + /** * Retrieves the system actor instance. * @@ -77,23 +75,29 @@ class SUService extends BaseService { * * @returns {Promise} A promise that resolves to the system actor. */ + async get_system_actor () { + return this.sys_actor_; + } + + /** + * Super-User Do + * + * Performs an operation as a specified actor, allowing for callback execution + * within the context of that actor. If no actor is provided, the system actor + * is used by default. The adapted actor is then utilized to execute the callback + * under the appropriate user context. + * + * @param {Actor} actor - The actor to perform the operation as. + * If omitted, defaults to the system actor. + * @param {Function} callback - The function to execute within the actor's context. + * @returns {Promise} A promise that resolves with the result of the callback execution. + */ async sudo (actor, callback) { if ( ! callback ) { callback = actor; actor = await this.sys_actor_; } actor = Actor.adapt(actor); - /** - * Performs an operation as a specified actor, allowing for callback execution - * within the context of that actor. If no actor is provided, the system actor - * is used by default. The adapted actor is then utilized to execute the callback - * under the appropriate user context. - * - * @param {Actor} actor - The actor to perform the operation as. - * If omitted, defaults to the system actor. - * @param {Function} callback - The function to execute within the actor's context. - * @returns {Promise} A promise that resolves with the result of the callback execution. - */ return await Context.get().sub({ actor, user: actor.type.user, diff --git a/src/backend/src/services/SessionService.js b/src/backend/src/services/SessionService.js index 2eb1f5525..0f69f26a1 100644 --- a/src/backend/src/services/SessionService.js +++ b/src/backend/src/services/SessionService.js @@ -45,13 +45,6 @@ class SessionService extends BaseService { } - /** - * Initializes the SessionService by setting up the database connection and scheduling periodic session updates. - * @async - * @memberof SessionService - * @instance - * @returns {Promise} - */ _construct () { this.sessions = {}; } @@ -194,6 +187,12 @@ class SessionService extends BaseService { return sessions.map(this.remove_internal_values_.bind(this)); } + /** + * Removes a session from the in-memory cache and the database. + * + * @param {string} uuid - The UUID of the session to remove. + * @returns {Promise} A promise that resolves to the result of the database write operation. + */ remove_session (uuid) { delete this.sessions[uuid]; return this.db.write( @@ -203,12 +202,6 @@ class SessionService extends BaseService { } - /** - * Removes a session from the in-memory cache and the database. - * - * @param {string} uuid - The UUID of the session to remove. - * @returns {Promise} A promise that resolves to the result of the database write operation. - */ async _update_sessions () { this.log.tick('UPDATING SESSIONS'); const now = Date.now(); diff --git a/src/backend/src/services/ShareService.js b/src/backend/src/services/ShareService.js index 9df64d3c8..43f9c147c 100644 --- a/src/backend/src/services/ShareService.js +++ b/src/backend/src/services/ShareService.js @@ -36,18 +36,6 @@ class ShareService extends BaseService { }; - /** - * Method to handle the creation of a new share - * - * This method creates a new share and saves it to the database. - * It takes three parameters: the issuer of the share, the recipient's email address, and the data to be shared. - * The method returns the UID of the created share. - * - * @param {Actor} issuer - The actor who is creating the share - * @param {string} email - The email address of the recipient - * @param {object} data - The data to be shared - * @returns {string} - The UID of the created share - */ async _init () { this.db = await this.services.get('database').get(DB_WRITE, 'share'); @@ -114,17 +102,17 @@ class ShareService extends BaseService { this.install_share_endpoint({ app }); } + /** + * This method is responsible for processing the share link application request. + * It checks if the share token is valid and if the user making the request is the intended recipient. + * If both conditions are met, it grants the requested permissions to the user and deletes the share from the database. + * + * @param {Object} req - Express request object. + * @param {Object} res - Express response object. + * @returns {Promise} + */ install_sharelink_endpoints ({ app }) { // track: scoping iife - /** - * This method is responsible for processing the share link application request. - * It checks if the share token is valid and if the user making the request is the intended recipient. - * If both conditions are met, it grants the requested permissions to the user and deletes the share from the database. - * - * @param {Object} req - Express request object. - * @param {Object} res - Express response object. - * @returns {Promise} - */ const router = (() => { const require = this.require; const express = require('express'); @@ -368,6 +356,18 @@ class ShareService extends BaseService { return share; } + /** + * Method to handle the creation of a new share + * + * This method creates a new share and saves it to the database. + * It takes three parameters: the issuer of the share, the recipient's email address, and the data to be shared. + * The method returns the UID of the created share. + * + * @param {Actor} issuer - The actor who is creating the share + * @param {string} email - The email address of the recipient + * @param {object} data - The data to be shared + * @returns {string} - The UID of the created share + */ async create_share ({ issuer, email, diff --git a/src/backend/src/services/StrategizedService.js b/src/backend/src/services/StrategizedService.js index 15b62ccf4..22c04d45c 100644 --- a/src/backend/src/services/StrategizedService.js +++ b/src/backend/src/services/StrategizedService.js @@ -22,11 +22,10 @@ const { quot } = require('@heyputer/putility').libs.string; /** -* Represents a service that applies strategies based on provided configuration -* and specified keys. The StrategizedService class initializes and manages -* strategies for a given service, ensuring that the necessary configurations -* and arguments are provided before attempting to execute any strategy logic. -*/ + * An abstract service used to strategize services in confirguration, + * primarily used for thumbnail service selection, but it could be used + * to strategize any service. + */ class StrategizedService { constructor (service_resources, ...a) { const { my_config, args, name } = service_resources; @@ -63,23 +62,13 @@ class StrategizedService { /** - * Initializes the service and throws an error if initialization fails. - * This method utilizes the initError property to determine if an error - * occurred during the setup process in the constructor. - * - * @throws {TechnicalError} Throws a TechnicalError if initError is set. + * This method must be implemented by the delegate or an error will be thrown */ async init () { throw this.initError; } - /** - * Constructs a new instance of the service. - * - * This method initializes any necessary resources or settings for the service instance. - * It does not accept any parameters and does not return any value. - */ async construct () {} } diff --git a/src/backend/src/services/SystemDataService.js b/src/backend/src/services/SystemDataService.js index 8d6826cc9..7e75b084f 100644 --- a/src/backend/src/services/SystemDataService.js +++ b/src/backend/src/services/SystemDataService.js @@ -34,9 +34,10 @@ const BaseService = require("./BaseService"); * - Manage different data types encountered during operations, ensuring proper handling or throwing errors for unrecognized types. */ class SystemDataService extends BaseService { + async _init () {} + /** - * Recursively interprets the structure of the given data object. - * This method handles dereferencing and deep interpretation of nested structures. + * Interprets data, dereferencing JSON-address pointers if necessary. * * @param {Object|Array|string|number|boolean|null} data - The data to interpret. * Can be an object, array, or primitive value. @@ -44,16 +45,6 @@ class SystemDataService extends BaseService { * For objects and arrays, this method recursively interprets each element. * For special objects with a '$' property, it performs dereferencing. */ - async _init () {} - - - /** - * Initializes the SystemDataService. - * This method is called when the service is instantiated to set up any necessary state or resources. - * - * @async - * @returns {Promise} A promise that resolves when initialization is complete. - */ async interpret (data) { if ( whatis(data) === 'object' && data.$ ) { return await this.dereference_(data); @@ -77,11 +68,8 @@ class SystemDataService extends BaseService { /** - * Recursively interprets and potentially dereferences complex data structures. - * - * This method handles: - * - Objects with special dereferencing syntax (indicated by the `$` property). - * - Nested objects and arrays by recursively calling itself on each element. + * De-references a JSON address by reading the respective file and parsing + * the JSON contents. * * @param {Object|Array|*} data - The data to interpret, which can be of any type. * @returns {Promise<*>} The interpreted result, which could be a primitive, object, or array. diff --git a/src/backend/src/services/TraceService.js b/src/backend/src/services/TraceService.js index 8f056b612..8f5dbb74a 100644 --- a/src/backend/src/services/TraceService.js +++ b/src/backend/src/services/TraceService.js @@ -28,12 +28,6 @@ const opentelemetry = require("@opentelemetry/api"); * operations and measuring performance within the application. */ class TraceService { - /** - * Retrieves the tracer instance used for creating spans. - * This method is a getter that returns the current tracer object. - * - * @returns {Tracer} The tracer instance for the TraceService. - */ constructor () { this.tracer_ = opentelemetry.trace.getTracer( 'puter-filesystem-tracer' @@ -42,7 +36,8 @@ class TraceService { /** - * Returns the tracer instance used by the TraceService. + * Retrieves the tracer instance used for creating spans. + * This method is a getter that returns the current tracer object. * * @returns {import("@opentelemetry/api").Tracer} The tracer instance for this service. */ diff --git a/src/backend/src/services/WSPushService.js b/src/backend/src/services/WSPushService.js index 5634eba63..ffd04b13a 100644 --- a/src/backend/src/services/WSPushService.js +++ b/src/backend/src/services/WSPushService.js @@ -19,6 +19,12 @@ */ const BaseService = require("./BaseService"); class WSPushService extends BaseService { + /** + * Initializes the WSPushService by setting up event listeners for various file system operations. + * + * @param {Object} options - The configuration options for the service. + * @param {Object} options.services - An object containing service dependencies. + */ async _init () { this.svc_event = this.services.get('event'); @@ -35,12 +41,6 @@ class WSPushService extends BaseService { } - /** - * Initializes the WSPushService by setting up event listeners for various file system operations. - * - * @param {Object} options - The configuration options for the service. - * @param {Object} options.services - An object containing service dependencies. - */ async _on_fs_create (key, data) { const { node, context } = data; @@ -58,19 +58,6 @@ class WSPushService extends BaseService { const response = await node.getSafeEntry({ thumbnail: true }); - /** - * Emits an upload or download progress event to the relevant socket. - * - * @param {string} key - The event key that triggered this method. - * @param {Object} data - Contains upload_tracker, context, and meta information. - * @param {Object} data.upload_tracker - Tracker for the upload/download progress. - * @param {Object} data.context - Context of the operation. - * @param {Object} data.meta - Additional metadata for the event. - * - * @note This method logs information about the progress event and checks for the presence of a socket ID. - * If the socket ID is missing, it logs an error but does not throw an exception for the Puter V1 release. - * It emits a progress event to the socket if it exists, otherwise, it does nothing if the socket has disconnected. - */ const user_id_list = await (async () => { // NOTE: Using a set because eventually we will need to dispatch // to multiple users, but this is not currently the case. @@ -94,12 +81,16 @@ class WSPushService extends BaseService { * * @param {string} key - The event key. * @param {Object} data - The event data containing node and context information. + * @returns {Promise} A promise that resolves when the update has been processed. * - * @description This method processes 'fs.update.*' events, retrieves necessary metadata, - * and emits an 'outer.gui.item.updated' event to update the GUI for the relevant users. - * It gathers user IDs, merges metadata, and prepares a response object for emission. + * @description + * This method is triggered when a file or directory is updated. It retrieves + * metadata from the context, fetches the updated node's entry, determines the + * relevant user IDs, and emits an event to notify the GUI of the update. * - * @returns {Promise} - Resolves when the event has been processed and emitted. + * @note + * - The method uses a set for user IDs to prepare for future multi-user dispatch. + * - If no specific user ID is provided in the metadata, it falls back to the node's user ID. */ async _on_fs_update (key, data) { const { node, context } = data; @@ -117,23 +108,6 @@ class WSPushService extends BaseService { const response = await node.getSafeEntry({ debug: 'hi', thumbnail: true }); - - /** - * Handles file system update events. - * - * @param {string} key - The event key. - * @param {Object} data - The event data containing node and context information. - * @returns {Promise} A promise that resolves when the update has been processed. - * - * @description - * This method is triggered when a file or directory is updated. It retrieves - * metadata from the context, fetches the updated node's entry, determines the - * relevant user IDs, and emits an event to notify the GUI of the update. - * - * @note - * - The method uses a set for user IDs to prepare for future multi-user dispatch. - * - If no specific user ID is provided in the metadata, it falls back to the node's user ID. - */ const user_id_list = await (async () => { // NOTE: Using a set because eventually we will need to dispatch // to multiple users, but this is not currently the case. @@ -182,18 +156,6 @@ class WSPushService extends BaseService { const response = await moved.getSafeEntry(); - - /** - * Handles the file system move event by emitting a GUI update event. - * This method processes the metadata associated with the move operation, - * retrieves safe entry details for the moved item, and notifies relevant users. - * - * @param {string} key - The event key for the move operation. - * @param {Object} data - Contains details of the move operation: - * - moved: The file system entry that was moved. - * - old_path: The original path of the moved item. - * - context: Contextual information for the operation. - */ const user_id_list = await (async () => { // NOTE: Using a set because eventually we will need to dispatch // to multiple users, but this is not currently the case. @@ -220,6 +182,7 @@ class WSPushService extends BaseService { * @param {Object} data - An object containing the fsentry and context of the pending file system operation. * @param {Object} data.fsentry - The file system entry that is pending. * @param {Object} data.context - The operation context providing additional metadata. + * @fires svc_event#outer.gui.item.pending - Emitted with user ID list and entry details. * * @returns {Promise} Emits an event to update the GUI about the pending item. */ @@ -239,17 +202,6 @@ class WSPushService extends BaseService { Object.assign(metadata, gui_metadata); } - - /** - * Emits a 'outer.gui.item.pending' event for an FS entry in a pending state. - * - * @param {string} key - The event key triggering this method. - * @param {Object} data - Contains the FS entry data and context. - * @param {Object} data.fsentry - The file system entry object. - * @param {Object} data.context - The context object containing service information. - * - * @fires svc_event#outer.gui.item.pending - Emitted with user ID list and entry details. - */ const user_id_list = await (async () => { // NOTE: Using a set because eventually we will need to dispatch // to multiple users, but this is not currently the case. @@ -266,18 +218,16 @@ class WSPushService extends BaseService { }); } - /** - * Handles upload progress events. + * Emits an upload or download progress event to the relevant socket. * - * @param {string} key - The event key. - * @param {Object} data - The event data containing upload progress information. - * @returns {Promise} A promise that resolves when the progress has been emitted to the appropriate socket. + * @param {string} key - The event key that triggered this method. + * @param {Object} data - Contains upload_tracker, context, and meta information. + * @param {Object} data.upload_tracker - Tracker for the upload/download progress. + * @param {Object} data.context - Context of the operation. + * @param {Object} data.meta - Additional metadata for the event. * - * @description - * This method processes upload progress events, logs information, - * prepares metadata, and emits the progress to the client socket associated with the given socket ID. - * If the socket ID is missing or the socket has disconnected, appropriate actions are taken. + * It emits a progress event to the socket if it exists, otherwise, it does nothing. */ async _on_upload_progress (key, data) { this.log.info('got upload progress event');