mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
refactor: Move file related metadata to FileResourceStore
This commit is contained in:
parent
22962192ff
commit
fa935cc4c7
@ -3,7 +3,7 @@ import { createReadStream, createWriteStream, promises as fsPromises } from 'fs'
|
|||||||
import { posix } from 'path';
|
import { posix } from 'path';
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import { DataFactory } from 'n3';
|
import { DataFactory } from 'n3';
|
||||||
import type { Quad } from 'rdf-js';
|
import type { NamedNode, Quad } from 'rdf-js';
|
||||||
import streamifyArray from 'streamify-array';
|
import streamifyArray from 'streamify-array';
|
||||||
import type { Representation } from '../ldp/representation/Representation';
|
import type { Representation } from '../ldp/representation/Representation';
|
||||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||||
@ -16,8 +16,8 @@ import { UnsupportedMediaTypeHttpError } from '../util/errors/UnsupportedMediaTy
|
|||||||
import type { InteractionController } from '../util/InteractionController';
|
import type { InteractionController } from '../util/InteractionController';
|
||||||
import type { MetadataController } from '../util/MetadataController';
|
import type { MetadataController } from '../util/MetadataController';
|
||||||
import { CONTENT_TYPE, DCTERMS, HTTP, POSIX, RDF, XSD } from '../util/UriConstants';
|
import { CONTENT_TYPE, DCTERMS, HTTP, POSIX, RDF, XSD } from '../util/UriConstants';
|
||||||
import { toTypedLiteral } from '../util/UriUtil';
|
import { toNamedNode, toTypedLiteral } from '../util/UriUtil';
|
||||||
import { ensureTrailingSlash } from '../util/Util';
|
import { ensureTrailingSlash, pushQuad } from '../util/Util';
|
||||||
import type { ExtensionBasedMapper } from './ExtensionBasedMapper';
|
import type { ExtensionBasedMapper } from './ExtensionBasedMapper';
|
||||||
import type { ResourceLink } from './FileIdentifierMapper';
|
import type { ResourceLink } from './FileIdentifierMapper';
|
||||||
import type { ResourceStore } from './ResourceStore';
|
import type { ResourceStore } from './ResourceStore';
|
||||||
@ -244,11 +244,11 @@ export class FileResourceStore implements ResourceStore {
|
|||||||
*/
|
*/
|
||||||
private async getDirectoryRepresentation(resourceLink: ResourceLink, stats: Stats): Promise<Representation> {
|
private async getDirectoryRepresentation(resourceLink: ResourceLink, stats: Stats): Promise<Representation> {
|
||||||
const files = await fsPromises.readdir(resourceLink.filePath);
|
const files = await fsPromises.readdir(resourceLink.filePath);
|
||||||
const quads: Quad[] = [];
|
|
||||||
|
|
||||||
const containerURI = resourceLink.identifier.path;
|
const containerURI = DataFactory.namedNode(resourceLink.identifier.path);
|
||||||
|
|
||||||
quads.push(...this.metadataController.generateResourceQuads(containerURI, stats));
|
const quads = this.metadataController.generateResourceQuads(containerURI, true);
|
||||||
|
quads.push(...this.generatePosixQuads(containerURI, stats));
|
||||||
quads.push(...await this.getDirChildrenQuadRepresentation(files, resourceLink.filePath, containerURI));
|
quads.push(...await this.getDirChildrenQuadRepresentation(files, resourceLink.filePath, containerURI));
|
||||||
|
|
||||||
let rawMetadata: Quad[] = [];
|
let rawMetadata: Quad[] = [];
|
||||||
@ -259,9 +259,11 @@ export class FileResourceStore implements ResourceStore {
|
|||||||
// Metadata file doesn't exist so lets keep `rawMetaData` an empty array.
|
// Metadata file doesn't exist so lets keep `rawMetaData` an empty array.
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadata = new RepresentationMetadata(containerURI).addQuads(rawMetadata)
|
const metadata = new RepresentationMetadata(containerURI, {
|
||||||
.set(DCTERMS.modified, toTypedLiteral(stats.mtime.toISOString(), XSD.dateTime))
|
[DCTERMS.modified]: toTypedLiteral(stats.mtime.toISOString(), XSD.dateTime),
|
||||||
.set(CONTENT_TYPE, INTERNAL_QUADS);
|
[CONTENT_TYPE]: INTERNAL_QUADS,
|
||||||
|
});
|
||||||
|
metadata.addQuads(rawMetadata);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
binary: false,
|
binary: false,
|
||||||
@ -278,7 +280,8 @@ export class FileResourceStore implements ResourceStore {
|
|||||||
*
|
*
|
||||||
* @returns A promise containing all quads.
|
* @returns A promise containing all quads.
|
||||||
*/
|
*/
|
||||||
private async getDirChildrenQuadRepresentation(files: string[], path: string, containerURI: string): Promise<Quad[]> {
|
private async getDirChildrenQuadRepresentation(files: string[], path: string, containerURI: NamedNode):
|
||||||
|
Promise<Quad[]> {
|
||||||
const quads: Quad[] = [];
|
const quads: Quad[] = [];
|
||||||
const childURIs: string[] = [];
|
const childURIs: string[] = [];
|
||||||
for (const childName of files) {
|
for (const childName of files) {
|
||||||
@ -290,7 +293,9 @@ export class FileResourceStore implements ResourceStore {
|
|||||||
const childLink = await this.resourceMapper
|
const childLink = await this.resourceMapper
|
||||||
.mapFilePathToUrl(joinPath(path, childName), childStats.isDirectory());
|
.mapFilePathToUrl(joinPath(path, childName), childStats.isDirectory());
|
||||||
|
|
||||||
quads.push(...this.metadataController.generateResourceQuads(childLink.identifier.path, childStats));
|
const subject = DataFactory.namedNode(childLink.identifier.path);
|
||||||
|
quads.push(...this.metadataController.generateResourceQuads(subject, childStats.isDirectory()));
|
||||||
|
quads.push(...this.generatePosixQuads(subject, childStats));
|
||||||
childURIs.push(childLink.identifier.path);
|
childURIs.push(childLink.identifier.path);
|
||||||
} catch {
|
} catch {
|
||||||
// Skip the child if there is an error.
|
// Skip the child if there is an error.
|
||||||
@ -302,6 +307,21 @@ export class FileResourceStore implements ResourceStore {
|
|||||||
return quads.concat(containsQuads);
|
return quads.concat(containsQuads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to add file system related metadata
|
||||||
|
* @param subject - Subject for the new quads.
|
||||||
|
* @param stats - Stats of the file/directory corresponding to the resource.
|
||||||
|
*/
|
||||||
|
private generatePosixQuads(subject: NamedNode, stats: Stats): Quad[] {
|
||||||
|
const quads: Quad[] = [];
|
||||||
|
pushQuad(quads, subject, toNamedNode(POSIX.size), toTypedLiteral(stats.size, XSD.integer));
|
||||||
|
pushQuad(quads, subject, toNamedNode(DCTERMS.modified), toTypedLiteral(stats.mtime.toISOString(), XSD.dateTime));
|
||||||
|
pushQuad(quads, subject, toNamedNode(POSIX.mtime), toTypedLiteral(
|
||||||
|
Math.floor(stats.mtime.getTime() / 1000), XSD.integer,
|
||||||
|
));
|
||||||
|
return quads;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to (re)write file for the resource if no container with that identifier exists.
|
* Helper function to (re)write file for the resource if no container with that identifier exists.
|
||||||
* @param path - The path to the directory of the file.
|
* @param path - The path to the directory of the file.
|
||||||
|
@ -1,35 +1,31 @@
|
|||||||
import type { Stats } from 'fs';
|
|
||||||
import type { Readable } from 'stream';
|
import type { Readable } from 'stream';
|
||||||
import arrayifyStream from 'arrayify-stream';
|
import arrayifyStream from 'arrayify-stream';
|
||||||
import { DataFactory, StreamParser, StreamWriter } from 'n3';
|
import { DataFactory, StreamParser, StreamWriter } from 'n3';
|
||||||
import type { Quad } from 'rdf-js';
|
import type { NamedNode, Quad } from 'rdf-js';
|
||||||
import streamifyArray from 'streamify-array';
|
import streamifyArray from 'streamify-array';
|
||||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||||
import { TEXT_TURTLE } from './ContentTypes';
|
import { TEXT_TURTLE } from './ContentTypes';
|
||||||
import { DCTERMS, LDP, POSIX, RDF, XSD } from './UriConstants';
|
import { LDP, RDF } from './UriConstants';
|
||||||
import { toNamedNode, toTypedLiteral } from './UriUtil';
|
import { toNamedNode } from './UriUtil';
|
||||||
import { pipeStreamsAndErrors } from './Util';
|
import { pipeStreamsAndErrors, pushQuad } from './Util';
|
||||||
|
|
||||||
export class MetadataController {
|
export class MetadataController {
|
||||||
/**
|
/**
|
||||||
* Helper function to generate quads for a Container or Resource.
|
* Helper function to generate type quads for a Container or Resource.
|
||||||
* @param uri - The URI for which the quads should be generated.
|
* @param subject - Subject for the new quads.
|
||||||
* @param stats - The Stats of the subject.
|
* @param isContainer - If the identifier corresponds to a container.
|
||||||
*
|
*
|
||||||
* @returns The generated quads.
|
* @returns The generated quads.
|
||||||
*/
|
*/
|
||||||
public generateResourceQuads(uri: string, stats: Stats): Quad[] {
|
public generateResourceQuads(subject: NamedNode, isContainer: boolean): Quad[] {
|
||||||
const metadata = new RepresentationMetadata(uri);
|
const quads: Quad[] = [];
|
||||||
if (stats.isDirectory()) {
|
if (isContainer) {
|
||||||
metadata.add(RDF.type, toNamedNode(LDP.Container));
|
pushQuad(quads, subject, toNamedNode(RDF.type), toNamedNode(LDP.Container));
|
||||||
metadata.add(RDF.type, toNamedNode(LDP.BasicContainer));
|
pushQuad(quads, subject, toNamedNode(RDF.type), toNamedNode(LDP.BasicContainer));
|
||||||
}
|
}
|
||||||
metadata.add(RDF.type, toNamedNode(LDP.Resource));
|
pushQuad(quads, subject, toNamedNode(RDF.type), toNamedNode(LDP.Resource));
|
||||||
metadata.add(POSIX.size, toTypedLiteral(stats.size, XSD.integer));
|
|
||||||
metadata.add(DCTERMS.modified, toTypedLiteral(stats.mtime.toISOString(), XSD.dateTime));
|
|
||||||
metadata.add(POSIX.mtime, toTypedLiteral(Math.floor(stats.mtime.getTime() / 1000), XSD.integer));
|
|
||||||
|
|
||||||
return metadata.quads();
|
return quads;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +35,7 @@ export class MetadataController {
|
|||||||
*
|
*
|
||||||
* @returns The generated quads.
|
* @returns The generated quads.
|
||||||
*/
|
*/
|
||||||
public generateContainerContainsResourceQuads(containerURI: string, childURIs: string[]): Quad[] {
|
public generateContainerContainsResourceQuads(containerURI: NamedNode, childURIs: string[]): Quad[] {
|
||||||
return new RepresentationMetadata(containerURI, { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads();
|
return new RepresentationMetadata(containerURI, { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import type { Readable, Writable } from 'stream';
|
import type { Readable, Writable } from 'stream';
|
||||||
import arrayifyStream from 'arrayify-stream';
|
import arrayifyStream from 'arrayify-stream';
|
||||||
|
import { DataFactory } from 'n3';
|
||||||
|
import type { Literal, NamedNode, Quad } from 'rdf-js';
|
||||||
import { UnsupportedHttpError } from './errors/UnsupportedHttpError';
|
import { UnsupportedHttpError } from './errors/UnsupportedHttpError';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,3 +86,10 @@ export const decodeUriPathComponents = (path: string): string => path.split('/')
|
|||||||
* Encodes all (non-slash) special characters in a URI path.
|
* Encodes all (non-slash) special characters in a URI path.
|
||||||
*/
|
*/
|
||||||
export const encodeUriPathComponents = (path: string): string => path.split('/').map(encodeURIComponent).join('/');
|
export const encodeUriPathComponents = (path: string): string => path.split('/').map(encodeURIComponent).join('/');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a quad with the given subject/predicate/object and pushes it to the given array.
|
||||||
|
*/
|
||||||
|
export const pushQuad =
|
||||||
|
(quads: Quad[], subject: NamedNode, predicate: NamedNode, object: NamedNode | Literal): number =>
|
||||||
|
quads.push(DataFactory.quad(subject, predicate, object));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user