diff --git a/package.json b/package.json index 5fedc9ef..e6b8d760 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "test:vc": "scripts/runVcTest.sh", "lint": "eslint . --ext .ts,.json --max-warnings 0", "lint:fix": "npm run lint -- --fix", + "fetch-v4-contexts": "npx ts-node scripts/fetchV4Contexts.ts", "generate-v4-fixtures": "npx ts-node scripts/generateV4JsonFixtures.ts", "generate-v4-json-schemas": "npx ts-node scripts/generateV4JsonSchemas.ts", "publish:schema": "./scripts/publishSchema.sh", diff --git a/scripts/fetchV4Contexts.ts b/scripts/fetchV4Contexts.ts new file mode 100644 index 00000000..b055a341 --- /dev/null +++ b/scripts/fetchV4Contexts.ts @@ -0,0 +1,24 @@ +import fs from "fs"; +import path from "path"; +import { ContextUrl } from "../src/4.0/context"; + +const OUTPUT_DIR = path.resolve("./src/4.0/contexts/__generated__"); + +// make sure the output directory exists +if (fs.existsSync(OUTPUT_DIR)) { + fs.rmSync(OUTPUT_DIR, { recursive: true }); +} +fs.mkdirSync(OUTPUT_DIR, { recursive: true }); + +const CONTEXTS_TO_FETCH = Object.values(ContextUrl); + +const sb: string[] = [`const contextsMap = new Map();`]; +Promise.all( + CONTEXTS_TO_FETCH.map(async (url) => { + const context = await (await fetch(url)).json(); + sb.push(`contextsMap.set("${url}", \`${JSON.stringify(context)}\`);`); + }) +).then(() => { + sb.push(`export { contextsMap };`); + fs.writeFileSync(path.join(OUTPUT_DIR, "index.ts"), sb.join("\n")); +}); diff --git a/src/4.0/context.ts b/src/4.0/context.ts index a742e598..74b4af3a 100644 --- a/src/4.0/context.ts +++ b/src/4.0/context.ts @@ -1,6 +1,6 @@ import { fetch } from "cross-fetch"; import { expand, Options, JsonLdDocument } from "jsonld"; -import { HARDCODED_CONTEXTS } from "./contexts/hardcodedContexts"; +import { contextsMap } from "./contexts/__generated__"; export const ContextUrl = { w3c_vc_v2: "https://www.w3.org/ns/credentials/v2", @@ -12,7 +12,7 @@ export const ContextType = { OAV4Context: "OpenAttestationCredential", } as const; -const contextCache: Map = new Map(); +const contextCache: Map> = new Map(); let isFirstLoad = true; // https://github.com/digitalbazaar/jsonld.js?tab=readme-ov-file#custom-document-loader @@ -21,8 +21,9 @@ const documentLoader: Options.DocLoader["documentLoader"] = async (url, _) => { // On first load: Preload hardcoded contexts so that no network call is necessary if (isFirstLoad) { isFirstLoad = false; - for (const url of Object.values(ContextUrl)) { - contextCache.set(url, HARDCODED_CONTEXTS[url]); + for (const [url, value] of contextsMap) { + const parsed = JSON.parse(value); + contextCache.set(url, parsed); } } if (contextCache.get(url)) { diff --git a/src/4.0/contexts/__generated__/index.ts b/src/4.0/contexts/__generated__/index.ts new file mode 100644 index 00000000..25980c89 --- /dev/null +++ b/src/4.0/contexts/__generated__/index.ts @@ -0,0 +1,4 @@ +const contextsMap = new Map(); +contextsMap.set("https://schemata.openattestation.com/com/openattestation/4.0/context.json", `{"@context":{"@version":1.1,"@protected":true,"schema":"https://schema.org/","oacred":"https://schemata.openattestation.com/com/openattestation/4.0/context.json#","OpenAttestationCredential":{"@id":"oacred:OpenAttestationCredential","@context":{"name":"schema:name"}},"OpenAttestationIssuer":{"@id":"oacred:OpenAttestationIssuer","@context":{"name":"schema:name","identityProof":{"@id":"oacred:identityProof","@context":{"identityProofType":"oacred:identityProofType","identifier":{"@id":"oacred:identityProofIdentifier","@type":"schema:identifier"}}}}},"OpenAttestationOcspResponder":{"@id":"oacred:credentialStatus"},"OpenAttestationEmbeddedRenderer":{"@id":"oacred:renderMethod","@context":{"templateName":"oacred:renderTemplateName"}},"OpenAttestationMerkleProofSignature2018":{"@id":"oacred:OpenAttestationMerkleProofSignature2018","@context":{"proofPurpose":"oacred:proofPurpose","targetHash":"oacred:proofTargetHash","proofs":{"@id":"oacred:proofIntermediateProofs","@container":"@list"},"merkleRoot":"oacred:proofMerkleRoot","salts":"oacred:proofSalts","privacy":{"@id":"oacred:proofPrivacy","@context":{"obfuscated":{"@id":"oacred:proofPrivacyObfuscated","@container":"@list"}}},"key":"oacred:proofKey","signature":"oacred:proofSignature"}}}}`); +contextsMap.set("https://www.w3.org/ns/credentials/v2", `{"@context":{"@protected":true,"id":"@id","type":"@type","description":"https://schema.org/description","digestMultibase":{"@id":"https://w3id.org/security#digestMultibase","@type":"https://w3id.org/security#multibase"},"digestSRI":{"@id":"https://www.w3.org/2018/credentials#digestSRI","@type":"https://www.w3.org/2018/credentials#sriString"},"mediaType":{"@id":"https://schema.org/encodingFormat"},"name":"https://schema.org/name","VerifiableCredential":{"@id":"https://www.w3.org/2018/credentials#VerifiableCredential","@context":{"@protected":true,"id":"@id","type":"@type","confidenceMethod":{"@id":"https://www.w3.org/2018/credentials#confidenceMethod","@type":"@id"},"credentialSchema":{"@id":"https://www.w3.org/2018/credentials#credentialSchema","@type":"@id"},"credentialStatus":{"@id":"https://www.w3.org/2018/credentials#credentialStatus","@type":"@id"},"credentialSubject":{"@id":"https://www.w3.org/2018/credentials#credentialSubject","@type":"@id"},"description":"https://schema.org/description","evidence":{"@id":"https://www.w3.org/2018/credentials#evidence","@type":"@id"},"issuer":{"@id":"https://www.w3.org/2018/credentials#issuer","@type":"@id"},"name":"https://schema.org/name","proof":{"@id":"https://w3id.org/security#proof","@type":"@id","@container":"@graph"},"refreshService":{"@id":"https://www.w3.org/2018/credentials#refreshService","@type":"@id"},"relatedResource":{"@id":"https://www.w3.org/2018/credentials#relatedResource","@type":"@id"},"renderMethod":{"@id":"https://www.w3.org/2018/credentials#renderMethod","@type":"@id"},"termsOfUse":{"@id":"https://www.w3.org/2018/credentials#termsOfUse","@type":"@id"},"validFrom":{"@id":"https://www.w3.org/2018/credentials#validFrom","@type":"http://www.w3.org/2001/XMLSchema#dateTime"},"validUntil":{"@id":"https://www.w3.org/2018/credentials#validUntil","@type":"http://www.w3.org/2001/XMLSchema#dateTime"}}},"EnvelopedVerifiableCredential":"https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential","VerifiablePresentation":{"@id":"https://www.w3.org/2018/credentials#VerifiablePresentation","@context":{"@protected":true,"id":"@id","type":"@type","holder":{"@id":"https://www.w3.org/2018/credentials#holder","@type":"@id"},"proof":{"@id":"https://w3id.org/security#proof","@type":"@id","@container":"@graph"},"termsOfUse":{"@id":"https://www.w3.org/2018/credentials#termsOfUse","@type":"@id"},"verifiableCredential":{"@id":"https://www.w3.org/2018/credentials#verifiableCredential","@type":"@id","@container":"@graph","@context":null}}},"EnvelopedVerifiablePresentation":"https://www.w3.org/2018/credentials#EnvelopedVerifiablePresentation","JsonSchemaCredential":"https://www.w3.org/2018/credentials#JsonSchemaCredential","JsonSchema":{"@id":"https://www.w3.org/2018/credentials#JsonSchema","@context":{"@protected":true,"id":"@id","type":"@type","jsonSchema":{"@id":"https://www.w3.org/2018/credentials#jsonSchema","@type":"@json"}}},"BitstringStatusListCredential":"https://www.w3.org/ns/credentials/status#BitstringStatusListCredential","BitstringStatusList":{"@id":"https://www.w3.org/ns/credentials/status#BitstringStatusList","@context":{"@protected":true,"id":"@id","type":"@type","encodedList":{"@id":"https://www.w3.org/ns/credentials/status#encodedList","@type":"https://w3id.org/security#multibase"},"statusMessage":{"@id":"https://www.w3.org/ns/credentials/status#statusMessage","@context":{"@protected":true,"id":"@id","type":"@type","message":"https://www.w3.org/ns/credentials/status#message","status":"https://www.w3.org/ns/credentials/status#status"}},"statusPurpose":"https://www.w3.org/ns/credentials/status#statusPurpose","statusReference":{"@id":"https://www.w3.org/ns/credentials/status#statusReference","@type":"@id"},"statusSize":{"@id":"https://www.w3.org/ns/credentials/status#statusSize","@type":"https://www.w3.org/2001/XMLSchema#positiveInteger"},"ttl":"https://www.w3.org/ns/credentials/status#ttl"}},"BitstringStatusListEntry":{"@id":"https://www.w3.org/ns/credentials/status#BitstringStatusListEntry","@context":{"@protected":true,"id":"@id","type":"@type","statusListCredential":{"@id":"https://www.w3.org/ns/credentials/status#statusListCredential","@type":"@id"},"statusListIndex":"https://www.w3.org/ns/credentials/status#statusListIndex","statusPurpose":"https://www.w3.org/ns/credentials/status#statusPurpose"}},"DataIntegrityProof":{"@id":"https://w3id.org/security#DataIntegrityProof","@context":{"@protected":true,"id":"@id","type":"@type","challenge":"https://w3id.org/security#challenge","created":{"@id":"http://purl.org/dc/terms/created","@type":"http://www.w3.org/2001/XMLSchema#dateTime"},"cryptosuite":{"@id":"https://w3id.org/security#cryptosuite","@type":"https://w3id.org/security#cryptosuiteString"},"domain":"https://w3id.org/security#domain","expires":{"@id":"https://w3id.org/security#expiration","@type":"http://www.w3.org/2001/XMLSchema#dateTime"},"nonce":"https://w3id.org/security#nonce","previousProof":{"@id":"https://w3id.org/security#previousProof","@type":"@id"},"proofPurpose":{"@id":"https://w3id.org/security#proofPurpose","@type":"@vocab","@context":{"@protected":true,"id":"@id","type":"@type","assertionMethod":{"@id":"https://w3id.org/security#assertionMethod","@type":"@id","@container":"@set"},"authentication":{"@id":"https://w3id.org/security#authenticationMethod","@type":"@id","@container":"@set"},"capabilityDelegation":{"@id":"https://w3id.org/security#capabilityDelegationMethod","@type":"@id","@container":"@set"},"capabilityInvocation":{"@id":"https://w3id.org/security#capabilityInvocationMethod","@type":"@id","@container":"@set"},"keyAgreement":{"@id":"https://w3id.org/security#keyAgreementMethod","@type":"@id","@container":"@set"}}},"proofValue":{"@id":"https://w3id.org/security#proofValue","@type":"https://w3id.org/security#multibase"},"verificationMethod":{"@id":"https://w3id.org/security#verificationMethod","@type":"@id"}}},"...":{"@id":"https://www.iana.org/assignments/jwt#..."},"_sd":{"@id":"https://www.iana.org/assignments/jwt#_sd","@type":"@json"},"_sd_alg":{"@id":"https://www.iana.org/assignments/jwt#_sd_alg"},"aud":{"@id":"https://www.iana.org/assignments/jwt#aud","@type":"@id"},"cnf":{"@id":"https://www.iana.org/assignments/jwt#cnf","@context":{"@protected":true,"kid":{"@id":"https://www.iana.org/assignments/jwt#kid","@type":"@id"},"jwk":{"@id":"https://www.iana.org/assignments/jwt#jwk","@type":"@json"}}},"exp":{"@id":"https://www.iana.org/assignments/jwt#exp","@type":"https://www.w3.org/2001/XMLSchema#nonNegativeInteger"},"iat":{"@id":"https://www.iana.org/assignments/jwt#iat","@type":"https://www.w3.org/2001/XMLSchema#nonNegativeInteger"},"iss":{"@id":"https://www.iana.org/assignments/jose#iss","@type":"@id"},"jku":{"@id":"https://www.iana.org/assignments/jose#jku","@type":"@id"},"kid":{"@id":"https://www.iana.org/assignments/jose#kid","@type":"@id"},"nbf":{"@id":"https://www.iana.org/assignments/jwt#nbf","@type":"https://www.w3.org/2001/XMLSchema#nonNegativeInteger"},"sub":{"@id":"https://www.iana.org/assignments/jose#sub","@type":"@id"},"x5u":{"@id":"https://www.iana.org/assignments/jose#x5u","@type":"@id"}}}`); +export { contextsMap }; \ No newline at end of file diff --git a/src/4.0/contexts/hardcodedContexts.ts b/src/4.0/contexts/hardcodedContexts.ts deleted file mode 100644 index 7ae2c73d..00000000 --- a/src/4.0/contexts/hardcodedContexts.ts +++ /dev/null @@ -1,368 +0,0 @@ -import { ContextUrl } from "../context"; - -export const HARDCODED_CONTEXTS: Record<(typeof ContextUrl)[keyof typeof ContextUrl], any> = { - "https://www.w3.org/ns/credentials/v2": { - "@context": { - "@protected": true, - id: "@id", - type: "@type", - description: "https://schema.org/description", - digestMultibase: { - "@id": "https://w3id.org/security#digestMultibase", - "@type": "https://w3id.org/security#multibase", - }, - digestSRI: { - "@id": "https://www.w3.org/2018/credentials#digestSRI", - "@type": "https://www.w3.org/2018/credentials#sriString", - }, - mediaType: { - "@id": "https://schema.org/encodingFormat", - }, - name: "https://schema.org/name", - VerifiableCredential: { - "@id": "https://www.w3.org/2018/credentials#VerifiableCredential", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - confidenceMethod: { - "@id": "https://www.w3.org/2018/credentials#confidenceMethod", - "@type": "@id", - }, - credentialSchema: { - "@id": "https://www.w3.org/2018/credentials#credentialSchema", - "@type": "@id", - }, - credentialStatus: { - "@id": "https://www.w3.org/2018/credentials#credentialStatus", - "@type": "@id", - }, - credentialSubject: { - "@id": "https://www.w3.org/2018/credentials#credentialSubject", - "@type": "@id", - }, - description: "https://schema.org/description", - evidence: { - "@id": "https://www.w3.org/2018/credentials#evidence", - "@type": "@id", - }, - issuer: { - "@id": "https://www.w3.org/2018/credentials#issuer", - "@type": "@id", - }, - name: "https://schema.org/name", - proof: { - "@id": "https://w3id.org/security#proof", - "@type": "@id", - "@container": "@graph", - }, - refreshService: { - "@id": "https://www.w3.org/2018/credentials#refreshService", - "@type": "@id", - }, - relatedResource: { - "@id": "https://www.w3.org/2018/credentials#relatedResource", - "@type": "@id", - }, - renderMethod: { - "@id": "https://www.w3.org/2018/credentials#renderMethod", - "@type": "@id", - }, - termsOfUse: { - "@id": "https://www.w3.org/2018/credentials#termsOfUse", - "@type": "@id", - }, - validFrom: { - "@id": "https://www.w3.org/2018/credentials#validFrom", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime", - }, - validUntil: { - "@id": "https://www.w3.org/2018/credentials#validUntil", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime", - }, - }, - }, - EnvelopedVerifiableCredential: "https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential", - VerifiablePresentation: { - "@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - holder: { - "@id": "https://www.w3.org/2018/credentials#holder", - "@type": "@id", - }, - proof: { - "@id": "https://w3id.org/security#proof", - "@type": "@id", - "@container": "@graph", - }, - termsOfUse: { - "@id": "https://www.w3.org/2018/credentials#termsOfUse", - "@type": "@id", - }, - verifiableCredential: { - "@id": "https://www.w3.org/2018/credentials#verifiableCredential", - "@type": "@id", - "@container": "@graph", - "@context": null, - }, - }, - }, - EnvelopedVerifiablePresentation: "https://www.w3.org/2018/credentials#EnvelopedVerifiablePresentation", - JsonSchemaCredential: "https://www.w3.org/2018/credentials#JsonSchemaCredential", - JsonSchema: { - "@id": "https://www.w3.org/2018/credentials#JsonSchema", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - jsonSchema: { - "@id": "https://www.w3.org/2018/credentials#jsonSchema", - "@type": "@json", - }, - }, - }, - BitstringStatusListCredential: "https://www.w3.org/ns/credentials/status#BitstringStatusListCredential", - BitstringStatusList: { - "@id": "https://www.w3.org/ns/credentials/status#BitstringStatusList", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - encodedList: { - "@id": "https://www.w3.org/ns/credentials/status#encodedList", - "@type": "https://w3id.org/security#multibase", - }, - statusMessage: { - "@id": "https://www.w3.org/ns/credentials/status#statusMessage", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - message: "https://www.w3.org/ns/credentials/status#message", - status: "https://www.w3.org/ns/credentials/status#status", - }, - }, - statusPurpose: "https://www.w3.org/ns/credentials/status#statusPurpose", - statusReference: { - "@id": "https://www.w3.org/ns/credentials/status#statusReference", - "@type": "@id", - }, - statusSize: { - "@id": "https://www.w3.org/ns/credentials/status#statusSize", - "@type": "https://www.w3.org/2001/XMLSchema#positiveInteger", - }, - ttl: "https://www.w3.org/ns/credentials/status#ttl", - }, - }, - BitstringStatusListEntry: { - "@id": "https://www.w3.org/ns/credentials/status#BitstringStatusListEntry", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - statusListCredential: { - "@id": "https://www.w3.org/ns/credentials/status#statusListCredential", - "@type": "@id", - }, - statusListIndex: "https://www.w3.org/ns/credentials/status#statusListIndex", - statusPurpose: "https://www.w3.org/ns/credentials/status#statusPurpose", - }, - }, - DataIntegrityProof: { - "@id": "https://w3id.org/security#DataIntegrityProof", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - challenge: "https://w3id.org/security#challenge", - created: { - "@id": "http://purl.org/dc/terms/created", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime", - }, - cryptosuite: { - "@id": "https://w3id.org/security#cryptosuite", - "@type": "https://w3id.org/security#cryptosuiteString", - }, - domain: "https://w3id.org/security#domain", - expires: { - "@id": "https://w3id.org/security#expiration", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime", - }, - nonce: "https://w3id.org/security#nonce", - previousProof: { - "@id": "https://w3id.org/security#previousProof", - "@type": "@id", - }, - proofPurpose: { - "@id": "https://w3id.org/security#proofPurpose", - "@type": "@vocab", - "@context": { - "@protected": true, - id: "@id", - type: "@type", - assertionMethod: { - "@id": "https://w3id.org/security#assertionMethod", - "@type": "@id", - "@container": "@set", - }, - authentication: { - "@id": "https://w3id.org/security#authenticationMethod", - "@type": "@id", - "@container": "@set", - }, - capabilityDelegation: { - "@id": "https://w3id.org/security#capabilityDelegationMethod", - "@type": "@id", - "@container": "@set", - }, - capabilityInvocation: { - "@id": "https://w3id.org/security#capabilityInvocationMethod", - "@type": "@id", - "@container": "@set", - }, - keyAgreement: { - "@id": "https://w3id.org/security#keyAgreementMethod", - "@type": "@id", - "@container": "@set", - }, - }, - }, - proofValue: { - "@id": "https://w3id.org/security#proofValue", - "@type": "https://w3id.org/security#multibase", - }, - verificationMethod: { - "@id": "https://w3id.org/security#verificationMethod", - "@type": "@id", - }, - }, - }, - "...": { - "@id": "https://www.iana.org/assignments/jwt#...", - }, - _sd: { - "@id": "https://www.iana.org/assignments/jwt#_sd", - "@type": "@json", - }, - _sd_alg: { - "@id": "https://www.iana.org/assignments/jwt#_sd_alg", - }, - aud: { - "@id": "https://www.iana.org/assignments/jwt#aud", - "@type": "@id", - }, - cnf: { - "@id": "https://www.iana.org/assignments/jwt#cnf", - "@context": { - "@protected": true, - kid: { - "@id": "https://www.iana.org/assignments/jwt#kid", - "@type": "@id", - }, - jwk: { - "@id": "https://www.iana.org/assignments/jwt#jwk", - "@type": "@json", - }, - }, - }, - exp: { - "@id": "https://www.iana.org/assignments/jwt#exp", - "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger", - }, - iat: { - "@id": "https://www.iana.org/assignments/jwt#iat", - "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger", - }, - iss: { - "@id": "https://www.iana.org/assignments/jose#iss", - "@type": "@id", - }, - jku: { - "@id": "https://www.iana.org/assignments/jose#jku", - "@type": "@id", - }, - kid: { - "@id": "https://www.iana.org/assignments/jose#kid", - "@type": "@id", - }, - nbf: { - "@id": "https://www.iana.org/assignments/jwt#nbf", - "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger", - }, - sub: { - "@id": "https://www.iana.org/assignments/jose#sub", - "@type": "@id", - }, - x5u: { - "@id": "https://www.iana.org/assignments/jose#x5u", - "@type": "@id", - }, - }, - }, - "https://schemata.openattestation.com/com/openattestation/4.0/context.json": { - "@context": { - "@version": 1.1, - "@protected": true, - schema: "https://schema.org/", - oacred: "https://schemata.openattestation.com/com/openattestation/4.0/context.json#", - OpenAttestationCredential: { - "@id": "oacred:OpenAttestationCredential", - "@context": { - name: "schema:name", - }, - }, - OpenAttestationIssuer: { - "@id": "oacred:OpenAttestationIssuer", - "@context": { - name: "schema:name", - identityProof: { - "@id": "oacred:identityProof", - "@context": { - identityProofType: "oacred:identityProofType", - identifier: { - "@id": "oacred:identityProofIdentifier", - "@type": "schema:identifier", - }, - }, - }, - }, - }, - OpenAttestationOcspResponder: { - "@id": "oacred:credentialStatus", - }, - OpenAttestationEmbeddedRenderer: { - "@id": "oacred:renderMethod", - "@context": { - templateName: "oacred:renderTemplateName", - }, - }, - OpenAttestationMerkleProofSignature2018: { - "@id": "oacred:OpenAttestationMerkleProofSignature2018", - "@context": { - proofPurpose: "oacred:proofPurpose", - targetHash: "oacred:proofTargetHash", - proofs: { - "@id": "oacred:proofIntermediateProofs", - "@container": "@list", - }, - merkleRoot: "oacred:proofMerkleRoot", - salts: "oacred:proofSalts", - privacy: { - "@id": "oacred:proofPrivacy", - "@context": { - obfuscated: { - "@id": "oacred:proofPrivacyObfuscated", - "@container": "@list", - }, - }, - }, - key: "oacred:proofKey", - signature: "oacred:proofSignature", - }, - }, - }, - }, -} as const;