@uncefact/untp-utils 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -2
- package/artefacts/context/untp/0.6.0/dcc.json +1241 -0
- package/artefacts/context/untp/0.6.0/dfr.json +619 -0
- package/artefacts/context/untp/0.6.0/dia.json +162 -0
- package/artefacts/context/untp/0.6.0/dpp.json +1078 -0
- package/artefacts/context/untp/0.6.0/dte.json +1285 -0
- package/artefacts/context/untp/0.6.1/dcc.json +1388 -0
- package/artefacts/context/untp/0.6.1/dfr.json +690 -0
- package/artefacts/context/untp/0.6.1/dia.json +196 -0
- package/artefacts/context/untp/0.6.1/dpp.json +1164 -0
- package/artefacts/context/untp/0.6.1/dte.json +1340 -0
- package/artefacts/context/untp/0.7.0/untp.json +3493 -0
- package/artefacts/context/vcdm/2/credentials.json +301 -0
- package/artefacts/manifest.json +214 -0
- package/artefacts/schema/untp/0.6.0/dcc.json +1131 -0
- package/artefacts/schema/untp/0.6.0/dfr.json +1028 -0
- package/artefacts/schema/untp/0.6.0/dia.json +236 -0
- package/artefacts/schema/untp/0.6.0/dpp.json +1219 -0
- package/artefacts/schema/untp/0.6.0/dte.json +845 -0
- package/artefacts/schema/untp/0.6.1/dcc.json +1196 -0
- package/artefacts/schema/untp/0.6.1/dfr.json +1037 -0
- package/artefacts/schema/untp/0.6.1/dia.json +236 -0
- package/artefacts/schema/untp/0.6.1/dpp.json +1229 -0
- package/artefacts/schema/untp/0.6.1/dte.json +845 -0
- package/artefacts/schema/untp/0.7.0/cvc.json +701 -0
- package/artefacts/schema/untp/0.7.0/dcc.json +1133 -0
- package/artefacts/schema/untp/0.7.0/dfr.json +1245 -0
- package/artefacts/schema/untp/0.7.0/dia.json +443 -0
- package/artefacts/schema/untp/0.7.0/dpp.json +1300 -0
- package/artefacts/schema/untp/0.7.0/dte.json +1226 -0
- package/artefacts/schema/untp/0.7.0/linkset.json +119 -0
- package/artefacts/schema/vcdm/2/verifiable-credential.json +318 -0
- package/build/artefacts/detect-version-from-context.d.ts +46 -0
- package/build/artefacts/detect-version-from-context.js +77 -0
- package/build/artefacts/detect-version-from-context.js.map +1 -0
- package/build/artefacts/detect-version-from-context.test.d.ts +1 -0
- package/build/artefacts/detect-version-from-context.test.js +69 -0
- package/build/artefacts/detect-version-from-context.test.js.map +1 -0
- package/build/artefacts/index.d.ts +3 -0
- package/build/artefacts/index.js +4 -0
- package/build/artefacts/index.js.map +1 -0
- package/build/artefacts/urls.d.ts +85 -0
- package/build/artefacts/urls.js +141 -0
- package/build/artefacts/urls.js.map +1 -0
- package/build/artefacts/urls.test.d.ts +1 -0
- package/build/artefacts/urls.test.js +99 -0
- package/build/artefacts/urls.test.js.map +1 -0
- package/build/artefacts/version.d.ts +9 -0
- package/build/artefacts/version.js +17 -0
- package/build/artefacts/version.js.map +1 -0
- package/build/artefacts/version.test.d.ts +1 -0
- package/build/artefacts/version.test.js +16 -0
- package/build/artefacts/version.test.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dcc.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dcc.js +1244 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dcc.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dfr.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dfr.js +622 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dfr.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dia.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dia.js +165 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dia.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dpp.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dpp.js +1081 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dpp.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dte.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dte.js +1288 -0
- package/build/bundle/artefacts/context/untp/0.6.0/dte.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dcc.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dcc.js +1391 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dcc.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dfr.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dfr.js +693 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dfr.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dia.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dia.js +199 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dia.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dpp.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dpp.js +1167 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dpp.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dte.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dte.js +1343 -0
- package/build/bundle/artefacts/context/untp/0.6.1/dte.js.map +1 -0
- package/build/bundle/artefacts/context/untp/0.7.0/untp.d.ts +2 -0
- package/build/bundle/artefacts/context/untp/0.7.0/untp.js +3496 -0
- package/build/bundle/artefacts/context/untp/0.7.0/untp.js.map +1 -0
- package/build/bundle/artefacts/context/vcdm/2/credentials.d.ts +2 -0
- package/build/bundle/artefacts/context/vcdm/2/credentials.js +304 -0
- package/build/bundle/artefacts/context/vcdm/2/credentials.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dcc.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dcc.js +1134 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dcc.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dfr.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dfr.js +1031 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dfr.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dia.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dia.js +239 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dia.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dpp.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dpp.js +1222 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dpp.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dte.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dte.js +848 -0
- package/build/bundle/artefacts/schema/untp/0.6.0/dte.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dcc.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dcc.js +1199 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dcc.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dfr.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dfr.js +1040 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dfr.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dia.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dia.js +239 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dia.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dpp.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dpp.js +1232 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dpp.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dte.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dte.js +848 -0
- package/build/bundle/artefacts/schema/untp/0.6.1/dte.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/cvc.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/cvc.js +704 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/cvc.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dcc.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dcc.js +1136 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dcc.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dfr.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dfr.js +1248 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dfr.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dia.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dia.js +446 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dia.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dpp.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dpp.js +1303 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dpp.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dte.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dte.js +1229 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/dte.js.map +1 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/linkset.d.ts +2 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/linkset.js +122 -0
- package/build/bundle/artefacts/schema/untp/0.7.0/linkset.js.map +1 -0
- package/build/bundle/artefacts/schema/vcdm/2/verifiable-credential.d.ts +2 -0
- package/build/bundle/artefacts/schema/vcdm/2/verifiable-credential.js +321 -0
- package/build/bundle/artefacts/schema/vcdm/2/verifiable-credential.js.map +1 -0
- package/build/bundle/fallback.d.ts +41 -0
- package/build/bundle/fallback.js +62 -0
- package/build/bundle/fallback.js.map +1 -0
- package/build/bundle/fallback.test.d.ts +1 -0
- package/build/bundle/fallback.test.js +124 -0
- package/build/bundle/fallback.test.js.map +1 -0
- package/build/bundle/index.d.ts +4 -0
- package/build/bundle/index.js +77 -0
- package/build/bundle/index.js.map +1 -0
- package/build/bundle/lookup.d.ts +14 -0
- package/build/bundle/lookup.js +40 -0
- package/build/bundle/lookup.js.map +1 -0
- package/build/bundle/lookup.test.d.ts +1 -0
- package/build/bundle/lookup.test.js +70 -0
- package/build/bundle/lookup.test.js.map +1 -0
- package/build/bundle/public.d.ts +25 -0
- package/build/bundle/public.js +56 -0
- package/build/bundle/public.js.map +1 -0
- package/build/bundle/public.test.d.ts +1 -0
- package/build/bundle/public.test.js +35 -0
- package/build/bundle/public.test.js.map +1 -0
- package/build/bundle/refresh-classify.test.d.ts +1 -0
- package/build/bundle/refresh-classify.test.js +20 -0
- package/build/bundle/refresh-classify.test.js.map +1 -0
- package/build/bundle/refresh-main.test.d.ts +1 -0
- package/build/bundle/refresh-main.test.js +98 -0
- package/build/bundle/refresh-main.test.js.map +1 -0
- package/build/cache/in-memory-ttl-cache.d.ts +2 -0
- package/build/cache/in-memory-ttl-cache.js +76 -0
- package/build/cache/in-memory-ttl-cache.js.map +1 -0
- package/build/cache/in-memory-ttl-cache.test.d.ts +1 -0
- package/build/cache/in-memory-ttl-cache.test.js +236 -0
- package/build/cache/in-memory-ttl-cache.test.js.map +1 -0
- package/build/cache/index.d.ts +2 -0
- package/build/cache/index.js +2 -0
- package/build/cache/index.js.map +1 -0
- package/build/cache/ttl-cache.d.ts +22 -0
- package/build/cache/ttl-cache.js +2 -0
- package/build/cache/ttl-cache.js.map +1 -0
- package/build/common/as-date-time.d.ts +13 -0
- package/build/common/as-date-time.js +44 -0
- package/build/common/as-date-time.js.map +1 -0
- package/build/common/as-date-time.test.d.ts +1 -0
- package/build/common/as-date-time.test.js +42 -0
- package/build/common/as-date-time.test.js.map +1 -0
- package/build/common/as-non-empty-string.d.ts +14 -0
- package/build/common/as-non-empty-string.js +20 -0
- package/build/common/as-non-empty-string.js.map +1 -0
- package/build/common/as-non-empty-string.test.d.ts +1 -0
- package/build/common/as-non-empty-string.test.js +30 -0
- package/build/common/as-non-empty-string.test.js.map +1 -0
- package/build/common/index.d.ts +4 -0
- package/build/common/index.js +5 -0
- package/build/common/index.js.map +1 -0
- package/build/common/require-string.d.ts +12 -0
- package/build/common/require-string.js +27 -0
- package/build/common/require-string.js.map +1 -0
- package/build/common/require-string.test.d.ts +1 -0
- package/build/common/require-string.test.js +53 -0
- package/build/common/require-string.test.js.map +1 -0
- package/build/common/validity-window.d.ts +45 -0
- package/build/common/validity-window.js +68 -0
- package/build/common/validity-window.js.map +1 -0
- package/build/common/validity-window.test.d.ts +1 -0
- package/build/common/validity-window.test.js +67 -0
- package/build/common/validity-window.test.js.map +1 -0
- package/build/conformity-vocabulary/codes.d.ts +10 -0
- package/build/conformity-vocabulary/codes.js +10 -0
- package/build/conformity-vocabulary/codes.js.map +1 -0
- package/build/conformity-vocabulary/errors.d.ts +44 -0
- package/build/conformity-vocabulary/errors.js +68 -0
- package/build/conformity-vocabulary/errors.js.map +1 -0
- package/build/conformity-vocabulary/index.d.ts +6 -0
- package/build/conformity-vocabulary/index.js +7 -0
- package/build/conformity-vocabulary/index.js.map +1 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.d.ts +26 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.js +106 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.js.map +1 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.test.d.ts +1 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.test.js +327 -0
- package/build/conformity-vocabulary/parse-conformity-catalogue.test.js.map +1 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.d.ts +28 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.js +47 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.js.map +1 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.test.d.ts +1 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.test.js +284 -0
- package/build/conformity-vocabulary/parse-conformity-scheme.test.js.map +1 -0
- package/build/conformity-vocabulary/parsers/v0-7-0.parser.d.ts +19 -0
- package/build/conformity-vocabulary/parsers/v0-7-0.parser.js +219 -0
- package/build/conformity-vocabulary/parsers/v0-7-0.parser.js.map +1 -0
- package/build/conformity-vocabulary/types.d.ts +180 -0
- package/build/conformity-vocabulary/types.js +2 -0
- package/build/conformity-vocabulary/types.js.map +1 -0
- package/build/conformity-vocabulary/validate-conformity-claim.d.ts +26 -0
- package/build/conformity-vocabulary/validate-conformity-claim.js +165 -0
- package/build/conformity-vocabulary/validate-conformity-claim.js.map +1 -0
- package/build/conformity-vocabulary/validate-conformity-claim.test.d.ts +1 -0
- package/build/conformity-vocabulary/validate-conformity-claim.test.js +478 -0
- package/build/conformity-vocabulary/validate-conformity-claim.test.js.map +1 -0
- package/build/http-headers/index.d.ts +5 -0
- package/build/http-headers/index.js +6 -0
- package/build/http-headers/index.js.map +1 -0
- package/build/http-headers/is-safe-header-value.d.ts +10 -0
- package/build/http-headers/is-safe-header-value.js +15 -0
- package/build/http-headers/is-safe-header-value.js.map +1 -0
- package/build/http-headers/is-safe-header-value.test.d.ts +1 -0
- package/build/http-headers/is-safe-header-value.test.js +37 -0
- package/build/http-headers/is-safe-header-value.test.js.map +1 -0
- package/build/http-headers/parse-entity-tag.d.ts +9 -0
- package/build/http-headers/parse-entity-tag.js +18 -0
- package/build/http-headers/parse-entity-tag.js.map +1 -0
- package/build/http-headers/parse-entity-tag.test.d.ts +1 -0
- package/build/http-headers/parse-entity-tag.test.js +41 -0
- package/build/http-headers/parse-entity-tag.test.js.map +1 -0
- package/build/http-headers/parse-imf-date.d.ts +13 -0
- package/build/http-headers/parse-imf-date.js +23 -0
- package/build/http-headers/parse-imf-date.js.map +1 -0
- package/build/http-headers/parse-imf-date.test.d.ts +1 -0
- package/build/http-headers/parse-imf-date.test.js +31 -0
- package/build/http-headers/parse-imf-date.test.js.map +1 -0
- package/build/http-headers/parse-media-type.d.ts +8 -0
- package/build/http-headers/parse-media-type.js +21 -0
- package/build/http-headers/parse-media-type.js.map +1 -0
- package/build/http-headers/parse-media-type.test.d.ts +1 -0
- package/build/http-headers/parse-media-type.test.js +39 -0
- package/build/http-headers/parse-media-type.test.js.map +1 -0
- package/build/http-headers/user-agent.d.ts +35 -0
- package/build/http-headers/user-agent.js +45 -0
- package/build/http-headers/user-agent.js.map +1 -0
- package/build/http-headers/user-agent.test.d.ts +1 -0
- package/build/http-headers/user-agent.test.js +27 -0
- package/build/http-headers/user-agent.test.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/loaders/errors.d.ts +21 -0
- package/build/loaders/errors.js +45 -0
- package/build/loaders/errors.js.map +1 -0
- package/build/loaders/index.d.ts +5 -0
- package/build/loaders/index.js +5 -0
- package/build/loaders/index.js.map +1 -0
- package/build/loaders/jsonld-document-loader.d.ts +48 -0
- package/build/loaders/jsonld-document-loader.js +43 -0
- package/build/loaders/jsonld-document-loader.js.map +1 -0
- package/build/loaders/jsonld-document-loader.test.d.ts +1 -0
- package/build/loaders/jsonld-document-loader.test.js +111 -0
- package/build/loaders/jsonld-document-loader.test.js.map +1 -0
- package/build/loaders/schema-loader.d.ts +31 -0
- package/build/loaders/schema-loader.js +83 -0
- package/build/loaders/schema-loader.js.map +1 -0
- package/build/loaders/schema-loader.ssrf.test.d.ts +1 -0
- package/build/loaders/schema-loader.ssrf.test.js +55 -0
- package/build/loaders/schema-loader.ssrf.test.js.map +1 -0
- package/build/loaders/schema-loader.test.d.ts +1 -0
- package/build/loaders/schema-loader.test.js +217 -0
- package/build/loaders/schema-loader.test.js.map +1 -0
- package/build/multibase-digest/multibase-digest.d.ts +23 -0
- package/build/multibase-digest/multibase-digest.js +40 -0
- package/build/multibase-digest/multibase-digest.js.map +1 -1
- package/build/multibase-digest/multibase-digest.test.js +46 -0
- package/build/multibase-digest/multibase-digest.test.js.map +1 -1
- package/build/node/errors.d.ts +47 -0
- package/build/node/errors.js +86 -0
- package/build/node/errors.js.map +1 -0
- package/build/node/index.d.ts +3 -0
- package/build/node/index.js +4 -0
- package/build/node/index.js.map +1 -0
- package/build/node/is-private-ip.d.ts +45 -0
- package/build/node/is-private-ip.fail-closed.test.d.ts +1 -0
- package/build/node/is-private-ip.fail-closed.test.js +36 -0
- package/build/node/is-private-ip.fail-closed.test.js.map +1 -0
- package/build/node/is-private-ip.js +203 -0
- package/build/node/is-private-ip.js.map +1 -0
- package/build/node/is-private-ip.test.d.ts +1 -0
- package/build/node/is-private-ip.test.js +124 -0
- package/build/node/is-private-ip.test.js.map +1 -0
- package/build/node/validate-public-url.d.ts +81 -0
- package/build/node/validate-public-url.js +128 -0
- package/build/node/validate-public-url.js.map +1 -0
- package/build/node/validate-public-url.test.d.ts +1 -0
- package/build/node/validate-public-url.test.js +324 -0
- package/build/node/validate-public-url.test.js.map +1 -0
- package/build/resolvers/errors.d.ts +73 -0
- package/build/resolvers/errors.js +133 -0
- package/build/resolvers/errors.js.map +1 -0
- package/build/resolvers/index.d.ts +5 -0
- package/build/resolvers/index.js +6 -0
- package/build/resolvers/index.js.map +1 -0
- package/build/resolvers/resolve-document-if-changed.d.ts +48 -0
- package/build/resolvers/resolve-document-if-changed.js +42 -0
- package/build/resolvers/resolve-document-if-changed.js.map +1 -0
- package/build/resolvers/resolve-document-if-changed.test.d.ts +1 -0
- package/build/resolvers/resolve-document-if-changed.test.js +116 -0
- package/build/resolvers/resolve-document-if-changed.test.js.map +1 -0
- package/build/resolvers/resolve-document.d.ts +106 -0
- package/build/resolvers/resolve-document.integration.test.d.ts +1 -0
- package/build/resolvers/resolve-document.integration.test.js +108 -0
- package/build/resolvers/resolve-document.integration.test.js.map +1 -0
- package/build/resolvers/resolve-document.js +319 -0
- package/build/resolvers/resolve-document.js.map +1 -0
- package/build/resolvers/resolve-document.test.d.ts +1 -0
- package/build/resolvers/resolve-document.test.js +749 -0
- package/build/resolvers/resolve-document.test.js.map +1 -0
- package/build/resolvers/resolve-json-document.d.ts +43 -0
- package/build/resolvers/resolve-json-document.js +43 -0
- package/build/resolvers/resolve-json-document.js.map +1 -0
- package/build/resolvers/resolve-json-document.test.d.ts +1 -0
- package/build/resolvers/resolve-json-document.test.js +78 -0
- package/build/resolvers/resolve-json-document.test.js.map +1 -0
- package/build/structured-error.d.ts +49 -0
- package/build/structured-error.js +17 -0
- package/build/structured-error.js.map +1 -0
- package/build/structured-error.test.d.ts +1 -0
- package/build/structured-error.test.js +112 -0
- package/build/structured-error.test.js.map +1 -0
- package/build/validation/describe-jsonld-failure.d.ts +90 -0
- package/build/validation/describe-jsonld-failure.js +171 -0
- package/build/validation/describe-jsonld-failure.js.map +1 -0
- package/build/validation/describe-jsonld-failure.test.d.ts +1 -0
- package/build/validation/describe-jsonld-failure.test.js +226 -0
- package/build/validation/describe-jsonld-failure.test.js.map +1 -0
- package/build/validation/errors.d.ts +40 -0
- package/build/validation/errors.js +75 -0
- package/build/validation/errors.js.map +1 -0
- package/build/validation/index.d.ts +5 -0
- package/build/validation/index.js +5 -0
- package/build/validation/index.js.map +1 -0
- package/build/validation/validate-against-schemas.d.ts +22 -0
- package/build/validation/validate-against-schemas.js +65 -0
- package/build/validation/validate-against-schemas.js.map +1 -0
- package/build/validation/validate-against-schemas.test.d.ts +1 -0
- package/build/validation/validate-against-schemas.test.js +169 -0
- package/build/validation/validate-against-schemas.test.js.map +1 -0
- package/build/validation/validate-jsonld.context-cache.test.d.ts +1 -0
- package/build/validation/validate-jsonld.context-cache.test.js +32 -0
- package/build/validation/validate-jsonld.context-cache.test.js.map +1 -0
- package/build/validation/validate-jsonld.d.ts +59 -0
- package/build/validation/validate-jsonld.js +126 -0
- package/build/validation/validate-jsonld.js.map +1 -0
- package/build/validation/validate-jsonld.ssrf.test.d.ts +1 -0
- package/build/validation/validate-jsonld.ssrf.test.js +108 -0
- package/build/validation/validate-jsonld.ssrf.test.js.map +1 -0
- package/build/validation/validate-jsonld.test.d.ts +1 -0
- package/build/validation/validate-jsonld.test.js +257 -0
- package/build/validation/validate-jsonld.test.js.map +1 -0
- package/package.json +86 -5
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ResolverNetworkError } from '../resolvers/errors.js';
|
|
2
|
+
import { ResolutionFailedError } from '../node/errors.js';
|
|
3
|
+
import { createInMemoryTtlCache } from '../cache/in-memory-ttl-cache.js';
|
|
4
|
+
import { jest } from '@jest/globals';
|
|
5
|
+
const resolveJsonDocument = jest.fn();
|
|
6
|
+
jest.unstable_mockModule('../resolvers/index.js', () => ({
|
|
7
|
+
resolveJsonDocument,
|
|
8
|
+
}));
|
|
9
|
+
const { createJsonLdDocumentLoader } = await import('./jsonld-document-loader.js');
|
|
10
|
+
describe('createJsonLdDocumentLoader', () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
resolveJsonDocument.mockReset();
|
|
13
|
+
});
|
|
14
|
+
it('resolves the URL through resolveJsonDocument and returns the RemoteDocument shape', async () => {
|
|
15
|
+
resolveJsonDocument.mockResolvedValue({
|
|
16
|
+
json: { '@context': { name: 'http://schema.org/name' } },
|
|
17
|
+
finalUrl: 'https://ex.test/ctx',
|
|
18
|
+
});
|
|
19
|
+
const result = await createJsonLdDocumentLoader()('https://ex.test/ctx');
|
|
20
|
+
expect(result).toEqual({
|
|
21
|
+
documentUrl: 'https://ex.test/ctx',
|
|
22
|
+
document: { '@context': { name: 'http://schema.org/name' } },
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it('requests JSON-LD via the default Accept', async () => {
|
|
26
|
+
resolveJsonDocument.mockResolvedValue({ json: {}, finalUrl: 'https://ex.test/ctx' });
|
|
27
|
+
await createJsonLdDocumentLoader()('https://ex.test/ctx');
|
|
28
|
+
expect(resolveJsonDocument).toHaveBeenCalledWith('https://ex.test/ctx', expect.objectContaining({ accept: expect.stringContaining('application/ld+json') }));
|
|
29
|
+
});
|
|
30
|
+
it('lets the caller override the Accept header', async () => {
|
|
31
|
+
resolveJsonDocument.mockResolvedValue({ json: {}, finalUrl: 'https://ex.test/ctx' });
|
|
32
|
+
await createJsonLdDocumentLoader({ accept: 'application/json' })('https://ex.test/ctx');
|
|
33
|
+
expect(resolveJsonDocument).toHaveBeenCalledWith('https://ex.test/ctx', expect.objectContaining({ accept: 'application/json' }));
|
|
34
|
+
});
|
|
35
|
+
it('reports the post-redirect finalUrl as documentUrl', async () => {
|
|
36
|
+
resolveJsonDocument.mockResolvedValue({ json: {}, finalUrl: 'https://ex.test/final' });
|
|
37
|
+
const result = await createJsonLdDocumentLoader()('https://ex.test/start');
|
|
38
|
+
expect(result.documentUrl).toBe('https://ex.test/final');
|
|
39
|
+
});
|
|
40
|
+
it('forwards resolver options (e.g. allowedSchemes) to resolveJsonDocument', async () => {
|
|
41
|
+
resolveJsonDocument.mockResolvedValue({ json: {}, finalUrl: 'https://ex.test/ctx' });
|
|
42
|
+
await createJsonLdDocumentLoader({ allowedSchemes: ['https'] })('https://ex.test/ctx');
|
|
43
|
+
expect(resolveJsonDocument).toHaveBeenCalledWith('https://ex.test/ctx', expect.objectContaining({ allowedSchemes: ['https'] }));
|
|
44
|
+
});
|
|
45
|
+
it('propagates resolveJsonDocument rejections (SSRF guard, HTTP errors, bad JSON) unchanged', async () => {
|
|
46
|
+
const guardError = Object.assign(new Error('private address'), { code: 'url.private-address' });
|
|
47
|
+
resolveJsonDocument.mockRejectedValue(guardError);
|
|
48
|
+
await expect(createJsonLdDocumentLoader()('http://127.0.0.1/ctx')).rejects.toBe(guardError);
|
|
49
|
+
});
|
|
50
|
+
describe('with a cache', () => {
|
|
51
|
+
it('reuses a resolved context within the TTL instead of re-fetching', async () => {
|
|
52
|
+
resolveJsonDocument.mockResolvedValue({ json: { '@context': {} }, finalUrl: 'https://ex.test/ctx' });
|
|
53
|
+
const cache = createInMemoryTtlCache({ ttlMs: 60_000 });
|
|
54
|
+
const load = createJsonLdDocumentLoader({ cache });
|
|
55
|
+
await load('https://ex.test/ctx');
|
|
56
|
+
await load('https://ex.test/ctx');
|
|
57
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
58
|
+
});
|
|
59
|
+
it('does not cache a rejected resolution (re-checks next time)', async () => {
|
|
60
|
+
const cache = createInMemoryTtlCache({ ttlMs: 60_000 });
|
|
61
|
+
const load = createJsonLdDocumentLoader({ cache });
|
|
62
|
+
resolveJsonDocument.mockRejectedValueOnce(new Error('blocked'));
|
|
63
|
+
await expect(load('https://ex.test/ctx')).rejects.toThrow('blocked');
|
|
64
|
+
resolveJsonDocument.mockResolvedValueOnce({ json: {}, finalUrl: 'https://ex.test/ctx' });
|
|
65
|
+
await expect(load('https://ex.test/ctx')).resolves.toEqual({
|
|
66
|
+
documentUrl: 'https://ex.test/ctx',
|
|
67
|
+
document: {},
|
|
68
|
+
});
|
|
69
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('createJsonLdDocumentLoader bundled fallback', () => {
|
|
74
|
+
const CONTEXT_URL = 'https://vocabulary.uncefact.org/untp/0.7.0/context/';
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
resolveJsonDocument.mockReset();
|
|
77
|
+
});
|
|
78
|
+
it('serves the bundled context under the requested URL when its fetch fails', async () => {
|
|
79
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(CONTEXT_URL, new Error('ENOTFOUND')));
|
|
80
|
+
const onBundledFallback = jest.fn();
|
|
81
|
+
const load = createJsonLdDocumentLoader({ onBundledFallback });
|
|
82
|
+
const result = await load(CONTEXT_URL);
|
|
83
|
+
expect(result.documentUrl).toBe(CONTEXT_URL);
|
|
84
|
+
expect(Object.keys(result.document)).toContain('@context');
|
|
85
|
+
expect(onBundledFallback).toHaveBeenCalledWith({ url: CONTEXT_URL, cause: expect.any(Error) });
|
|
86
|
+
});
|
|
87
|
+
it('rethrows for a context the bundle does not carry', async () => {
|
|
88
|
+
const cause = new ResolverNetworkError('https://example.com/context.jsonld', new Error('ENOTFOUND'));
|
|
89
|
+
resolveJsonDocument.mockRejectedValue(cause);
|
|
90
|
+
const load = createJsonLdDocumentLoader();
|
|
91
|
+
await expect(load('https://example.com/context.jsonld')).rejects.toBe(cause);
|
|
92
|
+
});
|
|
93
|
+
it('serves the copy when the context host name stops resolving', async () => {
|
|
94
|
+
resolveJsonDocument.mockRejectedValue(new ResolutionFailedError('vocabulary.uncefact.org', new Error('ENOTFOUND')));
|
|
95
|
+
const result = await createJsonLdDocumentLoader()(CONTEXT_URL);
|
|
96
|
+
expect(result.documentUrl).toBe(CONTEXT_URL);
|
|
97
|
+
});
|
|
98
|
+
it('rethrows when the fallback is switched off', async () => {
|
|
99
|
+
const cause = new ResolverNetworkError(CONTEXT_URL, new Error('ENOTFOUND'));
|
|
100
|
+
resolveJsonDocument.mockRejectedValue(cause);
|
|
101
|
+
await expect(createJsonLdDocumentLoader({ bundledFallback: false })(CONTEXT_URL)).rejects.toBe(cause);
|
|
102
|
+
});
|
|
103
|
+
it('caches a bundled context so the next load does not retry the network', async () => {
|
|
104
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(CONTEXT_URL, new Error('ENOTFOUND')));
|
|
105
|
+
const load = createJsonLdDocumentLoader({ cache: createInMemoryTtlCache({ ttlMs: 60_000 }) });
|
|
106
|
+
await load(CONTEXT_URL);
|
|
107
|
+
await load(CONTEXT_URL);
|
|
108
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=jsonld-document-loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonld-document-loader.test.js","sourceRoot":"","sources":["../../src/loaders/jsonld-document-loader.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { BundledFallbackOptions } from '../bundle/fallback.js';
|
|
2
|
+
import type { TtlCache } from '../cache/ttl-cache.js';
|
|
3
|
+
/**
|
|
4
|
+
* Loads a JSON Schema document by URL. `T` declares the shape the caller
|
|
5
|
+
* expects the fetched schema to have; the loader asserts the parsed JSON to
|
|
6
|
+
* `T` without runtime validation, so a mismatch surfaces downstream (for
|
|
7
|
+
* schemas, at Ajv compile time).
|
|
8
|
+
*/
|
|
9
|
+
export interface SchemaLoader<T extends object = object> {
|
|
10
|
+
load(url: string): Promise<T>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Returns a {@link SchemaLoader} that fetches schemas over HTTP through the
|
|
14
|
+
* guarded resolver. If `cache` is supplied, results are read through the
|
|
15
|
+
* cache; otherwise every call makes a fresh network request. Failed loads
|
|
16
|
+
* are never cached; a successfully fetched and parsed document is cached
|
|
17
|
+
* even if it later fails Ajv compilation.
|
|
18
|
+
*
|
|
19
|
+
* When the host cannot deliver a bundled UNTP artefact (see
|
|
20
|
+
* `isHostDeliveryFailure`: unreachable, non-2xx, bad body, size, redirect or
|
|
21
|
+
* time bounds), the bundled copy is returned instead and
|
|
22
|
+
* `options.onBundledFallback` is told (see {@link BundledFallbackOptions}); a
|
|
23
|
+
* bundled copy served this way is cached like a fetched one. A URL the SSRF
|
|
24
|
+
* guard refused, an unexpected error, and any URL the bundle does not carry
|
|
25
|
+
* fail exactly as before.
|
|
26
|
+
*
|
|
27
|
+
* @throws {SchemaLoaderError} on `load(url)` if the underlying fetch fails
|
|
28
|
+
* and no bundled copy stands in. The concrete subclass identifies which
|
|
29
|
+
* step failed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createSchemaLoader<T extends object = object>(cache?: TtlCache<T>, options?: BundledFallbackOptions): SchemaLoader<T>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { withBundledFallback } from '../bundle/fallback.js';
|
|
2
|
+
import { ResolverHttpError, ResolverInvalidJsonError, ResolverNetworkError } from '../resolvers/errors.js';
|
|
3
|
+
import { SchemaLoaderHttpError, SchemaLoaderInvalidJsonError, SchemaLoaderNetworkError } from './errors.js';
|
|
4
|
+
const FETCH_TIMEOUT_MS = 10_000;
|
|
5
|
+
const SCHEMA_ACCEPT = 'application/schema+json, application/json;q=0.9';
|
|
6
|
+
/**
|
|
7
|
+
* Maps the guarded resolver's typed errors onto this package's public error
|
|
8
|
+
* contract. HTTP-status and invalid-JSON failures keep their dedicated types.
|
|
9
|
+
* The two failure modes that predate the guarded resolver (plain network
|
|
10
|
+
* errors and unparseable JSON) unwrap to their underlying transport / parser
|
|
11
|
+
* error, so `received` and `cause` carry the raw diagnostic exactly as they
|
|
12
|
+
* did before the resolver was introduced. Every other failure (timeout, size
|
|
13
|
+
* cap, redirect cap, SSRF / URL-validation rejections) surfaces as
|
|
14
|
+
* {@link SchemaLoaderNetworkError} with the typed resolver error preserved on
|
|
15
|
+
* `cause`, because for those the typed error is the informative diagnostic.
|
|
16
|
+
*/
|
|
17
|
+
function toSchemaLoaderError(url, cause) {
|
|
18
|
+
if (cause instanceof ResolverHttpError) {
|
|
19
|
+
return new SchemaLoaderHttpError(url, cause.status);
|
|
20
|
+
}
|
|
21
|
+
if (cause instanceof ResolverInvalidJsonError) {
|
|
22
|
+
return new SchemaLoaderInvalidJsonError(url, cause.cause ?? cause);
|
|
23
|
+
}
|
|
24
|
+
if (cause instanceof ResolverNetworkError) {
|
|
25
|
+
return new SchemaLoaderNetworkError(url, cause.cause ?? cause);
|
|
26
|
+
}
|
|
27
|
+
return new SchemaLoaderNetworkError(url, cause);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetches a schema through the guarded resolver so the URL passes the
|
|
31
|
+
* `validatePublicUrl` SSRF guard (public scheme, non-private/non-metadata
|
|
32
|
+
* address, IP-pinned) with the resolver's size, redirect, and timeout bounds
|
|
33
|
+
* applied.
|
|
34
|
+
*
|
|
35
|
+
* @throws {SchemaLoaderNetworkError} if the request rejects, times out, or fails the SSRF guard.
|
|
36
|
+
* @throws {SchemaLoaderHttpError} on a non-2xx HTTP status.
|
|
37
|
+
* @throws {SchemaLoaderInvalidJsonError} if the body is not parseable as JSON.
|
|
38
|
+
*/
|
|
39
|
+
async function fetchSchema(url, options) {
|
|
40
|
+
// Lazy import: the resolver stack pulls in undici, which jsdom test
|
|
41
|
+
// environments cannot evaluate, so it loads at fetch time to keep this
|
|
42
|
+
// module importable there.
|
|
43
|
+
const { resolveJsonDocument } = await import('../resolvers/index.js');
|
|
44
|
+
try {
|
|
45
|
+
// The fallback classifies the resolver's own error, before it is mapped
|
|
46
|
+
// to this package's public error classes, so an untyped failure inside
|
|
47
|
+
// the fetch never reads as a host outage.
|
|
48
|
+
return await withBundledFallback(url, options, async () => {
|
|
49
|
+
const { json } = await resolveJsonDocument(url, { accept: SCHEMA_ACCEPT, totalTimeoutMs: FETCH_TIMEOUT_MS });
|
|
50
|
+
return json;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (cause) {
|
|
54
|
+
throw toSchemaLoaderError(url, cause);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns a {@link SchemaLoader} that fetches schemas over HTTP through the
|
|
59
|
+
* guarded resolver. If `cache` is supplied, results are read through the
|
|
60
|
+
* cache; otherwise every call makes a fresh network request. Failed loads
|
|
61
|
+
* are never cached; a successfully fetched and parsed document is cached
|
|
62
|
+
* even if it later fails Ajv compilation.
|
|
63
|
+
*
|
|
64
|
+
* When the host cannot deliver a bundled UNTP artefact (see
|
|
65
|
+
* `isHostDeliveryFailure`: unreachable, non-2xx, bad body, size, redirect or
|
|
66
|
+
* time bounds), the bundled copy is returned instead and
|
|
67
|
+
* `options.onBundledFallback` is told (see {@link BundledFallbackOptions}); a
|
|
68
|
+
* bundled copy served this way is cached like a fetched one. A URL the SSRF
|
|
69
|
+
* guard refused, an unexpected error, and any URL the bundle does not carry
|
|
70
|
+
* fail exactly as before.
|
|
71
|
+
*
|
|
72
|
+
* @throws {SchemaLoaderError} on `load(url)` if the underlying fetch fails
|
|
73
|
+
* and no bundled copy stands in. The concrete subclass identifies which
|
|
74
|
+
* step failed.
|
|
75
|
+
*/
|
|
76
|
+
export function createSchemaLoader(cache, options) {
|
|
77
|
+
const load = (url) => fetchSchema(url, options);
|
|
78
|
+
if (!cache) {
|
|
79
|
+
return { load };
|
|
80
|
+
}
|
|
81
|
+
return { load: (url) => cache.get(url, () => load(url)) };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=schema-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.js","sourceRoot":"","sources":["../../src/loaders/schema-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC3G,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAY5G,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,aAAa,GAAG,iDAAiD,CAAC;AAExE;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,GAAW,EAAE,KAAc;IACtD,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;QACvC,OAAO,IAAI,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,KAAK,YAAY,wBAAwB,EAAE,CAAC;QAC9C,OAAO,IAAI,4BAA4B,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;QAC1C,OAAO,IAAI,wBAAwB,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,IAAI,wBAAwB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,WAAW,CAAmB,GAAW,EAAE,OAA2C;IACnG,oEAAoE;IACpE,uEAAuE;IACvE,2BAA2B;IAC3B,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;IACtE,IAAI,CAAC;QACH,wEAAwE;QACxE,uEAAuE;QACvE,0CAA0C;QAC1C,OAAO,MAAM,mBAAmB,CAAI,GAAG,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC7G,OAAO,IAAS,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAmB,EACnB,OAAgC;IAEhC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,WAAW,CAAI,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { createSchemaLoader } from './schema-loader.js';
|
|
3
|
+
import { SchemaLoaderNetworkError } from './errors.js';
|
|
4
|
+
import { UrlValidationError } from '../node/errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* End-to-end SSRF regression for schema loading. Unlike `schema-loader.test.ts`,
|
|
7
|
+
* this suite does NOT mock the resolver stack: it exercises the real
|
|
8
|
+
* `createSchemaLoader` -> `resolveJsonDocument` -> `validatePublicUrl` chain
|
|
9
|
+
* against a live loopback server standing in for an internal service.
|
|
10
|
+
*
|
|
11
|
+
* The load-bearing assertion is that the canary server is NEVER contacted. The
|
|
12
|
+
* pre-guard implementation fetched schemas with a raw `fetch` that would have
|
|
13
|
+
* reached a private URL; the guard rejects it before any connection.
|
|
14
|
+
*
|
|
15
|
+
* @see https://github.com/uncefact/tests-untp/issues/707
|
|
16
|
+
*/
|
|
17
|
+
describe('createSchemaLoader SSRF guard (real resolver stack)', () => {
|
|
18
|
+
let server;
|
|
19
|
+
let baseUrl;
|
|
20
|
+
let hits = 0;
|
|
21
|
+
beforeAll(async () => {
|
|
22
|
+
server = http.createServer((_req, res) => {
|
|
23
|
+
hits += 1;
|
|
24
|
+
res.setHeader('content-type', 'application/schema+json');
|
|
25
|
+
res.end(JSON.stringify({ $schema: 'https://json-schema.org/draft/2020-12/schema' }));
|
|
26
|
+
});
|
|
27
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
28
|
+
const address = server.address();
|
|
29
|
+
baseUrl = `http://127.0.0.1:${address.port}`;
|
|
30
|
+
});
|
|
31
|
+
afterAll(async () => {
|
|
32
|
+
await new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())));
|
|
33
|
+
});
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
hits = 0;
|
|
36
|
+
});
|
|
37
|
+
it('never contacts a private schema URL', async () => {
|
|
38
|
+
const error = await createSchemaLoader()
|
|
39
|
+
.load(`${baseUrl}/schema.json`)
|
|
40
|
+
.catch((e) => e);
|
|
41
|
+
expect(error).toBeInstanceOf(SchemaLoaderNetworkError);
|
|
42
|
+
// The rejection came from the SSRF guard, preserved on the cause chain.
|
|
43
|
+
expect(error.cause).toBeInstanceOf(UrlValidationError);
|
|
44
|
+
// The security property: the loopback canary was never reached.
|
|
45
|
+
expect(hits).toBe(0);
|
|
46
|
+
});
|
|
47
|
+
it('rejects a metadata-service schema URL literal', async () => {
|
|
48
|
+
const error = await createSchemaLoader()
|
|
49
|
+
.load('http://169.254.169.254/latest/schema.json')
|
|
50
|
+
.catch((e) => e);
|
|
51
|
+
expect(error).toBeInstanceOf(SchemaLoaderNetworkError);
|
|
52
|
+
expect(error.cause).toBeInstanceOf(UrlValidationError);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=schema-loader.ssrf.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.ssrf.test.js","sourceRoot":"","sources":["../../src/loaders/schema-loader.ssrf.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACnE,IAAI,MAAmB,CAAC;IACxB,IAAI,OAAe,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YACvC,IAAI,IAAI,CAAC,CAAC;YACV,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;YACzD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;QAC7E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAiB,CAAC;QAChD,OAAO,GAAG,oBAAoB,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,GAAG,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE;aACrC,IAAI,CAAC,GAAG,OAAO,cAAc,CAAC;aAC9B,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAE5B,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACvD,wEAAwE;QACxE,MAAM,CAAE,KAAkC,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;QACrF,gEAAgE;QAChE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE;aACrC,IAAI,CAAC,2CAA2C,CAAC;aACjD,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAE5B,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACvD,MAAM,CAAE,KAAkC,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { createInMemoryTtlCache } from '../cache/in-memory-ttl-cache.js';
|
|
3
|
+
import { ResolverHttpError, ResolverInvalidJsonError, ResolverNetworkError, ResolverTimedOutError, } from '../resolvers/errors.js';
|
|
4
|
+
import { PrivateHostnameError, ResolutionFailedError } from '../node/errors.js';
|
|
5
|
+
import { SchemaLoaderError, SchemaLoaderHttpError, SchemaLoaderInvalidJsonError, SchemaLoaderNetworkError, } from './errors.js';
|
|
6
|
+
const resolveJsonDocument = jest.fn();
|
|
7
|
+
// Mock the resolver entry point but keep the real error classes so the
|
|
8
|
+
// loader's `instanceof` mapping continues to work.
|
|
9
|
+
jest.unstable_mockModule('../resolvers/index.js', () => ({
|
|
10
|
+
resolveJsonDocument,
|
|
11
|
+
ResolverHttpError,
|
|
12
|
+
ResolverInvalidJsonError,
|
|
13
|
+
}));
|
|
14
|
+
const { createSchemaLoader } = await import('./schema-loader.js');
|
|
15
|
+
const SCHEMA_URL = 'https://example.com/schema.json';
|
|
16
|
+
function mockOk(body) {
|
|
17
|
+
resolveJsonDocument.mockResolvedValue({ json: body, finalUrl: SCHEMA_URL });
|
|
18
|
+
}
|
|
19
|
+
describe('createSchemaLoader', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
resolveJsonDocument.mockReset();
|
|
22
|
+
});
|
|
23
|
+
describe('uncached (no cache supplied)', () => {
|
|
24
|
+
it('resolves with the parsed schema body', async () => {
|
|
25
|
+
mockOk({ $schema: 'foo' });
|
|
26
|
+
await expect(createSchemaLoader().load(SCHEMA_URL)).resolves.toEqual({ $schema: 'foo' });
|
|
27
|
+
});
|
|
28
|
+
it('fetches the URL through the guarded resolver', async () => {
|
|
29
|
+
mockOk({ $schema: 'foo' });
|
|
30
|
+
await createSchemaLoader().load(SCHEMA_URL);
|
|
31
|
+
expect(resolveJsonDocument).toHaveBeenCalledWith(SCHEMA_URL, expect.objectContaining({
|
|
32
|
+
accept: expect.stringContaining('application/schema+json'),
|
|
33
|
+
totalTimeoutMs: 10_000,
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
it('fetches afresh on every call', async () => {
|
|
37
|
+
mockOk({ $schema: 'foo' });
|
|
38
|
+
const loader = createSchemaLoader();
|
|
39
|
+
await loader.load(SCHEMA_URL);
|
|
40
|
+
await loader.load(SCHEMA_URL);
|
|
41
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
|
|
42
|
+
});
|
|
43
|
+
it('types load() by the caller-declared schema shape', async () => {
|
|
44
|
+
mockOk({ $id: SCHEMA_URL });
|
|
45
|
+
const loader = createSchemaLoader();
|
|
46
|
+
const schema = await loader.load(SCHEMA_URL);
|
|
47
|
+
// The generic is a compile-time assertion only; the value is the parsed JSON.
|
|
48
|
+
expect(schema.$id).toBe(SCHEMA_URL);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('cached (cache supplied)', () => {
|
|
52
|
+
it('caches subsequent loads within the TTL', async () => {
|
|
53
|
+
mockOk({ $schema: 'foo' });
|
|
54
|
+
const loader = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
55
|
+
await loader.load(SCHEMA_URL);
|
|
56
|
+
await loader.load(SCHEMA_URL);
|
|
57
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
58
|
+
});
|
|
59
|
+
it('deduplicates concurrent loads for the same URL via the cache', async () => {
|
|
60
|
+
let resolve;
|
|
61
|
+
resolveJsonDocument.mockImplementation(() => new Promise((r) => {
|
|
62
|
+
resolve = r;
|
|
63
|
+
}));
|
|
64
|
+
const loader = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
65
|
+
const a = loader.load(SCHEMA_URL);
|
|
66
|
+
const b = loader.load(SCHEMA_URL);
|
|
67
|
+
// The loader imports the guarded resolver lazily, so the mocked fetch
|
|
68
|
+
// starts a tick after load(); wait for it before releasing the promise.
|
|
69
|
+
while (resolveJsonDocument.mock.calls.length === 0) {
|
|
70
|
+
await new Promise((r) => setImmediate(r));
|
|
71
|
+
}
|
|
72
|
+
resolve({ json: { $schema: 'foo' }, finalUrl: SCHEMA_URL });
|
|
73
|
+
await expect(a).resolves.toEqual({ $schema: 'foo' });
|
|
74
|
+
await expect(b).resolves.toEqual({ $schema: 'foo' });
|
|
75
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
76
|
+
});
|
|
77
|
+
it('two loaders with separate caches do not share state', async () => {
|
|
78
|
+
mockOk({ $schema: 'foo' });
|
|
79
|
+
const a = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
80
|
+
const b = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
81
|
+
await a.load(SCHEMA_URL);
|
|
82
|
+
await b.load(SCHEMA_URL);
|
|
83
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
|
|
84
|
+
});
|
|
85
|
+
it('clearing the cache forces the next load to re-fetch', async () => {
|
|
86
|
+
mockOk({ $schema: 'foo' });
|
|
87
|
+
const cache = createInMemoryTtlCache({ ttlMs: 60_000 });
|
|
88
|
+
const loader = createSchemaLoader(cache);
|
|
89
|
+
await loader.load(SCHEMA_URL);
|
|
90
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
91
|
+
await cache.clear();
|
|
92
|
+
await loader.load(SCHEMA_URL);
|
|
93
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('error mapping (applies to both cached and uncached paths)', () => {
|
|
97
|
+
it('maps a resolver HTTP error to SchemaLoaderHttpError with the status', async () => {
|
|
98
|
+
resolveJsonDocument.mockRejectedValue(new ResolverHttpError(SCHEMA_URL, 503));
|
|
99
|
+
const error = (await createSchemaLoader()
|
|
100
|
+
.load(SCHEMA_URL)
|
|
101
|
+
.catch((e) => e));
|
|
102
|
+
expect(error).toBeInstanceOf(SchemaLoaderHttpError);
|
|
103
|
+
expect(error.status).toBe(503);
|
|
104
|
+
});
|
|
105
|
+
it('maps a resolver invalid-JSON error to SchemaLoaderInvalidJsonError with the parser diagnostic', async () => {
|
|
106
|
+
const parserError = new Error('Unexpected token < in JSON at position 0');
|
|
107
|
+
resolveJsonDocument.mockRejectedValue(new ResolverInvalidJsonError(SCHEMA_URL, parserError));
|
|
108
|
+
const error = (await createSchemaLoader()
|
|
109
|
+
.load(SCHEMA_URL)
|
|
110
|
+
.catch((e) => e));
|
|
111
|
+
expect(error).toBeInstanceOf(SchemaLoaderInvalidJsonError);
|
|
112
|
+
expect(error.received).toBe('Unexpected token < in JSON at position 0');
|
|
113
|
+
expect(error.cause).toBe(parserError);
|
|
114
|
+
});
|
|
115
|
+
it('maps a resolver network error to SchemaLoaderNetworkError with the transport diagnostic', async () => {
|
|
116
|
+
const transportError = new Error('connection refused');
|
|
117
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(SCHEMA_URL, transportError));
|
|
118
|
+
const error = (await createSchemaLoader()
|
|
119
|
+
.load(SCHEMA_URL)
|
|
120
|
+
.catch((e) => e));
|
|
121
|
+
expect(error).toBeInstanceOf(SchemaLoaderNetworkError);
|
|
122
|
+
expect(error.received).toBe('connection refused');
|
|
123
|
+
expect(error.cause).toBe(transportError);
|
|
124
|
+
});
|
|
125
|
+
it('keeps the typed resolver error as the cause for new failure modes (timeout)', async () => {
|
|
126
|
+
const cause = new ResolverTimedOutError(SCHEMA_URL, 10_000, new Error('aborted'));
|
|
127
|
+
resolveJsonDocument.mockRejectedValue(cause);
|
|
128
|
+
const error = (await createSchemaLoader()
|
|
129
|
+
.load(SCHEMA_URL)
|
|
130
|
+
.catch((e) => e));
|
|
131
|
+
expect(error).toBeInstanceOf(SchemaLoaderNetworkError);
|
|
132
|
+
expect(error.cause).toBe(cause);
|
|
133
|
+
});
|
|
134
|
+
it('maps an SSRF / URL-validation rejection to SchemaLoaderNetworkError, preserving the cause', async () => {
|
|
135
|
+
const cause = new PrivateHostnameError('127.0.0.1');
|
|
136
|
+
resolveJsonDocument.mockRejectedValue(cause);
|
|
137
|
+
const error = (await createSchemaLoader()
|
|
138
|
+
.load(SCHEMA_URL)
|
|
139
|
+
.catch((e) => e));
|
|
140
|
+
expect(error).toBeInstanceOf(SchemaLoaderNetworkError);
|
|
141
|
+
expect(error.cause).toBe(cause);
|
|
142
|
+
});
|
|
143
|
+
it('does not cache failed loads (retries on next call)', async () => {
|
|
144
|
+
const loader = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
145
|
+
resolveJsonDocument.mockRejectedValueOnce(new ResolverHttpError(SCHEMA_URL, 503));
|
|
146
|
+
await expect(loader.load(SCHEMA_URL)).rejects.toBeInstanceOf(SchemaLoaderHttpError);
|
|
147
|
+
mockOk({ $schema: 'foo' });
|
|
148
|
+
await expect(loader.load(SCHEMA_URL)).resolves.toEqual({ $schema: 'foo' });
|
|
149
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(2);
|
|
150
|
+
});
|
|
151
|
+
it('every concrete error extends SchemaLoaderError', async () => {
|
|
152
|
+
const loader = createSchemaLoader();
|
|
153
|
+
resolveJsonDocument.mockRejectedValueOnce(new ResolverNetworkError(SCHEMA_URL, new Error('x')));
|
|
154
|
+
await expect(loader.load(SCHEMA_URL)).rejects.toBeInstanceOf(SchemaLoaderError);
|
|
155
|
+
resolveJsonDocument.mockRejectedValueOnce(new ResolverHttpError(SCHEMA_URL, 404));
|
|
156
|
+
await expect(loader.load(SCHEMA_URL)).rejects.toBeInstanceOf(SchemaLoaderError);
|
|
157
|
+
resolveJsonDocument.mockRejectedValueOnce(new ResolverInvalidJsonError(SCHEMA_URL, new Error('x')));
|
|
158
|
+
await expect(loader.load(SCHEMA_URL)).rejects.toBeInstanceOf(SchemaLoaderError);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('createSchemaLoader bundled fallback', () => {
|
|
163
|
+
const BUNDLED_URL = 'https://untp.unece.org/artefacts/schema/v0.7.0/dpp/DigitalProductPassport.json';
|
|
164
|
+
beforeEach(() => {
|
|
165
|
+
resolveJsonDocument.mockReset();
|
|
166
|
+
});
|
|
167
|
+
it('serves the bundled schema when the fetch of a bundled URL fails, and reports it', async () => {
|
|
168
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(BUNDLED_URL, new Error('ENOTFOUND')));
|
|
169
|
+
const onBundledFallback = jest.fn();
|
|
170
|
+
const loader = createSchemaLoader(undefined, { onBundledFallback });
|
|
171
|
+
const schema = await loader.load(BUNDLED_URL);
|
|
172
|
+
expect(JSON.stringify(schema)).toContain('DigitalProductPassport');
|
|
173
|
+
expect(onBundledFallback).toHaveBeenCalledTimes(1);
|
|
174
|
+
expect(onBundledFallback.mock.calls[0][0]).toMatchObject({
|
|
175
|
+
url: BUNDLED_URL,
|
|
176
|
+
cause: expect.any(ResolverNetworkError),
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it('falls back on an upstream HTTP failure too, since the artefact is immutable once published', async () => {
|
|
180
|
+
resolveJsonDocument.mockRejectedValue(new ResolverHttpError(BUNDLED_URL, 403));
|
|
181
|
+
const loader = createSchemaLoader();
|
|
182
|
+
await expect(loader.load(BUNDLED_URL)).resolves.toBeDefined();
|
|
183
|
+
});
|
|
184
|
+
it('caches a bundled copy so the next load does not retry the network', async () => {
|
|
185
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(BUNDLED_URL, new Error('ENOTFOUND')));
|
|
186
|
+
const loader = createSchemaLoader(createInMemoryTtlCache({ ttlMs: 60_000 }));
|
|
187
|
+
await loader.load(BUNDLED_URL);
|
|
188
|
+
await loader.load(BUNDLED_URL);
|
|
189
|
+
expect(resolveJsonDocument).toHaveBeenCalledTimes(1);
|
|
190
|
+
});
|
|
191
|
+
it('still fails exactly as before for a URL the bundle does not carry', async () => {
|
|
192
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(SCHEMA_URL, new Error('ENOTFOUND')));
|
|
193
|
+
const onBundledFallback = jest.fn();
|
|
194
|
+
const loader = createSchemaLoader(undefined, { onBundledFallback });
|
|
195
|
+
await expect(loader.load(SCHEMA_URL)).rejects.toBeInstanceOf(SchemaLoaderNetworkError);
|
|
196
|
+
expect(onBundledFallback).not.toHaveBeenCalled();
|
|
197
|
+
});
|
|
198
|
+
it('serves the copy when DNS resolution fails, the outage behind uncefact/tests-untp#1006', async () => {
|
|
199
|
+
resolveJsonDocument.mockRejectedValue(new ResolutionFailedError('untp.unece.org', new Error('ENOTFOUND')));
|
|
200
|
+
const loader = createSchemaLoader();
|
|
201
|
+
await expect(loader.load(BUNDLED_URL)).resolves.toBeDefined();
|
|
202
|
+
});
|
|
203
|
+
it('rethrows an untyped failure inside the fetch as a loader error instead of serving the copy', async () => {
|
|
204
|
+
const bug = new TypeError('resolver programming error');
|
|
205
|
+
resolveJsonDocument.mockRejectedValue(bug);
|
|
206
|
+
const onBundledFallback = jest.fn();
|
|
207
|
+
const loader = createSchemaLoader(undefined, { onBundledFallback });
|
|
208
|
+
await expect(loader.load(BUNDLED_URL)).rejects.toBeInstanceOf(SchemaLoaderNetworkError);
|
|
209
|
+
expect(onBundledFallback).not.toHaveBeenCalled();
|
|
210
|
+
});
|
|
211
|
+
it('can be switched off', async () => {
|
|
212
|
+
resolveJsonDocument.mockRejectedValue(new ResolverNetworkError(BUNDLED_URL, new Error('ENOTFOUND')));
|
|
213
|
+
const loader = createSchemaLoader(undefined, { bundledFallback: false });
|
|
214
|
+
await expect(loader.load(BUNDLED_URL)).rejects.toBeInstanceOf(SchemaLoaderNetworkError);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
//# sourceMappingURL=schema-loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.test.js","sourceRoot":"","sources":["../../src/loaders/schema-loader.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAErB,MAAM,mBAAmB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;AAEtC,uEAAuE;AACvE,mDAAmD;AACnD,IAAI,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC;IACvD,mBAAmB;IACnB,iBAAiB;IACjB,wBAAwB;CACzB,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAElE,MAAM,UAAU,GAAG,iCAAiC,CAAC;AAErD,SAAS,MAAM,CAAC,IAAY;IAC1B,mBAAmB,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAW,CAAC,CAAC;AACvF,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,UAAU,CAAC,GAAG,EAAE;QACd,mBAAmB,CAAC,SAAS,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,kBAAkB,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5C,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAC9C,UAAU,EACV,MAAM,CAAC,gBAAgB,CAAC;gBACtB,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,yBAAyB,CAAC;gBAC1D,cAAc,EAAE,MAAM;aACvB,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACpC,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,kBAAkB,EAAmB,CAAC;YACrD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC7C,8EAA8E;YAC9E,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YACrF,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,IAAI,OAAyD,CAAC;YAC9D,mBAAmB,CAAC,kBAAkB,CACpC,GAAG,EAAE,CACH,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBAChB,OAAO,GAAG,CAAoD,CAAC;YACjE,CAAC,CAAU,CACd,CAAC;YACF,MAAM,MAAM,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAErF,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAClC,sEAAsE;YACtE,wEAAwE;YACxE,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;YAC5D,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,CAAC,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAChF,MAAM,CAAC,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YAChF,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzB,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,KAAK,GAAG,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACzE,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;YACnF,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAU,CAAC,CAAC;YACvF,MAAM,KAAK,GAAG,CAAC,MAAM,kBAAkB,EAAE;iBACtC,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAA0B,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;YACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;YAC7G,MAAM,WAAW,GAAG,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;YAC1E,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,wBAAwB,CAAC,UAAU,EAAE,WAAW,CAAU,CAAC,CAAC;YACtG,MAAM,KAAK,GAAG,CAAC,MAAM,kBAAkB,EAAE;iBACtC,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAiC,CAAC;YAC7D,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;YACxE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;YACvG,MAAM,cAAc,GAAG,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACvD,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,UAAU,EAAE,cAAc,CAAU,CAAC,CAAC;YACrG,MAAM,KAAK,GAAG,CAAC,MAAM,kBAAkB,EAAE;iBACtC,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAA6B,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;YAC3F,MAAM,KAAK,GAAG,IAAI,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;YAClF,mBAAmB,CAAC,iBAAiB,CAAC,KAAc,CAAC,CAAC;YACtD,MAAM,KAAK,GAAG,CAAC,MAAM,kBAAkB,EAAE;iBACtC,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAA6B,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2FAA2F,EAAE,KAAK,IAAI,EAAE;YACzG,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,WAAW,CAAC,CAAC;YACpD,mBAAmB,CAAC,iBAAiB,CAAC,KAAc,CAAC,CAAC;YACtD,MAAM,KAAK,GAAG,CAAC,MAAM,kBAAkB,EAAE;iBACtC,IAAI,CAAC,UAAU,CAAC;iBAChB,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAA6B,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,MAAM,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YACrF,mBAAmB,CAAC,qBAAqB,CAAC,IAAI,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAU,CAAC,CAAC;YAC3F,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;YACpF,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3E,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACpC,mBAAmB,CAAC,qBAAqB,CAAC,IAAI,oBAAoB,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,CAAU,CAAC,CAAC;YACzG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAChF,mBAAmB,CAAC,qBAAqB,CAAC,IAAI,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAU,CAAC,CAAC;YAC3F,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAChF,mBAAmB,CAAC,qBAAqB,CAAC,IAAI,wBAAwB,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,CAAU,CAAC,CAAC;YAC7G,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,MAAM,WAAW,GAAG,gFAAgF,CAAC;IAErG,UAAU,CAAC,GAAG,EAAE;QACd,mBAAmB,CAAC,SAAS,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAU,CAAC,CAAC;QAC9G,MAAM,iBAAiB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACnE,MAAM,CAAC,iBAAiB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACvD,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC;SACxC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAC1G,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,WAAW,EAAE,GAAG,CAAU,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACpC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAU,CAAC,CAAC;QAC9G,MAAM,MAAM,GAAG,kBAAkB,CAAC,sBAAsB,CAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACrF,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/B,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/B,MAAM,CAAC,mBAAmB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,UAAU,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAU,CAAC,CAAC;QAC7G,MAAM,iBAAiB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACpE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACvF,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACrG,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,qBAAqB,CAAC,gBAAgB,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAU,CAAC,CAAC;QACpH,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACpC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAC1G,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACxD,mBAAmB,CAAC,iBAAiB,CAAC,GAAY,CAAC,CAAC;QACpD,MAAM,iBAAiB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACpE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACxF,MAAM,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,mBAAmB,CAAC,iBAAiB,CAAC,IAAI,oBAAoB,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAU,CAAC,CAAC;QAC9G,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -51,6 +51,15 @@ export declare class MultibaseDigest {
|
|
|
51
51
|
* @throws If `algorithm` or `base` is not in the allow-list.
|
|
52
52
|
*/
|
|
53
53
|
static fromData(data: Uint8Array, opts: MultibaseDigestOptions): Promise<MultibaseDigest>;
|
|
54
|
+
/**
|
|
55
|
+
* UTF-8 encodes `text` and delegates to {@link MultibaseDigest.fromData}.
|
|
56
|
+
* Convenience for the very common case of digesting a string of content
|
|
57
|
+
* (rendered template HTML, JSON-serialised credential, etc.) without
|
|
58
|
+
* hand-rolling the `TextEncoder` boilerplate at every call site.
|
|
59
|
+
*
|
|
60
|
+
* @throws If `algorithm` or `base` is not in the allow-list.
|
|
61
|
+
*/
|
|
62
|
+
static fromText(text: string, opts: MultibaseDigestOptions): Promise<MultibaseDigest>;
|
|
54
63
|
/**
|
|
55
64
|
* Wraps an already-computed raw `digest` (the bytes a hash function produces,
|
|
56
65
|
* no multihash prefix) and tags it with the requested multibase encoding. The
|
|
@@ -61,6 +70,20 @@ export declare class MultibaseDigest {
|
|
|
61
70
|
* does not match the expected size for `algorithm`.
|
|
62
71
|
*/
|
|
63
72
|
static fromDigest(digest: Uint8Array, opts: MultibaseDigestOptions): MultibaseDigest;
|
|
73
|
+
/**
|
|
74
|
+
* Wraps a hex-encoded raw `digest` and tags it with the requested multibase
|
|
75
|
+
* encoding. The caller asserts the algorithm; the decoded byte length must
|
|
76
|
+
* match its expected digest size.
|
|
77
|
+
*
|
|
78
|
+
* Provided as the canonical bridge from hex-based legacy systems (Uncefact
|
|
79
|
+
* storage's pre-migration `hash` field, RI rows still holding hex values
|
|
80
|
+
* during the multibase migration, etc.) to multibase-encoded consumers.
|
|
81
|
+
*
|
|
82
|
+
* @throws If `hex` is empty, contains non-hex characters, or has an odd
|
|
83
|
+
* number of characters, or if the decoded byte length does not match
|
|
84
|
+
* the expected size for `algorithm`.
|
|
85
|
+
*/
|
|
86
|
+
static fromHex(hex: string, opts: MultibaseDigestOptions): MultibaseDigest;
|
|
64
87
|
/**
|
|
65
88
|
* Parses a multibase string into a {@link MultibaseDigest}. The algorithm and
|
|
66
89
|
* multibase encoding are both recovered from the string itself: the leading
|