@uncefact/untp-utils 0.1.0 → 0.2.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 (220) hide show
  1. package/README.md +23 -1
  2. package/build/artefacts/detect-version-from-context.d.ts +46 -0
  3. package/build/artefacts/detect-version-from-context.js +77 -0
  4. package/build/artefacts/detect-version-from-context.js.map +1 -0
  5. package/build/artefacts/detect-version-from-context.test.d.ts +1 -0
  6. package/build/artefacts/detect-version-from-context.test.js +69 -0
  7. package/build/artefacts/detect-version-from-context.test.js.map +1 -0
  8. package/build/artefacts/index.d.ts +3 -0
  9. package/build/artefacts/index.js +4 -0
  10. package/build/artefacts/index.js.map +1 -0
  11. package/build/artefacts/urls.d.ts +79 -0
  12. package/build/artefacts/urls.js +133 -0
  13. package/build/artefacts/urls.js.map +1 -0
  14. package/build/artefacts/urls.test.d.ts +1 -0
  15. package/build/artefacts/urls.test.js +91 -0
  16. package/build/artefacts/urls.test.js.map +1 -0
  17. package/build/artefacts/version.d.ts +9 -0
  18. package/build/artefacts/version.js +17 -0
  19. package/build/artefacts/version.js.map +1 -0
  20. package/build/artefacts/version.test.d.ts +1 -0
  21. package/build/artefacts/version.test.js +16 -0
  22. package/build/artefacts/version.test.js.map +1 -0
  23. package/build/cache/in-memory-ttl-cache.d.ts +2 -0
  24. package/build/cache/in-memory-ttl-cache.js +76 -0
  25. package/build/cache/in-memory-ttl-cache.js.map +1 -0
  26. package/build/cache/in-memory-ttl-cache.test.d.ts +1 -0
  27. package/build/cache/in-memory-ttl-cache.test.js +236 -0
  28. package/build/cache/in-memory-ttl-cache.test.js.map +1 -0
  29. package/build/cache/index.d.ts +2 -0
  30. package/build/cache/index.js +2 -0
  31. package/build/cache/index.js.map +1 -0
  32. package/build/cache/ttl-cache.d.ts +22 -0
  33. package/build/cache/ttl-cache.js +2 -0
  34. package/build/cache/ttl-cache.js.map +1 -0
  35. package/build/common/as-non-empty-string.d.ts +7 -0
  36. package/build/common/as-non-empty-string.js +10 -0
  37. package/build/common/as-non-empty-string.js.map +1 -0
  38. package/build/common/as-non-empty-string.test.d.ts +1 -0
  39. package/build/common/as-non-empty-string.test.js +25 -0
  40. package/build/common/as-non-empty-string.test.js.map +1 -0
  41. package/build/common/require-string.d.ts +12 -0
  42. package/build/common/require-string.js +27 -0
  43. package/build/common/require-string.js.map +1 -0
  44. package/build/common/require-string.test.d.ts +1 -0
  45. package/build/common/require-string.test.js +53 -0
  46. package/build/common/require-string.test.js.map +1 -0
  47. package/build/conformity-vocabulary/codes.d.ts +10 -0
  48. package/build/conformity-vocabulary/codes.js +10 -0
  49. package/build/conformity-vocabulary/codes.js.map +1 -0
  50. package/build/conformity-vocabulary/errors.d.ts +44 -0
  51. package/build/conformity-vocabulary/errors.js +68 -0
  52. package/build/conformity-vocabulary/errors.js.map +1 -0
  53. package/build/conformity-vocabulary/index.d.ts +6 -0
  54. package/build/conformity-vocabulary/index.js +7 -0
  55. package/build/conformity-vocabulary/index.js.map +1 -0
  56. package/build/conformity-vocabulary/parse-conformity-catalogue.d.ts +26 -0
  57. package/build/conformity-vocabulary/parse-conformity-catalogue.js +106 -0
  58. package/build/conformity-vocabulary/parse-conformity-catalogue.js.map +1 -0
  59. package/build/conformity-vocabulary/parse-conformity-catalogue.test.d.ts +1 -0
  60. package/build/conformity-vocabulary/parse-conformity-catalogue.test.js +327 -0
  61. package/build/conformity-vocabulary/parse-conformity-catalogue.test.js.map +1 -0
  62. package/build/conformity-vocabulary/parse-conformity-scheme.d.ts +28 -0
  63. package/build/conformity-vocabulary/parse-conformity-scheme.js +47 -0
  64. package/build/conformity-vocabulary/parse-conformity-scheme.js.map +1 -0
  65. package/build/conformity-vocabulary/parse-conformity-scheme.test.d.ts +1 -0
  66. package/build/conformity-vocabulary/parse-conformity-scheme.test.js +284 -0
  67. package/build/conformity-vocabulary/parse-conformity-scheme.test.js.map +1 -0
  68. package/build/conformity-vocabulary/parsers/v0-7-0.parser.d.ts +19 -0
  69. package/build/conformity-vocabulary/parsers/v0-7-0.parser.js +219 -0
  70. package/build/conformity-vocabulary/parsers/v0-7-0.parser.js.map +1 -0
  71. package/build/conformity-vocabulary/types.d.ts +180 -0
  72. package/build/conformity-vocabulary/types.js +2 -0
  73. package/build/conformity-vocabulary/types.js.map +1 -0
  74. package/build/conformity-vocabulary/validate-conformity-claim.d.ts +26 -0
  75. package/build/conformity-vocabulary/validate-conformity-claim.js +165 -0
  76. package/build/conformity-vocabulary/validate-conformity-claim.js.map +1 -0
  77. package/build/conformity-vocabulary/validate-conformity-claim.test.d.ts +1 -0
  78. package/build/conformity-vocabulary/validate-conformity-claim.test.js +478 -0
  79. package/build/conformity-vocabulary/validate-conformity-claim.test.js.map +1 -0
  80. package/build/http-headers/index.d.ts +5 -0
  81. package/build/http-headers/index.js +6 -0
  82. package/build/http-headers/index.js.map +1 -0
  83. package/build/http-headers/is-safe-header-value.d.ts +10 -0
  84. package/build/http-headers/is-safe-header-value.js +15 -0
  85. package/build/http-headers/is-safe-header-value.js.map +1 -0
  86. package/build/http-headers/is-safe-header-value.test.d.ts +1 -0
  87. package/build/http-headers/is-safe-header-value.test.js +37 -0
  88. package/build/http-headers/is-safe-header-value.test.js.map +1 -0
  89. package/build/http-headers/parse-entity-tag.d.ts +9 -0
  90. package/build/http-headers/parse-entity-tag.js +18 -0
  91. package/build/http-headers/parse-entity-tag.js.map +1 -0
  92. package/build/http-headers/parse-entity-tag.test.d.ts +1 -0
  93. package/build/http-headers/parse-entity-tag.test.js +41 -0
  94. package/build/http-headers/parse-entity-tag.test.js.map +1 -0
  95. package/build/http-headers/parse-imf-date.d.ts +13 -0
  96. package/build/http-headers/parse-imf-date.js +23 -0
  97. package/build/http-headers/parse-imf-date.js.map +1 -0
  98. package/build/http-headers/parse-imf-date.test.d.ts +1 -0
  99. package/build/http-headers/parse-imf-date.test.js +31 -0
  100. package/build/http-headers/parse-imf-date.test.js.map +1 -0
  101. package/build/http-headers/parse-media-type.d.ts +8 -0
  102. package/build/http-headers/parse-media-type.js +21 -0
  103. package/build/http-headers/parse-media-type.js.map +1 -0
  104. package/build/http-headers/parse-media-type.test.d.ts +1 -0
  105. package/build/http-headers/parse-media-type.test.js +39 -0
  106. package/build/http-headers/parse-media-type.test.js.map +1 -0
  107. package/build/http-headers/user-agent.d.ts +35 -0
  108. package/build/http-headers/user-agent.js +45 -0
  109. package/build/http-headers/user-agent.js.map +1 -0
  110. package/build/http-headers/user-agent.test.d.ts +1 -0
  111. package/build/http-headers/user-agent.test.js +27 -0
  112. package/build/http-headers/user-agent.test.js.map +1 -0
  113. package/build/index.d.ts +1 -1
  114. package/build/index.js +1 -1
  115. package/build/index.js.map +1 -1
  116. package/build/loaders/errors.d.ts +21 -0
  117. package/build/loaders/errors.js +45 -0
  118. package/build/loaders/errors.js.map +1 -0
  119. package/build/loaders/index.d.ts +3 -0
  120. package/build/loaders/index.js +4 -0
  121. package/build/loaders/index.js.map +1 -0
  122. package/build/loaders/jsonld-document-loader.d.ts +46 -0
  123. package/build/loaders/jsonld-document-loader.js +34 -0
  124. package/build/loaders/jsonld-document-loader.js.map +1 -0
  125. package/build/loaders/jsonld-document-loader.test.d.ts +1 -0
  126. package/build/loaders/jsonld-document-loader.test.js +71 -0
  127. package/build/loaders/jsonld-document-loader.test.js.map +1 -0
  128. package/build/loaders/schema-loader.d.ts +21 -0
  129. package/build/loaders/schema-loader.js +67 -0
  130. package/build/loaders/schema-loader.js.map +1 -0
  131. package/build/loaders/schema-loader.ssrf.test.d.ts +1 -0
  132. package/build/loaders/schema-loader.ssrf.test.js +55 -0
  133. package/build/loaders/schema-loader.ssrf.test.js.map +1 -0
  134. package/build/loaders/schema-loader.test.d.ts +1 -0
  135. package/build/loaders/schema-loader.test.js +162 -0
  136. package/build/loaders/schema-loader.test.js.map +1 -0
  137. package/build/multibase-digest/multibase-digest.d.ts +23 -0
  138. package/build/multibase-digest/multibase-digest.js +40 -0
  139. package/build/multibase-digest/multibase-digest.js.map +1 -1
  140. package/build/multibase-digest/multibase-digest.test.js +46 -0
  141. package/build/multibase-digest/multibase-digest.test.js.map +1 -1
  142. package/build/node/errors.d.ts +41 -0
  143. package/build/node/errors.js +80 -0
  144. package/build/node/errors.js.map +1 -0
  145. package/build/node/index.d.ts +3 -0
  146. package/build/node/index.js +4 -0
  147. package/build/node/index.js.map +1 -0
  148. package/build/node/is-private-ip.d.ts +41 -0
  149. package/build/node/is-private-ip.js +138 -0
  150. package/build/node/is-private-ip.js.map +1 -0
  151. package/build/node/is-private-ip.test.d.ts +1 -0
  152. package/build/node/is-private-ip.test.js +96 -0
  153. package/build/node/is-private-ip.test.js.map +1 -0
  154. package/build/node/validate-public-url.d.ts +49 -0
  155. package/build/node/validate-public-url.js +94 -0
  156. package/build/node/validate-public-url.js.map +1 -0
  157. package/build/node/validate-public-url.test.d.ts +1 -0
  158. package/build/node/validate-public-url.test.js +177 -0
  159. package/build/node/validate-public-url.test.js.map +1 -0
  160. package/build/resolvers/errors.d.ts +43 -0
  161. package/build/resolvers/errors.js +99 -0
  162. package/build/resolvers/errors.js.map +1 -0
  163. package/build/resolvers/index.d.ts +5 -0
  164. package/build/resolvers/index.js +6 -0
  165. package/build/resolvers/index.js.map +1 -0
  166. package/build/resolvers/resolve-document-if-changed.d.ts +48 -0
  167. package/build/resolvers/resolve-document-if-changed.js +42 -0
  168. package/build/resolvers/resolve-document-if-changed.js.map +1 -0
  169. package/build/resolvers/resolve-document-if-changed.test.d.ts +1 -0
  170. package/build/resolvers/resolve-document-if-changed.test.js +109 -0
  171. package/build/resolvers/resolve-document-if-changed.test.js.map +1 -0
  172. package/build/resolvers/resolve-document.d.ts +86 -0
  173. package/build/resolvers/resolve-document.js +239 -0
  174. package/build/resolvers/resolve-document.js.map +1 -0
  175. package/build/resolvers/resolve-document.test.d.ts +1 -0
  176. package/build/resolvers/resolve-document.test.js +299 -0
  177. package/build/resolvers/resolve-document.test.js.map +1 -0
  178. package/build/resolvers/resolve-json-document.d.ts +40 -0
  179. package/build/resolvers/resolve-json-document.js +42 -0
  180. package/build/resolvers/resolve-json-document.js.map +1 -0
  181. package/build/resolvers/resolve-json-document.test.d.ts +1 -0
  182. package/build/resolvers/resolve-json-document.test.js +61 -0
  183. package/build/resolvers/resolve-json-document.test.js.map +1 -0
  184. package/build/structured-error.d.ts +49 -0
  185. package/build/structured-error.js +17 -0
  186. package/build/structured-error.js.map +1 -0
  187. package/build/structured-error.test.d.ts +1 -0
  188. package/build/structured-error.test.js +112 -0
  189. package/build/structured-error.test.js.map +1 -0
  190. package/build/validation/describe-jsonld-failure.d.ts +50 -0
  191. package/build/validation/describe-jsonld-failure.js +104 -0
  192. package/build/validation/describe-jsonld-failure.js.map +1 -0
  193. package/build/validation/describe-jsonld-failure.test.d.ts +1 -0
  194. package/build/validation/describe-jsonld-failure.test.js +141 -0
  195. package/build/validation/describe-jsonld-failure.test.js.map +1 -0
  196. package/build/validation/errors.d.ts +40 -0
  197. package/build/validation/errors.js +75 -0
  198. package/build/validation/errors.js.map +1 -0
  199. package/build/validation/index.d.ts +4 -0
  200. package/build/validation/index.js +5 -0
  201. package/build/validation/index.js.map +1 -0
  202. package/build/validation/validate-against-schemas.d.ts +22 -0
  203. package/build/validation/validate-against-schemas.js +65 -0
  204. package/build/validation/validate-against-schemas.js.map +1 -0
  205. package/build/validation/validate-against-schemas.test.d.ts +1 -0
  206. package/build/validation/validate-against-schemas.test.js +169 -0
  207. package/build/validation/validate-against-schemas.test.js.map +1 -0
  208. package/build/validation/validate-jsonld.context-cache.test.d.ts +1 -0
  209. package/build/validation/validate-jsonld.context-cache.test.js +32 -0
  210. package/build/validation/validate-jsonld.context-cache.test.js.map +1 -0
  211. package/build/validation/validate-jsonld.d.ts +33 -0
  212. package/build/validation/validate-jsonld.js +99 -0
  213. package/build/validation/validate-jsonld.js.map +1 -0
  214. package/build/validation/validate-jsonld.ssrf.test.d.ts +1 -0
  215. package/build/validation/validate-jsonld.ssrf.test.js +108 -0
  216. package/build/validation/validate-jsonld.ssrf.test.js.map +1 -0
  217. package/build/validation/validate-jsonld.test.d.ts +1 -0
  218. package/build/validation/validate-jsonld.test.js +200 -0
  219. package/build/validation/validate-jsonld.test.js.map +1 -0
  220. package/package.json +64 -3
@@ -0,0 +1,141 @@
1
+ import { describeJsonLdFailure } from './describe-jsonld-failure.js';
2
+ import { JsonLdExpansionFailedError, JsonLdInvalidShapeError } from './errors.js';
3
+ import { ResolverHttpError, ResolverTimedOutError } from '../resolvers/errors.js';
4
+ import { PrivateAddressError, ResolutionFailedError } from '../node/errors.js';
5
+ /** Builds an error shaped like jsonld.js's JsonLdError (which never sets native `cause`). */
6
+ function jsonLdError(name, message, details) {
7
+ const error = new Error(message);
8
+ error.name = name;
9
+ error.details = details;
10
+ return error;
11
+ }
12
+ describe('describeJsonLdFailure', () => {
13
+ describe('context-fetch: typed loader failures', () => {
14
+ it('classifies an HTTP failure on the cause chain as context-fetch, naming URL and status', () => {
15
+ const http = new ResolverHttpError('https://www.w3.org/ns/credentials/v2', 429);
16
+ const wrapped = new JsonLdExpansionFailedError(new Error('jsonld wrapper', { cause: http }));
17
+ const failure = describeJsonLdFailure(wrapped);
18
+ expect(failure.kind).toBe('context-fetch');
19
+ expect(failure.detail).toContain('https://www.w3.org/ns/credentials/v2');
20
+ expect(failure.detail).toContain('429');
21
+ });
22
+ it('classifies a timeout on the cause chain as context-fetch', () => {
23
+ const wrapped = new JsonLdExpansionFailedError(new ResolverTimedOutError('https://example.com/ctx', 10_000));
24
+ expect(describeJsonLdFailure(wrapped)).toMatchObject({ kind: 'context-fetch' });
25
+ });
26
+ it.each([
27
+ ['PrivateAddressError', new PrivateAddressError('https://internal.example/ctx', ['10.0.0.5'])],
28
+ ['ResolutionFailedError', new ResolutionFailedError('https://nxdomain.example/ctx', new Error('ENOTFOUND'))],
29
+ ])('collapses %s to one flat message, leaking neither the URL nor the rejection class', (_name, rejected) => {
30
+ const wrapped = new JsonLdExpansionFailedError(new Error('scoped context', { cause: rejected }));
31
+ const failure = describeJsonLdFailure(wrapped);
32
+ expect(failure.kind).toBe('context-fetch');
33
+ // One message for every UrlValidationError subclass: distinguishing
34
+ // "does not resolve" from "resolves privately" would be a per-hostname
35
+ // reconnaissance oracle. The typed detail stays on the cause chain.
36
+ expect(failure.detail).toBe("a remote @context URL was rejected by this service's URL policy or could not be resolved");
37
+ expect(failure.detail).not.toMatch(/10\.0\.0\.5|internal\.example|nxdomain\.example/);
38
+ });
39
+ it('prefers the flat loader message over the URL-bearing jsonld wrapper above it (rehydrated chain shape)', () => {
40
+ // The real chain after validateJsonLd rehydration: the loader error
41
+ // hangs BENEATH jsonld.InvalidUrl, whose message contains the URL.
42
+ const loaderError = new PrivateAddressError('https://169.254.169.254/latest/meta-data/', ['169.254.169.254']);
43
+ const wrapper = jsonLdError('jsonld.InvalidUrl', 'Dereferencing a URL did not result in a valid JSON-LD object. URL: "https://169.254.169.254/latest/meta-data/".', { code: 'loading remote context failed' });
44
+ wrapper.cause = loaderError;
45
+ const wrapped = new JsonLdExpansionFailedError(wrapper);
46
+ const failure = describeJsonLdFailure(wrapped);
47
+ expect(failure.kind).toBe('context-fetch');
48
+ expect(failure.detail).not.toContain('169.254.169.254');
49
+ });
50
+ it('finds a typed failure at any depth of the cause chain', () => {
51
+ let chain = new ResolverHttpError('https://example.com/ctx', 503);
52
+ for (let i = 0; i < 20; i += 1) {
53
+ chain = new Error(`wrapper ${i}`, { cause: chain });
54
+ }
55
+ expect(describeJsonLdFailure(new JsonLdExpansionFailedError(chain))).toMatchObject({ kind: 'context-fetch' });
56
+ });
57
+ });
58
+ describe('context-fetch: fetched but unusable remote contexts', () => {
59
+ it('classifies non-object remote context content as context-fetch with a generic message', () => {
60
+ const processor = jsonLdError('jsonld.InvalidUrl', 'Dereferencing a URL did not result in a JSON object. The response was valid JSON, but it was not a JSON object. URL: "https://example.com/ctx".', { code: 'invalid remote context' });
61
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(processor));
62
+ expect(failure.kind).toBe('context-fetch');
63
+ expect(failure.detail).toBe('a remote @context document was fetched but could not be used as a context');
64
+ });
65
+ it('leaves the shared "loading remote context failed" code document-class for other error names', () => {
66
+ // jsonld.ContextUrlError reuses the code for the JSON-LD 1.0 context
67
+ // limit; only jsonld.InvalidUrl carries the remote-content meaning.
68
+ const processor = jsonLdError('jsonld.ContextUrlError', 'Maximum number of @context URLs exceeded.', {
69
+ code: 'loading remote context failed',
70
+ });
71
+ expect(describeJsonLdFailure(new JsonLdExpansionFailedError(processor))).toMatchObject({ kind: 'document' });
72
+ });
73
+ });
74
+ describe('document: recognised processor shapes', () => {
75
+ it('extracts the safe-mode event message and offending property (real jsonld@8.3.3 shape)', () => {
76
+ const processor = jsonLdError('jsonld.ValidationError', 'Safe mode validation error.', {
77
+ event: {
78
+ type: ['JsonLdEvent'],
79
+ code: 'invalid property',
80
+ level: 'warning',
81
+ message: 'Dropping property that did not expand into an absolute IRI or keyword.',
82
+ details: { property: 'unknownTerm', expandedProperty: 'unknownTerm' },
83
+ },
84
+ });
85
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(processor));
86
+ expect(failure.kind).toBe('document');
87
+ expect(failure.detail).toContain('Dropping property that did not expand');
88
+ expect(failure.detail).toContain('unknownTerm');
89
+ });
90
+ it('never echoes non-allowlisted event fields, which can carry credential content', () => {
91
+ const processor = jsonLdError('jsonld.ValidationError', 'Safe mode validation error.', {
92
+ event: {
93
+ code: 'object with only @id',
94
+ message: 'Dropping object with only @id.',
95
+ details: { value: { '@id': 'urn:secret:batch-7734' } },
96
+ },
97
+ });
98
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(processor));
99
+ expect(failure.kind).toBe('document');
100
+ expect(failure.detail).not.toContain('urn:secret:batch-7734');
101
+ });
102
+ it('passes a jsonld syntax-error message through (library-authored fixed strings)', () => {
103
+ const processor = jsonLdError('jsonld.SyntaxError', 'Invalid JSON-LD syntax; @type value must be a string.', {
104
+ code: 'invalid type value',
105
+ });
106
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(processor));
107
+ expect(failure.kind).toBe('document');
108
+ expect(failure.detail).toBe('Invalid JSON-LD syntax; @type value must be a string.');
109
+ });
110
+ it('keeps the typed invalid-shape diagnostic', () => {
111
+ const failure = describeJsonLdFailure(new JsonLdInvalidShapeError(null));
112
+ expect(failure.kind).toBe('document');
113
+ expect(failure.detail).toContain('non-null object');
114
+ });
115
+ });
116
+ describe('document: unrecognised failures never leak raw messages', () => {
117
+ it('returns the generic message for an untyped error instead of echoing its text', () => {
118
+ const leaky = new Error('internal path /srv/app/private-config.json');
119
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(leaky));
120
+ expect(failure.kind).toBe('document');
121
+ expect(failure.detail).toBe('the document could not be expanded as valid JSON-LD');
122
+ expect(failure.detail).not.toContain('/srv/app');
123
+ });
124
+ it('returns the generic message for an unknown jsonld.* error name', () => {
125
+ const processor = jsonLdError('jsonld.OptionsError', 'Some future message naming internals.', {});
126
+ const failure = describeJsonLdFailure(new JsonLdExpansionFailedError(processor));
127
+ expect(failure.kind).toBe('document');
128
+ expect(failure.detail).toBe('the document could not be expanded as valid JSON-LD');
129
+ });
130
+ it('terminates on a cyclic cause chain and classifies it as document', () => {
131
+ const a = new Error('a');
132
+ const b = new Error('b', { cause: a });
133
+ a.cause = b;
134
+ expect(describeJsonLdFailure(new JsonLdExpansionFailedError(a))).toMatchObject({
135
+ kind: 'document',
136
+ detail: 'the document could not be expanded as valid JSON-LD',
137
+ });
138
+ });
139
+ });
140
+ });
141
+ //# sourceMappingURL=describe-jsonld-failure.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe-jsonld-failure.test.js","sourceRoot":"","sources":["../../src/validation/describe-jsonld-failure.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { StructuredError, type ValidationFailure } from '../structured-error.js';
2
+ /**
3
+ * Base for every JSON-LD validation diagnostic. Catch to handle any
4
+ * JSON-LD failure generically; catch a concrete subclass for specific handling.
5
+ */
6
+ export declare class JsonLdValidationError extends StructuredError {
7
+ }
8
+ /** The input was not a non-null object. */
9
+ export declare class JsonLdInvalidShapeError extends JsonLdValidationError {
10
+ constructor(document: unknown);
11
+ }
12
+ /** `jsonld.toRDF` rejected the document (malformed context, undefined terms, etc.). */
13
+ export declare class JsonLdExpansionFailedError extends JsonLdValidationError {
14
+ constructor(cause: unknown);
15
+ }
16
+ /**
17
+ * Base for every JSON Schema validation diagnostic. Catch to handle any
18
+ * schema-validation failure generically; catch a concrete subclass for
19
+ * specific handling.
20
+ */
21
+ export declare class SchemaValidationError extends StructuredError {
22
+ }
23
+ /** A schema URL could not be loaded. */
24
+ export declare class SchemaFetchFailedError extends SchemaValidationError {
25
+ constructor(url: string, cause: unknown);
26
+ }
27
+ /** Ajv refused to compile the schema (malformed schema, duplicate `$id`, etc.). */
28
+ export declare class SchemaCompilationFailedError extends SchemaValidationError {
29
+ constructor(identifier: string, cause: unknown);
30
+ }
31
+ /**
32
+ * The payload failed schema validation. Carries every Ajv `allErrors`
33
+ * failure across every schema in {@link failures}, each with `code`
34
+ * `'schema.payload-invalid'` plus the Ajv-derived `pointer`, `received`,
35
+ * and `expected`.
36
+ */
37
+ export declare class SchemaPayloadError extends SchemaValidationError {
38
+ readonly failures: readonly ValidationFailure[];
39
+ constructor(failures: readonly ValidationFailure[]);
40
+ }
@@ -0,0 +1,75 @@
1
+ import { StructuredError } from '../structured-error.js';
2
+ /**
3
+ * Base for every JSON-LD validation diagnostic. Catch to handle any
4
+ * JSON-LD failure generically; catch a concrete subclass for specific handling.
5
+ */
6
+ export class JsonLdValidationError extends StructuredError {
7
+ }
8
+ /** The input was not a non-null object. */
9
+ export class JsonLdInvalidShapeError extends JsonLdValidationError {
10
+ constructor(document) {
11
+ super({
12
+ code: 'jsonld.invalid-shape',
13
+ message: 'JSON-LD document must be a non-null object.',
14
+ received: document === null ? 'null' : typeof document,
15
+ expected: 'object',
16
+ });
17
+ }
18
+ }
19
+ /** `jsonld.toRDF` rejected the document (malformed context, undefined terms, etc.). */
20
+ export class JsonLdExpansionFailedError extends JsonLdValidationError {
21
+ constructor(cause) {
22
+ super({
23
+ code: 'jsonld.expansion-failed',
24
+ message: 'JSON-LD expansion failed.',
25
+ received: cause instanceof Error ? cause.message : String(cause),
26
+ cause,
27
+ });
28
+ }
29
+ }
30
+ /**
31
+ * Base for every JSON Schema validation diagnostic. Catch to handle any
32
+ * schema-validation failure generically; catch a concrete subclass for
33
+ * specific handling.
34
+ */
35
+ export class SchemaValidationError extends StructuredError {
36
+ }
37
+ /** A schema URL could not be loaded. */
38
+ export class SchemaFetchFailedError extends SchemaValidationError {
39
+ constructor(url, cause) {
40
+ super({
41
+ code: 'schema.fetch-failed',
42
+ message: `Could not load schema from ${url}.`,
43
+ received: url,
44
+ cause,
45
+ });
46
+ }
47
+ }
48
+ /** Ajv refused to compile the schema (malformed schema, duplicate `$id`, etc.). */
49
+ export class SchemaCompilationFailedError extends SchemaValidationError {
50
+ constructor(identifier, cause) {
51
+ super({
52
+ code: 'schema.compilation-failed',
53
+ message: `Could not compile schema from ${identifier}.`,
54
+ received: cause instanceof Error ? cause.message : String(cause),
55
+ cause,
56
+ });
57
+ }
58
+ }
59
+ /**
60
+ * The payload failed schema validation. Carries every Ajv `allErrors`
61
+ * failure across every schema in {@link failures}, each with `code`
62
+ * `'schema.payload-invalid'` plus the Ajv-derived `pointer`, `received`,
63
+ * and `expected`.
64
+ */
65
+ export class SchemaPayloadError extends SchemaValidationError {
66
+ failures;
67
+ constructor(failures) {
68
+ super({
69
+ code: 'schema.payload-invalid',
70
+ message: `Payload failed validation against ${failures.length} rule(s).`,
71
+ });
72
+ this.failures = failures;
73
+ }
74
+ }
75
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/validation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA0B,MAAM,wBAAwB,CAAC;AAEjF;;;GAGG;AACH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;CAAG;AAE7D,2CAA2C;AAC3C,MAAM,OAAO,uBAAwB,SAAQ,qBAAqB;IAChE,YAAY,QAAiB;QAC3B,KAAK,CAAC;YACJ,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,6CAA6C;YACtD,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,QAAQ;YACtD,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC;CACF;AAED,uFAAuF;AACvF,MAAM,OAAO,0BAA2B,SAAQ,qBAAqB;IACnE,YAAY,KAAc;QACxB,KAAK,CAAC;YACJ,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,2BAA2B;YACpC,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAChE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;CAAG;AAE7D,wCAAwC;AACxC,MAAM,OAAO,sBAAuB,SAAQ,qBAAqB;IAC/D,YAAY,GAAW,EAAE,KAAc;QACrC,KAAK,CAAC;YACJ,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,8BAA8B,GAAG,GAAG;YAC7C,QAAQ,EAAE,GAAG;YACb,KAAK;SACN,CAAC,CAAC;IACL,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,OAAO,4BAA6B,SAAQ,qBAAqB;IACrE,YAAY,UAAkB,EAAE,KAAc;QAC5C,KAAK,CAAC;YACJ,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,iCAAiC,UAAU,GAAG;YACvD,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAChE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,qBAAqB;IAClD,QAAQ,CAA+B;IAChD,YAAY,QAAsC;QAChD,KAAK,CAAC;YACJ,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,qCAAqC,QAAQ,CAAC,MAAM,WAAW;SACzE,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { JsonLdValidationError, JsonLdInvalidShapeError, JsonLdExpansionFailedError, SchemaValidationError, SchemaFetchFailedError, SchemaCompilationFailedError, SchemaPayloadError, } from './errors.js';
2
+ export { validateJsonLd, type ValidateJsonLdOptions } from './validate-jsonld.js';
3
+ export { validateAgainstSchemas, type SchemaReference } from './validate-against-schemas.js';
4
+ export { describeJsonLdFailure, type JsonLdFailureDescription } from './describe-jsonld-failure.js';
@@ -0,0 +1,5 @@
1
+ export { JsonLdValidationError, JsonLdInvalidShapeError, JsonLdExpansionFailedError, SchemaValidationError, SchemaFetchFailedError, SchemaCompilationFailedError, SchemaPayloadError, } from './errors.js';
2
+ export { validateJsonLd } from './validate-jsonld.js';
3
+ export { validateAgainstSchemas } from './validate-against-schemas.js';
4
+ export { describeJsonLdFailure } from './describe-jsonld-failure.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAwB,MAAM,+BAA+B,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAiC,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SchemaLoader } from '../loaders/schema-loader.js';
2
+ /**
3
+ * A schema reference. A string is treated as a URL and loaded via the
4
+ * supplied {@link SchemaLoader}; an object is used directly as the JSON
5
+ * Schema document. The two forms may be mixed in one call.
6
+ */
7
+ export type SchemaReference = string | object;
8
+ /**
9
+ * Validates a payload against one or more JSON Schemas. Ajv runs with
10
+ * `allErrors: true` so a single payload surfaces every validation failure
11
+ * per schema, and payload failures accumulate across all schemas.
12
+ *
13
+ * Fetch and compile failures are fail-fast: the first schema that cannot
14
+ * be loaded or compiled aborts the run. Only payload-invalid failures
15
+ * accumulate.
16
+ *
17
+ * @throws {SchemaFetchFailedError} if a schema URL cannot be loaded.
18
+ * @throws {SchemaCompilationFailedError} if Ajv refuses a schema.
19
+ * @throws {SchemaPayloadError} carrying every Ajv `allErrors` failure in
20
+ * `failures[]` if any payload validation failed.
21
+ */
22
+ export declare function validateAgainstSchemas(payload: unknown, schemas: SchemaReference[], loader: SchemaLoader): Promise<void>;
@@ -0,0 +1,65 @@
1
+ import Ajv2020 from 'ajv/dist/2020.js';
2
+ import addFormats from 'ajv-formats';
3
+ import { SchemaCompilationFailedError, SchemaFetchFailedError, SchemaPayloadError } from './errors.js';
4
+ function buildAjv() {
5
+ const ajv = new Ajv2020({ strict: false, allErrors: true, verbose: true });
6
+ addFormats(ajv);
7
+ return ajv;
8
+ }
9
+ /**
10
+ * Validates a payload against one or more JSON Schemas. Ajv runs with
11
+ * `allErrors: true` so a single payload surfaces every validation failure
12
+ * per schema, and payload failures accumulate across all schemas.
13
+ *
14
+ * Fetch and compile failures are fail-fast: the first schema that cannot
15
+ * be loaded or compiled aborts the run. Only payload-invalid failures
16
+ * accumulate.
17
+ *
18
+ * @throws {SchemaFetchFailedError} if a schema URL cannot be loaded.
19
+ * @throws {SchemaCompilationFailedError} if Ajv refuses a schema.
20
+ * @throws {SchemaPayloadError} carrying every Ajv `allErrors` failure in
21
+ * `failures[]` if any payload validation failed.
22
+ */
23
+ export async function validateAgainstSchemas(payload, schemas, loader) {
24
+ const failures = [];
25
+ const ajv = buildAjv();
26
+ for (const ref of schemas) {
27
+ let schemaDoc;
28
+ let identifier;
29
+ if (typeof ref === 'string') {
30
+ identifier = ref;
31
+ try {
32
+ schemaDoc = await loader.load(ref);
33
+ }
34
+ catch (cause) {
35
+ throw new SchemaFetchFailedError(ref, cause);
36
+ }
37
+ }
38
+ else {
39
+ identifier = '<inline schema>';
40
+ schemaDoc = ref;
41
+ }
42
+ let validate;
43
+ try {
44
+ validate = ajv.compile(schemaDoc);
45
+ }
46
+ catch (cause) {
47
+ throw new SchemaCompilationFailedError(identifier, cause);
48
+ }
49
+ if (!validate(payload) && validate.errors) {
50
+ for (const ajvError of validate.errors) {
51
+ failures.push({
52
+ code: 'schema.payload-invalid',
53
+ message: ajvError.message ?? 'Schema validation failed.',
54
+ pointer: ajvError.instancePath || '',
55
+ received: ajvError.data,
56
+ expected: ajvError.params,
57
+ });
58
+ }
59
+ }
60
+ }
61
+ if (failures.length > 0) {
62
+ throw new SchemaPayloadError(failures);
63
+ }
64
+ }
65
+ //# sourceMappingURL=validate-against-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-against-schemas.js","sourceRoot":"","sources":["../../src/validation/validate-against-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AACvC,OAAO,UAAU,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvG,SAAS,QAAQ;IACf,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC;AASD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAgB,EAChB,OAA0B,EAC1B,MAAoB;IAEpB,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IAEvB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,SAAiB,CAAC;QACtB,IAAI,UAAkB,CAAC;QAEvB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,UAAU,GAAG,GAAG,CAAC;YACjB,IAAI,CAAC;gBACH,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,sBAAsB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,UAAU,GAAG,iBAAiB,CAAC;YAC/B,SAAS,GAAG,GAAG,CAAC;QAClB,CAAC;QAED,IAAI,QAAwC,CAAC;QAC7C,IAAI,CAAC;YACH,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,4BAA4B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC1C,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACvC,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,wBAAwB;oBAC9B,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,2BAA2B;oBACxD,OAAO,EAAE,QAAQ,CAAC,YAAY,IAAI,EAAE;oBACpC,QAAQ,EAAE,QAAQ,CAAC,IAAI;oBACvB,QAAQ,EAAE,QAAQ,CAAC,MAAM;iBAC1B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,169 @@
1
+ import { jest } from '@jest/globals';
2
+ import { ResolverHttpError, ResolverInvalidJsonError } from '../resolvers/errors.js';
3
+ import { SchemaCompilationFailedError, SchemaFetchFailedError, SchemaPayloadError, SchemaValidationError, } from './errors.js';
4
+ const resolveJsonDocument = jest.fn();
5
+ // The real schema loader fetches through the guarded resolver; mock that
6
+ // boundary (keeping the real error classes) so this suite exercises the real
7
+ // loader + cache + Ajv without touching the network.
8
+ jest.unstable_mockModule('../resolvers/index.js', () => ({
9
+ resolveJsonDocument,
10
+ ResolverHttpError,
11
+ ResolverInvalidJsonError,
12
+ }));
13
+ const { createInMemoryTtlCache } = await import('../cache/in-memory-ttl-cache.js');
14
+ const { createSchemaLoader } = await import('../loaders/schema-loader.js');
15
+ const { validateAgainstSchemas } = await import('./validate-against-schemas.js');
16
+ const SCHEMA_URL_NAME = 'https://example.com/name-schema.json';
17
+ const SCHEMA_URL_AGE = 'https://example.com/age-schema.json';
18
+ const NAME_SCHEMA = {
19
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
20
+ type: 'object',
21
+ properties: { name: { type: 'string' } },
22
+ required: ['name'],
23
+ };
24
+ const AGE_SCHEMA = {
25
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
26
+ type: 'object',
27
+ properties: { age: { type: 'integer', minimum: 0 } },
28
+ required: ['age'],
29
+ };
30
+ describe('validateAgainstSchemas', () => {
31
+ let loader;
32
+ beforeEach(() => {
33
+ resolveJsonDocument.mockReset();
34
+ loader = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
35
+ });
36
+ function mockSchemaResponses(map) {
37
+ resolveJsonDocument.mockImplementation((async (url) => {
38
+ const schema = map[url];
39
+ if (!schema) {
40
+ throw new ResolverHttpError(url, 404);
41
+ }
42
+ return { json: schema, finalUrl: url };
43
+ }));
44
+ }
45
+ it('returns void when the payload passes every schema', async () => {
46
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: NAME_SCHEMA, [SCHEMA_URL_AGE]: AGE_SCHEMA });
47
+ await expect(validateAgainstSchemas({ name: 'Alice', age: 30 }, [SCHEMA_URL_NAME, SCHEMA_URL_AGE], loader)).resolves.toBeUndefined();
48
+ });
49
+ describe('payload-invalid failures (accumulating)', () => {
50
+ it('throws SchemaPayloadError with a failure per Ajv failure', async () => {
51
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: NAME_SCHEMA });
52
+ const promise = validateAgainstSchemas({ age: 30 }, [SCHEMA_URL_NAME], loader);
53
+ await expect(promise).rejects.toBeInstanceOf(SchemaPayloadError);
54
+ await expect(promise).rejects.toMatchObject({
55
+ failures: expect.arrayContaining([expect.objectContaining({ code: 'schema.payload-invalid' })]),
56
+ });
57
+ });
58
+ it('accumulates failures across multiple schemas with allErrors', async () => {
59
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: NAME_SCHEMA, [SCHEMA_URL_AGE]: AGE_SCHEMA });
60
+ try {
61
+ await validateAgainstSchemas({}, [SCHEMA_URL_NAME, SCHEMA_URL_AGE], loader);
62
+ throw new Error('expected validateAgainstSchemas to throw');
63
+ }
64
+ catch (e) {
65
+ expect(e).toBeInstanceOf(SchemaPayloadError);
66
+ expect(e.failures.length).toBeGreaterThanOrEqual(2);
67
+ }
68
+ });
69
+ it('populates pointer from Ajv instancePath', async () => {
70
+ mockSchemaResponses({ [SCHEMA_URL_AGE]: AGE_SCHEMA });
71
+ try {
72
+ await validateAgainstSchemas({ age: -1 }, [SCHEMA_URL_AGE], loader);
73
+ throw new Error('expected validateAgainstSchemas to throw');
74
+ }
75
+ catch (e) {
76
+ expect(e).toBeInstanceOf(SchemaPayloadError);
77
+ expect(e.failures[0].pointer).toBe('/age');
78
+ }
79
+ });
80
+ it('populates received from Ajv data and expected from Ajv params', async () => {
81
+ mockSchemaResponses({ [SCHEMA_URL_AGE]: AGE_SCHEMA });
82
+ try {
83
+ await validateAgainstSchemas({ age: -1 }, [SCHEMA_URL_AGE], loader);
84
+ throw new Error('expected validateAgainstSchemas to throw');
85
+ }
86
+ catch (e) {
87
+ expect(e).toBeInstanceOf(SchemaPayloadError);
88
+ const failure = e.failures[0];
89
+ expect(failure.received).toBe(-1);
90
+ expect(failure.expected).toEqual(expect.objectContaining({ comparison: '>=', limit: 0 }));
91
+ }
92
+ });
93
+ });
94
+ describe('fetch failures (fail-fast)', () => {
95
+ it('throws SchemaFetchFailedError when a schema cannot be loaded', async () => {
96
+ resolveJsonDocument.mockRejectedValue(new ResolverHttpError(SCHEMA_URL_NAME, 404));
97
+ await expect(validateAgainstSchemas({}, [SCHEMA_URL_NAME], loader)).rejects.toBeInstanceOf(SchemaFetchFailedError);
98
+ });
99
+ it('aborts on the first fetch failure without checking subsequent schemas', async () => {
100
+ mockSchemaResponses({ [SCHEMA_URL_AGE]: AGE_SCHEMA });
101
+ await expect(validateAgainstSchemas({ age: 30 }, [SCHEMA_URL_NAME, SCHEMA_URL_AGE], loader)).rejects.toMatchObject({
102
+ name: 'SchemaFetchFailedError',
103
+ received: SCHEMA_URL_NAME,
104
+ });
105
+ const fetchedUrls = resolveJsonDocument.mock.calls.map((args) => args[0]);
106
+ expect(fetchedUrls).toContain(SCHEMA_URL_NAME);
107
+ expect(fetchedUrls).not.toContain(SCHEMA_URL_AGE);
108
+ });
109
+ it("wraps a custom loader's error as SchemaFetchFailedError", async () => {
110
+ const failingLoad = jest.fn(async () => {
111
+ throw new Error('loader exploded');
112
+ });
113
+ const customLoader = { load: failingLoad };
114
+ const error = await validateAgainstSchemas({}, [SCHEMA_URL_NAME], customLoader).catch((e) => e);
115
+ expect(error).toBeInstanceOf(SchemaFetchFailedError);
116
+ expect(error.cause).toBeInstanceOf(Error);
117
+ });
118
+ it('passes URLs to the supplied loader and validates the returned schema', async () => {
119
+ const load = jest.fn(async () => NAME_SCHEMA);
120
+ const customLoader = { load: load };
121
+ await expect(validateAgainstSchemas({ name: 'Alice' }, [SCHEMA_URL_NAME], customLoader)).resolves.toBeUndefined();
122
+ expect(load).toHaveBeenCalledWith(SCHEMA_URL_NAME);
123
+ expect(resolveJsonDocument).not.toHaveBeenCalled();
124
+ });
125
+ });
126
+ describe('compilation failures (fail-fast)', () => {
127
+ it('throws SchemaCompilationFailedError when the fetched schema is invalid', async () => {
128
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: { type: 'not-a-real-type' } });
129
+ await expect(validateAgainstSchemas({}, [SCHEMA_URL_NAME], loader)).rejects.toBeInstanceOf(SchemaCompilationFailedError);
130
+ });
131
+ it('throws SchemaCompilationFailedError for an inline schema that does not compile', async () => {
132
+ const badSchema = { type: 'not-a-real-type' };
133
+ await expect(validateAgainstSchemas({}, [badSchema], loader)).rejects.toBeInstanceOf(SchemaCompilationFailedError);
134
+ expect(resolveJsonDocument).not.toHaveBeenCalled();
135
+ });
136
+ it('attributes inline-schema compilation failure to <inline schema>', async () => {
137
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: NAME_SCHEMA });
138
+ const badInline = { type: 'not-a-real-type' };
139
+ const error = (await validateAgainstSchemas({ name: 'Alice' }, [SCHEMA_URL_NAME, badInline], loader).catch((e) => e));
140
+ expect(error).toBeInstanceOf(SchemaCompilationFailedError);
141
+ expect(error.received).toMatch(/.+/);
142
+ expect(error.message).toContain('<inline schema>');
143
+ });
144
+ });
145
+ describe('inline schema references', () => {
146
+ it('validates against an inline schema without invoking the loader', async () => {
147
+ await expect(validateAgainstSchemas({ name: 'Alice' }, [NAME_SCHEMA], loader)).resolves.toBeUndefined();
148
+ expect(resolveJsonDocument).not.toHaveBeenCalled();
149
+ });
150
+ it('throws SchemaPayloadError from an inline schema when the payload fails', async () => {
151
+ await expect(validateAgainstSchemas({}, [NAME_SCHEMA], loader)).rejects.toBeInstanceOf(SchemaPayloadError);
152
+ expect(resolveJsonDocument).not.toHaveBeenCalled();
153
+ });
154
+ it('mixes URL and inline schema references in a single call', async () => {
155
+ mockSchemaResponses({ [SCHEMA_URL_NAME]: NAME_SCHEMA });
156
+ await expect(validateAgainstSchemas({ name: 'Alice', age: 30 }, [SCHEMA_URL_NAME, AGE_SCHEMA], loader)).resolves.toBeUndefined();
157
+ expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
158
+ });
159
+ });
160
+ describe('hierarchy', () => {
161
+ it('every concrete error extends SchemaValidationError', async () => {
162
+ resolveJsonDocument.mockRejectedValue(new ResolverHttpError(SCHEMA_URL_NAME, 404));
163
+ await expect(validateAgainstSchemas({}, [SCHEMA_URL_NAME], loader)).rejects.toBeInstanceOf(SchemaValidationError);
164
+ await expect(validateAgainstSchemas({}, [{ type: 'not-a-real-type' }], loader)).rejects.toBeInstanceOf(SchemaValidationError);
165
+ await expect(validateAgainstSchemas({}, [NAME_SCHEMA], loader)).rejects.toBeInstanceOf(SchemaValidationError);
166
+ });
167
+ });
168
+ });
169
+ //# sourceMappingURL=validate-against-schemas.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-against-schemas.test.js","sourceRoot":"","sources":["../../src/validation/validate-against-schemas.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { jest } from '@jest/globals';
2
+ import { createInMemoryTtlCache } from '../cache/in-memory-ttl-cache.js';
3
+ const resolveJsonDocument = jest.fn();
4
+ // Mock only the resolver boundary: real jsonld, real document loader, real
5
+ // cache. This pins the seam validateJsonLd's contextCache option promises:
6
+ // the cache outlives the per-call loader instance, so separate validateJsonLd
7
+ // calls sharing one cache resolve each remote @context once.
8
+ jest.unstable_mockModule('../resolvers/index.js', () => ({ resolveJsonDocument }));
9
+ const { validateJsonLd } = await import('./validate-jsonld.js');
10
+ const CONTEXT_URL = 'https://example.com/context';
11
+ const DOCUMENT = { '@context': CONTEXT_URL, name: 'Acme' };
12
+ describe('validateJsonLd contextCache reuse across calls', () => {
13
+ beforeEach(() => {
14
+ resolveJsonDocument.mockReset();
15
+ resolveJsonDocument.mockResolvedValue({
16
+ json: { '@context': { name: 'http://schema.org/name' } },
17
+ finalUrl: CONTEXT_URL,
18
+ });
19
+ });
20
+ it('resolves a remote @context once across separate calls sharing one cache', async () => {
21
+ const contextCache = createInMemoryTtlCache({ ttlMs: 60_000 });
22
+ await expect(validateJsonLd(DOCUMENT, { contextCache })).resolves.toBeUndefined();
23
+ await expect(validateJsonLd(DOCUMENT, { contextCache })).resolves.toBeUndefined();
24
+ expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
25
+ });
26
+ it('re-resolves the remote @context per call without a shared cache', async () => {
27
+ await expect(validateJsonLd(DOCUMENT)).resolves.toBeUndefined();
28
+ await expect(validateJsonLd(DOCUMENT)).resolves.toBeUndefined();
29
+ expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
30
+ });
31
+ });
32
+ //# sourceMappingURL=validate-jsonld.context-cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-jsonld.context-cache.test.js","sourceRoot":"","sources":["../../src/validation/validate-jsonld.context-cache.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,MAAM,mBAAmB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;AAEtC,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,6DAA6D;AAC7D,IAAI,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;AAEnF,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAEhE,MAAM,WAAW,GAAG,6BAA6B,CAAC;AAClD,MAAM,QAAQ,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAE3D,QAAQ,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,UAAU,CAAC,GAAG,EAAE;QACd,mBAAmB,CAAC,SAAS,EAAE,CAAC;QAChC,mBAAmB,CAAC,iBAAiB,CAAC;YACpC,IAAI,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,EAAE;YACxD,QAAQ,EAAE,WAAW;SACb,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,YAAY,GAAG,sBAAsB,CAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACrF,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClF,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClF,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAChE,MAAM,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAChE,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}