anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
328 lines • 12 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultContextLoader = exports.ContextLoader = void 0;
const vc2_1 = require("../types/vc2");
class SimpleCache {
constructor(maxSize = 100, ttl = 3600000) {
this.cache = new Map();
this.hits = 0;
this.misses = 0;
this.maxSize = maxSize;
this.ttl = ttl;
}
get(key) {
const entry = this.cache.get(key);
if (entry && entry.expires > Date.now()) {
this.hits++;
return entry.document;
}
if (entry) {
this.cache.delete(key);
}
this.misses++;
return undefined;
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
if (firstKey) {
this.cache.delete(firstKey);
}
}
this.cache.set(key, {
document: value,
expires: Date.now() + this.ttl
});
}
delete(key) {
this.cache.delete(key);
}
clear() {
this.cache.clear();
}
get size() {
return this.cache.size;
}
getStats() {
return {
size: this.cache.size,
hits: this.hits,
misses: this.misses
};
}
}
/**
* Built-in contexts that are always available
*/
const BUILT_IN_CONTEXTS = new Map([
[vc2_1.VC_V2_CONTEXTS.CREDENTIALS_V2, {
'@context': {
'@version': 1.1,
'@protected': true,
'id': '@id',
'type': '@type',
'VerifiableCredential': {
'@id': 'https://www.w3.org/2018/credentials#VerifiableCredential',
'@context': {
'@version': 1.1,
'@protected': true,
'id': '@id',
'type': '@type',
'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'
},
'evidence': {
'@id': 'https://www.w3.org/2018/credentials#evidence',
'@type': '@id'
},
'issuer': {
'@id': 'https://www.w3.org/2018/credentials#issuer',
'@type': '@id'
},
'refreshService': {
'@id': 'https://www.w3.org/2018/credentials#refreshService',
'@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'
},
'proof': {
'@id': 'https://w3id.org/security#proof',
'@type': '@id',
'@container': '@graph'
}
}
}
}
}],
[vc2_1.VC_V2_CONTEXTS.CREDENTIALS_V1, {
'@context': {
'@version': 1.1,
'id': '@id',
'type': '@type',
'VerifiableCredential': {
'@id': 'https://www.w3.org/2018/credentials#VerifiableCredential'
},
'VerifiablePresentation': {
'@id': 'https://www.w3.org/2018/credentials#VerifiablePresentation'
},
'credentialSubject': {
'@id': 'https://www.w3.org/2018/credentials#credentialSubject',
'@type': '@id'
},
'issuer': {
'@id': 'https://www.w3.org/2018/credentials#issuer',
'@type': '@id'
},
'issuanceDate': {
'@id': 'https://www.w3.org/2018/credentials#issuanceDate',
'@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
},
'expirationDate': {
'@id': 'https://www.w3.org/2018/credentials#expirationDate',
'@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
},
'proof': {
'@id': 'https://w3id.org/security#proof',
'@type': '@id',
'@container': '@graph'
}
}
}],
[vc2_1.VC_V2_CONTEXTS.ED25519_2020, {
'@context': {
'id': '@id',
'type': '@type',
'@protected': true,
'Ed25519Signature2020': {
'@id': 'https://w3id.org/security#Ed25519Signature2020',
'@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'
},
'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',
'proofPurpose': {
'@id': 'https://w3id.org/security#proofPurpose',
'@type': '@vocab'
},
'proofValue': {
'@id': 'https://w3id.org/security#proofValue'
},
'verificationMethod': {
'@id': 'https://w3id.org/security#verificationMethod',
'@type': '@id'
}
}
},
'Ed25519VerificationKey2020': {
'@id': 'https://w3id.org/security#Ed25519VerificationKey2020'
},
'publicKeyMultibase': {
'@id': 'https://w3id.org/security#publicKeyMultibase'
}
}
}],
[vc2_1.VC_V2_CONTEXTS.STATUS_LIST_2021, {
'@context': {
'@protected': true,
'StatusList2021Credential': {
'@id': 'https://w3id.org/vc/status-list#StatusList2021Credential'
},
'StatusList2021': {
'@id': 'https://w3id.org/vc/status-list#StatusList2021'
},
'StatusList2021Entry': {
'@id': 'https://w3id.org/vc/status-list#StatusList2021Entry',
'@context': {
'@protected': true,
'id': '@id',
'type': '@type',
'statusPurpose': {
'@id': 'https://w3id.org/vc/status-list#statusPurpose'
},
'statusListIndex': {
'@id': 'https://w3id.org/vc/status-list#statusListIndex'
},
'statusListCredential': {
'@id': 'https://w3id.org/vc/status-list#statusListCredential',
'@type': '@id'
}
}
},
'statusPurpose': {
'@id': 'https://w3id.org/vc/status-list#statusPurpose'
},
'encodedList': {
'@id': 'https://w3id.org/vc/status-list#encodedList'
}
}
}]
]);
/**
* JSON-LD Context Loader with caching
*/
class ContextLoader {
constructor(options = {}) {
this.cache = new SimpleCache(options.maxCacheSize || 100, options.cacheTTL || 3600000 // 1 hour default
);
this.customLoaders = options.customLoaders || new Map();
this.allowRemote = options.allowRemote ?? false;
// Pre-populate cache with built-in contexts
for (const [url, doc] of BUILT_IN_CONTEXTS) {
this.cache.set(url, doc);
}
}
/**
* Load a context document by URL
*/
async loadContext(url) {
// Check if it's a built-in context
const builtIn = BUILT_IN_CONTEXTS.get(url);
if (builtIn) {
return builtIn;
}
// Try to get from cache
const cached = this.cache.get(url);
if (cached) {
return cached;
}
// Fetch and cache if not found
try {
const document = await this.fetchContext(url);
this.cache.set(url, document);
return document;
}
catch (error) {
throw new Error(`Failed to load context: ${url} - ${error}`);
}
}
/**
* Fetch a context document
*/
async fetchContext(url) {
// Check custom loaders first
const customLoader = this.customLoaders.get(url);
if (customLoader) {
return await customLoader();
}
// Check if remote loading is allowed
if (!this.allowRemote) {
throw new Error(`Remote context loading disabled for: ${url}`);
}
// In a real implementation, this would fetch from the URL
// For now, we'll throw an error
throw new Error(`Remote context loading not implemented for: ${url}`);
}
/**
* Add a custom context
*/
addContext(url, document) {
this.cache.set(url, document);
}
/**
* Clear the context cache
*/
clearCache() {
this.cache.clear();
// Re-populate with built-in contexts
for (const [url, doc] of BUILT_IN_CONTEXTS) {
this.cache.set(url, doc);
}
}
/**
* Get cache statistics
*/
getCacheStats() {
return this.cache.getStats();
}
/**
* Create a document loader function for jsonld library
*/
createDocumentLoader() {
return async (url) => {
try {
const doc = await this.loadContext(url);
return {
contextUrl: null,
document: doc,
documentUrl: url
};
}
catch (error) {
throw new Error(`Error loading document ${url}: ${error}`);
}
};
}
}
exports.ContextLoader = ContextLoader;
// Default instance
exports.defaultContextLoader = new ContextLoader();
//# sourceMappingURL=context-loader.js.map