@groundbrick/service-base 0.0.1
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 +713 -0
- package/dist/core/BaseService.d.ts +55 -0
- package/dist/core/BaseService.d.ts.map +1 -0
- package/dist/core/BaseService.js +123 -0
- package/dist/core/BaseService.js.map +1 -0
- package/dist/email/EmailConfigurationService.d.ts +14 -0
- package/dist/email/EmailConfigurationService.d.ts.map +1 -0
- package/dist/email/EmailConfigurationService.js +60 -0
- package/dist/email/EmailConfigurationService.js.map +1 -0
- package/dist/email/EmailService.d.ts +15 -0
- package/dist/email/EmailService.d.ts.map +1 -0
- package/dist/email/EmailService.js +96 -0
- package/dist/email/EmailService.js.map +1 -0
- package/dist/email/interfaces/EmailInterfaces.d.ts +45 -0
- package/dist/email/interfaces/EmailInterfaces.d.ts.map +1 -0
- package/dist/email/interfaces/EmailInterfaces.js +2 -0
- package/dist/email/interfaces/EmailInterfaces.js.map +1 -0
- package/dist/email/providers/SmtpEmailProvider.d.ts +14 -0
- package/dist/email/providers/SmtpEmailProvider.d.ts.map +1 -0
- package/dist/email/providers/SmtpEmailProvider.js +88 -0
- package/dist/email/providers/SmtpEmailProvider.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/types/BusinessError.d.ts +31 -0
- package/dist/types/BusinessError.d.ts.map +1 -0
- package/dist/types/BusinessError.js +57 -0
- package/dist/types/BusinessError.js.map +1 -0
- package/dist/types/ServiceOptions.d.ts +14 -0
- package/dist/types/ServiceOptions.d.ts.map +1 -0
- package/dist/types/ServiceOptions.js +2 -0
- package/dist/types/ServiceOptions.js.map +1 -0
- package/dist/types/ServiceResult.d.ts +31 -0
- package/dist/types/ServiceResult.d.ts.map +1 -0
- package/dist/types/ServiceResult.js +61 -0
- package/dist/types/ServiceResult.js.map +1 -0
- package/dist/validation/ValidationError.d.ts +14 -0
- package/dist/validation/ValidationError.d.ts.map +1 -0
- package/dist/validation/ValidationError.js +2 -0
- package/dist/validation/ValidationError.js.map +1 -0
- package/dist/validation/ValidationHelper.d.ts +70 -0
- package/dist/validation/ValidationHelper.d.ts.map +1 -0
- package/dist/validation/ValidationHelper.js +169 -0
- package/dist/validation/ValidationHelper.js.map +1 -0
- package/dist/validation/ValidationResult.d.ts +12 -0
- package/dist/validation/ValidationResult.d.ts.map +1 -0
- package/dist/validation/ValidationResult.js +2 -0
- package/dist/validation/ValidationResult.js.map +1 -0
- package/dist/validation/Validator.d.ts +35 -0
- package/dist/validation/Validator.d.ts.map +1 -0
- package/dist/validation/Validator.js +52 -0
- package/dist/validation/Validator.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business logic error with structured information
|
|
3
|
+
*/
|
|
4
|
+
export declare class BusinessError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly originalError?: Error;
|
|
7
|
+
readonly context?: Record<string, any>;
|
|
8
|
+
readonly timestamp: Date;
|
|
9
|
+
constructor(message: string, code: string, originalError?: Error, context?: Record<string, any>);
|
|
10
|
+
/**
|
|
11
|
+
* Convert to JSON for logging/API responses
|
|
12
|
+
*/
|
|
13
|
+
toJSON(): Record<string, any>;
|
|
14
|
+
/**
|
|
15
|
+
* Create user-friendly error response
|
|
16
|
+
*/
|
|
17
|
+
toUserResponse(): {
|
|
18
|
+
error: string;
|
|
19
|
+
code: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Check if error is of specific business type
|
|
24
|
+
*/
|
|
25
|
+
static isBusinessError(error: any): error is BusinessError;
|
|
26
|
+
/**
|
|
27
|
+
* Check if error has specific code
|
|
28
|
+
*/
|
|
29
|
+
hasCode(code: string): boolean;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=BusinessError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BusinessError.d.ts","sourceRoot":"","sources":["../../src/types/BusinessError.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACpC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,aAAa,CAAC,EAAE,KAAK,CAAC;IACtC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9C,SAAgB,SAAS,EAAE,IAAI,CAAC;gBAG5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,KAAK,EACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAejC;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAW7B;;OAEG;IACH,cAAc,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAQpE;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,aAAa;IAI1D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGjC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Business logic error with structured information
|
|
3
|
+
*/
|
|
4
|
+
export class BusinessError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
originalError;
|
|
7
|
+
context;
|
|
8
|
+
timestamp;
|
|
9
|
+
constructor(message, code, originalError, context) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'BusinessError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.originalError = originalError;
|
|
14
|
+
this.context = context;
|
|
15
|
+
this.timestamp = new Date();
|
|
16
|
+
// Maintain stack trace
|
|
17
|
+
if (Error.captureStackTrace) {
|
|
18
|
+
Error.captureStackTrace(this, BusinessError);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert to JSON for logging/API responses
|
|
23
|
+
*/
|
|
24
|
+
toJSON() {
|
|
25
|
+
return {
|
|
26
|
+
name: this.name,
|
|
27
|
+
message: this.message,
|
|
28
|
+
code: this.code,
|
|
29
|
+
timestamp: this.timestamp.toISOString(),
|
|
30
|
+
context: this.context,
|
|
31
|
+
stack: this.stack
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create user-friendly error response
|
|
36
|
+
*/
|
|
37
|
+
toUserResponse() {
|
|
38
|
+
return {
|
|
39
|
+
error: this.message,
|
|
40
|
+
code: this.code,
|
|
41
|
+
timestamp: this.timestamp.toISOString()
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if error is of specific business type
|
|
46
|
+
*/
|
|
47
|
+
static isBusinessError(error) {
|
|
48
|
+
return error instanceof BusinessError;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if error has specific code
|
|
52
|
+
*/
|
|
53
|
+
hasCode(code) {
|
|
54
|
+
return this.code === code;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=BusinessError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BusinessError.js","sourceRoot":"","sources":["../../src/types/BusinessError.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACpB,IAAI,CAAS;IACb,aAAa,CAAS;IACtB,OAAO,CAAuB;IAC9B,SAAS,CAAO;IAEhC,YACI,OAAe,EACf,IAAY,EACZ,aAAqB,EACrB,OAA6B;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAE5B,uBAAuB;QACvB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACjD,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM;QACF,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YACvC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;SACpB,CAAC;IACN,CAAC;IAED;;OAEG;IACH,cAAc;QACV,OAAO;YACH,KAAK,EAAE,IAAI,CAAC,OAAO;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;SAC1C,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAU;QAC7B,OAAO,KAAK,YAAY,aAAa,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAY;QAChB,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;IAC9B,CAAC;CACJ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DatabaseClient } from '@groundbrick/db-core';
|
|
2
|
+
import { Validator } from '../validation/Validator.js';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for service instances
|
|
5
|
+
*/
|
|
6
|
+
export interface ServiceOptions {
|
|
7
|
+
/** Database client for transaction support */
|
|
8
|
+
database?: DatabaseClient;
|
|
9
|
+
/** Custom validator instance */
|
|
10
|
+
validator?: Validator;
|
|
11
|
+
/** Additional service-specific configuration */
|
|
12
|
+
config?: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ServiceOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceOptions.d.ts","sourceRoot":"","sources":["../../src/types/ServiceOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B,gCAAgC;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceOptions.js","sourceRoot":"","sources":["../../src/types/ServiceOptions.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BusinessError } from "./BusinessError.js";
|
|
2
|
+
/**
|
|
3
|
+
* Standardized service operation result
|
|
4
|
+
*/
|
|
5
|
+
export interface ServiceResult<T = any> {
|
|
6
|
+
/** Whether operation succeeded */
|
|
7
|
+
success: boolean;
|
|
8
|
+
/** Result data (if successful) */
|
|
9
|
+
data?: T;
|
|
10
|
+
/** Error information (if failed) */
|
|
11
|
+
error?: {
|
|
12
|
+
message: string;
|
|
13
|
+
code: string;
|
|
14
|
+
details?: Record<string, any>;
|
|
15
|
+
};
|
|
16
|
+
/** Operation metadata */
|
|
17
|
+
metadata?: {
|
|
18
|
+
duration?: number;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
operation?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Helper to create successful result
|
|
25
|
+
*/
|
|
26
|
+
export declare function createSuccessResult<T>(data: T, metadata?: any): ServiceResult<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Helper to create error result
|
|
29
|
+
*/
|
|
30
|
+
export declare function createErrorResult(error: BusinessError | Error | any): ServiceResult;
|
|
31
|
+
//# sourceMappingURL=ServiceResult.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceResult.d.ts","sourceRoot":"","sources":["../../src/types/ServiceResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,GAAG;IAClC,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IAEjB,kCAAkC;IAClC,IAAI,CAAC,EAAE,CAAC,CAAC;IAET,oCAAoC;IACpC,KAAK,CAAC,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACjC,CAAC;IAEF,yBAAyB;IACzB,QAAQ,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACL;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,CAShF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,KAAK,GAAG,GAAG,GAAG,aAAa,CAkBnF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BusinessError } from "./BusinessError.js";
|
|
2
|
+
/**
|
|
3
|
+
* Helper to create successful result
|
|
4
|
+
*/
|
|
5
|
+
export function createSuccessResult(data, metadata) {
|
|
6
|
+
return {
|
|
7
|
+
success: true,
|
|
8
|
+
data,
|
|
9
|
+
metadata: {
|
|
10
|
+
timestamp: new Date().toISOString(),
|
|
11
|
+
...metadata
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Helper to create error result
|
|
17
|
+
*/
|
|
18
|
+
export function createErrorResult(error) {
|
|
19
|
+
const isBusinessError = BusinessError.isBusinessError(error);
|
|
20
|
+
if (!isBusinessError) {
|
|
21
|
+
handleRepositoryError(error);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
success: false,
|
|
25
|
+
error: {
|
|
26
|
+
message: error.message,
|
|
27
|
+
code: isBusinessError ? error.code : 'UNKNOWN_ERROR',
|
|
28
|
+
details: isBusinessError ? error.context : undefined
|
|
29
|
+
},
|
|
30
|
+
metadata: {
|
|
31
|
+
timestamp: new Date().toISOString()
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Transform repository errors into business errors
|
|
37
|
+
* @param error - Original error from repository layer
|
|
38
|
+
* @returns BusinessError with appropriate context
|
|
39
|
+
*/
|
|
40
|
+
function handleRepositoryError(error) {
|
|
41
|
+
// Handle query errors
|
|
42
|
+
if (error.code === 'QUERY_ERROR' || error.message.includes('query failed') || error.message.includes('syntax error')) {
|
|
43
|
+
return new BusinessError('Execução inválida na base de dados.', 'QUERY_ERROR', error);
|
|
44
|
+
}
|
|
45
|
+
// Handle common database constraint violations
|
|
46
|
+
if (error.message.includes('duplicate') || error.message.includes('unique')) {
|
|
47
|
+
return new BusinessError('Recurso já existe', 'DUPLICATE_RESOURCE', error);
|
|
48
|
+
}
|
|
49
|
+
if (error.message.includes('not found') || error.message.includes('does not exist')) {
|
|
50
|
+
return new BusinessError('Recurso não encontrado', 'RESOURCE_NOT_FOUND', error);
|
|
51
|
+
}
|
|
52
|
+
if (error.message.includes('foreign key') || error.message.includes('constraint')) {
|
|
53
|
+
return new BusinessError('Referência inválida ou violação de restrição', 'CONSTRAINT_VIOLATION', error);
|
|
54
|
+
}
|
|
55
|
+
if (error.message.includes('ETIMEDOUT') || error.message.includes('deadlock')) {
|
|
56
|
+
return new BusinessError('Operação no banco de dados expirou ou ficou bloqueada', 'DATABASE_TIMEOUT', error);
|
|
57
|
+
}
|
|
58
|
+
// Default: wrap as generic business error
|
|
59
|
+
return new BusinessError('Operação falhou', 'OPERATION_FAILED', error);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ServiceResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceResult.js","sourceRoot":"","sources":["../../src/types/ServiceResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA2BnD;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAI,IAAO,EAAE,QAAc;IAC1D,OAAO;QACH,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,QAAQ,EAAE;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,GAAG,QAAQ;SACd;KACJ,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAkC;IAChE,MAAM,eAAe,GAAG,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAE7D,IAAI,CAAC,eAAe,EAAE,CAAC;QACnB,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,OAAO;QACH,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACH,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe;YACpD,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;SACvD;QACD,QAAQ,EAAE;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC;KACJ,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,KAAU;IAErC,sBAAsB;IACtB,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACnH,OAAO,IAAI,aAAa,CACpB,qCAAqC,EACrC,aAAa,EACb,KAAK,CACR,CAAC;IACN,CAAC;IAED,+CAA+C;IAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,OAAO,IAAI,aAAa,CACpB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,CACR,CAAC;IACN,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,aAAa,CACpB,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,CACR,CAAC;IACN,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAChF,OAAO,IAAI,aAAa,CACpB,8CAA8C,EAC9C,sBAAsB,EACtB,KAAK,CACR,CAAC;IACN,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5E,OAAO,IAAI,aAAa,CACpB,uDAAuD,EACvD,kBAAkB,EAClB,KAAK,CACR,CAAC;IACN,CAAC;IAED,0CAA0C;IAC1C,OAAO,IAAI,aAAa,CACpB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,CACR,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Individual validation error
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
/** Field that failed validation */
|
|
6
|
+
field: string;
|
|
7
|
+
/** Error message */
|
|
8
|
+
message: string;
|
|
9
|
+
/** Validation rule that failed */
|
|
10
|
+
rule: string;
|
|
11
|
+
/** Current value that failed */
|
|
12
|
+
value?: any;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=ValidationError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationError.d.ts","sourceRoot":"","sources":["../../src/validation/ValidationError.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IAEd,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,KAAK,CAAC,EAAE,GAAG,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationError.js","sourceRoot":"","sources":["../../src/validation/ValidationError.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ValidationRule } from "./Validator.js";
|
|
2
|
+
/**
|
|
3
|
+
* Common validation rules and helpers
|
|
4
|
+
*/
|
|
5
|
+
export declare class ValidationHelper {
|
|
6
|
+
/**
|
|
7
|
+
* Rule: Field is required (not null, undefined, or empty string)
|
|
8
|
+
*/
|
|
9
|
+
static required(): ValidationRule;
|
|
10
|
+
/**
|
|
11
|
+
* Rule: String minimum length
|
|
12
|
+
*/
|
|
13
|
+
static minLength(min: number): ValidationRule;
|
|
14
|
+
/**
|
|
15
|
+
* Rule: String maximum length
|
|
16
|
+
*/
|
|
17
|
+
static maxLength(max: number): ValidationRule;
|
|
18
|
+
/**
|
|
19
|
+
* Rule: Valid email format
|
|
20
|
+
*/
|
|
21
|
+
static email(): ValidationRule;
|
|
22
|
+
/**
|
|
23
|
+
* Rule: Numeric value within range
|
|
24
|
+
*/
|
|
25
|
+
static numberRange(min?: number, max?: number): ValidationRule;
|
|
26
|
+
/**
|
|
27
|
+
* Rule: Value matches regex pattern
|
|
28
|
+
*/
|
|
29
|
+
static pattern(regex: RegExp, message: string): ValidationRule;
|
|
30
|
+
/**
|
|
31
|
+
* Rule: Value is one of allowed options
|
|
32
|
+
*/
|
|
33
|
+
static oneOf(options: any[], message?: string): ValidationRule;
|
|
34
|
+
/**
|
|
35
|
+
* Rule: Array has minimum length
|
|
36
|
+
*/
|
|
37
|
+
static arrayMinLength(min: number): ValidationRule;
|
|
38
|
+
/**
|
|
39
|
+
* Rule: Custom validation with context
|
|
40
|
+
*/
|
|
41
|
+
static custom(validator: (value: any, data?: any) => string | null): ValidationRule;
|
|
42
|
+
/**
|
|
43
|
+
* Rule: Conditional validation
|
|
44
|
+
*/
|
|
45
|
+
static when(condition: (data: any) => boolean, rule: ValidationRule): ValidationRule;
|
|
46
|
+
/**
|
|
47
|
+
* Combine multiple validation rules
|
|
48
|
+
*/
|
|
49
|
+
static combine(...rules: ValidationRule[]): ValidationRule[];
|
|
50
|
+
/**
|
|
51
|
+
* Create validation rules for common entity patterns
|
|
52
|
+
*/
|
|
53
|
+
static entityId(): ValidationRule[];
|
|
54
|
+
/**
|
|
55
|
+
* Create validation rules for user creation
|
|
56
|
+
*/
|
|
57
|
+
static userCreation(): {
|
|
58
|
+
name: ValidationRule[];
|
|
59
|
+
email: ValidationRule[];
|
|
60
|
+
password: ValidationRule[];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Create validation rules for pagination
|
|
64
|
+
*/
|
|
65
|
+
static pagination(): {
|
|
66
|
+
limit: ValidationRule[];
|
|
67
|
+
offset: ValidationRule[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=ValidationHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationHelper.d.ts","sourceRoot":"","sources":["../../src/validation/ValidationHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,qBAAa,gBAAgB;IACzB;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,cAAc;IASjC;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc;IAU7C;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc;IAU7C;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,cAAc;IAW9B;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc;IAgB9D;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc;IAU9D;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc;IAS9D;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc;IAUlD;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,cAAc;IAInF;;OAEG;IACH,MAAM,CAAC,IAAI,CACP,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,EACjC,IAAI,EAAE,cAAc,GACrB,cAAc;IASjB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE;IAI5D;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,cAAc,EAAE;IAanC;;OAEG;IACH,MAAM,CAAC,YAAY;;;;;IAQnB;;OAEG;IACH,MAAM,CAAC,UAAU;;;;CAMpB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common validation rules and helpers
|
|
3
|
+
*/
|
|
4
|
+
export class ValidationHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Rule: Field is required (not null, undefined, or empty string)
|
|
7
|
+
*/
|
|
8
|
+
static required() {
|
|
9
|
+
return (value) => {
|
|
10
|
+
if (value === null || value === undefined || value === '') {
|
|
11
|
+
return 'This field is required';
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rule: String minimum length
|
|
18
|
+
*/
|
|
19
|
+
static minLength(min) {
|
|
20
|
+
return (value) => {
|
|
21
|
+
if (typeof value !== 'string')
|
|
22
|
+
return null;
|
|
23
|
+
if (value.length < min) {
|
|
24
|
+
return `Must be at least ${min} characters long`;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Rule: String maximum length
|
|
31
|
+
*/
|
|
32
|
+
static maxLength(max) {
|
|
33
|
+
return (value) => {
|
|
34
|
+
if (typeof value !== 'string')
|
|
35
|
+
return null;
|
|
36
|
+
if (value.length > max) {
|
|
37
|
+
return `Must be no more than ${max} characters long`;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Rule: Valid email format
|
|
44
|
+
*/
|
|
45
|
+
static email() {
|
|
46
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
47
|
+
return (value) => {
|
|
48
|
+
if (typeof value !== 'string')
|
|
49
|
+
return null;
|
|
50
|
+
if (!emailRegex.test(value)) {
|
|
51
|
+
return 'Must be a valid email address';
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Rule: Numeric value within range
|
|
58
|
+
*/
|
|
59
|
+
static numberRange(min, max) {
|
|
60
|
+
return (value) => {
|
|
61
|
+
const num = Number(value);
|
|
62
|
+
if (isNaN(num)) {
|
|
63
|
+
return 'Must be a valid number';
|
|
64
|
+
}
|
|
65
|
+
if (min !== undefined && num < min) {
|
|
66
|
+
return `Must be at least ${min}`;
|
|
67
|
+
}
|
|
68
|
+
if (max !== undefined && num > max) {
|
|
69
|
+
return `Must be no more than ${max}`;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Rule: Value matches regex pattern
|
|
76
|
+
*/
|
|
77
|
+
static pattern(regex, message) {
|
|
78
|
+
return (value) => {
|
|
79
|
+
if (typeof value !== 'string')
|
|
80
|
+
return null;
|
|
81
|
+
if (!regex.test(value)) {
|
|
82
|
+
return message;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Rule: Value is one of allowed options
|
|
89
|
+
*/
|
|
90
|
+
static oneOf(options, message) {
|
|
91
|
+
return (value) => {
|
|
92
|
+
if (!options.includes(value)) {
|
|
93
|
+
return message || `Must be one of: ${options.join(', ')}`;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Rule: Array has minimum length
|
|
100
|
+
*/
|
|
101
|
+
static arrayMinLength(min) {
|
|
102
|
+
return (value) => {
|
|
103
|
+
if (!Array.isArray(value))
|
|
104
|
+
return null;
|
|
105
|
+
if (value.length < min) {
|
|
106
|
+
return `Must contain at least ${min} items`;
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Rule: Custom validation with context
|
|
113
|
+
*/
|
|
114
|
+
static custom(validator) {
|
|
115
|
+
return validator;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Rule: Conditional validation
|
|
119
|
+
*/
|
|
120
|
+
static when(condition, rule) {
|
|
121
|
+
return (value, data) => {
|
|
122
|
+
if (condition(data || {})) {
|
|
123
|
+
return rule(value, data);
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Combine multiple validation rules
|
|
130
|
+
*/
|
|
131
|
+
static combine(...rules) {
|
|
132
|
+
return rules;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Create validation rules for common entity patterns
|
|
136
|
+
*/
|
|
137
|
+
static entityId() {
|
|
138
|
+
return [
|
|
139
|
+
this.required(),
|
|
140
|
+
this.custom((value) => {
|
|
141
|
+
const id = Number(value);
|
|
142
|
+
if (isNaN(id) || id <= 0) {
|
|
143
|
+
return 'Must be a valid positive ID';
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
})
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create validation rules for user creation
|
|
151
|
+
*/
|
|
152
|
+
static userCreation() {
|
|
153
|
+
return {
|
|
154
|
+
name: [this.required(), this.minLength(2), this.maxLength(100)],
|
|
155
|
+
email: [this.required(), this.email()],
|
|
156
|
+
password: [this.required(), this.minLength(8)]
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Create validation rules for pagination
|
|
161
|
+
*/
|
|
162
|
+
static pagination() {
|
|
163
|
+
return {
|
|
164
|
+
limit: [this.numberRange(1, 100)],
|
|
165
|
+
offset: [this.numberRange(0)]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=ValidationHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationHelper.js","sourceRoot":"","sources":["../../src/validation/ValidationHelper.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,gBAAgB;IACzB;;OAEG;IACH,MAAM,CAAC,QAAQ;QACX,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACxD,OAAO,wBAAwB,CAAC;YACpC,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,GAAW;QACxB,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,OAAO,oBAAoB,GAAG,kBAAkB,CAAC;YACrD,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,GAAW;QACxB,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,OAAO,wBAAwB,GAAG,kBAAkB,CAAC;YACzD,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK;QACR,MAAM,UAAU,GAAG,4BAA4B,CAAC;QAChD,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,+BAA+B,CAAC;YAC3C,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,GAAY,EAAE,GAAY;QACzC,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBACb,OAAO,wBAAwB,CAAC;YACpC,CAAC;YACD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACjC,OAAO,oBAAoB,GAAG,EAAE,CAAC;YACrC,CAAC;YACD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACjC,OAAO,wBAAwB,GAAG,EAAE,CAAC;YACzC,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,KAAa,EAAE,OAAe;QACzC,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC;YACnB,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAc,EAAE,OAAgB;QACzC,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,OAAO,IAAI,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,GAAW;QAC7B,OAAO,CAAC,KAAU,EAAE,EAAE;YAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACvC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACrB,OAAO,yBAAyB,GAAG,QAAQ,CAAC;YAChD,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,SAAoD;QAC9D,OAAO,SAAS,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CACP,SAAiC,EACjC,IAAoB;QAEpB,OAAO,CAAC,KAAU,EAAE,IAAU,EAAE,EAAE;YAC9B,IAAI,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,KAAuB;QACrC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ;QACX,OAAO;YACH,IAAI,CAAC,QAAQ,EAAE;YACf,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBAClB,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBACzB,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;oBACvB,OAAO,6BAA6B,CAAC;gBACzC,CAAC;gBACD,OAAO,IAAI,CAAC;YAChB,CAAC,CAAC;SACL,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,YAAY;QACf,OAAO;YACH,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC/D,KAAK,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;SACjD,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,UAAU;QACb,OAAO;YACH,KAAK,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACjC,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;SAChC,CAAC;IACN,CAAC;CACJ"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of input validation
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationResult {
|
|
5
|
+
/** Whether validation passed */
|
|
6
|
+
isValid: boolean;
|
|
7
|
+
/** Validation errors by field name */
|
|
8
|
+
errors: Record<string, string[]>;
|
|
9
|
+
/** Total number of errors */
|
|
10
|
+
errorCount: number;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ValidationResult.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationResult.d.ts","sourceRoot":"","sources":["../../src/validation/ValidationResult.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IAEjB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEjC,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationResult.js","sourceRoot":"","sources":["../../src/validation/ValidationResult.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ValidationResult } from './ValidationResult.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validation rule function
|
|
4
|
+
*/
|
|
5
|
+
export type ValidationRule = (value: any, data?: any) => string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Validation rules by field name
|
|
8
|
+
*/
|
|
9
|
+
export type ValidationRules = Record<string, ValidationRule[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Simple, extensible validation system
|
|
12
|
+
*/
|
|
13
|
+
export declare class Validator {
|
|
14
|
+
private customRules;
|
|
15
|
+
/**
|
|
16
|
+
* Register a custom validation rule
|
|
17
|
+
* @param name - Rule name
|
|
18
|
+
* @param rule - Validation function
|
|
19
|
+
*/
|
|
20
|
+
registerRule(name: string, rule: ValidationRule): void;
|
|
21
|
+
/**
|
|
22
|
+
* Validate data against rules
|
|
23
|
+
* @param data - Data to validate
|
|
24
|
+
* @param rules - Validation rules
|
|
25
|
+
* @returns ValidationResult
|
|
26
|
+
*/
|
|
27
|
+
validate<T>(data: T, rules: ValidationRules): Promise<ValidationResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Get a registered custom rule
|
|
30
|
+
* @param name - Rule name
|
|
31
|
+
* @returns ValidationRule or undefined
|
|
32
|
+
*/
|
|
33
|
+
getRule(name: string): ValidationRule | undefined;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=Validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Validator.d.ts","sourceRoot":"","sources":["../../src/validation/Validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;AAE/D;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,WAAW,CAA0C;IAE7D;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI;IAItD;;;;;OAKG;IACG,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA6B7E;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;CAGpD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple, extensible validation system
|
|
3
|
+
*/
|
|
4
|
+
export class Validator {
|
|
5
|
+
customRules = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Register a custom validation rule
|
|
8
|
+
* @param name - Rule name
|
|
9
|
+
* @param rule - Validation function
|
|
10
|
+
*/
|
|
11
|
+
registerRule(name, rule) {
|
|
12
|
+
this.customRules.set(name, rule);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate data against rules
|
|
16
|
+
* @param data - Data to validate
|
|
17
|
+
* @param rules - Validation rules
|
|
18
|
+
* @returns ValidationResult
|
|
19
|
+
*/
|
|
20
|
+
async validate(data, rules) {
|
|
21
|
+
const errors = {};
|
|
22
|
+
const dataObj = data;
|
|
23
|
+
for (const [fieldName, fieldRules] of Object.entries(rules)) {
|
|
24
|
+
const fieldErrors = [];
|
|
25
|
+
const fieldValue = dataObj[fieldName];
|
|
26
|
+
for (const rule of fieldRules) {
|
|
27
|
+
const errorMessage = rule(fieldValue, dataObj);
|
|
28
|
+
if (errorMessage) {
|
|
29
|
+
fieldErrors.push(errorMessage);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (fieldErrors.length > 0) {
|
|
33
|
+
errors[fieldName] = fieldErrors;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const errorCount = Object.values(errors).reduce((sum, errs) => sum + errs.length, 0);
|
|
37
|
+
return {
|
|
38
|
+
isValid: errorCount === 0,
|
|
39
|
+
errors,
|
|
40
|
+
errorCount
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a registered custom rule
|
|
45
|
+
* @param name - Rule name
|
|
46
|
+
* @returns ValidationRule or undefined
|
|
47
|
+
*/
|
|
48
|
+
getRule(name) {
|
|
49
|
+
return this.customRules.get(name);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=Validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Validator.js","sourceRoot":"","sources":["../../src/validation/Validator.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,OAAO,SAAS;IACV,WAAW,GAAgC,IAAI,GAAG,EAAE,CAAC;IAE7D;;;;OAIG;IACH,YAAY,CAAC,IAAY,EAAE,IAAoB;QAC3C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAI,IAAO,EAAE,KAAsB;QAC7C,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAA2B,CAAC;QAE5C,KAAK,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YAEtC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAC/C,IAAI,YAAY,EAAE,CAAC;oBACf,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACnC,CAAC;YACL,CAAC;YAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC;YACpC,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAErF,OAAO;YACH,OAAO,EAAE,UAAU,KAAK,CAAC;YACzB,MAAM;YACN,UAAU;SACb,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAY;QAChB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;CACJ"}
|