Selaa lähdekoodia

doc: ai generated comments

KernelDeimos 6 kuukautta sitten
vanhempi
säilyke
7a8687cd2c

+ 28 - 0
src/backend/src/services/AnomalyService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"openai-completion","model":"gpt-4o"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -18,9 +19,26 @@
  */
 const BaseService = require("./BaseService");
 
+// Symbol used to indicate a denial of service instruction in anomaly handling.
 const DENY_SERVICE_INSTRUCTION = Symbol('DENY_SERVICE_INSTRUCTION');
 
+
+/**
+* @class AnomalyService
+* @extends BaseService
+* @description The AnomalyService class is responsible for managing and processing anomaly detection types and configurations.
+* It allows the registration of different types with associated handlers, enabling the detection of anomalies based on specified criteria.
+*/
 class AnomalyService extends BaseService {
+    /**
+    * AnomalyService class that extends BaseService and provides methods
+    * for registering anomaly types and handling incoming data for those anomalies.
+    * 
+    * The register method allows the registration of different anomaly types 
+    * and their respective configurations, including custom handlers for data 
+    * evaluation. It supports two modes of operation: a direct handler or 
+    * a threshold-based evaluation.
+    */
     _construct () {
         this.types = {};
     }
@@ -39,6 +57,16 @@ class AnomalyService extends BaseService {
         }
         this.types[type] = type_instance;
     }
+    /**
+     * Registers a new type with the service, including its configuration and handler.
+     * 
+     * @param {string} type - The name of the type to register.
+     * @param {Object} config - The configuration object for the type.
+     * @param {Function} [config.handler] - An optional handler function for the type.
+     * @param {number} [config.high] - An optional threshold value; triggers the handler if exceeded.
+     * 
+     * @returns {void}
+     */
     async note (id, data) {
         const type = this.types[id];
         if ( ! type ) return;

+ 134 - 0
src/backend/src/services/AppInformationService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"xai"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -23,6 +24,17 @@ const { DB_READ } = require("./database/consts");
 
 const uuidv4 = require('uuid').v4;
 
+
+/**
+* @class AppInformationService
+* @description
+* The AppInformationService class manages application-related information,
+* including caching, statistical data, and tags for applications within the Puter ecosystem.
+* It provides methods for refreshing application data, managing app statistics,
+* and handling tags associated with apps. This service is crucial for maintaining
+* up-to-date information about applications, facilitating features like app listings,
+* recent apps, and tag-based app discovery.
+*/
 class AppInformationService {
     constructor ({ services }) {
         this.services = services;
@@ -37,33 +49,87 @@ class AppInformationService {
             // await new Promise(rslv => setTimeout(rslv, 500))
 
             await this._refresh_app_cache();
+            /**
+            * Refreshes the application cache by querying the database for all apps and updating the key-value store.
+            * 
+            * This method is called periodically to ensure that the in-memory cache reflects the latest
+            * state from the database. It uses the 'database' service to fetch app data and then updates
+            * multiple cache entries for quick lookups by name, ID, and UID.
+            *
+            * @async
+            */
             asyncSafeSetInterval(async () => {
                 this._refresh_app_cache();
             }, 30 * 1000);
 
             await this._refresh_app_stats();
+            /**
+            * Refreshes the cache of recently opened apps.
+            * This method updates the 'recent' collection with the UIDs of apps sorted by their most recent timestamp.
+            * 
+            * @async
+            * @returns {Promise<void>} A promise that resolves when the cache has been refreshed.
+            */
             asyncSafeSetInterval(async () => {
                 this._refresh_app_stats();
             }, 120 * 1000);
 
             // This stat is more expensive so we don't update it as often
             await this._refresh_app_stat_referrals();
+            /**
+            * Refreshes the app referral statistics.
+            * This method is computationally expensive and thus runs less frequently.
+            * It queries the database for user counts referred by each app's origin URL.
+            * 
+            * @async
+            */
             asyncSafeSetInterval(async () => {
                 this._refresh_app_stat_referrals();
             }, 15 * MINUTE);
 
             await this._refresh_recent_cache();
+            /**
+            * Refreshes the recent cache by updating the list of recently added or updated apps.
+            * This method fetches all app data, filters for approved apps, sorts them by timestamp,
+            * and updates the `this.collections.recent` array with the UIDs of the most recent 50 apps.
+            * 
+            * @async
+            * @private
+            */
             asyncSafeSetInterval(async () => {
                 this._refresh_recent_cache();
             }, 120 * 1000);
 
             await this._refresh_tags();
+            /**
+            * Refreshes the tags cache by iterating through all approved apps,
+            * extracting their tags, and organizing them into a structured format.
+            * This method updates the `this.tags` object with the latest tag information.
+            *
+            * @async
+            * @method
+            * @memberof AppInformationService
+            */
             asyncSafeSetInterval(async () => {
                 this._refresh_tags();
             } , 120 * 1000);
         })();
     }
 
+
+    /**
+    * Retrieves and returns statistical data for a specific application.
+    * 
+    * This method fetches various metrics such as the number of times the app has been opened,
+    * the count of unique users who have opened the app, and the number of referrals attributed to the app.
+    * It uses cached data where available to improve performance.
+    *
+    * @param {string} app_uid - The unique identifier for the application.
+    * @returns {Promise<Object>} An object containing:
+    *   - {number} open_count - The total number of times the app has been opened.
+    *   - {number} user_count - The count of unique users who have opened the app.
+    *   - {number|null} referral_count - The number of referrals, or null if the data is not available or too expensive to retrieve.
+    */
     async get_stats (app_uid) {
         const db = this.services.get('database').get(DB_READ, 'apps');
 
@@ -100,6 +166,19 @@ class AppInformationService {
         };
     }
 
+
+    /**
+    * Retrieves various statistics for a given app.
+    * 
+    * This method fetches the open count, user count, and referral count for an app identified by its UID.
+    * It uses cached values where available to improve performance, but will query the database if necessary.
+    * 
+    * @param {string} app_uid - The unique identifier of the app for which to retrieve stats.
+    * @returns {Promise<Object>} An object containing:
+    *   - {number} open_count - Total number of times the app was opened.
+    *   - {number} user_count - Number of unique users who opened the app.
+    *   - {number|null} referral_count - Number of referrals attributed to the app. This value might not be reported if not cached.
+    */
     async _refresh_app_cache () {
         this.log.tick('refresh app cache');
 
@@ -114,6 +193,17 @@ class AppInformationService {
         }
     }
 
+
+    /**
+    * Refreshes the application cache by querying the database for all apps and updating the key-value store.
+    * 
+    * @async
+    * @returns {Promise<void>} A promise that resolves when the cache refresh operation is complete.
+    * 
+    * @notes
+    * - This method logs a tick event for performance monitoring.
+    * - It populates the cache with app data indexed by name, id, and uid.
+    */
     async _refresh_app_stats () {
         this.log.tick('refresh app stats');
 
@@ -144,6 +234,13 @@ class AppInformationService {
         }
     }
 
+
+    /**
+    * Refreshes the cache of app statistics including open and user counts.
+    * This method updates the cache every 120 seconds to ensure data freshness.
+    *
+    * @async
+    */
     async _refresh_app_stat_referrals () {
         this.log.tick('refresh app stat referrals');
 
@@ -176,6 +273,17 @@ class AppInformationService {
         this.log.info('DONE refresh app stat referrals');
     }
 
+
+    /**
+    * Updates the cache with recently updated apps.
+    * 
+    * @description This method refreshes the cache containing the most recently updated applications.
+    *              It fetches all app UIDs, retrieves the corresponding app data, filters for approved apps,
+    *              sorts them by timestamp in descending order, and updates the 'recent' collection with
+    *              the UIDs of the top 50 most recent apps.
+    * 
+    * @returns {Promise<void>} Resolves when the cache has been updated.
+    */
     async _refresh_recent_cache () {
         const app_keys = kv.keys(`apps:uid:*`);
         // console.log('APP KEYS', app_keys);
@@ -194,6 +302,16 @@ class AppInformationService {
         this.collections.recent = apps.map(app => app.uid).slice(0, 50);
     }
 
+
+    /**
+    * Refreshes the cache of recently added or updated apps.
+    * 
+    * This method retrieves all apps from the cache, filters for approved listings,
+    * sorts them by timestamp in descending order, and updates the `recent` collection
+    * with the UIDs of the most recent 50 apps.
+    *
+    * @returns {Promise<void>}
+    */
     async _refresh_tags () {
         const app_keys = kv.keys(`apps:uid:*`);
         // console.log('APP KEYS', app_keys);
@@ -229,6 +347,22 @@ class AppInformationService {
         this.tags = new_tags;
     }
 
+
+    /**
+    * Deletes an application from the system.
+    * 
+    * This method performs the following actions:
+    * - Retrieves the app data from cache or database if not provided.
+    * - Deletes the app record from the database.
+    * - Removes the app from all relevant caches (by name, id, and uid).
+    * - Removes the app from the recent collection if present.
+    * - Removes the app from any associated tags.
+    * 
+    * @param {string} app_uid - The unique identifier of the app to be deleted.
+    * @param {Object} [app] - The app object, if already fetched. If not provided, it will be retrieved.
+    * @throws {Error} If the app is not found in either cache or database.
+    * @returns {Promise<void>} A promise that resolves when the app has been successfully deleted.
+    */
     async delete_app (app_uid, app) {
         const db = this.services.get('database').get(DB_READ, 'apps');
 

+ 46 - 0
src/backend/src/services/BaseService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-params":{"service":"xai"},"ai-refs":["../../doc/contributors/boot-sequence.md"],"ai-commented":{"service":"xai"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -18,8 +19,25 @@
  */
 const { concepts } = require("@heyputer/putility");
 
+
+
+// This is a no-op function that AI is incapable of writing a comment for.
+// That said, I suppose it didn't need one anyway.
 const NOOP = async () => {};
 
+
+/**
+* @class BaseService
+* @extends concepts.Service
+* @description
+* BaseService is the foundational class for all services in the Puter backend.
+* It provides lifecycle methods like `construct` and `init` that are invoked during
+* different phases of the boot sequence. This class ensures that services can be
+* instantiated, initialized, and activated in a coordinated manner through
+* events emitted by the Kernel. It also manages common service resources like
+* logging and error handling, and supports legacy services by allowing
+* instantiation after initialization but before consolidation.
+*/
 class BaseService extends concepts.Service {
     constructor (service_resources, ...a) {
         const { services, config, my_config, name, args } = service_resources;
@@ -36,10 +54,29 @@ class BaseService extends concepts.Service {
         }
     }
 
+
+    /**
+    * Initializes the service with configuration and dependencies.
+    * This method sets up logging and error handling, and calls a custom `_init` method if defined.
+    * 
+    * @param {Object} args - Arguments passed to the service for initialization.
+    * @returns {Promise<void>} A promise that resolves when initialization is complete.
+    */
     async construct () {
         await (this._construct || NOOP).call(this, this.args);
     }
 
+
+    /**
+    * Performs the initialization phase of the service lifecycle.
+    * This method sets up logging and error handling for the service,
+    * then calls the service-specific initialization logic if defined.
+    * 
+    * @async
+    * @memberof BaseService
+    * @instance
+    * @returns {Promise<void>} A promise that resolves when initialization is complete.
+    */
     async init () {
         const services = this.services;
         this.log = services.get('log-service').create(this.service_name);
@@ -48,6 +85,15 @@ class BaseService extends concepts.Service {
         await (this._init || NOOP).call(this, this.args);
     }
 
+
+    /**
+    * Handles an event by retrieving the appropriate event handler
+    * and executing it with the provided arguments.
+    *
+    * @param {string} id - The identifier of the event to handle.
+    * @param {Array<any>} args - The arguments to pass to the event handler.
+    * @returns {Promise<any>} The result of the event handler execution.
+    */
     async __on (id, args) {
         const handler = this.__get_event_handler(id);
 

+ 30 - 0
src/backend/src/services/BootScriptService.js

@@ -1,10 +1,29 @@
+// METADATA // {"ai-commented":{"service":"mistral","model":"mistral-large-latest"}}
 const { Context } = require("../util/context");
 const BaseService = require("./BaseService");
 
+
+/**
+* @class BootScriptService
+* @extends BaseService
+* @description The BootScriptService class extends BaseService and is responsible for
+* managing and executing boot scripts. It provides methods to handle boot scripts when
+* the system is ready and to run individual script commands.
+*/
 class BootScriptService extends BaseService {
     static MODULES = {
         fs: require('fs'),
     }
+    /**
+    * Loads and executes a boot script if specified in the arguments.
+    *
+    * This method reads the provided boot script file, parses it, and runs the script using the `run_script` method.
+    * If no boot script is specified in the arguments, the method returns immediately.
+    *
+    * @async
+    * @function
+    * @returns {Promise<void>}
+    */
     async ['__on_boot.ready'] () {
         const args = Context.get('args');
         if ( ! args['boot-script'] ) return;
@@ -17,6 +36,17 @@ class BootScriptService extends BaseService {
         await this.run_script(boot_json);
     }
 
+
+    /**
+    * Executes a series of commands defined in a JSON boot script.
+    *
+    * This method processes each command in the boot_json array.
+    * If the command is recognized within the predefined scope, it will be executed.
+    * If not, an error is thrown.
+    *
+    * @param {Array} boot_json - An array of commands to execute.
+    * @throws {Error} Thrown if an unknown command is encountered.
+    */
     async run_script (boot_json) {
         const scope = {
             runner: 'boot-script',

+ 34 - 0
src/backend/src/services/CleanEmailService.js

@@ -1,6 +1,15 @@
+// METADATA // {"ai-commented":{"service":"claude"}}
 const { can } = require("../util/langutil");
 const BaseService = require("./BaseService");
 
+
+/**
+* CleanEmailService - A service class for cleaning and validating email addresses
+* Handles email normalization by applying provider-specific rules (e.g. Gmail's dot-insensitivity),
+* manages subaddressing (plus addressing), and validates against blocked domains.
+* Extends BaseService to integrate with the application's service infrastructure.
+* @extends BaseService
+*/
 class CleanEmailService extends BaseService {
     static NAMED_RULES = {
         // For some providers, dots don't matter
@@ -54,6 +63,12 @@ class CleanEmailService extends BaseService {
     static DOMAIN_NONDISTINCT = {
         'googlemail.com': 'gmail.com',
     }
+    /**
+    * Maps non-distinct email domains to their canonical equivalents.
+    * For example, 'googlemail.com' is mapped to 'gmail.com' since they
+    * represent the same email service.
+    * @type {Object.<string, string>}
+    */
     _construct () {
         this.named_rules = this.constructor.NAMED_RULES;
         this.providers = this.constructor.PROVIDERS;
@@ -62,6 +77,16 @@ class CleanEmailService extends BaseService {
     }
 
     clean (email) {
+        /**
+        * Cleans an email address by applying provider-specific rules and standardizations
+        * @param {string} email - The email address to clean
+        * @returns {string} The cleaned email address with applied rules and standardizations
+        * 
+        * Splits email into local and domain parts, applies provider-specific rules like:
+        * - Removing dots for certain providers (Gmail, iCloud)
+        * - Handling subaddressing (removing +suffix)
+        * - Normalizing domains (e.g. googlemail.com -> gmail.com)
+        */
         const eml = (() => {
             const [local, domain] = email.split('@');
             return { local, domain };
@@ -101,6 +126,15 @@ class CleanEmailService extends BaseService {
         return eml.local + '@' + eml.domain;
     }
     
+
+    /**
+    * Validates an email address against blocked domains and custom validation rules
+    * @param {string} email - The email address to validate
+    * @returns {Promise<boolean>} True if email is valid, false if blocked or invalid
+    * @description First cleans the email, then checks against blocked domains from config.
+    * Emits 'email.validate' event to allow custom validation rules. Event handlers can
+    * set event.allow=false to reject the email.
+    */
     async validate (email) {
         email = this.clean(email);
         const config = this.global_config;

+ 23 - 0
src/backend/src/services/ClientOperationService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"openai-completion","model":"gpt-4o"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -18,7 +19,14 @@
  */
 const { Context } = require("../util/context");
 
+// Key for tracing operations in the context, used for logging and tracking.
 const CONTEXT_KEY = Context.make_context_key('operation-trace');
+/**
+* Class representing a tracker for individual client operations.
+* The ClientOperationTracker class is designed to handle the metadata
+* and attributes associated with each operation, allowing for better 
+* management and organization of client data during processing.
+*/
 class ClientOperationTracker {
     constructor (parameters) {
         this.name = parameters.name || 'untitled';
@@ -29,11 +37,26 @@ class ClientOperationTracker {
     }
 }
 
+
+/**
+* Class representing the ClientOperationService, which manages the 
+* operations related to client interactions. It provides methods to 
+* add new operations and handle their associated client operation 
+* trackers, ensuring efficient management and tracking of client-side 
+* operations during their lifecycle.
+*/
 class ClientOperationService {
     constructor ({ services }) {
         this.operations_ = [];
     }
 
+
+    /**
+    * Adds a new operation to the service by creating a ClientOperationTracker instance.
+    * 
+    * @param {Object} parameters - The parameters for the new operation.
+    * @returns {Promise<ClientOperationTracker>} A promise that resolves to the created ClientOperationTracker instance.
+    */
     async add_operation (parameters) {
         const tracker = new ClientOperationTracker(parameters);
 

+ 70 - 0
src/backend/src/services/CommandService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"claude"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -18,15 +19,36 @@
  */
 const BaseService = require("./BaseService");
 
+
+/**
+* Represents a Command class that encapsulates command execution functionality.
+* Each Command instance contains a specification (spec) that defines its ID,
+* name, description, handler function, and optional argument completer.
+* The class provides methods for executing commands and handling command
+* argument completion.
+*/
 class Command {
     constructor(spec) {
         this.spec_ = spec;
     }
 
+
+    /**
+    * Gets the unique identifier for this command
+    * @returns {string} The command's ID as specified in the constructor
+    */
     get id() {
         return this.spec_.id;
     }
 
+
+    /**
+    * Executes the command with given arguments and logging
+    * @param {Array} args - Command arguments to pass to the handler
+    * @param {Object} [log=console] - Logger object for output, defaults to console
+    * @returns {Promise<void>}
+    * @throws {Error} Logs any errors that occur during command execution
+    */
     async execute(args, log) {
         log = log ?? console;
         const { id, name, description, handler } = this.spec_;
@@ -46,10 +68,30 @@ class Command {
     }
 }
 
+
+/**
+* CommandService class manages the registration, execution, and handling of commands in the Puter system.
+* Extends BaseService to provide command-line interface functionality. Maintains a collection of Command
+* objects, supports command registration with namespaces, command execution with arguments, and provides
+* command lookup capabilities. Includes built-in help command functionality.
+* @extends BaseService
+*/
 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.
+    */
     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<void>}
+    */
     async _init () {
         this.commands_.push(new Command({
             id: 'help',
@@ -73,6 +115,14 @@ class CommandService extends BaseService {
         }
     }
 
+
+    /**
+    * Executes a command with the given arguments and logging context
+    * @param {string[]} args - Array of command arguments where first element is command name
+    * @param {Object} log - Logger object for output (defaults to console if not provided)
+    * @returns {Promise<void>}
+    * @throws {Error} If command execution fails
+    */
     async executeCommand(args, log) {
         const [commandName, ...commandArgs] = args;
         const command = this.commands_.find(c => c.spec_.id === commandName);
@@ -80,17 +130,37 @@ class CommandService extends BaseService {
             log.error(`unknown command: ${commandName}`);
             return;
         }
+        /**
+        * Executes a command with the given arguments in a global context
+        * @param {string[]} args - Array of command arguments where first element is command name
+        * @param {Object} log - Logger object for output
+        * @returns {Promise<void>}
+        * @throws {Error} If command execution fails
+        */
         await globalThis.root_context.arun(async () => {
             await command.execute(commandArgs, log);
         });
     }
 
+
+    /**
+    * Executes a raw command string by splitting it into arguments and executing the command
+    * @param {string} text - Raw command string to execute
+    * @param {object} log - Logger object for output (defaults to console if not provided)
+    * @returns {Promise<void>}
+    * @todo Replace basic whitespace splitting with proper tokenizer (obvious-json)
+    */
     async executeRawCommand(text, log) {
         // TODO: add obvious-json as a tokenizer
         const args = text.split(/\s+/);
         await this.executeCommand(args, log);
     }
 
+
+    /**
+    * Gets a list of all registered command names/IDs
+    * @returns {string[]} Array of command identifier strings
+    */
     get commandNames() {
         return this.commands_.map(command => command.id);
     }

+ 50 - 0
src/backend/src/services/CommentService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"claude"}}
 const APIError = require("../api/APIError");
 const FSNodeParam = require("../api/filesystem/FSNodeParam");
 const { get_user } = require("../helpers");
@@ -6,15 +7,37 @@ const { Endpoint } = require("../util/expressutil");
 const BaseService = require("./BaseService");
 const { DB_WRITE } = require("./database/consts");
 
+
+/**
+* CommentService class handles all comment-related functionality in the system.
+* Extends BaseService to provide comment creation, retrieval, and attachment capabilities
+* for filesystem entries. Manages database operations for user comments and their
+* associations with filesystem nodes. Provides REST API endpoints for comment
+* operations including posting new comments and listing existing comments.
+* @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
+    */
     _init () {
         const svc_database = this.services.get('database');
         this.db = svc_database.get(DB_WRITE, 'notification');
     }
     ['__on_install.routes'] (_, { app }) {
+        /**
+        * Installs route handlers for comment-related endpoints
+        * Sets up POST routes for creating and listing comments on filesystem entries
+        * 
+        * @param {*} _ Unused parameter
+        * @param {Object} options Installation options
+        * @param {Express} options.app Express application instance
+        * @private
+        */
         const r_comment = (() => {
             const require = this.require;
             const express = require('express');
@@ -113,6 +136,16 @@ class CommentService extends BaseService {
 
     }
 
+
+    /**
+    * Creates a new comment with the given text
+    * 
+    * @param {Object} params - The parameters object
+    * @param {Object} params.req - Express request object containing user and body data
+    * @param {Object} params.res - Express response object
+    * @returns {Promise<Object>} The created comment object with id and uid
+    * @throws {APIError} If text field is missing from request body
+    */
     async create_comment_ ({ req, res }) {
         if ( ! req.body.text ) {
             throw APIError.create('field_missing', null, { key: 'text' });
@@ -135,6 +168,15 @@ class CommentService extends BaseService {
         };
     }
 
+
+    /**
+    * Attaches a comment to a filesystem entry
+    * 
+    * @param {Object} params - The parameters object
+    * @param {Object} params.node - The filesystem node to attach the comment to
+    * @param {Object} params.comment - The comment object containing id and other details
+    * @returns {Promise<void>} Resolves when comment is successfully attached
+    */
     async attach_comment_to_fsentry ({ node, comment })  {
         await this.db.write(
             'INSERT INTO `user_fsentry_comments` ' +
@@ -144,6 +186,14 @@ class CommentService extends BaseService {
         );
     }
 
+
+    /**
+    * Retrieves all comments associated with a filesystem entry
+    * 
+    * @param {Object} params - The parameters object
+    * @param {Object} params.node - The filesystem node to get comments for
+    * @returns {Promise<Array>} Array of comment objects with user info attached
+    */
     async get_comments_for_fsentry ({ node }) {
         const comments = await this.db.read(
             'SELECT * FROM `user_comments` ' +

+ 35 - 0
src/backend/src/services/ConfigurableCountingService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"mistral","model":"mistral-large-latest"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -27,6 +28,16 @@ const hash = v => {
     return sum.digest();
 }
 
+
+/**
+* @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
+*              types and values. This class is used to manage usage counts for various services, ensuring accurate tracking
+*              and updating of counts in the database.
+*/
 class ConfigurableCountingService extends BaseService {
     static counting_types = {
         gpt: {
@@ -73,10 +84,34 @@ class ConfigurableCountingService extends BaseService {
         ],
     }
 
+
+    /**
+    * Initializes the database connection for the ConfigurableCountingService.
+    * This method sets up the database service for writing counting data.
+    *
+    * @async
+    * @function _init
+    * @returns {Promise<void>} A promise that resolves when the database connection is established.
+    * @memberof ConfigurableCountingService
+    */
     async _init () {
         this.db = this.services.get('database').get(DB_WRITE, 'counting');
     }
 
+
+    /**
+    * Increments the count for a given service based on the provided parameters.
+    * This method builds an SQL query to update the count and other custom values
+    * in the database. It handles different SQL dialects (MySQL and SQLite) and
+    * ensures that the pricing category is correctly hashed and stored.
+    *
+    * @param {Object} params - The parameters for incrementing the count.
+    * @param {string} params.service_name - The name of the service.
+    * @param {string} params.service_type - The type of the service.
+    * @param {Object} params.values - The values to be incremented.
+    * @throws {Error} If the service type is unknown or if there are no more available columns.
+    * @returns {Promise<void>} A promise that resolves when the count is successfully incremented.
+    */
     async increment ({ service_name, service_type, values }) {
         values = values ? {...values} : {};
 

+ 53 - 0
src/backend/src/services/Container.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"mistral","model":"mistral-large-latest"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -23,6 +24,15 @@ const { CompositeError } = require("../util/errorutil");
 const { TeePromise } = require("../util/promise");
 
 // 17 lines of code instead of an entire dependency-injection framework
+/**
+* The `Container` class is a lightweight dependency-injection container designed to manage
+* service instances within the application. It provides functionality for registering,
+* retrieving, and managing the lifecycle of services, including initialization and event
+* handling. This class is intended to simplify dependency management and ensure that services
+* are properly initialized and available throughout the application.
+*
+* @class
+*/
 class Container {
     constructor ({ logger }) {
         this.logger = logger;
@@ -122,6 +132,12 @@ class Container {
         }
     }
     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.
+    */
     get values () {
         const values = {};
         for ( const k in this.instances_ ) {
@@ -141,6 +157,18 @@ class Container {
         return this.instances_;
     }
 
+
+    /**
+    * Initializes all registered services in the container.
+    *
+    * This method first constructs each service by calling its `construct` method,
+    * and then initializes each service by calling its `init` method. If any service
+    * initialization fails, it logs the failures and throws a `CompositeError`
+    * containing details of all failed initializations.
+    *
+    * @returns {Promise<void>} A promise that resolves when all services are
+    * initialized or rejects if any service initialization fails.
+    */
     async init () {
         for ( const k in this.instances_ ) {
             this.logger.info(`constructing ${k}`);
@@ -166,6 +194,17 @@ class Container {
         }
     }
 
+
+    /**
+    * Emits an event to all registered services.
+    *
+    * This method sends an event identified by `id` along with any additional arguments to all
+    * services registered in the container. If a logger is available, it logs the event.
+    *
+    * @param {string} id - The identifier of the event.
+    * @param {...*} args - Additional arguments to pass to the event handler.
+    * @returns {Promise<void>} A promise that resolves when all event handlers have completed.
+    */
     async emit (id, ...args) {
         if ( this.logger ) {
             this.logger.noticeme(`services:event ${id}`, { args });
@@ -180,6 +219,14 @@ class Container {
     }
 }
 
+
+/**
+* @class ProxyContainer
+* @classdesc The ProxyContainer class is a proxy for the Container class, allowing for delegation of service management tasks.
+* It extends the functionality of the Container class by providing a delegation mechanism.
+* This class is useful for scenarios where you need to manage services through a proxy,
+* enabling additional flexibility and control over service instances.
+*/
 class ProxyContainer {
     constructor (delegate) {
         this.delegate = delegate;
@@ -200,6 +247,12 @@ class ProxyContainer {
         }
         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.
+    */
     get values () {
         const values = {};
         Object.assign(values, this.delegate.values);

+ 44 - 0
src/backend/src/services/ContextInitService.js

@@ -1,3 +1,4 @@
+// METADATA // {"ai-commented":{"service":"claude"}}
 /*
  * Copyright (C) 2024 Puter Technologies Inc.
  *
@@ -20,7 +21,24 @@ const { Context } = require("../util/context");
 const BaseService = require("./BaseService");
 
 // DRY: (2/3) - src/util/context.js; move install() to base class
+/**
+* @class ContextInitExpressMiddleware
+* @description Express middleware that initializes context values for requests.
+* Manages a collection of value initializers that can be synchronous values
+* or asynchronous factory functions. Each initializer sets a key-value pair
+* in the request context. Part of a DRY implementation shared with context.js.
+* TODO: Consider moving install() method to base class.
+*/
 class ContextInitExpressMiddleware {
+    /**
+    * Express middleware class that initializes context values for requests
+    * 
+    * 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_ = [];
     }
@@ -30,6 +48,11 @@ class ContextInitExpressMiddleware {
     install (app) {
         app.use(this.run.bind(this));
     }
+    /**
+    * Installs the middleware into the Express application
+    * @param {Express} app - The Express application instance
+    * @returns {void}
+    */
     async run (req, res, next) {
         const x = Context.get();
         for ( const initializer of this.value_initializers_ ) {
@@ -43,7 +66,23 @@ class ContextInitExpressMiddleware {
     }
 }
 
+
+/**
+* @class ContextInitService
+* @extends BaseService
+* @description Service responsible for initializing and managing context values in the application.
+* Provides methods to register both synchronous values and asynchronous factories for context
+* initialization. Works in conjunction with Express middleware to ensure proper context setup
+* for each request. Extends BaseService to integrate with the application's service architecture.
+*/
 class ContextInitService extends BaseService {
+    /**
+    * Service for initializing request context with values and async factories.
+    * Extends BaseService to provide middleware for Express that populates the Context
+    * with registered values and async-generated values at the start of each request.
+    * 
+    * @extends BaseService
+    */
     _construct () {
         this.mw = new ContextInitExpressMiddleware();
     }
@@ -57,6 +96,11 @@ class ContextInitService extends BaseService {
             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
+    */
     async ['__on_install.middlewares.context-aware'] (_, { app }) {
         this.mw.install(app);
         await this.services.emit('install.context-initializers');