|
|
|
@ -1,4 +1,4 @@ |
|
|
|
|
import type { LdoBase, ShapeType } from "@ldo/ldo"; |
|
|
|
|
import type { LdoBase, LdoTransactionDataset, ShapeType } from "@ldo/ldo"; |
|
|
|
|
import { LdoDataset, startTransaction } from "@ldo/ldo"; |
|
|
|
|
import type { DatasetChanges, GraphNode, SubjectNode } from "@ldo/rdf-utils"; |
|
|
|
|
import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; |
|
|
|
@ -22,6 +22,7 @@ import { splitChangesByGraph } from "./util/splitChangesByGraph"; |
|
|
|
|
import type { ContainerUri, LeafUri } from "./util/uriTypes"; |
|
|
|
|
import { isContainerUri } from "./util/uriTypes"; |
|
|
|
|
import type { Resource } from "./resource/Resource"; |
|
|
|
|
import { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset"; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* A SolidLdoDataset has all the functionality of an LdoDataset with the added |
|
|
|
@ -61,7 +62,7 @@ export class SolidLdoDataset extends LdoDataset { |
|
|
|
|
*/ |
|
|
|
|
constructor( |
|
|
|
|
context: SolidLdoDatasetContext, |
|
|
|
|
datasetFactory: DatasetFactory, |
|
|
|
|
datasetFactory: DatasetFactory,
|
|
|
|
|
initialDataset?: Dataset, |
|
|
|
|
) { |
|
|
|
|
super(datasetFactory, initialDataset); |
|
|
|
@ -92,120 +93,128 @@ export class SolidLdoDataset extends LdoDataset { |
|
|
|
|
return this.context.resourceStore.get(uri, options); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Given dataset changes, commit all changes made to the proper place |
|
|
|
|
* on Solid Pods. |
|
|
|
|
* |
|
|
|
|
* @param changes - A set of changes that should be applied to Solid Pods |
|
|
|
|
* |
|
|
|
|
* @returns an AggregateSuccess if successful and an AggregateError if not |
|
|
|
|
* |
|
|
|
|
* @example |
|
|
|
|
* ```typescript
|
|
|
|
|
* const result = await solidLdoDataset.commitChangesToPod({ |
|
|
|
|
* added: createDataset([ |
|
|
|
|
* quad(namedNode("a"), namedNode("b"), namedNode("d")); |
|
|
|
|
* ]), |
|
|
|
|
* removed: createDataset([ |
|
|
|
|
* quad(namedNode("a"), namedNode("b"), namedNode("c")); |
|
|
|
|
* ]) |
|
|
|
|
* }); |
|
|
|
|
* if (result.isError()) { |
|
|
|
|
* // handle error
|
|
|
|
|
* } |
|
|
|
|
* ``` |
|
|
|
|
*/ |
|
|
|
|
async commitChangesToPod( |
|
|
|
|
changes: DatasetChanges<Quad>, |
|
|
|
|
): Promise< |
|
|
|
|
| AggregateSuccess< |
|
|
|
|
ResourceResult<UpdateSuccess | UpdateDefaultGraphSuccess, Leaf> |
|
|
|
|
> |
|
|
|
|
| AggregateError<UpdateResultError | InvalidUriError> |
|
|
|
|
> { |
|
|
|
|
// Optimistically add changes to the datastore
|
|
|
|
|
// this.bulk(changes);
|
|
|
|
|
const changesByGraph = splitChangesByGraph(changes); |
|
|
|
|
|
|
|
|
|
// Iterate through all changes by graph in
|
|
|
|
|
const results: [ |
|
|
|
|
GraphNode, |
|
|
|
|
DatasetChanges<Quad>, |
|
|
|
|
UpdateResult | InvalidUriError | UpdateDefaultGraphSuccess, |
|
|
|
|
][] = await Promise.all( |
|
|
|
|
Array.from(changesByGraph.entries()).map( |
|
|
|
|
async ([graph, datasetChanges]) => { |
|
|
|
|
if (graph.termType === "DefaultGraph") { |
|
|
|
|
// Undefined means that this is the default graph
|
|
|
|
|
this.bulk(datasetChanges); |
|
|
|
|
return [ |
|
|
|
|
graph, |
|
|
|
|
datasetChanges, |
|
|
|
|
{ |
|
|
|
|
type: "updateDefaultGraphSuccess", |
|
|
|
|
isError: false, |
|
|
|
|
} as UpdateDefaultGraphSuccess, |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
if (isContainerUri(graph.value)) { |
|
|
|
|
return [ |
|
|
|
|
graph, |
|
|
|
|
datasetChanges, |
|
|
|
|
new InvalidUriError( |
|
|
|
|
graph.value, |
|
|
|
|
`Container URIs are not allowed for custom data.`, |
|
|
|
|
), |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
const resource = this.getResource(graph.value as LeafUri); |
|
|
|
|
return [graph, datasetChanges, await resource.update(datasetChanges)]; |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
public startTransaction(): SolidLdoTransactionDataset { |
|
|
|
|
return new SolidLdoTransactionDataset( |
|
|
|
|
this, |
|
|
|
|
this.datasetFactory, |
|
|
|
|
this.transactionDatasetFactory, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If one has errored, return error
|
|
|
|
|
const errors = results.filter((result) => result[2].isError); |
|
|
|
|
// /**
|
|
|
|
|
// * Given dataset changes, commit all changes made to the proper place
|
|
|
|
|
// * on Solid Pods.
|
|
|
|
|
// *
|
|
|
|
|
// * @param changes - A set of changes that should be applied to Solid Pods
|
|
|
|
|
// *
|
|
|
|
|
// * @returns an AggregateSuccess if successful and an AggregateError if not
|
|
|
|
|
// *
|
|
|
|
|
// * @example
|
|
|
|
|
// * ```typescript
|
|
|
|
|
// * const result = await solidLdoDataset.commitChangesToPod({
|
|
|
|
|
// * added: createDataset([
|
|
|
|
|
// * quad(namedNode("a"), namedNode("b"), namedNode("d"));
|
|
|
|
|
// * ]),
|
|
|
|
|
// * removed: createDataset([
|
|
|
|
|
// * quad(namedNode("a"), namedNode("b"), namedNode("c"));
|
|
|
|
|
// * ])
|
|
|
|
|
// * });
|
|
|
|
|
// * if (result.isError()) {
|
|
|
|
|
// * // handle error
|
|
|
|
|
// * }
|
|
|
|
|
// * ```
|
|
|
|
|
// */
|
|
|
|
|
// async commitChangesToPod(
|
|
|
|
|
// changes: DatasetChanges<Quad>,
|
|
|
|
|
// ): Promise<
|
|
|
|
|
// | AggregateSuccess<
|
|
|
|
|
// ResourceResult<UpdateSuccess | UpdateDefaultGraphSuccess, Leaf>
|
|
|
|
|
// >
|
|
|
|
|
// | AggregateError<UpdateResultError | InvalidUriError>
|
|
|
|
|
// > {
|
|
|
|
|
// // Optimistically add changes to the datastore
|
|
|
|
|
// // this.bulk(changes);
|
|
|
|
|
// const changesByGraph = splitChangesByGraph(changes);
|
|
|
|
|
|
|
|
|
|
if (errors.length > 0) { |
|
|
|
|
return new AggregateError( |
|
|
|
|
errors.map( |
|
|
|
|
(result) => result[2] as UpdateResultError | InvalidUriError, |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
return { |
|
|
|
|
isError: false, |
|
|
|
|
type: "aggregateSuccess", |
|
|
|
|
results: results |
|
|
|
|
.map((result) => result[2]) |
|
|
|
|
.filter( |
|
|
|
|
(result): result is ResourceResult<UpdateSuccess, Leaf> => |
|
|
|
|
result.type === "updateSuccess" || |
|
|
|
|
result.type === "updateDefaultGraphSuccess", |
|
|
|
|
), |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
// // Iterate through all changes by graph in
|
|
|
|
|
// const results: [
|
|
|
|
|
// GraphNode,
|
|
|
|
|
// DatasetChanges<Quad>,
|
|
|
|
|
// UpdateResult | InvalidUriError | UpdateDefaultGraphSuccess,
|
|
|
|
|
// ][] = await Promise.all(
|
|
|
|
|
// Array.from(changesByGraph.entries()).map(
|
|
|
|
|
// async ([graph, datasetChanges]) => {
|
|
|
|
|
// if (graph.termType === "DefaultGraph") {
|
|
|
|
|
// // Undefined means that this is the default graph
|
|
|
|
|
// this.bulk(datasetChanges);
|
|
|
|
|
// return [
|
|
|
|
|
// graph,
|
|
|
|
|
// datasetChanges,
|
|
|
|
|
// {
|
|
|
|
|
// type: "updateDefaultGraphSuccess",
|
|
|
|
|
// isError: false,
|
|
|
|
|
// } as UpdateDefaultGraphSuccess,
|
|
|
|
|
// ];
|
|
|
|
|
// }
|
|
|
|
|
// if (isContainerUri(graph.value)) {
|
|
|
|
|
// return [
|
|
|
|
|
// graph,
|
|
|
|
|
// datasetChanges,
|
|
|
|
|
// new InvalidUriError(
|
|
|
|
|
// graph.value,
|
|
|
|
|
// `Container URIs are not allowed for custom data.`,
|
|
|
|
|
// ),
|
|
|
|
|
// ];
|
|
|
|
|
// }
|
|
|
|
|
// const resource = this.getResource(graph.value as LeafUri);
|
|
|
|
|
// return [graph, datasetChanges, await resource.update(datasetChanges) ];
|
|
|
|
|
// },
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Shorthand for solidLdoDataset |
|
|
|
|
* .usingType(shapeType) |
|
|
|
|
* .write(...resources.map((r) => r.uri)) |
|
|
|
|
* .fromSubject(subject); |
|
|
|
|
* @param shapeType - The shapetype to represent the data |
|
|
|
|
* @param subject - A subject URI |
|
|
|
|
* @param resources - The resources changes to should written to |
|
|
|
|
*/ |
|
|
|
|
createData<Type extends LdoBase>( |
|
|
|
|
shapeType: ShapeType<Type>, |
|
|
|
|
subject: string | SubjectNode, |
|
|
|
|
resource: Resource, |
|
|
|
|
...additionalResources: Resource[] |
|
|
|
|
): Type { |
|
|
|
|
const resources = [resource, ...additionalResources]; |
|
|
|
|
const linkedDataObject = this.usingType(shapeType) |
|
|
|
|
.write(...resources.map((r) => r.uri)) |
|
|
|
|
.fromSubject(subject); |
|
|
|
|
startTransaction(linkedDataObject); |
|
|
|
|
return linkedDataObject; |
|
|
|
|
} |
|
|
|
|
// // If one has errored, return error
|
|
|
|
|
// const errors = results.filter((result) => result[2].isError);
|
|
|
|
|
|
|
|
|
|
// if (errors.length > 0) {
|
|
|
|
|
// return new AggregateError(
|
|
|
|
|
// errors.map(
|
|
|
|
|
// (result) => result[2] as UpdateResultError | InvalidUriError,
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// return {
|
|
|
|
|
// isError: false,
|
|
|
|
|
// type: "aggregateSuccess",
|
|
|
|
|
// results: results
|
|
|
|
|
// .map((result) => result[2])
|
|
|
|
|
// .filter(
|
|
|
|
|
// (result): result is ResourceResult<UpdateSuccess, Leaf> =>
|
|
|
|
|
// result.type === "updateSuccess" ||
|
|
|
|
|
// result.type === "updateDefaultGraphSuccess",
|
|
|
|
|
// ),
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// /**
|
|
|
|
|
// * Shorthand for solidLdoDataset
|
|
|
|
|
// * .usingType(shapeType)
|
|
|
|
|
// * .write(...resources.map((r) => r.uri))
|
|
|
|
|
// * .fromSubject(subject);
|
|
|
|
|
// * @param shapeType - The shapetype to represent the data
|
|
|
|
|
// * @param subject - A subject URI
|
|
|
|
|
// * @param resources - The resources changes to should written to
|
|
|
|
|
// */
|
|
|
|
|
// createData<Type extends LdoBase>(
|
|
|
|
|
// shapeType: ShapeType<Type>,
|
|
|
|
|
// subject: string | SubjectNode,
|
|
|
|
|
// resource: Resource,
|
|
|
|
|
// ...additionalResources: Resource[]
|
|
|
|
|
// ): Type {
|
|
|
|
|
// const resources = [resource, ...additionalResources];
|
|
|
|
|
// const linkedDataObject = this.usingType(shapeType)
|
|
|
|
|
// .write(...resources.map((r) => r.uri))
|
|
|
|
|
// .fromSubject(subject);
|
|
|
|
|
// startTransaction(linkedDataObject);
|
|
|
|
|
// return linkedDataObject;
|
|
|
|
|
// }
|
|
|
|
|
} |
|
|
|
|