mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 06:00:21 +08:00
doc: ai generated comments
This commit is contained in:
parent
2dfeeeda27
commit
ea5a8ef906
@ -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;
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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` ' +
|
||||
|
@ -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} : {};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user