npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ticatec/script-loader

v1.0.0

Published

A powerful TypeScript dynamic script loading and management library with real-time script updates, caching management, and timestamp persistence.

Downloads

79

Readme

@ticatec/script-loader

Node.js Version TypeScript License: MIT

A high-reliability TypeScript library for dynamic script loading, hot-reloading, and lifecycle management in Node.js. Supports database sync, zero-downtime atomic hot reloading, timestamp cursor persistence, manual/webhook/MQ refresh triggers, and safe module path resolution.

Features

  • Dual Module Support - Full ES Module (ESM) & CommonJS (CJS) compatibility
  • 🚀 Zero-Downtime Hot Reload - Atomic write & evaluation via temporary files, preserving existing working modules on syntax errors
  • Reliable Timestamp Cursor - Halts cursor progression safely on batch failures so no failed script is ever skipped
  • 🔄 Polling & Event-Driven Hybrid - Periodic automatic polling plus refresh() manual trigger (e.g. for Webhooks, Redis Pub/Sub, MQ)
  • 🛡️ Boundary Protection - Path traversal validation restricting output strictly inside plugins/
  • 🌲 Structured Logging - Native integration with @ticatec/logger-wrapper (Pino)
  • 🧩 Singleton & Lifecycle Hooks - DynaModuleManager singleton plus onScriptLoaded and afterRemoveModule callbacks

Installation

pnpm add @ticatec/script-loader @ticatec/logger-wrapper pino
# or npm
npm install @ticatec/script-loader @ticatec/logger-wrapper pino

🚀 Real-World Usage Examples

1. Basic Setup: Subclass BaseScriptLoader

Subclass BaseScriptLoader and implement getUpdatedScripts(anchor):

import { BaseScriptLoader, DynaScript } from '@ticatec/script-loader';

export class DbScriptLoader extends BaseScriptLoader {
    constructor(scriptHome: string, pollIntervalMs: number = 5000) {
        super(scriptHome, pollIntervalMs);
    }

    /**
     * Query active scripts updated after the anchor timestamp
     */
    protected async getUpdatedScripts(anchor: Date): Promise<DynaScript[]> {
        const rows = await db.query(
            'SELECT key_code, file_name, is_active, updated_at, script_code FROM sys_dynamic_scripts WHERE updated_at > $1',
            [anchor]
        );

        return rows.map(r => ({
            keyCode: r.key_code,
            fileName: r.file_name,
            active: r.is_active,
            latestUpdated: new Date(r.updated_at),
            scriptCode: r.script_code
        }));
    }

    /**
     * Optional hook: Triggered when a script is successfully loaded/updated
     */
    protected onScriptLoaded(script: DynaScript, moduleExports: any): void {
        console.log(`[Plugin Loaded] ${script.keyCode} updated successfully.`);
    }

    /**
     * Optional hook: Triggered when a script is deactivated/removed
     */
    protected afterRemoveModule(keyCode: string, modFile: string): void {
        console.log(`[Plugin Removed] ${keyCode} removed from cache.`);
    }
}

2. Initialize DynaModuleManager Singleton

Initialize the singleton at your application entry point:

import DynaModuleManager from '@ticatec/script-loader';
import { DbScriptLoader } from './DbScriptLoader.js';

// Concurrent-safe singleton initialization
const manager = await DynaModuleManager.initialize(
    DbScriptLoader,
    './runtime_scripts', // Local plugin cache directory
    5000                 // Polling interval in ms
);

// Fetch loaded module instance
const calcRule = manager.get('order_discount_rule');
if (calcRule) {
    const finalPrice = calcRule.calculateDiscount({ price: 100, userLevel: 'VIP' });
    console.log('Discounted Price:', finalPrice);
}

3. Programmatic / Event-Driven Immediate Reload (Webhook / MQ)

Trigger an immediate reload programmatically via manager.refresh() without waiting for the next timer poll:

import express from 'express';
import DynaModuleManager from '@ticatec/script-loader';

const app = express();

// Webhook / MQ Endpoint for immediate script reload
app.post('/api/v1/reload-scripts', async (req, res) => {
    try {
        const manager = DynaModuleManager.getInstance();
        
        // Immediately pull and reload updated scripts from DB
        const updatedScripts = await manager.refresh();
        
        res.json({
            success: true,
            updatedCount: updatedScripts.length,
            scripts: updatedScripts.map(s => s.keyCode)
        });
    } catch (error) {
        res.status(500).json({ success: false, error: (error as Error).message });
    }
});

4. Integration with Express / Rule Engine Middleware

Dynamically resolve and execute rules inside Web requests:

import { Request, Response, NextFunction } from 'express';
import DynaModuleManager from '@ticatec/script-loader';

export function dynamicRuleMiddleware(ruleKey: string) {
    return (req: Request, res: Response, next: NextFunction) => {
        const manager = DynaModuleManager.getInstance();
        const ruleModule = manager.get(ruleKey);

        if (!ruleModule) {
            return res.status(503).json({ error: `Dynamic rule '${ruleKey}' is not active` });
        }

        try {
            req['ruleResult'] = ruleModule.execute(req.body, req['user']);
            next();
        } catch (err) {
            next(err);
        }
    };
}

📖 API Reference

DynaScript Interface

interface DynaScript {
    keyCode: string;        // Unique key identifier (e.g. 'discount_rule')
    fileName: string;       // Target file name (e.g. 'discount_rule_v1')
    active: boolean;        // Active flag (false removes local file and cache)
    latestUpdated: Date;    // Last updated timestamp
    scriptCode: string;     // JavaScript / CommonJS source code
}

DynaModuleManager

| Method | Return Type | Description | | :--- | :--- | :--- | | initialize(loaderConstructor, ...args) | Promise<DynaModuleManager> | Concurrent-safe singleton initializer | | getInstance() | DynaModuleManager | Returns initialized singleton (throws if uninitialized) | | get<T>(key: string): T \| null | T \| null | Returns exports of loaded module | | refresh(forceAll?: boolean) | Promise<DynaScript[]> | Programmatically triggers immediate script reload | | shutdown() | void | Stops polling and clears singleton instance | | resetInstance() | void | Resets singleton (unit test helper) |

BaseScriptLoader

| Method / Hook | Visibility | Description | | :--- | :--- | :--- | | getUpdatedScripts(anchor: Date) | abstract protected | Must implement: fetches scripts updated after anchor | | onScriptLoaded(script, exports) | protected | Hook: called after script is loaded/updated | | afterRemoveModule(keyCode, modFile)| protected | Hook: called after script is removed | | refresh(forceAll?: boolean) | public | Triggers immediate script reload | | stopWatching() | public | Stops polling watcher |


License

MIT License - see LICENSE.