@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,33 @@
1
+ import type { TtlCache } from '../cache/ttl-cache.js';
2
+ import type { LoadedRemoteDocument } from '../loaders/jsonld-document-loader.js';
3
+ export interface ValidateJsonLdOptions {
4
+ /** Whether to use safe mode for JSON-LD expansion. Defaults to true. */
5
+ safe?: boolean;
6
+ /**
7
+ * Optional cache, keyed by URL, for resolved remote `@context` documents.
8
+ * Supplying a shared cache avoids re-fetching the same contexts on every
9
+ * validation (e.g. the credential context on the issuance/verification
10
+ * hot path). Only successful fetches are cached, so a URL the SSRF guard
11
+ * rejects is re-checked every time. A successfully fetched and parsed
12
+ * document is cached even if expansion later rejects it.
13
+ */
14
+ contextCache?: TtlCache<LoadedRemoteDocument>;
15
+ }
16
+ /**
17
+ * Catches malformed contexts, undefined terms, and structurally invalid
18
+ * linked data by expanding to RDF in safe mode (unless explicitly disabled).
19
+ *
20
+ * Expansion resolves every remote `@context` through a guarded document
21
+ * loader ({@link createJsonLdDocumentLoader}) so `@context` fetches pass the
22
+ * `validatePublicUrl` SSRF guard rather than jsonld.js's default unguarded
23
+ * Node loader. See ADR-033 §7 and issue #707.
24
+ *
25
+ * @see https://github.com/digitalbazaar/jsonld.js#safe-mode jsonld.js safe mode (a jsonld.js option, not a W3C-defined term).
26
+ * @see ../../../../docs/adrs/033-cvc-architecture.md ADR-033 §7 (Security considerations).
27
+ * @throws {JsonLdInvalidShapeError} if `document` is not a non-null object.
28
+ * @throws {JsonLdExpansionFailedError} if `jsonld.toRDF` rejects (which
29
+ * includes a remote `@context` failing the SSRF guard; the guard's
30
+ * rejection is reachable via native `.cause` hops off the thrown error,
31
+ * see {@link rehydrateJsonLdCause}).
32
+ */
33
+ export declare function validateJsonLd(document: unknown, options?: ValidateJsonLdOptions): Promise<void>;
@@ -0,0 +1,99 @@
1
+ import { JsonLdExpansionFailedError, JsonLdInvalidShapeError } from './errors.js';
2
+ /**
3
+ * jsonld.js's own `JsonLdError` wraps a document loader's rejection in the
4
+ * proprietary `details.cause` and never sets native `Error.cause`
5
+ * (jsonld@8.3.3 `lib/JsonLdError.js`, loader wrap in
6
+ * `lib/ContextResolver.js`), so a plain `.cause` walk over a caught
7
+ * expansion failure dead-ends one hop early: the SSRF guard's rejection
8
+ * (see `createJsonLdDocumentLoader`) is reachable only via the non-standard
9
+ * `error.details.cause`, unlike the schema-fetch path (`schema-loader.ts`),
10
+ * which surfaces the same class of rejection on the native chain.
11
+ *
12
+ * A term's own remote `@context` (a JSON-LD 1.1 "scoped context") loses even
13
+ * that: jsonld.js resolves it through the same loader, but on failure its
14
+ * scoped-context branch (`lib/context.js`) discards the loader's error
15
+ * entirely and throws a fresh `JsonLdError` whose `details` carry no `cause`
16
+ * at all. `fallback` recovers the guard's rejection in that case: `toRDF`'s
17
+ * `documentLoader` is wrapped ({@link validateJsonLd}) to record the last
18
+ * error it threw during the call, and that call-scoped record is passed here
19
+ * as `fallback`. Because jsonld.js resolves `@context` documents one at a
20
+ * time and any loader throw immediately aborts the whole call (no later,
21
+ * unrelated loader call can follow one that failed), a recorded loader error
22
+ * is always the proximate cause of whatever expansion failure this function
23
+ * is asked to rehydrate, whether or not jsonld.js chose to keep its own
24
+ * reference to it.
25
+ *
26
+ * Rehydrates the recovered error (preferring `details.cause` when jsonld.js
27
+ * kept it) onto `error.cause` so a plain `.cause` walk reaches it. Mutates
28
+ * and returns the same object jsonld.js just threw for this call (safe:
29
+ * nothing else holds a reference to it), and only when there is something to
30
+ * recover and jsonld.js has not already set a `cause` itself, so a malformed
31
+ * `@context` that never reached the document loader (and so has nothing
32
+ * buried and no fallback recorded) does not gain a spurious one.
33
+ *
34
+ * @see https://github.com/uncefact/tests-untp/issues/773
35
+ */
36
+ function rehydrateJsonLdCause(error, fallback) {
37
+ if (!(error instanceof Error) || error.cause !== undefined) {
38
+ return error;
39
+ }
40
+ const buried = error.details?.cause;
41
+ const recovered = buried !== undefined ? buried : fallback;
42
+ if (recovered !== undefined) {
43
+ error.cause = recovered;
44
+ }
45
+ return error;
46
+ }
47
+ /**
48
+ * Catches malformed contexts, undefined terms, and structurally invalid
49
+ * linked data by expanding to RDF in safe mode (unless explicitly disabled).
50
+ *
51
+ * Expansion resolves every remote `@context` through a guarded document
52
+ * loader ({@link createJsonLdDocumentLoader}) so `@context` fetches pass the
53
+ * `validatePublicUrl` SSRF guard rather than jsonld.js's default unguarded
54
+ * Node loader. See ADR-033 §7 and issue #707.
55
+ *
56
+ * @see https://github.com/digitalbazaar/jsonld.js#safe-mode jsonld.js safe mode (a jsonld.js option, not a W3C-defined term).
57
+ * @see ../../../../docs/adrs/033-cvc-architecture.md ADR-033 §7 (Security considerations).
58
+ * @throws {JsonLdInvalidShapeError} if `document` is not a non-null object.
59
+ * @throws {JsonLdExpansionFailedError} if `jsonld.toRDF` rejects (which
60
+ * includes a remote `@context` failing the SSRF guard; the guard's
61
+ * rejection is reachable via native `.cause` hops off the thrown error,
62
+ * see {@link rehydrateJsonLdCause}).
63
+ */
64
+ export async function validateJsonLd(document, options) {
65
+ if (typeof document !== 'object' || document === null) {
66
+ throw new JsonLdInvalidShapeError(document);
67
+ }
68
+ // Dynamic import: jsonld pulls in undici/TextDecoder which aren't
69
+ // available in jsdom, so we load it lazily to allow test mocking. The
70
+ // guarded document loader is loaded lazily for the same reason (it depends
71
+ // on the resolvers/node stack, which uses undici and node:dns).
72
+ const jsonldModule = await import('jsonld');
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ const jsonld = ('default' in jsonldModule ? jsonldModule.default : jsonldModule);
75
+ const { createJsonLdDocumentLoader } = await import('../loaders/jsonld-document-loader.js');
76
+ const documentLoader = createJsonLdDocumentLoader({ cache: options?.contextCache });
77
+ // Recorded for rehydrateJsonLdCause's fallback: the last error the loader
78
+ // threw during this call (undefined if every fetch it made succeeded).
79
+ let lastLoaderError;
80
+ const trackedDocumentLoader = async (url) => {
81
+ try {
82
+ return await documentLoader(url);
83
+ }
84
+ catch (loaderError) {
85
+ lastLoaderError = loaderError;
86
+ throw loaderError;
87
+ }
88
+ };
89
+ try {
90
+ // The options cast bridges @types/jsonld, which types documentLoader with
91
+ // a legacy callback signature; jsonld.js itself accepts the
92
+ // single-argument promise-returning loader used here.
93
+ await jsonld.toRDF(document, { safe: options?.safe ?? true, documentLoader: trackedDocumentLoader });
94
+ }
95
+ catch (cause) {
96
+ throw new JsonLdExpansionFailedError(rehydrateJsonLdCause(cause, lastLoaderError));
97
+ }
98
+ }
99
+ //# sourceMappingURL=validate-jsonld.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-jsonld.js","sourceRoot":"","sources":["../../src/validation/validate-jsonld.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAgBlF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,SAAS,oBAAoB,CAAC,KAAc,EAAE,QAAkB;IAC9D,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAI,KAAmD,CAAC,OAAO,EAAE,KAAK,CAAC;IACnF,MAAM,SAAS,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAiB,EAAE,OAA+B;IACrF,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,kEAAkE;IAClE,sEAAsE;IACtE,2EAA2E;IAC3E,gEAAgE;IAChE,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,8DAA8D;IAC9D,MAAM,MAAM,GAAG,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC,CAAE,YAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAA4B,CAAC;IACrH,MAAM,EAAE,0BAA0B,EAAE,GAAG,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAAC;IAC5F,MAAM,cAAc,GAAG,0BAA0B,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;IAEpF,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,eAAwB,CAAC;IAC7B,MAAM,qBAAqB,GAAG,KAAK,EAAE,GAAW,EAAiC,EAAE;QACjF,IAAI,CAAC;YACH,OAAO,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,eAAe,GAAG,WAAW,CAAC;YAC9B,MAAM,WAAW,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,0EAA0E;QAC1E,4DAA4D;QAC5D,sDAAsD;QACtD,MAAM,MAAM,CAAC,KAAK,CAChB,QAA0B,EAC1B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,cAAc,EAAE,qBAAqB,EAAwC,CAC7G,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,0BAA0B,CAAC,oBAAoB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;IACrF,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import http from 'node:http';
2
+ import { validateJsonLd } from './validate-jsonld.js';
3
+ import { JsonLdExpansionFailedError } from './errors.js';
4
+ import { UrlValidationError } from '../node/errors.js';
5
+ /**
6
+ * Walks the native `Error.cause` chain from `error`, collecting every link.
7
+ * jsonld.js's own `JsonLdError` buries a document loader's rejection at the
8
+ * non-standard `details.cause` and never sets native `Error.cause`;
9
+ * `validateJsonLd` rehydrates it onto `error.cause` when wrapping an
10
+ * expansion failure (see `validate-jsonld.ts`), so a plain `.cause` walk
11
+ * reaches the SSRF guard's rejection the same way it does on the
12
+ * schema-fetch path (`schema-loader.ssrf.test.ts`).
13
+ */
14
+ function nativeCauseChain(error) {
15
+ const chain = [];
16
+ let current = error;
17
+ while (current instanceof Error && current.cause !== undefined) {
18
+ chain.push(current.cause);
19
+ current = current.cause;
20
+ }
21
+ return chain;
22
+ }
23
+ /**
24
+ * End-to-end SSRF regression for JSON-LD expansion. Unlike `validate-jsonld.test.ts`,
25
+ * this suite does NOT mock `jsonld` or the resolver stack: it exercises the real
26
+ * `jsonld.toRDF` + guarded document loader against a live loopback server standing
27
+ * in for an internal service.
28
+ *
29
+ * The load-bearing assertion is that the canary server is NEVER contacted. A prior
30
+ * (unguarded) implementation would let jsonld.js's default Node loader fetch a
31
+ * private `@context` URL, hitting the canary. The guard rejects the URL before any
32
+ * connection, so `hits` stays 0 regardless of how the expansion ultimately fails.
33
+ *
34
+ * @see https://github.com/uncefact/tests-untp/issues/707
35
+ */
36
+ describe('validateJsonLd SSRF guard (real jsonld + guarded loader)', () => {
37
+ let server;
38
+ let baseUrl;
39
+ let hits = 0;
40
+ beforeAll(async () => {
41
+ server = http.createServer((_req, res) => {
42
+ hits += 1;
43
+ res.setHeader('content-type', 'application/ld+json');
44
+ res.end(JSON.stringify({ '@context': {} }));
45
+ });
46
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
47
+ const address = server.address();
48
+ baseUrl = `http://127.0.0.1:${address.port}`;
49
+ });
50
+ afterAll(async () => {
51
+ await new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())));
52
+ });
53
+ beforeEach(() => {
54
+ hits = 0;
55
+ });
56
+ it('never contacts a private @context URL during expansion', async () => {
57
+ const malicious = { '@context': `${baseUrl}/internal-context`, name: 'value' };
58
+ const error = await validateJsonLd(malicious).catch((e) => e);
59
+ expect(error).toBeInstanceOf(JsonLdExpansionFailedError);
60
+ // The rejection came from the SSRF guard, not an unrelated expansion failure.
61
+ expect(nativeCauseChain(error)).toContainEqual(expect.any(UrlValidationError));
62
+ // The security property: the loopback canary was never reached.
63
+ expect(hits).toBe(0);
64
+ });
65
+ it('rejects a metadata-service @context literal before any connection', async () => {
66
+ const malicious = { '@context': 'http://169.254.169.254/latest/meta-data', name: 'value' };
67
+ const error = await validateJsonLd(malicious).catch((e) => e);
68
+ expect(error).toBeInstanceOf(JsonLdExpansionFailedError);
69
+ expect(nativeCauseChain(error)).toContainEqual(expect.any(UrlValidationError));
70
+ });
71
+ it('expands a document with an inline @context without any network fetch', async () => {
72
+ const document = { '@context': { name: 'http://schema.org/name' }, name: 'Acme' };
73
+ await expect(validateJsonLd(document)).resolves.toBeUndefined();
74
+ expect(hits).toBe(0);
75
+ });
76
+ it('reaches the UrlValidationError by plain .cause hops, matching the schema-fetch path shape', async () => {
77
+ const malicious = { '@context': `${baseUrl}/internal-context`, name: 'value' };
78
+ const error = (await validateJsonLd(malicious).catch((e) => e));
79
+ // First hop: jsonld.js's own JsonLdError (still carries `.details` for
80
+ // callers that want the raw jsonld diagnostic).
81
+ expect(error.cause).toBeInstanceOf(Error);
82
+ expect(error.cause.name).toBe('jsonld.InvalidUrl');
83
+ // Second hop: the guard's rejection itself, reachable without digging
84
+ // into jsonld.js's proprietary `details.cause`.
85
+ expect(error.cause.cause).toBeInstanceOf(UrlValidationError);
86
+ });
87
+ it('never contacts a private scoped (term-level) @context URL during expansion', async () => {
88
+ // A term can declare its own remote @context (JSON-LD 1.1 scoped contexts).
89
+ // jsonld.js resolves it through the same guarded loader as a top-level
90
+ // @context, so it must be rejected the same way.
91
+ const malicious = {
92
+ '@context': { myTerm: { '@id': 'http://schema.org/myTerm', '@context': `${baseUrl}/internal-scoped-context` } },
93
+ myTerm: 'value',
94
+ };
95
+ const error = await validateJsonLd(malicious).catch((e) => e);
96
+ expect(error).toBeInstanceOf(JsonLdExpansionFailedError);
97
+ // The rejection came from the SSRF guard, reachable by plain .cause hops.
98
+ // jsonld.js's scoped-context branch (lib/context.js) discards the loader
99
+ // failure entirely and throws a fresh 'invalid scoped context' JsonLdError
100
+ // with no `details.cause` of its own, so this can only pass if
101
+ // validateJsonLd recovers the guard's rejection some other way (tracking
102
+ // it at the document-loader call, see `validate-jsonld.ts`).
103
+ expect(nativeCauseChain(error)).toContainEqual(expect.any(UrlValidationError));
104
+ // The security property: the loopback canary was never reached.
105
+ expect(hits).toBe(0);
106
+ });
107
+ });
108
+ //# sourceMappingURL=validate-jsonld.ssrf.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-jsonld.ssrf.test.js","sourceRoot":"","sources":["../../src/validation/validate-jsonld.ssrf.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,200 @@
1
+ import { jest } from '@jest/globals';
2
+ import { createInMemoryTtlCache } from '../cache/in-memory-ttl-cache.js';
3
+ import { JsonLdValidationError } from './errors.js';
4
+ const toRDF = jest.fn();
5
+ const documentLoader = jest.fn();
6
+ const createJsonLdDocumentLoader = jest.fn(() => documentLoader);
7
+ jest.unstable_mockModule('jsonld', () => ({
8
+ default: { toRDF },
9
+ toRDF,
10
+ }));
11
+ // The loader factory is mocked so this suite can assert the option threading
12
+ // (contextCache -> cache) without invoking the real resolver stack; the
13
+ // factory's own behaviour is covered in loaders/jsonld-document-loader.test.ts.
14
+ jest.unstable_mockModule('../loaders/jsonld-document-loader.js', () => ({
15
+ createJsonLdDocumentLoader,
16
+ }));
17
+ const { validateJsonLd } = await import('./validate-jsonld.js');
18
+ describe('validateJsonLd', () => {
19
+ beforeEach(() => {
20
+ toRDF.mockReset();
21
+ documentLoader.mockReset();
22
+ createJsonLdDocumentLoader.mockClear();
23
+ });
24
+ it('returns void when JSON-LD expansion succeeds', async () => {
25
+ toRDF.mockResolvedValue([]);
26
+ await expect(validateJsonLd({ '@context': 'https://example.com' })).resolves.toBeUndefined();
27
+ expect(toRDF).toHaveBeenCalledWith({ '@context': 'https://example.com' }, expect.objectContaining({ safe: true, documentLoader: expect.any(Function) }));
28
+ });
29
+ it('throws JsonLdExpansionFailedError when toRDF rejects', async () => {
30
+ toRDF.mockRejectedValue(new Error('Invalid JSON-LD'));
31
+ await expect(validateJsonLd({})).rejects.toMatchObject({
32
+ name: 'JsonLdExpansionFailedError',
33
+ code: 'jsonld.expansion-failed',
34
+ received: 'Invalid JSON-LD',
35
+ });
36
+ });
37
+ it('captures the original error on Error.cause', async () => {
38
+ const cause = new Error('Missing @context');
39
+ toRDF.mockRejectedValue(cause);
40
+ await expect(validateJsonLd({})).rejects.toMatchObject({ cause });
41
+ });
42
+ describe('rehydrating a buried jsonld.js loader error', () => {
43
+ // jsonld.js's own JsonLdError stores a document loader's rejection at
44
+ // the proprietary `details.cause` and never sets native `Error.cause`
45
+ // (jsonld@8.3.3 `lib/JsonLdError.js`, loader wrap in
46
+ // `lib/ContextResolver.js`). `validateJsonLd` rehydrates it onto the
47
+ // caught error's native `cause` so a plain `.cause` walk reaches it,
48
+ // matching the schema-fetch path (see `validate-jsonld.ssrf.test.ts`).
49
+ it('rehydrates the buried loader error onto the native cause chain', async () => {
50
+ const buried = new Error('SSRF rejected');
51
+ const jsonldError = Object.assign(new Error('Dereferencing a URL did not result in a valid JSON-LD object.'), {
52
+ name: 'jsonld.InvalidUrl',
53
+ details: { code: 'loading remote context failed', url: 'https://internal.example', cause: buried },
54
+ });
55
+ toRDF.mockRejectedValue(jsonldError);
56
+ const error = await validateJsonLd({}).catch((e) => e);
57
+ expect(error.cause).toBe(jsonldError);
58
+ // Without the rehydration, jsonldError.cause stays unset (jsonld.js
59
+ // never sets it), so this hop would be absent.
60
+ expect(jsonldError.cause).toBe(buried);
61
+ });
62
+ it('does not add a spurious cause when the jsonld error has no buried loader error', async () => {
63
+ // A malformed @context never reaches the document loader, so jsonld.js's
64
+ // details carry no `cause` to rehydrate.
65
+ const jsonldError = Object.assign(new Error('Invalid JSON-LD syntax; @context must be an object.'), {
66
+ name: 'jsonld.SyntaxError',
67
+ details: { code: 'invalid @context' },
68
+ });
69
+ toRDF.mockRejectedValue(jsonldError);
70
+ await validateJsonLd({}).catch(() => undefined);
71
+ // Asserts absence, not merely `undefined`: an implementation that sets
72
+ // `error.cause = undefined` unconditionally would pass a `toBeUndefined()`
73
+ // check but still fabricate a `cause` property that was never there.
74
+ expect('cause' in jsonldError).toBe(false);
75
+ });
76
+ it('does not clobber an existing native cause on the jsonld error', async () => {
77
+ const existingCause = new Error('existing, legitimate native cause');
78
+ const buried = new Error('buried loader error, must not overwrite the existing cause');
79
+ const jsonldError = Object.assign(new Error('wrapped', { cause: existingCause }), {
80
+ name: 'jsonld.InvalidUrl',
81
+ details: { cause: buried },
82
+ });
83
+ toRDF.mockRejectedValue(jsonldError);
84
+ await validateJsonLd({}).catch(() => undefined);
85
+ expect(jsonldError.cause).toBe(existingCause);
86
+ });
87
+ // A term's own remote @context (a JSON-LD 1.1 "scoped context") is
88
+ // resolved through the same document loader, but on failure jsonld.js's
89
+ // scoped-context branch (lib/context.js) discards the loader's error
90
+ // entirely and throws a fresh JsonLdError with no `details.cause` at
91
+ // all (see validate-jsonld.ssrf.test.ts for the real-jsonld
92
+ // reproduction). validateJsonLd recovers it by tracking the last error
93
+ // the document loader threw during the call and using that as a
94
+ // fallback cause.
95
+ describe('recovering via the tracked-loader fallback', () => {
96
+ /** Simulates toRDF calling the documentLoader it was given, then rejecting as jsonld.js would. */
97
+ function rejectAfterCallingLoader(url, rejection) {
98
+ toRDF.mockImplementation(async (...args) => {
99
+ const opts = args[1];
100
+ await opts.documentLoader(url).catch(() => undefined);
101
+ throw rejection;
102
+ });
103
+ }
104
+ it('recovers the tracked loader error when the jsonld error has no buried cause of its own', async () => {
105
+ const loaderError = new Error('SSRF rejected, recorded from the tracked loader');
106
+ documentLoader.mockRejectedValue(loaderError);
107
+ const scopedContextError = Object.assign(new Error('Invalid JSON-LD syntax; invalid scoped context.'), {
108
+ name: 'jsonld.SyntaxError',
109
+ details: { code: 'invalid scoped context', context: 'https://internal.example', term: 'myTerm' },
110
+ });
111
+ rejectAfterCallingLoader('https://internal.example', scopedContextError);
112
+ await validateJsonLd({}).catch(() => undefined);
113
+ // Without the fallback, this jsonld error's details carry no `cause`
114
+ // at all, so scopedContextError.cause would stay unset.
115
+ expect(scopedContextError.cause).toBe(loaderError);
116
+ });
117
+ it('prefers the buried details.cause over the fallback when jsonld.js kept both', async () => {
118
+ const buried = new Error('buried on details.cause, should win');
119
+ const fallbackLoaderError = new Error('recorded from the tracked loader, should lose');
120
+ documentLoader.mockRejectedValue(fallbackLoaderError);
121
+ const jsonldError = Object.assign(new Error('wrapped'), {
122
+ name: 'jsonld.InvalidUrl',
123
+ details: { cause: buried },
124
+ });
125
+ rejectAfterCallingLoader('https://example.com', jsonldError);
126
+ await validateJsonLd({}).catch(() => undefined);
127
+ expect(jsonldError.cause).toBe(buried);
128
+ });
129
+ it('does not fabricate a cause when the loader never threw during the call', async () => {
130
+ // The loader succeeds (or is never called); the eventual rejection
131
+ // is for an unrelated reason, so there is nothing to fall back to.
132
+ documentLoader.mockResolvedValue({ documentUrl: 'https://example.com', document: {} });
133
+ const unrelatedError = Object.assign(new Error('Invalid JSON-LD syntax; @context must be an object.'), {
134
+ name: 'jsonld.SyntaxError',
135
+ details: { code: 'invalid @context' },
136
+ });
137
+ rejectAfterCallingLoader('https://example.com', unrelatedError);
138
+ await validateJsonLd({}).catch(() => undefined);
139
+ expect('cause' in unrelatedError).toBe(false);
140
+ });
141
+ });
142
+ });
143
+ it('throws JsonLdInvalidShapeError when the document is not an object', async () => {
144
+ await expect(validateJsonLd('not-an-object')).rejects.toMatchObject({
145
+ name: 'JsonLdInvalidShapeError',
146
+ code: 'jsonld.invalid-shape',
147
+ received: 'string',
148
+ expected: 'object',
149
+ });
150
+ expect(toRDF).not.toHaveBeenCalled();
151
+ });
152
+ it('throws JsonLdInvalidShapeError for null input', async () => {
153
+ await expect(validateJsonLd(null)).rejects.toMatchObject({
154
+ name: 'JsonLdInvalidShapeError',
155
+ received: 'null',
156
+ });
157
+ });
158
+ it('passes safe: false to toRDF when options.safe is false', async () => {
159
+ toRDF.mockResolvedValue([]);
160
+ await validateJsonLd({ '@context': 'https://example.com' }, { safe: false });
161
+ expect(toRDF).toHaveBeenCalledWith({ '@context': 'https://example.com' }, expect.objectContaining({ safe: false, documentLoader: expect.any(Function) }));
162
+ });
163
+ it('defaults safe to true when no options provided', async () => {
164
+ toRDF.mockResolvedValue([]);
165
+ await validateJsonLd({ '@context': 'https://example.com' });
166
+ expect(toRDF).toHaveBeenCalledWith({ '@context': 'https://example.com' }, expect.objectContaining({ safe: true, documentLoader: expect.any(Function) }));
167
+ });
168
+ it('creates the document loader with the supplied contextCache', async () => {
169
+ toRDF.mockResolvedValue([]);
170
+ const contextCache = createInMemoryTtlCache({ ttlMs: 60_000 });
171
+ await validateJsonLd({ '@context': 'https://example.com' }, { contextCache });
172
+ expect(createJsonLdDocumentLoader).toHaveBeenCalledWith({ cache: contextCache });
173
+ });
174
+ it('passes toRDF a loader that delegates to the one createJsonLdDocumentLoader created', async () => {
175
+ toRDF.mockResolvedValue([]);
176
+ const remoteDoc = { documentUrl: 'https://example.com', document: {} };
177
+ documentLoader.mockResolvedValue(remoteDoc);
178
+ await validateJsonLd({ '@context': 'https://example.com' });
179
+ expect(createJsonLdDocumentLoader).toHaveBeenCalledWith({ cache: undefined });
180
+ // validateJsonLd wraps the created loader (to record failures for
181
+ // rehydrateJsonLdCause's fallback, see validate-jsonld.ts), so toRDF
182
+ // receives a different function reference; assert delegation instead.
183
+ const passedOptions = toRDF.mock.calls[0]?.[1];
184
+ await expect(passedOptions.documentLoader('https://example.com')).resolves.toBe(remoteDoc);
185
+ expect(documentLoader).toHaveBeenCalledWith('https://example.com');
186
+ });
187
+ it('handles non-Error thrown values', async () => {
188
+ toRDF.mockRejectedValue('string error');
189
+ await expect(validateJsonLd({})).rejects.toMatchObject({
190
+ code: 'jsonld.expansion-failed',
191
+ received: 'string error',
192
+ });
193
+ });
194
+ it('every concrete error extends JsonLdValidationError', async () => {
195
+ await expect(validateJsonLd(null)).rejects.toBeInstanceOf(JsonLdValidationError);
196
+ toRDF.mockRejectedValue(new Error('x'));
197
+ await expect(validateJsonLd({})).rejects.toBeInstanceOf(JsonLdValidationError);
198
+ });
199
+ });
200
+ //# sourceMappingURL=validate-jsonld.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-jsonld.test.js","sourceRoot":"","sources":["../../src/validation/validate-jsonld.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uncefact/untp-utils",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Shared utility primitives for UNTP packages and consumers.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -9,15 +9,68 @@
9
9
  "types": "./build/index.d.ts",
10
10
  "default": "./build/index.js"
11
11
  },
12
+ "./artefacts": {
13
+ "types": "./build/artefacts/index.d.ts",
14
+ "default": "./build/artefacts/index.js"
15
+ },
12
16
  "./multibase-digest": {
13
17
  "types": "./build/multibase-digest/index.d.ts",
14
18
  "default": "./build/multibase-digest/index.js"
19
+ },
20
+ "./conformity-vocabulary": {
21
+ "types": "./build/conformity-vocabulary/index.d.ts",
22
+ "default": "./build/conformity-vocabulary/index.js"
23
+ },
24
+ "./validation": {
25
+ "types": "./build/validation/index.d.ts",
26
+ "default": "./build/validation/index.js"
27
+ },
28
+ "./loaders": {
29
+ "types": "./build/loaders/index.d.ts",
30
+ "default": "./build/loaders/index.js"
31
+ },
32
+ "./node": {
33
+ "types": "./build/node/index.d.ts",
34
+ "default": "./build/node/index.js"
35
+ },
36
+ "./cache": {
37
+ "types": "./build/cache/index.d.ts",
38
+ "default": "./build/cache/index.js"
39
+ },
40
+ "./resolvers": {
41
+ "types": "./build/resolvers/index.d.ts",
42
+ "default": "./build/resolvers/index.js"
43
+ },
44
+ "./http-headers": {
45
+ "types": "./build/http-headers/index.d.ts",
46
+ "default": "./build/http-headers/index.js"
15
47
  }
16
48
  },
17
49
  "typesVersions": {
18
50
  "*": {
19
51
  "multibase-digest": [
20
52
  "./build/multibase-digest/index.d.ts"
53
+ ],
54
+ "conformity-vocabulary": [
55
+ "./build/conformity-vocabulary/index.d.ts"
56
+ ],
57
+ "validation": [
58
+ "./build/validation/index.d.ts"
59
+ ],
60
+ "loaders": [
61
+ "./build/loaders/index.d.ts"
62
+ ],
63
+ "node": [
64
+ "./build/node/index.d.ts"
65
+ ],
66
+ "cache": [
67
+ "./build/cache/index.d.ts"
68
+ ],
69
+ "resolvers": [
70
+ "./build/resolvers/index.d.ts"
71
+ ],
72
+ "http-headers": [
73
+ "./build/http-headers/index.d.ts"
21
74
  ]
22
75
  }
23
76
  },
@@ -35,7 +88,8 @@
35
88
  "untp",
36
89
  "multibase",
37
90
  "multihash",
38
- "digest"
91
+ "digest",
92
+ "conformity-vocabulary"
39
93
  ],
40
94
  "author": "",
41
95
  "license": "Apache-2.0",
@@ -45,10 +99,17 @@
45
99
  "directory": "packages/untp-utils"
46
100
  },
47
101
  "dependencies": {
48
- "multiformats": "^13.3.1"
102
+ "ajv": "^8.17.1",
103
+ "ajv-formats": "^3.0.1",
104
+ "ipaddr.js": "^2.4.0",
105
+ "jsonld": "^8.3.3",
106
+ "multiformats": "^13.3.1",
107
+ "undici": "^6.25.0"
49
108
  },
50
109
  "devDependencies": {
110
+ "@jest/globals": "29.7.0",
51
111
  "@types/jest": "29.5.11",
112
+ "@types/jsonld": "^1.5.15",
52
113
  "cross-env": "^7.0.3",
53
114
  "jest": "29.7.0",
54
115
  "ts-jest": "29.1.1",