зеркало из
1
0
Форкнуть 0

Add full fhir-bundle schema; add fhir definitions file; update schema tests

This commit is contained in:
Larry Joy 2021-03-08 19:10:43 -08:00
Родитель 1c8cf8f733
Коммит 15ed7121a3
7 изменённых файлов: 3304 добавлений и 309 удалений

191
package-lock.json сгенерированный
Просмотреть файл

@ -1879,9 +1879,9 @@
}
},
"node_modules/ajv": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.0.tgz",
"integrity": "sha512-51Na3IUg3uOACsQ7hzTUCjSzGy8xROySgI8tmNJ+y9JF2hfDS6qkTP7+Ep3htUtSQG1t17QMbe+jZFTlaU4dDQ==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz",
"integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@ -2492,9 +2492,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001196",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001196.tgz",
"integrity": "sha512-CPvObjD3ovWrNBaXlAIGWmg2gQQuJ5YhuciUOjPRox6hIQttu8O+b51dx6VIpIY9ESd2d0Vac1RKpICdG4rGUg==",
"version": "1.0.30001197",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001197.tgz",
"integrity": "sha512-8aE+sqBqtXz4G8g35Eg/XEaFr2N7rd/VQ6eABGBmNtcB8cN6qNJhMi6oSFy4UWWZgqgL3filHT8Nha4meu3tsw==",
"dev": true
},
"node_modules/canonicalize": {
@ -3251,12 +3251,12 @@
}
},
"node_modules/escodegen": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
"integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
"estraverse": "^5.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1"
},
@ -3265,12 +3265,20 @@
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=4.0"
"node": ">=6.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/escodegen/node_modules/estraverse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/escodegen/node_modules/levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@ -3521,6 +3529,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
@ -4593,14 +4602,6 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
"integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
"engines": {
"node": ">=4"
}
},
"node_modules/is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
@ -5561,35 +5562,35 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"node_modules/jsdom": {
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz",
"integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==",
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.0.tgz",
"integrity": "sha512-QxZH0nmDTnTTVI0YDm4RUlaUPl5dcyn62G5TMDNfMmTW+J1u1v9gCR8WR+WZ6UghAa7nKJjDOFaI00eMMWvJFQ==",
"dependencies": {
"abab": "^2.0.3",
"acorn": "^7.1.1",
"abab": "^2.0.5",
"acorn": "^8.0.5",
"acorn-globals": "^6.0.0",
"cssom": "^0.4.4",
"cssstyle": "^2.2.0",
"cssstyle": "^2.3.0",
"data-urls": "^2.0.0",
"decimal.js": "^10.2.0",
"decimal.js": "^10.2.1",
"domexception": "^2.0.1",
"escodegen": "^1.14.1",
"escodegen": "^2.0.0",
"html-encoding-sniffer": "^2.0.1",
"is-potential-custom-element-name": "^1.0.0",
"nwsapi": "^2.2.0",
"parse5": "5.1.1",
"parse5": "6.0.1",
"request": "^2.88.2",
"request-promise-native": "^1.0.8",
"saxes": "^5.0.0",
"request-promise-native": "^1.0.9",
"saxes": "^5.0.1",
"symbol-tree": "^3.2.4",
"tough-cookie": "^3.0.1",
"tough-cookie": "^4.0.0",
"w3c-hr-time": "^1.0.2",
"w3c-xmlserializer": "^2.0.0",
"webidl-conversions": "^6.1.0",
"whatwg-encoding": "^1.0.5",
"whatwg-mimetype": "^2.3.0",
"whatwg-url": "^8.0.0",
"ws": "^7.2.3",
"ws": "^7.4.4",
"xml-name-validator": "^3.0.0"
},
"engines": {
@ -5604,6 +5605,17 @@
}
}
},
"node_modules/jsdom/node_modules/acorn": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz",
"integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@ -6611,9 +6623,9 @@
}
},
"node_modules/parse5": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/pascalcase": {
"version": "0.1.1",
@ -8617,13 +8629,13 @@
}
},
"node_modules/tough-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
"integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
"dependencies": {
"ip-regex": "^2.1.0",
"psl": "^1.1.28",
"punycode": "^2.1.1"
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.1.2"
},
"engines": {
"node": ">=6"
@ -8818,6 +8830,14 @@
"node": ">=0.10.0"
}
},
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@ -10817,9 +10837,9 @@
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA=="
},
"ajv": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.0.tgz",
"integrity": "sha512-51Na3IUg3uOACsQ7hzTUCjSzGy8xROySgI8tmNJ+y9JF2hfDS6qkTP7+Ep3htUtSQG1t17QMbe+jZFTlaU4dDQ==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz",
"integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@ -11262,9 +11282,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001196",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001196.tgz",
"integrity": "sha512-CPvObjD3ovWrNBaXlAIGWmg2gQQuJ5YhuciUOjPRox6hIQttu8O+b51dx6VIpIY9ESd2d0Vac1RKpICdG4rGUg==",
"version": "1.0.30001197",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001197.tgz",
"integrity": "sha512-8aE+sqBqtXz4G8g35Eg/XEaFr2N7rd/VQ6eABGBmNtcB8cN6qNJhMi6oSFy4UWWZgqgL3filHT8Nha4meu3tsw==",
"dev": true
},
"canonicalize": {
@ -11849,17 +11869,22 @@
"dev": true
},
"escodegen": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
"integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
"requires": {
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
"estraverse": "^5.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
},
"dependencies": {
"estraverse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ=="
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@ -12056,7 +12081,8 @@
"estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"esutils": {
"version": "2.0.3",
@ -12900,11 +12926,6 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"ip-regex": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
"integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
},
"is-accessor-descriptor": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
@ -13656,36 +13677,43 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"jsdom": {
"version": "16.4.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz",
"integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==",
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.5.0.tgz",
"integrity": "sha512-QxZH0nmDTnTTVI0YDm4RUlaUPl5dcyn62G5TMDNfMmTW+J1u1v9gCR8WR+WZ6UghAa7nKJjDOFaI00eMMWvJFQ==",
"requires": {
"abab": "^2.0.3",
"acorn": "^7.1.1",
"abab": "^2.0.5",
"acorn": "^8.0.5",
"acorn-globals": "^6.0.0",
"cssom": "^0.4.4",
"cssstyle": "^2.2.0",
"cssstyle": "^2.3.0",
"data-urls": "^2.0.0",
"decimal.js": "^10.2.0",
"decimal.js": "^10.2.1",
"domexception": "^2.0.1",
"escodegen": "^1.14.1",
"escodegen": "^2.0.0",
"html-encoding-sniffer": "^2.0.1",
"is-potential-custom-element-name": "^1.0.0",
"nwsapi": "^2.2.0",
"parse5": "5.1.1",
"parse5": "6.0.1",
"request": "^2.88.2",
"request-promise-native": "^1.0.8",
"saxes": "^5.0.0",
"request-promise-native": "^1.0.9",
"saxes": "^5.0.1",
"symbol-tree": "^3.2.4",
"tough-cookie": "^3.0.1",
"tough-cookie": "^4.0.0",
"w3c-hr-time": "^1.0.2",
"w3c-xmlserializer": "^2.0.0",
"webidl-conversions": "^6.1.0",
"whatwg-encoding": "^1.0.5",
"whatwg-mimetype": "^2.3.0",
"whatwg-url": "^8.0.0",
"ws": "^7.2.3",
"ws": "^7.4.4",
"xml-name-validator": "^3.0.0"
},
"dependencies": {
"acorn": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz",
"integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg=="
}
}
},
"jsesc": {
@ -14502,9 +14530,9 @@
}
},
"parse5": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"pascalcase": {
"version": "0.1.1",
@ -16045,13 +16073,13 @@
}
},
"tough-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
"integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
"requires": {
"ip-regex": "^2.1.0",
"psl": "^1.1.28",
"punycode": "^2.1.1"
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.1.2"
}
},
"tr46": {
@ -16185,6 +16213,11 @@
}
}
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",

Просмотреть файл

@ -1,151 +1,379 @@
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$id": "https://smarthealth.cards/schema/fhir-bundle-schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "root",
"type": "object",
"required": [
"resourceType",
"type",
"entry"
],
"additionalProperties": false,
"properties": {
"resourceType": {
"$id": "#root/resourceType",
"title": "Resourcetype",
"type": "string",
"default": "",
"examples": [
"Bundle"
],
"pattern": "^.*$"
},
"type": {
"$id": "#root/type",
"title": "Type",
"type": "string",
"default": "",
"examples": [
"collection"
],
"pattern": "^.*$"
},
"entry": {
"$id": "#root/entry",
"title": "Entry",
"type": "array",
"default": [],
"$ref": "#/definitions/Bundle",
"description": "see https://www.hl7.org/fhir/bundle.schema.json.html for information about the FHIR Json Schemas",
"definitions": {
"Bundle": {
"description": "A container for a collection of resources.",
"properties": {
"resourceType": {
"description": "This is a Bundle resource",
"const": "Bundle"
},
"id": {
"description": "The logical id of the resource, as used in the URL for the resource. Once assigned, this value never changes.",
"$ref": "fhir.schema.json#/definitions/id"
},
"meta": {
"description": "The metadata about the resource. This is content that is maintained by the infrastructure. Changes to the content might not always be associated with version changes to the resource.",
"$ref": "fhir.schema.json#/definitions/Meta"
},
"implicitRules": {
"description": "A reference to a set of rules that were followed when the resource was constructed, and which must be understood when processing the content. Often, this is a reference to an implementation guide that defines the special rules along with other profiles etc.",
"$ref": "fhir.schema.json#/definitions/uri"
},
"_implicitRules": {
"description": "Extensions for implicitRules",
"$ref": "fhir.schema.json#/definitions/Element"
},
"language": {
"description": "The base language in which the resource is written.",
"$ref": "fhir.schema.json#/definitions/code"
},
"_language": {
"description": "Extensions for language",
"$ref": "fhir.schema.json#/definitions/Element"
},
"identifier": {
"description": "A persistent identifier for the bundle that won\u0027t change as a bundle is copied from server to server.",
"$ref": "fhir.schema.json#/definitions/Identifier"
},
"type": {
"description": "Indicates the purpose of this bundle - how it is intended to be used.",
"enum": [
"document",
"message",
"transaction",
"transaction-response",
"batch",
"batch-response",
"history",
"searchset",
"collection"
]
},
"_type": {
"description": "Extensions for type",
"$ref": "fhir.schema.json#/definitions/Element"
},
"timestamp": {
"description": "The date/time that the bundle was assembled - i.e. when the resources were placed in the bundle.",
"$ref": "fhir.schema.json#/definitions/instant"
},
"_timestamp": {
"description": "Extensions for timestamp",
"$ref": "fhir.schema.json#/definitions/Element"
},
"total": {
"description": "If a set of search matches, this is the total number of entries of type \u0027match\u0027 across all pages in the search. It does not include search.mode \u003d \u0027include\u0027 or \u0027outcome\u0027 entries and it does not provide a count of the number of entries in the Bundle.",
"$ref": "fhir.schema.json#/definitions/unsignedInt"
},
"_total": {
"description": "Extensions for total",
"$ref": "fhir.schema.json#/definitions/Element"
},
"link": {
"description": "A series of links that provide context to this bundle.",
"items": {
"$id": "#root/entry/items",
"title": "Items",
"type": "object",
"required": [
"fullUrl",
"resource"
],
"properties": {
"fullUrl": {
"$id": "#root/entry/items/fullUrl",
"title": "Fullurl",
"type": "string",
"default": "",
"examples": [
"resource:0"
],
"pattern": "^.*$"
},
"resource": {
"$id": "#root/entry/items/resource",
"title": "Resource",
"type": "object",
"required": [
"resourceType"
],
"properties": {
"resourceType": {
"$id": "#root/entry/items/resource/resourceType",
"title": "Resourcetype",
"type": "string",
"default": "",
"examples": [
"Patient"
],
"pattern": "^.*$"
},
"name": {
"$id": "#root/entry/items/resource/name",
"title": "Name",
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"default": [],
"items": {
"$id": "#root/entry/items/resource/name/items",
"title": "Items",
"type": "object",
"required": [
"family",
"given"
],
"properties": {
"family": {
"$id": "#root/entry/items/resource/name/items/family",
"title": "Family",
"type": "string",
"default": "",
"examples": [
"Anyperson"
],
"pattern": "^.*$"
},
"given": {
"$id": "#root/entry/items/resource/name/items/given",
"title": "Given",
"type": "array",
"default": [],
"items": {
"$id": "#root/entry/items/resource/name/items/given/items",
"title": "Items",
"type": "string",
"default": "",
"examples": [
"John"
],
"pattern": "^.*$"
}
}
}
}
}
]
},
"gender": {
"$id": "#root/entry/items/resource/gender",
"title": "Gender",
"type": "string",
"default": "",
"examples": [
"male"
],
"pattern": "^.*$"
},
"birthDate": {
"$id": "#root/entry/items/resource/birthDate",
"title": "Birthdate",
"type": "string",
"default": "",
"examples": [
"1951-01-20"
],
"pattern": "^.*$"
}
}
}
}
}
}
"$ref": "#/definitions/Bundle_Link"
},
"type": "array"
},
"entry": {
"description": "An entry in a bundle resource - will either contain a resource or information about a resource (transactions and history only).",
"items": {
"$ref": "#/definitions/Bundle_Entry"
},
"type": "array"
},
"signature": {
"description": "Digital Signature - base64 encoded. XML-DSig or a JWT.",
"$ref": "fhir.schema.json#/definitions/Signature"
}
},
"additionalProperties": false,
"required": [
"resourceType"
]
},
"Bundle_Link": {
"description": "A container for a collection of resources.",
"properties": {
"id": {
"description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"$ref": "fhir.schema.json#/definitions/string"
},
"extension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"modifierExtension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element\u0027s descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"relation": {
"description": "A name which details the functional use for this link - see [http://www.iana.org/assignments/link-relations/link-relations.xhtml#link-relations-1](http://www.iana.org/assignments/link-relations/link-relations.xhtml#link-relations-1).",
"$ref": "fhir.schema.json#/definitions/string"
},
"_relation": {
"description": "Extensions for relation",
"$ref": "fhir.schema.json#/definitions/Element"
},
"url": {
"description": "The reference details for the link.",
"$ref": "fhir.schema.json#/definitions/uri"
},
"_url": {
"description": "Extensions for url",
"$ref": "fhir.schema.json#/definitions/Element"
}
},
"additionalProperties": false
},
"Bundle_Entry": {
"description": "A container for a collection of resources.",
"properties": {
"id": {
"description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"$ref": "fhir.schema.json#/definitions/string"
},
"extension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"modifierExtension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element\u0027s descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"link": {
"description": "A series of links that provide context to this entry.",
"items": {
"$ref": "#/definitions/Bundle_Link"
},
"type": "array"
},
"fullUrl": {
"description": "The Absolute URL for the resource. The fullUrl SHALL NOT disagree with the id in the resource - i.e. if the fullUrl is not a urn:uuid, the URL shall be version-independent URL consistent with the Resource.id. The fullUrl is a version independent reference to the resource. The fullUrl element SHALL have a value except that: \n* fullUrl can be empty on a POST (although it does not need to when specifying a temporary id for reference in the bundle)\n* Results from operations might involve resources that are not identified.",
"$ref": "fhir.schema.json#/definitions/uri"
},
"_fullUrl": {
"description": "Extensions for fullUrl",
"$ref": "fhir.schema.json#/definitions/Element"
},
"resource": {
"description": "The Resource for the entry. The purpose/meaning of the resource is determined by the Bundle.type.",
"$ref": "fhir.schema.json#/definitions/ResourceList"
},
"search": {
"description": "Information about the search process that lead to the creation of this entry.",
"$ref": "#/definitions/Bundle_Search"
},
"request": {
"description": "Additional information about how this entry should be processed as part of a transaction or batch. For history, it shows how the entry was processed to create the version contained in the entry.",
"$ref": "#/definitions/Bundle_Request"
},
"response": {
"description": "Indicates the results of processing the corresponding \u0027request\u0027 entry in the batch or transaction being responded to or what the results of an operation where when returning history.",
"$ref": "#/definitions/Bundle_Response"
}
},
"additionalProperties": false
},
"Bundle_Search": {
"description": "A container for a collection of resources.",
"properties": {
"id": {
"description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"$ref": "fhir.schema.json#/definitions/string"
},
"extension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"modifierExtension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element\u0027s descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"mode": {
"description": "Why this entry is in the result set - whether it\u0027s included as a match or because of an _include requirement, or to convey information or warning information about the search process.",
"enum": [
"match",
"include",
"outcome"
]
},
"_mode": {
"description": "Extensions for mode",
"$ref": "fhir.schema.json#/definitions/Element"
},
"score": {
"description": "When searching, the server\u0027s search ranking score for the entry.",
"$ref": "fhir.schema.json#/definitions/decimal"
},
"_score": {
"description": "Extensions for score",
"$ref": "fhir.schema.json#/definitions/Element"
}
},
"additionalProperties": false
},
"Bundle_Request": {
"description": "A container for a collection of resources.",
"properties": {
"id": {
"description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"$ref": "fhir.schema.json#/definitions/string"
},
"extension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"modifierExtension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element\u0027s descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"method": {
"description": "In a transaction or batch, this is the HTTP action to be executed for this entry. In a history bundle, this indicates the HTTP action that occurred.",
"enum": [
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"PATCH"
]
},
"_method": {
"description": "Extensions for method",
"$ref": "fhir.schema.json#/definitions/Element"
},
"url": {
"description": "The URL for this entry, relative to the root (the address to which the request is posted).",
"$ref": "fhir.schema.json#/definitions/uri"
},
"_url": {
"description": "Extensions for url",
"$ref": "fhir.schema.json#/definitions/Element"
},
"ifNoneMatch": {
"description": "If the ETag values match, return a 304 Not Modified status. See the API documentation for [\"Conditional Read\"](http.html#cread).",
"$ref": "fhir.schema.json#/definitions/string"
},
"_ifNoneMatch": {
"description": "Extensions for ifNoneMatch",
"$ref": "fhir.schema.json#/definitions/Element"
},
"ifModifiedSince": {
"description": "Only perform the operation if the last updated date matches. See the API documentation for [\"Conditional Read\"](http.html#cread).",
"$ref": "fhir.schema.json#/definitions/instant"
},
"_ifModifiedSince": {
"description": "Extensions for ifModifiedSince",
"$ref": "fhir.schema.json#/definitions/Element"
},
"ifMatch": {
"description": "Only perform the operation if the Etag value matches. For more information, see the API section [\"Managing Resource Contention\"](http.html#concurrency).",
"$ref": "fhir.schema.json#/definitions/string"
},
"_ifMatch": {
"description": "Extensions for ifMatch",
"$ref": "fhir.schema.json#/definitions/Element"
},
"ifNoneExist": {
"description": "Instruct the server not to perform the create if a specified resource already exists. For further information, see the API documentation for [\"Conditional Create\"](http.html#ccreate). This is just the query portion of the URL - what follows the \"?\" (not including the \"?\").",
"$ref": "fhir.schema.json#/definitions/string"
},
"_ifNoneExist": {
"description": "Extensions for ifNoneExist",
"$ref": "fhir.schema.json#/definitions/Element"
}
},
"additionalProperties": false
},
"Bundle_Response": {
"description": "A container for a collection of resources.",
"properties": {
"id": {
"description": "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"$ref": "fhir.schema.json#/definitions/string"
},
"extension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"modifierExtension": {
"description": "May be used to represent additional information that is not part of the basic definition of the element and that modifies the understanding of the element in which it is contained and/or the understanding of the containing element\u0027s descendants. Usually modifier elements provide negation or qualification. To make the use of extensions safe and manageable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension. Applications processing a resource are required to check for modifier extensions.\n\nModifier extensions SHALL NOT change the meaning of any elements on Resource or DomainResource (including cannot change the meaning of modifierExtension itself).",
"items": {
"$ref": "fhir.schema.json#/definitions/Extension"
},
"type": "array"
},
"status": {
"description": "The status code returned by processing this entry. The status SHALL start with a 3 digit HTTP code (e.g. 404) and may contain the standard HTTP description associated with the status code.",
"$ref": "fhir.schema.json#/definitions/string"
},
"_status": {
"description": "Extensions for status",
"$ref": "fhir.schema.json#/definitions/Element"
},
"location": {
"description": "The location header created by processing this operation, populated if the operation returns a location.",
"$ref": "fhir.schema.json#/definitions/uri"
},
"_location": {
"description": "Extensions for location",
"$ref": "fhir.schema.json#/definitions/Element"
},
"etag": {
"description": "The Etag for the resource, if the operation for the entry produced a versioned resource (see [Resource Metadata and Versioning](http.html#versioning) and [Managing Resource Contention](http.html#concurrency)).",
"$ref": "fhir.schema.json#/definitions/string"
},
"_etag": {
"description": "Extensions for etag",
"$ref": "fhir.schema.json#/definitions/Element"
},
"lastModified": {
"description": "The date/time that the resource was modified on the server.",
"$ref": "fhir.schema.json#/definitions/instant"
},
"_lastModified": {
"description": "Extensions for lastModified",
"$ref": "fhir.schema.json#/definitions/Element"
},
"outcome": {
"description": "An OperationOutcome containing hints and warnings produced as part of processing this entry in a batch or transaction.",
"$ref": "fhir.schema.json#/definitions/ResourceList"
}
},
"additionalProperties": false
}
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,5 +1,5 @@
{
"$id": "https://smarthealth.cards/schema/fhir-bundle-schema.json",
"$id": "https://smarthealth.cards/schema/keyset-schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "root",
"type": "object",
@ -9,8 +9,7 @@
"properties": {
"keys": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"minItems": 1,
"items": {
"type": "object",
"properties": {

95
src/prune-fhir-schema.ts Normal file
Просмотреть файл

@ -0,0 +1,95 @@
import fhir_schema from '../schema/fhir.schema.json';
import fhir_bundle_schema from '../schema/fhir-bundle-schema.json';
import fs from 'fs';
// Takes the full fhir schema and prunes it down to just the required Bundle definitions
const bundle_refs = getUniqueBundleReferences(fhir_bundle_schema);
let fhir_refs = getFhirReferences(fhir_schema, bundle_refs);
fhir_refs = getFhirReferences(fhir_schema, fhir_refs);
fhir_refs = getFhirReferences(fhir_schema, fhir_refs);
const allRefs = bundle_refs.concat(fhir_refs);
const newSchema = pruneFhirSchema(fhir_schema, allRefs);
fs.writeFileSync('trimmed.fhir.schema.json',JSON.stringify(newSchema, null, 4));
function pruneFhirSchema(fhirSchema: Record<string, unknown>, bundle_refs: string[]) {
const defs = fhir_schema.definitions;
for (const key in defs) {
if (Object.prototype.hasOwnProperty.call(defs, key)) {
if(bundle_refs.indexOf(key) < 0) {
delete (fhir_schema.definitions as {[key: string] : unknown})[key];
}
}
}
return fhirSchema;
}
function findChildRefs(definition: Record<string, unknown | string>): string[] {
let result: string[] = [];
for (const key in definition) {
if (Object.prototype.hasOwnProperty.call(definition, key)) {
const prop = definition[key];
if (key === '$ref') result.push(prop as string);
if (key === 'oneOf') continue;
if (prop instanceof Object) {
result = result.concat(findChildRefs(definition[key] as Record<string, unknown>));
}
}
}
return result;
}
// from a list of bundle refs, collect all the internal references to fhir-schema definitions
// a definition, refered to by a bundle ref, may reference other internal references
function getFhirReferences(fhirSchema: Record<string, unknown>, bundle_refs: string[]): string[] {
const defs = fhir_schema.definitions;
let child_refs: string[] = bundle_refs.slice();
for (const key of bundle_refs) {
if (Object.prototype.hasOwnProperty.call(defs, key)) {
const prop = (defs as Record<string, unknown>)[key];
child_refs = child_refs.concat(
findChildRefs(prop as Record<string, unknown>))
.map(ref => ref.slice(ref.lastIndexOf('/') + 1));
}
}
// remove the duplicates and trim to just the definition name
return child_refs
.filter((ref, index) => child_refs.indexOf(ref) === index);
}
// returns unique external references to fhir-schema definitions
function getUniqueBundleReferences(bundleSchema: unknown): string[] {
const fhirBundleSchemaText = JSON.stringify(bundleSchema);
let references = fhirBundleSchemaText.match(/"\$ref":"fhir\.schema\.json#\/definitions\/(.+?)"/g);
if (!references) throw new Error('No refereneces found');
// remove the duplicates and trim to just the definition name
references = references
.filter((ref, index) => references!.indexOf(ref) === index)
.map(ref => ref.slice(ref.lastIndexOf('/') + 1, ref.length - 1));
return Array.from(references) as unknown as string[];
}

Просмотреть файл

@ -5,63 +5,23 @@ import fs from 'fs';
import path from 'path';
import Log from './logger';
import { ErrorCode } from './error';
import metaSchema from 'ajv/lib/refs/json-schema-draft-06.json';
import fhirSchema from '../schema/fhir-definitions-schema.json';
import Ajv, { AnySchemaObject } from "ajv";
// http://json-schema.org/
// https://github.com/ajv-validator/ajv
import JsonValidator, { AnySchemaObject } from "ajv";
export async function validateFromFile(schemaPath: string, data: FhirBundle | JWS | JWSPayload | HealthCard, log: Log): Promise<boolean> {
if (!fs.existsSync(schemaPath)) {
log.fatal('Schema file not found : ' + schemaPath, ErrorCode.SCHEMA_ERROR);
return false;
}
const schemaDir = path.basename(path.dirname(schemaPath));
// for each $ref in our schema, load the schema file into an object and return it.
const jsonValidator = new JsonValidator({
allErrors: true,
loadSchema: (uri) => {
const schemaFile: string = uri.slice(uri.lastIndexOf('/'));
const schemaFullPath = path.join(schemaDir, schemaFile);
const schema = JSON.parse(fs.readFileSync(schemaFullPath, 'utf8')) as AnySchemaObject;
return Promise.resolve(schema);
}
});
const schemaObj = JSON.parse(fs.readFileSync(schemaPath, 'utf8')) as AnySchemaObject;
return jsonValidator.compileAsync(schemaObj)
.then(validate => {
if (validate(data)) { return true; }
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
validate.errors!.forEach(ve => {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
log.error('Schema: ' + ve.schemaPath + ' \'' + ve.message + '\'', ErrorCode.SCHEMA_ERROR);
});
return false;
})
.catch(err => {
// TODO: get to this catch in test
log.error('Schema: ' + (err as Error).message, ErrorCode.SCHEMA_ERROR);
return false;
});
}
export function validateSchema(schema: AnySchemaObject, data: FhirBundle | JWS | JWSPayload | HealthCard, log: Log): boolean {
export function validateSchema(schema: AnySchemaObject | AnySchemaObject[], data: FhirBundle | JWS | JWSPayload | HealthCard, log: Log): boolean {
// by default, the validator will stop at the first failure. 'allErrors' allows it to keep going.
const jsonValidator = new JsonValidator({ allErrors: true });
const ajv = new Ajv({ allErrors: true, strict: false });
ajv.addMetaSchema(metaSchema); // required for avj 7 to support json-schema draft-06 (draft-07 is current)
try {
// TODO: make this fail in test
const validate = jsonValidator.compile(schema);
const validate = ajv.addSchema(fhirSchema).compile(schema);
if (validate(data)) { return true; }

Просмотреть файл

@ -1,15 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { AnySchemaObject } from 'ajv';
import fs from 'fs';
import path from 'path';
import Log, { LogLevels } from '../src/logger';
import { validateFromFile } from '../src/schema';
import Log from '../src/logger';
import { validateSchema } from '../src/schema';
const schemaDir = './schema';
const exampleDir = './testdata';
// Map our schema files to the examples. The tests below can lookup
// the appropriate schema with the 'lookup' function
const schemaMappings: { [key: string]: string[] } = {
@ -43,45 +45,39 @@ const lookup = function (example: string): string {
throw new Error('Example not found : ' + example);
};
const examples: string[] = [
'issuer.jwks.public.json',
'example-00-a-fhirBundle.json',
'example-00-b-jws-payload-expanded.json',
'example-00-c-jws-payload-minified.json',
'example-00-d-jws.txt',
'example-00-e-file.smart-health-card',
'example-01-a-fhirBundle.json',
'example-01-b-jws-payload-expanded.json',
'example-01-c-jws-payload-minified.json',
'example-01-d-jws.txt',
'example-01-e-file.smart-health-card'
];
const log = new Log('Schema Tests');
examples.forEach(exampleName => {
testSchema(exampleName);
});
function testSchema(exampleFile: string): void {
// TODO: the next logical step would be to read each example file out of the examples directory
// and determine the appropriate schema and then build a test.
// this would require code that can determine schema by analysing the example.
function testSchema(exampleFile: string): boolean {
const schemaName = lookup(exampleFile);
const schemaPath = path.resolve(schemaDir, schemaName + ".json");
const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8')) as AnySchemaObject;
const examplePath = path.resolve(exampleDir, exampleFile);
const fileData = fs.readFileSync(examplePath, 'utf-8');
const ext = path.extname(examplePath);
const dataObj = ext !== '.txt' ? JSON.parse(fileData) as FhirBundle | JWS | JWSPayload | HealthCard : fileData;
const log = new Log('testSchema');
test("Schema: " + schemaName + " " + exampleFile, async () => {
const result = await validateFromFile(schemaPath, dataObj, log);
expect(result).toBe(true);
expect(log.flatten(LogLevels.WARNING).length).toBe(0);
});
const result = validateSchema(schema, dataObj, log);
return;
}
expect(result).toBe(true);
return result;
}
test("Schema: valid 00-a-fhirBundle", () => { testSchema('example-00-a-fhirBundle.json'); });
test("Schema: valid 00-b-jws-payload-expanded", () => { testSchema('example-00-b-jws-payload-expanded.json'); });
test("Schema: valid 00-c-jws-payload-minified", () => { testSchema('example-00-c-jws-payload-minified.json'); });
test("Schema: valid 00-d-jws", () => { testSchema('example-00-d-jws.txt'); });
test("Schema: valid 00-e-file.smart-health-card", () => { testSchema('example-00-e-file.smart-health-card'); });
test("Schema: valid issuer.jwks.public", () => { testSchema('issuer.jwks.public.json'); });
test("Schema: valid 01-a-fhirBundle", () => { testSchema('example-01-a-fhirBundle.json'); });
test("Schema: valid 01-b-jws-payload-expanded", () => { testSchema('example-01-b-jws-payload-expanded.json'); });
test("Schema: valid 01-c-jws-payload-minified", () => { testSchema('example-01-c-jws-payload-minified.json'); });
test("Schema: valid 01-d-jws", () => { testSchema('example-01-d-jws.txt'); });
test("Schema: valid 01-e-file.smart-health-card", () => { testSchema('example-01-e-file.smart-health-card'); });