-
Notifications
You must be signed in to change notification settings - Fork 1
wip/term wrapper type #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| import type { BaseQuad, DataFactory, DatasetCore, Literal, NamedNode, Quad_Subject, Term } from "@rdfjs/types" | ||
| import type { IRdfJsTerm } from "./type/IRdfJsTerm.js" | ||
| import type { DataFactory, DatasetCore, NamedNode, Term } from "@rdfjs/types" | ||
|
|
||
| /** | ||
| * `TermWrapper` is one of the two central constructs of this library. It is the base class of all models that represent a mapping from RDF to JavaScript. It _is_ an {@link Term | RDF/JS term} (or node) that also has a reference to both the dataset (or graph) that is the context of (i.e. contains) the term and to a factory that can be used to create additional terms. | ||
|
|
@@ -31,46 +30,30 @@ import type { IRdfJsTerm } from "./type/IRdfJsTerm.js" | |
| * We can work with this data in JavaScript and TypeScript as follows: | ||
| * ```ts | ||
| * const dataset: DatasetCore // which has the RDF above loaded | ||
| * const instance = new SomeClass("http://example.com/someSubject", dataset, DataFactory) | ||
| * const instance = SomeClass.from("http://example.com/someSubject", dataset, DataFactory) | ||
| * | ||
| * const value = instance.someProperty // contains "some value" | ||
| * | ||
| * instance.someProperty = "some other value" // underlying RDF is now <someSubject> <someProperty> "some other value" . | ||
| * ``` | ||
| * | ||
| * @example Using instances of TermWrapper as instances of RDF/JS Term | ||
| * Since this class implements all members of all term types (named nodes, literals, blank nodes etc.), it can be cast to an RDF/JS Term: | ||
| * Instances created via {@link TermWrapper.from} are typed as both the wrapper and the underlying RDF/JS {@link Term}, so they can be passed directly anywhere a `Term` is expected — no casts required: | ||
| * ```ts | ||
| * let instance: TermWrapper | ||
| * const instance = SomeClass.from("http://example.com/someSubject", dataset, factory) | ||
| * | ||
| * // Our instance cast as Term | ||
| * const term = instance as Term | ||
| * ``` | ||
| * | ||
| * @example Using instances of TermWrapper to create quads | ||
| * Instances of this class can be used anywhere an RDF/JS Term can be used, which includes creating quads: | ||
| * ```ts | ||
| * let instance: TermWrapper | ||
| * let factory: DataFactory | ||
| * const predicate = factory.namedNode("http://example.com/p") | ||
| * const object = factory.literal("o") | ||
| * // Used as subject when creating a quad | ||
| * factory.quad(instance, predicate, object) | ||
| * | ||
| * // Our instance used as subject when creating a quad | ||
| * factory.quad(instance as Quad_Subject, predicate, object) | ||
| * // Used as subject when matching statements in a dataset | ||
| * dataset.match(instance) | ||
| * ``` | ||
| * | ||
| * @example Using instances of TermWrapper to match graph patterns | ||
| * Instances of this class can be used anywhere an RDF/JS Term can be used, which includes matching quads in a dataset: | ||
| * ```ts | ||
| * let instance: TermWrapper | ||
| * let dataset: DatasetCore | ||
| * | ||
| * // Our instance used as subject when matching statements in a dataset | ||
| * dataset.match(instance as Term) | ||
| * ``` | ||
| * @see | ||
| * - {@link TermWrapper.from} | ||
| */ | ||
| export class TermWrapper implements IRdfJsTerm { | ||
| private readonly original: Term | ||
| export class TermWrapper<T extends Term = Term> { | ||
| private readonly original: T | ||
| private readonly _dataset: DatasetCore | ||
| private readonly _factory: DataFactory | ||
|
|
||
|
|
@@ -93,7 +76,7 @@ export class TermWrapper implements IRdfJsTerm { | |
| constructor(term: Term, dataset: DatasetCore, factory: DataFactory) | ||
|
|
||
| constructor(term: string | Term, dataset: DatasetCore, factory: DataFactory) { | ||
| this.original = typeof term === "string" ? factory.namedNode(term) : term | ||
| this.original = (typeof term === "string" ? factory.namedNode(term) : term) as T | ||
| this._dataset = dataset | ||
| this._factory = factory | ||
| } | ||
|
|
@@ -189,7 +172,7 @@ export class TermWrapper implements IRdfJsTerm { | |
|
|
||
| //#region Implementation of RDF/JS Term | ||
|
|
||
| get termType(): Term["termType"] { | ||
| get termType(): T["termType"] { | ||
| return this.original.termType | ||
| } | ||
|
|
||
|
|
@@ -201,41 +184,39 @@ export class TermWrapper implements IRdfJsTerm { | |
| return this.original.equals(other) | ||
| } | ||
|
|
||
| //#region Implementation of RDF/JS Literal | ||
|
|
||
| get language(): string { | ||
| return (this.original as Literal).language | ||
| } | ||
|
|
||
| get direction(): Literal["direction"] { | ||
| return (this.original as Literal).direction | ||
| } | ||
|
|
||
| get datatype(): NamedNode { | ||
| return (this.original as Literal).datatype | ||
| } | ||
|
|
||
| //#endregion | ||
|
|
||
| //#region Implementation of RDF/JS Quad | ||
|
|
||
| get subject(): Term { | ||
| return (this.original as BaseQuad).subject | ||
| } | ||
|
|
||
| get predicate(): Term { | ||
| return (this.original as BaseQuad).predicate | ||
| } | ||
|
|
||
| get object(): Term { | ||
| return (this.original as BaseQuad).object | ||
| } | ||
|
|
||
| get graph(): Term { | ||
| return (this.original as BaseQuad).graph | ||
| /** | ||
| * Creates a new instance of this class (or subclass), typed as both the wrapper and the underlying RDF/JS {@link Term}. | ||
| * | ||
| * @remarks | ||
| * Equivalent to invoking the constructor directly, but the returned value is typed as the intersection of the (sub)class instance type and the term type. When called on a subclass (e.g. `Child.from(...)`), the returned value is `Child & T`, where `T` is inferred from the `term` argument (defaults to {@link NamedNode} when a string is passed). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const child = Child.from("http://example.com/x", dataset, factory) | ||
| * // typeof child === Child & NamedNode<string> | ||
| * ``` | ||
| */ | ||
| public static from<This extends new (term: string, dataset: DatasetCore, factory: DataFactory) => any>( | ||
| this: This, | ||
| term: string, | ||
| dataset: DatasetCore, | ||
| factory: DataFactory, | ||
| ): InstanceType<This> & NamedNode<string> | ||
| public static from<T extends Term, This extends new (term: T, dataset: DatasetCore, factory: DataFactory) => any>( | ||
| this: This, | ||
| term: T, | ||
| dataset: DatasetCore, | ||
| factory: DataFactory, | ||
| ): InstanceType<This> & T | ||
| public static from(this: any, term: string | Term, dataset: DatasetCore, factory: DataFactory): any { | ||
| return new this(term, dataset, factory) | ||
| } | ||
| } | ||
|
|
||
| //#endregion | ||
|
|
||
| //#endregion | ||
| for (const prop of ['language', 'direction', 'datatype', 'subject', 'predicate', 'object', 'graph'] as const) { | ||
| Object.defineProperty(TermWrapper.prototype, prop, { | ||
| get(this: TermWrapper) { return (this as any).original[prop] }, | ||
| enumerable: false, | ||
| configurable: true, | ||
| }) | ||
| } | ||
|
Comment on lines
+216
to
222
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,7 @@ export namespace LiteralAs { | |
| ensureDatatype(term, RDF.langString) | ||
|
|
||
| // TODO: Direction | ||
| return {lang: term.language, string: term.value} | ||
| return {lang: (term as unknown as Literal).language, string: term.value} | ||
|
jeswr marked this conversation as resolved.
|
||
| } | ||
|
|
||
| export function number(term: TermWrapper): number { | ||
|
|
@@ -152,7 +152,7 @@ export namespace LiteralAs { | |
| ensureTermType(term, "Literal") | ||
| ensureDatatype(term, ...byteArrayDatatypes) | ||
|
|
||
| switch (term.datatype.value) { | ||
| switch ((term as unknown as Literal).datatype.value) { | ||
|
||
| case XSD.hexBinary: | ||
| // TODO: When Node 25 - return Uint8Array.fromHex(term.value) | ||
| return Uint8Array.from(Buffer.from(term.value, "hex")) | ||
|
|
@@ -179,15 +179,15 @@ export namespace LiteralAs { | |
| ensureTermType(term, "Literal") | ||
| ensureDatatype(term, RDF.langString) | ||
|
|
||
| return [term.language, term.value] | ||
| return [(term as unknown as Literal).language, term.value] | ||
|
||
| } | ||
|
|
||
| export function datatypeTuple(term: TermWrapper): [string, string] { | ||
| ensurePresent(term) | ||
| ensureIs(term, TermWrapper) | ||
| ensureTermType(term, "Literal") | ||
|
|
||
| return [term.datatype.value, term.value] | ||
| return [(term as unknown as Literal).datatype.value, term.value] | ||
|
jeswr marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||
| import type { DataFactory, Term } from "@rdfjs/types" | ||||||
| import type { IRdfJsTerm } from "../type/IRdfJsTerm.js" | ||||||
| import { TermWrapper } from "../TermWrapper.js" | ||||||
|
|
||||||
| /** | ||||||
| * A collection of {@link ITermAsValueMapping | mappers} that create RDF/JS terms from JavaScript primitives. | ||||||
|
|
@@ -9,7 +9,7 @@ import type { IRdfJsTerm } from "../type/IRdfJsTerm.js" | |||||
| * - [Nodes in RDF 1.1 Concepts and Abstract Syntax](https://www.w3.org/TR/rdf11-concepts/#dfn-node) | ||||||
| */ | ||||||
| export namespace TermFrom { | ||||||
| export function instance(value: IRdfJsTerm, factory: DataFactory): Term { | ||||||
| export function instance(value: TermWrapper, factory: DataFactory): Term { | ||||||
| return itself(value as Term, factory) | ||||||
|
||||||
| return itself(value as Term, factory) | |
| return itself(value, factory) |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.