@ckirg/corelib - v0.4.1
    Preparing search index...

    @ckirg/corelib - v0.4.1

    @ckirg/corelib

    The foundational package of the Corelib monorepo, providing essential utilities, resilient HTTP, structured logging, and database abstractions.

    Important

    Not on the public npm registry — install from GitHub Releases. See the root install guide.

    • Multi-Runtime Support: Compatible with Node.js, Bun, and Deno.
    • Resilient HTTP: RequestUnlimited (based on ky) with automatic retries and consistent error serialization.
    • Structured Logging: Strict Logger API with telemetry and structured data support.
    • Database Abstraction: Unified interface for SQLite (via LibSQL) and PostgreSQL.
    • Configuration Management: ConfigManager with support for CLI, Environment Variables, and Local/Remote encrypted files.
    • Native Core (FFI): High-performance logic implemented in Rust and exposed via N-API.
    • Runtime Utilities: Platform-agnostic helpers for environment, file system, and telemetry.

    Install from the GitHub Release — see the root install guide for package manager overrides.

    # pnpm
    pnpm add https://github.com/ckir/corelib/releases/download/v0.1.17/ckirg-corelib-0.1.17.tgz

    Use endPoint for single requests or endPoints for parallel requests.

    import { endPoint } from '@ckirg/corelib';

    const result = await endPoint('https://api.github.com/repos/ckir/corelib');

    if (result.status === 'success') {
    // result.value is a SerializedResponse object
    console.log('Body:', result.value.body);
    }

    RequestProxied provides an identical API to RequestUnlimited but adds automatic rotation, full fallback, and automatic removal of dead proxies. The pool is self-healing — unhealthy endpoints are pruned on first failure and do not re-enter rotation.

    import { RequestProxied } from '@ckirg/corelib';

    const proxies = [
    "https://proxy-us.example.com",
    "https://proxy-eu.example.com",
    "https://proxy-as.example.com"
    ];

    const client = new RequestProxied(proxies);

    // Single request with automatic rotation and fallback
    const result = await client.endPoint("https://api.nasdaq.com/api/market-info");

    // Parallel requests with round-robin load balancing
    const results = await client.endPoints([
    "https://api.nasdaq.com/api/quote/AAPL/info",
    "https://api.nasdaq.com/api/quote/TSLA/info"
    ]);

    The logger follows a strict (msg: string, extras?: object) signature and handles runtime differences automatically.

    import { logger } from '@ckirg/corelib';

    // Basic logging
    logger.info("Application started");

    // Logging with structured metadata
    logger.error("Database connection failed", {
    host: "localhost",
    port: 5432,
    error: "Connection timeout"
    });

    // Telemetry support (if configured)
    logger.setTelemetry('on');
    logger.info("Critical event", { telemetry: true });

    Switch between SQLite and PostgreSQL with minimal configuration changes.

    import { createDatabase } from '@ckirg/corelib';

    // SQLite
    const db = await createDatabase({
    dialect: 'sqlite',
    url: 'file:./app.db'
    });

    // PostgreSQL
    // const db = await createDatabase({
    // dialect: 'postgres',
    // url: 'postgres://user:pass@localhost:5432/dbname'
    // });

    // Querying (Returns a DatabaseResult discriminated union)
    const result = await db.query('SELECT * FROM users WHERE active = ?', [true]);

    if (result.status === 'success') {
    // result.value is a QueryResponse object containing .rows
    const users = result.value.rows;
    console.log(`Found ${users.length} users`);
    } else {
    console.error('Query failed:', result.reason.message);
    }

    // Transactions
    await db.transaction(async () => {
    await db.query('INSERT INTO logs (msg) VALUES (?)', ['Transaction step 1']);
    await db.query('UPDATE status SET value = ?', ['processed']);
    // Return success from the callback to commit the transaction
    return { status: 'success', value: true };
    });

    Manage complex configuration hierarchies with ease.

    Both the static and instance forms of get() are supported by design — use whichever fits your call site. They read from the same singleton store.

    import { ConfigManager } from '@ckirg/corelib';

    // ── Instance form (explicit singleton) ────────────────────────────────────
    const config = ConfigManager.getInstance();

    // Initialize (parses CLI, Env, and local defaults). Idempotent under
    // concurrency: simultaneous calls share one in-flight run.
    await config.initialize();

    // Instance get — nested value with dot-notation
    const dbPort = config.get('database.port');

    // ── Static form (convenience shorthand — same singleton, same data) ────────
    // Both of these are equivalent after the first initialize() settles:
    const port = ConfigManager.get('database.port');

    // Load external encrypted configuration
    await config.loadExternalConfig('https://remote-server.com/prod.json.enc');

    // Reactive updates
    config.on('change:database.port', (newPort) => {
    console.log(`Port changed to ${newPort}`);
    });

    get() is synchronous and never throws — bundled defaults are seeded in the constructor, so reads are safe even before initialize() resolves (a one-time dev warning fires if you read pre-init, suppressed in production). Long-lived orchestrators (DB connections, stream wrappers) that need resolved config should gate on readiness:

    if (!config.isInitialized) {
    await config.whenReady(); // resolves when the first initialize() settles
    }

    Anti-pattern — don't cache a sub-section at module scope. Read at the hot point instead. this._config's object identity is stable (mutation is in place), but caching a nested slice can still mask a later override:

    // ❌ captured once at import; may miss overrides applied during initialize()
    const db = ConfigManager.getInstance().get('database');

    // ✅ read at the use site (static or instance — both work)
    const port = ConfigManager.get('database.port');

    Access high-performance Rust logic directly from TypeScript. The implementation is resilient and will disable FFI features if the native binary is missing rather than crashing the module.

    import { Core } from '@ckirg/corelib';

    // Check if FFI is available in current runtime
    if (Core.isFfiAvailable()) {
    console.log('Rust Version:', Core.getVersion());
    const doubled = Core.logAndDouble("Double me", 21);
    console.log('Result:', doubled); // 42
    }

    // Safe run method that includes runtime info
    Core.run("maintenance-task", { verbose: true });

    Platform-agnostic helpers for common tasks.

    Key Helpers:

    • detectRuntime() — returns current runtime ("node" | "bun" | "deno" | ...)
    • sleep(ms) — cross-runtime delay
    • getEnv(key), getAllEnv() — safe environment access
    • getSysInfo() — detailed system info with automatic secret redaction
    • includeExcludeCron — helpers for complex cron include/exclude patterns
    • File system helpers with graceful fallbacks across runtimes
    import { detectRuntime, sleep, getEnv, getSysInfo } from '@ckirg/corelib';

    // Detect where we are (node, bun, deno, cloudflare, aws-lambda, etc.)
    const runtime = detectRuntime();

    // Resilient sleep
    await sleep(1000);

    // Platform-agnostic env access
    const apiKey = getEnv('API_KEY');

    // Detailed system and process telemetry (auto-redacts secrets)
    const sysInfo = getSysInfo();
    console.log('Memory Usage:', sysInfo.memory.rss);