@vqp/core
Version:
Core VQP protocol implementation - adapter-agnostic
217 lines • 5.77 kB
JavaScript
/**
* Query Builder - Fluent interface for building VQP queries
*/
import { randomUUID } from 'node:crypto';
export class QueryBuilder {
query = {};
constructor() {
this.query = {
id: randomUUID(),
version: '1.1.0', // Updated to support response modes
timestamp: new Date().toISOString(),
};
}
/**
* Set the requester DID
*/
requester(did) {
this.query.requester = did;
return this;
}
/**
* Set the target DID (optional for broadcast queries)
*/
target(did) {
this.query.target = did;
return this;
}
/**
* Set response mode for the query
*/
responseMode(mode, config) {
this.query.responseMode = {
type: mode,
config,
};
return this;
}
/**
* Set strict response mode (default) - only returns boolean result
*/
strict() {
return this.responseMode('strict');
}
/**
* Set consensual response mode - returns actual value if consent is granted
*/
consensual(justification, consentRequired = true) {
return this.responseMode('consensual', {
justification,
consentRequired,
});
}
/**
* Set reciprocal response mode - requires mutual verification
*/
reciprocal(requesterProof, requiredClaims) {
return this.responseMode('reciprocal', {
mutualVerification: {
requesterProof,
requiredClaims,
},
});
}
/**
* Set obfuscated response mode - returns obfuscated actual value
*/
obfuscated(method, options = {}) {
return this.responseMode('obfuscated', {
obfuscation: {
method,
...options,
},
});
}
/**
* Set the vocabulary URI
*/
vocabulary(vocabUri) {
if (!this.query.query) {
this.query.query = {
lang: 'jsonlogic@1.0.0',
vocab: vocabUri,
expr: {},
};
}
else {
this.query.query.vocab = vocabUri;
}
return this;
}
/**
* Set the query expression
*/
expression(expr) {
if (!this.query.query) {
this.query.query = {
lang: 'jsonlogic@1.0.0',
vocab: '',
expr: expr,
};
}
else {
this.query.query.expr = expr;
}
return this;
}
/**
* Set a custom query ID
*/
id(queryId) {
this.query.id = queryId;
return this;
}
/**
* Set a custom timestamp
*/
timestamp(timestamp) {
this.query.timestamp = timestamp;
return this;
}
/**
* Set the query language (defaults to jsonlogic@1.0.0)
*/
language(lang) {
if (!this.query.query) {
this.query.query = {
lang: lang,
vocab: '',
expr: {},
};
}
else {
this.query.query.lang = lang;
}
return this;
}
/**
* Build the complete VQP query
*/
build() {
if (!this.query.id || !this.query.version || !this.query.timestamp || !this.query.requester) {
throw new Error('Missing required query fields: id, version, timestamp, requester');
}
if (!this.query.query || !this.query.query.vocab || !this.query.query.expr) {
throw new Error('Missing required query fields: vocab, expr');
}
return this.query;
}
/**
* Create a query with a simple field comparison
*/
static compare(requester, vocabulary, field, operator, value, target) {
const builder = new QueryBuilder()
.requester(requester)
.vocabulary(vocabulary)
.expression({
[operator]: [{ var: field }, value],
});
if (target) {
builder.target(target);
}
return builder.build();
}
/**
* Create a query with an 'and' condition
*/
static and(requester, vocabulary, conditions, target) {
const builder = new QueryBuilder().requester(requester).vocabulary(vocabulary).expression({
and: conditions,
});
if (target) {
builder.target(target);
}
return builder.build();
}
/**
* Create a query with an 'or' condition
*/
static or(requester, vocabulary, conditions, target) {
const builder = new QueryBuilder().requester(requester).vocabulary(vocabulary).expression({
or: conditions,
});
if (target) {
builder.target(target);
}
return builder.build();
}
/**
* Create a query with an 'in' condition (array membership)
*/
static in(requester, vocabulary, value, arrayField, target) {
const builder = new QueryBuilder()
.requester(requester)
.vocabulary(vocabulary)
.expression({
in: [value, { var: arrayField }],
});
if (target) {
builder.target(target);
}
return builder.build();
}
/**
* Create a query from raw JSONLogic expression
*/
static fromExpression(requester, vocabulary, expression, target) {
const builder = new QueryBuilder()
.requester(requester)
.vocabulary(vocabulary)
.expression(expression);
if (target) {
builder.target(target);
}
return builder.build();
}
}
//# sourceMappingURL=query-builder.js.map