@cleverbrush/schema 0.0.3

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.
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateObject = void 0;
4
+ const validateObject = async (obj, schema, validator) => {
5
+ if (typeof obj === 'undefined' &&
6
+ typeof schema === 'object' &&
7
+ schema.isRequired === false) {
8
+ return {
9
+ valid: true
10
+ };
11
+ }
12
+ if (typeof obj !== 'object') {
13
+ return {
14
+ valid: false,
15
+ errors: [
16
+ `expected to have type='object', but saw '${typeof obj}' instead`
17
+ ]
18
+ };
19
+ }
20
+ if (typeof schema.properties === 'object' && schema.properties) {
21
+ const errors = (await Promise.all(Object.entries(schema.properties).map(async ([name, schema]) => {
22
+ const result = await validator.validate(schema, obj[name]);
23
+ if (result.valid)
24
+ return result;
25
+ return {
26
+ valid: false,
27
+ errors: (result.errors || []).map((e) => `->${name} ${e}`)
28
+ };
29
+ })))
30
+ .filter((r) => !r.valid)
31
+ .map((r) => r.errors)
32
+ .flat(Infinity);
33
+ if (errors.length) {
34
+ return {
35
+ valid: false,
36
+ errors
37
+ };
38
+ }
39
+ }
40
+ return {
41
+ valid: true
42
+ };
43
+ };
44
+ exports.validateObject = validateObject;
@@ -0,0 +1,2 @@
1
+ import { ValidationResult, StringSchemaDefinition, ISchemaValidator } from '../index';
2
+ export declare const validateString: (obj: any, schema: StringSchemaDefinition<any>, validator: ISchemaValidator<any>) => Promise<ValidationResult>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateString = void 0;
4
+ const validateString = async (obj, schema, validator) => {
5
+ if (typeof obj === 'undefined' &&
6
+ typeof schema === 'object' &&
7
+ schema.isRequired === false) {
8
+ return {
9
+ valid: true
10
+ };
11
+ }
12
+ if (typeof obj !== 'string')
13
+ return {
14
+ valid: false,
15
+ errors: [`expected type string, but saw ${typeof obj}`]
16
+ };
17
+ if (typeof schema === 'string') {
18
+ return obj === schema
19
+ ? { valid: true }
20
+ : {
21
+ valid: false,
22
+ errors: [`should be equal to ${schema}`]
23
+ };
24
+ }
25
+ const str = obj;
26
+ if (typeof schema.equals === 'string' && str !== schema.equals) {
27
+ return {
28
+ valid: false,
29
+ errors: [
30
+ `expected to be equal to '${schema.equals}' but saw '${str}'`
31
+ ]
32
+ };
33
+ }
34
+ if (typeof schema.minLength === 'number' && str.length < schema.minLength) {
35
+ return {
36
+ valid: false,
37
+ errors: [`expected to be at least ${schema.minLength} chars long`]
38
+ };
39
+ }
40
+ if (typeof schema.maxLength === 'number' && str.length > schema.maxLength) {
41
+ return {
42
+ valid: false,
43
+ errors: [`expected to be at most ${schema.maxLength} chars long`]
44
+ };
45
+ }
46
+ return {
47
+ valid: true
48
+ };
49
+ };
50
+ exports.validateString = validateString;
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@cleverbrush/schema",
3
+ "version": "0.0.3",
4
+ "keywords": [
5
+ "object schema validator",
6
+ "schema",
7
+ "validate object"
8
+ ],
9
+ "author": "Andrew Zolotukhin <andrew_zol@cleverbrush.com>",
10
+ "license": "BSD",
11
+ "main": "./dist/index.js",
12
+ "scripts": {
13
+ "watch": "tsc --watch",
14
+ "build": "tsc"
15
+ },
16
+ "dependencies": {
17
+ "@cleverbrush/deep": "0.0.3"
18
+ },
19
+ "types": "./dist/index.d.ts"
20
+ }
package/src/index.ts ADDED
@@ -0,0 +1,137 @@
1
+ import SchemaValidator from './schemaValidator';
2
+
3
+ export type DefaultSchemaType =
4
+ | 'object'
5
+ | 'function'
6
+ | 'number'
7
+ | 'string'
8
+ | 'array';
9
+
10
+ export type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];
11
+
12
+ export type DefaultPropertyDefinition = {
13
+ isRequired: boolean;
14
+ isNullable: boolean;
15
+ };
16
+
17
+ export type ValidationResultRaw = {
18
+ valid: boolean;
19
+ errors?: Array<string>;
20
+ };
21
+
22
+ export type ValidationResult =
23
+ | ValidationResultRaw
24
+ | Promise<ValidationResultRaw>;
25
+
26
+ export type Validator<TObj> = (value: TObj) => ValidationResult;
27
+
28
+ export type SchemaDefintion<TObj> = {
29
+ type: DefaultSchemaType;
30
+ isRequired?: boolean;
31
+ isNullable?: boolean;
32
+ validators?: Array<Validator<TObj>>;
33
+ };
34
+
35
+ export type ObjectSchemaDefinition<T> = Omit<SchemaDefintion<T>, 'type'> & {
36
+ type: 'object';
37
+ extends?: string;
38
+ properties?: Partial<{
39
+ [S in keyof T]: Schema<PropType<T, S>>;
40
+ }>;
41
+ };
42
+
43
+ export type ObjectSchemaDefinitionParam<T> = Omit<
44
+ ObjectSchemaDefinition<T>,
45
+ 'type'
46
+ >;
47
+
48
+ export type ParamsValidators<TFunc extends (...args: any) => any> = {
49
+ [S in keyof Parameters<TFunc>]: SingleSchema<Parameters<TFunc>[S]>;
50
+ };
51
+
52
+ export type FunctionSchemaDefinition<T extends (...args: any) => any> = Omit<
53
+ SchemaDefintion<T>,
54
+ 'type'
55
+ > & {
56
+ type: 'function';
57
+ params?: ParamsValidators<T>;
58
+ };
59
+
60
+ export type NumberSchemaDefinition<TObj> = Omit<
61
+ SchemaDefintion<TObj>,
62
+ 'type'
63
+ > & {
64
+ type: 'number';
65
+ min?: number;
66
+ max?: number;
67
+ equals?: number;
68
+ isInteger?: boolean;
69
+ ensureNotNaN?: boolean;
70
+ ensureIsFinite?: boolean;
71
+ };
72
+
73
+ export type StringSchemaDefinition<TObj> = Omit<
74
+ SchemaDefintion<TObj>,
75
+ 'type'
76
+ > & {
77
+ type: 'string';
78
+ equals?: string;
79
+ minLength?: number;
80
+ maxLength?: number;
81
+ };
82
+
83
+ export type ArraySchemaDefinition<TObj> = Omit<
84
+ SchemaDefintion<TObj>,
85
+ 'type'
86
+ > & {
87
+ type: 'array';
88
+ ofType?: Schema<any>;
89
+ minLength?: number;
90
+ maxLength?: number;
91
+ };
92
+
93
+ export type CompositeSchema<TObj> = TObj extends (...args: any) => any
94
+ ? FunctionSchemaDefinition<TObj>
95
+ : TObj extends number
96
+ ? NumberSchemaDefinition<TObj>
97
+ : TObj extends string
98
+ ? StringSchemaDefinition<TObj> | 'string'
99
+ :
100
+ | NumberSchemaDefinition<TObj>
101
+ | StringSchemaDefinition<TObj>
102
+ | ArraySchemaDefinition<TObj>
103
+ | ObjectSchemaDefinition<TObj>;
104
+
105
+ export type SingleSchema<TObj = Record<string, never>> =
106
+ | number
107
+ | string
108
+ | DefaultSchemaType
109
+ | CompositeSchema<TObj>;
110
+
111
+ export type Schema<TObj> = SingleSchema<TObj> | Array<SingleSchema<TObj>>;
112
+
113
+ export interface ISchemaActions<K, T extends keyof K> {
114
+ validate(value: any): Promise<ValidationResult>;
115
+ schema: PropType<K, T>;
116
+ }
117
+
118
+ export interface ISchemasProvider<T = Record<string, never>> {
119
+ schemas: {
120
+ [K in keyof T]: ISchemaActions<T, K>;
121
+ };
122
+ }
123
+
124
+ export interface ISchemaValidator<T = Record<string, never>> {
125
+ addSchemaType<K, L extends ObjectSchemaDefinitionParam<M>, M = any>(
126
+ name: keyof K,
127
+ schema: L
128
+ ): SchemaValidator<T & { [key in keyof K]: L }>;
129
+
130
+ validate(
131
+ schema: keyof T | DefaultSchemaType | Schema<any>,
132
+ obj: any
133
+ ): Promise<ValidationResult>;
134
+ }
135
+
136
+ export { SchemaValidator };
137
+ export default SchemaValidator;