@weconjs/core
v1.4.1
Published
Wecon Framework Core - defineConfig, defineModule, and runtime utilities
Maintainers
Readme
@weconjs/core
Convention-over-configuration Node.js framework built on Express.
Table of Contents
- Installation
- Quick Start
- Configuration
- Modules
- Routing & RBAC
- Postman Generation
- Database
- Logging
- i18n
- Socket.IO
- Context & Services
- Authentication
- DevTools
- Server Factory
- API Reference
- Testing
- Requirements
- License
Installation
npm install @weconjs/coreExpress and Mongoose are peer dependencies:
npm install express mongooseOptional 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 ioredisQuick 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:
- Intelligence Layer —
RaiMatcherresolves the request to a RAI (Route Access Identifier) and checks authorization against the user's roles - 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)
PostmanGroupcreates folders,PostmanRouteadds 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.jsonEnable 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 ● connectedWithout 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 shutdownMiddleware execution order
When both auth and middlewares are provided, the execution order is:
- Context injection (
req.ctx) auth.middlewares— JWT, session, passportmiddlewares— security headers, body parsing, rate limiting, logging- RBAC check (via the
weconhandler) - 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 modeThe 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
/healthendpoint- 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
