Skip to content

Commit

Permalink
feat: support custom contexts in the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
jeswr committed Sep 26, 2023
1 parent 4ceca8f commit baaef5f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
15 changes: 5 additions & 10 deletions src/common/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import type { Store, Term } from "n3";
import { DataFactory as DF } from "n3";
import { context } from "../parser/contexts";
import VcContext from "../parser/contexts/vc";
import type { ParseOptions } from "../parser/jsonld";
import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld";

export type Iri = string;
Expand Down Expand Up @@ -439,13 +440,11 @@ function validateVcResponse(response: Response, vcUrl: string): Response {
async function responseToVcStore(
response: Response,
vcUrl: UrlString,
options?: Partial<{
fetch: typeof fetch;
}>,
options?: ParseOptions,
): Promise<Store> {
try {
return await jsonLdResponseToStore(validateVcResponse(response, vcUrl), {
fetch: options?.fetch,
...options,
baseIRI: vcUrl,
});
} catch (e) {
Expand Down Expand Up @@ -787,9 +786,7 @@ export async function getVerifiableCredentialFromStore(
export async function getVerifiableCredentialFromResponse(
response: Response,
vcUrl: UrlString,
options?: Partial<{
fetch: typeof fetch;
}>,
options?: ParseOptions,
): Promise<VerifiableCredential & DatasetCore> {
const vcStore = await responseToVcStore(response, vcUrl, options);
return getVerifiableCredentialFromStore(vcStore, vcUrl);
Expand All @@ -806,9 +803,7 @@ export async function getVerifiableCredentialFromResponse(
*/
export async function getVerifiableCredential(
vcUrl: UrlString,
options?: Partial<{
fetch: typeof fetch;
}>,
options?: ParseOptions,
): Promise<VerifiableCredential & DatasetCore> {
const authFetch = options?.fetch ?? uniFetch;
const response = await authFetch(vcUrl);
Expand Down
1 change: 1 addition & 0 deletions src/lookup/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export async function query(

let data;
try {
// FIXME: Perform parsing here
data = normalizeVp(await response.json());
} catch (e) {
throw new Error(
Expand Down
36 changes: 28 additions & 8 deletions src/parser/jsonld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,24 @@ import type { JsonLd } from "../common/common";
* A JSON-LD document loader with the standard context for VCs pre-loaded
*/
class CachedFetchDocumentLoader extends FetchDocumentLoader {
private contexts: Record<string, JsonLd>;

constructor(
contexts?: Record<string, JsonLd>,
private readonly allowContextFetching = true,
...args: ConstructorParameters<typeof FetchDocumentLoader>
) {
super(...args);
this.contexts = contexts ? { ...contexts, ...CONTEXTS } : CONTEXTS;
}

public async load(url: string): Promise<IJsonLdContext> {
if (Object.keys(CONTEXTS).includes(url)) {
return CONTEXTS[url as keyof typeof CONTEXTS];
if (Object.keys(this.contexts).includes(url)) {
return this.contexts[url as keyof typeof CONTEXTS];
}
if (!this.allowContextFetching) {
throw new Error(`Unexpected context requested [${url}]`);
}
// FIXME: See if we want to error on other contexts
return super.load(url);
}
}
Expand All @@ -62,18 +75,22 @@ export function getVcContext(
]);
}

interface Options {
export interface ParseOptions {
fetch?: typeof globalThis.fetch;
baseIRI?: string;
contexts?: Record<string, JsonLd>;
allowContextFetching?: boolean;
}

/**
* Our internal JsonLd Parser with a cached VC context
*/
export class CachedJsonLdParser extends JsonLdParser {
constructor(options?: Options) {
constructor(options?: ParseOptions) {
super({
documentLoader: new CachedFetchDocumentLoader(
options?.contexts,
options?.allowContextFetching,
options?.fetch ?? defaultFetch,
),
baseIRI: options?.baseIRI,
Expand All @@ -87,7 +104,10 @@ export class CachedJsonLdParser extends JsonLdParser {
* @param options An optional fetch function for dereferencing remote contexts
* @returns A store containing the Quads in the JSON-LD response
*/
export async function jsonLdStringToStore(data: string, options?: Options) {
export async function jsonLdStringToStore(
data: string,
options?: ParseOptions,
) {
try {
const parser = new CachedJsonLdParser(options);
const store = new Store();
Expand All @@ -108,7 +128,7 @@ export async function jsonLdStringToStore(data: string, options?: Options) {
*/
export async function jsonLdResponseToStore(
response: Response,
options?: Options,
options?: ParseOptions,
): Promise<Store> {
if (response.body === null)
throw new Error("Empty response body. Expected JSON-LD.");
Expand Down Expand Up @@ -144,6 +164,6 @@ export async function jsonLdResponseToStore(
* @param options An optional fetch function for dereferencing remote contexts
* @returns A store containing the Quads in the JSON-LD response
*/
export function jsonLdToStore(data: JsonLd, options?: Options) {
export function jsonLdToStore(data: JsonLd, options?: ParseOptions) {
return jsonLdStringToStore(JSON.stringify(data), options);
}
2 changes: 2 additions & 0 deletions src/verify/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export async function isValidVc(
}

try {
// FIXME: Perform parsing here
return await response.json();
} catch (e) {
throw new Error(
Expand Down Expand Up @@ -217,6 +218,7 @@ export async function isValidVerifiablePresentation(
}

try {
// FIXME: Perform parsing here
return await response.json();
} catch (e) {
throw new Error(
Expand Down

0 comments on commit baaef5f

Please sign in to comment.