parent
d1eb89ea91
commit
8dd6540c63
@ -1,61 +0,0 @@ |
|||||||
import type { |
|
||||||
ProxyContextOptions, |
|
||||||
SubjectProxy, |
|
||||||
SetProxy, |
|
||||||
} from "@ldo/jsonld-dataset-proxy"; |
|
||||||
import { ProxyContext } from "@ldo/jsonld-dataset-proxy"; |
|
||||||
import type { QuadMatch } from "@ldo/rdf-utils"; |
|
||||||
import type { SubscribableDataset } from "@ldo/subscribable-dataset"; |
|
||||||
import type { BlankNode, NamedNode, Quad } from "@rdfjs/types"; |
|
||||||
import { createTrackingSubjectProxy } from "./TrackingSubjectProxy"; |
|
||||||
import { createTrackingSetProxy } from "./TrackingSetProxy"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @internal |
|
||||||
* Options to be passed to the tracking proxy |
|
||||||
*/ |
|
||||||
export interface TrackingProxyContextOptions extends ProxyContextOptions { |
|
||||||
dataset: SubscribableDataset<Quad>; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @internal |
|
||||||
* This proxy exists to ensure react components rerender at the right time. It |
|
||||||
* keeps track of every key accessed in a Linked Data Object and only when the |
|
||||||
* dataset is updated with that key does it rerender the react component. |
|
||||||
*/ |
|
||||||
export class TrackingProxyContext extends ProxyContext { |
|
||||||
private listener: () => void; |
|
||||||
private subscribableDataset: SubscribableDataset<Quad>; |
|
||||||
|
|
||||||
constructor(options: TrackingProxyContextOptions, listener: () => void) { |
|
||||||
super(options); |
|
||||||
this.subscribableDataset = options.dataset; |
|
||||||
this.listener = listener; |
|
||||||
} |
|
||||||
|
|
||||||
// Adds the listener to the subscribable dataset while ensuring deduping of the listener
|
|
||||||
public addListener(eventName: QuadMatch) { |
|
||||||
const listeners = this.subscribableDataset.listeners(eventName); |
|
||||||
if (!listeners.includes(this.listener)) { |
|
||||||
this.subscribableDataset.on(eventName, this.listener); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected createNewSubjectProxy(node: NamedNode | BlankNode): SubjectProxy { |
|
||||||
return createTrackingSubjectProxy(this, node); |
|
||||||
} |
|
||||||
|
|
||||||
protected createNewSetProxy( |
|
||||||
quadMatch: QuadMatch, |
|
||||||
isSubjectOriented?: boolean, |
|
||||||
isLangStringSet?: boolean, |
|
||||||
): SetProxy { |
|
||||||
return createTrackingSetProxy( |
|
||||||
this, |
|
||||||
quadMatch, |
|
||||||
isSubjectOriented, |
|
||||||
isLangStringSet, |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
import { createNewSetProxy, type SetProxy } from "@ldo/jsonld-dataset-proxy"; |
|
||||||
import type { TrackingProxyContext } from "./TrackingProxyContext"; |
|
||||||
import type { QuadMatch } from "@ldo/rdf-utils"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @internal |
|
||||||
* |
|
||||||
* Creates a tracking proxy for a set, a proxy that tracks the fields that have |
|
||||||
* been accessed. |
|
||||||
*/ |
|
||||||
export function createTrackingSetProxy( |
|
||||||
proxyContext: TrackingProxyContext, |
|
||||||
quadMatch: QuadMatch, |
|
||||||
isSubjectOriented?: boolean, |
|
||||||
isLangStringSet?: boolean, |
|
||||||
): SetProxy { |
|
||||||
const baseSetProxy = createNewSetProxy( |
|
||||||
quadMatch, |
|
||||||
isSubjectOriented ?? false, |
|
||||||
proxyContext, |
|
||||||
isLangStringSet, |
|
||||||
); |
|
||||||
|
|
||||||
return new Proxy(baseSetProxy, { |
|
||||||
get: (target: SetProxy, key: string | symbol, receiver) => { |
|
||||||
if (trackingMethods.has(key)) { |
|
||||||
proxyContext.addListener(quadMatch); |
|
||||||
} else if (disallowedMethods.has(key)) { |
|
||||||
console.warn( |
|
||||||
"You've attempted to modify 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 Reflect.get(target, key, receiver); |
|
||||||
}, |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
const trackingMethods = new Set([ |
|
||||||
"has", |
|
||||||
"size", |
|
||||||
"entries", |
|
||||||
"keys", |
|
||||||
"values", |
|
||||||
Symbol.iterator, |
|
||||||
"every", |
|
||||||
"every", |
|
||||||
"some", |
|
||||||
"forEach", |
|
||||||
"map", |
|
||||||
"reduce", |
|
||||||
"toArray", |
|
||||||
"toJSON", |
|
||||||
"difference", |
|
||||||
"intersection", |
|
||||||
"isDisjointFrom", |
|
||||||
"isSubsetOf", |
|
||||||
"isSupersetOf", |
|
||||||
"symmetricDifference", |
|
||||||
"union", |
|
||||||
]); |
|
||||||
|
|
||||||
const disallowedMethods = new Set<string | symbol>(["add", "clear", "delete"]); |
|
@ -1,49 +0,0 @@ |
|||||||
import type { SubjectProxyTarget } from "@ldo/jsonld-dataset-proxy"; |
|
||||||
import { |
|
||||||
createSubjectHandler, |
|
||||||
type SubjectProxy, |
|
||||||
} from "@ldo/jsonld-dataset-proxy"; |
|
||||||
import type { BlankNode, NamedNode } from "@rdfjs/types"; |
|
||||||
import type { TrackingProxyContext } from "./TrackingProxyContext"; |
|
||||||
import { namedNode } from "@rdfjs/data-model"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @internal |
|
||||||
* |
|
||||||
* Creates a tracking proxy for a single value, a proxy that tracks the fields |
|
||||||
* that have been accessed. |
|
||||||
*/ |
|
||||||
export function createTrackingSubjectProxy( |
|
||||||
proxyContext: TrackingProxyContext, |
|
||||||
node: NamedNode | BlankNode, |
|
||||||
): SubjectProxy { |
|
||||||
const baseHandler = createSubjectHandler(proxyContext); |
|
||||||
const oldGetFunction = baseHandler.get; |
|
||||||
const newGetFunction: ProxyHandler<SubjectProxyTarget>["get"] = ( |
|
||||||
target: SubjectProxyTarget, |
|
||||||
key: string | symbol, |
|
||||||
receiver, |
|
||||||
) => { |
|
||||||
const subject = target["@id"]; |
|
||||||
const rdfTypes = proxyContext.getRdfType(subject); |
|
||||||
if (typeof key === "symbol") { |
|
||||||
// Do Nothing
|
|
||||||
} else if (key === "@id") { |
|
||||||
proxyContext.addListener([subject, null, null, null]); |
|
||||||
} else if (!proxyContext.contextUtil.isSet(key, rdfTypes)) { |
|
||||||
const predicate = namedNode( |
|
||||||
proxyContext.contextUtil.keyToIri(key, rdfTypes), |
|
||||||
); |
|
||||||
proxyContext.addListener([subject, predicate, null, null]); |
|
||||||
} |
|
||||||
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 new Proxy({ "@id": node }, baseHandler) as unknown as SubjectProxy; |
|
||||||
} |
|
Loading…
Reference in new issue