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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@weconjs/core

v0.2.0

Published

Wecon Framework Core - defineConfig, defineModule, and runtime utilities

Readme

@weconjs/core

Core framework package for Wecon - A convention-over-configuration Node.js framework.

npm version License: MIT

Table of Contents

Installation

npm install @weconjs/core
# or
yarn add @weconjs/core

Optional Dependencies

# Winston logging with daily file rotation
npm install winston winston-daily-rotate-file

# Field-level access control for Mongoose
npm install @weconjs/mongoose-field-shield

Features

| Feature | Description | |---------|-------------| | Configuration System | Mode-based configuration with inheritance (development, staging, production) | | Module System | Auto-discovery, dependency resolution, and lifecycle hooks | | i18n Support | Automatic translation file loading from module directories | | Socket.IO Integration | Auto-discover and register socket handlers and middleware | | Database Connection | MongoDB/Mongoose with URI builders, plugins, retry logic | | Server Factory | Complete Express bootstrap with HTTPS, graceful shutdown | | Winston Logger | Production-ready logging with console and file rotation | | Response Helpers | Standardized API responses via res.respond() | | HTTPS Support | Built-in SSL/TLS certificate loading and validation | | Graceful Shutdown | Proper SIGTERM/SIGINT handling with cleanup hooks |


Quick Start

1. Create Configuration File

// wecon.config.ts
import { defineConfig } from '@weconjs/core';

export default defineConfig({
  app: {
    name: 'my-api',
    version: '1.0.0',
  },
  modes: {
    development: {
      port: 3000,
      database: {
        mongoose: {
          protocol: 'mongodb',
          host: 'localhost',
          port: 27017,
          database: 'myapp_dev',
        },
      },
      logging: { level: 'debug' },
    },
    production: {
      port: 8080,
      database: {
        mongoose: {
          protocol: 'mongodb+srv',
          host: process.env.DB_HOST,
          database: 'myapp',
          username: process.env.DB_USER,
          password: process.env.DB_PASSWORD,
        },
      },
      logging: { 
        level: 'info', 
        enableFile: true,
        directory: './logs',
      },
      https: {
        enabled: true,
        keyPath: './certs/privkey.pem',
        certPath: './certs/fullchain.pem',
      },
    },
  },
  modules: ['./src/modules/users', './src/modules/auth'],
  features: {
    i18n: { 
      enabled: true, 
      defaultLocale: 'en',
      supported: ['en', 'es', 'fr'],
    },
    fieldShield: {
      enabled: true,
      strict: true,
    },
  },
});

2. Define a Module

// src/modules/users/users.module.ts
import { defineModule } from '@weconjs/core';
import { Routes, Route } from '@weconjs/lib';
import { userController } from './controllers/user.controller.js';

const usersRoutes = new Routes({
  prefix: '/users',
  routes: [
    new Route({ method: 'get', path: '/', handler: userController.findAll }),
    new Route({ method: 'get', path: '/:id', handler: userController.findById }),
    new Route({ method: 'post', path: '/', handler: userController.create }),
    new Route({ method: 'put', path: '/:id', handler: userController.update }),
    new Route({ method: 'delete', path: '/:id', handler: userController.delete }),
  ],
});

export default defineModule({
  name: 'users',
  description: 'User management module',
  routes: usersRoutes,
  dependencies: ['auth'], // Load auth module first
  onInit: async (ctx) => {
    ctx.logger.info('Users module initialized');
    // Setup module-specific resources
  },
});

3. Create Application Entry Point

// src/main.ts
import path from 'path';
import { 
  createWecon, 
  loadConfig, 
  buildUriFromConfig, 
  type WeconContext 
} from '@weconjs/core';

async function main() {
  // Load configuration with mode resolution
  const config = await loadConfig(
    path.resolve(process.cwd(), 'wecon.config.ts'),
    process.env.NODE_ENV
  );

  console.log(`Starting ${config.app.name} v${config.app.version}`);
  console.log(`Mode: ${config.mode}`);

  // Dynamic import after config is loaded
  const { wecon, modules } = await import('./bootstrap.js');

  // Create and configure the application
  const app = await createWecon({
    config,
    modules: [...modules],
    wecon,
    middleware: [], // Your custom middleware array
    database: {
      enabled: true,
      uri: buildUriFromConfig(config.database),
      plugins: [], // Global Mongoose plugins
      debug: config.mode === 'development',
    },
    plugins: {
      fieldShield: config.features?.fieldShield?.enabled
        ? { strict: config.features.fieldShield.strict ?? true }
        : false,
    },
    i18n: {
      enabled: config.features?.i18n?.enabled ?? false,
      modulesDir: './src/modules',
    },
    logger: {
      useWinston: true,
      level: config.logging?.level ?? 'info',
      appName: config.app.name,
      enableFile: config.logging?.enableFile ?? false,
      logsDir: config.logging?.directory ?? './logs',
    },
    hooks: {
      onBoot: async (ctx: WeconContext) => {
        ctx.logger.info('Application ready to receive requests');
      },
      onShutdown: async (ctx: WeconContext) => {
        ctx.logger.info('Application shutting down...');
        // Cleanup resources, close connections
      },
    },
  });

  await app.start();
}

main().catch((err) => {
  console.error('Failed to start application:', err);
  process.exit(1);
});

Configuration System

Mode-Based Configuration

Define environment-specific settings that inherit from a base configuration:

import { defineConfig } from '@weconjs/core';

export default defineConfig({
  // Base configuration (shared across all modes)
  app: { name: 'my-api', version: '1.0.0' },
  
  // Mode-specific overrides
  modes: {
    development: {
      port: 3000,
      logging: { level: 'debug' },
    },
    staging: {
      port: 3000,
      logging: { level: 'info' },
    },
    production: {
      port: 8080,
      logging: { level: 'warn', enableFile: true },
    },
  },
});

Loading Configuration

import { loadConfig, resolveConfig } from '@weconjs/core';

// Load and resolve for current environment
const config = await loadConfig('./wecon.config.ts', process.env.NODE_ENV);

// Or load and resolve separately
const rawConfig = await loadConfig('./wecon.config.ts');
const resolved = resolveConfig(rawConfig, 'production');

Module System

Module Definition

import { defineModule, type WeconContext } from '@weconjs/core';

export default defineModule({
  name: 'auth',
  description: 'Authentication and authorization',
  routes: authRoutes,
  
  // Declare dependencies (loaded first)
  dependencies: ['database-seeds'],
  
  // Lifecycle hooks
  onInit: async (module, ctx: WeconContext) => {
    // Called when module is registered
    ctx.logger.debug(`${module.name} module initializing`);
  },
  
  onBoot: async (module, ctx: WeconContext) => {
    // Called after all modules initialized, before server starts
    await seedDefaultRoles(ctx);
  },
  
  onShutdown: async (module, ctx: WeconContext) => {
    // Called on graceful shutdown
    await cleanupSessions();
  },
});

Module Discovery

The framework automatically resolves dependencies using topological sorting:

import { resolveModuleDependencies, loadModule } from '@weconjs/core';

const modules = await Promise.all([
  loadModule('./src/modules/users'),
  loadModule('./src/modules/auth'),
  loadModule('./src/modules/orders'),
]);

// Returns modules in correct initialization order
const sorted = resolveModuleDependencies(modules);

Server Factory

Basic Usage

import { createWecon } from '@weconjs/core';

const app = await createWecon({
  config,
  modules,
  wecon, // @weconjs/lib instance
});

await app.start();

Full Configuration

const app = await createWecon({
  config,
  modules,
  wecon,
  
  // Custom Express middleware
  middleware: [cors(), helmet(), rateLimit()],
  
  // Database configuration
  database: {
    enabled: true,
    uri: 'mongodb://localhost/myapp',
    plugins: [timestampPlugin, auditPlugin],
    debug: true,
    retryAttempts: 5,
    retryDelay: 2000,
  },
  
  // FieldShield integration
  plugins: {
    fieldShield: { strict: true },
  },
  
  // i18n configuration
  i18n: {
    enabled: true,
    modulesDir: './src/modules',
  },
  
  // Logger configuration
  logger: {
    useWinston: true,
    level: 'info',
    appName: 'my-api',
    enableFile: true,
    logsDir: './logs',
  },
  
  // Lifecycle hooks
  hooks: {
    onBoot: async (ctx) => { /* Server starting */ },
    onShutdown: async (ctx) => { /* Cleanup */ },
    onModuleInit: async (module, ctx) => { /* Module loaded */ },
  },
});

Response Helpers

The server factory installs res.respond() on all Express responses:

// Controller example
async findAll(req: Request, res: Response) {
  const users = await userService.findAll();
  
  res.respond({
    success: true,
    data: users,
    meta: { total: users.length },
  });
}

// Error response
res.respond({
  success: false,
  message: req.t('user_not_found'),
  errors: [{ code: 'NOT_FOUND', field: 'id' }],
}, 404);

Database Integration

URI Builder

Build MongoDB connection strings from configuration:

import { buildMongoUri, buildUriFromConfig } from '@weconjs/core';

// From individual parts
const uri = buildMongoUri({
  protocol: 'mongodb+srv',
  host: 'cluster.mongodb.net',
  database: 'myapp',
  username: 'user',
  password: 'pass',
  options: { retryWrites: 'true', w: 'majority' },
});

// From config object
const uri = buildUriFromConfig(config.database);

Database Connection

import { createDatabaseConnection } from '@weconjs/core';

const db = await createDatabaseConnection({
  uri: 'mongodb://localhost/myapp',
  plugins: [timestampPlugin],
  debug: process.env.NODE_ENV === 'development',
  retryAttempts: 5,
  retryDelay: 2000,
});

Logging

Winston Logger

import { createWinstonLogger, createConsoleLogger } from '@weconjs/core';

// Winston with file rotation (requires winston + winston-daily-rotate-file)
const logger = await createWinstonLogger({
  level: 'info',
  appName: 'my-api',
  enableFile: true,
  logsDir: './logs',
});

// Console-only fallback
const logger = createConsoleLogger({
  level: 'debug',
  appName: 'my-api',
});

logger.info('Server started', { port: 3000 });
logger.error('Database connection failed', { error: err.message });

API Reference

Configuration

| Function | Description | |----------|-------------| | defineConfig(config) | Define application configuration with TypeScript support | | resolveConfig(config, mode) | Resolve configuration for a specific mode | | loadConfig(path, mode?) | Load configuration file and optionally resolve mode |

Modules

| Function | Description | |----------|-------------| | defineModule(definition) | Define a module with routes and lifecycle hooks | | loadModule(path) | Load a module from file path | | resolveModuleDependencies(modules) | Sort modules by dependencies |

Server

| Function | Description | |----------|-------------| | createWecon(options) | Create and configure Wecon application |

Database

| Function | Description | |----------|-------------| | createDatabaseConnection(options) | Create MongoDB connection with retry logic | | buildMongoUri(parts) | Build MongoDB URI from parts | | buildUriFromConfig(config) | Build URI from database config object |

Logging

| Function | Description | |----------|-------------| | createWinstonLogger(options) | Create Winston logger with file rotation | | createConsoleLogger(options) | Create console-based logger |

Socket.IO

| Function | Description | |----------|-------------| | setupSocketIO(server, modulesDir, options) | Setup Socket.IO with auto-discovery | | discoverSocketHandlers(modulesDir) | Find socket handlers in modules | | discoverSocketMiddleware(modulesDir) | Find socket middleware in modules |


Testing

yarn test      # Run all 82 unit tests
yarn build     # Build TypeScript to dist/

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0.0
  • Express 5.x
  • Mongoose 8.x

License

MIT © weconjs