schema-shield 0.0.2 → 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.
package/lib/types.ts CHANGED
@@ -1,176 +1,49 @@
1
- import { ValidationError } from "./utils";
2
- import { ValidatorFunction } from "./index";
1
+ import { TypeFunction } from "./index";
2
+ import { isObject } from "./utils";
3
3
 
4
- export const Types: Record<string, ValidatorFunction> = {
5
- object(schema, data, pointer) {
6
- if (typeof data === "object" && data !== null && !Array.isArray(data)) {
7
- return {
8
- valid: true,
9
- errors: [],
10
- data
11
- };
12
- }
13
-
14
- return {
15
- valid: false,
16
- errors: [
17
- new ValidationError("Data is not an object", {
18
- pointer,
19
- value: data,
20
- code: "NOT_AN_OBJECT"
21
- })
22
- ],
23
- data
24
- };
4
+ export const Types: Record<string, TypeFunction | false> = {
5
+ object(data) {
6
+ return isObject(data);
25
7
  },
26
- array(schema, data, pointer) {
8
+ array(data) {
27
9
  if (Array.isArray(data)) {
28
- return {
29
- valid: true,
30
- errors: [],
31
- data
32
- };
33
- }
34
-
35
- if (typeof data === "object" && data !== null && "length" in data) {
36
- // Check if the first key is a number and the length is the same as the number of keys - 1 (length)
37
- const keys = Object.keys(data);
38
- if (keys.length > 0 && (keys[0] !== "0" || keys.length !== data.length)) {
39
- return {
40
- valid: false,
41
- errors: [
42
- new ValidationError("Data is not an array", {
43
- pointer,
44
- value: data,
45
- code: "NOT_AN_ARRAY"
46
- })
47
- ],
48
- data
49
- };
50
- }
51
-
52
- return {
53
- valid: true,
54
- errors: [],
55
- data
56
- };
10
+ return true;
57
11
  }
58
12
 
59
- return {
60
- valid: false,
61
- errors: [
62
- new ValidationError("Data is not an array", {
63
- pointer,
64
- value: data,
65
- code: "NOT_AN_ARRAY"
66
- })
67
- ],
68
- data
69
- };
13
+ return (
14
+ typeof data === "object" &&
15
+ data !== null &&
16
+ "length" in data &&
17
+ "0" in data &&
18
+ Object.keys(data).length - 1 === data.length
19
+ );
70
20
  },
71
- string(schema, data, pointer) {
72
- if (typeof data === "string") {
73
- return {
74
- valid: true,
75
- errors: [],
76
- data
77
- };
78
- }
79
-
80
- return {
81
- valid: false,
82
- errors: [
83
- new ValidationError("Data is not a string", {
84
- pointer,
85
- value: data,
86
- code: "NOT_A_STRING"
87
- })
88
- ],
89
- data
90
- };
21
+ string(data) {
22
+ return typeof data === "string";
91
23
  },
92
- number(schema, data, pointer) {
93
- if (typeof data === "number") {
94
- return {
95
- valid: true,
96
- errors: [],
97
- data
98
- };
99
- }
100
-
101
- return {
102
- valid: false,
103
- errors: [
104
- new ValidationError("Data is not a number", {
105
- pointer,
106
- value: data,
107
- code: "NOT_A_NUMBER"
108
- })
109
- ],
110
- data
111
- };
24
+ number(data) {
25
+ return typeof data === "number";
112
26
  },
113
- integer(schema, data, pointer) {
114
- if (typeof data === "number" && Number.isInteger(data)) {
115
- return {
116
- valid: true,
117
- errors: [],
118
- data
119
- };
120
- }
121
-
122
- return {
123
- valid: false,
124
- errors: [
125
- new ValidationError("Data is not an integer", {
126
- pointer,
127
- value: data,
128
- code: "NOT_AN_INTEGER"
129
- })
130
- ],
131
- data
132
- };
27
+ integer(data) {
28
+ return typeof data === "number" && data % 1 === 0;
133
29
  },
134
- boolean(schema, data, pointer) {
135
- if (typeof data === "boolean") {
136
- return {
137
- valid: true,
138
- errors: [],
139
- data
140
- };
141
- }
142
-
143
- return {
144
- valid: false,
145
- errors: [
146
- new ValidationError("Data is not a boolean", {
147
- pointer,
148
- value: data,
149
- code: "NOT_A_BOOLEAN"
150
- })
151
- ],
152
- data
153
- };
30
+ boolean(data) {
31
+ return typeof data === "boolean";
154
32
  },
155
- null(schema, data, pointer) {
156
- if (data === null) {
157
- return {
158
- valid: true,
159
- errors: [],
160
- data
161
- };
162
- }
33
+ null(data) {
34
+ return data === null;
35
+ },
36
+
37
+ // Not implemented yet
38
+ timestamp: false,
39
+ int8: false,
40
+ unit8: false,
41
+ int16: false,
42
+ unit16: false,
43
+ int32: false,
44
+ unit32: false,
45
+ float32: false,
46
+ float64: false
47
+
163
48
 
164
- return {
165
- valid: false,
166
- errors: [
167
- new ValidationError("Data is not null", {
168
- pointer,
169
- value: data,
170
- code: "NOT_NULL"
171
- })
172
- ],
173
- data
174
- };
175
- }
176
49
  };
package/lib/utils.ts CHANGED
@@ -1,38 +1,65 @@
1
- import { SchemaShield, ValidationErrorProps } from "./index";
1
+ import { CompiledSchema } from "./index";
2
2
 
3
3
  export class ValidationError extends Error {
4
- name: string;
5
- pointer: string;
6
4
  message: string;
7
- value: any;
8
- code: string;
9
-
10
- constructor(
11
- message: string,
12
- options: ValidationErrorProps = {
13
- pointer: "",
14
- value: null,
15
- code: ""
5
+ item: string | number;
6
+ keyword: string;
7
+ cause: ValidationError;
8
+ path: string = "";
9
+ data?: any;
10
+ schema?: CompiledSchema;
11
+
12
+ private _getCause(pointer = "#") {
13
+ const path =
14
+ pointer +
15
+ "/" +
16
+ this.keyword +
17
+ (typeof this.item !== "undefined" ? "/" + this.item : "");
18
+
19
+ if (!this.cause) {
20
+ this.path = path;
21
+ return this;
16
22
  }
17
- ) {
18
- super(message);
19
- this.name = "ValidationError";
20
- this.pointer = options.pointer;
21
- this.message = message;
22
- this.value = options.value;
23
- this.code = options.code;
23
+
24
+ return this.cause._getCause(path);
25
+ }
26
+
27
+ getCause() {
28
+ return this._getCause();
24
29
  }
25
30
  }
26
31
 
27
- export const defaultValidator = (schema, data, pointer) => {
28
- return [
29
- new ValidationError("No validator for this schema", {
30
- pointer,
31
- value: data,
32
- code: "NO_VALIDATOR"
33
- })
34
- ];
35
- };
32
+ export interface DefineErrorOptions {
33
+ item?: any; // Final item in the path
34
+ cause?: ValidationError; // Cause of the error
35
+ data?: any; // Data that caused the error
36
+ }
37
+
38
+ export interface DefineErrorFunction {
39
+ (message: string, options?: DefineErrorOptions): ValidationError;
40
+ }
41
+
42
+ export function getDefinedErrorFunctionForKey(
43
+ key: string,
44
+ schema: CompiledSchema
45
+ ) {
46
+ const KeywordError = new ValidationError(`Invalid ${key}`);
47
+ KeywordError.keyword = key;
48
+ KeywordError.schema = schema;
49
+
50
+ const defineError: DefineErrorFunction = (message, options = {}) => {
51
+ KeywordError.message = message;
52
+ KeywordError.item = options.item;
53
+ KeywordError.cause = options.cause;
54
+ KeywordError.data = options.data;
55
+ return KeywordError;
56
+ };
57
+
58
+ return getNamedFunction<DefineErrorFunction>(
59
+ `defineError_${key}`,
60
+ defineError
61
+ );
62
+ }
36
63
 
37
64
  export function deepEqual(
38
65
  obj: Array<any> | Record<string, any>,
@@ -77,3 +104,54 @@ export function deepEqual(
77
104
  export function isObject(data) {
78
105
  return typeof data === "object" && data !== null && !Array.isArray(data);
79
106
  }
107
+
108
+ export function areCloseEnough(a, b, epsilon = 1e-15) {
109
+ return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
110
+ }
111
+
112
+ export function getUTF16Length(str) {
113
+ let length = 0;
114
+ for (let i = 0; i < str.length; i++) {
115
+ const codePoint = str.codePointAt(i);
116
+ if (codePoint > 0xffff) {
117
+ i++;
118
+ }
119
+ length++;
120
+ }
121
+ return length;
122
+ }
123
+
124
+ export function deepClone(obj: any): any {
125
+ if (Array.isArray(obj)) {
126
+ const result = [];
127
+ for (let i = 0; i < obj.length; i++) {
128
+ result[i] = deepClone(obj[i]);
129
+ }
130
+ return result;
131
+ }
132
+
133
+ // Is class instance of any kind
134
+ if (obj && obj.constructor && obj.constructor.name !== "Object") {
135
+ return obj;
136
+ }
137
+
138
+ if (isObject(obj)) {
139
+ const result = {
140
+ ...obj
141
+ };
142
+ for (const key in obj) {
143
+ result[key] = deepClone(obj[key]);
144
+ }
145
+ return result;
146
+ }
147
+
148
+ return obj;
149
+ }
150
+
151
+ export function isCompiledSchema(subSchema: any): subSchema is CompiledSchema {
152
+ return isObject(subSchema) && "$validate" in subSchema;
153
+ }
154
+
155
+ export function getNamedFunction<T>(name: string, fn: T): T {
156
+ return Object.defineProperty(fn, "name", { value: name });
157
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schema-shield",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "A fast library that protects your JSON schema from invalid data.",
5
5
  "repository": "git@github.com:Masquerade-Circus/schema-shield.git",
6
6
  "author": "Masquerade <christian@masquerade-circus.net>",
@@ -69,7 +69,7 @@
69
69
  "node": ">=12.0.0"
70
70
  },
71
71
  "scripts": {
72
- "test": "mocha --bail --recursive --no-timeouts --exit --require ts-node/register --enable-source-maps tests/**/*.test.ts",
72
+ "test": "mocha --bail --recursive --no-timeouts --forbid-only --exit --require ts-node/register --enable-source-maps tests/**/*.test.ts",
73
73
  "dev:test": "nodemon -e ts,js -w ./tests -w ./lib --exec npm run test",
74
74
  "dev:source": "NODE_ENV=development nodemon --enable-source-maps -e tsx,ts,json,css -w ./lib -w ./www source.js",
75
75
  "build": "node source.js",
@@ -79,6 +79,7 @@
79
79
  "release-test": "release-it --dry-run --verbose"
80
80
  },
81
81
  "dependencies": {
82
+ "is-my-ip-valid": "^1.0.1",
82
83
  "ts-node": "^10.9.1",
83
84
  "tsc-prog": "^2.2.1",
84
85
  "tslib": "^2.5.0",