mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Added cloneRepresentation function to ResourceUtil
* feat: added cloneRepresentation function to ResourceUtil * fix: adapted to review * fix: adapted to review Co-authored-by: Arne Vandoorslaer <arne@digita.ai>
This commit is contained in:
parent
4385b461b5
commit
ee88bf14de
@ -1,8 +1,7 @@
|
||||
import arrayifyStream from 'arrayify-stream';
|
||||
import type { RepresentationConverter } from '../../storage/conversion/RepresentationConverter';
|
||||
import { INTERNAL_QUADS } from '../../util/ContentTypes';
|
||||
import { guardedStreamFrom } from '../../util/StreamUtil';
|
||||
import { BasicRepresentation } from '../representation/BasicRepresentation';
|
||||
import { cloneRepresentation } from '../../util/ResourceUtil';
|
||||
import type { Representation } from '../representation/Representation';
|
||||
import { Validator } from './Validator';
|
||||
|
||||
@ -23,23 +22,22 @@ export class RdfValidator extends Validator {
|
||||
if (representation.metadata.contentType === INTERNAL_QUADS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/expiring-todo-comments
|
||||
// TODO: Everything below should be part of a utility cloneRepresentation function.
|
||||
|
||||
const identifier = { path: representation.metadata.identifier.value };
|
||||
|
||||
// Read data in memory first so it does not get lost
|
||||
const data = await arrayifyStream(representation.data);
|
||||
const preferences = { type: { [INTERNAL_QUADS]: 1 }};
|
||||
|
||||
// Creating new representation since converter might edit metadata
|
||||
const tempRepresentation = new BasicRepresentation(data, identifier, representation.metadata.contentType);
|
||||
const result = await this.converter.handleSafe({ identifier, representation: tempRepresentation, preferences });
|
||||
let result;
|
||||
try {
|
||||
// Creating new representation since converter might edit metadata
|
||||
const tempRepresentation = await cloneRepresentation(representation);
|
||||
result = await this.converter.handleSafe({
|
||||
identifier,
|
||||
representation: tempRepresentation,
|
||||
preferences,
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
representation.data.destroy();
|
||||
throw error;
|
||||
}
|
||||
// Drain stream to make sure data was parsed correctly
|
||||
await arrayifyStream(result.data);
|
||||
|
||||
// Stream has been drained so need to create new stream
|
||||
representation.data = guardedStreamFrom(data);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,12 @@
|
||||
import arrayifyStream from 'arrayify-stream';
|
||||
import { DataFactory } from 'n3';
|
||||
import type { NamedNode, Quad } from 'rdf-js';
|
||||
import { BasicRepresentation } from '../ldp/representation/BasicRepresentation';
|
||||
import type { Representation } from '../ldp/representation/Representation';
|
||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||
import { pushQuad } from './QuadUtil';
|
||||
import { guardedStreamFrom } from './StreamUtil';
|
||||
|
||||
import { LDP, RDF } from './Vocabularies';
|
||||
|
||||
/**
|
||||
@ -33,3 +38,21 @@ export function generateContainmentQuads(containerURI: NamedNode, childURIs: str
|
||||
return new RepresentationMetadata(containerURI,
|
||||
{ [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to clone a representation, the original representation can still be used.
|
||||
* This function loads the entire stream in memory.
|
||||
* @param representation - The representation to clone.
|
||||
*
|
||||
* @returns The cloned representation.
|
||||
*/
|
||||
export async function cloneRepresentation(representation: Representation): Promise<BasicRepresentation> {
|
||||
const data = await arrayifyStream(representation.data);
|
||||
const result = new BasicRepresentation(
|
||||
data,
|
||||
new RepresentationMetadata(representation.metadata),
|
||||
representation.binary,
|
||||
);
|
||||
representation.data = guardedStreamFrom(data);
|
||||
return result;
|
||||
}
|
||||
|
@ -39,6 +39,6 @@ describe('An RdfValidator', (): void => {
|
||||
const representation = new BasicRepresentation('data', 'content-type');
|
||||
await expect(validator.handle(representation)).rejects.toThrow('bad data!');
|
||||
// Make sure the data on the readable has not been reset
|
||||
expect(representation.data.readableEnded).toBe(true);
|
||||
expect(representation.data.destroyed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
27
test/unit/util/ResourceUtil.test.ts
Normal file
27
test/unit/util/ResourceUtil.test.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { BasicRepresentation } from '../../../src/ldp/representation/BasicRepresentation';
|
||||
import type { Representation } from '../../../src/ldp/representation/Representation';
|
||||
import * as resourceUtils from '../../../src/util/ResourceUtil';
|
||||
import 'jest-rdf';
|
||||
|
||||
describe('ResourceUtil', (): void => {
|
||||
let representation: Representation;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
representation = new BasicRepresentation('data', 'metadata');
|
||||
});
|
||||
|
||||
describe('cloneRepresentation', (): void => {
|
||||
it('returns a clone of the passed representation.', async(): Promise<void> => {
|
||||
const res = await resourceUtils.cloneRepresentation(representation);
|
||||
expect(res.binary).toBe(representation.binary);
|
||||
expect(res.metadata.identifier).toBe(representation.metadata.identifier);
|
||||
expect(res.metadata.contentType).toBe(representation.metadata.contentType);
|
||||
});
|
||||
|
||||
it('ensures that original representation does not update when the clone is updated.', async(): Promise<void> => {
|
||||
const res = await resourceUtils.cloneRepresentation(representation);
|
||||
res.metadata.contentType = 'typetype';
|
||||
expect(representation.metadata.contentType).not.toBe(res.metadata.contentType);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user