schematox 0.1.2 → 0.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.json CHANGED
@@ -15,7 +15,15 @@
15
15
  "no-async-promise-executor": "off",
16
16
  "quotes": "off",
17
17
  "semi": "off",
18
- "@typescript-eslint/no-var-requires": "off"
18
+ "@typescript-eslint/no-var-requires": "off",
19
+ "@typescript-eslint/ban-types": [
20
+ "error",
21
+ {
22
+ "types": {
23
+ "{}": false
24
+ }
25
+ }
26
+ ]
19
27
  },
20
28
  "ignorePatterns": ["/dist"]
21
29
  }
package/README.md CHANGED
@@ -83,19 +83,19 @@ const subject = {
83
83
 
84
84
  const parsed = parse(userSchema, subject)
85
85
 
86
- if (parsed.error) {
86
+ if (parsed.left) {
87
87
  throw Error('Not expected')
88
88
  }
89
89
 
90
- console.log(parsed.data) // { id: '1', name: 'John' }
90
+ console.log(parsed.right) // { id: '1', name: 'John' }
91
91
 
92
92
  const validated = validate(userSchema, subject)
93
93
 
94
- if (validated.error) {
94
+ if (validated.left) {
95
95
  throw Error('Not expected')
96
96
  }
97
97
 
98
- console.log(validated.data) // { id: '1', name: 'John' }
98
+ console.log(validated.right) // { id: '1', name: 'John' }
99
99
 
100
100
  if (guard(userSchema, subject)) {
101
101
  // { id: string & { __idFor: 'User' }; name: string }
@@ -120,19 +120,19 @@ const subject = { id: '1', name: 'John' } as unknown
120
120
 
121
121
  const parsed = struct.parse(subject)
122
122
 
123
- if (parsed.error) {
123
+ if (parsed.left) {
124
124
  throw Error('Not expected')
125
125
  }
126
126
 
127
- console.log(parsed.data) // { id: '1', name: 'John' }
127
+ console.log(parsed.right) // { id: '1', name: 'John' }
128
128
 
129
129
  const validated = struct.validate(subject)
130
130
 
131
- if (validated.error) {
131
+ if (validated.left) {
132
132
  throw Error('Not expected')
133
133
  }
134
134
 
135
- console.log(validated.data) // { id: '1', name: 'John' }
135
+ console.log(validated.right) // { id: '1', name: 'John' }
136
136
 
137
137
  if (struct.guard(subject)) {
138
138
  // { id: string & { __idFor: 'User' }; name: string }
@@ -325,8 +325,19 @@ type FromStruct = SubjectType<typeof struct>
325
325
 
326
326
  ## Schema parameters
327
327
 
328
- - `optional?: boolean` – does `undefined` is valid value
329
- - `nullable?: boolean` – does `null` is valid value
328
+ - `optional?: boolean` –  unionize with `undefined`: `{ type: 'string', optinoal: true }` result in `string | undefined`
329
+
330
+ In the context of the object, optional values will be treated as optional properties:
331
+
332
+ ```typescript
333
+ const struct = object({ x: string().optional() })
334
+
335
+ type ExpectedSubjectType = {
336
+ x?: string | undefined
337
+ }
338
+ ```
339
+
340
+ - `nullable?: boolean` – unionize with `null`: `{ type: 'string', nullable: true }` result in `string | null`
330
341
  - `brand?: [string, string]` – make primitive type nominal "['idFor', 'User'] -> T & { \_\_idFor: 'User' }"
331
342
  - `minLength/maxLength/min/max` – schema type dependent limiting characteristics
332
343
  - `description?: string` – description of the particular schema property which can be used to provide more detailed information for the user/developer on validation/parse error
@@ -351,7 +362,7 @@ const struct = object({
351
362
  const result = struct.parse({ x: { y: [{ z: 0 }] } })
352
363
  ```
353
364
 
354
- The `result.error` shape is:
365
+ The `result.left` shape is:
355
366
 
356
367
  ```json
357
368
  [
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.guard = exports.validate = exports.parse = exports.data = exports.error = exports.object = exports.array = exports.union = exports.literal = exports.boolean = exports.number = exports.string = exports.ERROR_CODE = void 0;
3
+ exports.guard = exports.validate = exports.parse = exports.right = exports.left = exports.object = exports.array = exports.union = exports.literal = exports.boolean = exports.number = exports.string = exports.makeStruct = exports.ERROR_CODE = void 0;
4
4
  var error_1 = require("./error");
5
5
  Object.defineProperty(exports, "ERROR_CODE", { enumerable: true, get: function () { return error_1.ERROR_CODE; } });
6
6
  var struct_1 = require("./struct");
7
+ Object.defineProperty(exports, "makeStruct", { enumerable: true, get: function () { return struct_1.makeStruct; } });
7
8
  Object.defineProperty(exports, "string", { enumerable: true, get: function () { return struct_1.string; } });
8
9
  Object.defineProperty(exports, "number", { enumerable: true, get: function () { return struct_1.number; } });
9
10
  Object.defineProperty(exports, "boolean", { enumerable: true, get: function () { return struct_1.boolean; } });
@@ -12,8 +13,8 @@ Object.defineProperty(exports, "union", { enumerable: true, get: function () { r
12
13
  Object.defineProperty(exports, "array", { enumerable: true, get: function () { return struct_1.array; } });
13
14
  Object.defineProperty(exports, "object", { enumerable: true, get: function () { return struct_1.object; } });
14
15
  var fp_1 = require("./utils/fp");
15
- Object.defineProperty(exports, "error", { enumerable: true, get: function () { return fp_1.error; } });
16
- Object.defineProperty(exports, "data", { enumerable: true, get: function () { return fp_1.data; } });
16
+ Object.defineProperty(exports, "left", { enumerable: true, get: function () { return fp_1.left; } });
17
+ Object.defineProperty(exports, "right", { enumerable: true, get: function () { return fp_1.right; } });
17
18
  var parse_1 = require("./parse");
18
19
  Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return parse_1.parse; } });
19
20
  var validate_1 = require("./validate");
package/dist/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { ERROR_CODE } from './error'
2
2
 
3
3
  export {
4
+ makeStruct,
4
5
  string,
5
6
  number,
6
7
  boolean,
@@ -10,11 +11,25 @@ export {
10
11
  object,
11
12
  } from './struct'
12
13
 
13
- export { error, data } from './utils/fp'
14
+ export { left, right } from './utils/fp'
14
15
  export { parse } from './parse'
15
16
  export { validate, guard } from './validate'
16
17
 
17
- export type { Schema } from './types/compounds'
18
+ export type {
19
+ StringSchema,
20
+ NumberSchema,
21
+ BooleanSchema,
22
+ LiteralSchema,
23
+ PrimitiveSchema,
24
+ } from './types/primitives'
25
+
26
+ export type {
27
+ Schema,
28
+ BaseArraySchema,
29
+ BaseObjectSchema,
30
+ BaseUnionSchema,
31
+ } from './types/compounds'
32
+
18
33
  export type { SubjectType } from './types/constructors'
19
34
 
20
35
  export type { InvalidSubject, ErrorPath, ErrorCode } from './error'
package/dist/parse.js CHANGED
@@ -44,16 +44,16 @@ function parse(schema, subject) {
44
44
  var e_1, _a;
45
45
  var errors = [];
46
46
  if (schema.optional === true && subject === undefined) {
47
- return (0, fp_1.data)(undefined);
47
+ return (0, fp_1.right)(undefined);
48
48
  }
49
49
  if (schema.nullable === true && subject === null) {
50
- return (0, fp_1.data)(null);
50
+ return (0, fp_1.right)(null);
51
51
  }
52
52
  if (schema.type === 'object') {
53
53
  if (typeof subject !== 'object' ||
54
54
  subject === null ||
55
55
  subject.constructor !== Object) {
56
- return (0, fp_1.error)([
56
+ return (0, fp_1.left)([
57
57
  {
58
58
  code: error_1.ERROR_CODE.invalidType,
59
59
  path: this || [],
@@ -67,20 +67,20 @@ function parse(schema, subject) {
67
67
  var nestedSchema = schema.of[key];
68
68
  var nestedValue = subject[key];
69
69
  var parsed = parse.bind(__spreadArray(__spreadArray([], __read((this || [])), false), [key], false))(nestedSchema, nestedValue);
70
- if (parsed.error) {
71
- parsed.error.forEach(function (err) { return errors.push(err); });
70
+ if (parsed.left) {
71
+ parsed.left.forEach(function (err) { return errors.push(err); });
72
72
  continue;
73
73
  }
74
- result[key] = parsed.data;
74
+ result[key] = parsed.right;
75
75
  }
76
76
  if (errors.length) {
77
- return (0, fp_1.error)(errors);
77
+ return (0, fp_1.left)(errors);
78
78
  }
79
- return (0, fp_1.data)(result);
79
+ return (0, fp_1.right)(result);
80
80
  }
81
81
  if (schema.type === 'array') {
82
82
  if (Array.isArray(subject) === false) {
83
- return (0, fp_1.error)([
83
+ return (0, fp_1.left)([
84
84
  {
85
85
  code: error_1.ERROR_CODE.invalidType,
86
86
  path: this || [],
@@ -94,18 +94,18 @@ function parse(schema, subject) {
94
94
  var nestedSchema = schema.of;
95
95
  var nestedValue = subject[i];
96
96
  var parsed = parse.bind(__spreadArray(__spreadArray([], __read((this || [])), false), [i], false))(nestedSchema, nestedValue);
97
- if (parsed.error) {
98
- parsed.error.forEach(function (err) { return errors.push(err); });
97
+ if (parsed.left) {
98
+ parsed.left.forEach(function (err) { return errors.push(err); });
99
99
  continue;
100
100
  }
101
- result.push(parsed.data);
101
+ result.push(parsed.right);
102
102
  }
103
103
  if (errors.length) {
104
- return (0, fp_1.error)(errors);
104
+ return (0, fp_1.left)(errors);
105
105
  }
106
106
  if (typeof schema.minLength === 'number' &&
107
107
  result.length < schema.minLength) {
108
- return (0, fp_1.error)([
108
+ return (0, fp_1.left)([
109
109
  {
110
110
  code: error_1.ERROR_CODE.invalidRange,
111
111
  path: this || [],
@@ -116,7 +116,7 @@ function parse(schema, subject) {
116
116
  }
117
117
  if (typeof schema.maxLength === 'number' &&
118
118
  result.length > schema.maxLength) {
119
- return (0, fp_1.error)([
119
+ return (0, fp_1.left)([
120
120
  {
121
121
  code: error_1.ERROR_CODE.invalidRange,
122
122
  path: this || [],
@@ -125,15 +125,15 @@ function parse(schema, subject) {
125
125
  },
126
126
  ]);
127
127
  }
128
- return (0, fp_1.data)(result);
128
+ return (0, fp_1.right)(result);
129
129
  }
130
130
  if (schema.type === 'union') {
131
131
  try {
132
132
  for (var _b = __values(schema.of), _c = _b.next(); !_c.done; _c = _b.next()) {
133
133
  var subSchema = _c.value;
134
134
  var parsed = parse(subSchema, subject);
135
- if (parsed.error === undefined) {
136
- return (0, fp_1.data)(parsed.data);
135
+ if (parsed.left === undefined) {
136
+ return (0, fp_1.right)(parsed.right);
137
137
  }
138
138
  }
139
139
  }
@@ -144,7 +144,7 @@ function parse(schema, subject) {
144
144
  }
145
145
  finally { if (e_1) throw e_1.error; }
146
146
  }
147
- return (0, fp_1.error)([
147
+ return (0, fp_1.left)([
148
148
  {
149
149
  code: error_1.ERROR_CODE.invalidType,
150
150
  path: this || [],
@@ -155,9 +155,9 @@ function parse(schema, subject) {
155
155
  }
156
156
  var verified = (0, verify_primitive_1.verifyPrimitive)(schema, subject);
157
157
  if (verified === true) {
158
- return (0, fp_1.data)(subject);
158
+ return (0, fp_1.right)(subject);
159
159
  }
160
- return (0, fp_1.error)([
160
+ return (0, fp_1.left)([
161
161
  {
162
162
  code: verified,
163
163
  path: this || [],
package/dist/struct.js CHANGED
@@ -33,7 +33,7 @@ function makeStruct(schema) {
33
33
  parse: function (subj) { return (0, parse_1.parse)(schema, subj); },
34
34
  validate: function (subj) { return (0, validate_1.validate)(schema, subj); },
35
35
  guard: function (subj) {
36
- return (0, validate_1.validate)(schema, subj).error === undefined;
36
+ return (0, validate_1.validate)(schema, subj).left === undefined;
37
37
  },
38
38
  };
39
39
  if (params.has('optional')) {
@@ -1,6 +1,6 @@
1
1
  import type { PrimitiveSchema } from './primitives'
2
2
 
3
- type BaseObjectSchema<T> = {
3
+ export type BaseObjectSchema<T> = {
4
4
  type: 'object'
5
5
  of: Record<string, T>
6
6
 
@@ -10,7 +10,7 @@ type BaseObjectSchema<T> = {
10
10
  description?: string
11
11
  }
12
12
 
13
- type BaseArraySchema<T> = {
13
+ export type BaseArraySchema<T> = {
14
14
  type: 'array'
15
15
  of: T
16
16
 
@@ -23,7 +23,7 @@ type BaseArraySchema<T> = {
23
23
  }
24
24
 
25
25
  // TODO: `discriminant` key as performance optimization measure
26
- type BaseUnionSchema<T> = {
26
+ export type BaseUnionSchema<T> = {
27
27
  type: 'union'
28
28
  of: Readonly<Array<T>>
29
29
 
@@ -32,14 +32,35 @@ type Con_ArraySchema_SubjT<T extends ArraySchema> = T extends { of: infer U }
32
32
  : never
33
33
  : never
34
34
 
35
+ type Prettify<T extends Record<string, unknown>> = {
36
+ [K in keyof T]: T[K]
37
+ } & {}
38
+
39
+ /**
40
+ * ```MakeOptional{ x: T | undefined, y: T }```
41
+ *
42
+ * will make:
43
+ *
44
+ * ```{ x?: T | undefined, y: T }```
45
+ *
46
+ * NOTE: `Exclude<T[K], undefined> will not work
47
+ * so we have technical constraint here
48
+ **/
49
+ type MakeOptional<T> = Prettify<
50
+ {
51
+ [K in keyof T as undefined extends T[K] ? K : never]?: T[K]
52
+ } & {
53
+ [K in keyof T as undefined extends T[K] ? never : K]: T[K]
54
+ }
55
+ >
35
56
  type Con_ObjectSchema_SubjT<T extends ObjectSchema> = T extends {
36
57
  of: infer U
37
58
  }
38
- ? {
59
+ ? MakeOptional<{
39
60
  -readonly [k in keyof U]: U[k] extends Schema
40
61
  ? Con_Schema_SubjT<U[k]>
41
62
  : never
42
- }
63
+ }>
43
64
  : never
44
65
 
45
66
  type Con_UnionSchema_SubjT<T extends UnionSchema> = T extends {
@@ -1,11 +1,11 @@
1
1
  export type Error<T> = {
2
- error: T;
3
- data?: never;
2
+ left: T;
3
+ right?: never;
4
4
  };
5
5
  export type Data<U> = {
6
- error?: never;
7
- data: U;
6
+ left?: never;
7
+ right: U;
8
8
  };
9
9
  export type EitherError<T, U> = NonNullable<Error<T> | Data<U>>;
10
- export declare const error: <T>(value: T) => Error<T>;
11
- export declare const data: <U>(value: U) => Data<U>;
10
+ export declare const left: <T>(value: T) => Error<T>;
11
+ export declare const right: <U>(value: U) => Data<U>;
package/dist/utils/fp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.data = exports.error = void 0;
4
- var error = function (value) { return ({ error: value }); };
5
- exports.error = error;
6
- var data = function (value) { return ({ data: value }); };
7
- exports.data = data;
3
+ exports.right = exports.left = void 0;
4
+ var left = function (value) { return ({ left: value }); };
5
+ exports.left = left;
6
+ var right = function (value) { return ({ right: value }); };
7
+ exports.right = right;
package/dist/validate.js CHANGED
@@ -44,16 +44,16 @@ function validate(schema, subject) {
44
44
  var e_1, _a;
45
45
  var errors = [];
46
46
  if (schema.optional === true && subject === undefined) {
47
- return (0, fp_1.data)(undefined);
47
+ return (0, fp_1.right)(undefined);
48
48
  }
49
49
  if (schema.nullable === true && subject === null) {
50
- return (0, fp_1.data)(null);
50
+ return (0, fp_1.right)(null);
51
51
  }
52
52
  if (schema.type === 'object') {
53
53
  if (typeof subject !== 'object' ||
54
54
  subject === null ||
55
55
  subject.constructor !== Object) {
56
- return (0, fp_1.error)([
56
+ return (0, fp_1.left)([
57
57
  {
58
58
  code: error_1.ERROR_CODE.invalidType,
59
59
  path: this || [],
@@ -68,13 +68,13 @@ function validate(schema, subject) {
68
68
  var nestedValue = subject[key];
69
69
  var nestedSchema = schema.of[key];
70
70
  var validated = validate.bind(__spreadArray(__spreadArray([], __read((this || [])), false), [key], false))(nestedSchema, nestedValue);
71
- if (validated.error) {
72
- validated.error.forEach(function (err) { return errors.push(err); });
71
+ if (validated.left) {
72
+ validated.left.forEach(function (err) { return errors.push(err); });
73
73
  continue;
74
74
  }
75
75
  }
76
76
  if (errors.length) {
77
- return (0, fp_1.error)(errors);
77
+ return (0, fp_1.left)(errors);
78
78
  }
79
79
  if (subjectKeySet.size !== 0) {
80
80
  errors.push({
@@ -83,13 +83,13 @@ function validate(schema, subject) {
83
83
  schema: schema,
84
84
  path: this || [],
85
85
  });
86
- return (0, fp_1.error)(errors);
86
+ return (0, fp_1.left)(errors);
87
87
  }
88
- return (0, fp_1.data)(subject);
88
+ return (0, fp_1.right)(subject);
89
89
  }
90
90
  if (schema.type === 'array') {
91
91
  if (Array.isArray(subject) === false) {
92
- return (0, fp_1.error)([
92
+ return (0, fp_1.left)([
93
93
  {
94
94
  code: error_1.ERROR_CODE.invalidType,
95
95
  path: this || [],
@@ -102,17 +102,17 @@ function validate(schema, subject) {
102
102
  var nestedSchema = schema.of;
103
103
  var nestedValue = subject[i];
104
104
  var validated = validate.bind(__spreadArray(__spreadArray([], __read((this || [])), false), [i], false))(nestedSchema, nestedValue);
105
- if (validated.error) {
106
- validated.error.forEach(function (err) { return errors.push(err); });
105
+ if (validated.left) {
106
+ validated.left.forEach(function (err) { return errors.push(err); });
107
107
  continue;
108
108
  }
109
109
  }
110
110
  if (errors.length) {
111
- return (0, fp_1.error)(errors);
111
+ return (0, fp_1.left)(errors);
112
112
  }
113
113
  if (typeof schema.minLength === 'number' &&
114
114
  subject.length < schema.minLength) {
115
- return (0, fp_1.error)([
115
+ return (0, fp_1.left)([
116
116
  {
117
117
  code: error_1.ERROR_CODE.invalidRange,
118
118
  path: this || [],
@@ -123,7 +123,7 @@ function validate(schema, subject) {
123
123
  }
124
124
  if (typeof schema.maxLength === 'number' &&
125
125
  subject.length > schema.maxLength) {
126
- return (0, fp_1.error)([
126
+ return (0, fp_1.left)([
127
127
  {
128
128
  code: error_1.ERROR_CODE.invalidRange,
129
129
  path: this || [],
@@ -132,14 +132,14 @@ function validate(schema, subject) {
132
132
  },
133
133
  ]);
134
134
  }
135
- return (0, fp_1.data)(subject);
135
+ return (0, fp_1.right)(subject);
136
136
  }
137
137
  if (schema.type === 'union') {
138
138
  try {
139
139
  for (var _b = __values(schema.of), _c = _b.next(); !_c.done; _c = _b.next()) {
140
140
  var subSchema = _c.value;
141
- if (validate(subSchema, subject).error === undefined) {
142
- return (0, fp_1.data)(subject);
141
+ if (validate(subSchema, subject).left === undefined) {
142
+ return (0, fp_1.right)(subject);
143
143
  }
144
144
  }
145
145
  }
@@ -150,7 +150,7 @@ function validate(schema, subject) {
150
150
  }
151
151
  finally { if (e_1) throw e_1.error; }
152
152
  }
153
- return (0, fp_1.error)([
153
+ return (0, fp_1.left)([
154
154
  {
155
155
  code: error_1.ERROR_CODE.invalidType,
156
156
  path: this || [],
@@ -161,9 +161,9 @@ function validate(schema, subject) {
161
161
  }
162
162
  var verified = (0, verify_primitive_1.verifyPrimitive)(schema, subject);
163
163
  if (verified === true) {
164
- return (0, fp_1.data)(subject);
164
+ return (0, fp_1.right)(subject);
165
165
  }
166
- return (0, fp_1.error)([
166
+ return (0, fp_1.left)([
167
167
  {
168
168
  code: verified,
169
169
  path: this || [],
@@ -174,6 +174,6 @@ function validate(schema, subject) {
174
174
  }
175
175
  exports.validate = validate;
176
176
  function guard(schema, subject) {
177
- return validate(schema, subject).error === undefined;
177
+ return validate(schema, subject).left === undefined;
178
178
  }
179
179
  exports.guard = guard;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schematox",
3
- "version": "0.1.2",
3
+ "version": "0.3.0-beta.0",
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",