@morojs/moro 1.3.0 → 1.4.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 +61 -7
- package/dist/core/config/types.d.ts +147 -0
- package/dist/core/config/types.js +124 -0
- package/dist/core/config/types.js.map +1 -0
- package/dist/core/config/typescript-loader.d.ts +6 -0
- package/dist/core/config/typescript-loader.js +268 -0
- package/dist/core/config/typescript-loader.js.map +1 -0
- package/dist/core/config/validation.d.ts +18 -0
- package/dist/core/config/validation.js +134 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/docs/openapi-generator.js +6 -6
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/schema-to-openapi.d.ts +7 -0
- package/dist/core/docs/schema-to-openapi.js +124 -0
- package/dist/core/docs/schema-to-openapi.js.map +1 -0
- package/dist/core/docs/zod-to-openapi.d.ts +2 -0
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/framework.d.ts +29 -6
- package/dist/core/framework.js +117 -18
- package/dist/core/framework.js.map +1 -1
- package/dist/core/networking/adapters/index.d.ts +3 -0
- package/dist/core/networking/adapters/index.js +10 -0
- package/dist/core/networking/adapters/index.js.map +1 -0
- package/dist/core/networking/adapters/socketio-adapter.d.ts +16 -0
- package/dist/core/networking/adapters/socketio-adapter.js +244 -0
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -0
- package/dist/core/networking/adapters/ws-adapter.d.ts +54 -0
- package/dist/core/networking/adapters/ws-adapter.js +383 -0
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -0
- package/dist/core/networking/websocket-adapter.d.ts +171 -0
- package/dist/core/networking/websocket-adapter.js +5 -0
- package/dist/core/networking/websocket-adapter.js.map +1 -0
- package/dist/core/networking/websocket-manager.d.ts +53 -17
- package/dist/core/networking/websocket-manager.js +166 -108
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/index.d.ts +13 -13
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/validation/adapters.d.ts +51 -0
- package/dist/core/validation/adapters.js +135 -0
- package/dist/core/validation/adapters.js.map +1 -0
- package/dist/core/validation/index.d.ts +14 -11
- package/dist/core/validation/index.js +37 -26
- package/dist/core/validation/index.js.map +1 -1
- package/dist/core/validation/schema-interface.d.ts +36 -0
- package/dist/core/validation/schema-interface.js +68 -0
- package/dist/core/validation/schema-interface.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/moro.js +8 -2
- package/dist/moro.js.map +1 -1
- package/package.json +31 -7
- package/src/core/config/types.ts +277 -0
- package/src/core/config/typescript-loader.ts +571 -0
- package/src/core/config/validation.ts +145 -0
- package/src/core/docs/openapi-generator.ts +7 -6
- package/src/core/docs/schema-to-openapi.ts +148 -0
- package/src/core/docs/zod-to-openapi.ts +2 -0
- package/src/core/framework.ts +121 -28
- package/src/core/networking/adapters/index.ts +16 -0
- package/src/core/networking/adapters/socketio-adapter.ts +252 -0
- package/src/core/networking/adapters/ws-adapter.ts +425 -0
- package/src/core/networking/websocket-adapter.ts +217 -0
- package/src/core/networking/websocket-manager.ts +185 -127
- package/src/core/routing/index.ts +13 -13
- package/src/core/validation/adapters.ts +147 -0
- package/src/core/validation/index.ts +60 -38
- package/src/core/validation/schema-interface.ts +100 -0
- package/src/index.ts +25 -2
- package/src/moro.ts +11 -2
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Validation Library Adapters for Moro Framework
|
|
2
|
+
// Makes Joi, Yup, and other libraries compatible with ValidationSchema interface
|
|
3
|
+
|
|
4
|
+
import { ValidationSchema, ValidationError, normalizeValidationError } from './schema-interface';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Zod Compatibility Check
|
|
8
|
+
* Zod ALREADY implements ValidationSchema interface natively!
|
|
9
|
+
* No adapter needed - it just works.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Joi Adapter - makes Joi schemas compatible with ValidationSchema
|
|
14
|
+
*/
|
|
15
|
+
export class JoiAdapter<T = any> implements ValidationSchema<T> {
|
|
16
|
+
constructor(private joiSchema: any) {
|
|
17
|
+
if (!joiSchema || typeof joiSchema.validateAsync !== 'function') {
|
|
18
|
+
throw new Error('Invalid Joi schema provided to JoiAdapter');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async parseAsync(data: unknown): Promise<T> {
|
|
23
|
+
try {
|
|
24
|
+
const result = await this.joiSchema.validateAsync(data, { abortEarly: false });
|
|
25
|
+
return result as T;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
throw normalizeValidationError(error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Yup Adapter - makes Yup schemas compatible with ValidationSchema
|
|
34
|
+
*/
|
|
35
|
+
export class YupAdapter<T = any> implements ValidationSchema<T> {
|
|
36
|
+
constructor(private yupSchema: any) {
|
|
37
|
+
if (!yupSchema || typeof yupSchema.validate !== 'function') {
|
|
38
|
+
throw new Error('Invalid Yup schema provided to YupAdapter');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async parseAsync(data: unknown): Promise<T> {
|
|
43
|
+
try {
|
|
44
|
+
const result = await this.yupSchema.validate(data, { abortEarly: false });
|
|
45
|
+
return result as T;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw normalizeValidationError(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Custom Validation Function Adapter
|
|
54
|
+
* Allows users to use simple validation functions
|
|
55
|
+
*/
|
|
56
|
+
export class FunctionAdapter<T = any> implements ValidationSchema<T> {
|
|
57
|
+
constructor(
|
|
58
|
+
private validateFn: (data: unknown) => T | Promise<T>,
|
|
59
|
+
private name: string = 'custom'
|
|
60
|
+
) {
|
|
61
|
+
if (typeof validateFn !== 'function') {
|
|
62
|
+
throw new Error('Validation function is required for FunctionAdapter');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async parseAsync(data: unknown): Promise<T> {
|
|
67
|
+
try {
|
|
68
|
+
return await this.validateFn(data);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
throw new ValidationError([
|
|
71
|
+
{
|
|
72
|
+
path: [],
|
|
73
|
+
message: error instanceof Error ? error.message : String(error),
|
|
74
|
+
code: this.name,
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Class Validator Adapter (for TypeScript decorators)
|
|
83
|
+
*/
|
|
84
|
+
export class ClassValidatorAdapter<T extends object = any> implements ValidationSchema<T> {
|
|
85
|
+
constructor(
|
|
86
|
+
private ClassType: new () => T,
|
|
87
|
+
private validate?: (obj: any) => Promise<any[]>
|
|
88
|
+
) {
|
|
89
|
+
if (typeof ClassType !== 'function') {
|
|
90
|
+
throw new Error('Class constructor is required for ClassValidatorAdapter');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async parseAsync(data: unknown): Promise<T> {
|
|
95
|
+
try {
|
|
96
|
+
const instance = Object.assign(new this.ClassType(), data as Record<string, any>);
|
|
97
|
+
|
|
98
|
+
if (this.validate) {
|
|
99
|
+
const errors = await this.validate(instance);
|
|
100
|
+
if (errors && errors.length > 0) {
|
|
101
|
+
throw new ValidationError(
|
|
102
|
+
errors.map((error: any, index: number) => ({
|
|
103
|
+
path: error.property ? [error.property] : [index],
|
|
104
|
+
message: Object.values(error.constraints || {}).join(', ') || 'Validation failed',
|
|
105
|
+
code: 'class_validator',
|
|
106
|
+
}))
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return instance as T;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
if (error instanceof ValidationError) throw error;
|
|
114
|
+
throw normalizeValidationError(error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Utility functions for creating adapters
|
|
121
|
+
*/
|
|
122
|
+
export function joi<T = any>(joiSchema: any): ValidationSchema<T> {
|
|
123
|
+
return new JoiAdapter<T>(joiSchema);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function yup<T = any>(yupSchema: any): ValidationSchema<T> {
|
|
127
|
+
return new YupAdapter<T>(yupSchema);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function fn<T = any>(
|
|
131
|
+
validateFn: (data: unknown) => T | Promise<T>,
|
|
132
|
+
name?: string
|
|
133
|
+
): ValidationSchema<T> {
|
|
134
|
+
return new FunctionAdapter<T>(validateFn, name);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function classValidator<T extends object = any>(
|
|
138
|
+
ClassType: new () => T,
|
|
139
|
+
validate?: (obj: any) => Promise<any[]>
|
|
140
|
+
): ValidationSchema<T> {
|
|
141
|
+
return new ClassValidatorAdapter<T>(ClassType, validate);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Type helpers
|
|
145
|
+
export type JoiSchema<T> = ValidationSchema<T>;
|
|
146
|
+
export type YupSchema<T> = ValidationSchema<T>;
|
|
147
|
+
export type CustomValidator<T> = ValidationSchema<T>;
|
|
@@ -1,28 +1,41 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Universal Validation System for Moro Framework
|
|
2
|
+
// Works with Zod, Joi, Yup, and any validation library via adapters
|
|
3
3
|
|
|
4
|
-
import { z, ZodSchema, ZodError } from 'zod';
|
|
5
4
|
import { HttpRequest, HttpResponse } from '../http';
|
|
6
5
|
import { createFrameworkLogger } from '../logger';
|
|
6
|
+
import {
|
|
7
|
+
ValidationSchema,
|
|
8
|
+
ValidationError,
|
|
9
|
+
normalizeValidationError,
|
|
10
|
+
InferSchemaType,
|
|
11
|
+
} from './schema-interface';
|
|
12
|
+
|
|
13
|
+
// Re-export zod if available (for backward compatibility)
|
|
14
|
+
let z: any;
|
|
15
|
+
try {
|
|
16
|
+
z = require('zod').z;
|
|
17
|
+
} catch {
|
|
18
|
+
// Zod not available - that's fine!
|
|
19
|
+
}
|
|
7
20
|
|
|
8
21
|
const logger = createFrameworkLogger('Validation');
|
|
9
22
|
|
|
10
|
-
//
|
|
23
|
+
// Universal validation configuration interface
|
|
11
24
|
export interface ValidationConfig {
|
|
12
|
-
body?:
|
|
13
|
-
query?:
|
|
14
|
-
params?:
|
|
15
|
-
headers?:
|
|
25
|
+
body?: ValidationSchema;
|
|
26
|
+
query?: ValidationSchema;
|
|
27
|
+
params?: ValidationSchema;
|
|
28
|
+
headers?: ValidationSchema;
|
|
16
29
|
}
|
|
17
30
|
|
|
18
31
|
// Validation result types
|
|
19
32
|
export interface ValidationResult<T = any> {
|
|
20
33
|
success: boolean;
|
|
21
34
|
data?: T;
|
|
22
|
-
errors?:
|
|
35
|
+
errors?: ValidationErrorDetail[];
|
|
23
36
|
}
|
|
24
37
|
|
|
25
|
-
export interface
|
|
38
|
+
export interface ValidationErrorDetail {
|
|
26
39
|
field: string;
|
|
27
40
|
message: string;
|
|
28
41
|
code: string;
|
|
@@ -110,9 +123,9 @@ export function validate<TBody = any, TQuery = any, TParams = any>(
|
|
|
110
123
|
};
|
|
111
124
|
}
|
|
112
125
|
|
|
113
|
-
// Validate individual field
|
|
126
|
+
// Validate individual field using universal schema interface
|
|
114
127
|
async function validateField(
|
|
115
|
-
schema:
|
|
128
|
+
schema: ValidationSchema,
|
|
116
129
|
data: any,
|
|
117
130
|
fieldName: string
|
|
118
131
|
): Promise<ValidationResult> {
|
|
@@ -123,32 +136,32 @@ async function validateField(
|
|
|
123
136
|
data: validated,
|
|
124
137
|
};
|
|
125
138
|
} catch (error) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return {
|
|
140
|
-
success: false,
|
|
141
|
-
errors,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
139
|
+
const normalizedError = normalizeValidationError(error);
|
|
140
|
+
const errors: ValidationErrorDetail[] = normalizedError.issues.map(issue => ({
|
|
141
|
+
field: issue.path.length > 0 ? issue.path.join('.') : fieldName,
|
|
142
|
+
message: issue.message,
|
|
143
|
+
code: issue.code,
|
|
144
|
+
}));
|
|
145
|
+
|
|
146
|
+
logger.debug('Field validation failed', 'ValidationFailed', {
|
|
147
|
+
field: fieldName,
|
|
148
|
+
errors: errors.length,
|
|
149
|
+
details: errors,
|
|
150
|
+
});
|
|
144
151
|
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
return {
|
|
153
|
+
success: false,
|
|
154
|
+
errors,
|
|
155
|
+
};
|
|
147
156
|
}
|
|
148
157
|
}
|
|
149
158
|
|
|
150
159
|
// Send validation error response
|
|
151
|
-
function sendValidationError(
|
|
160
|
+
function sendValidationError(
|
|
161
|
+
res: HttpResponse,
|
|
162
|
+
errors: ValidationErrorDetail[],
|
|
163
|
+
field: string
|
|
164
|
+
): void {
|
|
152
165
|
logger.debug('Sending validation error response', 'ValidationResponse', {
|
|
153
166
|
field,
|
|
154
167
|
errorCount: errors.length,
|
|
@@ -163,19 +176,19 @@ function sendValidationError(res: HttpResponse, errors: ValidationError[], field
|
|
|
163
176
|
}
|
|
164
177
|
|
|
165
178
|
// Convenience functions for single-field validation
|
|
166
|
-
export function body<T>(schema:
|
|
179
|
+
export function body<T>(schema: ValidationSchema<T>) {
|
|
167
180
|
return (handler: (req: ValidatedRequest<T>, res: HttpResponse) => any | Promise<any>) => {
|
|
168
181
|
return validate({ body: schema }, handler);
|
|
169
182
|
};
|
|
170
183
|
}
|
|
171
184
|
|
|
172
|
-
export function query<T>(schema:
|
|
185
|
+
export function query<T>(schema: ValidationSchema<T>) {
|
|
173
186
|
return (handler: (req: ValidatedRequest<any>, res: HttpResponse) => any | Promise<any>) => {
|
|
174
187
|
return validate({ query: schema }, handler);
|
|
175
188
|
};
|
|
176
189
|
}
|
|
177
190
|
|
|
178
|
-
export function params<T>(schema:
|
|
191
|
+
export function params<T>(schema: ValidationSchema<T>) {
|
|
179
192
|
return (handler: (req: ValidatedRequest<any>, res: HttpResponse) => any | Promise<any>) => {
|
|
180
193
|
return validate({ params: schema }, handler);
|
|
181
194
|
};
|
|
@@ -186,5 +199,14 @@ export function combineSchemas(schemas: ValidationConfig): ValidationConfig {
|
|
|
186
199
|
return schemas;
|
|
187
200
|
}
|
|
188
201
|
|
|
189
|
-
// Re-export
|
|
190
|
-
export {
|
|
202
|
+
// Re-export common validation tools
|
|
203
|
+
export {
|
|
204
|
+
ValidationSchema,
|
|
205
|
+
ValidationError,
|
|
206
|
+
normalizeValidationError,
|
|
207
|
+
InferSchemaType,
|
|
208
|
+
} from './schema-interface';
|
|
209
|
+
export { joi, yup, fn as customValidator, classValidator } from './adapters';
|
|
210
|
+
|
|
211
|
+
// Re-export Zod if available (optional dependency)
|
|
212
|
+
export { z };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Universal Validation Schema Interface for Moro Framework
|
|
2
|
+
// Allows Zod, Joi, Yup, and other validation libraries to work seamlessly
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Standard validation error structure
|
|
6
|
+
*/
|
|
7
|
+
export interface ValidationIssue {
|
|
8
|
+
path: (string | number)[];
|
|
9
|
+
message: string;
|
|
10
|
+
code: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Standard validation error class
|
|
15
|
+
* Compatible with ZodError structure
|
|
16
|
+
*/
|
|
17
|
+
export class ValidationError extends Error {
|
|
18
|
+
public readonly issues: ValidationIssue[];
|
|
19
|
+
|
|
20
|
+
constructor(issues: ValidationIssue[]) {
|
|
21
|
+
const message = `Validation failed: ${issues.map(i => i.message).join(', ')}`;
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'ValidationError';
|
|
24
|
+
this.issues = issues;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Universal validation schema interface
|
|
30
|
+
* This is what Zod naturally implements! No breaking changes needed.
|
|
31
|
+
*/
|
|
32
|
+
export interface ValidationSchema<T = any> {
|
|
33
|
+
/**
|
|
34
|
+
* Parse data asynchronously and return validated result
|
|
35
|
+
* Throws ValidationError on validation failure
|
|
36
|
+
*/
|
|
37
|
+
parseAsync(data: unknown): Promise<T>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if an object implements the ValidationSchema interface
|
|
42
|
+
*/
|
|
43
|
+
export function isValidationSchema(obj: any): obj is ValidationSchema {
|
|
44
|
+
return obj && typeof obj.parseAsync === 'function';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convert various error formats to our standard ValidationError
|
|
49
|
+
*/
|
|
50
|
+
export function normalizeValidationError(error: any): ValidationError {
|
|
51
|
+
// Already our format
|
|
52
|
+
if (error instanceof ValidationError) {
|
|
53
|
+
return error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Zod error format
|
|
57
|
+
if (error && error.issues && Array.isArray(error.issues)) {
|
|
58
|
+
return new ValidationError(
|
|
59
|
+
error.issues.map((issue: any) => ({
|
|
60
|
+
path: issue.path || [],
|
|
61
|
+
message: issue.message || 'Validation failed',
|
|
62
|
+
code: issue.code || 'invalid',
|
|
63
|
+
}))
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Joi error format
|
|
68
|
+
if (error && error.details && Array.isArray(error.details)) {
|
|
69
|
+
return new ValidationError(
|
|
70
|
+
error.details.map((detail: any) => ({
|
|
71
|
+
path: detail.path || [],
|
|
72
|
+
message: detail.message || 'Validation failed',
|
|
73
|
+
code: detail.type || 'invalid',
|
|
74
|
+
}))
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Yup error format
|
|
79
|
+
if (error && error.errors && Array.isArray(error.errors)) {
|
|
80
|
+
return new ValidationError(
|
|
81
|
+
error.errors.map((msg: string, index: number) => ({
|
|
82
|
+
path: error.path ? [error.path] : [index],
|
|
83
|
+
message: msg,
|
|
84
|
+
code: error.type || 'invalid',
|
|
85
|
+
}))
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Generic error
|
|
90
|
+
return new ValidationError([
|
|
91
|
+
{
|
|
92
|
+
path: [],
|
|
93
|
+
message: error.message || String(error),
|
|
94
|
+
code: 'unknown',
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Type helper for inferring types from validation schemas
|
|
100
|
+
export type InferSchemaType<T> = T extends ValidationSchema<infer U> ? U : never;
|
package/src/index.ts
CHANGED
|
@@ -105,15 +105,24 @@ export type {
|
|
|
105
105
|
// Logger System
|
|
106
106
|
export { createFrameworkLogger, logger } from './core/logger';
|
|
107
107
|
|
|
108
|
-
// Validation System
|
|
108
|
+
// Universal Validation System
|
|
109
109
|
export { validate, body, query, params, combineSchemas, z } from './core/validation';
|
|
110
110
|
export type {
|
|
111
111
|
ValidationConfig,
|
|
112
112
|
ValidationResult,
|
|
113
|
-
|
|
113
|
+
ValidationErrorDetail,
|
|
114
114
|
ValidatedRequest,
|
|
115
115
|
} from './core/validation';
|
|
116
116
|
|
|
117
|
+
// Universal Validation Interfaces and Adapters
|
|
118
|
+
export type {
|
|
119
|
+
ValidationSchema,
|
|
120
|
+
ValidationError,
|
|
121
|
+
InferSchemaType,
|
|
122
|
+
} from './core/validation/schema-interface';
|
|
123
|
+
export { normalizeValidationError } from './core/validation/schema-interface';
|
|
124
|
+
export { joi, yup, fn as customValidator, classValidator } from './core/validation/adapters';
|
|
125
|
+
|
|
117
126
|
// Module System
|
|
118
127
|
export {
|
|
119
128
|
defineModule,
|
|
@@ -123,6 +132,20 @@ export {
|
|
|
123
132
|
} from './core/modules';
|
|
124
133
|
export type { ModuleDefinition, ModuleRoute, ModuleSocket, ModuleConfig } from './types/module';
|
|
125
134
|
|
|
135
|
+
// WebSocket Adapter System
|
|
136
|
+
export type {
|
|
137
|
+
WebSocketAdapter,
|
|
138
|
+
WebSocketAdapterOptions,
|
|
139
|
+
WebSocketNamespace,
|
|
140
|
+
WebSocketConnection,
|
|
141
|
+
WebSocketEmitter,
|
|
142
|
+
WebSocketMiddleware,
|
|
143
|
+
WebSocketEventHandler,
|
|
144
|
+
} from './core/networking/websocket-adapter';
|
|
145
|
+
|
|
146
|
+
// Built-in WebSocket Adapters
|
|
147
|
+
export { SocketIOAdapter, WSAdapter } from './core/networking/adapters';
|
|
148
|
+
|
|
126
149
|
// Intelligent Routing System
|
|
127
150
|
export { createRoute, defineRoute, EXECUTION_PHASES } from './core/routing';
|
|
128
151
|
export { IntelligentRoutingManager, RouteRegistry } from './core/routing/app-integration';
|
package/src/moro.ts
CHANGED
|
@@ -387,10 +387,19 @@ export class Moro extends EventEmitter {
|
|
|
387
387
|
|
|
388
388
|
// WebSocket helper with events
|
|
389
389
|
websocket(namespace: string, handlers: Record<string, Function>) {
|
|
390
|
+
const adapter = this.coreFramework.getWebSocketAdapter();
|
|
391
|
+
if (!adapter) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
'WebSocket features require a WebSocket adapter. Install socket.io or configure an adapter:\n' +
|
|
394
|
+
'npm install socket.io\n' +
|
|
395
|
+
'or\n' +
|
|
396
|
+
'new Moro({ websocket: { adapter: new SocketIOAdapter() } })'
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
390
400
|
this.emit('websocket:registering', { namespace, handlers });
|
|
391
401
|
|
|
392
|
-
const
|
|
393
|
-
const ns = io.of(namespace);
|
|
402
|
+
const ns = adapter.createNamespace(namespace);
|
|
394
403
|
|
|
395
404
|
Object.entries(handlers).forEach(([event, handler]) => {
|
|
396
405
|
ns.on('connection', socket => {
|