UNPKG

@inrupt/solid-client

Version:

Make your web apps work with Solid Pods.

389 lines (379 loc) • 13.7 kB
// Copyright Inrupt Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the // Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // import type { Literal, Quad_Object, NamedNode } from "@rdfjs/types"; import type { Time } from "../datatypes"; import type { Thing, ThingLocal, ThingPersisted, Url, UrlString, } from "../interfaces"; import type { AddOfType } from "./add"; import { addBoolean, addDate, addDatetime, addTime, addDecimal, addInteger, addIri, addLiteral, addNamedNode, addStringNoLocale, addStringWithLocale, addTerm, addUrl, } from "./add"; import type { RemoveOfType } from "./remove"; import { removeAll, removeBoolean, removeDate, removeDatetime, removeTime, removeDecimal, removeInteger, removeIri, removeLiteral, removeNamedNode, removeStringNoLocale, removeStringWithLocale, removeUrl, } from "./remove"; import type { SetOfType } from "./set"; import { setBoolean, setDate, setDatetime, setTime, setDecimal, setInteger, setIri, setLiteral, setNamedNode, setStringNoLocale, setStringWithLocale, setTerm, setUrl, } from "./set"; import type { CreateThingLocalOptions, CreateThingOptions, CreateThingPersistedOptions, } from "./thing"; import { createThing, isThing } from "./thing"; type Adder<Type, T extends Thing> = ( property: Parameters<AddOfType<Type>>[1], value: Parameters<AddOfType<Type>>[2], ) => ThingBuilder<T>; type Setter<Type, T extends Thing> = ( property: Parameters<SetOfType<Type>>[1], value: Parameters<SetOfType<Type>>[2], ) => ThingBuilder<T>; type Remover<Type, T extends Thing> = ( property: Parameters<RemoveOfType<Type>>[1], value: Parameters<RemoveOfType<Type>>[2], ) => ThingBuilder<T>; // Unfortunately this interface has too many properties for TypeScript to infer, // hence the duplication between the interface and the implementation method names. /** * A Fluent interface to build a [[Thing]]. * * Add, replace or remove property values using consecutive calls to `.add*()`, * `.set*()` and `.remove*()`, then finally generate a [[Thing]] with the given * properties using `.build()`. * @since 1.9.0 */ export type ThingBuilder<T extends Thing> = { build: () => T; addUrl: Adder<Url | UrlString | Thing, T>; addIri: Adder<Url | UrlString | Thing, T>; addBoolean: Adder<boolean, T>; addDatetime: Adder<Date, T>; addDate: Adder<Date, T>; addTime: Adder<Time, T>; addDecimal: Adder<number, T>; addInteger: Adder<number, T>; addStringNoLocale: Adder<string, T>; addStringEnglish: Adder<string, T>; addStringWithLocale: ( property: Parameters<typeof addStringWithLocale>[1], value: Parameters<typeof addStringWithLocale>[2], locale: Parameters<typeof addStringWithLocale>[3], ) => ThingBuilder<T>; addNamedNode: Adder<NamedNode, T>; addLiteral: Adder<Literal, T>; addTerm: Adder<Quad_Object, T>; setUrl: Setter<Url | UrlString | Thing, T>; setIri: Setter<Url | UrlString | Thing, T>; setBoolean: Setter<boolean, T>; setDatetime: Setter<Date, T>; setDate: Setter<Date, T>; setTime: Setter<Time, T>; setDecimal: Setter<number, T>; setInteger: Setter<number, T>; setStringNoLocale: Setter<string, T>; setStringEnglish: Setter<string, T>; setStringWithLocale: ( property: Parameters<typeof setStringWithLocale>[1], value: Parameters<typeof setStringWithLocale>[2], locale: Parameters<typeof setStringWithLocale>[3], ) => ThingBuilder<T>; setNamedNode: Setter<NamedNode, T>; setLiteral: Setter<Literal, T>; setTerm: Setter<Quad_Object, T>; removeAll: (property: Parameters<typeof removeLiteral>[1]) => ThingBuilder<T>; removeUrl: Remover<Url | UrlString | Thing, T>; removeIri: Remover<Url | UrlString | Thing, T>; removeBoolean: Remover<boolean, T>; removeDatetime: Remover<Date, T>; removeDate: Remover<Date, T>; removeTime: Remover<Time, T>; removeDecimal: Remover<number, T>; removeInteger: Remover<number, T>; removeStringNoLocale: Remover<string, T>; removeStringEnglish: Remover<string, T>; removeStringWithLocale: ( property: Parameters<typeof removeStringWithLocale>[1], value: Parameters<typeof removeStringWithLocale>[2], locale: Parameters<typeof removeStringWithLocale>[3], ) => ThingBuilder<T>; removeNamedNode: Remover<NamedNode, T>; removeLiteral: Remover<Literal, T>; }; /** * Modify a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can initialise several properties of a given Thing as follows: * * const me = buildThing(createThing({ name: "profile-vincent" })) * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @param init A Thing to modify. * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing(init: ThingLocal): ThingBuilder<ThingLocal>; /** * Modify a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can initialise several properties of a given Thing as follows: * * const me = buildThing(createThing({ url: "https://example.pod/profile#vincent" })) * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @param init A Thing to modify. * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing(init: ThingPersisted): ThingBuilder<ThingPersisted>; /** * Create a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can create a new Thing and initialise several properties as follows: * * const me = buildThing({ name: "profile-vincent" }) * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @param init Options used to initialise a new Thing. * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing( init: CreateThingLocalOptions, ): ThingBuilder<ThingLocal>; /** * Create a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can create a new Thing and initialise several properties as follows: * * const me = buildThing({ url: "https://example.pod/profile#vincent" }) * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @param init Optionally pass an existing [[Thing]] to modify the properties of. If left empty, `buildThing` will initialise a new Thing. * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing( init: CreateThingPersistedOptions, ): ThingBuilder<ThingPersisted>; /** * Create a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can create a new Thing and initialise several properties as follows: * * const me = buildThing() * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing(): ThingBuilder<ThingLocal>; /** * Create or modify a [[Thing]], setting multiple properties in a single expresssion. * * For example, you can create a new Thing and initialise several properties as follows: * * const me = buildThing() * .addUrl(rdf.type, schema.Person) * .addStringNoLocale(schema.givenName, "Vincent") * .build(); * * Take note of the final call to `.build()` to obtain the actual Thing. * * @param init Optionally pass an existing [[Thing]] to modify the properties of. If left empty, `buildThing` will initialise a new Thing. * @returns a [[ThingBuilder]], a Fluent API that allows you to set multiple properties in a single expression. * @since 1.9.0 */ export function buildThing( init: Thing | CreateThingOptions = createThing(), ): ThingBuilder<Thing> { let thing = isThing(init) ? init : createThing(init); function getAdder<Type>(adder: AddOfType<Type>) { return ( property: Parameters<typeof adder>[1], value: Parameters<typeof adder>[2], ) => { thing = adder(thing, property, value); return builder; }; } function getSetter<Type>(setter: SetOfType<Type>) { return ( property: Parameters<typeof setter>[1], value: Parameters<typeof setter>[2], ) => { thing = setter(thing, property, value); return builder; }; } function getRemover<Type>(remover: RemoveOfType<Type>) { return ( property: Parameters<typeof remover>[1], value: Parameters<typeof remover>[2], ) => { thing = remover(thing, property, value); return builder; }; } const builder: ThingBuilder<Thing> = { build: () => thing, addUrl: getAdder(addUrl), addIri: getAdder(addIri), addBoolean: getAdder(addBoolean), addDatetime: getAdder(addDatetime), addDate: getAdder(addDate), addTime: getAdder(addTime), addDecimal: getAdder(addDecimal), addInteger: getAdder(addInteger), addStringNoLocale: getAdder(addStringNoLocale), addStringEnglish: ( property: Parameters<typeof addStringWithLocale>[1], value: Parameters<typeof addStringWithLocale>[2], ) => { thing = addStringWithLocale(thing, property, value, "en"); return builder; }, addStringWithLocale: ( property: Parameters<typeof addStringWithLocale>[1], value: Parameters<typeof addStringWithLocale>[2], locale: Parameters<typeof addStringWithLocale>[3], ) => { thing = addStringWithLocale(thing, property, value, locale); return builder; }, addNamedNode: getAdder(addNamedNode), addLiteral: getAdder(addLiteral), addTerm: getAdder(addTerm), setUrl: getSetter(setUrl), setIri: getSetter(setIri), setBoolean: getSetter(setBoolean), setDatetime: getSetter(setDatetime), setDate: getSetter(setDate), setTime: getSetter(setTime), setDecimal: getSetter(setDecimal), setInteger: getSetter(setInteger), setStringNoLocale: getSetter(setStringNoLocale), setStringEnglish: ( property: Parameters<typeof setStringWithLocale>[1], value: Parameters<typeof setStringWithLocale>[2], ) => { thing = setStringWithLocale(thing, property, value, "en"); return builder; }, setStringWithLocale: ( property: Parameters<typeof setStringWithLocale>[1], value: Parameters<typeof setStringWithLocale>[2], locale: Parameters<typeof setStringWithLocale>[3], ) => { thing = setStringWithLocale(thing, property, value, locale); return builder; }, setNamedNode: getSetter(setNamedNode), setLiteral: getSetter(setLiteral), setTerm: getSetter(setTerm), removeAll: (property: Parameters<typeof removeAll>[1]) => { thing = removeAll(thing, property); return builder; }, removeUrl: getRemover(removeUrl), removeIri: getRemover(removeIri), removeBoolean: getRemover(removeBoolean), removeDatetime: getRemover(removeDatetime), removeDate: getRemover(removeDate), removeTime: getRemover(removeTime), removeDecimal: getRemover(removeDecimal), removeInteger: getRemover(removeInteger), removeStringNoLocale: getRemover(removeStringNoLocale), removeStringEnglish: ( property: Parameters<typeof removeStringWithLocale>[1], value: Parameters<typeof removeStringWithLocale>[2], ) => buildThing(removeStringWithLocale(thing, property, value, "en")), removeStringWithLocale: ( property: Parameters<typeof removeStringWithLocale>[1], value: Parameters<typeof removeStringWithLocale>[2], locale: Parameters<typeof removeStringWithLocale>[3], ) => buildThing(removeStringWithLocale(thing, property, value, locale)), removeNamedNode: getRemover(removeNamedNode), removeLiteral: getRemover(removeLiteral), }; return builder; }