schema-shield 0.0.6 → 1.0.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/README.md CHANGED
@@ -1,16 +1,28 @@
1
- # SchemaShield
1
+ # SchemaShield 🛡️
2
2
 
3
- SchemaShield is a versatile and powerful JSON Schema validator designed to simplify the process of validating complex data structures.
3
+ **Validation for Modern Architectures: Secure, Stack-Safe, and Domain-Aware.**
4
4
 
5
- Unlike many other libraries, SchemaShield does not rely on code generation, making it safer to pass real references to objects, classes, or variables and opening new possibilities for custom validation that are not possible with other libraries.
5
+ SchemaShield is a secure interpreter for JSON Schema engineered for strict environments and complex domain logic. It prioritizes **architectural stability** and **developer experience** over raw synthetic throughput.
6
6
 
7
- Despite its feature-rich and easy extendable nature, SchemaShield is designed to be fast and efficient, matching the performance of other libraries that use code generation.
7
+ - **Security by Design:** Zero Code Generation. Fully compatible with strict Content Security Policy (CSP).
8
+ - **Production Stability:** Stack-safe traversal. Designed to minimize stack usage and reduce the risk of stack overflows, even on deeply nested schemas.
9
+ - **Domain Integrated:** Validates runtime objects (Classes, Dates, Streams) alongside serialized JSON.
10
+ - **Transparent Debugging:** Pure JavaScript execution means clean stack traces and no black-box generated code.
8
11
 
9
12
  ## Table of Contents
10
13
 
11
14
  - [Table of Contents](#table-of-contents)
12
- - [Features](#features)
15
+ - [Why SchemaShield?](#why-schemashield)
16
+ - [Comparison with Other Approaches](#comparison-with-other-approaches)
13
17
  - [Usage](#usage)
18
+ - [Performance](#performance)
19
+ - [Understanding Performance Context](#understanding-performance-context)
20
+ - [1. Modern Runtimes (Bun)](#1-modern-runtimes-bun)
21
+ - [2. Standard Runtimes (Node.js)](#2-standard-runtimes-nodejs)
22
+ - [Edge \& Serverless Ready](#edge--serverless-ready)
23
+ - [Features](#features)
24
+ - [Security Philosophy: Hermetic Validation](#security-philosophy-hermetic-validation)
25
+ - [Why No Remote References?](#why-no-remote-references)
14
26
  - [No Code Generation](#no-code-generation)
15
27
  - [Error Handling](#error-handling)
16
28
  - [Adding Custom Types](#adding-custom-types)
@@ -23,7 +35,8 @@ Despite its feature-rich and easy extendable nature, SchemaShield is designed to
23
35
  - [Method Signature](#method-signature-2)
24
36
  - [Example: Adding a Custom Keyword](#example-adding-a-custom-keyword)
25
37
  - [Complex example: Adding a Custom Keyword that uses the instance](#complex-example-adding-a-custom-keyword-that-uses-the-instance)
26
- - [No Code Generation Opened Possibilities](#no-code-generation-opened-possibilities)
38
+ - [Supported Formats](#supported-formats)
39
+ - [Validating Runtime Objects](#validating-runtime-objects)
27
40
  - [More on Error Handling](#more-on-error-handling)
28
41
  - [ValidationError Properties](#validationerror-properties)
29
42
  - [Get the path to the error location](#get-the-path-to-the-error-location)
@@ -32,22 +45,39 @@ Despite its feature-rich and easy extendable nature, SchemaShield is designed to
32
45
  - [Immutable Mode](#immutable-mode)
33
46
  - [TypeScript Support](#typescript-support)
34
47
  - [Known Limitations](#known-limitations)
35
- - [Schema References and Schema Definitions](#schema-references-and-schema-definitions)
36
- - [Unsupported Formats](#unsupported-formats)
48
+ - [1. Dynamic ID Scope Resolution (Scope Alteration)](#1-dynamic-id-scope-resolution-scope-alteration)
49
+ - [2. Unicode Length Validation](#2-unicode-length-validation)
37
50
  - [Testing](#testing)
38
51
  - [Contribute](#contribute)
39
52
  - [Legal](#legal)
40
53
 
41
- ## Features
54
+ ## Why SchemaShield?
42
55
 
43
- - Supports draft-06 and draft-07 of the [JSON Schema](https://json-schema.org/) specification.
44
- - No Code Generation for Enhanced Safety and Validation Flexibility.
45
- - Custom type, keyword, and format validators.
46
- - Immutable mode for data protection.
47
- - Lightweight and fast.
48
- - Easy to use and extend.
49
- - No dependencies.
50
- - Typescript support.
56
+ Most validators optimize for "operations per second" in synthetic benchmarks, often sacrificing security, stability, or maintainability. SchemaShield optimizes for the **Total Cost of Ownership** of your software.
57
+
58
+ | Feature | JIT Compilers | SchemaShield | Why it matters |
59
+ | :------------------- | :------------------------------------------------------------------- | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------- |
60
+ | **Security Model** | **Reactive**<br>(Requires config to prevent Prototype Pollution/DoS) | **Preventive**<br>(Hermetic & Immutable by design) | "Secure by default" prevents human error and vulnerabilities in production. |
61
+ | **Debug Experience** | **Black Box**<br>(Debugs opaque generated strings/code) | **White Box**<br>(Standard JS stack traces) | Drastically reduces time-to-fix when validation fails in complex logic. |
62
+ | **Stability** | **Recursive**<br>(Risk of Stack Overflow on deep data) | **Flat Loop**<br>(Constant memory usage) | Protects your server availability against malicious deep-payload attacks. |
63
+ | **Domain Logic** | **Disconnected**<br>(Hard to validate Class Instances/State) | **Integrated**<br>(Native `instanceof` & state validation) | Unifies DTO validation and Business Rules, eliminating "spaghetti code" in controllers. |
64
+ | **Ecosystem** | **Fragmented**<br>(Requires plugins for errors/formats) | **Cohesive**<br>(Advanced error trees & formats built-in) | Reduces dependency fatigue and maintenance burden. |
65
+
66
+ > **The Trade-off:** While JIT compilers can be faster in raw throughput on V8 (Node.js), SchemaShield offers a balanced architecture where validation is never the bottleneck in real-world I/O bound applications (Database/Network APIs).
67
+
68
+ ### Comparison with Other Approaches
69
+
70
+ | Feature | SchemaShield | JIT Compilers | Classic Interpreters |
71
+ | :---------------------------- | :-------------------------------------------------- | :------------------------------- | :-------------------- |
72
+ | **Architecture** | **Secure Flat Interpreter** | JIT Compiler (eval/new Function) | Recursive Interpreter |
73
+ | **Relative Speed** | **High (~60%)** | Reference (100%) | Low (1% - 20%) |
74
+ | **CSP Compliance** | **Native (100% Safe)** | Requires Build Config | Variable |
75
+ | **Edge Ready** | **Native** | Complex Setup | Variable |
76
+ | **Stack Safety** | **Minimized stack usage (non-recursive core loop)** | Risk of Overflow | Risk of Overflow |
77
+ | **Class Instance Validation** | **Native** | No | No |
78
+ | **Debug Experience** | **Clean Stack Trace** | Opaque Generated Code | Variable |
79
+
80
+ > **Note:** Stack Safety refers to the risk of stack overflow errors when validating deeply nested data structures. SchemaShield's flat interpreter design minimizes this risk in its core validation loop. Keep in mind that custom keywords can still introduce recursion if not implemented carefully.
51
81
 
52
82
  ## Usage
53
83
 
@@ -56,7 +86,7 @@ Despite its feature-rich and easy extendable nature, SchemaShield is designed to
56
86
  ```bash
57
87
  npm install schema-shield
58
88
  # or
59
- yarn add schema-shield
89
+ bun add schema-shield
60
90
  ```
61
91
 
62
92
  **2. Import the SchemaShield class**
@@ -70,10 +100,11 @@ const { SchemaShield } = require("schema-shield");
70
100
  **3. Instantiate the SchemaShield class**
71
101
 
72
102
  ```javascript
73
- const schemaShield = new SchemaShield({ immutable: true });
103
+ const schemaShield = new SchemaShield();
74
104
  ```
75
105
 
76
- **`immutable`** (optional): Set to `true` to ensure that input data remains unmodified during validation. Default is `false` for better performance.
106
+ - **`immutable`** (optional): Set to `true` to ensure that input data remains unmodified during validation. Default is `false` for better performance.
107
+ - **`failFast`** (optional): Set to `false` to receive detailed error objects on validation failure. Default is `true` for lightweight failure indication.
77
108
 
78
109
  **3.5. Add custom types, keywords, and formats (optional)**
79
110
 
@@ -128,9 +159,92 @@ if (validationResult.valid) {
128
159
  **`validationResult`**: Contains the following properties:
129
160
 
130
161
  - `data`: The validated (and potentially modified) data.
131
- - `error`: A `ValidationError` instance if validation failed, otherwise null.
162
+ - `error`: A `ValidationError` instance if validation failed (when `failFast: false`), `true` if validation failed in fail-fast mode, otherwise `null`.
132
163
  - `valid`: true if validation was successful, otherwise false.
133
164
 
165
+ > Note: When SchemaShield is instantiated with `{ failFast: false }`, `validationResult.error` will contain a detailed `ValidationError` instance if validation fails. In `failFast: true` mode, `error` is just `true` as a lightweight sentinel.
166
+
167
+ **6. Intelligent Defaults**
168
+
169
+ SchemaShield applies `default` values only when necessary to fulfill the schema contract. A `default` value is injected if and only if:
170
+
171
+ 1. The property is missing in the input data.
172
+ 2. The property is marked as `required` in the schema.
173
+
174
+ ## Performance
175
+
176
+ SchemaShield is engineered with a **Flat Loop Interpreter** architecture. This design choice implies zero compilation overhead, making it exceptionally stable and significantly faster in modern runtimes.
177
+
178
+ ### Understanding Performance Context
179
+
180
+ In real-world applications, validation latency is often negligible compared to Network I/O (~20-100ms) or Database queries (~5-50ms).
181
+
182
+ SchemaShield is engineered to be **"Elite Fast" (Sufficiently Fast)**:
183
+
184
+ - **Zero Compilation Overhead:** Ideal for Serverless/Edge cold-starts.
185
+ - **Predictable Throughput:** Consistent performance regardless of schema complexity.
186
+
187
+ While JIT compilers may show higher numbers in micro-benchmarks on V8, SchemaShield processes thousands of requests per second—more than enough for high-traffic APIs—without the architectural risks of code generation.
188
+
189
+ ### 1. Modern Runtimes (Bun)
190
+
191
+ In runtimes using JavaScriptCore (like Bun), SchemaShield outperforms JIT compilers because it avoids the heavy cost of runtime code generation and optimization overhead.
192
+
193
+ | Validator | Relative Speed | Context |
194
+ | :----------------- | :------------- | :----------- |
195
+ | **SchemaShield** | **100%** | **Fastest** |
196
+ | ajv | ~55% | JIT Compiler |
197
+ | @exodus/schemasafe | ~12% | Interpreter |
198
+ | jsonschema | ~2% | Legacy |
199
+
200
+ ### 2. Standard Runtimes (Node.js)
201
+
202
+ In V8-based environments (Node.js), SchemaShield maintains elite performance for a secure interpreter, being roughly **50x faster** than legacy libraries.
203
+
204
+ | Validator | Relative Speed | Context |
205
+ | :----------------- | :------------- | :------------------ |
206
+ | ajv | 100% | Reference (JIT) |
207
+ | @exodus/schemasafe | ~75% | Interpreter |
208
+ | **SchemaShield** | **~60%** | **Secure Standard** |
209
+ | jsonschema | ~1% | Legacy |
210
+
211
+ **Key Takeaway:** SchemaShield delivers consistent high performance in Node.js without the security risks, memory leaks, or "cold start" latency associated with code generation.
212
+
213
+ ## Edge & Serverless Ready
214
+
215
+ SchemaShield is designed to run seamlessly in restrictive environments like **Cloudflare Workers**, **Vercel Edge Functions**, **Deno Deploy**, and **Bun**.
216
+
217
+ - **Zero Dependencies:** No strict reliance on Node.js built-ins.
218
+ - **CSP Compliant:** Works in environments where `eval()` and `new Function()` are banned for security.
219
+ - **Instant Startup:** No compilation overhead, minimizing "cold start" latency in Serverless functions.
220
+
221
+ ## Features
222
+
223
+ - Supports draft-06 and draft-07 of the [JSON Schema](https://json-schema.org/) specification.
224
+ - Full support for internal references ($ref) and anchors ($id).
225
+ - No Code Generation for Enhanced Safety and Validation Flexibility.
226
+ - Custom type, keyword, and format validators.
227
+ - Runtime object validation: first-class support for business logic checks (type checking and schema validation).
228
+ - Immutable mode for data protection.
229
+ - Lightweight and fast.
230
+ - Easy to use and extend.
231
+ - No dependencies.
232
+ - TypeScript support.
233
+
234
+ ## Security Philosophy: Hermetic Validation
235
+
236
+ SchemaShield adopts a **Zero Trust** and **Hermetic Architecture** approach. Unlike validators that allow runtime network access, SchemaShield is strictly synchronous and offline by design.
237
+
238
+ ### Why No Remote References?
239
+
240
+ Allowing a validator to fetch schemas from remote URLs (`$ref: "https://..."`) at runtime introduces critical security vectors and stability issues:
241
+
242
+ 1. **SSRF (Server-Side Request Forgery):** Prevents attackers from manipulating schemas to force internal network scanning or access metadata services.
243
+ 2. **Supply Chain Attacks:** Eliminates the risk of a remote schema being silently compromised, which could alter validation logic without code deployment.
244
+ 3. **Deterministic Reliability:** Validation never fails due to network latency, DNS issues, or third-party server downtime.
245
+
246
+ **Recommendation:** Treat schemas as **code dependencies**, not dynamic assets. Download and bundle remote schemas locally during your build process to ensure immutable, versioned, and audit-ready validation.
247
+
134
248
  ## No Code Generation
135
249
 
136
250
  Unlike some other validation libraries that rely on code generation to achieve fast performance, SchemaShield does not use code generation.
@@ -146,18 +260,21 @@ class CustomDate extends Date {}
146
260
  schemaShield.addType("custom-date-class", (data) => data instanceof CustomDate);
147
261
  ```
148
262
 
149
- You can see a full example of this in the [No Code Generation opened possibilities](#no-code-generation-opened-possibilities) section.
150
-
151
263
  ## Error Handling
152
264
 
153
- SchemaShield provides comprehensive error handling for schema validation. When a validation error occurs, a `ValidationError` instance is returned in the error property of the validation result. This error has the `getPath()` method, which is particularly useful for quickly identifying the location of an error in both the schema and the data.
265
+ SchemaShield provides comprehensive error handling for schema validation. When a validation error occurs:
266
+
267
+ - If the instance was created with `{ failFast: true }` (the default), the `error` property will be `true` as a lightweight sentinel indicating that validation failed.
268
+ - If the instance was created with `{ failFast: false }`, the `error` property will contain a `ValidationError` instance with rich debugging information.
269
+
270
+ This error object has the `getPath()` method, which is particularly useful for quickly identifying the location of an error in both the schema and the data.
154
271
 
155
272
  **Example:**
156
273
 
157
274
  ```javascript
158
275
  import { SchemaShield } from "schema-shield";
159
276
 
160
- const schemaShield = new SchemaShield();
277
+ const schemaShield = new SchemaShield({ failFast: false });
161
278
 
162
279
  const schema = {
163
280
  type: "object",
@@ -218,7 +335,7 @@ In this example, we'll add a custom type called age that validates if a given nu
218
335
  ```javascript
219
336
  import { SchemaShield } from "schema-shield";
220
337
 
221
- const schemaShield = new SchemaShield();
338
+ const schemaShield = new SchemaShield({ failFast: false });
222
339
 
223
340
  // Custom type 'age' validator function
224
341
  const ageValidator = (data) => {
@@ -275,9 +392,9 @@ addFormat(name: string, validator: FormatFunction, overwrite?: boolean): void;
275
392
  In this example, we'll add a custom format called ssn that validates if a given string is a valid U.S. Social Security Number (SSN).
276
393
 
277
394
  ```javascript
278
- import { SchemaShield } from "./path/to/SchemaShield";
395
+ import { SchemaShield } from "schema-shield";
279
396
 
280
- const schemaShield = new SchemaShield();
397
+ const schemaShield = new SchemaShield({ failFast: false });
281
398
 
282
399
  // Custom format 'ssn' validator function
283
400
  const ssnValidator = (data) => {
@@ -314,21 +431,21 @@ if (validationResult.valid) {
314
431
 
315
432
  ## Adding Custom Keywords
316
433
 
317
- SchemaShield allows you to add custom keywords for validation using the addKeyword method. This is the most powerful method for adding custom validation logic to SchemaShield because it allows to interact with the entire schema and data being validated at the level of the keyword.
434
+ SchemaShield allows you to add custom keywords for validation using the `addKeyword` method. This is the most powerful method for adding custom validation logic to SchemaShield because it allows you to interact with the entire schema and data being validated at the level of the keyword.
318
435
 
319
436
  ### Method Signature
320
437
 
321
438
  ```javascript
322
- type Result = void | ValidationError;
439
+ type Result = void | ValidationError | true;
323
440
 
324
441
  interface DefineErrorOptions {
325
442
  item?: any; // Final item in the path
326
- cause?: ValidationError; // Cause of the error
443
+ cause?: ValidationError | true; // Cause of the error (or true in failFast mode)
327
444
  data?: any; // Data that caused the error
328
445
  }
329
446
 
330
447
  interface DefineErrorFunction {
331
- (message: string, options?: DefineErrorOptions): ValidationError;
448
+ (message: string, options?: DefineErrorOptions): ValidationError | true;
332
449
  }
333
450
 
334
451
  interface ValidateFunction {
@@ -349,8 +466,9 @@ interface TypeFunction {
349
466
  }
350
467
 
351
468
  declare class SchemaShield {
352
- constructor({ immutable }?: {
353
- immutable?: boolean;
469
+ constructor(options?: {
470
+ immutable?: boolean;
471
+ failFast?: boolean;
354
472
  });
355
473
  compile(schema: any): Validator;
356
474
  addType(name: string, validator: TypeFunction, overwrite?: boolean): void;
@@ -377,7 +495,7 @@ addKeyword(name: string, validator: KeywordFunction, overwrite?: boolean): void;
377
495
  ```
378
496
 
379
497
  - `name`: The name of the custom keyword. This should be a unique string that does not conflict with existing keywords.
380
- - `validator`: A `KeywordFunction` that takes four arguments: `schema`, `data`, `defineError`, and `instance` (The SchemaShield instance that is currently running the validation). The function should not return anything if the data is valid for the custom keyword, and should return a `ValidationError` instance if the data is invalid.
498
+ - `validator`: A `KeywordFunction` that takes four arguments: `schema`, `data`, `defineError`, and `instance` (The SchemaShield instance that is currently running the validation). The function should not return anything if the data is valid for the custom keyword, and should return a `ValidationError` instance if the data is invalid when `failFast` is `false`, or `true` when `failFast` is `true`.
381
499
  - `overwrite` (optional): Set to true to overwrite an existing keyword with the same name. Default is false. If set to false and a keyword with the same name already exists, an error will be thrown.
382
500
 
383
501
  #### About the `defineError` Function
@@ -386,10 +504,13 @@ Take into account that the error must be generated using the `defineError` funct
386
504
 
387
505
  - `message`: A string that describes the validation error.
388
506
  - `options`: An optional object with properties that provide more context for the error:
507
+
389
508
  - `item`?: An optional value representing the final item in the path where the validation error occurred. (e.g. index of an array item)
390
- - `cause`?: An optional `ValidationError` that represents the cause of the current error.
509
+ - `cause`?: An optional `ValidationError` (or `true` in fail-fast mode) that represents the cause of the current error.
391
510
  - `data`?: An optional value representing the data that caused the validation error.
392
511
 
512
+ When the SchemaShield instance is created with `failFast: true`, `defineError` returns `true` instead of a `ValidationError`, and keyword implementations should simply `return` whatever `defineError` gives them.
513
+
393
514
  #### About the `instance` Argument
394
515
 
395
516
  The `instance` argument is the SchemaShield instance that is currently running the validation. This can be used to access to other `types`, `keywords` or `formats` that have been added to the instance.
@@ -399,9 +520,9 @@ The `instance` argument is the SchemaShield instance that is currently running t
399
520
  In this example, we'll add a custom keyword called divisibleBy that validates if a given number is divisible by a specified divisor.
400
521
 
401
522
  ```javascript
402
- import { SchemaShield, ValidationError } from "./path/to/SchemaShield";
523
+ import { SchemaShield, ValidationError } from "schema-shield";
403
524
 
404
- const schemaShield = new SchemaShield();
525
+ const schemaShield = new SchemaShield({ failFast: false });
405
526
 
406
527
  // Custom keyword 'divisibleBy' validator function
407
528
  const divisibleByValidator = (schema, data, defineError, instance) => {
@@ -450,7 +571,7 @@ In this example we'll add a custom keyword called `prefixedUsername` that will v
450
571
  ```javascript
451
572
  import { SchemaShield, ValidationError } from "schema-shield";
452
573
 
453
- const schemaShield = new SchemaShield();
574
+ const schemaShield = new SchemaShield({ failFast: false });
454
575
 
455
576
  // Custom type validator: nonEmptyString
456
577
  const nonEmptyStringValidator = (data) =>
@@ -479,7 +600,7 @@ const prefixedUsername = (schema, data, defineError, instance) => {
479
600
  // Get the validators for the specified types and formats from the instance
480
601
  // (if they exist)
481
602
  const typeValidator = instance.getType(validType);
482
- const prefixValidator = instance.getKeyword(prefixValidator);
603
+ const prefixKeyword = instance.getKeyword(prefixValidator);
483
604
  const formatValidator = instance.getFormat(validFormat);
484
605
 
485
606
  for (let i = 0; i < data.length; i++) {
@@ -506,8 +627,8 @@ const prefixedUsername = (schema, data, defineError, instance) => {
506
627
  }
507
628
 
508
629
  // Validate that the data has the correct prefix if specified
509
- if (prefixValidator) {
510
- const error = prefixValidator(schema, item, defineError, instance);
630
+ if (prefixKeyword) {
631
+ const error = prefixKeyword(schema, item, defineError, instance);
511
632
  if (error) {
512
633
  return defineError(`Invalid prefix: ${prefixValidator}`, {
513
634
  cause: error,
@@ -546,16 +667,30 @@ if (validationResult.valid) {
546
667
  }
547
668
  ```
548
669
 
549
- ## No Code Generation Opened Possibilities
670
+ ## Supported Formats
671
+
672
+ SchemaShield includes built-in validators for the following formats:
550
673
 
551
- With the no code generation nature of SchemaShield, you can create complex validation logic that incorporates custom classes, objects, or variables. This flexibility allows you to seamlessly integrate the validation process into your application's unique requirements and data structures.
674
+ - **Date & Time:** `date`, `time`, `date-time`, `duration`.
675
+ - **Email:** `email`, `idn-email`.
676
+ - **Hostnames:** `hostname`, `idn-hostname`.
677
+ - **IP Addresses:** `ipv4`, `ipv6`.
678
+ - **Resource Identifiers:** `uuid`, `uri`, `uri-reference`, `uri-template`, `iri`, `iri-reference`.
679
+ - **JSON Pointers:** `json-pointer`, `relative-json-pointer`.
680
+ - **Regex:** `regex`.
681
+
682
+ You can override any of these or add new ones using `schemaShield.addFormat`.
683
+
684
+ ## Validating Runtime Objects
685
+
686
+ JSON Schema is traditionally for serialized JSON text. SchemaShield extends this concept to **JavaScript Objects**. It allows validation of class instances, Dates, and internal application state directly.
552
687
 
553
688
  For example, imagine you have a custom class representing a project and another representing an employee. You could create a custom validator to ensure that only employees with the right qualifications are assigned to a specific project:
554
689
 
555
690
  ```javascript
556
691
  import { SchemaShield, ValidationError } from "schema-shield";
557
692
 
558
- const schemaShield = new SchemaShield();
693
+ const schemaShield = new SchemaShield({ failFast: false });
559
694
 
560
695
  // Custom classes
561
696
  class Project {
@@ -653,7 +788,7 @@ const dataToValidate = {
653
788
  };
654
789
 
655
790
  // Validate the data
656
- const validationResult = validator(schema);
791
+ const validationResult = validator(dataToValidate);
657
792
 
658
793
  if (validationResult.valid) {
659
794
  console.log("Assignment is valid:", validationResult.data);
@@ -666,9 +801,9 @@ In this example, SchemaShield safely accesses instances of custom classes and ut
666
801
 
667
802
  ## More on Error Handling
668
803
 
669
- SchemaShield provides a `ValidationError` class to handle errors that occur during schema validation. When a validation error is encountered, a `ValidationError` instance is returned in the error property of the validation result.
804
+ SchemaShield provides a `ValidationError` class to handle errors that occur during schema validation. When a validation error is encountered, a `ValidationError` instance is returned in the error property of the validation result when `failFast: false` is used; otherwise `error` is `true`.
670
805
 
671
- This error instance uses the new [Error: cause](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) property introduced in ES6. This allows you to analyze the whole error chain or to retrieve the root cause of the error using the `getCause()` `getTree()` and `getPath()` methods.
806
+ This error instance uses the [`Error.cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) property. This allows you to analyze the whole error chain or retrieve the root cause of the error using the `getCause()`, `getTree()`, and `getPath()` methods.
672
807
 
673
808
  ### ValidationError Properties
674
809
 
@@ -692,7 +827,7 @@ You can use the `getPath` method to get the JSON Pointer path to the error locat
692
827
  ```javascript
693
828
  import { SchemaShield } from "schema-shield";
694
829
 
695
- const schemaShield = new SchemaShield();
830
+ const schemaShield = new SchemaShield({ failFast: false });
696
831
 
697
832
  const schema = {
698
833
  type: "object",
@@ -768,7 +903,7 @@ interface ErrorTree {
768
903
  ```javascript
769
904
  import { SchemaShield } from "schema-shield";
770
905
 
771
- const schemaShield = new SchemaShield();
906
+ const schemaShield = new SchemaShield({ failFast: false });
772
907
 
773
908
  const schema = {
774
909
  type: "object",
@@ -856,7 +991,7 @@ You can use the `getCause()` method to retrieve the root cause of a validation e
856
991
  ```javascript
857
992
  import { SchemaShield } from "schema-shield";
858
993
 
859
- const schemaShield = new SchemaShield();
994
+ const schemaShield = new SchemaShield({ failFast: false });
860
995
 
861
996
  const schema = {
862
997
  type: "object",
@@ -937,26 +1072,19 @@ With the built in TypeScript support, you can take advantage of features like st
937
1072
 
938
1073
  ## Known Limitations
939
1074
 
940
- SchemaShield is a powerful and flexible library, but there are some limitations to be aware of when using it. Some features are not yet supported in the current version.
941
-
942
- ### Schema References and Schema Definitions
943
-
944
- SchemaShield currently does not support schema references and schema definitions (i.e. `$ref` and `definitions`). This is planned to be addressed in future updates of SchemaShield.
1075
+ SchemaShield is optimized for local execution and strict security.
945
1076
 
946
- For now, consider using custom implementations using the `addKeyword` method or use alternative libraries to handle these specific features if you need them.
1077
+ ### 1. Dynamic ID Scope Resolution (Scope Alteration)
947
1078
 
948
- ### Unsupported Formats
1079
+ SchemaShield resolves references based on static JSON Pointers and unique IDs. It does not support changing the resolution base URI dynamically based on nested `$id` properties within sub-schemas.
949
1080
 
950
- #### Internationalized Formats
1081
+ - **Impact:** Rare edge-cases in draft-07 involving complex relative URI resolution inside nested scopes are not supported.
951
1082
 
952
- There is no plan to support the following formats in SchemaShield, as they are not relevant to the majority of use cases. If you need to use these formats, consider using custom implementations using the `addFormat` method to handle them.
1083
+ ### 2. Unicode Length Validation
953
1084
 
954
- - `idn-email`
955
- - `idn-hostname`
956
- - `iri`
957
- - `iri-reference`
1085
+ SchemaShield validates `minLength` and `maxLength` based on JavaScript's `length` property (UTF-16 code units), not Unicode Code Points.
958
1086
 
959
- Also you can contribute to SchemaShield and add support for these keywords and formats or leve a comment requesting support for them.
1087
+ - **Impact:** Emoji or surrogate pairs may be counted as length 2.
960
1088
 
961
1089
  ## Testing
962
1090
 
@@ -994,5 +1122,5 @@ We appreciate your interest in contributing to SchemaShield and look forward to
994
1122
 
995
1123
  ## Legal
996
1124
 
997
- Author: [Masquerade Circus](http://masquerade-circus.net).
1125
+ Author: [Masquerade Circus](http://masquerade-circus.net).
998
1126
  License [Apache-2.0](https://opensource.org/licenses/Apache-2.0)
@@ -1 +1 @@
1
- {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../lib/formats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,KAAK,CA+O1D,CAAC"}
1
+ {"version":3,"file":"formats.d.ts","sourceRoot":"","sources":["../lib/formats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAwCzC,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,KAAK,CAoM1D,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
+ /****************** Path: lib/index.ts ******************/
1
2
  import { DefineErrorFunction, ValidationError } from "./utils";
2
3
  export { ValidationError } from "./utils";
3
4
  export { deepClone } from "./utils";
4
- export type Result = void | ValidationError;
5
+ export type Result = void | ValidationError | true;
5
6
  export interface KeywordFunction {
6
7
  (schema: CompiledSchema, data: any, defineError: DefineErrorFunction, instance: SchemaShield): Result;
7
8
  }
@@ -21,7 +22,7 @@ export interface CompiledSchema {
21
22
  export interface Validator {
22
23
  (data: any): {
23
24
  data: any;
24
- error: ValidationError | null;
25
+ error: ValidationError | null | true;
25
26
  valid: boolean;
26
27
  };
27
28
  compiledSchema: CompiledSchema;
@@ -31,8 +32,12 @@ export declare class SchemaShield {
31
32
  private formats;
32
33
  private keywords;
33
34
  private immutable;
34
- constructor({ immutable }?: {
35
+ private rootSchema;
36
+ private idRegistry;
37
+ private failFast;
38
+ constructor({ immutable, failFast }?: {
35
39
  immutable?: boolean;
40
+ failFast?: boolean;
36
41
  });
37
42
  addType(name: string, validator: TypeFunction, overwrite?: boolean): void;
38
43
  getType(type: string): TypeFunction | false;
@@ -40,8 +45,11 @@ export declare class SchemaShield {
40
45
  getFormat(format: string): FormatFunction | false;
41
46
  addKeyword(name: string, validator: KeywordFunction, overwrite?: boolean): void;
42
47
  getKeyword(keyword: string): KeywordFunction | false;
48
+ getSchemaRef(path: string): CompiledSchema | undefined;
49
+ getSchemaById(id: string): CompiledSchema | undefined;
43
50
  compile(schema: any): Validator;
44
51
  private compileSchema;
45
52
  isSchemaLike(subSchema: any): boolean;
53
+ private linkReferences;
46
54
  }
47
55
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,eAAe,EAKhB,MAAM,SAAS,CAAC;AAMjB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,eAAe,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC9B,CACE,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,GAAG,EACT,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,YAAY,GACrB,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,IAAI,EAAE,GAAG,GAAG;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1E,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,SAAS,CAAS;gBAEd,EACV,SAAiB,EAClB,GAAE;QACD,SAAS,CAAC,EAAE,OAAO,CAAC;KAChB;IAoBN,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,UAAQ;IAOhE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,KAAK;IAI3C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,UAAQ;IAOpE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,KAAK;IAIjD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,UAAQ;IAOtE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK;IAIpD,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS;IA6B/B,OAAO,CAAC,aAAa;IA0IrB,YAAY,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO;CActC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,OAAO,EACL,mBAAmB,EACnB,eAAe,EAMhB,MAAM,SAAS,CAAC;AAMjB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,eAAe,GAAG,IAAI,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,CACE,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,GAAG,EACT,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,YAAY,GACrB,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,IAAI,EAAE,GAAG,GAAG;QACX,IAAI,EAAE,GAAG,CAAC;QACV,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;QACrC,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,cAAc,EAAE,cAAc,CAAC;CAChC;AAOD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,QAAQ,CAAiB;gBAErB,EACV,SAAiB,EACjB,QAAe,EAChB,GAAE;QACD,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACf;IAqBN,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,UAAQ;IAOhE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,KAAK;IAI3C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,UAAQ;IAOpE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,KAAK;IAIjD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,UAAQ;IAOtE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,KAAK;IAIpD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAOtD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIrD,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS;IAkC/B,OAAO,CAAC,aAAa;IAgMrB,YAAY,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO;IAerC,OAAO,CAAC,cAAc;CA4DvB"}