@weconjs/core 1.2.15 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -83
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,12 +12,14 @@
|
|
|
12
12
|
- [Configuration](#configuration)
|
|
13
13
|
- [Modules](#modules)
|
|
14
14
|
- [Routing & RBAC](#routing--rbac)
|
|
15
|
+
- [Postman Generation](#postman-generation)
|
|
15
16
|
- [Database](#database)
|
|
16
17
|
- [Logging](#logging)
|
|
17
18
|
- [i18n](#i18n)
|
|
18
19
|
- [Socket.IO](#socketio)
|
|
19
20
|
- [Context & Services](#context--services)
|
|
20
21
|
- [Authentication](#authentication)
|
|
22
|
+
- [DevTools](#devtools)
|
|
21
23
|
- [API Reference](#api-reference)
|
|
22
24
|
- [Testing](#testing)
|
|
23
25
|
- [Requirements](#requirements)
|
|
@@ -87,7 +89,6 @@ export default defineConfig({
|
|
|
87
89
|
logging: { level: 'info', enableFile: true },
|
|
88
90
|
},
|
|
89
91
|
},
|
|
90
|
-
modules: ['./src/modules/auth', './src/modules/users'],
|
|
91
92
|
});
|
|
92
93
|
```
|
|
93
94
|
|
|
@@ -95,9 +96,14 @@ export default defineConfig({
|
|
|
95
96
|
|
|
96
97
|
```typescript
|
|
97
98
|
// src/modules/users/users.module.ts
|
|
99
|
+
import { z } from 'zod';
|
|
98
100
|
import { defineModule, Routes, Route } from '@weconjs/core';
|
|
99
101
|
import { userController } from './controllers/user.controller.js';
|
|
100
102
|
|
|
103
|
+
const UsersConfigSchema = z.object({
|
|
104
|
+
maxPerPage: z.coerce.number().default(50),
|
|
105
|
+
});
|
|
106
|
+
|
|
101
107
|
const usersRoutes = new Routes({
|
|
102
108
|
prefix: '/users',
|
|
103
109
|
routes: [
|
|
@@ -108,13 +114,6 @@ const usersRoutes = new Routes({
|
|
|
108
114
|
roles: ['admin', 'user'],
|
|
109
115
|
middlewares: [userController.findAll],
|
|
110
116
|
}),
|
|
111
|
-
new Route({
|
|
112
|
-
method: 'GET',
|
|
113
|
-
path: '/:id',
|
|
114
|
-
rai: 'users:read',
|
|
115
|
-
roles: ['admin', 'user'],
|
|
116
|
-
middlewares: [userController.findById],
|
|
117
|
-
}),
|
|
118
117
|
new Route({
|
|
119
118
|
method: 'POST',
|
|
120
119
|
path: '/',
|
|
@@ -128,8 +127,14 @@ const usersRoutes = new Routes({
|
|
|
128
127
|
export default defineModule({
|
|
129
128
|
name: 'users',
|
|
130
129
|
description: 'User management module',
|
|
130
|
+
config: {
|
|
131
|
+
schema: UsersConfigSchema,
|
|
132
|
+
load: () => ({
|
|
133
|
+
maxPerPage: Number(process.env.USERS_MAX_PER_PAGE) || 50,
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
131
136
|
routes: usersRoutes,
|
|
132
|
-
|
|
137
|
+
priority: 0,
|
|
133
138
|
onInit: async (ctx) => {
|
|
134
139
|
ctx.logger.info('Users module initialized');
|
|
135
140
|
},
|
|
@@ -155,7 +160,17 @@ export const wecon = new Wecon()
|
|
|
155
160
|
routes: [authModule.routes!, usersModule.routes!],
|
|
156
161
|
})
|
|
157
162
|
)
|
|
158
|
-
.
|
|
163
|
+
.postman({
|
|
164
|
+
name: 'My API',
|
|
165
|
+
baseUrl: 'http://localhost:3000',
|
|
166
|
+
apiPrefix: '/api',
|
|
167
|
+
autoGenerate: true,
|
|
168
|
+
output: {
|
|
169
|
+
collection: './postman/collection.json',
|
|
170
|
+
environment: './postman/environment.json',
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
.dev({ helpfulErrors: true })
|
|
159
174
|
.build();
|
|
160
175
|
|
|
161
176
|
export const modules = [authModule, usersModule];
|
|
@@ -165,12 +180,21 @@ export const modules = [authModule, usersModule];
|
|
|
165
180
|
|
|
166
181
|
```typescript
|
|
167
182
|
// src/main.ts
|
|
168
|
-
import {
|
|
183
|
+
import {
|
|
184
|
+
createWecon,
|
|
185
|
+
loadConfig,
|
|
186
|
+
buildUriFromConfig,
|
|
187
|
+
resolveModuleConfigs,
|
|
188
|
+
} from '@weconjs/core';
|
|
169
189
|
import { wecon, modules } from './bootstrap.js';
|
|
170
190
|
|
|
171
191
|
async function main() {
|
|
172
192
|
const config = await loadConfig('./wecon.config.ts', process.env.NODE_ENV);
|
|
173
193
|
|
|
194
|
+
// Resolve module configs (calls load() + validates with Zod schema)
|
|
195
|
+
const moduleConfigs = await resolveModuleConfigs(modules);
|
|
196
|
+
config.moduleConfigs = moduleConfigs;
|
|
197
|
+
|
|
174
198
|
const app = await createWecon({
|
|
175
199
|
config,
|
|
176
200
|
modules,
|
|
@@ -179,6 +203,7 @@ async function main() {
|
|
|
179
203
|
enabled: true,
|
|
180
204
|
uri: buildUriFromConfig(config.database),
|
|
181
205
|
},
|
|
206
|
+
i18n: { enabled: true, modulesDir: './src/modules' },
|
|
182
207
|
logger: { useWinston: true, enableFile: false },
|
|
183
208
|
hooks: {
|
|
184
209
|
onBoot: (ctx) => ctx.logger.info('Server ready'),
|
|
@@ -244,38 +269,42 @@ const resolved = resolveConfig(rawConfig, 'production');
|
|
|
244
269
|
|
|
245
270
|
### Per-module configuration
|
|
246
271
|
|
|
247
|
-
Modules
|
|
272
|
+
Modules declare a Zod schema and a `load()` function to read environment variables. Config is validated at startup and accessible at runtime:
|
|
248
273
|
|
|
249
274
|
```typescript
|
|
250
275
|
import { z } from 'zod';
|
|
251
276
|
import { defineModule } from '@weconjs/core';
|
|
252
277
|
|
|
278
|
+
const MailConfigSchema = z.object({
|
|
279
|
+
from: z.string().email().default('noreply@example.com'),
|
|
280
|
+
host: z.string().default('smtp.gmail.com'),
|
|
281
|
+
port: z.coerce.number().default(587),
|
|
282
|
+
});
|
|
283
|
+
|
|
253
284
|
export default defineModule({
|
|
254
285
|
name: 'mail',
|
|
255
286
|
config: {
|
|
256
|
-
schema:
|
|
257
|
-
|
|
258
|
-
|
|
287
|
+
schema: MailConfigSchema,
|
|
288
|
+
load: () => ({
|
|
289
|
+
from: process.env.MAIL_FROM || 'noreply@example.com',
|
|
290
|
+
host: process.env.MAIL_HOST || 'smtp.gmail.com',
|
|
291
|
+
port: Number(process.env.MAIL_PORT) || 587,
|
|
259
292
|
}),
|
|
260
|
-
defaults: { provider: 'ses' },
|
|
261
293
|
},
|
|
262
294
|
onInit: async (ctx) => {
|
|
263
|
-
const mailConfig = ctx.getModuleConfig<
|
|
264
|
-
ctx.logger.info(`Mail
|
|
295
|
+
const mailConfig = ctx.getModuleConfig<z.infer<typeof MailConfigSchema>>('mail');
|
|
296
|
+
ctx.logger.info(`Mail host: ${mailConfig.host}`);
|
|
265
297
|
},
|
|
266
298
|
});
|
|
267
299
|
```
|
|
268
300
|
|
|
269
|
-
|
|
301
|
+
Resolve all module configs before creating the application:
|
|
270
302
|
|
|
271
303
|
```typescript
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
},
|
|
277
|
-
// ...
|
|
278
|
-
});
|
|
304
|
+
import { resolveModuleConfigs } from '@weconjs/core';
|
|
305
|
+
|
|
306
|
+
const moduleConfigs = await resolveModuleConfigs(modules);
|
|
307
|
+
config.moduleConfigs = moduleConfigs;
|
|
279
308
|
```
|
|
280
309
|
|
|
281
310
|
## Modules
|
|
@@ -286,15 +315,16 @@ export default defineConfig({
|
|
|
286
315
|
import { defineModule } from '@weconjs/core';
|
|
287
316
|
|
|
288
317
|
export default defineModule({
|
|
289
|
-
name: 'auth',
|
|
290
|
-
description: 'Authentication
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
path: __dirname,
|
|
318
|
+
name: 'auth', // Unique identifier (lowercase, hyphens allowed)
|
|
319
|
+
description: 'Authentication module',
|
|
320
|
+
config: { schema, load: () => ({}) }, // Zod schema + env loader
|
|
321
|
+
routes: authRoutes, // Routes instance (optional)
|
|
322
|
+
priority: 1, // Load order (lower = first, default: 0)
|
|
323
|
+
path: __dirname, // Enables per-module package.json discovery
|
|
295
324
|
|
|
296
325
|
onInit: async (ctx) => {
|
|
297
|
-
// Called
|
|
326
|
+
// Called during initialization — register services here
|
|
327
|
+
ctx.registerService('auth', new AuthService(config));
|
|
298
328
|
},
|
|
299
329
|
onDestroy: async (ctx) => {
|
|
300
330
|
// Called on graceful shutdown
|
|
@@ -302,21 +332,21 @@ export default defineModule({
|
|
|
302
332
|
});
|
|
303
333
|
```
|
|
304
334
|
|
|
305
|
-
###
|
|
335
|
+
### Priority-based load order
|
|
306
336
|
|
|
307
|
-
Modules are sorted
|
|
337
|
+
Modules are sorted by `priority` ascending — lower numbers initialize first:
|
|
308
338
|
|
|
309
339
|
```typescript
|
|
310
|
-
import {
|
|
340
|
+
import { resolveModuleDependencies } from '@weconjs/core';
|
|
311
341
|
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
342
|
+
const modulesMap = new Map([
|
|
343
|
+
['core', coreModule], // priority: 0
|
|
344
|
+
['users', usersModule], // priority: 0
|
|
345
|
+
['auth', authModule], // priority: 1
|
|
316
346
|
]);
|
|
317
347
|
|
|
318
|
-
// Returns
|
|
319
|
-
const sorted = resolveModuleDependencies(
|
|
348
|
+
// Returns: [coreModule, usersModule, authModule]
|
|
349
|
+
const sorted = resolveModuleDependencies(modulesMap);
|
|
320
350
|
```
|
|
321
351
|
|
|
322
352
|
### Per-module dependencies
|
|
@@ -352,11 +382,12 @@ Every route has a unique RAI string (e.g. `users:list`, `orders:create`). The RA
|
|
|
352
382
|
### Defining routes
|
|
353
383
|
|
|
354
384
|
```typescript
|
|
355
|
-
import { Route, Routes,
|
|
385
|
+
import { Route, Routes, PostmanGroup, PostmanRoute } from '@weconjs/core';
|
|
356
386
|
|
|
357
387
|
const routes = new Routes({
|
|
358
388
|
prefix: '/api/orders',
|
|
359
389
|
middlewares: [authMiddleware],
|
|
390
|
+
postman: new PostmanGroup({ folderName: 'Orders' }),
|
|
360
391
|
routes: [
|
|
361
392
|
new Route({
|
|
362
393
|
method: 'GET',
|
|
@@ -364,6 +395,7 @@ const routes = new Routes({
|
|
|
364
395
|
rai: 'orders:list',
|
|
365
396
|
roles: ['admin', 'user'],
|
|
366
397
|
middlewares: [orderController.list],
|
|
398
|
+
postman: new PostmanRoute({ name: 'List Orders' }),
|
|
367
399
|
}),
|
|
368
400
|
new Route({
|
|
369
401
|
method: 'POST',
|
|
@@ -371,6 +403,14 @@ const routes = new Routes({
|
|
|
371
403
|
rai: 'orders:create',
|
|
372
404
|
roles: ['admin', 'user'],
|
|
373
405
|
middlewares: [validateOrder, orderController.create],
|
|
406
|
+
postman: new PostmanRoute({
|
|
407
|
+
name: 'Create Order',
|
|
408
|
+
body: {
|
|
409
|
+
mode: 'raw',
|
|
410
|
+
raw: JSON.stringify({ item: 'Widget', qty: 1 }, null, 2),
|
|
411
|
+
options: { raw: { language: 'json' } },
|
|
412
|
+
},
|
|
413
|
+
}),
|
|
374
414
|
}),
|
|
375
415
|
new Route({
|
|
376
416
|
method: 'DELETE',
|
|
@@ -404,12 +444,7 @@ const wecon = new Wecon()
|
|
|
404
444
|
.guestRole('guest')
|
|
405
445
|
.routes(apiRoutes)
|
|
406
446
|
.dev({
|
|
407
|
-
debugMode: true,
|
|
408
447
|
helpfulErrors: true, // Detailed 401/404 messages in development
|
|
409
|
-
logRoutes: true,
|
|
410
|
-
})
|
|
411
|
-
.onRoutesPrepared((routes) => {
|
|
412
|
-
console.log(`Registered ${routes.length} routes`);
|
|
413
448
|
})
|
|
414
449
|
.build();
|
|
415
450
|
|
|
@@ -438,6 +473,31 @@ const allRoutes = wecon.getRoutes();
|
|
|
438
473
|
const route = wecon.getRoute('users:read');
|
|
439
474
|
```
|
|
440
475
|
|
|
476
|
+
## Postman Generation
|
|
477
|
+
|
|
478
|
+
Auto-generate Postman Collection v2.1.0 and Environment files from your route tree:
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
const wecon = new Wecon()
|
|
482
|
+
.routes(apiRoutes)
|
|
483
|
+
.postman({
|
|
484
|
+
name: 'My API',
|
|
485
|
+
description: 'API documentation',
|
|
486
|
+
baseUrl: 'http://localhost:3000',
|
|
487
|
+
apiPrefix: '/api/v1',
|
|
488
|
+
autoGenerate: true,
|
|
489
|
+
output: {
|
|
490
|
+
collection: './postman/collection.json',
|
|
491
|
+
environment: './postman/environment.json',
|
|
492
|
+
},
|
|
493
|
+
})
|
|
494
|
+
.build();
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
- URLs use `{{APP_PUBLIC_ADDRESS}}{{API_PREFIX}}` variables in the generated collection
|
|
498
|
+
- Variables are placed in the environment file (not the collection)
|
|
499
|
+
- `PostmanGroup` creates folders, `PostmanRoute` adds request metadata (body, description)
|
|
500
|
+
|
|
441
501
|
## Database
|
|
442
502
|
|
|
443
503
|
### URI builder
|
|
@@ -467,7 +527,6 @@ const db = await createDatabaseConnection({
|
|
|
467
527
|
uri: 'mongodb://localhost/myapp',
|
|
468
528
|
plugins: [timestampPlugin],
|
|
469
529
|
debug: process.env.NODE_ENV === 'development',
|
|
470
|
-
fieldShield: { enabled: true, strict: true },
|
|
471
530
|
});
|
|
472
531
|
|
|
473
532
|
await db.connect();
|
|
@@ -504,11 +563,11 @@ When creating an app with `createWecon`, the framework tries Winston first and f
|
|
|
504
563
|
|
|
505
564
|
## i18n
|
|
506
565
|
|
|
507
|
-
Translation files are auto-discovered from module directories. Each module
|
|
566
|
+
Translation files are auto-discovered from module directories. Each module has an `i18n/` folder with locale JSON files:
|
|
508
567
|
|
|
509
568
|
```
|
|
510
|
-
src/modules/users/
|
|
511
|
-
src/modules/users/
|
|
569
|
+
src/modules/users/i18n/en.translation.json
|
|
570
|
+
src/modules/users/i18n/fr.translation.json
|
|
512
571
|
```
|
|
513
572
|
|
|
514
573
|
Enable i18n in your config:
|
|
@@ -521,12 +580,11 @@ const app = await createWecon({
|
|
|
521
580
|
});
|
|
522
581
|
```
|
|
523
582
|
|
|
524
|
-
Use translations in handlers via `req.t()
|
|
583
|
+
Use translations in handlers via `req.t()`. Keys are namespaced by module:
|
|
525
584
|
|
|
526
585
|
```typescript
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
});
|
|
586
|
+
// Format: {module}:{section}.{KEY}
|
|
587
|
+
res.json({ message: req.t('users:welcome', { name: 'Alice' }) });
|
|
530
588
|
```
|
|
531
589
|
|
|
532
590
|
Interpolation uses `{{key}}` syntax in translation files:
|
|
@@ -535,40 +593,78 @@ Interpolation uses `{{key}}` syntax in translation files:
|
|
|
535
593
|
{ "welcome": "Welcome, {{name}}!" }
|
|
536
594
|
```
|
|
537
595
|
|
|
596
|
+
The `i18nNamespaceMiddleware` automatically sets the translation namespace based on the route's module, so `RequestError` codes are automatically mapped to `{namespace}:errors.{CODE}`.
|
|
597
|
+
|
|
538
598
|
## Socket.IO
|
|
539
599
|
|
|
540
600
|
Socket handlers and middleware are auto-discovered from module directories:
|
|
541
601
|
|
|
602
|
+
```
|
|
603
|
+
src/modules/chat/socket/chat.socket.ts # Handler
|
|
604
|
+
src/modules/chat/socket/socket.middleware.ts # Middleware (optional)
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Handler
|
|
608
|
+
|
|
542
609
|
```typescript
|
|
543
|
-
|
|
610
|
+
// src/modules/chat/socket/chat.socket.ts
|
|
611
|
+
import type { SocketHandlerFn } from '@weconjs/core';
|
|
544
612
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
});
|
|
613
|
+
const chatHandler: SocketHandlerFn = (io, socket) => {
|
|
614
|
+
socket.on('message', (data) => {
|
|
615
|
+
io.emit('message', data);
|
|
616
|
+
});
|
|
617
|
+
};
|
|
549
618
|
|
|
550
|
-
|
|
551
|
-
await setupSocketIO(io, './src/modules');
|
|
619
|
+
export default chatHandler;
|
|
552
620
|
```
|
|
553
621
|
|
|
554
|
-
|
|
622
|
+
### Middleware
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// src/modules/chat/socket/socket.middleware.ts
|
|
626
|
+
import type { SocketMiddlewareFn } from '@weconjs/core';
|
|
627
|
+
|
|
628
|
+
const authMiddleware: SocketMiddlewareFn = (socket, next) => {
|
|
629
|
+
const token = socket.handshake.auth?.token;
|
|
630
|
+
if (!token) return next(new Error('Authentication required'));
|
|
631
|
+
next();
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
export default authMiddleware;
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Setup
|
|
638
|
+
|
|
639
|
+
```typescript
|
|
640
|
+
import { setupSocketIO } from '@weconjs/core';
|
|
641
|
+
|
|
642
|
+
// Full auto-discovery setup
|
|
643
|
+
const io = await setupSocketIO(httpServer, './src/modules', {
|
|
644
|
+
enabled: true,
|
|
645
|
+
path: '/ws',
|
|
646
|
+
cors: { origin: '*' },
|
|
647
|
+
});
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
When socket is enabled, the `io` instance is available on `ctx.io`.
|
|
555
651
|
|
|
556
652
|
## Context & Services
|
|
557
653
|
|
|
558
654
|
The `WeconContext` is passed to all module hooks, handlers, and middleware. It provides access to configuration, logging, and a service registry.
|
|
559
655
|
|
|
560
656
|
```typescript
|
|
561
|
-
// Register a service
|
|
562
|
-
ctx.registerService('mailer', new MailerService());
|
|
657
|
+
// Register a service (in onInit)
|
|
658
|
+
ctx.registerService('mailer', new MailerService(config));
|
|
563
659
|
|
|
564
|
-
// Retrieve a service
|
|
565
|
-
const mailer = ctx
|
|
660
|
+
// Retrieve a service (in controllers via req.ctx)
|
|
661
|
+
const mailer = req.ctx!.getService<MailerService>('mailer');
|
|
566
662
|
|
|
567
663
|
// Access module config (validated at startup)
|
|
568
664
|
const mailConfig = ctx.getModuleConfig<MailConfig>('mail');
|
|
569
665
|
|
|
570
666
|
// Update module config at runtime (re-validates against Zod schema)
|
|
571
|
-
ctx.setModuleConfig('mail', { from: 'new@example.com'
|
|
667
|
+
ctx.setModuleConfig('mail', { from: 'new@example.com' });
|
|
572
668
|
```
|
|
573
669
|
|
|
574
670
|
## Authentication
|
|
@@ -605,6 +701,33 @@ res.status(404).respond({
|
|
|
605
701
|
// → { success: false, data: null, errors: [...], meta: null }
|
|
606
702
|
```
|
|
607
703
|
|
|
704
|
+
### RequestError
|
|
705
|
+
|
|
706
|
+
Throw structured errors that integrate with i18n:
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
import { RequestError } from '@weconjs/core';
|
|
710
|
+
|
|
711
|
+
throw new RequestError('User not found', {
|
|
712
|
+
code: 'USER_NOT_FOUND', // Maps to i18n key: {namespace}:errors.USER_NOT_FOUND
|
|
713
|
+
status: 404,
|
|
714
|
+
details: { id: userId },
|
|
715
|
+
});
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
## DevTools
|
|
719
|
+
|
|
720
|
+
Built-in development tools for module and route introspection:
|
|
721
|
+
|
|
722
|
+
```typescript
|
|
723
|
+
import { createDevToolsRouter } from '@weconjs/core';
|
|
724
|
+
|
|
725
|
+
const devRouter = createDevToolsRouter({ modules, wecon });
|
|
726
|
+
app.use('/_dev', devRouter);
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
Provides endpoints for listing modules (with priority, config) and inspecting routes.
|
|
730
|
+
|
|
608
731
|
## Server Factory
|
|
609
732
|
|
|
610
733
|
`createWecon` is the main entry point. It wires together all framework features and returns a `WeconApp` instance:
|
|
@@ -616,16 +739,14 @@ const app = await createWecon({
|
|
|
616
739
|
config,
|
|
617
740
|
modules,
|
|
618
741
|
wecon, // Wecon routing instance (optional)
|
|
619
|
-
|
|
742
|
+
apiPrefix: '/api/v1', // API prefix for middleware/routing
|
|
743
|
+
middlewares: [cors(), helmet()], // Custom Express middleware
|
|
620
744
|
database: { enabled: true, uri: '...' },
|
|
621
|
-
plugins: { fieldShield: { strict: true } },
|
|
622
745
|
i18n: { enabled: true, modulesDir: './src/modules' },
|
|
623
746
|
logger: { useWinston: true, enableFile: true, logDir: './logs' },
|
|
624
|
-
moduleDeps: { autoInstall: true, paths: { auth: './src/modules/auth' } },
|
|
625
747
|
hooks: {
|
|
626
748
|
onBoot: async (ctx) => { /* before server starts */ },
|
|
627
749
|
onShutdown: async (ctx) => { /* cleanup */ },
|
|
628
|
-
onModuleInit: async (module, ctx) => { /* after each module init */ },
|
|
629
750
|
},
|
|
630
751
|
});
|
|
631
752
|
|
|
@@ -654,9 +775,10 @@ Features included automatically:
|
|
|
654
775
|
|
|
655
776
|
| Export | Description |
|
|
656
777
|
|--------|-------------|
|
|
657
|
-
| `defineModule(definition)` | Define a module with routes and lifecycle hooks |
|
|
658
|
-
| `loadModule(path)` | Load a module from file path |
|
|
659
|
-
| `resolveModuleDependencies(modules)` | Sort modules by
|
|
778
|
+
| `defineModule(definition)` | Define a module with routes, config, and lifecycle hooks |
|
|
779
|
+
| `loadModule(path, baseDir)` | Load a module from file path with socket discovery |
|
|
780
|
+
| `resolveModuleDependencies(modules)` | Sort modules by priority (lower first) |
|
|
781
|
+
| `resolveModuleConfigs(modules)` | Call each module's `load()` and validate with Zod schema |
|
|
660
782
|
| `readModulePackageJson(path)` | Read a module's package.json |
|
|
661
783
|
| `checkModuleDeps(path, rootDir)` | Check if module dependencies are installed |
|
|
662
784
|
| `installModuleDeps(path, rootDir)` | Install missing module dependencies |
|
|
@@ -677,8 +799,11 @@ Features included automatically:
|
|
|
677
799
|
| `Route` | Single endpoint definition (method, path, RAI, roles, middlewares) |
|
|
678
800
|
| `Routes` | Hierarchical route group with prefix, middleware, and params |
|
|
679
801
|
| `RoutesParam` | Route parameter definition with validation |
|
|
802
|
+
| `PostmanRoute` | Postman request metadata (name, description, body) |
|
|
803
|
+
| `PostmanGroup` | Postman folder grouping |
|
|
680
804
|
| `RaiMatcher` | RAI resolution engine (maps request path + method to a RAI) |
|
|
681
805
|
| `ErrorCatcher` | Base class for configuration error reporting |
|
|
806
|
+
| `PostmanGenerator` | Generates Postman Collection v2.1.0 + Environment files |
|
|
682
807
|
|
|
683
808
|
### Database
|
|
684
809
|
|
|
@@ -699,19 +824,23 @@ Features included automatically:
|
|
|
699
824
|
|
|
700
825
|
| Export | Description |
|
|
701
826
|
|--------|-------------|
|
|
827
|
+
| `initializeI18n(options)` | Initialize i18n system |
|
|
702
828
|
| `initI18n(modulesDir, defaultLocale)` | Initialize i18n and return Express middleware |
|
|
703
|
-
| `
|
|
704
|
-
| `
|
|
829
|
+
| `i18nNamespaceMiddleware` | Middleware that sets i18n namespace from route module |
|
|
830
|
+
| `getI18n()` | Get the i18next instance |
|
|
831
|
+
| `translate(key, options?)` | Translate a key programmatically |
|
|
705
832
|
|
|
706
833
|
### Socket.IO
|
|
707
834
|
|
|
708
835
|
| Export | Description |
|
|
709
836
|
|--------|-------------|
|
|
710
837
|
| `createSocketServer(httpServer, options)` | Create Socket.IO server |
|
|
711
|
-
| `setupSocketIO(
|
|
712
|
-
| `initializeSocket(
|
|
713
|
-
| `
|
|
714
|
-
| `
|
|
838
|
+
| `setupSocketIO(httpServer, modulesDir, options)` | Full auto-discovery setup |
|
|
839
|
+
| `initializeSocket(io, handlers, middleware)` | Wire handlers and middleware to io |
|
|
840
|
+
| `discoverSocketHandlersFromModules(modulesDir)` | Find all socket handler files |
|
|
841
|
+
| `discoverSocketMiddlewareFromModules(modulesDir)` | Find all socket middleware files |
|
|
842
|
+
| `discoverSocketHandlers(modulePath)` | Find handlers in a single module |
|
|
843
|
+
| `discoverSocketMiddleware(modulePath)` | Find middleware in a single module |
|
|
715
844
|
|
|
716
845
|
### Context
|
|
717
846
|
|
|
@@ -720,12 +849,52 @@ Features included automatically:
|
|
|
720
849
|
| `createContext(options)` | Create application context with service registry |
|
|
721
850
|
| `createLogger(options)` | Create a logger instance |
|
|
722
851
|
|
|
852
|
+
### DevTools
|
|
853
|
+
|
|
854
|
+
| Export | Description |
|
|
855
|
+
|--------|-------------|
|
|
856
|
+
| `createDevToolsRouter(options)` | Create Express router for module/route introspection |
|
|
857
|
+
|
|
723
858
|
### Errors
|
|
724
859
|
|
|
725
860
|
| Export | Description |
|
|
726
861
|
|--------|-------------|
|
|
727
862
|
| `ConfigError` | Configuration error with code and metadata |
|
|
728
|
-
| `RequestError` | Request error with code and metadata |
|
|
863
|
+
| `RequestError` | Request error with code, status, and metadata |
|
|
864
|
+
|
|
865
|
+
### Types
|
|
866
|
+
|
|
867
|
+
Key TypeScript types available for import:
|
|
868
|
+
|
|
869
|
+
```typescript
|
|
870
|
+
import type {
|
|
871
|
+
// Config
|
|
872
|
+
WeconConfig, ResolvedConfig, AppConfig, DatabaseConfig,
|
|
873
|
+
LoggingConfig, HttpsConfig, SocketConfig, FeaturesConfig,
|
|
874
|
+
|
|
875
|
+
// Modules
|
|
876
|
+
ModuleDefinition, ModuleConfigDefinition, WeconModule,
|
|
877
|
+
|
|
878
|
+
// Routing
|
|
879
|
+
RouteConfig, RoutesConfig, RAI, WeconDevConfig, WeconPostmanConfig,
|
|
880
|
+
|
|
881
|
+
// Context
|
|
882
|
+
WeconContext, WeconLogger, WeconServices,
|
|
883
|
+
|
|
884
|
+
// Socket
|
|
885
|
+
SocketHandler, SocketMiddleware, SocketHandlerFn, SocketMiddlewareFn,
|
|
886
|
+
SocketServer, SocketInstance, DiscoveredSocketHandler, SocketOptions,
|
|
887
|
+
|
|
888
|
+
// Auth & Request
|
|
889
|
+
Authenticable, WeconRequest, WeconResponse, RouteHandler, WeconMiddleware,
|
|
890
|
+
|
|
891
|
+
// Server
|
|
892
|
+
CreateWeconOptions, WeconApp, ApiError, ApiResponse, RespondOptions,
|
|
893
|
+
|
|
894
|
+
// Postman
|
|
895
|
+
PostmanGeneratorConfig, PostmanCollectionConfig,
|
|
896
|
+
} from '@weconjs/core';
|
|
897
|
+
```
|
|
729
898
|
|
|
730
899
|
## Testing
|
|
731
900
|
|