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

@weconjs/core

v1.4.1

Published

Wecon Framework Core - defineConfig, defineModule, and runtime utilities

Readme

@weconjs/core

Convention-over-configuration Node.js framework built on Express.

npm version License: MIT

Table of Contents

Installation

npm install @weconjs/core

Express and Mongoose are peer dependencies:

npm install express mongoose

Optional peer dependencies:

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

# Socket.IO real-time support
npm install socket.io

# Socket.IO Redis adapter (for horizontal scaling)
npm install @socket.io/redis-adapter ioredis

Quick Start

1. Define your configuration

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

dotenv.config({ path: `.envs/.env.${process.env.NODE_ENV || 'development'}` });

export default defineConfig({
  app: {
    name: process.env.APP_NAME || 'my-api',
    version: process.env.APP_VERSION || '1.0.0',
  },
  mode: process.env.NODE_ENV || 'development',
  port: Number(process.env.PORT) || 3000,
  database: {
    mongoose: {
      protocol: process.env.MONGODB_PROTOCOL || 'mongodb',
      host: process.env.MONGODB_HOST || 'localhost',
      port: Number(process.env.MONGODB_PORT) || 27017,
      database: process.env.MONGODB_DB_NAME || 'myapp-dev',
      auth: {
        username: process.env.MONGODB_USER || '',
        password: process.env.MONGODB_PASSWORD || '',
      },
    },
  },
  logging: {
    level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
    enableFile: process.env.NODE_ENV === 'production',
  },
  https: {
    enabled: process.env.HTTPS_ENABLED === 'true',
    port: Number(process.env.HTTPS_PORT) || 8443,
    keyPath: process.env.SSL_KEY_PATH || './certs/private-key.pem',
    certPath: process.env.SSL_CERT_PATH || './certs/certificate.pem',
  },
  features: {
    i18n: { enabled: true, defaultLocale: 'en', supported: ['en', 'fr'] },
    socket: {
      enabled: true,
      cors: { origin: '*' },
      adapter: { type: 'redis', keyPrefix: 'myapp' },
    },
  },
});

2. Define a module

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

const UsersConfigSchema = z.object({
  maxPerPage: z.coerce.number().default(50),
});

const usersRoutes = new Routes({
  prefix: '/users',
  routes: [
    new Route({
      method: 'GET',
      path: '/',
      rai: 'users:list',
      roles: ['admin', 'user'],
      middlewares: [userController.findAll],
    }),
    new Route({
      method: 'POST',
      path: '/',
      rai: 'users:create',
      roles: ['admin'],
      middlewares: [userController.create],
    }),
  ],
});

export default defineModule({
  name: 'users',
  description: 'User management module',
  config: {
    schema: UsersConfigSchema,
    load: () => ({
      maxPerPage: Number(process.env.USERS_MAX_PER_PAGE) || 50,
    }),
  },
  routes: usersRoutes,
  priority: 0,
  onInit: async (ctx) => {
    ctx.logger.info('Users module initialized');
  },
});

3. Set up routing with RBAC

// src/bootstrap.ts
import { Wecon, Routes } from '@weconjs/core';
import usersModule from './modules/users/users.module.js';
import authModule from './modules/auth/auth.module.js';

export const wecon = new Wecon()
  .roles(['admin', 'user', 'guest'] as const)
  .guestRole('guest')
  .routes(
    new Routes({
      prefix: '/api',
      routes: [authModule.routes!, usersModule.routes!],
    })
  )
  .exclude(['/socket.io', '/ws'])
  .postman({
    name: 'My API',
    baseUrl: 'http://localhost:3000',
    apiPrefix: '/api',
    autoGenerate: true,
    output: {
      collection: './postman/collection.json',
      environment: './postman/environment.json',
    },
  })
  .dev({ helpfulErrors: true })
  .build();

export const modules = [authModule, usersModule];

4. Create the application entry point

// src/main.ts
import {
  createWecon,
  loadConfig,
  buildUriFromConfig,
  resolveModuleConfigs,
} from '@weconjs/core';
import mongoose from 'mongoose';
import Redis from 'ioredis';
import { wecon, modules } from './bootstrap.js';
import {
  createAuthMiddlewares,
  createSecurityMiddlewares,
  utilityMiddlewares,
} from './shared/middleware.js';

async function main() {
  const config = await loadConfig('./wecon.config.ts', process.env.NODE_ENV);

  const moduleConfigs = await resolveModuleConfigs(modules);
  config.moduleConfigs = moduleConfigs;

  const mongoUri = buildUriFromConfig(config.database);

  // Redis clients for Socket.IO adapter (if configured)
  let socketOptions: { pubClient?: Redis; subClient?: Redis } | undefined;
  if (config.features?.socket?.adapter) {
    const redis = new Redis({ host: process.env.REDIS_HOST || 'localhost' });
    const sub = redis.duplicate();
    redis.on('error', (err) => console.warn('[Redis pub]', err.message));
    sub.on('error', (err) => console.warn('[Redis sub]', err.message));
    socketOptions = { pubClient: redis, subClient: sub };
  }

  const app = await createWecon({
    config,
    modules,
    wecon,
    apiPrefix: '/api',
    // Auth middlewares run immediately after context injection
    auth: {
      middlewares: createAuthMiddlewares(authConfig, mongoUri),
    },
    // Security + utility middlewares run after auth
    middlewares: [
      ...createSecurityMiddlewares(coreConfig.security, config.mode),
      ...utilityMiddlewares,
    ],
    database: { enabled: true, uri: mongoUri, mongoose },
    i18n: { enabled: true, modulesDir: './src/modules' },
    logger: { useWinston: true, enableFile: false },
    socket: socketOptions,
    hooks: {
      onBoot: (ctx) => ctx.logger.info('Server ready'),
      onShutdown: (ctx) => ctx.logger.info('Shutting down...'),
    },
  });

  await app.start();
}

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

Configuration

Configuration is a flat object — no mode nesting. Use environment variables and .env files for per-environment values:

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

export default defineConfig({
  app: { name: 'my-api', version: '1.0.0' },
  mode: process.env.NODE_ENV || 'development',
  port: Number(process.env.PORT) || 3000,

  database: {
    mongoose: {
      protocol: 'mongodb',
      host: process.env.DB_HOST || 'localhost',
      port: 27017,
      database: process.env.DB_NAME || 'myapp',
      auth: {
        username: process.env.DB_USER || '',
        password: process.env.DB_PASSWORD || '',
      },
    },
  },

  logging: {
    level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
    enableConsole: true,
    enableFile: process.env.NODE_ENV === 'production',
  },

  https: {
    enabled: process.env.HTTPS_ENABLED === 'true',
    port: Number(process.env.HTTPS_PORT) || 8443,
    keyPath: './certs/private-key.pem',
    certPath: './certs/certificate.pem',
  },

  features: {
    i18n: { enabled: true, defaultLocale: 'en', supported: ['en', 'fr'] },
    socket: {
      enabled: true,
      path: '/socket.io',
      cors: { origin: '*' },
      adapter: { type: 'redis', keyPrefix: 'myapp' },
    },
  },
});

Loading configuration

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

const config = await loadConfig('./wecon.config.ts', process.env.NODE_ENV);

Per-module configuration

Modules declare a Zod schema and a load() function to read environment variables. Config is validated at startup and accessible at runtime:

import { z } from 'zod';
import { defineModule } from '@weconjs/core';

const MailConfigSchema = z.object({
  from: z.string().email().default('[email protected]'),
  host: z.string().default('smtp.gmail.com'),
  port: z.coerce.number().default(587),
});

export default defineModule({
  name: 'mail',
  config: {
    schema: MailConfigSchema,
    load: () => ({
      from: process.env.MAIL_FROM || '[email protected]',
      host: process.env.MAIL_HOST || 'smtp.gmail.com',
      port: Number(process.env.MAIL_PORT) || 587,
    }),
  },
  onInit: async (ctx) => {
    const mailConfig = ctx.getModuleConfig<z.infer<typeof MailConfigSchema>>('mail');
    ctx.logger.info(`Mail host: ${mailConfig.host}`);
  },
});

Resolve all module configs before creating the application:

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

const moduleConfigs = await resolveModuleConfigs(modules);
config.moduleConfigs = moduleConfigs;

Modules

Defining modules

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

export default defineModule({
  name: 'auth',                          // Unique identifier (lowercase, hyphens allowed)
  description: 'Authentication module',
  config: { schema, load: () => ({}) },  // Zod schema + env loader
  routes: authRoutes,                    // Routes instance (optional)
  priority: 1,                           // Load order (lower = first, default: 0)
  path: __dirname,                       // Enables per-module package.json discovery

  onInit: async (ctx) => {
    // Called during initialization — register services here
    ctx.registerService('auth', new AuthService(config));
  },
  onDestroy: async (ctx) => {
    // Called on graceful shutdown
  },
});

Priority-based load order

Modules are sorted by priority ascending — lower numbers initialize first:

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

const modulesMap = new Map([
  ['core', coreModule],      // priority: 0
  ['users', usersModule],    // priority: 0
  ['auth', authModule],      // priority: 1
]);

// Returns: [coreModule, usersModule, authModule]
const sorted = resolveModuleDependencies(modulesMap);

Routing & RBAC

Wecon uses a two-layer architecture for request processing:

  1. Intelligence LayerRaiMatcher resolves the request to a RAI (Route Access Identifier) and checks authorization against the user's roles
  2. Execution Layer — a single compiled Express Router handles the request

Route Access Identifiers (RAI)

Every route has a unique RAI string (e.g. users:list, orders:create). The RAI is used for authorization checks and route introspection.

Defining routes

import { Route, Routes, PostmanGroup, PostmanRoute } from '@weconjs/core';

const routes = new Routes({
  prefix: '/api/orders',
  postman: new PostmanGroup({ folderName: 'Orders' }),
  routes: [
    new Route({
      method: 'GET',
      path: '/',
      rai: 'orders:list',
      roles: ['admin', 'user'],
      middlewares: [orderController.list],
      postman: new PostmanRoute({ name: 'List Orders' }),
    }),
    new Route({
      method: 'POST',
      path: '/',
      rai: 'orders:create',
      roles: ['admin', 'user'],
      middlewares: [validateOrder, orderController.create],
      postman: new PostmanRoute({
        name: 'Create Order',
        body: {
          mode: 'raw',
          raw: JSON.stringify({ item: 'Widget', qty: 1 }, null, 2),
          options: { raw: { language: 'json' } },
        },
      }),
    }),
    new Route({
      method: 'DELETE',
      path: '/:id',
      rai: 'orders:delete',
      roles: ['admin'],
      middlewares: [orderController.delete],
      meta: { audit: true },
    }),
  ],
});

Routes can be nested. Prefixes, middleware, and params accumulate from parent groups:

const apiRoutes = new Routes({
  prefix: '/api',
  routes: [authRoutes, userRoutes, orderRoutes],
});

Building the Wecon instance

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

const wecon = new Wecon()
  .roles(['admin', 'user', 'guest'] as const)
  .guestRole('guest')
  .routes(apiRoutes)
  .exclude(['/socket.io', '/ws'])  // Bypass RBAC for these paths (default: ["/socket.io"])
  .dev({
    helpfulErrors: true,  // Detailed 401/404 messages in development
  })
  .build();

// Mount as Express middleware
app.use(wecon.handler());

Path exclusion

The .exclude(paths) method lets you bypass RBAC for specific path prefixes. By default, /socket.io is excluded (for Socket.IO handshake requests). Additional paths are merged with the defaults:

wecon.exclude(['/socket.io', '/ws', '/webhooks'])

Type-safe roles

Augment the global Wecon.Roles type for compile-time role checking:

// wecon.d.ts
declare global {
  namespace Wecon {
    type Roles = 'admin' | 'user' | 'guest';
  }
}
export {};

Route introspection

const allRoutes = wecon.getRoutes();
const route = wecon.getRoute('users:read');

Postman Generation

Auto-generate Postman Collection v2.1.0 and Environment files from your route tree:

const wecon = new Wecon()
  .routes(apiRoutes)
  .postman({
    name: 'My API',
    description: 'API documentation',
    baseUrl: 'http://localhost:3000',
    apiPrefix: '/api/v1',
    autoGenerate: true,
    output: {
      collection: './postman/collection.json',
      environment: './postman/environment.json',
    },
  })
  .build();
  • URLs use {{APP_PUBLIC_ADDRESS}}{{API_PREFIX}} variables in the generated collection
  • Variables are placed in the environment file (not the collection)
  • PostmanGroup creates folders, PostmanRoute adds request metadata (body, description)

Database

URI builder

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

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

// Or build from a resolved config
const uri = buildUriFromConfig(config.database);

Connection with retry logic

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

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

await db.connect();

The connection retries with configurable exponential backoff on failure.

Logging

Two logging backends are supported: Winston (with daily file rotation) and a console-only fallback.

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

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

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

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

When creating an app with createWecon, the framework tries Winston first and falls back to the console logger automatically.

i18n

Translation files are auto-discovered from module directories. Each module has an i18n/ folder with locale JSON files:

src/modules/users/i18n/en.translation.json
src/modules/users/i18n/fr.translation.json

Enable i18n in your config:

const app = await createWecon({
  config,
  modules,
  i18n: { enabled: true, modulesDir: './src/modules' },
});

Use translations in handlers via req.t(). Keys are namespaced by module:

// Format: {module}:{section}.{KEY}
res.json({ message: req.t('users:welcome', { name: 'Alice' }) });

Interpolation uses {{key}} syntax in translation files:

{ "welcome": "Welcome, {{name}}!" }

The i18nNamespaceMiddleware automatically sets the translation namespace based on the route's module, so RequestError codes are automatically mapped to {namespace}:errors.{CODE}.

Socket.IO

Socket.IO support is built into the server factory. Enable it in your config and the framework handles server creation, handler discovery, and optional Redis adapter setup.

Configuration

// wecon.config.ts
features: {
  socket: {
    enabled: true,
    path: '/socket.io',          // Custom path (default: '/socket.io')
    cors: { origin: '*' },
    adapter: {                   // Optional — for horizontal scaling
      type: 'redis',
      keyPrefix: 'myapp',       // Redis key prefix (default: 'socket.io')
    },
  },
}

Redis adapter

For horizontal scaling across multiple Node processes, pass Redis clients via createWecon. The consuming project owns the Redis instances — core only needs @socket.io/redis-adapter:

import Redis from 'ioredis';

const redis = new Redis({
  host: process.env.REDIS_HOST || 'localhost',
  port: Number(process.env.REDIS_PORT) || 6379,
  password: process.env.REDIS_PASSWORD || undefined,
});
const sub = redis.duplicate();

redis.on('error', (err) => console.warn('[Redis pub]', err.message));
sub.on('error', (err) => console.warn('[Redis sub]', err.message));

const app = await createWecon({
  // ...
  socket: { pubClient: redis, subClient: sub },
});

When Redis is connected, the startup banner shows its status:

  ├─ Database    ● connected — myapp
  ├─ Redis       ● connected

Without the adapter config or without passing Redis clients, Socket.IO runs in-memory (single-process mode).

Handler discovery

Socket handlers and middleware are auto-discovered from module directories:

src/modules/chat/socket/chat.socket.ts        # Handler
src/modules/chat/socket/socket.middleware.ts   # Middleware (optional)

Handler

// src/modules/chat/socket/chat.socket.ts
import type { SocketHandlerFn } from '@weconjs/core';

const chatHandler: SocketHandlerFn = (io, socket) => {
  socket.on('message', (data) => {
    io.emit('message', data);
  });
};

export default chatHandler;

Middleware

// src/modules/chat/socket/socket.middleware.ts
import type { SocketMiddlewareFn } from '@weconjs/core';

const authMiddleware: SocketMiddlewareFn = (socket, next) => {
  const token = socket.handshake.auth?.token;
  if (!token) return next(new Error('Authentication required'));
  next();
};

export default authMiddleware;

Manual setup

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

const io = await setupSocketIO(httpServer, './src/modules', {
  enabled: true,
  path: '/socket.io',
  cors: { origin: '*' },
  adapter: {
    type: 'redis',
    pubClient: redisPub,
    subClient: redisSub,
    keyPrefix: 'myapp',
  },
});

When socket is enabled, the io instance is available on ctx.io.

Context & Services

The WeconContext is passed to all module hooks, handlers, and middleware. It provides access to configuration, logging, and a service registry.

// Register a service (in onInit)
ctx.registerService('mailer', new MailerService(config));

// Retrieve a service (in controllers via req.ctx)
const mailer = req.ctx!.getService<MailerService>('mailer');

// Access module config (validated at startup)
const mailConfig = ctx.getModuleConfig<MailConfig>('mail');

// Update module config at runtime (re-validates against Zod schema)
ctx.setModuleConfig('mail', { from: '[email protected]' });

Authentication

Wecon provides an Authenticable interface for any model used in authentication. The WeconRequest generic lets you type req.user:

import type { Authenticable, WeconRequest, WeconResponse } from '@weconjs/core';

interface User extends Authenticable {
  email: string;
  name: { first: string; last: string };
}

function getProfile(req: WeconRequest<User>, res: WeconResponse) {
  const user = req.user!;
  res.respond({ data: { email: user.email, roles: user.roles } });
}

Response helpers

The res.respond() helper produces standardized API responses:

// Success
res.respond({ data: users, meta: { total: users.length } });
// → { success: true, data: [...], errors: null, meta: { total: 10 } }

// Error
res.status(404).respond({
  errors: [{ code: 'NOT_FOUND', message: 'User not found' }],
});
// → { success: false, data: null, errors: [...], meta: null }

RequestError

Throw structured errors that integrate with i18n:

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

throw new RequestError('User not found', {
  code: 'USER_NOT_FOUND',  // Maps to i18n key: {namespace}:errors.USER_NOT_FOUND
  status: 404,
  details: { id: userId },
});

DevTools

Built-in development tools for module and route introspection:

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

const devRouter = createDevToolsRouter({ modules, wecon });
app.use('/_dev', devRouter);

Provides endpoints for listing modules (with priority, config) and inspecting routes.

Server Factory

createWecon is the main entry point. It wires together all framework features and returns a WeconApp instance:

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

const app = await createWecon({
  config,
  modules,
  wecon,                           // Wecon routing instance (optional)
  apiPrefix: '/api/v1',            // API prefix for middleware/routing

  // Auth middlewares run immediately after context injection, before all other middleware.
  // Use this to wire JWT verification, session deserialization, passport, etc.
  auth: {
    middlewares: [jwtMiddleware, sessionMiddleware, passport.initialize()],
  },

  // General middleware (security headers, body parsing, logging) — runs after auth.
  middlewares: [cors(), helmet(), express.json()],

  database: { enabled: true, uri: '...' },
  i18n: { enabled: true, modulesDir: './src/modules' },
  logger: { useWinston: true, enableFile: true, logDir: './logs' },
  socket: {                        // Redis clients for Socket.IO adapter (optional)
    pubClient: redisPub,
    subClient: redisSub,
  },
  hooks: {
    onBoot: async (ctx) => { /* runs before server starts listening */ },
    onShutdown: async (ctx) => { /* cleanup on SIGTERM/SIGINT */ },
  },
});

const server = await app.start();     // Start listening
await app.shutdown();                  // Graceful shutdown

Middleware execution order

When both auth and middlewares are provided, the execution order is:

  1. Context injection (req.ctx)
  2. auth.middlewares — JWT, session, passport
  3. middlewares — security headers, body parsing, rate limiting, logging
  4. RBAC check (via the wecon handler)
  5. Route handlers

Startup banner

On start, a colored banner is printed with server info:

  ▲ my-api v1.0.0

  ├─ URL         http://localhost:3000
  ├─ API Prefix  /api/v1
  ├─ Version     v1.0.0
  ├─ Mode        development
  ├─ Database    ● connected — myapp
  ├─ Redis       ● connected
  ├─ Modules     3 — core, auth, users
  ├─ Routes      12 endpoints
  ├─ Features    i18n, Socket.IO
  │
  ✓ Ready in development mode

The Redis line only appears when a Redis adapter is configured. It shows ● connected (green) or ● disconnected (yellow) based on live client status.

Features included automatically

  • /health endpoint
  • HTTPS support (falls back to HTTP if certs are missing)
  • Socket.IO server creation and handler discovery
  • Redis adapter attachment (when configured + clients provided)
  • Graceful shutdown on SIGTERM, SIGINT, SIGUSR2
  • Global error handler with standardized responses

API Reference

Configuration

| Export | Description | |--------|-------------| | defineConfig(config) | Define application configuration with TypeScript support | | loadConfig(path, mode?) | Load configuration file and optionally resolve mode |

Modules

| Export | Description | |--------|-------------| | defineModule(definition) | Define a module with routes, config, and lifecycle hooks | | loadModule(path, baseDir) | Load a module from file path with socket discovery | | resolveModuleDependencies(modules) | Sort modules by priority (lower first) | | resolveModuleConfigs(modules) | Call each module's load() and validate with Zod schema | | readModulePackageJson(path) | Read a module's package.json | | detectPackageManager() | Detect npm/yarn/pnpm |

Server

| Export | Description | |--------|-------------| | createWecon(options) | Create and configure the application |

Routing

| Export | Description | |--------|-------------| | Wecon | Main routing class with fluent API and RBAC | | Route | Single endpoint definition (method, path, RAI, roles, middlewares) | | Routes | Hierarchical route group with prefix, middleware, and params | | RoutesParam | Route parameter definition with validation | | PostmanRoute | Postman request metadata (name, description, body) | | PostmanGroup | Postman folder grouping | | RaiMatcher | RAI resolution engine (maps request path + method to a RAI) | | ErrorCatcher | Base class for configuration error reporting | | PostmanGenerator | Generates Postman Collection v2.1.0 + Environment files |

Database

| Export | 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

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

i18n

| Export | Description | |--------|-------------| | initializeI18n(modulesDir, defaultLocale) | Initialize i18n and return Express middleware | | initI18n(modulesDir, defaultLocale) | Alias for initializeI18n | | i18nNamespaceMiddleware | Middleware that sets i18n namespace from route module | | getI18n() | Get the i18next instance | | translate(key, options?) | Translate a key programmatically |

Socket.IO

| Export | Description | |--------|-------------| | createSocketServer(httpServer, options) | Create Socket.IO server | | setupSocketIO(httpServer, modulesDir, options) | Full auto-discovery setup | | initializeSocket(io, handlers, middleware) | Wire handlers and middleware to io | | discoverSocketHandlersFromModules(modulesDir) | Find all socket handler files | | discoverSocketMiddlewareFromModules(modulesDir) | Find all socket middleware files |

Context

| Export | Description | |--------|-------------| | createContext(options) | Create application context with service registry | | createLogger(options) | Create a logger instance |

DevTools

| Export | Description | |--------|-------------| | createDevToolsRouter(options) | Create Express router for module/route introspection |

Errors

| Export | Description | |--------|-------------| | ConfigError | Configuration error with code and metadata | | RequestError | Request error with code, status, and metadata |

Types

Key TypeScript types available for import:

import type {
  // Config
  WeconConfig, ResolvedConfig, AppConfig, DatabaseConfig,
  LoggingConfig, HttpsConfig, SocketConfig, FeaturesConfig,

  // Modules
  ModuleDefinition, ModuleConfigDefinition, WeconModule,

  // Routing
  RouteConfig, RoutesConfig, RAI, WeconDevConfig, WeconPostmanConfig,

  // Context
  WeconContext, WeconLogger, WeconServices,

  // Socket
  SocketHandler, SocketMiddleware, SocketHandlerFn, SocketMiddlewareFn,
  SocketServer, SocketInstance, DiscoveredSocketHandler, SocketOptions,

  // Auth & Request
  Authenticable, WeconRequest, WeconResponse, RouteHandler, WeconMiddleware,

  // Server
  CreateWeconOptions, WeconApp, ApiError, ApiResponse, RespondOptions,

  // Postman
  PostmanGeneratorConfig, PostmanCollectionConfig,
} from '@weconjs/core';

Testing

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # With coverage report
npm run build         # Build TypeScript to dist/

Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0.0
  • Express 5.x (peer dependency)
  • Mongoose 8.x (peer dependency)

License

MIT