From 5a9cd3660f72c2bfd0ab4ca53425d34ad3affca0 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Wed, 14 Feb 2024 23:36:41 -0500 Subject: [PATCH 01/10] transactionDataset readability refactor --- packages/ldo/src/LdoDatasetFactory.ts | 2 +- packages/ldo/src/LdoTransactionalDataset.ts | 23 +++++++++ ...bableDataset.ts => SubscribableDataset.ts} | 28 ++++++----- .../src/SubscribableDatasetFactory.ts | 31 ++++++++++++ ...tionalDataset.ts => TransactionDataset.ts} | 43 ++++++----------- .../src/TransactionDatasetFactory.ts | 27 +++++++++++ .../src/WrapperSubscribableDatasetFactory.ts | 27 ----------- .../src/createSubscribableDataset.ts | 46 ++++++++++++++++++ ...SubscribableDatasetFromSerializedInput.ts} | 10 ++-- .../src/createWrapperSubscribableDataset.ts | 30 ------------ packages/subscribable-dataset/src/index.ts | 14 +++--- packages/subscribable-dataset/src/types.ts | 47 ++++++++++++++----- ...et.test.ts => SubscribableDataset.test.ts} | 11 ++--- ...t.test.ts => TransactionalDataset.test.ts} | 27 ++++++----- ...ribableDatasetFromSerializedInput.test.ts} | 0 .../subscribable-dataset/test/index.test.ts | 14 +++--- 16 files changed, 235 insertions(+), 145 deletions(-) create mode 100644 packages/ldo/src/LdoTransactionalDataset.ts rename packages/subscribable-dataset/src/{WrapperSubscribableDataset.ts => SubscribableDataset.ts} (95%) create mode 100644 packages/subscribable-dataset/src/SubscribableDatasetFactory.ts rename packages/subscribable-dataset/src/{ProxyTransactionalDataset.ts => TransactionDataset.ts} (87%) create mode 100644 packages/subscribable-dataset/src/TransactionDatasetFactory.ts delete mode 100644 packages/subscribable-dataset/src/WrapperSubscribableDatasetFactory.ts create mode 100644 packages/subscribable-dataset/src/createSubscribableDataset.ts rename packages/subscribable-dataset/src/{createWrapperSubscribableDatasetFromSerializedInput.ts => createSubscribableDatasetFromSerializedInput.ts} (67%) delete mode 100644 packages/subscribable-dataset/src/createWrapperSubscribableDataset.ts rename packages/subscribable-dataset/test/{WrapperSubscribableDataset.test.ts => SubscribableDataset.test.ts} (97%) rename packages/subscribable-dataset/test/{ProxyTransactionalDataset.test.ts => TransactionalDataset.test.ts} (94%) rename packages/subscribable-dataset/test/{createWrapperSubscribableDatasetFromSerializedInput.test.ts => createSubscribableDatasetFromSerializedInput.test.ts} (100%) diff --git a/packages/ldo/src/LdoDatasetFactory.ts b/packages/ldo/src/LdoDatasetFactory.ts index 9b6e335..b0150b2 100644 --- a/packages/ldo/src/LdoDatasetFactory.ts +++ b/packages/ldo/src/LdoDatasetFactory.ts @@ -34,7 +34,7 @@ export class LdoDatasetFactory implements DatasetFactory { */ dataset(quads?: Dataset | Quad[]): LdoDataset { return new LdoDataset( - this.datasetFactory, + this, quads ? Array.isArray(quads) ? this.datasetFactory.dataset(quads) diff --git a/packages/ldo/src/LdoTransactionalDataset.ts b/packages/ldo/src/LdoTransactionalDataset.ts new file mode 100644 index 0000000..38baf93 --- /dev/null +++ b/packages/ldo/src/LdoTransactionalDataset.ts @@ -0,0 +1,23 @@ +import type { TransactionalDataset } from "@ldo/subscribable-dataset"; +import { LdoDataset } from "../dist/LdoDataset"; +import type { Quad } from "@rdfjs/types"; +import type { DatasetChanges } from "@ldo/rdf-utils"; + +export class LdoTransactionalDataset + extends LdoDataset + implements TransactionalDataset +{ + constructor() { + + } + + rollback(): void { + throw new Error("Method not implemented."); + } + commit(): void { + throw new Error("Method not implemented."); + } + getChanges(): DatasetChanges { + throw new Error("Method not implemented."); + } +} diff --git a/packages/subscribable-dataset/src/WrapperSubscribableDataset.ts b/packages/subscribable-dataset/src/SubscribableDataset.ts similarity index 95% rename from packages/subscribable-dataset/src/WrapperSubscribableDataset.ts rename to packages/subscribable-dataset/src/SubscribableDataset.ts index a2d0ee5..b2d7db1 100644 --- a/packages/subscribable-dataset/src/WrapperSubscribableDataset.ts +++ b/packages/subscribable-dataset/src/SubscribableDataset.ts @@ -17,31 +17,34 @@ import type { } from "@rdfjs/types"; import type { nodeEventListener, - SubscribableDataset, - TransactionalDataset, + ISubscribableDataset, + ITransactionDataset, + ITransactionDatasetFactory, } from "./types"; -import { ProxyTransactionalDataset } from "./ProxyTransactionalDataset"; /** * A wrapper for a dataset that allows subscriptions to be made on nodes to * be triggered whenever a quad containing that added or removed. */ -export class WrapperSubscribableDataset< - InAndOutQuad extends BaseQuad = BaseQuad, -> implements SubscribableDataset +export class SubscribableDataset + implements ISubscribableDataset { /** * The underlying dataset factory */ - private datasetFactory: DatasetFactory; + protected datasetFactory: DatasetFactory; /** * The underlying dataset */ - private dataset: Dataset; + protected dataset: Dataset; /** * The underlying event emitter */ - private eventEmitter: EventEmitter; + protected eventEmitter: EventEmitter; + /** + * The underlying dataset factory for creating transaction datasets + */ + protected transactionDatasetFactory: ITransactionDatasetFactory; /** * Helps find all the events for a given listener */ @@ -54,9 +57,11 @@ export class WrapperSubscribableDataset< */ constructor( datasetFactory: DatasetFactory, + transactionDatasetFactory: ITransactionDatasetFactory, initialDataset?: Dataset, ) { this.datasetFactory = datasetFactory; + this.transactionDatasetFactory = transactionDatasetFactory; this.dataset = initialDataset || this.datasetFactory.dataset(); this.eventEmitter = new EventEmitter(); } @@ -249,6 +254,7 @@ export class WrapperSubscribableDataset< * Note: Since a DatasetCore is an unordered set, the order of the quads within the returned sequence is arbitrary. */ public toArray(): InAndOutQuad[] { + console.log("Calling toArray"); return this.dataset.toArray(); } @@ -609,7 +615,7 @@ export class WrapperSubscribableDataset< /** * Returns a transactional dataset that will update this dataset when its transaction is committed. */ - public startTransaction(): TransactionalDataset { - return new ProxyTransactionalDataset(this, this.datasetFactory); + public startTransaction(): ITransactionDataset { + return this.transactionDatasetFactory.transactionDataset(this); } } diff --git a/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts b/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts new file mode 100644 index 0000000..483ee06 --- /dev/null +++ b/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts @@ -0,0 +1,31 @@ +import type { DatasetFactory, BaseQuad, Dataset } from "@rdfjs/types"; +import type { ITransactionDatasetFactory } from "./types"; +import { SubscribableDataset } from "./SubscribableDataset"; + +/** + * A DatasetFactory that returns a SubscribableDataset given a generic DatasetFactory. + */ +export class SubscribableDatasetFactory< + InAndOutQuad extends BaseQuad = BaseQuad, +> implements DatasetFactory +{ + private datasetFactory: DatasetFactory; + private transactionDatasetFactory: ITransactionDatasetFactory; + constructor( + datasetFactory: DatasetFactory, + transactionDatasetFactory: ITransactionDatasetFactory, + ) { + this.datasetFactory = datasetFactory; + this.transactionDatasetFactory = transactionDatasetFactory; + } + + dataset( + quads?: Dataset | InAndOutQuad[], + ): SubscribableDataset { + return new SubscribableDataset( + this.datasetFactory, + this.transactionDatasetFactory, + quads ? this.datasetFactory.dataset(quads) : undefined, + ); + } +} diff --git a/packages/subscribable-dataset/src/ProxyTransactionalDataset.ts b/packages/subscribable-dataset/src/TransactionDataset.ts similarity index 87% rename from packages/subscribable-dataset/src/ProxyTransactionalDataset.ts rename to packages/subscribable-dataset/src/TransactionDataset.ts index 6e7a66d..875ad6f 100644 --- a/packages/subscribable-dataset/src/ProxyTransactionalDataset.ts +++ b/packages/subscribable-dataset/src/TransactionDataset.ts @@ -1,27 +1,26 @@ import type { Dataset, BaseQuad, Term, DatasetFactory } from "@rdfjs/types"; import type { DatasetChanges } from "@ldo/rdf-utils"; -import type { BulkEditableDataset, TransactionalDataset } from "./types"; -import { ExtendedDataset } from "@ldo/dataset"; +import type { + ISubscribableDataset, + ITransactionDataset, + ITransactionDatasetFactory, +} from "./types"; import { mergeDatasetChanges } from "./mergeDatasetChanges"; +import { SubscribableDataset } from "./SubscribableDataset"; /** * Proxy Transactional Dataset is a transactional dataset that does not duplicate * the parent dataset, it will dynamically determine the correct return value for * methods in real time when the method is called. */ -export class ProxyTransactionalDataset - extends ExtendedDataset - implements TransactionalDataset +export class TransactionDataset + extends SubscribableDataset + implements ITransactionDataset { /** * The parent dataset that will be updated upon commit */ - private parentDataset: Dataset; - - /** - * A factory for creating new datasets to be added to the update method - */ - private datasetFactory: DatasetFactory; + public readonly parentDataset: ISubscribableDataset; /** * The changes made that are ready to commit @@ -42,12 +41,12 @@ export class ProxyTransactionalDataset * @param parentDataset The dataset that will be updated upon commit */ constructor( - parentDataset: Dataset, + parentDataset: ISubscribableDataset, datasetFactory: DatasetFactory, + transactionDatasetFactory: ITransactionDatasetFactory, ) { - super(datasetFactory.dataset(), datasetFactory); + super(datasetFactory, transactionDatasetFactory, datasetFactory.dataset()); this.parentDataset = parentDataset; - this.datasetFactory = datasetFactory; this.datasetChanges = {}; } @@ -179,6 +178,7 @@ export class ProxyTransactionalDataset * Returns an iterator */ public [Symbol.iterator](): Iterator { + console.log("Getting Iterator"); const addedIterator = (this.datasetChanges.added || [])[Symbol.iterator](); let addedNext = addedIterator.next(); const parentIterator = this.parentDataset[Symbol.iterator](); @@ -253,9 +253,7 @@ export class ProxyTransactionalDataset private updateParentDataset(datasetChanges: DatasetChanges) { // eslint-disable-next-line @typescript-eslint/no-explicit-any if ((this.parentDataset as any).bulk) { - (this.parentDataset as BulkEditableDataset).bulk( - datasetChanges, - ); + this.parentDataset.bulk(datasetChanges); } else { if (datasetChanges.added) { this.parentDataset.addAll(datasetChanges.added); @@ -296,17 +294,6 @@ export class ProxyTransactionalDataset this.committedDatasetChanges = undefined; } - /** - * Starts a new transaction with this transactional dataset as the parent - * @returns - */ - public startTransaction(): TransactionalDataset { - // This is caused by the typings being incorrect for the intersect method - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return new ProxyTransactionalDataset(this, this.datasetFactory); - } - public getChanges(): DatasetChanges { return this.datasetChanges; } diff --git a/packages/subscribable-dataset/src/TransactionDatasetFactory.ts b/packages/subscribable-dataset/src/TransactionDatasetFactory.ts new file mode 100644 index 0000000..86ebfac --- /dev/null +++ b/packages/subscribable-dataset/src/TransactionDatasetFactory.ts @@ -0,0 +1,27 @@ +import type { BaseQuad, DatasetFactory } from "@rdfjs/types"; +import type { ISubscribableDataset, ITransactionDatasetFactory } from "./types"; +import { TransactionDataset } from "./TransactionDataset"; + +export class TransactionDatasetFactory + implements ITransactionDatasetFactory +{ + private datasetFactory: DatasetFactory; + private transactionDatasetFactory: ITransactionDatasetFactory; + constructor( + datasetFactory: DatasetFactory, + transactionDatasetFactory?: ITransactionDatasetFactory, + ) { + this.datasetFactory = datasetFactory; + this.transactionDatasetFactory = transactionDatasetFactory || this; + } + + transactionDataset( + parentDataset: ISubscribableDataset, + ): TransactionDataset { + return new TransactionDataset( + parentDataset, + this.datasetFactory, + this.transactionDatasetFactory, + ); + } +} diff --git a/packages/subscribable-dataset/src/WrapperSubscribableDatasetFactory.ts b/packages/subscribable-dataset/src/WrapperSubscribableDatasetFactory.ts deleted file mode 100644 index b3d1757..0000000 --- a/packages/subscribable-dataset/src/WrapperSubscribableDatasetFactory.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { DatasetFactory, BaseQuad, Dataset } from "@rdfjs/types"; -import { WrapperSubscribableDataset } from "./WrapperSubscribableDataset"; - -/** - * A DatasetFactory that returns a WrapperSubscribableDataset given a generic DatasetFactory. - */ -export class WrapperSubscribableDatasetFactory< - InAndOutQuad extends BaseQuad = BaseQuad, -> implements DatasetFactory -{ - private datasetFactory: DatasetFactory; - constructor(datasetFactory: DatasetFactory) { - this.datasetFactory = datasetFactory; - } - - dataset( - quads?: Dataset | InAndOutQuad[], - ): WrapperSubscribableDataset { - // Typings are wrong - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return new WrapperSubscribableDataset( - this.datasetFactory, - quads ? this.datasetFactory.dataset(quads) : undefined, - ); - } -} diff --git a/packages/subscribable-dataset/src/createSubscribableDataset.ts b/packages/subscribable-dataset/src/createSubscribableDataset.ts new file mode 100644 index 0000000..186a7e7 --- /dev/null +++ b/packages/subscribable-dataset/src/createSubscribableDataset.ts @@ -0,0 +1,46 @@ +import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; +import { createDataset } from "@ldo/dataset"; +import { SubscribableDatasetFactory } from "./SubscribableDatasetFactory"; +import type { + ISubscribableDataset, + ISubscribableDatasetFactory, + ITransactionDatasetFactory, +} from "./types"; +import { TransactionDatasetFactory } from "./TransactionDatasetFactory"; + +const datasetFactory: DatasetFactory = { + dataset: (quads?: Dataset | Quad[]): Dataset => { + return createDataset(quads); + }, +}; + +/** + * Creates a factory that generates TransactionDatasets + * @returns TransactionDatasetFactory + */ +export function createTransactionDatasetFactory(): ITransactionDatasetFactory { + return new TransactionDatasetFactory(datasetFactory); +} + +/** + * Creates a dataset factory that generates a SubscribableDataset + * @returns DatasetFactory for SubscribableDataset + */ +export function createSubscribableDatasetFactory(): ISubscribableDatasetFactory { + return new SubscribableDatasetFactory( + datasetFactory, + createTransactionDatasetFactory(), + ); +} + +/** + * Creates a SubscribableDataset + * @param quads: A dataset or array of Quads to initialize the dataset. + * @returns Dataset + */ +export function createSubscribableDataset( + quads?: Dataset | Quad[], +): ISubscribableDataset { + const subscribableDatasetFactory = createSubscribableDatasetFactory(); + return subscribableDatasetFactory.dataset(quads); +} diff --git a/packages/subscribable-dataset/src/createWrapperSubscribableDatasetFromSerializedInput.ts b/packages/subscribable-dataset/src/createSubscribableDatasetFromSerializedInput.ts similarity index 67% rename from packages/subscribable-dataset/src/createWrapperSubscribableDatasetFromSerializedInput.ts rename to packages/subscribable-dataset/src/createSubscribableDatasetFromSerializedInput.ts index dd3c511..bed692a 100644 --- a/packages/subscribable-dataset/src/createWrapperSubscribableDatasetFromSerializedInput.ts +++ b/packages/subscribable-dataset/src/createSubscribableDatasetFromSerializedInput.ts @@ -1,8 +1,8 @@ import type { Quad } from "@rdfjs/types"; import type { ParserOptions } from "@ldo/rdf-utils"; import { createDatasetFromSerializedInput } from "@ldo/dataset"; -import { createWrapperSubscribableDatasetFactory } from "./createWrapperSubscribableDataset"; -import type { WrapperSubscribableDataset } from "./WrapperSubscribableDataset"; +import { createSubscribableDatasetFactory } from "./createSubscribableDataset"; +import type { ISubscribableDataset } from "./types"; /** * Creates a SubscribableDataset with a string input that could be JSON-LD, Turtle, N-Triples, TriG, RDF*, or N3. @@ -18,9 +18,9 @@ import type { WrapperSubscribableDataset } from "./WrapperSubscribableDataset"; export async function createWrapperSubscribableDatasetFromSerializedInput( data: string, options?: ParserOptions, -): Promise> { - const datasetFactory = createWrapperSubscribableDatasetFactory(); - return createDatasetFromSerializedInput>( +): Promise> { + const datasetFactory = createSubscribableDatasetFactory(); + return createDatasetFromSerializedInput>( datasetFactory, data, options, diff --git a/packages/subscribable-dataset/src/createWrapperSubscribableDataset.ts b/packages/subscribable-dataset/src/createWrapperSubscribableDataset.ts deleted file mode 100644 index df7af0d..0000000 --- a/packages/subscribable-dataset/src/createWrapperSubscribableDataset.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; -import type { WrapperSubscribableDataset } from "./WrapperSubscribableDataset"; -import { createDataset } from "@ldo/dataset"; -import { WrapperSubscribableDatasetFactory } from "./WrapperSubscribableDatasetFactory"; - -/** - * Creates a dataset factory that generates a SubscribableDataset - * @returns DatasetFactory for SubscribableDataset - */ -export function createWrapperSubscribableDatasetFactory(): WrapperSubscribableDatasetFactory { - const datasetFactory: DatasetFactory = { - dataset: (quads?: Dataset | Quad[]): Dataset => { - return createDataset(quads); - }, - }; - return new WrapperSubscribableDatasetFactory(datasetFactory); -} - -/** - * Creates a SubscribableDataset - * @param quads: A dataset or array of Quads to initialize the dataset. - * @returns Dataset - */ -export function createWrapperSubscribableDataset( - quads?: Dataset | Quad[], -): WrapperSubscribableDataset { - const wrapperSubscribableDatasetFactory = - createWrapperSubscribableDatasetFactory(); - return wrapperSubscribableDatasetFactory.dataset(quads); -} diff --git a/packages/subscribable-dataset/src/index.ts b/packages/subscribable-dataset/src/index.ts index d4ecf2f..071e05d 100644 --- a/packages/subscribable-dataset/src/index.ts +++ b/packages/subscribable-dataset/src/index.ts @@ -1,10 +1,8 @@ -export { - createWrapperSubscribableDataset as createSubscribableDataset, - createWrapperSubscribableDatasetFactory as createSubscribableDatasetFactory, -} from "./createWrapperSubscribableDataset"; -export { createWrapperSubscribableDatasetFromSerializedInput as serializedToSubscribableDataset } from "./createWrapperSubscribableDatasetFromSerializedInput"; -export * from "./ProxyTransactionalDataset"; -export * from "./WrapperSubscribableDataset"; -export * from "./WrapperSubscribableDatasetFactory"; +export * from "./createSubscribableDataset"; +export { createWrapperSubscribableDatasetFromSerializedInput as serializedToSubscribableDataset } from "./createSubscribableDatasetFromSerializedInput"; +export * from "./TransactionDataset"; +export * from "./TransactionDatasetFactory"; +export * from "./SubscribableDataset"; +export * from "./SubscribableDatasetFactory"; export * from "./types"; export * from "./mergeDatasetChanges"; diff --git a/packages/subscribable-dataset/src/types.ts b/packages/subscribable-dataset/src/types.ts index 4987642..41f2de7 100644 --- a/packages/subscribable-dataset/src/types.ts +++ b/packages/subscribable-dataset/src/types.ts @@ -1,5 +1,5 @@ import type { DatasetChanges, QuadMatch } from "@ldo/rdf-utils"; -import type { Dataset, BaseQuad } from "@rdfjs/types"; +import type { Dataset, BaseQuad, DatasetFactory } from "@rdfjs/types"; /** * An event listeners for nodes @@ -11,28 +11,29 @@ export type nodeEventListener = ( /** * Adds the bulk method for add and remove */ -export interface BulkEditableDataset +export interface IBulkEditableDataset extends Dataset { bulk(changes: DatasetChanges): this; } /** - * A dataset that allows you to modify the dataset and + * Factory for creating SubscribableDatasets */ -export interface TransactionalDataset - extends BulkEditableDataset { - rollback(): void; - commit(): void; - getChanges(): DatasetChanges; -} +export type ISubscribableDatasetFactory< + InAndOutQuad extends BaseQuad = BaseQuad, +> = DatasetFactory< + InAndOutQuad, + InAndOutQuad, + ISubscribableDataset +>; /** * Dataset that allows developers to subscribe to a sepecific term and be alerted * if a quad is added or removed containing that term. It's methods follow the * EventEmitter interface except take in namedNodes as keys. */ -export interface SubscribableDataset - extends BulkEditableDataset { +export interface ISubscribableDataset + extends IBulkEditableDataset { /** * Alias for emitter.on(eventName, listener). * @param eventName @@ -140,5 +141,27 @@ export interface SubscribableDataset /** * Returns a transactional dataset that will update this dataset when its transaction is committed. */ - startTransaction(): TransactionalDataset; + startTransaction(): ITransactionDataset; +} + +/** + * Creates a TransactionDataset + */ +export interface ITransactionDatasetFactory< + InAndOutQuad extends BaseQuad = BaseQuad, +> { + transactionDataset( + parent: ISubscribableDataset, + ): ITransactionDataset; +} + +/** + * A dataset that allows you to modify the dataset and + */ +export interface ITransactionDataset + extends ISubscribableDataset { + readonly parentDataset: ISubscribableDataset; + rollback(): void; + commit(): void; + getChanges(): DatasetChanges; } diff --git a/packages/subscribable-dataset/test/WrapperSubscribableDataset.test.ts b/packages/subscribable-dataset/test/SubscribableDataset.test.ts similarity index 97% rename from packages/subscribable-dataset/test/WrapperSubscribableDataset.test.ts rename to packages/subscribable-dataset/test/SubscribableDataset.test.ts index c8e91b4..84a707d 100644 --- a/packages/subscribable-dataset/test/WrapperSubscribableDataset.test.ts +++ b/packages/subscribable-dataset/test/SubscribableDataset.test.ts @@ -1,5 +1,5 @@ -import type { SubscribableDataset } from "../src"; -import { ProxyTransactionalDataset, createSubscribableDataset } from "../src"; +import type { ISubscribableDataset } from "../src"; +import { TransactionDataset, createSubscribableDataset } from "../src"; import { createDataset } from "@ldo/dataset"; import { namedNode, @@ -11,14 +11,14 @@ import { import type { Quad, BlankNode } from "@rdfjs/types"; import testDataset from "@ldo/dataset/test/dataset.testHelper"; -describe("WrapperSubscribableDataset", () => { +describe("SubscribableDataset", () => { // Regular dataset tests testDataset({ dataset: createSubscribableDataset, }); // Subscribable Dataset tests - let subscribableDatastet: SubscribableDataset; + let subscribableDatastet: ISubscribableDataset; const tomTypeQuad = quad( namedNode("http://example.org/cartoons#Tom"), namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), @@ -449,8 +449,7 @@ describe("WrapperSubscribableDataset", () => { it("Returns a transaction", () => { expect( - subscribableDatastet.startTransaction() instanceof - ProxyTransactionalDataset, + subscribableDatastet.startTransaction() instanceof TransactionDataset, ).toBe(true); }); }); diff --git a/packages/subscribable-dataset/test/ProxyTransactionalDataset.test.ts b/packages/subscribable-dataset/test/TransactionalDataset.test.ts similarity index 94% rename from packages/subscribable-dataset/test/ProxyTransactionalDataset.test.ts rename to packages/subscribable-dataset/test/TransactionalDataset.test.ts index bc380be..30c0dbf 100644 --- a/packages/subscribable-dataset/test/ProxyTransactionalDataset.test.ts +++ b/packages/subscribable-dataset/test/TransactionalDataset.test.ts @@ -5,14 +5,18 @@ import type { Quad, DatasetCore, } from "@rdfjs/types"; -import type { BulkEditableDataset } from "../src"; +import type { ISubscribableDataset } from "../src"; import { ExtendedDatasetFactory } from "@ldo/dataset"; -import { ProxyTransactionalDataset } from "../src"; +import { + TransactionDataset, + createSubscribableDataset, + createTransactionDatasetFactory, +} from "../src"; import datasetCoreFactory from "@rdfjs/dataset"; -describe("ProxyTransactionalDataset", () => { - let parentDataset: Dataset; - let transactionalDataset: ProxyTransactionalDataset; +describe("TransactionDataset", () => { + let parentDataset: ISubscribableDataset; + let transactionalDataset: TransactionDataset; const tomTypeQuad = quad( namedNode("http://example.org/cartoons#Tom"), namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), @@ -41,12 +45,13 @@ describe("ProxyTransactionalDataset", () => { const extendedDatasetFactory = new ExtendedDatasetFactory(datasetFactory); const initializeWithExtendedDatasetParent = (quads?: Quad[]) => { - parentDataset = extendedDatasetFactory.dataset( + parentDataset = createSubscribableDataset( quads || [tomTypeQuad, tomNameQuad], ); - transactionalDataset = new ProxyTransactionalDataset( + transactionalDataset = new TransactionDataset( parentDataset, extendedDatasetFactory, + createTransactionDatasetFactory(), ); }; @@ -301,14 +306,15 @@ describe("ProxyTransactionalDataset", () => { // Disable for tests // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - const mockParent: BulkEditableDataset = { + const mockParent: ISubscribableDataset = { bulk: jest.fn(), has: (curQuad) => parentDataset.has(curQuad), [Symbol.iterator]: () => parentDataset[Symbol.iterator](), }; - transactionalDataset = new ProxyTransactionalDataset( + transactionalDataset = new TransactionDataset( mockParent, extendedDatasetFactory, + createTransactionDatasetFactory(), ); transactionalDataset.add(lickyNameQuad); @@ -319,8 +325,7 @@ describe("ProxyTransactionalDataset", () => { it("Returns a transactional dataset", () => { expect( - transactionalDataset.startTransaction() instanceof - ProxyTransactionalDataset, + transactionalDataset.startTransaction() instanceof TransactionDataset, ).toBe(true); }); diff --git a/packages/subscribable-dataset/test/createWrapperSubscribableDatasetFromSerializedInput.test.ts b/packages/subscribable-dataset/test/createSubscribableDatasetFromSerializedInput.test.ts similarity index 100% rename from packages/subscribable-dataset/test/createWrapperSubscribableDatasetFromSerializedInput.test.ts rename to packages/subscribable-dataset/test/createSubscribableDatasetFromSerializedInput.test.ts diff --git a/packages/subscribable-dataset/test/index.test.ts b/packages/subscribable-dataset/test/index.test.ts index 493e1ac..dd48974 100644 --- a/packages/subscribable-dataset/test/index.test.ts +++ b/packages/subscribable-dataset/test/index.test.ts @@ -2,17 +2,19 @@ import { createSubscribableDataset, createSubscribableDatasetFactory, serializedToSubscribableDataset, - ProxyTransactionalDataset, - WrapperSubscribableDataset, - WrapperSubscribableDatasetFactory, + SubscribableDataset, + SubscribableDatasetFactory, + TransactionDataset, + TransactionDatasetFactory, } from "../src"; describe("Exports", () => { it("Has all exports", () => { expect(createSubscribableDataset); - expect(ProxyTransactionalDataset); - expect(WrapperSubscribableDataset); - expect(WrapperSubscribableDatasetFactory); + expect(SubscribableDataset); + expect(TransactionDataset); + expect(SubscribableDatasetFactory); + expect(TransactionDatasetFactory); expect(serializedToSubscribableDataset); expect(createSubscribableDatasetFactory); }); From 744603bef6568a0c21d67d830b12c4fcda67da28 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Thu, 15 Feb 2024 00:05:57 -0500 Subject: [PATCH 02/10] Completed Subscribable Dataset refactor --- .../src/SubscribableDataset.ts | 251 ++---------------- .../src/TransactionDataset.ts | 15 +- 2 files changed, 28 insertions(+), 238 deletions(-) diff --git a/packages/subscribable-dataset/src/SubscribableDataset.ts b/packages/subscribable-dataset/src/SubscribableDataset.ts index b2d7db1..c2f99dd 100644 --- a/packages/subscribable-dataset/src/SubscribableDataset.ts +++ b/packages/subscribable-dataset/src/SubscribableDataset.ts @@ -8,35 +8,28 @@ import type { ObjectNode, GraphNode, } from "@ldo/rdf-utils"; -import type { - Dataset, - BaseQuad, - Stream, - Term, - DatasetFactory, -} from "@rdfjs/types"; +import type { Dataset, BaseQuad, Term, DatasetFactory } from "@rdfjs/types"; import type { nodeEventListener, ISubscribableDataset, ITransactionDataset, ITransactionDatasetFactory, } from "./types"; +import { ExtendedDataset } from "@ldo/dataset"; /** * A wrapper for a dataset that allows subscriptions to be made on nodes to * be triggered whenever a quad containing that added or removed. */ export class SubscribableDataset + extends ExtendedDataset implements ISubscribableDataset { /** - * The underlying dataset factory - */ - protected datasetFactory: DatasetFactory; - /** - * The underlying dataset + * DatasetFactory for creating new datasets */ - protected dataset: Dataset; + protected datasetFactory: DatasetFactory; + /** * The underlying event emitter */ @@ -60,10 +53,10 @@ export class SubscribableDataset transactionDatasetFactory: ITransactionDatasetFactory, initialDataset?: Dataset, ) { - this.datasetFactory = datasetFactory; + super(initialDataset || datasetFactory.dataset(), datasetFactory); this.transactionDatasetFactory = transactionDatasetFactory; - this.dataset = initialDataset || this.datasetFactory.dataset(); this.eventEmitter = new EventEmitter(); + this.datasetFactory = datasetFactory; } /** @@ -72,6 +65,18 @@ export class SubscribableDataset * ================================================================== */ + /** + * A helper method that mimics what the super of addAll would be + */ + private superAddAll( + quads: Dataset | InAndOutQuad[], + ): this { + for (const quad of quads) { + super.add(quad); + } + return this; + } + /** * Imports the quads into this dataset. * This method differs from Dataset.union in that it adds all quads to the current instance, rather than combining quads and the current instance to create a new instance. @@ -81,7 +86,7 @@ export class SubscribableDataset public addAll( quads: Dataset | InAndOutQuad[], ): this { - this.dataset.addAll(quads); + this.superAddAll(quads); this.triggerSubscriptionForQuads({ added: this.datasetFactory.dataset(quads), }); @@ -94,26 +99,17 @@ export class SubscribableDataset */ public bulk(changed: DatasetChanges): this { if (changed.added) { - this.dataset.addAll(changed.added); + this.superAddAll(changed.added); } if (changed.removed) { changed.removed.forEach((quad) => { - this.dataset.delete(quad); + super.delete(quad); }); } this.triggerSubscriptionForQuads(changed); return this; } - /** - * Returns true if the current instance is a superset of the given dataset; differently put: if the given dataset is a subset of, is contained in the current dataset. - * Blank Nodes will be normalized. - * @param other - */ - public contains(other: Dataset): boolean { - return this.dataset.contains(other); - } - /** * This method removes the quads in the current instance that match the given arguments. The logic described in Quad Matching is applied for each quad in this dataset to select the quads which will be deleted. * @param subject @@ -128,192 +124,14 @@ export class SubscribableDataset object?: Term, graph?: Term, ): this { - const matching = this.dataset.match(subject, predicate, object, graph); + const matching = super.match(subject, predicate, object, graph); for (const quad of matching) { - this.dataset.delete(quad); + super.delete(quad); } this.triggerSubscriptionForQuads({ removed: matching }); return this; } - /** - * Returns a new dataset that contains alls quads from the current dataset, not included in the given dataset. - * @param other - */ - public difference( - other: Dataset, - ): Dataset { - return this.dataset.difference(other); - } - - /** - * Returns true if the current instance contains the same graph structure as the given dataset. - * @param other - */ - public equals(other: Dataset): boolean { - return this.dataset.equals(other); - } - - /** - * Universal quantification method, tests whether every quad in the dataset passes the test implemented by the provided iteratee. - * This method immediately returns boolean false once a quad that does not pass the test is found. - * This method always returns boolean true on an empty dataset. - * Note: This method is aligned with Array.prototype.every() in ECMAScript-262. - * @param iteratee - */ - public every( - iteratee: (quad: InAndOutQuad, dataset: this) => boolean, - ): boolean { - return this.dataset.every((quad) => iteratee(quad, this)); - } - - /** - * Creates a new dataset with all the quads that pass the test implemented by the provided iteratee. - * Note: This method is aligned with Array.prototype.filter() in ECMAScript-262. - * @param iteratee - */ - public filter( - iteratee: (quad: InAndOutQuad, dataset: this) => boolean, - ): Dataset { - return this.dataset.filter((quad) => iteratee(quad, this)); - } - - /** - * Executes the provided iteratee once on each quad in the dataset. - * Note: This method is aligned with Array.prototype.forEach() in ECMAScript-262. - * @param iteratee - */ - public forEach(iteratee: (quad: InAndOutQuad, dataset: this) => void): void { - return this.dataset.forEach((quad) => iteratee(quad, this)); - } - - /** - * Imports all quads from the given stream into the dataset. - * The stream events end and error are wrapped in a Promise. - * @param stream - */ - public async import(stream: Stream): Promise { - await this.dataset.import(stream); - return this; - } - - /** - * Returns a new dataset containing alls quads from the current dataset that are also included in the given dataset. - * @param other - */ - // Typescript disabled because rdf-js has incorrect typings - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - public intersection( - other: Dataset, - ): Dataset { - return this.dataset.intersection(other); - } - - /** - * Returns a new dataset containing all quads returned by applying iteratee to each quad in the current dataset. - * @param iteratee - */ - public map( - iteratee: (quad: InAndOutQuad, dataset: this) => InAndOutQuad, - ): Dataset { - return this.dataset.map((quad) => iteratee(quad, this)); - } - - /** - * This method calls the iteratee on each quad of the DatasetCore. The first time the iteratee is called, the accumulator value is the initialValue or, if not given, equals to the first quad of the Dataset. The return value of the iteratee is used as accumulator value for the next calls. - * This method returns the return value of the last iteratee call. - * Note: This method is aligned with Array.prototype.reduce() in ECMAScript-262. - * @param iteratee - * @param initialValue - */ - public reduce( - iteratee: (accumulator: A, quad: InAndOutQuad, dataset: this) => A, - initialValue?: A, - ): A { - return this.dataset.reduce( - (acc, quad) => iteratee(acc, quad, this), - initialValue, - ); - } - - /** - * Existential quantification method, tests whether some quads in the dataset pass the test implemented by the provided iteratee. - * Note: This method is aligned with Array.prototype.some() in ECMAScript-262. - * @param iteratee - * @returns boolean true once a quad that passes the test is found. - */ - public some( - iteratee: (quad: InAndOutQuad, dataset: this) => boolean, - ): boolean { - return this.dataset.some((quad) => iteratee(quad, this)); - } - - /** - * Returns the set of quads within the dataset as a host language native sequence, for example an Array in ECMAScript-262. - * Note: Since a DatasetCore is an unordered set, the order of the quads within the returned sequence is arbitrary. - */ - public toArray(): InAndOutQuad[] { - console.log("Calling toArray"); - return this.dataset.toArray(); - } - - /** - * Returns an N-Quads string representation of the dataset, preprocessed with RDF Dataset Normalization algorithm. - */ - public toCanonical(): string { - return this.dataset.toCanonical(); - } - - /** - * Returns a stream that contains all quads of the dataset. - */ - public toStream(): Stream { - return this.dataset.toStream(); - } - - /** - * Returns an N-Quads string representation of the dataset. - * No prior normalization is required, therefore the results for the same quads may vary depending on the Dataset implementation. - */ - public toString(): string { - return this.dataset.toString(); - } - - /** - * Returns a new Dataset that is a concatenation of this dataset and the quads given as an argument. - * @param other - */ - public union( - quads: Dataset, - ): Dataset { - return this.dataset.union(quads); - } - - /** - * This method returns a new dataset that is comprised of all quads in the current instance matching the given arguments. The logic described in Quad Matching is applied for each quad in this dataset to check if it should be included in the output dataset. - * @param subject - * @param predicate - * @param object - * @param graph - * @returns a Dataset with matching triples - */ - public match( - subject?: Term | null, - predicate?: Term | null, - object?: Term | null, - graph?: Term | null, - ): Dataset { - return this.dataset.match(subject, predicate, object, graph); - } - - /** - * A non-negative integer that specifies the number of quads in the set. - */ - public get size(): number { - return this.dataset.size; - } - /** * Adds the specified quad to the dataset. * Existing quads, as defined in Quad.equals, will be ignored. @@ -321,7 +139,7 @@ export class SubscribableDataset * @returns the dataset instance it was called on. */ public add(quad: InAndOutQuad): this { - this.dataset.add(quad); + super.add(quad); this.triggerSubscriptionForQuads({ added: this.datasetFactory.dataset([quad]), }); @@ -334,28 +152,13 @@ export class SubscribableDataset * @param quad */ public delete(quad: InAndOutQuad): this { - this.dataset.delete(quad); + super.delete(quad); this.triggerSubscriptionForQuads({ removed: this.datasetFactory.dataset([quad]), }); return this; } - /** - * Determines whether a dataset includes a certain quad, returning true or false as appropriate. - * @param quad - */ - public has(quad: InAndOutQuad): boolean { - return this.dataset.has(quad); - } - - /** - * Returns an iterator - */ - public [Symbol.iterator](): Iterator { - return this.dataset[Symbol.iterator](); - } - /** * ================================================================== * EVENTEMITTER METHODS diff --git a/packages/subscribable-dataset/src/TransactionDataset.ts b/packages/subscribable-dataset/src/TransactionDataset.ts index 875ad6f..4b92fff 100644 --- a/packages/subscribable-dataset/src/TransactionDataset.ts +++ b/packages/subscribable-dataset/src/TransactionDataset.ts @@ -178,7 +178,6 @@ export class TransactionDataset * Returns an iterator */ public [Symbol.iterator](): Iterator { - console.log("Getting Iterator"); const addedIterator = (this.datasetChanges.added || [])[Symbol.iterator](); let addedNext = addedIterator.next(); const parentIterator = this.parentDataset[Symbol.iterator](); @@ -251,19 +250,7 @@ export class TransactionDataset * Helper method to update the parent dataset or any other provided dataset */ private updateParentDataset(datasetChanges: DatasetChanges) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if ((this.parentDataset as any).bulk) { - this.parentDataset.bulk(datasetChanges); - } else { - if (datasetChanges.added) { - this.parentDataset.addAll(datasetChanges.added); - } - if (datasetChanges.removed) { - datasetChanges.removed.forEach((curQuad) => { - this.parentDataset.delete(curQuad); - }); - } - } + this.parentDataset.bulk(datasetChanges); } /** From 893e745903970b10734c984a689237ebe181b01d Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Thu, 15 Feb 2024 10:59:46 -0500 Subject: [PATCH 03/10] Updated @ldo/ldo to have a transaction dataset --- packages/ldo/src/LdoDataset.ts | 17 ++++++- packages/ldo/src/LdoDatasetFactory.ts | 47 ++++++++----------- packages/ldo/src/LdoTransactionDataset.ts | 19 ++++++++ packages/ldo/src/LdoTransactionalDataset.ts | 23 --------- packages/ldo/src/createLdoDataset.ts | 6 ++- packages/ldo/src/types.ts | 9 ++++ packages/ldo/src/util.ts | 15 +++--- .../ldo/test/TransactionLdoDataset.test.ts | 21 +++++++++ packages/ldo/test/methods.test.ts | 4 +- .../src/SubscribableDatasetFactory.ts | 4 +- 10 files changed, 101 insertions(+), 64 deletions(-) create mode 100644 packages/ldo/src/LdoTransactionDataset.ts delete mode 100644 packages/ldo/src/LdoTransactionalDataset.ts create mode 100644 packages/ldo/src/types.ts create mode 100644 packages/ldo/test/TransactionLdoDataset.test.ts diff --git a/packages/ldo/src/LdoDataset.ts b/packages/ldo/src/LdoDataset.ts index f8e73e0..bdd736e 100644 --- a/packages/ldo/src/LdoDataset.ts +++ b/packages/ldo/src/LdoDataset.ts @@ -1,9 +1,11 @@ import type { Quad } from "@rdfjs/types"; import jsonldDatasetProxy from "@ldo/jsonld-dataset-proxy"; -import { WrapperSubscribableDataset } from "@ldo/subscribable-dataset"; +import { SubscribableDataset } from "@ldo/subscribable-dataset"; import { LdoBuilder } from "./LdoBuilder"; import type { ShapeType } from "./ShapeType"; import type { LdoBase } from "./index"; +import { LdoTransactionDataset } from "./LdoTransactionDataset"; +import type { ILdoDataset } from "./types"; /** * @category Getting an LdoDataset @@ -22,7 +24,10 @@ import type { LdoBase } from "./index"; * const ldoBuilder = ldoDataset.usingType(FoafProfileShapeType); * ``` */ -export class LdoDataset extends WrapperSubscribableDataset { +export class LdoDataset + extends SubscribableDataset + implements ILdoDataset +{ /** * Creates an LdoBuilder for a given shapeType * @@ -35,4 +40,12 @@ export class LdoDataset extends WrapperSubscribableDataset { const proxyBuilder = jsonldDatasetProxy(this, shapeType.context); return new LdoBuilder(proxyBuilder, shapeType); } + + public startTransaction(): LdoTransactionDataset { + return new LdoTransactionDataset( + this, + this.datasetFactory, + this.transactionDatasetFactory, + ); + } } diff --git a/packages/ldo/src/LdoDatasetFactory.ts b/packages/ldo/src/LdoDatasetFactory.ts index b0150b2..94343a3 100644 --- a/packages/ldo/src/LdoDatasetFactory.ts +++ b/packages/ldo/src/LdoDatasetFactory.ts @@ -1,4 +1,6 @@ -import type { DatasetFactory, Dataset, Quad } from "@rdfjs/types"; +import type { Dataset, Quad } from "@rdfjs/types"; +import type { ISubscribableDatasetFactory } from "@ldo/subscribable-dataset"; +import { SubscribableDatasetFactory } from "@ldo/subscribable-dataset"; import { LdoDataset } from "./LdoDataset"; /** @@ -9,37 +11,28 @@ import { LdoDataset } from "./LdoDataset"; * * @example * ```typescript - * import { createLdoDatasetFactory } from "ldo"; + * import { createLdoDatasetFactory } from "@ldo/ldo"; + * import { createExtendedDatasetFactory } from "@ldo/dataset"; + * import { createTransactionDatasetFactory } from "@ldo/subscribable-dataset"; * - * const datasetFactory = // some RDF/JS Dataset Factory - * const ldoDatasetFactory = new LdoDatasetFactory(datasetFactory); + * const datasetFactory = createExtendedDatasetFactory(); + * const transactionDatasetFactory = createTransactionDatasetFactroy(); + * const ldoDatasetFactory = new LdoDatasetFactory( + * datasetFactory, + * transactionDatasetFactory + * ); * const ldoDataset = ldoDatasetFactory.dataset(initialDataset); * ``` */ -export class LdoDatasetFactory implements DatasetFactory { - private datasetFactory: DatasetFactory; - - /** - * @constructor - * @param datasetFactory - A generic dataset factory this factory will wrap - */ - constructor(datasetFactory: DatasetFactory) { - this.datasetFactory = datasetFactory; - } - - /** - * Creates an LdoDataset - * @param quads - A list of quads to initialize the dataset - * @returns an LdoDataset - */ - dataset(quads?: Dataset | Quad[]): LdoDataset { +export class LdoDatasetFactory + extends SubscribableDatasetFactory + implements ISubscribableDatasetFactory +{ + dataset(quads?: Dataset | Quad[] | undefined): LdoDataset { return new LdoDataset( - this, - quads - ? Array.isArray(quads) - ? this.datasetFactory.dataset(quads) - : quads - : undefined, + this.datasetFactory, + this.transactionDatasetFactory, + this.datasetFactory.dataset(quads), ); } } diff --git a/packages/ldo/src/LdoTransactionDataset.ts b/packages/ldo/src/LdoTransactionDataset.ts new file mode 100644 index 0000000..762a068 --- /dev/null +++ b/packages/ldo/src/LdoTransactionDataset.ts @@ -0,0 +1,19 @@ +import { TransactionDataset } from "@ldo/subscribable-dataset"; +import type { Quad } from "@rdfjs/types"; +import type { ILdoDataset } from "./types"; +import { LdoBuilder } from "./LdoBuilder"; +import type { ShapeType } from "./ShapeType"; +import type { LdoBase } from "./util"; +import jsonldDatasetProxy from "@ldo/jsonld-dataset-proxy"; + +export class LdoTransactionDataset + extends TransactionDataset + implements ILdoDataset +{ + usingType( + shapeType: ShapeType, + ): LdoBuilder { + const proxyBuilder = jsonldDatasetProxy(this, shapeType.context); + return new LdoBuilder(proxyBuilder, shapeType); + } +} diff --git a/packages/ldo/src/LdoTransactionalDataset.ts b/packages/ldo/src/LdoTransactionalDataset.ts deleted file mode 100644 index 38baf93..0000000 --- a/packages/ldo/src/LdoTransactionalDataset.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { TransactionalDataset } from "@ldo/subscribable-dataset"; -import { LdoDataset } from "../dist/LdoDataset"; -import type { Quad } from "@rdfjs/types"; -import type { DatasetChanges } from "@ldo/rdf-utils"; - -export class LdoTransactionalDataset - extends LdoDataset - implements TransactionalDataset -{ - constructor() { - - } - - rollback(): void { - throw new Error("Method not implemented."); - } - commit(): void { - throw new Error("Method not implemented."); - } - getChanges(): DatasetChanges { - throw new Error("Method not implemented."); - } -} diff --git a/packages/ldo/src/createLdoDataset.ts b/packages/ldo/src/createLdoDataset.ts index cca5b04..9ec6037 100644 --- a/packages/ldo/src/createLdoDataset.ts +++ b/packages/ldo/src/createLdoDataset.ts @@ -1,6 +1,7 @@ import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; import { createDataset } from "@ldo/dataset"; import { LdoDatasetFactory } from "./LdoDatasetFactory"; +import { createTransactionDatasetFactory } from "@ldo/subscribable-dataset"; import type { LdoDataset } from "./LdoDataset"; /** @@ -22,7 +23,10 @@ export function createLdoDatasetFactory() { return createDataset(quads); }, }; - return new LdoDatasetFactory(datasetFactory); + return new LdoDatasetFactory( + datasetFactory, + createTransactionDatasetFactory(), + ); } /** diff --git a/packages/ldo/src/types.ts b/packages/ldo/src/types.ts new file mode 100644 index 0000000..6f751f3 --- /dev/null +++ b/packages/ldo/src/types.ts @@ -0,0 +1,9 @@ +import type { ISubscribableDataset } from "@ldo/subscribable-dataset"; +import type { LdoBuilder } from "./LdoBuilder"; +import type { ShapeType } from "./ShapeType"; +import type { LdoBase } from "./util"; +import type { Quad } from "@rdfjs/types"; + +export interface ILdoDataset extends ISubscribableDataset { + usingType(shapeType: ShapeType): LdoBuilder; +} diff --git a/packages/ldo/src/util.ts b/packages/ldo/src/util.ts index fa7ad0a..322a3b7 100644 --- a/packages/ldo/src/util.ts +++ b/packages/ldo/src/util.ts @@ -8,14 +8,15 @@ import { } from "@ldo/jsonld-dataset-proxy"; import type { AnyNode } from "@ldo/rdf-utils"; import type { - SubscribableDataset, - TransactionalDataset, + ISubscribableDataset, + ITransactionDataset, } from "@ldo/subscribable-dataset"; /** * @category Types * `LdoBase` is an interface defining that a Linked Data Object is a JavaScript Object Literal. */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type LdoBase = Record; /** @@ -42,21 +43,21 @@ export function normalizeNodeNames( export function canDatasetStartTransaction( dataset: Dataset, -): dataset is SubscribableDataset { +): dataset is ISubscribableDataset { return ( - typeof (dataset as SubscribableDataset).startTransaction === "function" + typeof (dataset as ISubscribableDataset).startTransaction === "function" ); } export function isTransactionalDataset( dataset: Dataset, -): dataset is TransactionalDataset { - return typeof (dataset as TransactionalDataset).commit === "function"; +): dataset is ITransactionDataset { + return typeof (dataset as ITransactionDataset).commit === "function"; } export function getTransactionalDatasetFromLdo( ldo: LdoBase, -): [TransactionalDataset, SubjectProxy | ArrayProxy] { +): [ITransactionDataset, SubjectProxy | ArrayProxy] { const proxy = getProxyFromObject(ldo); const dataset = proxy[_getUnderlyingDataset]; if ( diff --git a/packages/ldo/test/TransactionLdoDataset.test.ts b/packages/ldo/test/TransactionLdoDataset.test.ts new file mode 100644 index 0000000..482b530 --- /dev/null +++ b/packages/ldo/test/TransactionLdoDataset.test.ts @@ -0,0 +1,21 @@ +import { createLdoDataset } from "../src/createLdoDataset"; +import { ProfileShapeType } from "./profileData"; + +describe("TransactionLdoDataset", () => { + it("Uses transactions with an LdoBuilder", () => { + const ldoDataset = createLdoDataset(); + const transaction = ldoDataset.startTransaction(); + const profile = transaction + .usingType(ProfileShapeType) + .fromSubject("https://example.com/Person1"); + profile.fn = "John Doe"; + expect(transaction.getChanges().added?.toString()).toBe( + ' "John Doe" .\n', + ); + expect(ldoDataset.toString()).toBe(""); + transaction.commit(); + expect(ldoDataset.toString()).toBe( + ' "John Doe" .\n', + ); + }); +}); diff --git a/packages/ldo/test/methods.test.ts b/packages/ldo/test/methods.test.ts index c89bc3c..a63d2fd 100644 --- a/packages/ldo/test/methods.test.ts +++ b/packages/ldo/test/methods.test.ts @@ -9,7 +9,6 @@ import { import { createDataset } from "@ldo/dataset"; import type { SolidProfileShape } from "./profileData"; import { ProfileShapeType } from "./profileData"; -import type { LdoDataset } from "../src"; import { commitTransaction, createLdoDataset, @@ -25,9 +24,10 @@ import { setLanguagePreferences, languagesOf, } from "../src"; +import type { ILdoDataset } from "../src/types"; describe("methods", () => { - let dataset: LdoDataset; + let dataset: ILdoDataset; let profile: SolidProfileShape; beforeEach(() => { dataset = createLdoDataset(); diff --git a/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts b/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts index 483ee06..3fbbcfe 100644 --- a/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts +++ b/packages/subscribable-dataset/src/SubscribableDatasetFactory.ts @@ -9,8 +9,8 @@ export class SubscribableDatasetFactory< InAndOutQuad extends BaseQuad = BaseQuad, > implements DatasetFactory { - private datasetFactory: DatasetFactory; - private transactionDatasetFactory: ITransactionDatasetFactory; + protected datasetFactory: DatasetFactory; + protected transactionDatasetFactory: ITransactionDatasetFactory; constructor( datasetFactory: DatasetFactory, transactionDatasetFactory: ITransactionDatasetFactory, From b941385a6ee90c1f1beaa065d456b157427f5596 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Thu, 15 Feb 2024 13:40:59 -0500 Subject: [PATCH 04/10] Before remove transactionDatasetFactory --- packages/ldo/src/index.ts | 1 + packages/solid/src/SolidLdoDataset.ts | 237 +++++++++--------- .../solid/src/SolidLdoTransactionDataset.ts | 8 + packages/solid/src/types.ts | 11 + 4 files changed, 143 insertions(+), 114 deletions(-) create mode 100644 packages/solid/src/SolidLdoTransactionDataset.ts create mode 100644 packages/solid/src/types.ts diff --git a/packages/ldo/src/index.ts b/packages/ldo/src/index.ts index a612422..77f5250 100644 --- a/packages/ldo/src/index.ts +++ b/packages/ldo/src/index.ts @@ -2,6 +2,7 @@ export * from "./parseRdf"; export * from "./ShapeType"; export * from "./methods"; export * from "./LdoDataset"; +export * from "./LdoTransactionDataset"; export * from "./LdoBuilder"; export * from "./createLdoDataset"; import type { LdoBase as LdoBaseImport } from "./util"; diff --git a/packages/solid/src/SolidLdoDataset.ts b/packages/solid/src/SolidLdoDataset.ts index 53c2e02..c655f00 100644 --- a/packages/solid/src/SolidLdoDataset.ts +++ b/packages/solid/src/SolidLdoDataset.ts @@ -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, - ): Promise< - | AggregateSuccess< - ResourceResult - > - | AggregateError - > { - // Optimistically add changes to the datastore - // this.bulk(changes); - const changesByGraph = splitChangesByGraph(changes); - - // Iterate through all changes by graph in - const results: [ - GraphNode, - DatasetChanges, - 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, + // ): Promise< + // | AggregateSuccess< + // ResourceResult + // > + // | AggregateError + // > { + // // 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 => - result.type === "updateSuccess" || - result.type === "updateDefaultGraphSuccess", - ), - }; - } + // // Iterate through all changes by graph in + // const results: [ + // GraphNode, + // DatasetChanges, + // 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( - shapeType: ShapeType, - 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 => + // 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( + // shapeType: ShapeType, + // 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; + // } } diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts new file mode 100644 index 0000000..4e31b9c --- /dev/null +++ b/packages/solid/src/SolidLdoTransactionDataset.ts @@ -0,0 +1,8 @@ +import { LdoTransactionDataset } from "@ldo/ldo"; +import type { ISolidLdoDataset } from "./types"; + +export class SolidLdoTransactionDataset + extends LdoTransactionDataset + implements ISolidLdoDataset { + + } diff --git a/packages/solid/src/types.ts b/packages/solid/src/types.ts new file mode 100644 index 0000000..45bd75a --- /dev/null +++ b/packages/solid/src/types.ts @@ -0,0 +1,11 @@ +import type { ResourceGetterOptions } from "./ResourceStore"; +import type { Container } from "./resource/Container"; +import type { Leaf } from "./resource/Leaf"; +import type { ContainerUri, LeafUri } from "./util/uriTypes"; + +export interface ISolidLdoDataset { + getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container; + getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf; + getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container; + getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container; +} From 64ea2070fd6a725138bd86f0b2e5934cfb470a17 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Thu, 15 Feb 2024 15:51:38 -0500 Subject: [PATCH 05/10] Refactored commitToPod to the transaction --- packages/solid/src/SolidLdoDataset.ts | 144 +-------------- .../solid/src/SolidLdoTransactionDataset.ts | 143 +++++++++++++- packages/solid/src/createSolidLdoDataset.ts | 2 + packages/solid/src/methods.ts | 22 +-- .../src/requester/requests/requestOptions.ts | 4 +- packages/solid/test/Integration.test.ts | 174 +++++++----------- 6 files changed, 222 insertions(+), 267 deletions(-) diff --git a/packages/solid/src/SolidLdoDataset.ts b/packages/solid/src/SolidLdoDataset.ts index c655f00..010f986 100644 --- a/packages/solid/src/SolidLdoDataset.ts +++ b/packages/solid/src/SolidLdoDataset.ts @@ -1,28 +1,12 @@ -import type { LdoBase, LdoTransactionDataset, ShapeType } from "@ldo/ldo"; -import { LdoDataset, startTransaction } from "@ldo/ldo"; -import type { DatasetChanges, GraphNode, SubjectNode } from "@ldo/rdf-utils"; +import { LdoDataset } from "@ldo/ldo"; import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; -import type { - UpdateResult, - UpdateResultError, -} from "./requester/requests/updateDataResource"; -import { AggregateError } from "./requester/results/error/ErrorResult"; -import { InvalidUriError } from "./requester/results/error/InvalidUriError"; -import type { AggregateSuccess } from "./requester/results/success/SuccessResult"; -import type { - UpdateDefaultGraphSuccess, - UpdateSuccess, -} from "./requester/results/success/UpdateSuccess"; import type { Container } from "./resource/Container"; import type { Leaf } from "./resource/Leaf"; -import type { ResourceResult } from "./resource/resourceResult/ResourceResult"; import type { ResourceGetterOptions } from "./ResourceStore"; import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext"; -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"; +import type { ITransactionDatasetFactory } from "@ldo/subscribable-dataset"; /** * A SolidLdoDataset has all the functionality of an LdoDataset with the added @@ -58,14 +42,16 @@ export class SolidLdoDataset extends LdoDataset { /** * @param context - SolidLdoDatasetContext * @param datasetFactory - An optional dataset factory + * @param transactionDatasetFactory - A factory for creating transaction datasets * @param initialDataset - A set of triples to initialize this dataset */ constructor( context: SolidLdoDatasetContext, - datasetFactory: DatasetFactory, + datasetFactory: DatasetFactory, + transactionDatasetFactory: ITransactionDatasetFactory, initialDataset?: Dataset, ) { - super(datasetFactory, initialDataset); + super(datasetFactory, transactionDatasetFactory, initialDataset); this.context = context; } @@ -96,125 +82,9 @@ export class SolidLdoDataset extends LdoDataset { public startTransaction(): SolidLdoTransactionDataset { return new SolidLdoTransactionDataset( this, + this.context, this.datasetFactory, this.transactionDatasetFactory, ); } - - // /** - // * 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, - // ): Promise< - // | AggregateSuccess< - // ResourceResult - // > - // | AggregateError - // > { - // // Optimistically add changes to the datastore - // // this.bulk(changes); - // const changesByGraph = splitChangesByGraph(changes); - - // // Iterate through all changes by graph in - // const results: [ - // GraphNode, - // DatasetChanges, - // 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) ]; - // }, - // ), - // ); - - // // 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 => - // 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( - // shapeType: ShapeType, - // 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; - // } } diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts index 4e31b9c..9c2665d 100644 --- a/packages/solid/src/SolidLdoTransactionDataset.ts +++ b/packages/solid/src/SolidLdoTransactionDataset.ts @@ -1,8 +1,147 @@ import { LdoTransactionDataset } from "@ldo/ldo"; import type { ISolidLdoDataset } from "./types"; +import type { ResourceGetterOptions } from "./ResourceStore"; +import type { Container } from "./resource/Container"; +import type { Leaf } from "./resource/Leaf"; +import { + isContainerUri, + type ContainerUri, + type LeafUri, +} from "./util/uriTypes"; +import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext"; +import type { DatasetFactory, Quad } from "@rdfjs/types"; +import type { ITransactionDatasetFactory } from "@ldo/subscribable-dataset"; +import type { SolidLdoDataset } from "./SolidLdoDataset"; +import type { AggregateSuccess } from "./requester/results/success/SuccessResult"; +import type { ResourceResult } from "./resource/resourceResult/ResourceResult"; +import type { + UpdateDefaultGraphSuccess, + UpdateSuccess, +} from "./requester/results/success/UpdateSuccess"; +import { AggregateError } from "./requester/results/error/ErrorResult"; +import type { + UpdateResult, + UpdateResultError, +} from "./requester/requests/updateDataResource"; +import { InvalidUriError } from "./requester/results/error/InvalidUriError"; +import type { DatasetChanges, GraphNode } from "@ldo/rdf-utils"; +import { splitChangesByGraph } from "./util/splitChangesByGraph"; export class SolidLdoTransactionDataset extends LdoTransactionDataset - implements ISolidLdoDataset { - + implements ISolidLdoDataset +{ + /** + * @internal + */ + public context: SolidLdoDatasetContext; + + /** + * @param context - SolidLdoDatasetContext + * @param datasetFactory - An optional dataset factory + * @param transactionDatasetFactory - A factory for creating transaction datasets + * @param initialDataset - A set of triples to initialize this dataset + */ + constructor( + parentDataset: SolidLdoDataset, + context: SolidLdoDatasetContext, + datasetFactory: DatasetFactory, + transactionDatasetFactory: ITransactionDatasetFactory, + ) { + super(parentDataset, datasetFactory, transactionDatasetFactory); + this.context = context; + } + + /** + * Retireves a representation (either a LeafResource or a ContainerResource) + * of a Solid Resource at the given URI. This resource represents the + * current state of the resource: whether it is currently fetched or in the + * process of fetching as well as some information about it. + * + * @param uri - the URI of the resource + * @param options - Special options for getting the resource + * + * @returns a Leaf or Container Resource + * + * @example + * ```typescript + * const profileDocument = solidLdoDataset + * .getResource("https://example.com/profile"); + * ``` + */ + getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container; + getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf; + getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container; + getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container { + return this.context.resourceStore.get(uri, options); + } + + async commitToPod(): Promise< + | AggregateSuccess< + ResourceResult + > + | AggregateError + > { + const changes = this.getChanges(); + const changesByGraph = splitChangesByGraph(changes); + + // Iterate through all changes by graph in + const results: [ + GraphNode, + DatasetChanges, + 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); + const updateResult = await resource.update(datasetChanges); + return [graph, datasetChanges, updateResult]; + }, + ), + ); + + // 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 => + result.type === "updateSuccess" || + result.type === "updateDefaultGraphSuccess", + ), + }; } +} diff --git a/packages/solid/src/createSolidLdoDataset.ts b/packages/solid/src/createSolidLdoDataset.ts index 3a58a84..dfafe85 100644 --- a/packages/solid/src/createSolidLdoDataset.ts +++ b/packages/solid/src/createSolidLdoDataset.ts @@ -5,6 +5,7 @@ import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext"; import { createDataset, createDatasetFactory } from "@ldo/dataset"; import { ResourceStore } from "./ResourceStore"; import { guaranteeFetch } from "./util/guaranteeFetch"; +import { createTransactionDatasetFactory } from "@ldo/subscribable-dataset"; /** * Options for createSolidDataset @@ -56,6 +57,7 @@ export function createSolidLdoDataset( const solidLdoDataset = new SolidLdoDataset( context, finalDatasetFactory, + createTransactionDatasetFactory(), finalDataset, ); const resourceStore = new ResourceStore(context); diff --git a/packages/solid/src/methods.ts b/packages/solid/src/methods.ts index 5c4333d..ccaf5a1 100644 --- a/packages/solid/src/methods.ts +++ b/packages/solid/src/methods.ts @@ -1,16 +1,9 @@ -import { - startTransaction, - type LdoBase, - write, - transactionChanges, - getDataset, -} from "@ldo/ldo"; -import type { DatasetChanges } from "@ldo/rdf-utils"; +import { startTransaction, type LdoBase, write, getDataset } from "@ldo/ldo"; import type { Resource } from "./resource/Resource"; -import type { SolidLdoDataset } from "./SolidLdoDataset"; import type { Quad } from "@rdfjs/types"; import { _proxyContext, getProxyFromObject } from "@ldo/jsonld-dataset-proxy"; import type { SubscribableDataset } from "@ldo/subscribable-dataset"; +import type { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset"; /** * Begins tracking changes to eventually commit. @@ -75,16 +68,17 @@ export function changeData( * await commitData(cProfile); * ``` */ -export function commitData( +export async function commitData( input: LdoBase, -): ReturnType { - const changes = transactionChanges(input); +): ReturnType { + const transactionDataset = getDataset(input) as SolidLdoTransactionDataset; + const result = await transactionDataset.commitToPod(); + if (result.isError) return result; // Take the LdoProxy out of commit mode. This uses hidden methods of JSONLD-DATASET-PROXY const proxy = getProxyFromObject(input); proxy[_proxyContext] = proxy[_proxyContext].duplicate({ dataset: proxy[_proxyContext].state .parentDataset as SubscribableDataset, }); - const dataset = getDataset(input) as SolidLdoDataset; - return dataset.commitChangesToPod(changes as DatasetChanges); + return result; } diff --git a/packages/solid/src/requester/requests/requestOptions.ts b/packages/solid/src/requester/requests/requestOptions.ts index 3232911..376c043 100644 --- a/packages/solid/src/requester/requests/requestOptions.ts +++ b/packages/solid/src/requester/requests/requestOptions.ts @@ -1,4 +1,4 @@ -import type { BulkEditableDataset } from "@ldo/subscribable-dataset"; +import type { IBulkEditableDataset } from "@ldo/subscribable-dataset"; import type { Quad } from "@rdfjs/types"; /** @@ -18,5 +18,5 @@ export interface DatasetRequestOptions extends BasicRequestOptions { /** * A dataset to be modified with any new information obtained from a request */ - dataset?: BulkEditableDataset; + dataset?: IBulkEditableDataset; } diff --git a/packages/solid/test/Integration.test.ts b/packages/solid/test/Integration.test.ts index 7ee73a1..0e74e8c 100644 --- a/packages/solid/test/Integration.test.ts +++ b/packages/solid/test/Integration.test.ts @@ -20,9 +20,7 @@ import { defaultGraph, } from "@rdfjs/data-model"; import type { CreateSuccess } from "../src/requester/results/success/CreateSuccess"; -import type { DatasetChanges } from "@ldo/rdf-utils"; import { createDataset } from "@ldo/dataset"; -import type { Quad } from "@rdfjs/types"; import type { AggregateSuccess } from "../src/requester/results/success/SuccessResult"; import type { UpdateDefaultGraphSuccess, @@ -983,28 +981,28 @@ describe("Integration", () => { * Update */ describe("updateDataResource", () => { - const changes: DatasetChanges = { - added: createDataset([ - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Norman Osborn"), - namedNode(SAMPLE_DATA_URI), - ), - ]), - removed: createDataset([ - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Green Goblin"), - namedNode(SAMPLE_DATA_URI), - ), - ]), - }; + const normanQuad = createQuad( + namedNode("http://example.org/#green-goblin"), + namedNode("http://xmlns.com/foaf/0.1/name"), + literal("Norman Osborn"), + namedNode(SAMPLE_DATA_URI), + ); + + const goblinQuad = createQuad( + namedNode("http://example.org/#green-goblin"), + namedNode("http://xmlns.com/foaf/0.1/name"), + literal("Green Goblin"), + namedNode(SAMPLE_DATA_URI), + ); it("applies changes to a Pod", async () => { const result = await testRequestLoads( - () => solidLdoDataset.commitChangesToPod(changes), + () => { + const transaction = solidLdoDataset.startTransaction(); + transaction.add(normanQuad); + transaction.delete(goblinQuad); + return transaction.commitToPod(); + }, solidLdoDataset.getResource(SAMPLE_DATA_URI), { isLoading: true, @@ -1017,41 +1015,17 @@ describe("Integration", () => { >; expect(aggregateSuccess.results.length).toBe(1); expect(aggregateSuccess.results[0].type === "updateSuccess").toBe(true); - expect( - solidLdoDataset.has( - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Norman Osborn"), - namedNode(SAMPLE_DATA_URI), - ), - ), - ).toBe(true); - expect( - solidLdoDataset.has( - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Green Goblin"), - namedNode(SAMPLE_DATA_URI), - ), - ), - ).toBe(false); + expect(solidLdoDataset.has(normanQuad)).toBe(true); + expect(solidLdoDataset.has(goblinQuad)).toBe(false); }); it("applies only remove changes to the Pod", async () => { - const changes: DatasetChanges = { - removed: createDataset([ - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Green Goblin"), - namedNode(SAMPLE_DATA_URI), - ), - ]), - }; const result = await testRequestLoads( - () => solidLdoDataset.commitChangesToPod(changes), + () => { + const transaction = solidLdoDataset.startTransaction(); + transaction.delete(goblinQuad); + return transaction.commitToPod(); + }, solidLdoDataset.getResource(SAMPLE_DATA_URI), { isLoading: true, @@ -1064,21 +1038,17 @@ describe("Integration", () => { >; expect(aggregateSuccess.results.length).toBe(1); expect(aggregateSuccess.results[0].type === "updateSuccess").toBe(true); - expect( - solidLdoDataset.has( - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Green Goblin"), - namedNode(SAMPLE_DATA_URI), - ), - ), - ).toBe(false); + expect(solidLdoDataset.has(goblinQuad)).toBe(false); }); it("handles an HTTP error", async () => { fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 })); - const result = await solidLdoDataset.commitChangesToPod(changes); + + const transaction = solidLdoDataset.startTransaction(); + transaction.add(normanQuad); + transaction.delete(goblinQuad); + const result = await transaction.commitToPod(); + expect(result.isError).toBe(true); expect(result.type).toBe("aggregateError"); const aggregateError = result as AggregateError< @@ -1092,7 +1062,10 @@ describe("Integration", () => { fetchMock.mockImplementationOnce(() => { throw new Error("Some Error"); }); - const result = await solidLdoDataset.commitChangesToPod(changes); + const transaction = solidLdoDataset.startTransaction(); + transaction.add(normanQuad); + transaction.delete(goblinQuad); + const result = await transaction.commitToPod(); expect(result.isError).toBe(true); expect(result.type).toBe("aggregateError"); const aggregateError = result as AggregateError< @@ -1103,17 +1076,15 @@ describe("Integration", () => { }); it("errors when trying to update a container", async () => { - const changes: DatasetChanges = { - added: createDataset([ - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Norman Osborn"), - namedNode(SAMPLE_CONTAINER_URI), - ), - ]), - }; - const result = await solidLdoDataset.commitChangesToPod(changes); + const badContainerQuad = createQuad( + namedNode("http://example.org/#green-goblin"), + namedNode("http://xmlns.com/foaf/0.1/name"), + literal("Norman Osborn"), + namedNode(SAMPLE_CONTAINER_URI), + ); + const transaction = solidLdoDataset.startTransaction(); + transaction.add(badContainerQuad); + const result = await transaction.commitToPod(); expect(result.isError).toBe(true); expect(result.type).toBe("aggregateError"); const aggregateError = result as AggregateError< @@ -1124,17 +1095,15 @@ describe("Integration", () => { }); it("writes to the default graph without fetching", async () => { - const changes: DatasetChanges = { - added: createDataset([ - createQuad( - namedNode("http://example.org/#green-goblin"), - namedNode("http://xmlns.com/foaf/0.1/name"), - literal("Norman Osborn"), - defaultGraph(), - ), - ]), - }; - const result = await solidLdoDataset.commitChangesToPod(changes); + const defaultGraphQuad = createQuad( + namedNode("http://example.org/#green-goblin"), + namedNode("http://xmlns.com/foaf/0.1/name"), + literal("Norman Osborn"), + defaultGraph(), + ); + const transaction = solidLdoDataset.startTransaction(); + transaction.add(defaultGraphQuad); + const result = await transaction.commitToPod(); expect(result.type).toBe("aggregateSuccess"); const aggregateSuccess = result as AggregateSuccess< ResourceSuccess @@ -1158,10 +1127,15 @@ describe("Integration", () => { it("batches data update changes", async () => { const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI); + const transaction1 = solidLdoDataset.startTransaction(); + transaction1.delete(goblinQuad); + const transaction2 = solidLdoDataset.startTransaction(); + transaction2.add(normanQuad); + const [, updateResult1, updateResult2] = await Promise.all([ resource.read(), - solidLdoDataset.commitChangesToPod({ removed: changes.removed }), - solidLdoDataset.commitChangesToPod({ added: changes.added }), + transaction1.commitToPod(), + transaction2.commitToPod(), ]); expect(updateResult1.type).toBe("aggregateSuccess"); expect(updateResult2.type).toBe("aggregateSuccess"); @@ -1445,30 +1419,6 @@ describe("Integration", () => { * =========================================================================== */ describe("methods", () => { - it("creates a data object for a specific subject", () => { - const resource = solidLdoDataset.getResource( - "https://example.com/resource.ttl", - ); - const post = solidLdoDataset.createData( - PostShShapeType, - "https://example.com/subject", - resource, - ); - post.type = { "@id": "CreativeWork" }; - expect(post.type["@id"]).toBe("CreativeWork"); - commitData(post); - expect( - solidLdoDataset.has( - createQuad( - namedNode("https://example.com/subject"), - namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), - namedNode("http://schema.org/CreativeWork"), - namedNode("https://example.com/resource.ttl"), - ), - ), - ).toBe(true); - }); - it("uses changeData to start a transaction", () => { const resource = solidLdoDataset.getResource( "https://example.com/resource.ttl", From a7f254fce9496adbf566250fe3fcacea1618e802 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Fri, 16 Feb 2024 00:24:03 -0500 Subject: [PATCH 06/10] Completed transaction on Solid Dataset --- packages/solid/src/SolidLdoDataset.ts | 28 +++++- .../solid/src/SolidLdoTransactionDataset.ts | 2 +- packages/solid/test/Integration.test.ts | 93 ++++++++++++++----- packages/solid/test/solidServer.helper.ts | 4 +- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/packages/solid/src/SolidLdoDataset.ts b/packages/solid/src/SolidLdoDataset.ts index 010f986..e3b6a34 100644 --- a/packages/solid/src/SolidLdoDataset.ts +++ b/packages/solid/src/SolidLdoDataset.ts @@ -1,4 +1,5 @@ -import { LdoDataset } from "@ldo/ldo"; +import type { LdoBase, ShapeType } from "@ldo/ldo"; +import { LdoDataset, startTransaction } from "@ldo/ldo"; import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types"; import type { Container } from "./resource/Container"; import type { Leaf } from "./resource/Leaf"; @@ -7,6 +8,8 @@ import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext"; import type { ContainerUri, LeafUri } from "./util/uriTypes"; import { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset"; import type { ITransactionDatasetFactory } from "@ldo/subscribable-dataset"; +import type { SubjectNode } from "@ldo/rdf-utils"; +import type { Resource } from "./resource/Resource"; /** * A SolidLdoDataset has all the functionality of an LdoDataset with the added @@ -87,4 +90,27 @@ export class SolidLdoDataset extends LdoDataset { this.transactionDatasetFactory, ); } + + /** + * 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( + shapeType: ShapeType, + 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; + } } diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts index 9c2665d..212bfba 100644 --- a/packages/solid/src/SolidLdoTransactionDataset.ts +++ b/packages/solid/src/SolidLdoTransactionDataset.ts @@ -95,7 +95,7 @@ export class SolidLdoTransactionDataset async ([graph, datasetChanges]) => { if (graph.termType === "DefaultGraph") { // Undefined means that this is the default graph - this.bulk(datasetChanges); + this.parentDataset.bulk(datasetChanges); return [ graph, datasetChanges, diff --git a/packages/solid/test/Integration.test.ts b/packages/solid/test/Integration.test.ts index 0e74e8c..fcc759b 100644 --- a/packages/solid/test/Integration.test.ts +++ b/packages/solid/test/Integration.test.ts @@ -10,6 +10,7 @@ import type { import { changeData, commitData, createSolidLdoDataset } from "../src"; import { ROOT_CONTAINER, + WEB_ID, createApp, getAuthenticatedFetch, } from "./solidServer.helper"; @@ -20,7 +21,6 @@ import { defaultGraph, } from "@rdfjs/data-model"; import type { CreateSuccess } from "../src/requester/results/success/CreateSuccess"; -import { createDataset } from "@ldo/dataset"; import type { AggregateSuccess } from "../src/requester/results/success/SuccessResult"; import type { UpdateDefaultGraphSuccess, @@ -89,6 +89,12 @@ const TEST_CONTAINER_TTL = `@prefix dc: . posix:size 522. posix:mtime 1697810234; posix:size 10.`; +const TEST_CONTAINER_ACL_URI = `${TEST_CONTAINER_URI}.acl`; +const TEST_CONTAINER_ACL = `<#b30e3fd1-b5a8-4763-ad9d-e95de9cf7933> a ; + <${TEST_CONTAINER_URI}>; + <${TEST_CONTAINER_URI}>; + , , , ; + <${WEB_ID}>.`; async function testRequestLoads( request: () => Promise, @@ -164,6 +170,13 @@ describe("Integration", () => { slug: TEST_CONTAINER_SLUG, }, }); + await authFetch(TEST_CONTAINER_ACL_URI, { + method: "PUT", + headers: { + "content-type": "text/turtle", + }, + body: TEST_CONTAINER_ACL, + }); await Promise.all([ authFetch(TEST_CONTAINER_URI, { method: "POST", @@ -328,8 +341,8 @@ describe("Integration", () => { expect(result.isError).toBe(true); if (!result.isError) return; expect(result.type).toBe("noncompliantPodError"); - expect(result.message).toBe( - "Response from https://solidweb.me/jackson3/test_ldo/sample2.ttl is not compliant with the Solid Specification: Resource requests must return a content-type header.", + expect(result.message).toMatch( + /\Response from .* is not compliant with the Solid Specification: Resource requests must return a content-type header\./, ); }); @@ -349,8 +362,8 @@ describe("Integration", () => { expect(result.isError).toBe(true); if (!result.isError) return; expect(result.type).toBe("noncompliantPodError"); - expect(result.message).toBe( - 'Response from https://solidweb.me/jackson3/test_ldo/sample2.ttl is not compliant with the Solid Specification: Request returned noncompliant turtle: Unexpected "Error" on line 1.', + expect(result.message).toMatch( + /\Response from .* is not compliant with the Solid Specification: Request returned noncompliant turtle: Unexpected "Error" on line 1\./, ); }); @@ -384,8 +397,8 @@ describe("Integration", () => { expect(result.isError).toBe(true); if (!result.isError) return; expect(result.type).toBe("noncompliantPodError"); - expect(result.message).toBe( - "Response from https://solidweb.me/jackson3/test_ldo/ is not compliant with the Solid Specification: No link header present in request.", + expect(result.message).toMatch( + /\Response from .* is not compliant with the Solid Specification: No link header present in request\./, ); }); @@ -404,26 +417,22 @@ describe("Integration", () => { resource.read(), ]); + expect(fetchMock).toHaveBeenCalledTimes(1); expect(result.type).toBe("dataReadSuccess"); expect(result1.type).toBe("dataReadSuccess"); - expect(fetchMock).toHaveBeenCalledTimes(1); }); it("batches the read request when a read request is in queue", async () => { const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI); const [, result, result1] = await Promise.all([ - resource.update({ - added: createDataset([ - createQuad(namedNode("a"), namedNode("b"), namedNode("c")), - ]), - }), + resource.createAndOverwrite(), resource.read(), resource.read(), ]); + expect(fetchMock).toHaveBeenCalledTimes(3); expect(result.type).toBe("dataReadSuccess"); expect(result1.type).toBe("dataReadSuccess"); - expect(fetchMock).toHaveBeenCalledTimes(2); }); }); @@ -544,8 +553,8 @@ describe("Integration", () => { expect(result.isError).toBe(true); if (!result.isError) return; expect(result.type).toBe("noncompliantPodError"); - expect(result.message).toBe( - "Response from https://solidweb.me/jackson3/test_ldo/ is not compliant with the Solid Specification: No link header present in request.", + expect(result.message).toMatch( + /\Response from .* is not compliant with the Solid Specification: No link header present in request\./, ); }); @@ -1419,16 +1428,55 @@ describe("Integration", () => { * =========================================================================== */ describe("methods", () => { - it("uses changeData to start a transaction", () => { - const resource = solidLdoDataset.getResource( - "https://example.com/resource.ttl", + it("creates a data object for a specific subject", async () => { + const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI); + const post = solidLdoDataset.createData( + PostShShapeType, + "https://example.com/subject", + resource, ); + post.type = { "@id": "CreativeWork" }; + expect(post.type["@id"]).toBe("CreativeWork"); + const result = await commitData(post); + expect(result.type).toBe("aggregateSuccess"); + expect( + solidLdoDataset.has( + createQuad( + namedNode("https://example.com/subject"), + namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + namedNode("http://schema.org/CreativeWork"), + namedNode(SAMPLE_DATA_URI), + ), + ), + ).toBe(true); + }); + + it("handles an error when committing data", async () => { + fetchMock.mockResolvedValueOnce( + new Response(SAMPLE_DATA_URI, { + status: 500, + }), + ); + const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI); + const post = solidLdoDataset.createData( + PostShShapeType, + "https://example.com/subject", + resource, + ); + post.type = { "@id": "CreativeWork" }; + expect(post.type["@id"]).toBe("CreativeWork"); + const result = await commitData(post); + expect(result.isError).toBe(true); + }); + + it("uses changeData to start a transaction", async () => { + const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI); solidLdoDataset.add( createQuad( namedNode("https://example.com/subject"), namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), namedNode("http://schema.org/CreativeWork"), - namedNode("https://example.com/resource.ttl"), + namedNode(SAMPLE_DATA_URI), ), ); const post = solidLdoDataset @@ -1437,14 +1485,15 @@ describe("Integration", () => { const cPost = changeData(post, resource); cPost.type = { "@id": "SocialMediaPosting" }; expect(cPost.type["@id"]).toBe("SocialMediaPosting"); - commitData(cPost); + const result = await commitData(cPost); + expect(result.isError).toBe(false); expect( solidLdoDataset.has( createQuad( namedNode("https://example.com/subject"), namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), namedNode("http://schema.org/SocialMediaPosting"), - namedNode("https://example.com/resource.ttl"), + namedNode(SAMPLE_DATA_URI), ), ), ).toBe(true); diff --git a/packages/solid/test/solidServer.helper.ts b/packages/solid/test/solidServer.helper.ts index 01ec04d..3447f96 100644 --- a/packages/solid/test/solidServer.helper.ts +++ b/packages/solid/test/solidServer.helper.ts @@ -21,8 +21,10 @@ const config = [ ]; export const SERVER_DOMAIN = process.env.SERVER || "http://localhost:3001/"; -export const ROOT_ROUTE = process.env.ROOT_CONTAINER || "example/"; +export const ROOT_ROUTE = process.env.ROOT_CONTAINER || ""; export const ROOT_CONTAINER = `${SERVER_DOMAIN}${ROOT_ROUTE}`; +export const WEB_ID = + process.env.WEB_ID || `${SERVER_DOMAIN}example/profile/card#me`; // Use an increased timeout, since the CSS server takes too much setup time. jest.setTimeout(40_000); From 7a9a2ff0d43b8de66477eed05f656b08413d214f Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Fri, 16 Feb 2024 12:09:00 -0500 Subject: [PATCH 07/10] Updated JS-Docs --- .../solid/src/SolidLdoTransactionDataset.ts | 29 +++++++++++++++++++ packages/solid/src/index.ts | 1 + packages/solid/src/methods.ts | 4 +-- packages/solid/src/types.ts | 3 ++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts index 212bfba..8c57c0d 100644 --- a/packages/solid/src/SolidLdoTransactionDataset.ts +++ b/packages/solid/src/SolidLdoTransactionDataset.ts @@ -27,6 +27,35 @@ import { InvalidUriError } from "./requester/results/error/InvalidUriError"; import type { DatasetChanges, GraphNode } from "@ldo/rdf-utils"; import { splitChangesByGraph } from "./util/splitChangesByGraph"; +/** + * A SolidLdoTransactionDataset has all the functionality of a SolidLdoDataset + * and represents a transaction to the parent SolidLdoDataset. + * + * It is recommended to use the `startTransaction` method on a SolidLdoDataset + * to initialize this class + * + * @example + * ```typescript + * import { createSolidLdoDataset } from "@ldo/solid"; + * import { ProfileShapeType } from "./.ldo/profile.shapeTypes.ts" + * + * // ... + * + * const solidLdoDataset = createSolidLdoDataset(); + * + * const profileDocument = solidLdoDataset + * .getResource("https://example.com/profile"); + * await profileDocument.read(); + * + * const transaction = solidLdoDataset.startTransaction(); + * + * const profile = transaction + * .using(ProfileShapeType) + * .fromSubject("https://example.com/profile#me"); + * profile.name = "Some Name"; + * await transaction.commitToPod(); + * ``` + */ export class SolidLdoTransactionDataset extends LdoTransactionDataset implements ISolidLdoDataset diff --git a/packages/solid/src/index.ts b/packages/solid/src/index.ts index 22b3108..1eb93cb 100644 --- a/packages/solid/src/index.ts +++ b/packages/solid/src/index.ts @@ -1,6 +1,7 @@ export * from "./createSolidLdoDataset"; export * from "./SolidLdoDataset"; export * from "./SolidLdoDatasetContext"; +export * from "./SolidLdoTransactionDataset"; export * from "./resource/Resource"; export * from "./resource/Container"; diff --git a/packages/solid/src/methods.ts b/packages/solid/src/methods.ts index ccaf5a1..b1945ba 100644 --- a/packages/solid/src/methods.ts +++ b/packages/solid/src/methods.ts @@ -27,7 +27,7 @@ import type { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset"; * * const cProfile = changeData(profile, resource); * cProfile.name = "My New Name"; - * await commitData(cProfile); + * const result = await commitData(cProfile); * ``` */ export function changeData( @@ -65,7 +65,7 @@ export function changeData( * * const cProfile = changeData(profile, resource); * cProfile.name = "My New Name"; - * await commitData(cProfile); + * const result = await commitData(cProfile); * ``` */ export async function commitData( diff --git a/packages/solid/src/types.ts b/packages/solid/src/types.ts index 45bd75a..e87f63c 100644 --- a/packages/solid/src/types.ts +++ b/packages/solid/src/types.ts @@ -3,6 +3,9 @@ import type { Container } from "./resource/Container"; import type { Leaf } from "./resource/Leaf"; import type { ContainerUri, LeafUri } from "./util/uriTypes"; +/** + * A SolidLdoDataset provides methods for getting Solid resources. + */ export interface ISolidLdoDataset { getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container; getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf; From d2384b2fc731354f3d52cbf9a69cc7f50ab61c14 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Fri, 16 Feb 2024 12:23:51 -0500 Subject: [PATCH 08/10] Update solid-react for the new types --- packages/solid-react/src/useLdoMethods.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/solid-react/src/useLdoMethods.ts b/packages/solid-react/src/useLdoMethods.ts index d6add4e..fc95869 100644 --- a/packages/solid-react/src/useLdoMethods.ts +++ b/packages/solid-react/src/useLdoMethods.ts @@ -1,6 +1,10 @@ import type { LdoBase, ShapeType } from "@ldo/ldo"; import type { SubjectNode } from "@ldo/rdf-utils"; -import type { Resource, SolidLdoDataset } from "@ldo/solid"; +import type { + Resource, + SolidLdoDataset, + SolidLdoTransactionDataset, +} from "@ldo/solid"; import { changeData, commitData } from "@ldo/solid"; export interface UseLdoMethods { @@ -21,7 +25,9 @@ export interface UseLdoMethods { resource: Resource, ...additionalResources: Resource[] ): Type; - commitData(input: LdoBase): ReturnType; + commitData( + input: LdoBase, + ): ReturnType; } export function createUseLdoMethods(dataset: SolidLdoDataset): UseLdoMethods { From db47f8bd1470b7a8fb552c1ad0ce9156cfe1dc81 Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Fri, 16 Feb 2024 13:47:57 -0500 Subject: [PATCH 09/10] Completed all libraries upgrading to the transactionLdoDataset --- .../src/arrayProxy/modifyArray.ts | 8 ++++-- .../solid/src/SolidLdoTransactionDataset.ts | 7 +++-- .../src/TransactionDataset.ts | 13 ++++----- packages/subscribable-dataset/src/index.ts | 1 + packages/subscribable-dataset/src/types.ts | 4 +-- packages/subscribable-dataset/src/util.ts | 27 +++++++++++++++++++ .../test/TransactionalDataset.test.ts | 20 +++++++++++++- 7 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 packages/subscribable-dataset/src/util.ts diff --git a/packages/jsonld-dataset-proxy/src/arrayProxy/modifyArray.ts b/packages/jsonld-dataset-proxy/src/arrayProxy/modifyArray.ts index 54cd5df..b1ae921 100644 --- a/packages/jsonld-dataset-proxy/src/arrayProxy/modifyArray.ts +++ b/packages/jsonld-dataset-proxy/src/arrayProxy/modifyArray.ts @@ -1,7 +1,10 @@ import { defaultGraph } from "@rdfjs/data-model"; import type { Quad } from "@rdfjs/types"; import type { ObjectNode } from "@ldo/rdf-utils"; -import { ProxyTransactionalDataset } from "@ldo/subscribable-dataset"; +import { + TransactionDataset, + createTransactionDatasetFactory, +} from "@ldo/subscribable-dataset"; import { createDatasetFactory } from "@ldo/dataset"; import type { ProxyContext } from "../ProxyContext"; import { addObjectToDataset } from "../util/addObjectToDataset"; @@ -31,9 +34,10 @@ export function checkArrayModification( ); } // Create a test dataset to see if the inputted data is valid - const testDataset = new ProxyTransactionalDataset( + const testDataset = new TransactionDataset( proxyContext.dataset, createDatasetFactory(), + createTransactionDatasetFactory(), ); addObjectToDataset( objectToAdd as RawObject, diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts index 8c57c0d..cbacbb3 100644 --- a/packages/solid/src/SolidLdoTransactionDataset.ts +++ b/packages/solid/src/SolidLdoTransactionDataset.ts @@ -10,7 +10,10 @@ import { } from "./util/uriTypes"; import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext"; import type { DatasetFactory, Quad } from "@rdfjs/types"; -import type { ITransactionDatasetFactory } from "@ldo/subscribable-dataset"; +import { + updateDatasetInBulk, + type ITransactionDatasetFactory, +} from "@ldo/subscribable-dataset"; import type { SolidLdoDataset } from "./SolidLdoDataset"; import type { AggregateSuccess } from "./requester/results/success/SuccessResult"; import type { ResourceResult } from "./resource/resourceResult/ResourceResult"; @@ -124,7 +127,7 @@ export class SolidLdoTransactionDataset async ([graph, datasetChanges]) => { if (graph.termType === "DefaultGraph") { // Undefined means that this is the default graph - this.parentDataset.bulk(datasetChanges); + updateDatasetInBulk(this.parentDataset, datasetChanges); return [ graph, datasetChanges, diff --git a/packages/subscribable-dataset/src/TransactionDataset.ts b/packages/subscribable-dataset/src/TransactionDataset.ts index 4b92fff..9e8ef3c 100644 --- a/packages/subscribable-dataset/src/TransactionDataset.ts +++ b/packages/subscribable-dataset/src/TransactionDataset.ts @@ -1,12 +1,9 @@ import type { Dataset, BaseQuad, Term, DatasetFactory } from "@rdfjs/types"; import type { DatasetChanges } from "@ldo/rdf-utils"; -import type { - ISubscribableDataset, - ITransactionDataset, - ITransactionDatasetFactory, -} from "./types"; +import type { ITransactionDataset, ITransactionDatasetFactory } from "./types"; import { mergeDatasetChanges } from "./mergeDatasetChanges"; import { SubscribableDataset } from "./SubscribableDataset"; +import { updateDatasetInBulk } from "./util"; /** * Proxy Transactional Dataset is a transactional dataset that does not duplicate @@ -20,7 +17,7 @@ export class TransactionDataset /** * The parent dataset that will be updated upon commit */ - public readonly parentDataset: ISubscribableDataset; + public readonly parentDataset: Dataset; /** * The changes made that are ready to commit @@ -41,7 +38,7 @@ export class TransactionDataset * @param parentDataset The dataset that will be updated upon commit */ constructor( - parentDataset: ISubscribableDataset, + parentDataset: Dataset, datasetFactory: DatasetFactory, transactionDatasetFactory: ITransactionDatasetFactory, ) { @@ -250,7 +247,7 @@ export class TransactionDataset * Helper method to update the parent dataset or any other provided dataset */ private updateParentDataset(datasetChanges: DatasetChanges) { - this.parentDataset.bulk(datasetChanges); + return updateDatasetInBulk(this.parentDataset, datasetChanges); } /** diff --git a/packages/subscribable-dataset/src/index.ts b/packages/subscribable-dataset/src/index.ts index 071e05d..a48f3f1 100644 --- a/packages/subscribable-dataset/src/index.ts +++ b/packages/subscribable-dataset/src/index.ts @@ -6,3 +6,4 @@ export * from "./SubscribableDataset"; export * from "./SubscribableDatasetFactory"; export * from "./types"; export * from "./mergeDatasetChanges"; +export * from "./util"; diff --git a/packages/subscribable-dataset/src/types.ts b/packages/subscribable-dataset/src/types.ts index 41f2de7..055ed21 100644 --- a/packages/subscribable-dataset/src/types.ts +++ b/packages/subscribable-dataset/src/types.ts @@ -151,7 +151,7 @@ export interface ITransactionDatasetFactory< InAndOutQuad extends BaseQuad = BaseQuad, > { transactionDataset( - parent: ISubscribableDataset, + parent: Dataset, ): ITransactionDataset; } @@ -160,7 +160,7 @@ export interface ITransactionDatasetFactory< */ export interface ITransactionDataset extends ISubscribableDataset { - readonly parentDataset: ISubscribableDataset; + readonly parentDataset: Dataset; rollback(): void; commit(): void; getChanges(): DatasetChanges; diff --git a/packages/subscribable-dataset/src/util.ts b/packages/subscribable-dataset/src/util.ts new file mode 100644 index 0000000..cfb8667 --- /dev/null +++ b/packages/subscribable-dataset/src/util.ts @@ -0,0 +1,27 @@ +import type { DatasetChanges } from "@ldo/rdf-utils"; +import type { BaseQuad, Dataset } from "@rdfjs/types"; +import type { IBulkEditableDataset } from "./types"; + +/** + * Performs a bulk update for a dataset even if it doesn't have a bulk method. + * @param dataset - the input dataset + * @param datasetChanges - changes to be applied + */ +export function updateDatasetInBulk( + dataset: Dataset, + datasetChanges: DatasetChanges, +) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if ((dataset as any).bulk) { + (dataset as IBulkEditableDataset).bulk(datasetChanges); + } else { + if (datasetChanges.added) { + dataset.addAll(datasetChanges.added); + } + if (datasetChanges.removed) { + datasetChanges.removed.forEach((curQuad) => { + dataset.delete(curQuad); + }); + } + } +} diff --git a/packages/subscribable-dataset/test/TransactionalDataset.test.ts b/packages/subscribable-dataset/test/TransactionalDataset.test.ts index 30c0dbf..903feef 100644 --- a/packages/subscribable-dataset/test/TransactionalDataset.test.ts +++ b/packages/subscribable-dataset/test/TransactionalDataset.test.ts @@ -6,7 +6,7 @@ import type { DatasetCore, } from "@rdfjs/types"; import type { ISubscribableDataset } from "../src"; -import { ExtendedDatasetFactory } from "@ldo/dataset"; +import { ExtendedDatasetFactory, createDataset } from "@ldo/dataset"; import { TransactionDataset, createSubscribableDataset, @@ -323,6 +323,24 @@ describe("TransactionDataset", () => { expect(mockParent.bulk).toHaveBeenCalled(); }); + it("Uses bulk update on commit when the parent dataset is not bulk updatable", () => { + // Disable for tests + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const mockParent: Dataset = createDataset([tomTypeQuad]); + transactionalDataset = new TransactionDataset( + mockParent, + extendedDatasetFactory, + createTransactionDatasetFactory(), + ); + + transactionalDataset.add(lickyNameQuad); + transactionalDataset.delete(tomTypeQuad); + transactionalDataset.commit(); + expect(mockParent.has(lickyNameQuad)).toBe(true); + expect(mockParent.has(tomTypeQuad)).toBe(false); + }); + it("Returns a transactional dataset", () => { expect( transactionalDataset.startTransaction() instanceof TransactionDataset, From c21144a5552978622d05c3f1db4a3b68d304813c Mon Sep 17 00:00:00 2001 From: jaxoncreed Date: Fri, 16 Feb 2024 13:48:47 -0500 Subject: [PATCH 10/10] v0.0.1-alpha.19 --- lerna.json | 2 +- package-lock.json | 36 +++++++++++----------- packages/cli/package.json | 2 +- packages/demo-react/package.json | 6 ++-- packages/jsonld-dataset-proxy/package.json | 4 +-- packages/ldo/package.json | 6 ++-- packages/solid-react/package.json | 10 +++--- packages/solid/package.json | 6 ++-- packages/subscribable-dataset/package.json | 2 +- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/lerna.json b/lerna.json index c532954..5e58c95 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,4 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "0.0.1-alpha.18" + "version": "0.0.1-alpha.19" } diff --git a/package-lock.json b/package-lock.json index 7ff28e9..d5ec26f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22784,7 +22784,7 @@ }, "packages/cli": { "name": "@ldo/cli", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@ldo/schema-converter-shex": "^0.0.1-alpha.17", @@ -23006,10 +23006,10 @@ }, "packages/demo-react": { "name": "@ldo/demo-react", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "dependencies": { "@inrupt/solid-client-authn-browser": "^2.0.0", - "@ldo/solid-react": "^0.0.1-alpha.18", + "@ldo/solid-react": "^0.0.1-alpha.19", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.15.0", @@ -23018,7 +23018,7 @@ }, "devDependencies": { "@craco/craco": "^7.1.0", - "@ldo/cli": "^0.0.1-alpha.18", + "@ldo/cli": "^0.0.1-alpha.19", "@types/jsonld": "^1.5.9", "@types/react": "^18.2.21", "@types/shexj": "^2.1.4", @@ -23197,11 +23197,11 @@ }, "packages/jsonld-dataset-proxy": { "name": "@ldo/jsonld-dataset-proxy", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@ldo/rdf-utils": "^0.0.1-alpha.17", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "@rdfjs/dataset": "^1.1.0", "jsonld2graphobject": "^0.0.4" @@ -23277,12 +23277,12 @@ }, "packages/ldo": { "name": "@ldo/ldo", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.18", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.19", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "buffer": "^6.0.3", "readable-stream": "^4.3.0" @@ -24561,12 +24561,12 @@ }, "packages/solid": { "name": "@ldo/solid", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@inrupt/solid-client": "^1.30.0", "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/ldo": "^0.0.1-alpha.18", + "@ldo/ldo": "^0.0.1-alpha.19", "@ldo/rdf-utils": "^0.0.1-alpha.17", "@types/parse-link-header": "^2.0.1", "cross-fetch": "^3.1.6", @@ -24575,7 +24575,7 @@ }, "devDependencies": { "@inrupt/solid-client-authn-core": "^1.17.1", - "@ldo/cli": "^0.0.1-alpha.18", + "@ldo/cli": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "@rdfjs/types": "^1.0.1", "@solid/community-server": "^6.0.2", @@ -24591,15 +24591,15 @@ }, "packages/solid-react": { "name": "@ldo/solid-react", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@inrupt/solid-client": "^2.0.0", "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.18", - "@ldo/ldo": "^0.0.1-alpha.18", - "@ldo/solid": "^0.0.1-alpha.18", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.19", + "@ldo/ldo": "^0.0.1-alpha.19", + "@ldo/solid": "^0.0.1-alpha.19", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "cross-fetch": "^3.1.6" }, @@ -26819,7 +26819,7 @@ }, "packages/subscribable-dataset": { "name": "@ldo/subscribable-dataset", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "license": "MIT", "dependencies": { "@ldo/dataset": "^0.0.1-alpha.17", diff --git a/packages/cli/package.json b/packages/cli/package.json index f6dafb8..c200b19 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/cli", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "A Command Line Interface for Linked Data Objects", "main": "./dist/index.js", "bin": { diff --git a/packages/demo-react/package.json b/packages/demo-react/package.json index 2c2756b..3eaec63 100644 --- a/packages/demo-react/package.json +++ b/packages/demo-react/package.json @@ -1,9 +1,9 @@ { "name": "@ldo/demo-react", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "dependencies": { "@inrupt/solid-client-authn-browser": "^2.0.0", - "@ldo/solid-react": "^0.0.1-alpha.18", + "@ldo/solid-react": "^0.0.1-alpha.19", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.15.0", @@ -37,7 +37,7 @@ }, "devDependencies": { "@craco/craco": "^7.1.0", - "@ldo/cli": "^0.0.1-alpha.18", + "@ldo/cli": "^0.0.1-alpha.19", "@types/jsonld": "^1.5.9", "@types/react": "^18.2.21", "@types/shexj": "^2.1.4", diff --git a/packages/jsonld-dataset-proxy/package.json b/packages/jsonld-dataset-proxy/package.json index 091cb29..5c4088e 100644 --- a/packages/jsonld-dataset-proxy/package.json +++ b/packages/jsonld-dataset-proxy/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/jsonld-dataset-proxy", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "", "main": "dist/index.js", "scripts": { @@ -41,7 +41,7 @@ ], "dependencies": { "@ldo/rdf-utils": "^0.0.1-alpha.17", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "@rdfjs/dataset": "^1.1.0", "jsonld2graphobject": "^0.0.4" diff --git a/packages/ldo/package.json b/packages/ldo/package.json index e08f3c1..47823f8 100644 --- a/packages/ldo/package.json +++ b/packages/ldo/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/ldo", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "", "main": "dist/index.js", "scripts": { @@ -39,8 +39,8 @@ }, "dependencies": { "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.18", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.19", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "buffer": "^6.0.3", "readable-stream": "^4.3.0" diff --git a/packages/solid-react/package.json b/packages/solid-react/package.json index c2f24e8..e3fee83 100644 --- a/packages/solid-react/package.json +++ b/packages/solid-react/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/solid-react", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "A React library for LDO and Solid", "main": "dist/index.js", "scripts": { @@ -38,10 +38,10 @@ "dependencies": { "@inrupt/solid-client": "^2.0.0", "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.18", - "@ldo/ldo": "^0.0.1-alpha.18", - "@ldo/solid": "^0.0.1-alpha.18", - "@ldo/subscribable-dataset": "^0.0.1-alpha.18", + "@ldo/jsonld-dataset-proxy": "^0.0.1-alpha.19", + "@ldo/ldo": "^0.0.1-alpha.19", + "@ldo/solid": "^0.0.1-alpha.19", + "@ldo/subscribable-dataset": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "cross-fetch": "^3.1.6" }, diff --git a/packages/solid/package.json b/packages/solid/package.json index 8629142..d0ec978 100644 --- a/packages/solid/package.json +++ b/packages/solid/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/solid", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "A library for LDO and Solid", "main": "dist/index.js", "scripts": { @@ -26,7 +26,7 @@ "homepage": "https://github.com/o-development/ldobjects/tree/main/packages/solid#readme", "devDependencies": { "@inrupt/solid-client-authn-core": "^1.17.1", - "@ldo/cli": "^0.0.1-alpha.18", + "@ldo/cli": "^0.0.1-alpha.19", "@rdfjs/data-model": "^1.2.0", "@rdfjs/types": "^1.0.1", "@solid/community-server": "^6.0.2", @@ -42,7 +42,7 @@ "dependencies": { "@inrupt/solid-client": "^1.30.0", "@ldo/dataset": "^0.0.1-alpha.17", - "@ldo/ldo": "^0.0.1-alpha.18", + "@ldo/ldo": "^0.0.1-alpha.19", "@ldo/rdf-utils": "^0.0.1-alpha.17", "@types/parse-link-header": "^2.0.1", "cross-fetch": "^3.1.6", diff --git a/packages/subscribable-dataset/package.json b/packages/subscribable-dataset/package.json index fc2bd7b..c9145e4 100644 --- a/packages/subscribable-dataset/package.json +++ b/packages/subscribable-dataset/package.json @@ -1,6 +1,6 @@ { "name": "@ldo/subscribable-dataset", - "version": "0.0.1-alpha.18", + "version": "0.0.1-alpha.19", "description": "An RDFJS dataset implementation that can be subscribed to for updates", "main": "dist/index.js", "scripts": {