@coherent.js/api 1.0.0-beta.5 → 1.0.0-beta.6
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/dist/index.cjs +45 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +45 -1
- package/dist/index.js.map +2 -2
- package/package.json +3 -3
- package/types/index.d.ts +188 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/api",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.6",
|
|
4
4
|
"description": "API framework for Coherent.js (REST/RPC/GraphQL).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"url": "git+https://github.com/Tomdrouv1/coherent.js.git"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@coherent.js/core": "1.0.0-beta.
|
|
50
|
+
"@coherent.js/core": "1.0.0-beta.6"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@coherent.js/state": "1.0.0-beta.
|
|
53
|
+
"@coherent.js/state": "1.0.0-beta.6"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public",
|
package/types/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
9
|
+
import { CoherentNode, RenderOptions } from '@coherent.js/core';
|
|
9
10
|
|
|
10
11
|
// ============================================================================
|
|
11
12
|
// HTTP Types
|
|
@@ -99,18 +100,23 @@ export interface ApiResponse extends ServerResponse {
|
|
|
99
100
|
redirect(url: string): void;
|
|
100
101
|
vary(field: string): ApiResponse;
|
|
101
102
|
render(view: string, locals?: any, callback?: Function): void;
|
|
103
|
+
/** Render a CoherentNode component to HTML */
|
|
104
|
+
renderCoherent(component: CoherentNode, options?: RenderOptions): void;
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
// ============================================================================
|
|
105
108
|
// Route Handler Types
|
|
106
109
|
// ============================================================================
|
|
107
110
|
|
|
108
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Route handler function.
|
|
113
|
+
* Can return void, Promise<void>, JSON-serializable data, or a CoherentNode for rendering.
|
|
114
|
+
*/
|
|
109
115
|
export type RouteHandler = (
|
|
110
116
|
req: ApiRequest,
|
|
111
117
|
res: ApiResponse,
|
|
112
118
|
next?: NextFunction
|
|
113
|
-
) => void | Promise<void> | any;
|
|
119
|
+
) => void | Promise<void> | CoherentNode | Promise<CoherentNode> | any;
|
|
114
120
|
|
|
115
121
|
/** Next function for middleware */
|
|
116
122
|
export interface NextFunction {
|
|
@@ -186,47 +192,142 @@ export interface ObjectRouter {
|
|
|
186
192
|
// Validation
|
|
187
193
|
// ============================================================================
|
|
188
194
|
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Primitive validation types.
|
|
197
|
+
*/
|
|
198
|
+
export type ValidationPrimitiveType = 'string' | 'number' | 'boolean' | 'date';
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Compound validation types.
|
|
202
|
+
*/
|
|
203
|
+
export type ValidationCompoundType = 'array' | 'object';
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* String format validation types.
|
|
207
|
+
*/
|
|
208
|
+
export type ValidationFormatType = 'email' | 'url' | 'uuid' | 'phone' | 'credit-card';
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* All supported validation types.
|
|
212
|
+
*/
|
|
213
|
+
export type ValidationType = ValidationPrimitiveType | ValidationCompoundType | ValidationFormatType;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Field validation rule.
|
|
217
|
+
* Defines constraints for validating a single field.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const emailRule: ValidationRule = {
|
|
222
|
+
* type: 'email',
|
|
223
|
+
* required: true,
|
|
224
|
+
* message: 'Please provide a valid email address'
|
|
225
|
+
* };
|
|
226
|
+
*
|
|
227
|
+
* const ageRule: ValidationRule<number> = {
|
|
228
|
+
* type: 'number',
|
|
229
|
+
* min: 0,
|
|
230
|
+
* max: 150,
|
|
231
|
+
* custom: (value) => value >= 18 || 'Must be 18 or older'
|
|
232
|
+
* };
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export interface ValidationRule<T = any> {
|
|
236
|
+
/** The expected type of the field value */
|
|
237
|
+
type?: ValidationType;
|
|
238
|
+
/** Whether the field is required */
|
|
192
239
|
required?: boolean;
|
|
240
|
+
/** Minimum value (for numbers) or minimum length (for strings/arrays) */
|
|
193
241
|
min?: number;
|
|
242
|
+
/** Maximum value (for numbers) or maximum length (for strings/arrays) */
|
|
194
243
|
max?: number;
|
|
244
|
+
/** Minimum string length */
|
|
195
245
|
minLength?: number;
|
|
246
|
+
/** Maximum string length */
|
|
196
247
|
maxLength?: number;
|
|
248
|
+
/** Regex pattern for string validation */
|
|
197
249
|
pattern?: RegExp | string;
|
|
198
|
-
|
|
199
|
-
|
|
250
|
+
/** Array of allowed values */
|
|
251
|
+
enum?: T[];
|
|
252
|
+
/**
|
|
253
|
+
* Custom validation function.
|
|
254
|
+
* Return true for valid, false or string message for invalid.
|
|
255
|
+
*/
|
|
256
|
+
custom?: (value: T, field: string, data: Record<string, any>) => boolean | string;
|
|
257
|
+
/** Custom error message */
|
|
200
258
|
message?: string;
|
|
201
|
-
|
|
259
|
+
/** Transform function applied before validation */
|
|
260
|
+
transform?: (value: any) => T;
|
|
261
|
+
/** Default value if field is missing */
|
|
262
|
+
default?: T | (() => T);
|
|
263
|
+
/** Validation for array items (when type is 'array') */
|
|
264
|
+
items?: ValidationRule;
|
|
265
|
+
/** Validation for object properties (when type is 'object') */
|
|
266
|
+
properties?: ValidationSchema;
|
|
267
|
+
/** Allow null values */
|
|
268
|
+
nullable?: boolean;
|
|
269
|
+
/** Trim whitespace from strings before validation */
|
|
270
|
+
trim?: boolean;
|
|
202
271
|
}
|
|
203
272
|
|
|
204
|
-
/**
|
|
273
|
+
/**
|
|
274
|
+
* Validation schema defining rules for multiple fields.
|
|
275
|
+
* Can be nested for complex object structures.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```typescript
|
|
279
|
+
* const userSchema: ValidationSchema = {
|
|
280
|
+
* email: { type: 'email', required: true },
|
|
281
|
+
* password: { type: 'string', minLength: 8, required: true },
|
|
282
|
+
* profile: {
|
|
283
|
+
* name: { type: 'string', required: true },
|
|
284
|
+
* age: { type: 'number', min: 0 }
|
|
285
|
+
* }
|
|
286
|
+
* };
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
205
289
|
export interface ValidationSchema {
|
|
206
290
|
[field: string]: ValidationRule | ValidationSchema;
|
|
207
291
|
}
|
|
208
292
|
|
|
209
|
-
/**
|
|
210
|
-
|
|
293
|
+
/**
|
|
294
|
+
* Result of validation operation.
|
|
295
|
+
* Generic type T represents the validated data shape.
|
|
296
|
+
*/
|
|
297
|
+
export interface ValidationResult<T = any> {
|
|
298
|
+
/** Whether validation passed */
|
|
211
299
|
valid: boolean;
|
|
212
|
-
errors
|
|
213
|
-
|
|
300
|
+
/** Array of validation errors (empty if valid) */
|
|
301
|
+
errors: ValidationErrorInfo[];
|
|
302
|
+
/** Validated and transformed data */
|
|
303
|
+
data: T;
|
|
214
304
|
}
|
|
215
305
|
|
|
216
|
-
/**
|
|
217
|
-
|
|
306
|
+
/**
|
|
307
|
+
* Information about a single validation error.
|
|
308
|
+
*/
|
|
309
|
+
export interface ValidationErrorInfo {
|
|
310
|
+
/** Dot-notation path to the field (e.g., 'user.email') */
|
|
218
311
|
field: string;
|
|
312
|
+
/** Human-readable error message */
|
|
219
313
|
message: string;
|
|
314
|
+
/** The invalid value */
|
|
220
315
|
value: any;
|
|
316
|
+
/** The rule that failed (e.g., 'required', 'min', 'pattern') */
|
|
221
317
|
rule: string;
|
|
222
318
|
}
|
|
223
319
|
|
|
224
320
|
/** Validation options */
|
|
225
321
|
export interface ValidationOptions {
|
|
322
|
+
/** Stop validation on first error */
|
|
226
323
|
abortEarly?: boolean;
|
|
324
|
+
/** Remove fields not in schema */
|
|
227
325
|
stripUnknown?: boolean;
|
|
326
|
+
/** Allow fields not in schema */
|
|
228
327
|
allowUnknown?: boolean;
|
|
328
|
+
/** Skip validation for missing optional fields */
|
|
229
329
|
skipMissing?: boolean;
|
|
330
|
+
/** Additional context passed to custom validators */
|
|
230
331
|
context?: any;
|
|
231
332
|
}
|
|
232
333
|
|
|
@@ -314,41 +415,72 @@ export interface SerializationOptions {
|
|
|
314
415
|
// Error Handling
|
|
315
416
|
// ============================================================================
|
|
316
417
|
|
|
317
|
-
/**
|
|
418
|
+
/**
|
|
419
|
+
* Base API error class.
|
|
420
|
+
* Extends Error with HTTP status code and error code support.
|
|
421
|
+
*/
|
|
318
422
|
export class ApiError extends Error {
|
|
319
423
|
constructor(message: string, statusCode?: number, code?: string);
|
|
424
|
+
/** HTTP status code (default: 500) */
|
|
320
425
|
statusCode: number;
|
|
426
|
+
/** Machine-readable error code */
|
|
321
427
|
code: string;
|
|
428
|
+
/** Additional error details */
|
|
322
429
|
details?: any;
|
|
323
|
-
|
|
430
|
+
/** Convert error to JSON-serializable object */
|
|
431
|
+
toJSON(): { message: string; statusCode: number; code: string; details?: any };
|
|
324
432
|
}
|
|
325
433
|
|
|
326
|
-
/**
|
|
434
|
+
/**
|
|
435
|
+
* Validation error class.
|
|
436
|
+
* Thrown when request validation fails.
|
|
437
|
+
*/
|
|
327
438
|
export class ValidationError extends ApiError {
|
|
328
|
-
constructor(message: string, errors?:
|
|
329
|
-
errors
|
|
439
|
+
constructor(message: string, errors?: ValidationErrorInfo[]);
|
|
440
|
+
/** Array of field-level validation errors */
|
|
441
|
+
errors: ValidationErrorInfo[];
|
|
330
442
|
}
|
|
331
443
|
|
|
332
|
-
/**
|
|
444
|
+
/**
|
|
445
|
+
* Authentication error class.
|
|
446
|
+
* Thrown when authentication fails (HTTP 401).
|
|
447
|
+
*/
|
|
333
448
|
export class AuthenticationError extends ApiError {
|
|
334
449
|
constructor(message?: string);
|
|
335
450
|
}
|
|
336
451
|
|
|
337
|
-
/**
|
|
452
|
+
/**
|
|
453
|
+
* Authorization error class.
|
|
454
|
+
* Thrown when user lacks required permissions (HTTP 403).
|
|
455
|
+
*/
|
|
338
456
|
export class AuthorizationError extends ApiError {
|
|
339
457
|
constructor(message?: string);
|
|
340
458
|
}
|
|
341
459
|
|
|
342
|
-
/**
|
|
460
|
+
/**
|
|
461
|
+
* Not found error class.
|
|
462
|
+
* Thrown when requested resource doesn't exist (HTTP 404).
|
|
463
|
+
*/
|
|
343
464
|
export class NotFoundError extends ApiError {
|
|
344
465
|
constructor(message?: string);
|
|
345
466
|
}
|
|
346
467
|
|
|
347
|
-
/**
|
|
468
|
+
/**
|
|
469
|
+
* Conflict error class.
|
|
470
|
+
* Thrown when operation conflicts with current state (HTTP 409).
|
|
471
|
+
*/
|
|
348
472
|
export class ConflictError extends ApiError {
|
|
349
473
|
constructor(message?: string);
|
|
350
474
|
}
|
|
351
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Bad request error class.
|
|
478
|
+
* Thrown when request is malformed (HTTP 400).
|
|
479
|
+
*/
|
|
480
|
+
export class BadRequestError extends ApiError {
|
|
481
|
+
constructor(message?: string);
|
|
482
|
+
}
|
|
483
|
+
|
|
352
484
|
/** Error handler options */
|
|
353
485
|
export interface ErrorHandlerOptions {
|
|
354
486
|
includeStack?: boolean;
|
|
@@ -616,26 +748,39 @@ export function withErrorHandling(options?: ErrorHandlerOptions): (handler: Rout
|
|
|
616
748
|
/** Create error handler middleware */
|
|
617
749
|
export function createErrorHandler(options?: ErrorHandlerOptions): ErrorMiddleware;
|
|
618
750
|
|
|
619
|
-
/**
|
|
620
|
-
|
|
751
|
+
/**
|
|
752
|
+
* Validate data against a schema.
|
|
753
|
+
* @param schema - The validation schema
|
|
754
|
+
* @param data - The data to validate
|
|
755
|
+
* @param options - Validation options
|
|
756
|
+
* @returns Validation result with valid flag, errors, and transformed data
|
|
757
|
+
*/
|
|
758
|
+
export function validateAgainstSchema<T = any>(
|
|
621
759
|
schema: ValidationSchema,
|
|
622
760
|
data: any,
|
|
623
761
|
options?: ValidationOptions
|
|
624
|
-
): ValidationResult
|
|
762
|
+
): ValidationResult<T>;
|
|
625
763
|
|
|
626
|
-
/**
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
764
|
+
/**
|
|
765
|
+
* Validate a single field against a rule.
|
|
766
|
+
* @param rule - The validation rule
|
|
767
|
+
* @param value - The value to validate
|
|
768
|
+
* @param field - The field name (for error messages)
|
|
769
|
+
* @param data - The full data object (for cross-field validation)
|
|
770
|
+
* @returns ValidationErrorInfo if invalid, null if valid
|
|
771
|
+
*/
|
|
772
|
+
export function validateField<T = any>(
|
|
773
|
+
rule: ValidationRule<T>,
|
|
774
|
+
value: T,
|
|
630
775
|
field: string,
|
|
631
|
-
data?: any
|
|
632
|
-
):
|
|
776
|
+
data?: Record<string, any>
|
|
777
|
+
): ValidationErrorInfo | null;
|
|
633
778
|
|
|
634
|
-
/** Validation middleware */
|
|
635
|
-
export function withValidation(schema: ValidationSchema): Middleware;
|
|
779
|
+
/** Validation middleware for request body */
|
|
780
|
+
export function withValidation<T = any>(schema: ValidationSchema): Middleware;
|
|
636
781
|
|
|
637
782
|
/** Query validation middleware */
|
|
638
|
-
export function withQueryValidation(schema: ValidationSchema): Middleware;
|
|
783
|
+
export function withQueryValidation<T = any>(schema: ValidationSchema): Middleware;
|
|
639
784
|
|
|
640
785
|
/** Params validation middleware */
|
|
641
786
|
export function withParamsValidation(schema: ValidationSchema): Middleware;
|
|
@@ -646,8 +791,12 @@ export function withAuth(config?: AuthConfig): Middleware;
|
|
|
646
791
|
/** Role-based authorization middleware */
|
|
647
792
|
export function withRole(roles: string | string[]): Middleware;
|
|
648
793
|
|
|
649
|
-
/** Input validation middleware */
|
|
650
|
-
export function withInputValidation(schema:
|
|
794
|
+
/** Input validation middleware (combines body, query, and params) */
|
|
795
|
+
export function withInputValidation(schema: {
|
|
796
|
+
body?: ValidationSchema;
|
|
797
|
+
query?: ValidationSchema;
|
|
798
|
+
params?: ValidationSchema;
|
|
799
|
+
}): Middleware;
|
|
651
800
|
|
|
652
801
|
/** Hash password */
|
|
653
802
|
export function hashPassword(password: string, saltRounds?: number): Promise<string>;
|
|
@@ -694,6 +843,7 @@ declare const coherentApi: {
|
|
|
694
843
|
AuthorizationError: typeof AuthorizationError;
|
|
695
844
|
NotFoundError: typeof NotFoundError;
|
|
696
845
|
ConflictError: typeof ConflictError;
|
|
846
|
+
BadRequestError: typeof BadRequestError;
|
|
697
847
|
withErrorHandling: typeof withErrorHandling;
|
|
698
848
|
createErrorHandler: typeof createErrorHandler;
|
|
699
849
|
validateAgainstSchema: typeof validateAgainstSchema;
|