@solid/community-server
Version:
Community Solid Server: an open and modular implementation of the Solid specifications
101 lines • 4.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateCachedRepresentationSize = calculateCachedRepresentationSize;
exports.readStream = readStream;
exports.cachedToRepresentation = cachedToRepresentation;
exports.representationToCached = representationToCached;
exports.duplicateRepresentation = duplicateRepresentation;
const node_stream_1 = require("node:stream");
const global_logger_factory_1 = require("global-logger-factory");
const BasicRepresentation_1 = require("../http/representation/BasicRepresentation");
const RepresentationMetadata_1 = require("../http/representation/RepresentationMetadata");
const ErrorUtil_1 = require("./errors/ErrorUtil");
const NotImplementedHttpError_1 = require("./errors/NotImplementedHttpError");
const StreamUtil_1 = require("./StreamUtil");
const logger = (0, global_logger_factory_1.getLoggerFor)('CacheUtil');
/**
* Function that can be used as `sizeCalculation` for an LRU cache storing {@link CachedRepresentation}s.
* The length of the data is used, so in the case of an array, the size of the entries is not taken into account.
*
* @param cached - The cached entry to determine the size of.
*/
function calculateCachedRepresentationSize(cached) {
// Needs to be a positive integer
return cached.data.length + 1;
}
/**
* Reads a data stream into an array or buffer, depending on if it is in object mode or not.
*
* @param stream - Data stream to read.
*/
async function readStream(stream) {
if (stream.readableObjectMode) {
const data = [];
for await (const obj of stream) {
data.push(obj);
}
return data;
}
const chunks = [];
for await (const chunk of stream) {
if (typeof chunk === 'string') {
chunks.push(Buffer.from(chunk));
}
else if (Buffer.isBuffer(chunk)) {
chunks.push(chunk);
}
else {
throw new NotImplementedHttpError_1.NotImplementedHttpError(`Unexpected ${typeof chunk} chunk: ${chunk}`);
}
}
return Buffer.concat(chunks);
}
/**
* Generates a {@link Representation} based on a {@link CachedRepresentation}.
* The generated value is not linked to the {@link CachedRepresentation},
* so any changes to it will not impact the original.
*
* @param cached - {@link CachedRepresentation} to create a representation from
*/
function cachedToRepresentation(cached) {
// Copy the metadata quads to prevent changes to the original cached metadata
const metadata = new RepresentationMetadata_1.RepresentationMetadata(cached.metadata);
return new BasicRepresentation_1.BasicRepresentation((0, StreamUtil_1.guardedStreamFrom)(cached.data, { objectMode: Array.isArray(cached.data) }), metadata);
}
/**
* Generates a {@link CachedRepresentation} based on a {@link Representation}.
* The generated value is not linked to the {@link Representation},
* so any changes to it will not impact the original.
*
* Returns undefined if there was an error, implying the data was not fully read.
*
* @param representation - Representation to convert.
*/
async function representationToCached(representation) {
try {
const data = await readStream(representation.data);
const metadata = new RepresentationMetadata_1.RepresentationMetadata(representation.metadata);
return { data, metadata };
}
catch (error) {
// This just means the request was not interested in the data and closed the stream
if (error.message !== 'Premature close') {
logger.error(`Unable to cache representation for ${representation.metadata.identifier.value}: ${(0, ErrorUtil_1.createErrorMessage)(error)}`);
}
}
}
/**
* Generates 2 {@link Representation}s from a single one.
* After this the input representation should not be used any more.
*
* @param representation - Representation to duplicate.
*/
function duplicateRepresentation(representation) {
const stream1 = (0, StreamUtil_1.pipeSafely)(representation.data, new node_stream_1.PassThrough({ objectMode: representation.data.readableObjectMode }));
const stream2 = (0, StreamUtil_1.pipeSafely)(representation.data, new node_stream_1.PassThrough({ objectMode: representation.data.readableObjectMode }));
return [
new BasicRepresentation_1.BasicRepresentation(stream1, new RepresentationMetadata_1.RepresentationMetadata(representation.metadata)),
new BasicRepresentation_1.BasicRepresentation(stream2, new RepresentationMetadata_1.RepresentationMetadata(representation.metadata)),
];
}
//# sourceMappingURL=CacheUtil.js.map