You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

98 lines
2.8 KiB

import type {
ArrayProxyTarget,
SubjectProxyTarget,
ProxyContextOptions,
} from "jsonld-dataset-proxy";
import { ProxyContext } from "jsonld-dataset-proxy";
import type { UpdateManager } from "./UpdateManager";
import { namedNode } from "@rdfjs/data-model";
export class TrackingProxyContext extends ProxyContext {
private updateManager: UpdateManager;
private listener: () => void;
constructor(
options: ProxyContextOptions,
updateManager: UpdateManager,
listener: () => void,
) {
super(options);
this.updateManager = updateManager;
this.listener = listener;
}
protected createSubjectHandler(): ProxyHandler<SubjectProxyTarget> {
const baseHandler = super.createSubjectHandler();
const oldGetFunction = baseHandler.get;
const newGetFunction: ProxyHandler<SubjectProxyTarget>["get"] = (
target: SubjectProxyTarget,
key: string | symbol,
receiver,
) => {
const subject = target["@id"];
if (typeof key === "symbol") {
// Do Nothing
} else if (key === "@id") {
this.updateManager.registerListener(
[subject, null, null],
this.listener,
);
} else if (!this.contextUtil.isArray(key)) {
const predicate = namedNode(this.contextUtil.keyToIri(key));
this.updateManager.registerListener(
[subject, predicate, null],
this.listener,
);
}
return oldGetFunction && oldGetFunction(target, key, receiver);
};
baseHandler.get = newGetFunction;
baseHandler.set = () => {
console.warn(
"You've attempted to set a value on a Linked Data Object from the useSubject, useMatchingSubject, or useMatchingObject hooks. These linked data objects should only be used to render data, not modify it. To modify data, use the `changeData` function.",
);
return true;
};
return baseHandler;
}
protected createArrayHandler(): ProxyHandler<ArrayProxyTarget> {
const baseHandler = super.createArrayHandler();
const oldGetFunction = baseHandler.get;
const newGetFunction: ProxyHandler<ArrayProxyTarget>["get"] = (
target: ArrayProxyTarget,
key: string | symbol,
receiver,
) => {
if (qualifiedArrayMethods.has(key)) {
this.updateManager.registerListener(
[target[0][0], target[0][1], target[0][2]],
this.listener,
);
}
return oldGetFunction && oldGetFunction(target, key, receiver);
};
baseHandler.get = newGetFunction;
return baseHandler;
}
}
const qualifiedArrayMethods = new Set([
"forEach",
"map",
"reduce",
Symbol.iterator,
"entries",
"every",
"filter",
"find",
"findIndex",
"findLast",
"findLastIndex",
"includes, indexOf",
"keys",
"lastIndexOf",
"reduceRight",
"some",
"values",
]);