schematox 0.0.3 → 0.0.5

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 CHANGED
@@ -4,19 +4,17 @@ SchmatoX is a lightweight library for creating JSON compatible schemas. The subj
4
4
 
5
5
  ## Pros
6
6
 
7
- - The statically defined JSON compatible schema is a killer feature:
8
- - It has great potential for automation in the context of DB model creation, CRUD backends, documentation, outer interface requirements etc.
9
- - One can store schema changes as static JSON and potentially use it for creating coherent DB Model migration logic.
10
- - One can check if the defined schema is compatible with our constraints using the "as const satisfies Schema".
11
- - Programmatically defined schemas are also supported, but as a means of creating statically defined schemas.
12
- - There is a clear separation of concerns for validating and parsing logic.
13
- - The Schematox parser is used for dealing with an outer interface where the data type is not guaranteed.
14
- - The Schematox validator is used for dealing with an internal interface where the data type is known.
15
- - Schematox uses an Ether-style error handling system. It never throws an error on an unsuccessful schema subject check. Instead, our parser/validator always returns an `EitherError` object.
16
- - We offer first-class support for branded base schema types.
7
+ - The statically defined JSON compatible schema
8
+ - Check defined schema correctness using non generic type `Schema`
9
+ - Programmatically defined schemas supported as mean of creation statically defined schema
10
+ - Clear separation of concerns for validating and parsing logic:
11
+ - Parser is used for dealing with an outer uknnown interface
12
+ - Validator is used for dealing with an internal known interface
13
+ - Schematox uses an Ether-style error handling
14
+ - We offer first-class support for branded base schema primitive types
17
15
  - We have zero dependencies. The runtime code logic is small and easy to grasp, consisting of just a couple of functions. Most of the library code is tests and types.
18
16
 
19
- Essentially, to define a schema, one doesn't even need to import any functions from our library, only the `Schema` type. This approach does come with a few limitations. The first is `stringUnion` and `numberUnion` schema default values are not constrained by the defined union choices, only the primitive type. We might fix this issue later, but for now, we prioritize this over the case when `default` extends union choice by its definition.
17
+ Essentially, to define a schema, one doesn't need to import any functions from our library, only the `as const satisfies Schema` statement. This approach does come with a few limitations. The first is `stringUnion` and `numberUnion` schema default values are not constrained by the defined union choices, only the primitive type. We might fix this issue later, but for now, we prioritize this over the case when `default` extends union choice by its definition.
20
18
 
21
19
  A second limitation is the depth of the compound schema data structure. Currently, we support 7 layers of depth. It's easy to increase this number, but because of the exponential nature of stored type variants in memory, we want to determine how much RAM each next layer will use before increasing it.
22
20
 
@@ -24,11 +22,13 @@ It's crucial to separate parsing/validation logic from the schema itself. Librar
24
22
 
25
23
  ## Cons
26
24
 
25
+ - The library is not ready for production yet, the version is 0 and public API might be changed
27
26
  - Currently we support only 7 layers of compound structure depth but most likely it will be higher soon
28
27
  - We do not support records, discriminated unions, object unions, array unions, intersections, functions, NaN, Infinity and other not JSON compatible structures
29
28
  - Null value is acceptable by the parser but will be treated as undefined and transformed to undefined
30
29
  - Null value is not acceptable by the validator
31
- - We only plan to support custom parser/normalizer integration logic.
30
+
31
+ Check out [github issues](https://github.com/incerta/schematox/issues) of the project to know what we are planning to support soon.
32
32
 
33
33
  ## Installation
34
34
 
@@ -299,7 +299,7 @@ const staticArray = {
299
299
  const programmaticArray = array(string())
300
300
  ```
301
301
 
302
- ## Validate/parse error shape
302
+ ## Validate/parse InvalidSubject error shape
303
303
 
304
304
  Nested schema example. Subject `0` is invalid, should be a `string`:
305
305
 
@@ -334,43 +334,41 @@ The `result.error` will be:
334
334
  ]
335
335
  ```
336
336
 
337
- ## Parse/validate differences
337
+ If the `error` is present it's always an array which has at least one entry. Each entry has the following properties:
338
338
 
339
- The parser provides a new object/primitive without references to the evaluated subject. This functionality is responsible for clearing the `array` schema result value from `undefined` optional schema values.
339
+ - `code` could be `INVALID_TYPE` if schema subject or schema default value is not satisfies schema type requirement. Another code `INVALID_RANGE` which is about `min/max` and `minLength/maxLength` schema requirements
340
+ - `schema` – the particular chunk of the `schema` where invalid subject value is found
341
+ - `subject` – the particular chunk of the validated subject where invalid value is found
342
+ - `path` – the path to error subject chunk from the root of the evaluated subject. Strings is keys and numbers are the array indexes
340
343
 
341
- Moreover, the parser manages the `null` value as `undefined` and subsequently replaces it with `undefined`. It also swaps `optional` values with the `default` value, provided that the default values are explicitly stated in the schema.
344
+ ## Parse/validate differences
342
345
 
343
- Particularly for this last function, the parser uses a separate type inference flow. This flow is accessible for the library user via the type generic `XParsed<T extends Schema>`. By leveraging this mechanism, the user can simplify the process and enhance efficiency.
346
+ The parser returns `data` as new object/primitive without references to the parsed subject. Parser manages the `null` value as `undefined` and subsequently replaces it with `undefined`. It also swaps `optional` values with the `default` value from schema. One can infer schema parsed subject type by using `XParsed<typeof schema>` generic.
344
347
 
345
- The validator operates by returning a reference to the original object, rather than applying any form of mutations to it. This is a significant feature because it disregards the schema’s default values.
348
+ The validator on the other hand returns the evaluated subject itself and not applying any mutation/transformation to it. The validator should be used in exceptional cases when we known subject type but not sure that it actually correct. One can infer schema validated subject type by using `XValidated<typeof schema>` generic.
346
349
 
347
- Furthermore, the validator incorporates a type inference flow distinct from the parser's. Available for utilization through the type generic `XValidated<T extends Schema>`.
350
+ So the difference between `XParsed` and `XValidated` is just about handling `default` schema value. `XParsed` narrows optional schema subject type with default value in the way that it will not be optional, because optional `undefined` and `null` values will be replaced by the `default`. `XValidated` just ignores `default` schema value.
348
351
 
349
- Examples of described differences:
352
+ Examples:
350
353
 
351
354
  ```typescript
352
355
  const optionalStrX = x('string?')
353
356
 
354
- /* Parser treats `null` as `undefined` */
355
-
356
- expect(optionalStrX.parse(null).data).toBe(undefined)
357
- expect(optionalStrX.parse(null).error).toBe(undefined)
358
-
359
- /* Validator is not */
357
+ /* Parser doesn't check subject type */
360
358
 
361
- // @ts-expect-error 'null' is not assignable to parameter of type 'string | undefined'
362
- expect(optionalStrX.validate(null).error).toStrictEqual([
359
+ expect(optionalStrX.parse(0).error).toStrictEqual([
363
360
  {
364
361
  code: 'INVALID_TYPE',
365
362
  schema: 'string?',
366
- subject: null,
363
+ subject: 0,
367
364
  path: [],
368
365
  },
369
366
  ])
370
367
 
371
- /* Parser doesn't check subject type */
368
+ /* Validator does */
372
369
 
373
- expect(optionalStrX.parse(0).error).toStrictEqual([
370
+ // @ts-expect-error 'number' is not 'string'
371
+ expect(optionalStrX.validate(0).error).toStrictEqual([
374
372
  {
375
373
  code: 'INVALID_TYPE',
376
374
  schema: 'string?',
@@ -379,14 +377,19 @@ expect(optionalStrX.parse(0).error).toStrictEqual([
379
377
  },
380
378
  ])
381
379
 
382
- /* Validator does */
380
+ /* Parser treats `null` as `undefined` */
383
381
 
384
- // @ts-expect-error 'number' is not assignable to parameter of type 'string'
385
- expect(optionalStrX.validate(0).error).toStrictEqual([
382
+ expect(optionalStrX.parse(null).data).toBe(undefined)
383
+ expect(optionalStrX.parse(null).error).toBe(undefined)
384
+
385
+ /* Validator is not */
386
+
387
+ // @ts-expect-error 'null' is not 'string | undefined'
388
+ expect(optionalStrX.validate(null).error).toStrictEqual([
386
389
  {
387
390
  code: 'INVALID_TYPE',
388
391
  schema: 'string?',
389
- subject: 0,
392
+ subject: null,
390
393
  path: [],
391
394
  },
392
395
  ])
@@ -402,17 +405,6 @@ expect(defaultedStrX.parse(undefined).data).toBe('y')
402
405
 
403
406
  expect(defaultedStrX.validate(undefined).data).toBe(undefined)
404
407
 
405
- /* Parser clears subject array from optional undefined */
406
-
407
- const arrX = x({ type: 'array', of: 'string?' })
408
- const subject = [undefined, 'y', undefined, 'z']
409
-
410
- expect(arrX.parse(subject).data).toStrictEqual(['y', 'z'])
411
-
412
- /* Validator keeps them */
413
-
414
- expect(arrX.validate(subject).data).toStrictEqual(subject)
415
-
416
408
  /* Parser returning new object */
417
409
 
418
410
  expect(arrX.parse(subject).data === subject).toBe(false)
@@ -1,5 +1,5 @@
1
1
  import type { EitherError } from './utils/fp';
2
2
  import type { BaseSchema, Con_Schema_SubjT_P } from './types/compound-schema-types';
3
- import type { BaseSchemaParseError } from './error';
3
+ import type { InvalidSubject, ErrorPath } from './error';
4
4
  export type BaseSchemaSubjectType = string | number | boolean | undefined;
5
- export declare function parseBaseSchemaSubject<T extends BaseSchema>(schema: T, schemaSubject: unknown): EitherError<BaseSchemaParseError, Con_Schema_SubjT_P<T>>;
5
+ export declare function parseBaseSchemaSubject<T extends BaseSchema>(this: ErrorPath | void, schema: T, schemaSubject: unknown): EitherError<InvalidSubject, Con_Schema_SubjT_P<T>>;
@@ -15,7 +15,8 @@ function parseBaseSchemaSubject(schema, subject) {
15
15
  }
16
16
  }
17
17
  return (0, fp_1.error)({
18
- code: error_1.PARSE_ERROR_CODE.invalidType,
18
+ code: error_1.ERROR_CODE.invalidType,
19
+ path: this || [],
19
20
  schema: schema,
20
21
  subject: subject,
21
22
  });
@@ -31,21 +32,16 @@ function parseBaseSchemaSubject(schema, subject) {
31
32
  }
32
33
  }
33
34
  return (0, fp_1.error)({
34
- code: error_1.PARSE_ERROR_CODE.invalidType,
35
- schema: schema,
36
- subject: subject,
37
- });
38
- }
39
- if (Number.isNaN(subject)) {
40
- return (0, fp_1.error)({
41
- code: error_1.PARSE_ERROR_CODE.NaN,
35
+ code: error_1.ERROR_CODE.invalidType,
36
+ path: this || [],
42
37
  schema: schema,
43
38
  subject: subject,
44
39
  });
45
40
  }
46
41
  if (Number.isFinite(subject) === false) {
47
42
  return (0, fp_1.error)({
48
- code: error_1.PARSE_ERROR_CODE.infinity,
43
+ code: error_1.ERROR_CODE.invalidType,
44
+ path: this || [],
49
45
  schema: schema,
50
46
  subject: subject,
51
47
  });
@@ -61,7 +57,8 @@ function parseBaseSchemaSubject(schema, subject) {
61
57
  }
62
58
  }
63
59
  return (0, fp_1.error)({
64
- code: error_1.PARSE_ERROR_CODE.invalidType,
60
+ code: error_1.ERROR_CODE.invalidType,
61
+ path: this || [],
65
62
  schema: schema,
66
63
  subject: subject,
67
64
  });
@@ -70,207 +67,138 @@ function parseBaseSchemaSubject(schema, subject) {
70
67
  }
71
68
  }
72
69
  }
70
+ var updatedSubject = typeof schema.default !== undefined &&
71
+ schema.optional &&
72
+ (subject === null || subject === undefined)
73
+ ? schema.default
74
+ : subject;
75
+ if (schema.optional) {
76
+ if (updatedSubject === null || updatedSubject === undefined) {
77
+ return (0, fp_1.data)(undefined);
78
+ }
79
+ }
73
80
  switch (schema.type) {
74
81
  case 'string': {
75
- if (typeof subject !== 'string') {
76
- if (subject === undefined || subject === null) {
77
- if (schema.optional) {
78
- if (typeof schema.default === 'string') {
79
- var rangeError_1 = getStringRangeError(schema, schema.default, true);
80
- if (rangeError_1) {
81
- return (0, fp_1.error)(rangeError_1);
82
- }
83
- return (0, fp_1.data)(schema.default);
84
- }
85
- return (0, fp_1.data)(undefined);
86
- }
87
- }
82
+ if (typeof updatedSubject !== 'string') {
88
83
  return (0, fp_1.error)({
89
- code: error_1.PARSE_ERROR_CODE.invalidType,
84
+ code: error_1.ERROR_CODE.invalidType,
85
+ subject: updatedSubject,
86
+ path: this || [],
90
87
  schema: schema,
91
- subject: subject,
92
88
  });
93
89
  }
94
- var rangeError = getStringRangeError(schema, subject, false);
95
- if (rangeError) {
96
- return (0, fp_1.error)(rangeError);
90
+ if (typeof schema.minLength === 'number') {
91
+ if (updatedSubject.length < schema.minLength) {
92
+ return (0, fp_1.error)({
93
+ code: error_1.ERROR_CODE.invalidRange,
94
+ subject: updatedSubject,
95
+ path: this || [],
96
+ schema: schema,
97
+ });
98
+ }
99
+ }
100
+ if (typeof schema.maxLength === 'number') {
101
+ if (updatedSubject.length > schema.maxLength) {
102
+ return (0, fp_1.error)({
103
+ code: error_1.ERROR_CODE.invalidRange,
104
+ subject: updatedSubject,
105
+ path: this || [],
106
+ schema: schema,
107
+ });
108
+ }
97
109
  }
98
- return (0, fp_1.data)(subject);
110
+ return (0, fp_1.data)(updatedSubject);
99
111
  }
100
112
  case 'number': {
101
- if (typeof subject !== 'number') {
102
- if (subject === undefined || subject === null) {
103
- if (schema.optional) {
104
- if (typeof schema.default === 'number') {
105
- var rangeError_2 = getNumberRangeError(schema, schema.default, true);
106
- if (rangeError_2) {
107
- return (0, fp_1.error)(rangeError_2);
108
- }
109
- return (0, fp_1.data)(schema.default);
110
- }
111
- return (0, fp_1.data)(undefined);
112
- }
113
- }
113
+ if (typeof updatedSubject !== 'number') {
114
114
  return (0, fp_1.error)({
115
- code: error_1.PARSE_ERROR_CODE.invalidType,
115
+ code: error_1.ERROR_CODE.invalidType,
116
+ subject: updatedSubject,
117
+ path: this || [],
116
118
  schema: schema,
117
- subject: subject,
118
119
  });
119
120
  }
120
- if (Number.isNaN(subject)) {
121
+ if (Number.isFinite(updatedSubject) === false) {
121
122
  return (0, fp_1.error)({
122
- code: error_1.PARSE_ERROR_CODE.NaN,
123
+ code: error_1.ERROR_CODE.invalidType,
124
+ subject: updatedSubject,
125
+ path: this || [],
123
126
  schema: schema,
124
- subject: subject,
125
127
  });
126
128
  }
127
- if (Number.isFinite(subject) === false) {
128
- return (0, fp_1.error)({
129
- code: error_1.PARSE_ERROR_CODE.infinity,
130
- schema: schema,
131
- subject: subject,
132
- });
129
+ if (typeof schema.min === 'number') {
130
+ if (updatedSubject < schema.min) {
131
+ return (0, fp_1.error)({
132
+ code: error_1.ERROR_CODE.invalidRange,
133
+ subject: updatedSubject,
134
+ path: this || [],
135
+ schema: schema,
136
+ });
137
+ }
133
138
  }
134
- var rangeError = getNumberRangeError(schema, subject, false);
135
- if (rangeError) {
136
- return (0, fp_1.error)(rangeError);
139
+ if (typeof schema.max === 'number') {
140
+ if (updatedSubject > schema.max) {
141
+ return (0, fp_1.error)({
142
+ code: error_1.ERROR_CODE.invalidRange,
143
+ subject: updatedSubject,
144
+ path: this || [],
145
+ schema: schema,
146
+ });
147
+ }
137
148
  }
138
- return (0, fp_1.data)(subject);
149
+ return (0, fp_1.data)(updatedSubject);
139
150
  }
140
151
  case 'boolean': {
141
- if (typeof subject !== 'boolean') {
142
- if (subject === undefined || subject === null) {
143
- if (schema.optional) {
144
- if (typeof schema.default === 'boolean') {
145
- return (0, fp_1.data)(schema.default);
146
- }
147
- return (0, fp_1.data)(undefined);
148
- }
149
- }
152
+ if (typeof updatedSubject !== 'boolean') {
150
153
  return (0, fp_1.error)({
151
- code: error_1.PARSE_ERROR_CODE.invalidType,
154
+ code: error_1.ERROR_CODE.invalidType,
155
+ subject: updatedSubject,
156
+ path: this || [],
152
157
  schema: schema,
153
- subject: subject,
154
158
  });
155
159
  }
156
- return (0, fp_1.data)(subject);
160
+ return (0, fp_1.data)(updatedSubject);
157
161
  }
158
162
  case 'stringUnion': {
159
- if (typeof subject !== 'string') {
160
- if (subject === undefined || subject === null) {
161
- if (schema.optional) {
162
- if (typeof schema.default === 'string') {
163
- var unionSet_1 = new Set(schema.of);
164
- if (unionSet_1.has(schema.default) === false) {
165
- return (0, fp_1.error)({
166
- code: error_1.PARSE_ERROR_CODE.schemaDefaultNotInUnion,
167
- subject: schema.default,
168
- schema: schema,
169
- });
170
- }
171
- return (0, fp_1.data)(schema.default);
172
- }
173
- return (0, fp_1.data)(undefined);
174
- }
175
- }
163
+ if (typeof updatedSubject !== 'string') {
176
164
  return (0, fp_1.error)({
177
- code: error_1.PARSE_ERROR_CODE.invalidType,
165
+ code: error_1.ERROR_CODE.invalidType,
166
+ subject: updatedSubject,
167
+ path: this || [],
178
168
  schema: schema,
179
- subject: subject,
180
169
  });
181
170
  }
182
171
  var unionSet = new Set(schema.of);
183
- if (unionSet.has(subject) === false) {
172
+ if (unionSet.has(updatedSubject) === false) {
184
173
  return (0, fp_1.error)({
185
- code: error_1.PARSE_ERROR_CODE.notInUnion,
174
+ code: error_1.ERROR_CODE.invalidType,
175
+ subject: updatedSubject,
176
+ path: this || [],
186
177
  schema: schema,
187
- subject: subject,
188
178
  });
189
179
  }
190
- return (0, fp_1.data)(subject);
180
+ return (0, fp_1.data)(updatedSubject);
191
181
  }
192
182
  case 'numberUnion': {
193
- if (typeof subject !== 'number') {
194
- if (subject === undefined || subject === null) {
195
- if (schema.optional) {
196
- if (typeof schema.default === 'number') {
197
- var unionSet_2 = new Set(schema.of);
198
- if (unionSet_2.has(schema.default) === false) {
199
- return (0, fp_1.error)({
200
- code: error_1.PARSE_ERROR_CODE.schemaDefaultNotInUnion,
201
- subject: schema.default,
202
- schema: schema,
203
- });
204
- }
205
- return (0, fp_1.data)(schema.default);
206
- }
207
- return (0, fp_1.data)(undefined);
208
- }
209
- }
183
+ if (typeof updatedSubject !== 'number') {
210
184
  return (0, fp_1.error)({
211
- code: error_1.PARSE_ERROR_CODE.invalidType,
185
+ code: error_1.ERROR_CODE.invalidType,
186
+ subject: updatedSubject,
187
+ path: this || [],
212
188
  schema: schema,
213
- subject: subject,
214
189
  });
215
190
  }
216
191
  var unionSet = new Set(schema.of);
217
- if (unionSet.has(subject) === false) {
192
+ if (unionSet.has(updatedSubject) === false) {
218
193
  return (0, fp_1.error)({
219
- code: error_1.PARSE_ERROR_CODE.notInUnion,
194
+ code: error_1.ERROR_CODE.invalidType,
195
+ subject: updatedSubject,
196
+ path: this || [],
220
197
  schema: schema,
221
- subject: subject,
222
198
  });
223
199
  }
224
- return (0, fp_1.data)(subject);
200
+ return (0, fp_1.data)(updatedSubject);
225
201
  }
226
202
  }
227
203
  }
228
204
  exports.parseBaseSchemaSubject = parseBaseSchemaSubject;
229
- function getStringRangeError(schema, subject, isSubjectFromSchemaDefault) {
230
- if (typeof schema.minLength === 'number') {
231
- if (subject.length < schema.minLength) {
232
- return {
233
- code: isSubjectFromSchemaDefault
234
- ? error_1.PARSE_ERROR_CODE.schemaDefaultMinRange
235
- : error_1.PARSE_ERROR_CODE.minRange,
236
- schema: schema,
237
- subject: subject,
238
- };
239
- }
240
- }
241
- if (typeof schema.maxLength === 'number') {
242
- if (subject.length > schema.maxLength) {
243
- return {
244
- code: isSubjectFromSchemaDefault
245
- ? error_1.PARSE_ERROR_CODE.schemaDefaultMaxRange
246
- : error_1.PARSE_ERROR_CODE.maxRange,
247
- schema: schema,
248
- subject: subject,
249
- };
250
- }
251
- }
252
- }
253
- function getNumberRangeError(schema, subject, isSubjectFromSchemaDefault) {
254
- if (typeof schema.min === 'number') {
255
- if (subject < schema.min) {
256
- return {
257
- code: isSubjectFromSchemaDefault
258
- ? error_1.PARSE_ERROR_CODE.schemaDefaultMinRange
259
- : error_1.PARSE_ERROR_CODE.minRange,
260
- schema: schema,
261
- subject: subject,
262
- };
263
- }
264
- }
265
- if (typeof schema.max === 'number') {
266
- if (subject > schema.max) {
267
- return {
268
- code: isSubjectFromSchemaDefault
269
- ? error_1.PARSE_ERROR_CODE.schemaDefaultMaxRange
270
- : error_1.PARSE_ERROR_CODE.maxRange,
271
- schema: schema,
272
- subject: subject,
273
- };
274
- }
275
- }
276
- }
@@ -1,5 +1,5 @@
1
1
  import type { EitherError } from './utils/fp';
2
2
  import type { BaseSchema, Con_Schema_SubjT_V } from './types/compound-schema-types';
3
- import type { BaseSchemaValidateError } from './error';
3
+ import type { InvalidSubject, ErrorPath } from './error';
4
4
  export type BaseSchemaSubjectType = string | number | boolean | undefined;
5
- export declare function validateBaseSchemaSubject<T extends BaseSchema>(schema: T, schemaSubject: unknown): EitherError<BaseSchemaValidateError, Con_Schema_SubjT_V<T>>;
5
+ export declare function validateBaseSchemaSubject<T extends BaseSchema>(this: ErrorPath | void, schema: T, schemaSubject: unknown): EitherError<InvalidSubject, Con_Schema_SubjT_V<T>>;
@@ -13,7 +13,8 @@ function validateBaseSchemaSubject(schema, subject) {
13
13
  return (0, fp_1.data)(undefined);
14
14
  }
15
15
  return (0, fp_1.error)({
16
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
16
+ code: error_1.ERROR_CODE.invalidType,
17
+ path: this || [],
17
18
  schema: schema,
18
19
  subject: subject,
19
20
  });
@@ -27,21 +28,16 @@ function validateBaseSchemaSubject(schema, subject) {
27
28
  return (0, fp_1.data)(undefined);
28
29
  }
29
30
  return (0, fp_1.error)({
30
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
31
- schema: schema,
32
- subject: subject,
33
- });
34
- }
35
- if (Number.isNaN(subject)) {
36
- return (0, fp_1.error)({
37
- code: error_1.VALIDATE_ERROR_CODE.NaN,
31
+ code: error_1.ERROR_CODE.invalidType,
32
+ path: this || [],
38
33
  schema: schema,
39
34
  subject: subject,
40
35
  });
41
36
  }
42
37
  if (Number.isFinite(subject) === false) {
43
38
  return (0, fp_1.error)({
44
- code: error_1.VALIDATE_ERROR_CODE.infinity,
39
+ code: error_1.ERROR_CODE.invalidType,
40
+ path: this || [],
45
41
  schema: schema,
46
42
  subject: subject,
47
43
  });
@@ -55,7 +51,8 @@ function validateBaseSchemaSubject(schema, subject) {
55
51
  return (0, fp_1.data)(undefined);
56
52
  }
57
53
  return (0, fp_1.error)({
58
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
54
+ code: error_1.ERROR_CODE.invalidType,
55
+ path: this || [],
59
56
  schema: schema,
60
57
  subject: subject,
61
58
  });
@@ -71,7 +68,8 @@ function validateBaseSchemaSubject(schema, subject) {
71
68
  return (0, fp_1.data)(undefined);
72
69
  }
73
70
  return (0, fp_1.error)({
74
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
71
+ code: error_1.ERROR_CODE.invalidType,
72
+ path: this || [],
75
73
  schema: schema,
76
74
  subject: subject,
77
75
  });
@@ -79,7 +77,8 @@ function validateBaseSchemaSubject(schema, subject) {
79
77
  if (typeof schema.minLength === 'number') {
80
78
  if (subject.length < schema.minLength) {
81
79
  return (0, fp_1.error)({
82
- code: error_1.VALIDATE_ERROR_CODE.minRange,
80
+ code: error_1.ERROR_CODE.invalidRange,
81
+ path: this || [],
83
82
  schema: schema,
84
83
  subject: subject,
85
84
  });
@@ -88,7 +87,8 @@ function validateBaseSchemaSubject(schema, subject) {
88
87
  if (typeof schema.maxLength === 'number') {
89
88
  if (subject.length > schema.maxLength) {
90
89
  return (0, fp_1.error)({
91
- code: error_1.VALIDATE_ERROR_CODE.maxRange,
90
+ code: error_1.ERROR_CODE.invalidRange,
91
+ path: this || [],
92
92
  schema: schema,
93
93
  subject: subject,
94
94
  });
@@ -102,21 +102,16 @@ function validateBaseSchemaSubject(schema, subject) {
102
102
  return (0, fp_1.data)(undefined);
103
103
  }
104
104
  return (0, fp_1.error)({
105
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
106
- schema: schema,
107
- subject: subject,
108
- });
109
- }
110
- if (Number.isNaN(subject)) {
111
- return (0, fp_1.error)({
112
- code: error_1.VALIDATE_ERROR_CODE.NaN,
105
+ code: error_1.ERROR_CODE.invalidType,
106
+ path: this || [],
113
107
  schema: schema,
114
108
  subject: subject,
115
109
  });
116
110
  }
117
111
  if (Number.isFinite(subject) === false) {
118
112
  return (0, fp_1.error)({
119
- code: error_1.VALIDATE_ERROR_CODE.infinity,
113
+ code: error_1.ERROR_CODE.invalidType,
114
+ path: this || [],
120
115
  schema: schema,
121
116
  subject: subject,
122
117
  });
@@ -124,7 +119,8 @@ function validateBaseSchemaSubject(schema, subject) {
124
119
  if (typeof schema.min === 'number') {
125
120
  if (subject < schema.min) {
126
121
  return (0, fp_1.error)({
127
- code: error_1.VALIDATE_ERROR_CODE.minRange,
122
+ code: error_1.ERROR_CODE.invalidRange,
123
+ path: this || [],
128
124
  schema: schema,
129
125
  subject: subject,
130
126
  });
@@ -133,7 +129,8 @@ function validateBaseSchemaSubject(schema, subject) {
133
129
  if (typeof schema.max === 'number') {
134
130
  if (subject > schema.max) {
135
131
  return (0, fp_1.error)({
136
- code: error_1.VALIDATE_ERROR_CODE.maxRange,
132
+ code: error_1.ERROR_CODE.invalidRange,
133
+ path: this || [],
137
134
  schema: schema,
138
135
  subject: subject,
139
136
  });
@@ -147,7 +144,8 @@ function validateBaseSchemaSubject(schema, subject) {
147
144
  return (0, fp_1.data)(undefined);
148
145
  }
149
146
  return (0, fp_1.error)({
150
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
147
+ code: error_1.ERROR_CODE.invalidType,
148
+ path: this || [],
151
149
  schema: schema,
152
150
  subject: subject,
153
151
  });
@@ -160,7 +158,8 @@ function validateBaseSchemaSubject(schema, subject) {
160
158
  return (0, fp_1.data)(undefined);
161
159
  }
162
160
  return (0, fp_1.error)({
163
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
161
+ code: error_1.ERROR_CODE.invalidType,
162
+ path: this || [],
164
163
  schema: schema,
165
164
  subject: subject,
166
165
  });
@@ -168,7 +167,8 @@ function validateBaseSchemaSubject(schema, subject) {
168
167
  var unionSet = new Set(schema.of);
169
168
  if (unionSet.has(subject) === false) {
170
169
  return (0, fp_1.error)({
171
- code: error_1.VALIDATE_ERROR_CODE.notInUnion,
170
+ code: error_1.ERROR_CODE.invalidType,
171
+ path: this || [],
172
172
  schema: schema,
173
173
  subject: subject,
174
174
  });
@@ -181,7 +181,8 @@ function validateBaseSchemaSubject(schema, subject) {
181
181
  return (0, fp_1.data)(undefined);
182
182
  }
183
183
  return (0, fp_1.error)({
184
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
184
+ code: error_1.ERROR_CODE.invalidType,
185
+ path: this || [],
185
186
  schema: schema,
186
187
  subject: subject,
187
188
  });
@@ -189,7 +190,8 @@ function validateBaseSchemaSubject(schema, subject) {
189
190
  var unionSet = new Set(schema.of);
190
191
  if (unionSet.has(subject) === false) {
191
192
  return (0, fp_1.error)({
192
- code: error_1.VALIDATE_ERROR_CODE.notInUnion,
193
+ code: error_1.ERROR_CODE.invalidType,
194
+ path: this || [],
193
195
  schema: schema,
194
196
  subject: subject,
195
197
  });
package/dist/error.d.ts CHANGED
@@ -1,45 +1,15 @@
1
- import type { Schema, BaseSchema } from './types/compound-schema-types';
2
- export type ParseErrorCode = (typeof PARSE_ERROR_CODE)[keyof typeof PARSE_ERROR_CODE];
3
- export type ValidateErrorCode = (typeof VALIDATE_ERROR_CODE)[keyof typeof VALIDATE_ERROR_CODE];
4
- export type BaseSchemaParseError = {
5
- code: ParseErrorCode;
6
- schema: BaseSchema;
7
- subject: unknown;
8
- };
9
- export type BaseSchemaValidateError = {
10
- code: ValidateErrorCode;
11
- schema: BaseSchema;
12
- subject: unknown;
13
- };
14
- export type ErrorPath = Array<string | number>;
15
- export type ParseError = {
16
- path: ErrorPath;
1
+ import type { Schema } from './types/compound-schema-types';
2
+ export type ErrorCode = (typeof ERROR_CODE)[keyof typeof ERROR_CODE];
3
+ export type InvalidSubject = {
4
+ code: ErrorCode;
17
5
  schema: Schema;
18
6
  subject: unknown;
19
- };
20
- export type ValidateError = {
21
7
  path: ErrorPath;
22
- schema: Schema;
23
- subject: unknown;
24
8
  };
25
- export declare const PARSE_ERROR_CODE: {
26
- readonly invalidType: "INVALID_TYPE";
27
- readonly NaN: "NOT_A_NUMBER";
28
- readonly infinity: "INFINITY";
29
- readonly minRange: "MIN_RANGE";
30
- readonly maxRange: "MAX_RANGE";
31
- readonly notInUnion: "NOT_IN_UNION";
32
- readonly schemaDefaultMinRange: "SCHEMA_DEFAULT_MIN_RANGE";
33
- readonly schemaDefaultMaxRange: "SCHEMA_DEFAULT_MAX_RANGE";
34
- readonly schemaDefaultNotInUnion: "SCHEMA_DEFAULT_NOT_IN_UNION";
35
- };
36
- export declare const VALIDATE_ERROR_CODE: {
37
- readonly invalidType: "INVALID_TYPE";
38
- readonly NaN: "NOT_A_NUMBER";
39
- readonly infinity: "INFINITY";
40
- readonly minRange: "MIN_RANGE";
41
- readonly maxRange: "MAX_RANGE";
42
- readonly notInUnion: "NOT_IN_UNION";
9
+ export type ErrorPath = Array<string | number>;
10
+ export declare const ERROR_CODE: {
11
+ invalidType: string;
12
+ invalidRange: string;
43
13
  };
44
14
  export declare const PROGRAMMATICALLY_DEFINED_ERROR_MSG: {
45
15
  readonly optionalDefined: "Schema \"optional\" is already defined";
package/dist/error.js CHANGED
@@ -1,24 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PROGRAMMATICALLY_DEFINED_ERROR_MSG = exports.VALIDATE_ERROR_CODE = exports.PARSE_ERROR_CODE = void 0;
4
- exports.PARSE_ERROR_CODE = {
3
+ exports.PROGRAMMATICALLY_DEFINED_ERROR_MSG = exports.ERROR_CODE = void 0;
4
+ exports.ERROR_CODE = {
5
5
  invalidType: 'INVALID_TYPE',
6
- NaN: 'NOT_A_NUMBER',
7
- infinity: 'INFINITY',
8
- minRange: 'MIN_RANGE',
9
- maxRange: 'MAX_RANGE',
10
- notInUnion: 'NOT_IN_UNION',
11
- schemaDefaultMinRange: 'SCHEMA_DEFAULT_MIN_RANGE',
12
- schemaDefaultMaxRange: 'SCHEMA_DEFAULT_MAX_RANGE',
13
- schemaDefaultNotInUnion: 'SCHEMA_DEFAULT_NOT_IN_UNION',
14
- };
15
- exports.VALIDATE_ERROR_CODE = {
16
- invalidType: 'INVALID_TYPE',
17
- NaN: 'NOT_A_NUMBER',
18
- infinity: 'INFINITY',
19
- minRange: 'MIN_RANGE',
20
- maxRange: 'MAX_RANGE',
21
- notInUnion: 'NOT_IN_UNION',
6
+ invalidRange: 'INVALID_RANGE',
22
7
  };
23
8
  exports.PROGRAMMATICALLY_DEFINED_ERROR_MSG = {
24
9
  optionalDefined: 'Schema "optional" is already defined',
@@ -1,4 +1,4 @@
1
1
  import type { EitherError } from './utils/fp';
2
2
  import type { Schema, Con_Schema_SubjT_P } from './types/compound-schema-types';
3
- import type { ParseError } from './error';
4
- export declare function parse<T extends Schema>(schema: T, subject: unknown): EitherError<ParseError[], Con_Schema_SubjT_P<T>>;
3
+ import type { InvalidSubject } from './error';
4
+ export declare function parse<T extends Schema>(schema: T, subject: unknown): EitherError<InvalidSubject[], Con_Schema_SubjT_P<T>>;
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __read = (this && this.__read) || function (o, n) {
14
3
  var m = typeof Symbol === "function" && o[Symbol.iterator];
15
4
  if (!m) return o;
@@ -47,9 +36,9 @@ function parse(schema, subject) {
47
36
  schema.type === 'boolean' ||
48
37
  schema.type === 'stringUnion' ||
49
38
  schema.type === 'numberUnion') {
50
- var parsed = (0, base_schema_parser_1.parseBaseSchemaSubject)(schema, subject);
39
+ var parsed = base_schema_parser_1.parseBaseSchemaSubject.bind(this)(schema, subject);
51
40
  if (parsed.error) {
52
- return (0, fp_1.error)([__assign(__assign({}, parsed.error), { path: this || [] })]);
41
+ return (0, fp_1.error)([parsed.error]);
53
42
  }
54
43
  return parsed;
55
44
  }
@@ -65,7 +54,7 @@ function parse(schema, subject) {
65
54
  subject.constructor !== Object) {
66
55
  return (0, fp_1.error)([
67
56
  {
68
- code: error_1.PARSE_ERROR_CODE.invalidType,
57
+ code: error_1.ERROR_CODE.invalidType,
69
58
  path: this || [],
70
59
  schema: schema,
71
60
  subject: subject,
@@ -96,7 +85,7 @@ function parse(schema, subject) {
96
85
  }
97
86
  return (0, fp_1.error)([
98
87
  {
99
- code: error_1.PARSE_ERROR_CODE.invalidType,
88
+ code: error_1.ERROR_CODE.invalidType,
100
89
  path: this || [],
101
90
  subject: subject,
102
91
  schema: schema,
@@ -112,13 +101,33 @@ function parse(schema, subject) {
112
101
  parsed.error.forEach(function (err) { return errors.push(err); });
113
102
  continue;
114
103
  }
115
- if (parsed.data !== undefined) {
116
- result.push(parsed.data);
117
- }
104
+ result.push(parsed.data);
118
105
  }
119
106
  if (errors.length) {
120
107
  return (0, fp_1.error)(errors);
121
108
  }
109
+ if (typeof schema.minLength === 'number' &&
110
+ result.length < schema.minLength) {
111
+ return (0, fp_1.error)([
112
+ {
113
+ code: error_1.ERROR_CODE.invalidRange,
114
+ path: this || [],
115
+ subject: subject,
116
+ schema: schema,
117
+ },
118
+ ]);
119
+ }
120
+ if (typeof schema.maxLength === 'number' &&
121
+ result.length > schema.maxLength) {
122
+ return (0, fp_1.error)([
123
+ {
124
+ code: error_1.ERROR_CODE.invalidRange,
125
+ path: this || [],
126
+ subject: subject,
127
+ schema: schema,
128
+ },
129
+ ]);
130
+ }
122
131
  return (0, fp_1.data)(result);
123
132
  }
124
133
  exports.parse = parse;
@@ -1,4 +1,4 @@
1
1
  import type { EitherError } from './utils/fp';
2
2
  import type { Schema, Con_Schema_SubjT_V } from './types/compound-schema-types';
3
- import type { ValidateError } from './error';
4
- export declare function validate<T extends Schema>(schema: T, subject: Con_Schema_SubjT_V<T>): EitherError<ValidateError[], Con_Schema_SubjT_V<T>>;
3
+ import type { InvalidSubject } from './error';
4
+ export declare function validate<T extends Schema>(schema: T, subject: Con_Schema_SubjT_V<T>): EitherError<InvalidSubject[], Con_Schema_SubjT_V<T>>;
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __read = (this && this.__read) || function (o, n) {
14
3
  var m = typeof Symbol === "function" && o[Symbol.iterator];
15
4
  if (!m) return o;
@@ -47,9 +36,9 @@ function validate(schema, subject) {
47
36
  schema.type === 'boolean' ||
48
37
  schema.type === 'stringUnion' ||
49
38
  schema.type === 'numberUnion') {
50
- var validated = (0, base_schema_validator_1.validateBaseSchemaSubject)(schema, subject);
39
+ var validated = base_schema_validator_1.validateBaseSchemaSubject.bind(this)(schema, subject);
51
40
  if (validated.error) {
52
- return (0, fp_1.error)([__assign(__assign({}, validated.error), { path: this || [] })]);
41
+ return (0, fp_1.error)([validated.error]);
53
42
  }
54
43
  return (0, fp_1.data)(subject);
55
44
  }
@@ -63,7 +52,7 @@ function validate(schema, subject) {
63
52
  subject.constructor !== Object) {
64
53
  return (0, fp_1.error)([
65
54
  {
66
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
55
+ code: error_1.ERROR_CODE.invalidType,
67
56
  path: this || [],
68
57
  schema: schema,
69
58
  subject: subject,
@@ -91,7 +80,7 @@ function validate(schema, subject) {
91
80
  }
92
81
  return (0, fp_1.error)([
93
82
  {
94
- code: error_1.VALIDATE_ERROR_CODE.invalidType,
83
+ code: error_1.ERROR_CODE.invalidType,
95
84
  path: this || [],
96
85
  subject: subject,
97
86
  schema: schema,
@@ -110,6 +99,28 @@ function validate(schema, subject) {
110
99
  if (errors.length) {
111
100
  return (0, fp_1.error)(errors);
112
101
  }
102
+ if (typeof schema.minLength === 'number' &&
103
+ subject.length < schema.minLength) {
104
+ return (0, fp_1.error)([
105
+ {
106
+ code: error_1.ERROR_CODE.invalidRange,
107
+ path: this || [],
108
+ subject: subject,
109
+ schema: schema,
110
+ },
111
+ ]);
112
+ }
113
+ if (typeof schema.maxLength === 'number' &&
114
+ subject.length > schema.maxLength) {
115
+ return (0, fp_1.error)([
116
+ {
117
+ code: error_1.ERROR_CODE.invalidRange,
118
+ path: this || [],
119
+ subject: subject,
120
+ schema: schema,
121
+ },
122
+ ]);
123
+ }
113
124
  return (0, fp_1.data)(subject);
114
125
  }
115
126
  exports.validate = validate;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@
8
8
  * but only with a MINOR version update.
9
9
  **/
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.x = exports.validate = exports.parse = exports.object = exports.array = exports.numberUnion = exports.stringUnion = exports.boolean = exports.number = exports.string = void 0;
11
+ exports.data = exports.error = exports.isData = exports.isError = exports.x = exports.validate = exports.parse = exports.object = exports.array = exports.numberUnion = exports.stringUnion = exports.boolean = exports.number = exports.string = void 0;
12
12
  /* Programmatically base schema definition */
13
13
  var string_1 = require("./programmatic-schema/string");
14
14
  Object.defineProperty(exports, "string", { enumerable: true, get: function () { return string_1.string; } });
@@ -32,3 +32,8 @@ var general_schema_validator_1 = require("./general-schema-validator");
32
32
  Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return general_schema_validator_1.validate; } });
33
33
  var x_closure_1 = require("./x-closure");
34
34
  Object.defineProperty(exports, "x", { enumerable: true, get: function () { return x_closure_1.x; } });
35
+ var fp_1 = require("./utils/fp");
36
+ Object.defineProperty(exports, "isError", { enumerable: true, get: function () { return fp_1.isError; } });
37
+ Object.defineProperty(exports, "isData", { enumerable: true, get: function () { return fp_1.isData; } });
38
+ Object.defineProperty(exports, "error", { enumerable: true, get: function () { return fp_1.error; } });
39
+ Object.defineProperty(exports, "data", { enumerable: true, get: function () { return fp_1.data; } });
package/dist/index.ts CHANGED
@@ -35,6 +35,12 @@ export { x } from './x-closure'
35
35
  /* Typings */
36
36
 
37
37
  export type { BaseSchema, Schema } from './types/compound-schema-types'
38
+ export type { InvalidSubject } from './error'
39
+
40
+ /* Utils */
41
+
42
+ export type { EitherError } from './utils/fp'
43
+ export { isError, isData, error, data } from './utils/fp'
38
44
 
39
45
  /* XParsed infers set optional default schema value as always present */
40
46
  export type XParsed<T extends { __schema: Schema } | Schema> = T extends {
@@ -14,6 +14,9 @@ type R<T> =
14
14
  | ({ type: 'array'; of: T } & ArrSchemaOptProps)
15
15
  | ({ type: 'object'; of: Record<string, T> } & ObjSchemaOptProps)
16
16
 
17
+ /* 7 layers of compound schema nesting is allowed */
18
+ type NestedSchema = R<R<R<R<R<R<BaseSchema>>>>>>
19
+
17
20
  /* ArraySchema */
18
21
 
19
22
  export type ArrSchemaOptProps = {
@@ -23,11 +26,10 @@ export type ArrSchemaOptProps = {
23
26
  maxLength?: number /* <= */
24
27
  }
25
28
 
26
- export type ArraySchema<T extends Schema = R<R<R<R<R<R<BaseSchema>>>>>>> =
27
- ArrSchemaOptProps & {
28
- type: 'array'
29
- of: T
30
- }
29
+ export type ArraySchema<T extends Schema = NestedSchema> = ArrSchemaOptProps & {
30
+ type: 'array'
31
+ of: T
32
+ }
31
33
 
32
34
  /* ObjectSchema */
33
35
 
@@ -36,7 +38,7 @@ export type ObjSchemaOptProps = {
36
38
  description?: string
37
39
  }
38
40
 
39
- export type ObjectSchema<T extends Schema = R<R<R<R<R<R<BaseSchema>>>>>>> =
41
+ export type ObjectSchema<T extends Schema = NestedSchema> =
40
42
  ObjSchemaOptProps & {
41
43
  type: 'object'
42
44
  of: Record<string, T>
@@ -63,12 +65,6 @@ export type ExtWith_CompoundSchemaOptionality<
63
65
  U,
64
66
  > = T extends { optional: true } ? U | undefined : U
65
67
 
66
- // TODO: should work as expected only if we add `& {}`
67
- // which is currently forbidden by our linter
68
- export type Prettify_ObjectSchema_SubjT<T> = {
69
- [k in keyof T]: T[k]
70
- }
71
-
72
68
  /* Construct ArraySchema subject type */
73
69
 
74
70
  export type Con_ArraySchema_SubjT_P<T extends ArraySchema> =
@@ -76,11 +72,11 @@ export type Con_ArraySchema_SubjT_P<T extends ArraySchema> =
76
72
  T,
77
73
  T extends { of: infer U }
78
74
  ? U extends BaseSchema
79
- ? Array<NonNullable<Con_BaseSchema_SubjT_P<U>>>
75
+ ? Array<Con_BaseSchema_SubjT_P<U>>
80
76
  : U extends ArraySchema
81
- ? Array<NonNullable<Con_ArraySchema_SubjT_P<U>>>
77
+ ? Array<Con_ArraySchema_SubjT_P<U>>
82
78
  : U extends ObjectSchema
83
- ? Array<NonNullable<Con_ObjectSchema_SubjT_P<U>>>
79
+ ? Array<Con_ObjectSchema_SubjT_P<U>>
84
80
  : never
85
81
  : never
86
82
  >
@@ -3,6 +3,6 @@ export declare function x<T extends Schema>(schemaDefinition: T | {
3
3
  __schema: T;
4
4
  }): {
5
5
  __schema: T;
6
- validate: (subject: Con_Schema_SubjT_V<T>) => import("./utils/fp").EitherError<import("./error").ValidateError[], Con_Schema_SubjT_V<T>>;
7
- parse: <T_1 = unknown>(subject: T_1) => import("./utils/fp").EitherError<import("./error").ParseError[], import("./types/compound-schema-types").Con_Schema_SubjT_P<T>>;
6
+ validate: (subject: Con_Schema_SubjT_V<T>) => import(".").EitherError<import("./error").InvalidSubject[], Con_Schema_SubjT_V<T>>;
7
+ parse: <T_1 = unknown>(subject: T_1) => import(".").EitherError<import("./error").InvalidSubject[], import("./types/compound-schema-types").Con_Schema_SubjT_P<T>>;
8
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schematox",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Define JSON compatible schema statically/programmatically and parse/validate its subject with typesafety",
5
5
  "author": "Konstantin Mazur",
6
6
  "license": "MIT",