[!] this is not latest release
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.
- Overview
- Features
- Architecture
- Quick Start
- Registry Server
- Pre-Built Binary Distribution
- Interactive Search
- Plugin System
- Node.js Integration
- Command Reference
- Building from Source
- Configuration
- Advanced Usage
- Contributing
- License
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.
CppPM v2.0 introduces a comprehensive set of features designed for enterprise Node.js applications with native module dependencies.
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.
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.
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.
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.
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.lockthat locks exact versions and dependencies - Cross-Platform: Runs on Linux, macOS, and Windows with native performance on each platform
CppPM v2.0 employs a sophisticated multi-component architecture designed for enterprise scalability and performance.
┌─────────────────────────────────────────────────────────────────────────┐
│ 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) │
└─────────────────────┘
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.
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.
This section provides a quick introduction to setting up and using CppPM in your project.
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.
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/localWith 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
}
}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-binaryLaunch the interactive search interface to discover and install packages:
# Start interactive search
cppm search
# Or use the shorthand
cppm search -iThe TUI allows you to search for packages, view details, and install directly from the interface.
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)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.
Start the registry server with default settings:
cd server
npm install
node registry.jsThe 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.jsThe 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"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();
});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'
}
};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;
}
}The binary distribution system is a key feature for accelerating package installation, especially in CI/CD environments where compilation time significantly impacts deployment velocity.
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.
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.
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 *.hThe CI/CD pipeline should build binaries for all supported platform combinations and upload them to the registry.
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.comCppPM 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/cacheThe 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.
Launch the interactive search interface:
cppm searchThe 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.
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
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
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.
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.*/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-devThe 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.
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;
};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
}Place compiled plugins in the designated plugins directory:
# Linux/macOS
~/.config/cpppm/plugins/libAnalyticsPlugin.so
# Windows
%APPDATA%\cpppm\plugins\AnalyticsPlugin.dllAlternatively, specify a custom plugins directory:
cppm --plugins /path/to/plugins installPlugins 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"
}
}
}
}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>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-publishersCppPM is designed to integrate seamlessly with Node.js applications that use native modules. This section covers integration patterns and best practices.
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";
}
};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"}
};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"
}
}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 testThis section provides a complete reference for all CppPM commands and options.
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 promptsinstall: 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 outputadd: 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 distributionremove: Remove a package from dependencies.
cppm remove <package> [options]
Options:
--save Remove from dependencies (default)
--save-dev Remove from devDependencieslist: List installed packages.
cppm list [options]
Options:
--long Show extended information
--json Output as JSON
--depth <n> Maximum dependency depth
--prod Show production dependencies onlysearch: 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 JSONinfo: Display detailed package information.
cppm info <package>[@<version>] [options]
Options:
--json Output as JSON
--versions List all available versionsregistry login: Authenticate with a registry.
cppm registry login <registry-url> [options]
Options:
--token <token> Use specific auth token
--browser Open browser for authenticationregistry publish: Publish a package to the registry.
cppm registry publish [options]
Options:
--access <public|restricted> Package access levelregistry token: Manage registry authentication tokens.
cppm registry token create # Create new token
cppm registry token list # List tokens
cppm registry token revoke # Revoke tokencache: Manage the local package cache.
cppm cache clean [packages...] # Clear cache
cppm cache list # List cached packages
cppm cache verify # Verify cache integrityplugin list: List installed plugins.
cppm plugin listplugin 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 versionThese 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 directoryThis section provides detailed instructions for building CppPM from source.
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 installmacOS:
# 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 installWindows:
# 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 .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 serverAfter building with tests enabled:
# Run all tests
cd build
ctest
# Run specific test suite
ctest -R unit
ctest -R integrationCppPM can be configured through multiple configuration layers with precedence from most to least specific: command-line options, project configuration, user configuration, and system 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-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"
}
}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"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 registryThis section covers advanced usage patterns and optimization strategies.
For large-scale applications, consider these optimization strategies:
Parallel Installation: Enable parallel package downloads and processing:
cppm install --jobs 8Binary-Only Mode: For CI/CD, always prefer binaries:
cppm install --prefer-binary --no-sourceCache Warming: Pre-populate cache for faster CI runs:
cppm cache warm --from-package-lock package-lock.jsonSecure your package management pipeline with these practices:
Package Signing: Enable signature verification:
cppm config set signature-verification trueAudit Integration: Integrate with security audit tools:
cppm audit --severity high --output json > audit-report.jsonConfigure 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"
}
}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.comMigrate 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-runContributions are welcome. Please read the contributing guide before submitting pull requests.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make changes and add tests
- Run tests:
cmake --build build && cd build && ctest - Submit a pull request
CppPM is licensed under the MIT License. See the LICENSE file for details.
For issues and feature requests, please use the GitHub issue tracker.
LINUX Distro: LotusOS-Core