@hyperjump/json-schema 1.16.4 → 1.17.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.
Files changed (72) hide show
  1. package/README.md +105 -16
  2. package/annotations/annotated-instance.js +1 -1
  3. package/draft-04/format.js +31 -0
  4. package/draft-04/index.js +3 -1
  5. package/draft-06/format.js +34 -0
  6. package/draft-06/index.js +3 -1
  7. package/draft-07/format.js +42 -0
  8. package/draft-07/index.js +3 -1
  9. package/draft-2019-09/format-assertion.js +44 -0
  10. package/draft-2019-09/format.js +44 -0
  11. package/draft-2019-09/index.js +5 -1
  12. package/draft-2020-12/format-assertion.js +43 -0
  13. package/draft-2020-12/index.js +6 -2
  14. package/formats/handlers/date-time.js +7 -0
  15. package/formats/handlers/date.js +7 -0
  16. package/formats/handlers/draft-04/hostname.js +7 -0
  17. package/formats/handlers/duration.js +7 -0
  18. package/formats/handlers/email.js +7 -0
  19. package/formats/handlers/hostname.js +7 -0
  20. package/formats/handlers/idn-email.js +7 -0
  21. package/formats/handlers/idn-hostname.js +7 -0
  22. package/formats/handlers/ipv4.js +7 -0
  23. package/formats/handlers/ipv6.js +7 -0
  24. package/formats/handlers/iri-reference.js +7 -0
  25. package/formats/handlers/iri.js +7 -0
  26. package/formats/handlers/json-pointer.js +7 -0
  27. package/formats/handlers/regex.js +7 -0
  28. package/formats/handlers/relative-json-pointer.js +7 -0
  29. package/formats/handlers/time.js +7 -0
  30. package/formats/handlers/uri-reference.js +7 -0
  31. package/formats/handlers/uri-template.js +7 -0
  32. package/formats/handlers/uri.js +7 -0
  33. package/formats/handlers/uuid.js +7 -0
  34. package/formats/index.js +12 -0
  35. package/formats/lite.js +43 -0
  36. package/lib/configuration.js +7 -2
  37. package/lib/experimental.d.ts +8 -0
  38. package/lib/experimental.js +1 -0
  39. package/lib/keywords/dynamicRef.js +1 -1
  40. package/lib/keywords/format.js +35 -2
  41. package/lib/keywords.js +25 -3
  42. package/openapi-3-0/index.js +1 -1
  43. package/openapi-3-1/index.d.ts +66 -17
  44. package/openapi-3-1/schema-draft-2019-09.js +1 -1
  45. package/openapi-3-1/schema-draft-2020-12.js +1 -1
  46. package/openapi-3-2/dialect/base.js +2 -2
  47. package/openapi-3-2/index.d.ts +326 -2
  48. package/openapi-3-2/index.js +2 -4
  49. package/openapi-3-2/meta/base.js +30 -5
  50. package/openapi-3-2/schema-base.js +2 -3
  51. package/openapi-3-2/schema-draft-04.js +2 -2
  52. package/openapi-3-2/schema-draft-06.js +2 -2
  53. package/openapi-3-2/schema-draft-07.js +2 -2
  54. package/openapi-3-2/schema-draft-2019-09.js +3 -3
  55. package/openapi-3-2/schema-draft-2020-12.js +3 -3
  56. package/openapi-3-2/schema.js +1661 -1
  57. package/package.json +9 -5
  58. package/v1/extension-tests/conditional.json +289 -0
  59. package/v1/extension-tests/itemPattern.json +462 -0
  60. package/{stable → v1}/index.d.ts +2 -2
  61. package/{stable → v1}/index.js +25 -30
  62. package/{stable → v1}/meta/applicator.js +1 -3
  63. package/{stable → v1}/meta/content.js +1 -3
  64. package/{stable → v1}/meta/core.js +5 -4
  65. package/v1/meta/format.js +8 -0
  66. package/{stable → v1}/meta/meta-data.js +1 -3
  67. package/{stable → v1}/meta/unevaluated.js +1 -3
  68. package/{stable → v1}/meta/validation.js +1 -3
  69. package/v1/schema.js +24 -0
  70. package/stable/meta/format-annotation.js +0 -10
  71. package/stable/meta/format-assertion.js +0 -10
  72. package/stable/validation.js +0 -24
package/README.md CHANGED
@@ -4,18 +4,19 @@ A collection of modules for working with JSON Schemas.
4
4
 
5
5
  * Validate JSON-compatible values against a JSON Schemas
6
6
  * Dialects: draft-2020-12, draft-2019-09, draft-07, draft-06, draft-04
7
+ * Complete validation support for all formats defined for the `format` keyword
7
8
  * Schemas can reference other schemas using a different dialect
8
9
  * Work directly with schemas on the filesystem or HTTP
9
10
  * OpenAPI
10
- * Versions: 3.0, 3.1
11
+ * Versions: 3.0, 3.1, 3.2
11
12
  * Validate an OpenAPI document
12
13
  * Validate values against a schema from an OpenAPI document
13
- * Create custom keywords, vocabularies, and dialects
14
+ * Create custom keywords, formats, vocabularies, and dialects
14
15
  * Bundle multiple schemas into one document
15
16
  * Uses the process defined in the 2020-12 specification but works with any
16
17
  dialect.
17
- * Utilities for building non-validation JSON Schema tooling
18
- * Utilities for working with annotations
18
+ * API for building non-validation JSON Schema tooling
19
+ * API for working with annotations
19
20
 
20
21
  ## Install
21
22
 
@@ -68,8 +69,8 @@ import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
68
69
  import "@hyperjump/json-schema/draft-07";
69
70
  ```
70
71
 
71
- **Note**: The default export (`@hyperjump/json-schema`) is reserved for the
72
- stable version of JSON Schema that will hopefully be released in near future.
72
+ **Note**: The default export (`@hyperjump/json-schema`) is reserved for v1 of
73
+ JSON Schema that will hopefully be released in near future.
73
74
 
74
75
  **Validate schema from JavaScript**
75
76
 
@@ -98,7 +99,7 @@ const output1 = isString("foo");
98
99
  const output2 = isString(42);
99
100
  ```
100
101
 
101
- **Fetching schemas**
102
+ **File-based and web-based schemas**
102
103
 
103
104
  Schemas that are available on the web can be loaded automatically without
104
105
  needing to load them manually.
@@ -130,24 +131,51 @@ You can add/modify/remove support for any URI scheme using the [plugin
130
131
  system](https://github.com/hyperjump-io/browser/#uri-schemes) provided by
131
132
  `@hyperjump/browser`.
132
133
 
134
+ **Format**
135
+
136
+ Format validation support needs to be explicitly loaded by importing
137
+ `@hyperjump/json-schema/formats`. Once loaded, it depends on the dialect whether
138
+ validation is enabled by default or not. You should explicitly enable/disable it
139
+ with the `setShouldValidateFormat` function.
140
+
141
+ The `hostname`, `idn-hostname`, and `idn-email` validators are fairly large. If
142
+ you don't need support for those formats and bundle size is a concern, you can
143
+ use `@hyperjump/json-schema/formats-lite` instead to leave out support for those
144
+ formats.
145
+
146
+ ```javascript
147
+ import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
148
+ import { setShouldValidateFormat } from "@hyperjump/json-schema/formats";
149
+
150
+ const schemaUri = "https://example.com/number";
151
+ registerSchema({
152
+ "type": "string",
153
+ "format": "date"
154
+ }, schemaUri);
155
+
156
+ setShouldValidateFormat(true);
157
+ const output = await validate(schemaUri, "Feb 29, 2031"); // { valid: false }
158
+ ```
159
+
133
160
  **OpenAPI**
134
161
 
135
- The OpenAPI 3.0 and 3.1 meta-schemas are pre-loaded and the OpenAPI JSON Schema
136
- dialects for each of those versions is supported. A document with a Content-Type
137
- of `application/openapi+json` (web) or a file extension of `openapi.json`
138
- (filesystem) is understood as an OpenAPI document.
162
+ The OpenAPI 3.0 and 3.1 and 3.2 meta-schemas are pre-loaded and the OpenAPI JSON
163
+ Schema dialects for each of those versions is supported. A document with a
164
+ Content-Type of `application/openapi+json` (web) or a file extension of
165
+ `openapi.json` (filesystem) is understood as an OpenAPI document.
139
166
 
140
167
  Use the pattern `@hyperjump/json-schema/*` to import the version you need. The
141
- available versions are `openapi-3-0` for 3.0 and `openapi-3-1` for 3.1.
168
+ available versions are `openapi-3-0` for 3.0, `openapi-3-1` for 3.1, and
169
+ `openapi-3-2` for 3.2.
142
170
 
143
171
  ```javascript
144
- import { validate } from "@hyperjump/json-schema/openapi-3-1";
172
+ import { validate } from "@hyperjump/json-schema/openapi-3-2";
145
173
 
146
174
 
147
- // Validate an OpenAPI document
148
- const output = await validate("https://spec.openapis.org/oas/3.1/schema-base", openapi);
175
+ // Validate an OpenAPI 3.2 document
176
+ const output = await validate("https://spec.openapis.org/oas/3.2/schema-base", openapi);
149
177
 
150
- // Validate an instance against a schema in an OpenAPI document
178
+ // Validate an instance against a schema in an OpenAPI 3.2 document
151
179
  const output = await validate("./example.openapi.json#/components/schemas/foo", 42);
152
180
  ```
153
181
 
@@ -472,6 +500,48 @@ registerSchema({
472
500
  const output = await validate("https://example.com/schema1", 42);
473
501
  ```
474
502
 
503
+ ### Custom Formats
504
+
505
+ Custom formats work similarly to keywords. You define a format handler and then
506
+ associate that format handler with the format keyword that applies to the
507
+ dialects you're targeting.
508
+
509
+ ```JavaScript
510
+ import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
511
+ import {
512
+ setShouldValiateFormat,
513
+ addFormat,
514
+ setFormatHandler
515
+ } from "@hyperjump/json-schema/formats";
516
+
517
+ const isoDateFormatUri = "https://example.com/format/iso-8601-date";
518
+
519
+ addFormat({
520
+ id: isoDateFormatUri,
521
+ handler: (date) => Date.parse(date).toISOString() === date
522
+ });
523
+
524
+ addFormatHandler("https://json-schema.org/keyword/format", "iso-date", isoDateFormatUri);
525
+ addFormatHandler("https://json-schema.org/keyword/format-assertion", "iso-date", isoDateFormatUri);
526
+ // Optional: Add the iso-date format to other dialects
527
+ addFormatHandler("https://json-schema.org/keyword/draft-2019-09/format", "iso-date", isoDateFormatUri);
528
+ addFormatHandler("https://json-schema.org/keyword/draft-2019-09/format-assertion", "iso-date", isoDateFormatUri);
529
+ addFormatHandler("https://json-schema.org/keyword/draft-07/format", "iso-date", isoDateFormatUri);
530
+ addFormatHandler("https://json-schema.org/keyword/draft-06/format", "iso-date", isoDateFormatUri);
531
+ addFormatHandler("https://json-schema.org/keyword/draft-04/format", "iso-date", isoDateFormatUri);
532
+
533
+ const schemaUri = "https://example.com/main";
534
+ registerSchema({
535
+ "$schema": "https://json-schema.org/draft/2002-12/schema",
536
+
537
+ "type": "string",
538
+ "format": "iso-date"
539
+ }, schemaUri);
540
+
541
+ setShouldValidateFormat(true);
542
+ const output = await validate(schemaUri, "Feb 28, 2031"); // { valid: false }
543
+ ```
544
+
475
545
  ### Custom Meta Schema
476
546
 
477
547
  You can use a custom meta-schema to restrict users to a subset of JSON Schema
@@ -605,6 +675,25 @@ These are available from the `@hyperjump/json-schema/experimental` export.
605
675
  * **ValidationContext**: object
606
676
  * ast: AST
607
677
  * plugins: EvaluationPlugins[]
678
+ * **addFormat**: (formatHandler: Format) => void
679
+
680
+ Add a format handler.
681
+
682
+ * **Format**: object
683
+ * id: string
684
+
685
+ A URI that uniquely identifies the format. It should use a domain you
686
+ own to avoid conflict with keywords defined by others.
687
+ * handler: (value: any) => boolean
688
+
689
+ A function that takes the value and returns a boolean determining if
690
+ it passes validation for the format.
691
+ * **setFormatHandler**: (keywordUri: string, formatName: string, formatUri: string) => void
692
+
693
+ Add support for a format to the specified keyword.
694
+ * **removeFormatHandler**: (keywordUri, formatName) => void
695
+
696
+ Remove support for a format from the specified keyword.
608
697
  * **defineVocabulary**: (id: string, keywords: { [keyword: string]: string }) => void
609
698
 
610
699
  Define a vocabulary that maps keyword name to keyword URIs defined using
@@ -2,7 +2,7 @@ import * as Instance from "../lib/instance.js";
2
2
  import { getKeywordId } from "../lib/keywords.js";
3
3
 
4
4
 
5
- const defaultDialectId = "https://json-schema.org/validation";
5
+ const defaultDialectId = "https://json-schema.org/v1";
6
6
 
7
7
  export const annotation = (node, keyword, dialect = defaultDialectId) => {
8
8
  const keywordUri = getKeywordId(keyword, dialect);
@@ -0,0 +1,31 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getShouldValidateFormat } from "../lib/configuration.js";
4
+ import { getFormatHandler } from "../lib/keywords.js";
5
+
6
+
7
+ const id = "https://json-schema.org/keyword/draft-04/format";
8
+
9
+ const compile = (schema) => Browser.value(schema);
10
+
11
+ const interpret = (format, instance) => {
12
+ if (getShouldValidateFormat() === false) {
13
+ return true;
14
+ }
15
+
16
+ const handler = getFormatHandler(formats[format]);
17
+ return handler?.(Instance.value(instance)) ?? true;
18
+ };
19
+
20
+ const annotation = (format) => format;
21
+
22
+ const formats = {
23
+ "date-time": "https://json-schema.org/format/date-time",
24
+ "email": "https://json-schema.org/format/email",
25
+ "hostname": "https://json-schema.org/format/draft-04/hostname",
26
+ "ipv4": "https://json-schema.org/format/ipv4",
27
+ "ipv6": "https://json-schema.org/format/ipv6",
28
+ "uri": "https://json-schema.org/format/uri"
29
+ };
30
+
31
+ export default { id, compile, interpret, annotation, formats };
package/draft-04/index.js CHANGED
@@ -7,6 +7,7 @@ import exclusiveMaximum from "./exclusiveMaximum.js";
7
7
  import exclusiveMinimum from "./exclusiveMinimum.js";
8
8
  import id from "./id.js";
9
9
  import items from "./items.js";
10
+ import format from "./format.js";
10
11
  import maximum from "./maximum.js";
11
12
  import minimum from "./minimum.js";
12
13
  import ref from "./ref.js";
@@ -20,6 +21,7 @@ addKeyword(maximum);
20
21
  addKeyword(minimum);
21
22
  addKeyword(id);
22
23
  addKeyword(items);
24
+ addKeyword(format);
23
25
  addKeyword(ref);
24
26
 
25
27
  const jsonSchemaVersion = "http://json-schema.org/draft-04/schema";
@@ -38,7 +40,7 @@ defineVocabulary(jsonSchemaVersion, {
38
40
  "enum": "https://json-schema.org/keyword/enum",
39
41
  "exclusiveMaximum": "https://json-schema.org/keyword/draft-04/exclusiveMaximum",
40
42
  "exclusiveMinimum": "https://json-schema.org/keyword/draft-04/exclusiveMinimum",
41
- "format": "https://json-schema.org/keyword/format",
43
+ "format": "https://json-schema.org/keyword/draft-04/format",
42
44
  "items": "https://json-schema.org/keyword/draft-04/items",
43
45
  "maxItems": "https://json-schema.org/keyword/maxItems",
44
46
  "maxLength": "https://json-schema.org/keyword/maxLength",
@@ -0,0 +1,34 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getShouldValidateFormat } from "../lib/configuration.js";
4
+ import { getFormatHandler } from "../lib/keywords.js";
5
+
6
+
7
+ const id = "https://json-schema.org/keyword/draft-06/format";
8
+
9
+ const compile = (schema) => Browser.value(schema);
10
+
11
+ const interpret = (format, instance) => {
12
+ if (getShouldValidateFormat() === false) {
13
+ return true;
14
+ }
15
+
16
+ const handler = getFormatHandler(formats[format]);
17
+ return handler?.(Instance.value(instance)) ?? true;
18
+ };
19
+
20
+ const annotation = (format) => format;
21
+
22
+ const formats = {
23
+ "date-time": "https://json-schema.org/format/date-time",
24
+ "email": "https://json-schema.org/format/email",
25
+ "hostname": "https://json-schema.org/format/draft-04/hostname",
26
+ "ipv4": "https://json-schema.org/format/ipv4",
27
+ "ipv6": "https://json-schema.org/format/ipv6",
28
+ "uri": "https://json-schema.org/format/uri",
29
+ "uri-reference": "https://json-schema.org/format/uri-reference",
30
+ "uri-template": "https://json-schema.org/format/uri-template",
31
+ "json-pointer": "https://json-schema.org/format/json-pointer"
32
+ };
33
+
34
+ export default { id, compile, interpret, annotation, formats };
package/draft-06/index.js CHANGED
@@ -7,6 +7,7 @@ import contains from "./contains.js";
7
7
  import dependencies from "../draft-04/dependencies.js";
8
8
  import id from "../draft-04/id.js";
9
9
  import items from "../draft-04/items.js";
10
+ import format from "./format.js";
10
11
  import ref from "../draft-04/ref.js";
11
12
 
12
13
 
@@ -15,6 +16,7 @@ addKeyword(dependencies);
15
16
  addKeyword(contains);
16
17
  addKeyword(id);
17
18
  addKeyword(items);
19
+ addKeyword(format);
18
20
  addKeyword(ref);
19
21
 
20
22
  const jsonSchemaVersion = "http://json-schema.org/draft-06/schema";
@@ -36,7 +38,7 @@ defineVocabulary(jsonSchemaVersion, {
36
38
  "examples": "https://json-schema.org/keyword/examples",
37
39
  "exclusiveMaximum": "https://json-schema.org/keyword/exclusiveMaximum",
38
40
  "exclusiveMinimum": "https://json-schema.org/keyword/exclusiveMinimum",
39
- "format": "https://json-schema.org/keyword/format",
41
+ "format": "https://json-schema.org/keyword/draft-06/format",
40
42
  "items": "https://json-schema.org/keyword/draft-04/items",
41
43
  "maxItems": "https://json-schema.org/keyword/maxItems",
42
44
  "maxLength": "https://json-schema.org/keyword/maxLength",
@@ -0,0 +1,42 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getShouldValidateFormat } from "../lib/configuration.js";
4
+ import { getFormatHandler } from "../lib/keywords.js";
5
+
6
+
7
+ const id = "https://json-schema.org/keyword/draft-07/format";
8
+
9
+ const compile = (schema) => Browser.value(schema);
10
+
11
+ const interpret = (format, instance) => {
12
+ if (getShouldValidateFormat() === false) {
13
+ return true;
14
+ }
15
+
16
+ const handler = getFormatHandler(formats[format]);
17
+ return handler?.(Instance.value(instance)) ?? true;
18
+ };
19
+
20
+ const annotation = (format) => format;
21
+
22
+ const formats = {
23
+ "date-time": "https://json-schema.org/format/date-time",
24
+ "date": "https://json-schema.org/format/date",
25
+ "time": "https://json-schema.org/format/time",
26
+ "email": "https://json-schema.org/format/email",
27
+ "idn-email": "https://json-schema.org/format/idn-email",
28
+ "hostname": "https://json-schema.org/format/hostname",
29
+ "idn-hostname": "https://json-schema.org/format/idn-hostname",
30
+ "ipv4": "https://json-schema.org/format/ipv4",
31
+ "ipv6": "https://json-schema.org/format/ipv6",
32
+ "uri": "https://json-schema.org/format/uri",
33
+ "uri-reference": "https://json-schema.org/format/uri-reference",
34
+ "iri": "https://json-schema.org/format/iri",
35
+ "iri-reference": "https://json-schema.org/format/iri-reference",
36
+ "uri-template": "https://json-schema.org/format/uri-template",
37
+ "json-pointer": "https://json-schema.org/format/json-pointer",
38
+ "relative-json-pointer": "https://json-schema.org/format/relative-json-pointer",
39
+ "regex": "https://json-schema.org/format/regex"
40
+ };
41
+
42
+ export default { id, compile, interpret, annotation, formats };
package/draft-07/index.js CHANGED
@@ -7,6 +7,7 @@ import contains from "../draft-06/contains.js";
7
7
  import dependencies from "../draft-04/dependencies.js";
8
8
  import items from "../draft-04/items.js";
9
9
  import id from "../draft-04/id.js";
10
+ import format from "./format.js";
10
11
  import ref from "../draft-04/ref.js";
11
12
 
12
13
 
@@ -15,6 +16,7 @@ addKeyword(contains);
15
16
  addKeyword(dependencies);
16
17
  addKeyword(id);
17
18
  addKeyword(items);
19
+ addKeyword(format);
18
20
  addKeyword(ref);
19
21
 
20
22
  const jsonSchemaVersion = "http://json-schema.org/draft-07/schema";
@@ -39,7 +41,7 @@ defineVocabulary(jsonSchemaVersion, {
39
41
  "examples": "https://json-schema.org/keyword/examples",
40
42
  "exclusiveMaximum": "https://json-schema.org/keyword/exclusiveMaximum",
41
43
  "exclusiveMinimum": "https://json-schema.org/keyword/exclusiveMinimum",
42
- "format": "https://json-schema.org/keyword/format",
44
+ "format": "https://json-schema.org/keyword/draft-07/format",
43
45
  "if": "https://json-schema.org/keyword/if",
44
46
  "then": "https://json-schema.org/keyword/then",
45
47
  "else": "https://json-schema.org/keyword/else",
@@ -0,0 +1,44 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getShouldValidateFormat } from "../lib/configuration.js";
4
+ import { getFormatHandler } from "../lib/keywords.js";
5
+
6
+
7
+ const id = "https://json-schema.org/keyword/draft-2019-09/format-assertion";
8
+
9
+ const compile = (schema) => Browser.value(schema);
10
+
11
+ const interpret = (format, instance) => {
12
+ if (getShouldValidateFormat() === false) {
13
+ return true;
14
+ }
15
+
16
+ const handler = getFormatHandler(formats[format]);
17
+ return handler?.(Instance.value(instance)) ?? true;
18
+ };
19
+
20
+ const annotation = (format) => format;
21
+
22
+ const formats = {
23
+ "date-time": "https://json-schema.org/format/date-time",
24
+ "date": "https://json-schema.org/format/date",
25
+ "time": "https://json-schema.org/format/time",
26
+ "duration": "https://json-schema.org/format/duration",
27
+ "email": "https://json-schema.org/format/email",
28
+ "idn-email": "https://json-schema.org/format/idn-email",
29
+ "hostname": "https://json-schema.org/format/hostname",
30
+ "idn-hostname": "https://json-schema.org/format/idn-hostname",
31
+ "ipv4": "https://json-schema.org/format/ipv4",
32
+ "ipv6": "https://json-schema.org/format/ipv6",
33
+ "uri": "https://json-schema.org/format/uri",
34
+ "uri-reference": "https://json-schema.org/format/uri-reference",
35
+ "iri": "https://json-schema.org/format/iri",
36
+ "iri-reference": "https://json-schema.org/format/iri-reference",
37
+ "uuid": "https://json-schema.org/format/uuid",
38
+ "uri-template": "https://json-schema.org/format/uri-template",
39
+ "json-pointer": "https://json-schema.org/format/json-pointer",
40
+ "relative-json-pointer": "https://json-schema.org/format/relative-json-pointer",
41
+ "regex": "https://json-schema.org/format/regex"
42
+ };
43
+
44
+ export default { id, compile, interpret, annotation, formats };
@@ -0,0 +1,44 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getShouldValidateFormat } from "../lib/configuration.js";
4
+ import { getFormatHandler } from "../lib/keywords.js";
5
+
6
+
7
+ const id = "https://json-schema.org/keyword/draft-2019-09/format";
8
+
9
+ const compile = (schema) => Browser.value(schema);
10
+
11
+ const interpret = (format, instance) => {
12
+ if (!getShouldValidateFormat()) {
13
+ return true;
14
+ }
15
+
16
+ const handler = getFormatHandler(formats[format]);
17
+ return handler?.(Instance.value(instance)) ?? true;
18
+ };
19
+
20
+ const annotation = (format) => format;
21
+
22
+ const formats = {
23
+ "date-time": "https://json-schema.org/format/date-time",
24
+ "date": "https://json-schema.org/format/date",
25
+ "time": "https://json-schema.org/format/time",
26
+ "duration": "https://json-schema.org/format/duration",
27
+ "email": "https://json-schema.org/format/email",
28
+ "idn-email": "https://json-schema.org/format/idn-email",
29
+ "hostname": "https://json-schema.org/format/hostname",
30
+ "idn-hostname": "https://json-schema.org/format/idn-hostname",
31
+ "ipv4": "https://json-schema.org/format/ipv4",
32
+ "ipv6": "https://json-schema.org/format/ipv6",
33
+ "uri": "https://json-schema.org/format/uri",
34
+ "uri-reference": "https://json-schema.org/format/uri-reference",
35
+ "iri": "https://json-schema.org/format/iri",
36
+ "iri-reference": "https://json-schema.org/format/iri-reference",
37
+ "uuid": "https://json-schema.org/format/uuid",
38
+ "uri-template": "https://json-schema.org/format/uri-template",
39
+ "json-pointer": "https://json-schema.org/format/json-pointer",
40
+ "relative-json-pointer": "https://json-schema.org/format/relative-json-pointer",
41
+ "regex": "https://json-schema.org/format/regex"
42
+ };
43
+
44
+ export default { id, compile, interpret, annotation, formats };
@@ -11,12 +11,16 @@ import contentMetaSchema from "./meta/content.js";
11
11
 
12
12
  import additionalItems from "../draft-04/additionalItems.js";
13
13
  import items from "../draft-04/items.js";
14
+ import formatAssertion from "./format-assertion.js";
15
+ import format from "./format.js";
14
16
  import recursiveAnchor from "./recursiveAnchor.js";
15
17
  import recursiveRef from "../draft-2020-12/dynamicRef.js";
16
18
 
17
19
 
18
20
  addKeyword(additionalItems);
19
21
  addKeyword(items);
22
+ addKeyword(formatAssertion);
23
+ addKeyword(format);
20
24
  addKeyword(recursiveAnchor);
21
25
  addKeyword(recursiveRef);
22
26
 
@@ -85,7 +89,7 @@ defineVocabulary("https://json-schema.org/draft/2019-09/vocab/meta-data", {
85
89
  });
86
90
 
87
91
  defineVocabulary("https://json-schema.org/draft/2019-09/vocab/format", {
88
- "format": "https://json-schema.org/keyword/format"
92
+ "format": "https://json-schema.org/keyword/draft-2019-09/format-assertion"
89
93
  });
90
94
 
91
95
  defineVocabulary("https://json-schema.org/draft/2019-09/vocab/content", {
@@ -0,0 +1,43 @@
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../lib/instance.js";
3
+ import { getFormatHandler } from "../lib/keywords.js";
4
+
5
+
6
+ const id = "https://json-schema.org/keyword/draft-2020-12/format-assertion";
7
+
8
+ const compile = (schema) => Browser.value(schema);
9
+
10
+ const interpret = (format, instance) => {
11
+ const handler = getFormatHandler(formats[format]);
12
+ if (!handler) {
13
+ throw Error(`The '${format}' format is not supported.`);
14
+ }
15
+
16
+ return handler(Instance.value(instance));
17
+ };
18
+
19
+ const annotation = (format) => format;
20
+
21
+ const formats = {
22
+ "date-time": "https://json-schema.org/format/date-time",
23
+ "date": "https://json-schema.org/format/date",
24
+ "time": "https://json-schema.org/format/time",
25
+ "duration": "https://json-schema.org/format/duration",
26
+ "email": "https://json-schema.org/format/email",
27
+ "idn-email": "https://json-schema.org/format/idn-email",
28
+ "hostname": "https://json-schema.org/format/hostname",
29
+ "idn-hostname": "https://json-schema.org/format/idn-hostname",
30
+ "ipv4": "https://json-schema.org/format/ipv4",
31
+ "ipv6": "https://json-schema.org/format/ipv6",
32
+ "uri": "https://json-schema.org/format/uri",
33
+ "uri-reference": "https://json-schema.org/format/uri-reference",
34
+ "iri": "https://json-schema.org/format/iri",
35
+ "iri-reference": "https://json-schema.org/format/iri-reference",
36
+ "uuid": "https://json-schema.org/format/uuid",
37
+ "uri-template": "https://json-schema.org/format/uri-template",
38
+ "json-pointer": "https://json-schema.org/format/json-pointer",
39
+ "relative-json-pointer": "https://json-schema.org/format/relative-json-pointer",
40
+ "regex": "https://json-schema.org/format/regex"
41
+ };
42
+
43
+ export default { id, compile, interpret, annotation, formats };
@@ -13,10 +13,14 @@ import unevaluatedMetaSchema from "./meta/unevaluated.js";
13
13
 
14
14
  import dynamicAnchor from "./dynamicAnchor.js";
15
15
  import dynamicRef from "./dynamicRef.js";
16
+ import format from "../draft-2019-09/format.js";
17
+ import formatAssertion from "./format-assertion.js";
16
18
 
17
19
 
18
20
  addKeyword(dynamicRef);
19
21
  addKeyword(dynamicAnchor);
22
+ addKeyword(format);
23
+ addKeyword(formatAssertion);
20
24
 
21
25
  defineVocabulary("https://json-schema.org/draft/2020-12/vocab/core", {
22
26
  "$anchor": "https://json-schema.org/keyword/anchor",
@@ -81,11 +85,11 @@ defineVocabulary("https://json-schema.org/draft/2020-12/vocab/meta-data", {
81
85
  });
82
86
 
83
87
  defineVocabulary("https://json-schema.org/draft/2020-12/vocab/format-annotation", {
84
- "format": "https://json-schema.org/keyword/format"
88
+ "format": "https://json-schema.org/keyword/draft-2019-09/format"
85
89
  });
86
90
 
87
91
  defineVocabulary("https://json-schema.org/draft/2020-12/vocab/format-assertion", {
88
- "format": "https://json-schema.org/keyword/format-assertion"
92
+ "format": "https://json-schema.org/keyword/draft-2020-12/format-assertion"
89
93
  });
90
94
 
91
95
  defineVocabulary("https://json-schema.org/draft/2020-12/vocab/content", {
@@ -0,0 +1,7 @@
1
+ import { isDateTime } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/date-time",
6
+ handler: (dateTime) => typeof dateTime !== "string" || isDateTime(dateTime)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isDate } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/date",
6
+ handler: (date) => typeof date !== "string" || isDate(date)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isAsciiIdn } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/draft-04/hostname",
6
+ handler: (hostname) => typeof hostname !== "string" || isAsciiIdn(hostname)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isDuration } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/duration",
6
+ handler: (duration) => typeof duration !== "string" || isDuration(duration)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isEmail } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/email",
6
+ handler: (email) => typeof email !== "string" || isEmail(email)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isAsciiIdn } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/hostname",
6
+ handler: (hostname) => typeof hostname !== "string" || isAsciiIdn(hostname)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isIdnEmail } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/idn-email",
6
+ handler: (email) => typeof email !== "string" || isIdnEmail(email)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isIdn } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/idn-hostname",
6
+ handler: (hostname) => typeof hostname !== "string" || isIdn(hostname)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isIPv4 } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/ipv4",
6
+ handler: (ip) => typeof ip !== "string" || isIPv4(ip)
7
+ };
@@ -0,0 +1,7 @@
1
+ import { isIPv6 } from "@hyperjump/json-schema-formats";
2
+
3
+
4
+ export default {
5
+ id: "https://json-schema.org/format/ipv6",
6
+ handler: (ip) => typeof ip !== "string" || isIPv6(ip)
7
+ };