Added update method

main
Jackson Morgan 6 months ago
parent 11bf103980
commit 8dd341bb87
  1. 8
      packages/connected/src/ConnectedContext.ts
  2. 11
      packages/connected/src/ConnectedLdoDataset.ts
  3. 51
      packages/connected/src/ConnectedLdoTransactionDataset.ts
  4. 7
      packages/connected/src/ConnectedPlugin.ts
  5. 5
      packages/connected/src/util/splitChangesByGraph.d.ts
  6. 45
      packages/connected/src/util/splitChangesByGraph.js
  7. 1
      packages/connected/src/util/splitChangesByGraph.js.map
  8. 14
      packages/connected/test/MockResource.ts
  9. 5
      packages/connected/tsconfig.build.json

@ -0,0 +1,8 @@
import type { ConnectedLdoDataset } from "./ConnectedLdoDataset";
import type { ConnectedPlugin } from "./ConnectedPlugin";
export type ConnectedContext<Plugins extends ConnectedPlugin[]> = {
dataset: ConnectedLdoDataset<Plugins>;
} & {
[P in Plugins[number] as P["name"]]: P["types"]["context"];
};

@ -33,6 +33,8 @@ export class ConnectedLdoDataset<Plugins extends ConnectedPlugin[]>
super(datasetFactory, transactionDatasetFactory, initialDataset);
this.plugins = plugins;
this.resourceMap = new Map();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore this is a builder. It will eventually match
this.context = {
dataset: this,
};
@ -91,6 +93,7 @@ export class ConnectedLdoDataset<Plugins extends ConnectedPlugin[]>
resource = plugin.getResource(uri, this.context);
this.resourceMap.set(normalizedUri, resource);
}
// HACK: cast to any
return resource as any;
}
@ -99,10 +102,14 @@ export class ConnectedLdoDataset<Plugins extends ConnectedPlugin[]>
Plugin extends Extract<Plugins[number], { name: Name }>,
>(name: Name): Promise<ReturnType<Plugin["createResource"]>> {
const validPlugin = this.plugins.find((plugin) => name === plugin.name)!;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore I'm not sure why this doesn't work
const newResourceResult = await validPlugin.createResource(this.context);
if (newResourceResult.isError) return newResourceResult;
// HACK: cast to any
if (newResourceResult.isError) return newResourceResult as any;
this.resourceMap.set(newResourceResult.uri, newResourceResult);
return newResourceResult;
// HACK: cast to any
return newResourceResult as any;
}
setContext<

@ -6,19 +6,19 @@ import {
type ITransactionDatasetFactory,
} from "@ldo/subscribable-dataset";
import type { DatasetChanges, GraphNode } from "@ldo/rdf-utils";
import type { ConnectedLdoDataset } from "./ConnectedLdoDataset";
import type { ConnectedPlugin } from "./ConnectedPlugin";
import type { ConnectedContext } from "./ConnectedContext";
import type { InvalidIdentifierResource } from "./InvalidIdentifierResource";
import type { IConnectedLdoDataset } from "./IConnectedLdoDataset";
import { splitChangesByGraph } from "./util/splitChangesByGraph";
import type {
IgnoredInvalidUpdateSuccess,
UpdateSuccess,
} from "./results/success/UpdateSuccess";
import type { IgnoredInvalidUpdateSuccess } from "./results/success/UpdateSuccess";
import { UpdateDefaultGraphSuccess } from "./results/success/UpdateSuccess";
import type { ErrorResult } from "./results/error/ErrorResult";
import { AggregateError } from "./results/error/ErrorResult";
import type { AggregateSuccess } from "./results/success/SuccessResult";
import type {
AggregateSuccess,
SuccessResult,
} from "./results/success/SuccessResult";
/**
* A SolidLdoTransactionDataset has all the functionality of a SolidLdoDataset
@ -138,12 +138,16 @@ export class ConnectedLdoTransactionDataset<Plugins extends ConnectedPlugin[]>
async commitChanges(): Promise<
| AggregateSuccess<
| UpdateSuccess<Plugins[number]["types"]["resource"]>
| Extract<
Awaited<ReturnType<Plugins[number]["types"]["resource"]["update"]>>,
{ isError: false }
>
| UpdateDefaultGraphSuccess
| IgnoredInvalidUpdateSuccess<Plugins[number]["types"]["resource"]>
>
| AggregateError<
Extract<
ReturnType<Plugins[number]["types"]["resource"]["update"]>,
Awaited<ReturnType<Plugins[number]["types"]["resource"]["update"]>>,
{ isError: true }
>
>
@ -156,7 +160,7 @@ export class ConnectedLdoTransactionDataset<Plugins extends ConnectedPlugin[]>
GraphNode,
DatasetChanges<Quad>,
(
| ReturnType<Plugins[number]["types"]["resource"]["update"]>
| Awaited<ReturnType<Plugins[number]["types"]["resource"]["update"]>>
| IgnoredInvalidUpdateSuccess<any>
| UpdateDefaultGraphSuccess
),
@ -168,32 +172,33 @@ export class ConnectedLdoTransactionDataset<Plugins extends ConnectedPlugin[]>
updateDatasetInBulk(this.parentDataset, datasetChanges);
return [graph, datasetChanges, new UpdateDefaultGraphSuccess()];
}
const resource = this.getResource(graph.value);
const updateResult = await resource.update(datasetChanges);
const resource = this.getResource(
graph.value,
) as Plugins[number]["types"]["resource"];
const updateResult = (await resource.update(
datasetChanges,
)) as Awaited<
ReturnType<Plugins[number]["types"]["resource"]["update"]>
>;
return [graph, datasetChanges, updateResult];
},
),
);
// If one has errored, return error
const errors = results.filter((result) => result[2].isError);
const errors = (
results.map((result) => result[2]) as (SuccessResult | ErrorResult)[]
).filter((result): result is ErrorResult => result.isError);
if (errors.length > 0) {
return new AggregateError(
errors.map((result) => result[2] as UpdateResultError),
);
// HACK: Cast to Any
return new AggregateError(errors) as any;
}
return {
isError: false,
type: "aggregateSuccess",
results: results
.map((result) => result[2])
.filter(
(result): result is ResourceResult<UpdateSuccess, Leaf> =>
result.type === "updateSuccess" ||
result.type === "updateDefaultGraphSuccess" ||
result.type === "ignoredInvalidUpdateSuccess",
),
// HACK: Cast to Any
results: results.map((result) => result[2]) as any,
};
}
}

@ -10,9 +10,12 @@ export interface ConnectedPlugin<
ContextType = any,
> {
name: Name;
getResource(uri: UriType, context: ConnectedContext<this[]>): ResourceType;
getResource(
uri: UriType,
context: ConnectedContext<ConnectedPlugin[]>,
): ResourceType;
createResource(
context: ConnectedContext<this[]>,
context: ConnectedContext<ConnectedPlugin[]>,
): Promise<ResourceType | ErrorResult>;
isUriValid(uri: UriType): uri is UriType;
normalizeUri?: (uri: UriType) => UriType;

@ -0,0 +1,5 @@
import type { GraphNode, DatasetChanges } from "@ldo/rdf-utils";
import type { Quad } from "@rdfjs/types";
export declare function graphNodeToString(graphNode: GraphNode): string;
export declare function stringToGraphNode(input: string): GraphNode;
export declare function splitChangesByGraph(changes: DatasetChanges<Quad>): Map<GraphNode, DatasetChanges<Quad>>;

@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitChangesByGraph = exports.stringToGraphNode = exports.graphNodeToString = void 0;
const dataset_1 = require("@ldo/dataset");
const data_model_1 = require("@rdfjs/data-model");
function graphNodeToString(graphNode) {
return graphNode.termType === "DefaultGraph"
? "defaultGraph()"
: graphNode.value;
}
exports.graphNodeToString = graphNodeToString;
function stringToGraphNode(input) {
return input === "defaultGraph()" ? (0, data_model_1.defaultGraph)() : (0, data_model_1.namedNode)(input);
}
exports.stringToGraphNode = stringToGraphNode;
function splitChangesByGraph(changes) {
const changesMap = {};
changes.added?.forEach((quad) => {
const graphHash = graphNodeToString(quad.graph);
if (!changesMap[graphHash]) {
changesMap[graphHash] = {};
}
if (!changesMap[graphHash].added) {
changesMap[graphHash].added = (0, dataset_1.createDataset)();
}
changesMap[graphHash].added?.add((0, data_model_1.quad)(quad.subject, quad.predicate, quad.object, quad.graph));
});
changes.removed?.forEach((quad) => {
const graphHash = graphNodeToString(quad.graph);
if (!changesMap[graphHash]) {
changesMap[graphHash] = {};
}
if (!changesMap[graphHash].removed) {
changesMap[graphHash].removed = (0, dataset_1.createDataset)();
}
changesMap[graphHash].removed?.add((0, data_model_1.quad)(quad.subject, quad.predicate, quad.object, quad.graph));
});
const finalMap = new Map();
Object.entries(changesMap).forEach(([key, value]) => {
finalMap.set(stringToGraphNode(key), value);
});
return finalMap;
}
exports.splitChangesByGraph = splitChangesByGraph;
//# sourceMappingURL=splitChangesByGraph.js.map

@ -0,0 +1 @@
{"version":3,"file":"splitChangesByGraph.js","sourceRoot":"","sources":["splitChangesByGraph.ts"],"names":[],"mappings":";;;AAAA,0CAA6C;AAG7C,kDAAgF;AAQhF,SAAgB,iBAAiB,CAAC,SAAoB;IACpD,OAAO,SAAS,CAAC,QAAQ,KAAK,cAAc;QAC1C,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC;AACtB,CAAC;AAJD,8CAIC;AAQD,SAAgB,iBAAiB,CAAC,KAAa;IAC7C,OAAO,KAAK,KAAK,gBAAgB,CAAC,CAAC,CAAC,IAAA,yBAAY,GAAE,CAAC,CAAC,CAAC,IAAA,sBAAS,EAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAFD,8CAEC;AASD,SAAgB,mBAAmB,CACjC,OAA6B;IAE7B,MAAM,UAAU,GAAyC,EAAE,CAAC;IAC5D,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAkB,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YAC1B,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;SAC5B;QACD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE;YAChC,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,GAAG,IAAA,uBAAa,GAAE,CAAC;SAC/C;QACD,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,GAAG,CAC9B,IAAA,iBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAClE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAkB,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YAC1B,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;SAC5B;QACD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;YAClC,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,GAAG,IAAA,uBAAa,GAAE,CAAC;SACjD;QACD,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,CAChC,IAAA,iBAAU,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAClE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC5D,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QAClD,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAnCD,kDAmCC"}

@ -1,12 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import EventEmitter from "events";
import type { ResourceError } from "../src";
import {
Unfetched,
type ConnectedResult,
type Resource,
type ResourceEventEmitter,
type ResourceResult,
} from "../src";
import type { DatasetChanges } from "@ldo/rdf-utils";
import type { ReadSuccess } from "../src/results/success/ReadSuccess";
import type { UpdateSuccess } from "../src/results/success/UpdateSuccess";
export class MockResouce
extends (EventEmitter as new () => ResourceEventEmitter)
@ -44,10 +47,15 @@ export class MockResouce
isSubscribedToNotifications(): boolean {
throw new Error("Method not implemented.");
}
read(): Promise<ResourceResult<any>> {
read(): Promise<ReadSuccess<any> | ResourceError<any>> {
throw new Error("Method not implemented.");
}
readIfAbsent(): Promise<ResourceResult<any>> {
readIfAbsent(): Promise<ReadSuccess<any> | ResourceError<any>> {
throw new Error("Method not implemented.");
}
update(
_datasetChanges: DatasetChanges,
): Promise<UpdateSuccess<any> | ResourceError<any>> {
throw new Error("Method not implemented.");
}
subscribeToNotifications(_callbacks?: {

@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"outDir": "./dist"
},
"include": ["./src"]
"include": ["./src"],
"exclude": ["./dist", "./coverage"]
}
Loading…
Cancel
Save