Skip to content

A high-performance, enterprise-grade C++ package manager optimized for managing native Node.js modules and C++ dependencies in large-scale applications. Features include a private registry server, pre-built binary distribution, interactive TUI search, and an extensible plugin system. LotusOS-Core

License

Notifications You must be signed in to change notification settings

Lotus-OS-Core/cpppm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

[!] this is not latest release

CppPM v2.0 - C++ Package Manager for Large-Scale Node.js Applications

A high-performance, enterprise-grade C++ package manager optimized for managing native Node.js modules and C++ dependencies in large-scale applications. Features include a private registry server, pre-built binary distribution, interactive TUI search, and an extensible plugin system.

Table of Contents

Overview

CppPM v2.0 is designed specifically for large-scale Node.js applications that rely on native C++ modules. As modern Node.js applications grow in complexity, with hundreds of dependencies and complex native module requirements, traditional package managers can become bottlenecks. CppPM addresses these challenges with a multi-component architecture that provides performance, reliability, and extensibility.

The system consists of two main components: a C++ CLI client that handles package management operations with maximum performance, and a Node.js registry server that manages package metadata and binary distributions. This hybrid architecture leverages the strengths of both languages: C++ for performance-critical operations like dependency resolution and file management, and Node.js for the registry infrastructure where its ecosystem and ease of development shine.

Large-scale Node.js applications often face specific challenges that CppPM is designed to solve. Native modules must be compiled against specific Node.js ABI versions, creating compatibility headaches across different environments. Different parts of an application may require different versions of the same native library, leading to complex dependency conflicts. CI/CD pipelines spend significant time compiling native modules repeatedly. CppPM addresses all of these challenges through its version containerization system, binary pre-distribution capabilities, and enterprise-grade architecture.

Features

CppPM v2.0 introduces a comprehensive set of features designed for enterprise Node.js applications with native module dependencies.

Private Registry Server

The built-in registry server provides complete control over package management in enterprise environments. Organizations can host their own private registry to manage proprietary libraries, enforce security policies, and ensure availability even without internet connectivity. The server supports all standard package management operations including publishing, searching, and version management. Integration with existing authentication systems allows for fine-grained access control, and the server can be easily scaled horizontally to handle enterprise-level traffic loads.

The registry server stores both package metadata and actual package artifacts, serving as the single source of truth for all package operations. It maintains a complete history of published versions, supports package deprecation workflows, and provides audit logs for compliance requirements. The server's REST API follows npm-compatible patterns, making it easy to integrate with existing development workflows and tooling.

Pre-Built Binary Distribution

Compilation of native modules is often the most time-consuming part of installing dependencies, especially in CI/CD pipelines. CppPM's pre-built binary distribution system eliminates this bottleneck by providing pre-compiled binaries for common platforms and configurations. When installing a package, the system first attempts to download a pre-built binary matching the target platform, falling back to source compilation only when no matching binary is available.

The binary distribution system considers multiple factors when selecting the appropriate binary: operating system, processor architecture, libc version, and Node.js ABI version. This ensures that binaries are compatible with the exact runtime environment, preventing subtle bugs that can arise from ABI incompatibilities. Organizations can also build and host their own binaries for internal packages, ensuring consistent, fast installations across all development and production environments.

Interactive Search TUI

Finding the right package among thousands of available options can be challenging. The interactive terminal-based user interface provides a rich search experience directly from the command line. Users can search for packages by name, description, or keyword, with results displayed in a formatted, easy-to-browse interface. The TUI supports keyboard navigation, instant installation from search results, and package detail previews.

The search interface is designed for speed and efficiency, with incremental search results that update as you type. Package information includes version numbers, dependency counts, and popularity metrics to help users make informed decisions. Integration with the registry server enables real-time search across all available packages, including both public registry packages and privately published libraries.

Extensible Plugin System

Every organization has unique requirements that may not fit into a one-size-fits-all package manager. CppPM's plugin system provides a powerful extension mechanism that allows developers to add custom functionality without modifying the core application. Plugins can intercept and react to package management events, add new commands, integrate with external systems, and modify package resolution behavior.

The plugin system uses a well-defined C++ interface that ensures type safety and clean integration. Plugins are loaded dynamically at runtime, allowing for easy deployment and updates without recompiling the main application. Sample plugins demonstrate common use cases including analytics tracking, custom notification systems, and integration with external monitoring tools.

Core Features

Beyond the major new features, CppPM retains all core capabilities that make it a powerful package manager:

  • Fast Dependency Resolution: Written in C++20 for optimal performance on large dependency graphs
  • Version Containerization: Each package version isolated in .cpp_modules/<name>/<version>/ to prevent conflicts
  • Semantic Versioning: Full semver support with range matching, caret, tilde, and custom operators
  • CMake Integration: Auto-generated CMake configuration files for seamless build system integration
  • Multiple Sources: Support for Git repositories, HTTP tarballs, and local file system packages
  • Lockfile: Reproducible installs with cpppm.lock that locks exact versions and dependencies
  • Cross-Platform: Runs on Linux, macOS, and Windows with native performance on each platform

Architecture

CppPM v2.0 employs a sophisticated multi-component architecture designed for enterprise scalability and performance.

System Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────┐
│                           CppPM Client (C++)                            │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌────────────┐   │
│  │ CLI Handler  │  │   Manifest   │  │  Dependency  │  │  Plugin    │   │
│  │              │  │   Parser     │  │  Resolver    │  │  Loader    │   │
│  └──────────────┘  └──────────────┘  └──────────────┘  └────────────┘   │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌────────────┐   │
│  │   Fetcher    │  │   Binary     │  │   TUI        │  │   Cache    │   │
│  │              │  │   Manager    │  │  Search      │  │   Manager  │   │
│  └──────────────┘  └──────────────┘  └──────────────┘  └────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ HTTPS/REST API
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                     Registry Server (Node.js)                           │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌────────────┐   │
│  │  Search      │  │  Package     │  │  Binary      │  │  Publish   │   │
│  │  Endpoint    │  │  Storage     │  │  Storage     │  │  Handler   │   │
│  └──────────────┘  └──────────────┘  └──────────────┘  └────────────┘   │
│                                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌────────────┐   │
│  │  Auth        │  │  Rate        │  │  Audit       │  │  Cache     │   │
│  │  Middleware  │  │  Limiting    │  │  Logging     │  │  Layer     │   │
│  └──────────────┘  └──────────────┘  └──────────────┘  └────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ File System / Database
                                    ▼
                         ┌─────────────────────┐
                         │   Storage Backend   │
                         │  (Packages/Meta)    │
                         └─────────────────────┘

Component Descriptions

The CLI Handler serves as the entry point for all user interactions. It parses command-line arguments, dispatches commands to appropriate handlers, and formats output for display. The CLI supports both traditional flag-based arguments and subcommand patterns familiar from tools like git and npm.

The Manifest Parser handles reading and writing of package configuration files in JSON format. It validates manifest structures, provides helpful error messages for malformed configurations, and supports the full range of manifest fields including dependencies, devDependencies, scripts, and custom metadata.

The Dependency Resolver is the core intelligence of the package manager. It implements sophisticated algorithms for resolving complex dependency graphs, handling version constraints, detecting conflicts, and producing optimal installation plans. The resolver is optimized for speed and can handle dependency trees with thousands of packages efficiently.

The Plugin Loader provides dynamic loading and lifecycle management for plugins. It handles library loading across different platforms, manages plugin lifetime, and provides event notification services that allow plugins to integrate with package management operations.

The Fetcher handles all network operations including downloading packages from registries, fetching metadata, and retrieving pre-built binaries. It implements efficient HTTP handling with connection pooling, retry logic, and progress tracking.

The Binary Manager implements the pre-built binary distribution system. It determines the appropriate binary for the current platform, manages binary caching, and handles fallback to source compilation when necessary.

The TUI Search component provides the interactive search interface. It maintains a connection to the registry server for real-time search results and provides keyboard navigation for efficient package browsing.

The Registry Server provides the infrastructure for hosting packages. It implements the REST API for all package operations, manages package storage, and provides authentication and rate limiting services.

Data Flow

Understanding how data flows through the system helps in debugging and optimization. When a user issues a command like cppm install [email protected], the CLI handler first validates the command and arguments. The manifest parser then checks for any existing configuration and validates the requested package specification. The dependency resolver analyzes the package's dependencies and determines the complete set of packages to install, checking for conflicts and optimizing the installation plan.

Once the resolution plan is complete, the fetcher retrieves each package from the registry. For each package, the binary manager determines whether a pre-built binary is available for the current platform. If a binary exists, it is downloaded and verified. If not, the source is downloaded and compiled locally. Throughout this process, any loaded plugins receive event notifications that allow them to perform custom actions.

After all packages are downloaded and processed, the file system manager installs them into the version-isolated directory structure. The CMake generator then creates or updates the build configuration files. Finally, the CLI handler reports success to the user and provides any relevant information about the installation.

Quick Start

This section provides a quick introduction to setting up and using CppPM in your project.

Prerequisites

Before installing CppPM, ensure your system meets the following requirements. The client requires a C++20-compatible compiler (GCC 10+, Clang 12+, or MSVC 2019+), CMake 3.16 or later, and standard build tools including git and make. The registry server requires Node.js 16 or later and npm 7 or later. Disk space requirements are minimal for the client (approximately 10MB) and vary based on the number and size of packages you host on the registry.

Installation

The quickest way to install CppPM is using the provided installation script. This script handles all build steps and installs the binary to your system.

# Download or clone the repository
cd cpppm

# Make the installation script executable
chmod +x install.sh

# Install to the default location (~/.local)
./install.sh install

# Verify installation
cppm --version

# If ~/.local/bin is not in PATH, add it
export PATH="$HOME/.local/bin:$PATH"

For custom installation locations, use the prefix option:

# Install to a specific directory
./install.sh install --prefix /opt/cpppm

# Install system-wide (requires root)
sudo ./install.sh install --prefix /usr/local

Creating Your First Project

With CppPM installed, you can now create and configure a new project. Initialize a project directory with the default configuration:

# Create project directory
mkdir my-nodejs-app
cd my-nodejs-app

# Initialize project
cppm init

# The following files are created:
# - cpppm.json      (project manifest)
# - .cpp_modules/   (dependency storage directory)

The cppm init command creates a basic project manifest. You can edit this file to configure your project's metadata and dependencies:

{
  "name": "my-nodejs-app",
  "version": "1.0.0",
  "description": "A large-scale Node.js application with native modules",
  "main": "src/index.js",
  "dependencies": {
    "bindings": "^1.5.0",
    "node-addon-api": "^6.0.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0"
  },
  "scripts": {
    "build": "node-gyp rebuild",
    "test": "node test/*.js"
  },
  "cpppm": {
    "registry": "http://localhost:3000",
    "binary-distribution": true
  }
}

Installing Dependencies

With your project configured, you can now install dependencies. CppPM supports both the public npm registry and private registries:

# Install all dependencies from manifest
cppm install

# Install a specific package
cppm add [email protected]

# Install from custom registry
cppm add [email protected] --registry https://my-registry.example.com

# Install with pre-built binaries (default behavior)
cppm add [email protected] --prefer-binary

# Install without pre-built binaries (compile from source)
cppm add [email protected] --no-binary

Interactive Search

Launch the interactive search interface to discover and install packages:

# Start interactive search
cppm search

# Or use the shorthand
cppm search -i

The TUI allows you to search for packages, view details, and install directly from the interface.

Using with CMake

CppPM generates CMake configuration files that integrate with your build system:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyNodeJsApp)

# Include CppPM generated configuration
include(cppmp_deps.cmake)

# Your executable or library
add_executable(myapp src/main.cpp)

# Link against CppPM installed packages
target_link_libraries(myapp PRIVATE fmt::fmt)

Registry Server

The registry server is a Node.js application that hosts package metadata and artifacts. It provides a REST API compatible with standard package manager protocols while adding enterprise features like authentication, rate limiting, and audit logging.

Quick Start

Start the registry server with default settings:

cd server
npm install
node registry.js

The server runs on port 3000 by default. You can customize the port and other settings through environment variables:

# Custom port
PORT=8080 node registry.js

# Custom storage directory
STORAGE_DIR=/path/to/storage node registry.js

# Enable authentication
AUTH_ENABLED=true node registry.js

API Reference

The registry server provides a comprehensive REST API for package management operations.

Search Packages

GET /v1/search?q=<query>&limit=<limit>

Search for packages matching the query string. Returns a list of matching packages with their metadata.

# Search for packages containing "logging"
curl "http://localhost:3000/v1/search?q=logging"

# Search with limit
curl "http://localhost:3000/v1/search?q=logging&limit=10"

Get Package Metadata

GET /v1/pkg/:name

Retrieve metadata for a specific package including available versions and dependencies.

# Get package metadata
curl "http://localhost:3000/v1/pkg/fmt"

Download Package

GET /v1/pkg/:name/:version[?platform=<platform>&node_abi=<abi>]

Download a package tarball. The optional platform and node_abi parameters enable binary distribution.

# Download source tarball
curl -O "http://localhost:3000/v1/pkg/fmt/9.1.0"

# Download platform-specific binary
curl -O "http://localhost:3000/v1/pkg/fmt/9.1.0?platform=linux-x64&node_abi=108"

Publish Package

POST /v1/publish
Content-Type: multipart/form-data

Publish a new package or version to the registry. Requires authentication.

# Publish a package
curl -X POST \
  -H "Authorization: Bearer <token>" \
  -F "[email protected]" \
  -F "name=mypackage" \
  -F "version=1.0.0" \
  -F "description=My package" \
  "http://localhost:3000/v1/publish"

Delete Package

DELETE /v1/pkg/:name/:version

Remove a specific version from the registry. Requires authentication.

# Delete package version
curl -X DELETE \
  -H "Authorization: Bearer <token>" \
  "http://localhost:3000/v1/pkg/mypackage/1.0.0"

Authentication

The registry server supports token-based authentication for publishing and administrative operations. Generate tokens using the server's authentication middleware:

// server/auth.js - Custom authentication provider
const jwt = require('jsonwebtoken');

function generateToken(user) {
  return jwt.sign({ id: user.id, role: user.role }, process.env.JWT_SECRET, {
    expiresIn: '24h'
  });
}

function verifyToken(token) {
  try {
    return jwt.verify(token, process.env.JWT_SECRET);
  } catch (e) {
    return null;
  }
}

Configure the server to use authentication:

// server/registry.js
const auth = require('./auth');

app.use('/v1/publish', (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  const user = auth.verifyToken(token);
  
  if (!user) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  req.user = user;
  next();
});

Rate Limiting

The registry includes built-in rate limiting to prevent abuse. Configure limits in the server configuration:

// server/config.js
module.exports = {
  rateLimit: {
    windowMs: 60000,       // 1 minute window
    max: 100,              // 100 requests per window
    message: 'Too many requests'
  }
};

Scaling

For high-traffic deployments, the registry server can be scaled horizontally. Use a reverse proxy like nginx or a load balancer to distribute traffic across multiple server instances. Package storage should be moved to a shared storage system like Amazon S3 or a network file system.

# nginx.conf - Load balancer configuration
upstream registry_servers {
    server registry-1:3000;
    server registry-2:3000;
    server registry-3:3000;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://registry_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Pre-Built Binary Distribution

The binary distribution system is a key feature for accelerating package installation, especially in CI/CD environments where compilation time significantly impacts deployment velocity.

How It Works

When installing a package, CppPM follows a decision process to determine whether to use a pre-built binary or compile from source:

Start
  ↓
Is binary distribution enabled?
  ├── No → Compile from source
  └── Yes → Continue
       ↓
Is there a matching binary for this platform?
  ├── No → Compile from source
  └── Yes → Continue
       ↓
Is the binary version compatible with Node.js ABI?
  ├── No → Compile from source
  └── Yes → Continue
       ↓
Download and verify binary
  ↓
Install binary package
End

The system considers multiple platform attributes when selecting binaries:

The operating system distinguishes between Windows, macOS, and various Linux distributions. The architecture identifies the processor family (x64, arm64, ia32). The libc variant matters on Linux, distinguishing between glibc and musl-based systems. The Node.js ABI version is critical for native module compatibility, as different Node.js versions have different ABIs.

Binary Naming Convention

CppPM follows a standardized naming convention for binary packages that encodes platform information in the filename:

<package-name>-<version>-<platform>-<arch>-<node-abi>.tar.gz

For example: fmt-9.1.0-linux-x64-glibc108.tar.gz

This naming convention allows the binary manager to quickly identify the appropriate binary for the current environment without querying the registry.

Creating Pre-Built Binaries

Organizations can create and host their own pre-built binaries for internal packages. This requires setting up a build pipeline that produces binaries for each supported platform:

#!/bin/bash
# scripts/build-binary.sh - Build and package binary for distribution

PACKAGE=$1
VERSION=$2
PLATFORM=$3
ARCH=$4
NODE_ABI=$5

# Set up build environment
export PLATFORM=$PLATFORM
export ARCH=$ARCH
export NODE_ABI=$NODE_ABI

# Compile the package
cd packages/$PACKAGE
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

# Create package
cd ..
tar czf ../../../dist/${PACKAGE}-${VERSION}-${PLATFORM}-${ARCH}-${NODE_ABI}.tar.gz \
    -C build lib lib${PACKAGE}.so \
    -C include *.h

The CI/CD pipeline should build binaries for all supported platform combinations and upload them to the registry.

Configuration

Binary distribution can be configured at the project level or globally:

{
  "cpppm": {
    "binary": {
      "enabled": true,
      "prefer-binary": true,
      "fallback-source": true,
      "platforms": ["linux-x64", "macos-arm64", "windows-x64"],
      "registries": ["https://binary.cpppm.example.com"]
    }
  }
}

Command-line options override project configuration:

# Prefer binary but allow source fallback
cppm install --prefer-binary

# Disable binary distribution entirely
cppm install --no-binary

# Use specific registry for binaries
cppm install --binary-registry https://my-binary-registry.example.com

Cache Management

CppPM maintains a local cache of downloaded binaries to avoid redundant network requests. The cache is stored in ~/.cache/cpppm/binaries by default.

# View cache contents
cppm cache list

# Clear specific package from cache
cppm cache clean bindings

# Clear entire cache
cppm cache clean --all

# Configure cache location
cppm config set cache-dir /path/to/cache

Interactive Search

The interactive search feature provides a terminal-based user interface for discovering and installing packages. It offers real-time search results, package previews, and quick installation actions.

Starting Interactive Mode

Launch the interactive search interface:

cppm search

The interface displays a search prompt where you can enter package names, keywords, or descriptions. Results update as you type, showing matching packages with their version, description, and dependency information.

Navigation

The TUI supports keyboard navigation for efficient browsing:

  • Arrow keys: Move selection up and down
  • Enter: Select package for detailed view or installation
  • Tab: Switch between search and results panels
  • Ctrl+F: Focus search input
  • Ctrl+I: Install selected package
  • Ctrl+Q: Quit
  • Ctrl+R: Refresh results

Package Details

Press Enter on a package to view detailed information including:

  • Package description and keywords
  • Available versions with release dates
  • Dependency list with version requirements
  • Download statistics and popularity metrics
  • Repository URL and documentation links

Quick Install

From the search results or package details view, press Ctrl+I to install the selected package. The installation proceeds immediately, with progress displayed in the status bar. Any installed plugins receive notification of the installation event.

Search Syntax

The search supports various syntaxes for refined queries:

# Simple text search (searches name and description)
cppm search logging

# Filter by specific field
cppm search name:fmt
cppm search description:"formatting library"

# Version constraints
cppm search fmt@^8.0.0

# Combine filters
cppm search name:fmt version:^8.0.0

# Regular expression (advanced)
cppm search /^log.*/

Search Options

Configure search behavior through command-line options:

# Limit results
cppm search logging --limit 20

# Show only packages with binaries
cppm search logging --binary-only

# Search specific registry
cppm search logging --registry https://my-registry.example.com

# Include dev dependencies in results
cppm search --include-dev

Plugin System

The plugin system allows extending CppPM's functionality through dynamically loaded modules. Plugins can intercept events, add new commands, integrate with external systems, and customize behavior.

Plugin Architecture

Plugins are implemented as shared libraries that conform to the IPlugin interface:

#pragma once
#include <string>

class IPlugin {
public:
    virtual ~IPlugin() = default;
    
    // Plugin metadata
    virtual std::string getName() const = 0;
    virtual std::string getVersion() const = 0;
    virtual std::string getDescription() const = 0;
    
    // Lifecycle hooks
    virtual void onLoad() = 0;
    virtual void onUnload() = 0;
    
    // Event handlers
    virtual void onPreInstall(const std::string& packageName, const std::string& version) = 0;
    virtual void onPostInstall(const std::string& packageName, const std::string& version, bool success) = 0;
    virtual void onPreRemove(const std::string& packageName) = 0;
    virtual void onPostRemove(const std::string& packageName, bool success) = 0;
    
    // Custom command support
    virtual bool executeCommand(const std::string& command, const std::vector<std::string>& args) = 0;
};

Example Plugin

Here is a complete example plugin that provides analytics tracking and custom notifications:

// plugins/analytics/analytics_plugin.cpp
#include "../../src/plugin/i_plugin.h"
#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>

class AnalyticsPlugin : public IPlugin {
private:
    std::string logFile;
    
public:
    AnalyticsPlugin() : logFile("cppm_analytics.log") {}
    
    std::string getName() const override { return "AnalyticsPlugin"; }
    std::string getVersion() const override { return "1.0.0"; }
    std::string getDescription() const override { return "Tracks package management events"; }
    
    void onLoad() override {
        std::cout << "[AnalyticsPlugin] Loaded" << std::endl;
        log("PLUGIN_LOADED");
    }
    
    void onUnload() override {
        log("PLUGIN_UNLOADED");
        std::cout << "[AnalyticsPlugin] Unloaded" << std::endl;
    }
    
    void onPreInstall(const std::string& packageName, const std::string& version) override {
        log("PRE_INSTALL", packageName, version);
        std::cout << "[AnalyticsPlugin] Preparing to install " << packageName << "@" << version << std::endl;
    }
    
    void onPostInstall(const std::string& packageName, const std::string& version, bool success) override {
        log("POST_INSTALL", packageName, version, success ? "SUCCESS" : "FAILED");
        std::cout << "[AnalyticsPlugin] Installation " 
                  << (success ? "completed" : "failed") << " for " 
                  << packageName << "@" << version << std::endl;
    }
    
    void onPreRemove(const std::string& packageName) override {
        log("PRE_REMOVE", packageName);
        std::cout << "[AnalyticsPlugin] Preparing to remove " << packageName << std::endl;
    }
    
    void onPostRemove(const std::string& packageName, bool success) override {
        log("POST_REMOVE", packageName, success ? "SUCCESS" : "FAILED");
    }
    
    bool executeCommand(const std::string& command, const std::vector<std::string>& args) override {
        if (command == "analytics-stats") {
            showStats();
            return true;
        }
        return false;
    }

private:
    void log(const std::string& event, const std::string& pkg = "", 
             const std::string& ver = "", const std::string& status = "") {
        auto now = std::chrono::system_clock::now();
        auto time = std::chrono::system_clock::to_time_t(now);
        
        std::ofstream file(logFile, std::ios::app);
        file << time << "|" << event << "|" << pkg << "|" << ver << "|" << status << std::endl;
    }
    
    void showStats() {
        std::cout << "\n=== Analytics Statistics ===" << std::endl;
        std::cout << "See cppm_analytics.log for details" << std::endl;
    }
};

// Export factory functions
extern "C" {
    #ifdef _WIN32
    __declspec(dllexport) IPlugin* createPlugin() { return new AnalyticsPlugin(); }
    __declspec(dllexport) void destroyPlugin(IPlugin* plugin) { delete plugin; }
    #else
    IPlugin* createPlugin() { return new AnalyticsPlugin(); }
    void destroyPlugin(IPlugin* plugin) { delete plugin; }
    #endif
}

Installing Plugins

Place compiled plugins in the designated plugins directory:

# Linux/macOS
~/.config/cpppm/plugins/libAnalyticsPlugin.so

# Windows
%APPDATA%\cpppm\plugins\AnalyticsPlugin.dll

Alternatively, specify a custom plugins directory:

cppm --plugins /path/to/plugins install

Plugin Configuration

Plugins can be configured through the project manifest or configuration files:

{
  "cpppm": {
    "plugins": {
      "AnalyticsPlugin": {
        "enabled": true,
        "log-file": "/var/log/cppm-analytics.log"
      },
      "CustomNotifier": {
        "enabled": true,
        "webhook-url": "https://hooks.example.com/notify"
      }
    }
  }
}

Developing Plugins

The CppPM SDK provides headers and libraries for plugin development:

# Install SDK headers
cppm install @cpppm/plugin-sdk

# Include in your plugin
#include <cpppm/plugin/i_plugin.hpp>
#include <cpppm/plugin/plugin_loader.hpp>

Plugin Security

Plugins execute with the same permissions as CppPM itself, requiring careful security consideration. Only load plugins from trusted sources, review plugin code before installation, and consider signing plugins for verification:

# Verify plugin signature
cppm plugin verify plugins/MyPlugin.so --keyring trusted-publishers

Node.js Integration

CppPM is designed to integrate seamlessly with Node.js applications that use native modules. This section covers integration patterns and best practices.

Native Module Compilation

For packages without pre-built binaries, CppPM integrates with node-gyp for native module compilation:

// src/native_builder.cpp - Integration with node-gyp
#include <iostream>
#include <cstdlib>
#include <string>

class NativeBuilder {
public:
    bool compile(const std::string& packagePath, const std::string& nodeVersion) {
        std::string buildCommand = "cd " + packagePath + " && node-gyp rebuild";
        
        // Set Node.js ABI version
        setenv("NODE_MODULE_VERSION", nodeVersion.c_str(), 1);
        
        int result = std::system(buildCommand.c_str());
        return result == 0;
    }
    
    std::string getNodeAbiVersion() {
        // Query Node.js for its ABI version
        const char* abi = std::getenv("NODE_MODULE_VERSION");
        return abi ? std::string(abi) : "unknown";
    }
};

N-API Compatibility

CppPM supports N-API for maintaining ABI stability across Node.js versions:

// src/napi_compat.cpp - N-API version detection
#include <string>
#include <map>

class NapiVersion {
private:
    static const std::map<int, std::string> napiVersions;
    
public:
    static std::string getNapiVersion(int abiVersion) {
        auto it = napiVersions.find(abiVersion);
        return it != napiVersions.end() ? it->second : "unknown";
    }
    
    static int getAbiFromNapi(const std::string& napiVersion) {
        for (const auto& [abi, napi] : napiVersions) {
            if (napi == napiVersion) return abi;
        }
        return -1;
    }
};

const std::map<int, std::string> NapiVersion::napiVersions = {
    {72, "v9"},
    {75, "v10"},
    {83, "v11"},
    {88, "v12"},
    {93, "v13"},
    {102, "v14"},
    {106, "v15"},
    {108, "v16"},
    {115, "v17"},
    {127, "v18"},
    {131, "v19"},
    {135, "v20"},
    {140, "v21"},
    {144, "v22"}
};

Integration with Node.js Build Tools

CppPM can be used alongside standard Node.js build tools:

// package.json
{
  "scripts": {
    "install": "cppm install && node-gyp rebuild",
    "rebuild": "node-gyp rebuild && cppm install",
    "clean": "rm -rf .cpp_modules && rm -rf build"
  },
  "dependencies": {
    "my-native-module": "^1.0.0"
  },
  "cpppm": {
    "registry": "https://registry.cpppm.example.com"
  }
}

Large-Scale Application Patterns

For large-scale Node.js applications, consider these integration patterns:

Monorepo Support: Manage multiple related packages in a single repository:

{
  "workspaces": ["packages/*"],
  "cpppm": {
    "shared-dependencies": ["fmt", "spdlog"],
    "workspace-protocol": "dependencies"
  }
}

CI/CD Integration: Optimize CI/CD pipelines with binary caching:

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup CppPM
        uses: cpppm/action-setup@v2
        
      - name: Cache binaries
        uses: actions/cache@v3
        with:
          path: ~/.cache/cpppm/binaries
          key: ${{ runner.os }}-binaries-${{ hashFiles('**/cpppm.json') }}
      
      - name: Install dependencies
        run: cppm install --prefer-binary
      
      - name: Build
        run: npm run build
      
      - name: Test
        run: npm test

Command Reference

This section provides a complete reference for all CppPM commands and options.

Core Commands

init: Initialize a new project with a default manifest file.

cppm init [options]

Options:
  --name <name>         Project name (default: directory name)
  --version <version>   Initial version (default: 1.0.0)
  --yes                 Accept defaults for all prompts

install: Install all dependencies from the project manifest.

cppm install [packages...] [options]

Options:
  --prefer-binary       Prefer pre-built binaries over source
  --no-binary           Disable binary distribution
  --registry <url>      Use specific registry
  --production          Skip devDependencies
  --verbose             Show detailed output

add: Add a package to the project dependencies.

cppm add <package>[@<version>] [options]

Options:
  --save                Save to dependencies (default)
  --save-dev            Save to devDependencies
  --registry <url>      Use specific registry
  --prefer-binary       Prefer binary distribution

remove: Remove a package from dependencies.

cppm remove <package> [options]

Options:
  --save                Remove from dependencies (default)
  --save-dev            Remove from devDependencies

list: List installed packages.

cppm list [options]

Options:
  --long                Show extended information
  --json                Output as JSON
  --depth <n>           Maximum dependency depth
  --prod                Show production dependencies only

search: Search for packages in the registry.

cppm search <query> [options]

Options:
  --interactive, -i     Open interactive TUI
  --limit <n>           Maximum results (default: 20)
  --registry <url>      Use specific registry
  --json                Output as JSON

info: Display detailed package information.

cppm info <package>[@<version>] [options]

Options:
  --json                Output as JSON
  --versions            List all available versions

Registry Commands

registry login: Authenticate with a registry.

cppm registry login <registry-url> [options]

Options:
  --token <token>       Use specific auth token
  --browser             Open browser for authentication

registry publish: Publish a package to the registry.

cppm registry publish [options]

Options:
  --access <public|restricted>  Package access level

registry token: Manage registry authentication tokens.

cppm registry token create    # Create new token
cppm registry token list      # List tokens
cppm registry token revoke    # Revoke token

Cache Commands

cache: Manage the local package cache.

cppm cache clean [packages...]  # Clear cache
cppm cache list                 # List cached packages
cppm cache verify               # Verify cache integrity

Plugin Commands

plugin list: List installed plugins.

cppm plugin list

plugin enable: Enable a plugin.

cppm plugin enable <name>

plugin disable: Disable a plugin.

cppm plugin disable <name>

plugin install: Install a plugin.

cppm plugin install <plugin> [options]

Options:
  --registry <url>     Plugin registry
  --version <version>  Specific version

Global Options

These options are available for all commands:

--help, -h           Show help
--version, -V        Show version
--verbose, -d        Enable debug output
--json               Output as JSON
--no-color           Disable colored output
--config <file>      Use specific config file
--cwd <directory>    Working directory
--plugins <dir>      Plugin directory

Building from Source

This section provides detailed instructions for building CppPM from source.

Platform-Specific Instructions

Linux (Ubuntu/Debian):

# Install dependencies
sudo apt-get update
sudo apt-get install -y build-essential cmake git curl libcurl4-openssl-dev

# Clone and build
cd cpppm
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install

macOS:

# Install dependencies via Homebrew
brew install cmake git curl

# Clone and build
cd cpppm
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(sysctl -n hw.ncpu)
sudo make install

Windows:

# Install dependencies
choco install -y cmake git visualstudio2022-workload-vctools

# Clone and build
cd cpppm
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release
cmake --install .

Build Options

The following CMake options customize the build:

cmake .. [options]

Options:
  -DCMAKE_BUILD_TYPE=Release      Build type (Release, Debug, RelWithDebInfo)
  -DCMAKE_INSTALL_PREFIX=path     Installation prefix
  -DCMAKE_CXX_COMPILER=compiler   C++ compiler
  -DBUILD_TESTS=ON                Build tests
  -DBUILD_PLUGINS=ON              Build example plugins
  -DBUILD_SERVER=ON               Build registry server

Running Tests

After building with tests enabled:

# Run all tests
cd build
ctest

# Run specific test suite
ctest -R unit
ctest -R integration

Configuration

CppPM can be configured through multiple configuration layers with precedence from most to least specific: command-line options, project configuration, user configuration, and system configuration.

Project Configuration

Configure project-specific settings in cpppm.json:

{
  "name": "my-project",
  "version": "1.0.0",
  "cpppm": {
    "registry": "https://registry.cpppm.example.com",
    "binary": {
      "enabled": true,
      "prefer-binary": true
    },
    "cache": {
      "enabled": true,
      "ttl": "7d"
    },
    "plugins": {
      "enabled": ["AnalyticsPlugin"]
    }
  }
}

User Configuration

User-level configuration is stored in ~/.config/cpppm/config.json on Linux/macOS or %APPDATA%\cpppm\config.json on Windows:

{
  "registry": "https://registry.cpppm.example.com",
  "binary": {
    "enabled": true,
    "prefer-binary": true
  },
  "cache": {
    "directory": "~/.cache/cpppm",
    "max-size": "2GB"
  },
  "proxy": {
    "http": "http://proxy.example.com:8080",
    "https": "http://proxy.example.com:8080"
  }
}

Environment Variables

Override configuration with environment variables:

# Registry
export CPPPM_REGISTRY="https://registry.cpppm.example.com"

# Binary distribution
export CPPPM_BINARY=1
export CPPPM_BINARY_REGISTRY="https://binary.cpppm.example.com"

# Cache
export CPPPM_CACHE_DIR="/path/to/cache"

# Proxy
export HTTP_PROXY="http://proxy.example.com:8080"
export HTTPS_PROXY="http://proxy.example.com:8080"

Configuration Commands

Use the CLI to manage configuration:

# View current configuration
cppm config list

# Set configuration value
cppm config set registry https://my-registry.example.com

# Get configuration value
cppm config get registry

# Delete configuration value
cppm config delete registry

Advanced Usage

This section covers advanced usage patterns and optimization strategies.

Performance Optimization

For large-scale applications, consider these optimization strategies:

Parallel Installation: Enable parallel package downloads and processing:

cppm install --jobs 8

Binary-Only Mode: For CI/CD, always prefer binaries:

cppm install --prefer-binary --no-source

Cache Warming: Pre-populate cache for faster CI runs:

cppm cache warm --from-package-lock package-lock.json

Security Best Practices

Secure your package management pipeline with these practices:

Package Signing: Enable signature verification:

cppm config set signature-verification true

Audit Integration: Integrate with security audit tools:

cppm audit --severity high --output json > audit-report.json

Multi-Registry Setup

Configure multiple registries for different packages:

{
  "registries": {
    "default": "https://registry.cpppm.example.com",
    "private": "https://private-registry.example.com",
    "public": "https://registry.npmjs.org"
  },
  "packageRegistries": {
    "@company/*": "private",
    "lodash": "public",
    "*": "default"
  }
}

Mirroring

Set up package mirrors for offline or high-availability scenarios:

# Create mirror
cppm mirror create https://mirror.example.com --from https://registry.cpppm.example.com

# Use mirror
cppm config set registry https://mirror.example.com

Migration from npm

Migrate existing npm projects to CppPM:

# Import package.json dependencies
cppm import package.json

# Convert package-lock.json to lockfile
cppm import package-lock.json --format lock

# Verify dependency tree matches
cppm install --dry-run

Contributing

Contributions are welcome. Please read the contributing guide before submitting pull requests.

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make changes and add tests
  4. Run tests: cmake --build build && cd build && ctest
  5. Submit a pull request

License

CppPM is licensed under the MIT License. See the LICENSE file for details.

Support

For issues and feature requests, please use the GitHub issue tracker.


LINUX Distro: LotusOS-Core

About

A high-performance, enterprise-grade C++ package manager optimized for managing native Node.js modules and C++ dependencies in large-scale applications. Features include a private registry server, pre-built binary distribution, interactive TUI search, and an extensible plugin system. LotusOS-Core

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published