schiva 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jesús Seijas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # schiva
2
+
3
+ Fast schema validation for JavaScript. Describe data with a small schema DSL or with JSON Schema (draft-07), and
4
+ schiva compiles it into a JavaScript function generated for that schema, so validating is several times faster than
5
+ walking the schema for every value.
6
+
7
+ - Passes the whole draft-07 [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite)
8
+ (929 of 929 tests), including `$ref` to other documents.
9
+ - Readable error messages with the path of each field: `lines[12].price must be a number`.
10
+ - Three modes: every error, the first error only, or just `true`/`false`.
11
+ - No dependencies. Unknown or unsupported keywords throw instead of being silently ignored.
12
+
13
+ ```sh
14
+ npm install schiva
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```js
20
+ const { ClosedSchema, String, Integer, ArrayOf } = require('schiva');
21
+
22
+ const person = new ClosedSchema({
23
+ id: String(),
24
+ age: Integer({ min: 18 }),
25
+ tags: ArrayOf({ type: String(), isMandatory: false }),
26
+ });
27
+
28
+ // Compile once, when the program starts:
29
+ const validatePerson = person.compile();
30
+
31
+ validatePerson({ id: 'x', age: 20 }); // []
32
+ validatePerson({ id: 1, age: 10, extra: 1 });
33
+ // ['id must be a string', 'age must be at least 18', 'Unexpected key: extra']
34
+ ```
35
+
36
+ With JSON Schema:
37
+
38
+ ```js
39
+ const { compileJsonSchema } = require('schiva');
40
+
41
+ const validate = compileJsonSchema({
42
+ type: 'object',
43
+ required: ['id'],
44
+ properties: { id: { type: 'string', pattern: '^[A-Z]+$' } },
45
+ });
46
+
47
+ validate({ id: 'AB' }); // []
48
+ validate({ id: 'ab' }); // ['id does not match the required pattern']
49
+ ```
50
+
51
+ ## Modes
52
+
53
+ `compile(options)` (on schemas and on every type) and `compileJsonSchema(json, options)` return a function:
54
+
55
+ | Option | The function returns | Use it when |
56
+ |---|---|---|
57
+ | (none) | every error message, `[]` when valid | messages are shown or logged |
58
+ | `{ allErrors: false }` | only the first error message, `[]` when valid | one message is enough; stops at the first failing check |
59
+ | `{ errors: false }` | `true` or `false` | only validity matters; builds no messages |
60
+
61
+ Schemas and types also have `validate(value)`, which checks without compiling (10 to 25 times slower), and
62
+ `isValid(value)`.
63
+
64
+ ## Compile once
65
+
66
+ The compiled function is a snapshot of the schema: changes made to the schema or its types afterwards (such as
67
+ `.optional()`, `.nullable()` or setting their fields) are not seen. Compile after building the schema, and compile
68
+ again if it changes. Compiling takes about 0.1 ms for a schema of moderate size, so compile when the program starts
69
+ (or cache the function), not for every value.
70
+
71
+ The generated code uses `new Function`, so it does not run where code generation is forbidden (for example with a
72
+ strict Content Security Policy).
73
+
74
+ ## Schema DSL
75
+
76
+ A `Schema` takes an object whose keys are the expected properties. Plain objects inside it become nested schemas.
77
+
78
+ ```js
79
+ const { Schema, String, Float, Enum } = require('schiva');
80
+
81
+ const order = new Schema(
82
+ {
83
+ id: String({ pattern: /^ORD-\d{8}$/ }),
84
+ status: Enum({ options: ['draft', 'placed'] }),
85
+ customer: { name: String({ min: 1 }), email: String({ isMandatory: false }) },
86
+ total: Float({ min: 0 }),
87
+ },
88
+ { isOpen: false }
89
+ );
90
+ ```
91
+
92
+ Every type takes `isMandatory` (default `true`: `undefined` is an error) and `isNullable` (default `false`: `null` is
93
+ an error), and has `.optional()`, `.required()`, `.nullable()` and `.notNull()`.
94
+
95
+ | Type | Options |
96
+ |---|---|
97
+ | `String` | `min`, `max` (length), `pattern` (RegExp), `allowEmpty`, `countCodePoints` |
98
+ | `Integer`, `Float` | `min`, `max`, `exclusiveMin`, `exclusiveMax`, `multipleOf` |
99
+ | `Boolean`, `Any`, `Never` | |
100
+ | `Enum` | `options` (strings) |
101
+ | `Values`, `Const(value)` | `values`: allowed values, compared deeply |
102
+ | `ArrayOf` | `type` (one type, or an array of types for a tuple), `min`, `max`, `unique`, `contains`, `additionalType` |
103
+ | `AnyOf`, `AllOf`, `OneOf` | `types` |
104
+ | `Not` | `type` |
105
+ | `Conditional` | `ifType`, `thenType`, `elseType` |
106
+ | `When` | `jsonType` (`object`, `array`, `string`, `number`), `type`: checks only values of that JSON type |
107
+ | `Ref` | `target`, for recursive schemas |
108
+
109
+ Schema options: `isOpen` (default `true`; `ClosedSchema` sets it to `false` and rejects unknown keys),
110
+ `additionalType`, `patternTypes` (`[{ pattern, type }]`), `propertyNameType`, `minProperties`, `maxProperties`,
111
+ `dependencies` (`[{ key, required: [...] }]` or `[{ key, type }]`), `isMandatory`, `isNullable`.
112
+
113
+ Short helpers are also exported: `str`, `int`, `float`, `bool`, `arrOf`, `obj`, `any`, `anyOf`, `allOf`, `oneOf`,
114
+ `not`, `enumt`, and optional versions prefixed with `o` (`ostr`, `oint`...).
115
+
116
+ Declared keys are read as own properties only, so `{}.toString` or a key added to `Object.prototype` never counts as
117
+ present.
118
+
119
+ ## JSON Schema
120
+
121
+ `fromJsonSchema(json, options)` converts a JSON Schema (draft-07) into the same types, and
122
+ `compileJsonSchema(json, options)` compiles it. Every validation keyword of draft-07 is supported, along with
123
+ `definitions` and `$ref` (JSON pointers, `$id` base URIs and anchors, recursive schemas). String lengths count Unicode
124
+ code points, as the specification says.
125
+
126
+ References to other documents resolve against the documents given in `options.schemas`, as `{ uri: schema }` or as an
127
+ array of schemas with `$id`. Nothing is loaded from the network, and a reference that cannot be resolved throws when
128
+ compiling:
129
+
130
+ ```js
131
+ const validateOrder = compileJsonSchema(orderSchema, {
132
+ schemas: { 'https://example.com/schemas/address.json': addressSchema },
133
+ });
134
+ ```
135
+
136
+ To validate schemas against the draft-07 meta-schema, register it in `schemas` (ajv ships a copy as
137
+ `ajv/dist/refs/json-schema-draft-07.json`).
138
+
139
+ ## Types of your own
140
+
141
+ Classes that extend `ValidateType` (or a built-in type) with their own `validate()` or `isValid()` keep working when
142
+ compiled: the generated code calls them for their part of the schema.
143
+
144
+ ## Speed
145
+
146
+ Compared with ajv and the other validators of
147
+ [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), each measurement in its own process
148
+ (see `bench/`):
149
+
150
+ | | schiva | ajv | @exodus/schemasafe |
151
+ |---|---|---|---|
152
+ | Test suite, tests passed | **929** of 929 | 921 (8 wrong) | 905 |
153
+ | Test suite, first error (runs/sec) | **118k** | 62k | 99k |
154
+ | Test suite, all errors (runs/sec) | **88k** | 54k | 65k |
155
+ | Order with 20 lines, valid, first error (validations/sec) | **2.26M** | 0.76M | 0.54M |
156
+ | Order with 20 lines, invalid, all errors (validations/sec) | **1.86M** | 0.43M | 0.32M |
157
+ | Compiling a schema (per sec) | **10k** | 0.2k | 0.8k |
158
+
159
+ ```sh
160
+ pnpm run bench # every validator in its own process (about 8 minutes)
161
+ pnpm run bench:quick # every validator in one process (about a minute)
162
+ ```
163
+
164
+ ## License
165
+
166
+ MIT
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "schiva",
3
+ "version": "0.1.0",
4
+ "description": "Fast schema validation for JavaScript: a schema DSL and JSON Schema (draft-07), compiled to generated code",
5
+ "main": "./src/index.js",
6
+ "type": "commonjs",
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "keywords": [
11
+ "schema",
12
+ "validation",
13
+ "validator",
14
+ "json-schema",
15
+ "draft-07",
16
+ "compiler",
17
+ "fast"
18
+ ],
19
+ "author": "Jesús Seijas <jseijas@gmail.com>",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=18"
23
+ },
24
+ "devDependencies": {
25
+ "@eslint/eslintrc": "^3.3.1",
26
+ "@eslint/js": "^9.39.2",
27
+ "eslint": "^9.39.2",
28
+ "eslint-config-prettier": "^10.1.8",
29
+ "eslint-plugin-jest": "^29.12.1",
30
+ "eslint-plugin-prettier": "^5.5.5",
31
+ "globals": "^17.0.0",
32
+ "jest": "^30.2.0",
33
+ "prettier": "^3.8.0"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "scripts": {
39
+ "lint": "eslint .",
40
+ "lintfix": "eslint --fix .",
41
+ "test": "eslint . && jest --silent --coverage .",
42
+ "bench": "cd bench && pnpm install && pnpm start",
43
+ "bench:quick": "cd bench && pnpm install && pnpm run quick"
44
+ }
45
+ }
@@ -0,0 +1,11 @@
1
+ const { Schema } = require('./schema');
2
+
3
+ class ClosedSchema extends Schema {
4
+ constructor(schema = {}, options = {}) {
5
+ super(schema, { ...options, isOpen: false });
6
+ }
7
+ }
8
+
9
+ module.exports = {
10
+ ClosedSchema,
11
+ };