From f9a20799eb4a8a211ef1316f49ee3cedad0187e7 Mon Sep 17 00:00:00 2001 From: Ruben Verborgh Date: Wed, 6 Jan 2021 11:24:43 +0100 Subject: [PATCH] refactor: Use declarations style for functions. --- .eslintrc.js | 2 + .../representation/RepresentationMetadata.ts | 4 +- src/ldp/representation/ResourceIdentifier.ts | 4 +- src/logging/LogUtil.ts | 14 +-- src/storage/conversion/ConversionUtil.ts | 16 ++-- src/storage/mapping/MapperUtil.ts | 13 +-- src/util/GuardedStream.ts | 17 ++-- src/util/HeaderUtil.ts | 89 ++++++++++--------- src/util/PathUtil.ts | 49 ++++++---- src/util/QuadUtil.ts | 16 ++-- src/util/ResourceUtil.ts | 10 ++- src/util/StreamUtil.ts | 15 ++-- src/util/TermUtil.ts | 23 ++--- src/util/Vocabularies.ts | 27 +++--- src/util/errors/SystemError.ts | 4 +- test/integration/Config.ts | 19 ++-- .../TemplatedResourcesGenerator.test.ts | 4 +- .../unit/storage/LockingResourceStore.test.ts | 10 +-- .../accessors/SparqlDataAccessor.test.ts | 4 +- .../patch/SparqlUpdatePatchHandler.test.ts | 4 +- .../WrappedExpiringResourceLocker.test.ts | 4 +- test/util/TestHelpers.ts | 4 +- test/util/Util.ts | 18 ++-- 23 files changed, 208 insertions(+), 162 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 960fc6e08..a9552b7e7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -48,6 +48,8 @@ module.exports = { 'class-methods-use-this': 'off', 'comma-dangle': [ 'error', 'always-multiline' ], 'dot-location': [ 'error', 'property' ], + // Allow declaring overloads in TypeScript (https://eslint.org/docs/rules/func-style) + 'func-style': [ 'error', 'declaration' ], 'generator-star-spacing': [ 'error', 'after' ], // Conflicts with padded-blocks 'lines-around-comment': 'off', diff --git a/src/ldp/representation/RepresentationMetadata.ts b/src/ldp/representation/RepresentationMetadata.ts index f71cf167b..890663116 100644 --- a/src/ldp/representation/RepresentationMetadata.ts +++ b/src/ldp/representation/RepresentationMetadata.ts @@ -12,9 +12,9 @@ export type MetadataOverrideValue = NamedNode | Literal | string | (NamedNode | /** * Determines whether the object is a `RepresentationMetadata`. */ -export const isRepresentationMetadata = function(object: any): object is RepresentationMetadata { +export function isRepresentationMetadata(object: any): object is RepresentationMetadata { return typeof object?.setMetadata === 'function'; -}; +} /** * Stores the metadata triples and provides methods for easy access. diff --git a/src/ldp/representation/ResourceIdentifier.ts b/src/ldp/representation/ResourceIdentifier.ts index ff0c7b9a4..f8f9c2923 100644 --- a/src/ldp/representation/ResourceIdentifier.ts +++ b/src/ldp/representation/ResourceIdentifier.ts @@ -11,6 +11,6 @@ export interface ResourceIdentifier { /** * Determines whether the object is a `ResourceIdentifier`. */ -export const isResourceIdentifier = function(object: any): object is ResourceIdentifier { +export function isResourceIdentifier(object: any): object is ResourceIdentifier { return object && (typeof object.path === 'string'); -}; +} diff --git a/src/logging/LogUtil.ts b/src/logging/LogUtil.ts index 745429833..f285230c8 100644 --- a/src/logging/LogUtil.ts +++ b/src/logging/LogUtil.ts @@ -20,17 +20,19 @@ import type { LoggerFactory } from './LoggerFactory'; * * @param loggable - A class instance or a class string name. */ -export const getLoggerFor = (loggable: string | Instance): Logger => LazyLoggerFactory.getInstance() - .createLogger(typeof loggable === 'string' ? loggable : loggable.constructor.name); +export function getLoggerFor(loggable: string | Instance): Logger { + return LazyLoggerFactory.getInstance() + .createLogger(typeof loggable === 'string' ? loggable : loggable.constructor.name); +} /** * Sets the global logger factory. * This will cause all loggers created by {@link getLoggerFor} to be delegated to a logger from the given factory. * @param loggerFactory - A logger factory. */ -export const setGlobalLoggerFactory = (loggerFactory: LoggerFactory): void => { +export function setGlobalLoggerFactory(loggerFactory: LoggerFactory): void { LazyLoggerFactory.getInstance().loggerFactory = loggerFactory; -}; +} /** * Resets the global logger factory to undefined. @@ -38,7 +40,9 @@ export const setGlobalLoggerFactory = (loggerFactory: LoggerFactory): void => { * This typically only needs to be called during testing. * Call this at your own risk. */ -export const resetGlobalLoggerFactory = (): void => LazyLoggerFactory.getInstance().resetLoggerFactory(); +export function resetGlobalLoggerFactory(): void { + LazyLoggerFactory.getInstance().resetLoggerFactory(); +} /** * Helper interface to identify class instances. diff --git a/src/storage/conversion/ConversionUtil.ts b/src/storage/conversion/ConversionUtil.ts index 1cfc9e40f..f574febcc 100644 --- a/src/storage/conversion/ConversionUtil.ts +++ b/src/storage/conversion/ConversionUtil.ts @@ -18,8 +18,8 @@ import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpErr * * @returns The weighted and filtered list of matching types. */ -export const matchingMediaTypes = (preferredTypes: ValuePreferences = {}, availableTypes: ValuePreferences = {}): -string[] => { +export function matchingMediaTypes(preferredTypes: ValuePreferences = {}, availableTypes: ValuePreferences = {}): +string[] { // No preference means anything is acceptable const preferred = { ...preferredTypes }; if (Object.keys(preferredTypes).length === 0) { @@ -53,7 +53,7 @@ string[] => { .filter(([ , weight ]): boolean => weight !== 0) .sort(([ , weightA ], [ , weightB ]): number => weightB - weightA) .map(([ type ]): string => type); -}; +} /** * Checks if the given two media types/ranges match each other. @@ -63,7 +63,7 @@ string[] => { * * @returns True if the media type patterns can match each other. */ -export const matchesMediaType = (mediaA: string, mediaB: string): boolean => { +export function matchesMediaType(mediaA: string, mediaB: string): boolean { if (mediaA === mediaB) { return true; } @@ -80,7 +80,7 @@ export const matchesMediaType = (mediaA: string, mediaB: string): boolean => { return true; } return subTypeA === subTypeB; -}; +} /** * Determines whether the given conversion request is supported, @@ -94,10 +94,10 @@ export const matchesMediaType = (mediaA: string, mediaB: string): boolean => { * @param convertorIn - Media types that can be parsed by the converter. * @param convertorOut - Media types that can be produced by the converter. */ -export const supportsMediaTypeConversion = ( +export function supportsMediaTypeConversion( inputType = 'unknown', outputTypes: ValuePreferences = {}, convertorIn: ValuePreferences = {}, convertorOut: ValuePreferences = {}, -): void => { +): void { if (!Object.keys(convertorIn).some((type): boolean => matchesMediaType(inputType, type)) || matchingMediaTypes(outputTypes, convertorOut).length === 0) { throw new NotImplementedHttpError( @@ -105,4 +105,4 @@ export const supportsMediaTypeConversion = ( }, only from ${Object.keys(convertorIn)} to ${Object.keys(convertorOut)}.`, ); } -}; +} diff --git a/src/storage/mapping/MapperUtil.ts b/src/storage/mapping/MapperUtil.ts index f68f00520..5d919ea98 100644 --- a/src/storage/mapping/MapperUtil.ts +++ b/src/storage/mapping/MapperUtil.ts @@ -14,8 +14,9 @@ const logger = getLoggerFor('MapperUtil'); * * @returns Absolute path of the file. */ -export const getAbsolutePath = (rootFilepath: string, path: string, identifier = ''): string => - joinFilePath(rootFilepath, path, identifier); +export function getAbsolutePath(rootFilepath: string, path: string, identifier = ''): string { + return joinFilePath(rootFilepath, path, identifier); +} /** * Strips the baseRequestURI from the identifier and checks if the stripped base URI matches the store's one. @@ -27,13 +28,13 @@ export const getAbsolutePath = (rootFilepath: string, path: string, identifier = * * @returns A string representing the relative path. */ -export const getRelativePath = (baseRequestURI: string, identifier: ResourceIdentifier): string => { +export function getRelativePath(baseRequestURI: string, identifier: ResourceIdentifier): string { if (!identifier.path.startsWith(baseRequestURI)) { logger.warn(`The URL ${identifier.path} is outside of the scope ${baseRequestURI}`); throw new NotFoundHttpError(); } return decodeUriPathComponents(identifier.path.slice(baseRequestURI.length)); -}; +} /** * Check if the given relative path is valid. @@ -44,7 +45,7 @@ export const getRelativePath = (baseRequestURI: string, identifier: ResourceIden * @param path - A relative path, as generated by {@link getRelativePath}. * @param identifier - A resource identifier. */ -export const validateRelativePath = (path: string, identifier: ResourceIdentifier): void => { +export function validateRelativePath(path: string, identifier: ResourceIdentifier): void { if (!path.startsWith('/')) { logger.warn(`URL ${identifier.path} needs a / after the base`); throw new BadRequestHttpError('URL needs a / after the base'); @@ -54,4 +55,4 @@ export const validateRelativePath = (path: string, identifier: ResourceIdentifie logger.warn(`Disallowed /.. segment in URL ${identifier.path}.`); throw new BadRequestHttpError('Disallowed /.. segment in URL'); } -}; +} diff --git a/src/util/GuardedStream.ts b/src/util/GuardedStream.ts index e64fad6f3..2fc95a78d 100644 --- a/src/util/GuardedStream.ts +++ b/src/util/GuardedStream.ts @@ -24,7 +24,9 @@ export type Guarded = T & G /** * Determines whether the stream is guarded from emitting errors. */ -export const isGuarded = (stream: T): stream is Guarded => guardedErrors in stream; +export function isGuarded(stream: T): stream is Guarded { + return guardedErrors in stream; +} /** * Makes sure that listeners always receive the error event of a stream, @@ -34,20 +36,20 @@ export const isGuarded = (stream: T): stream is G * * @returns The stream. */ -export const guardStream = (stream: T): Guarded => { +export function guardStream(stream: T): Guarded { const guarded = stream as Guarded; if (!isGuarded(stream)) { guarded[guardedErrors] = []; attachDefaultErrorListener.call(guarded, 'error'); } return guarded; -}; +} /** * Callback that is used when a stream emits an error and no error listener is attached. * Used to store the error and start the logger timer. */ -const defaultErrorListener = function(this: Guarded, error: Error): void { +function defaultErrorListener(this: Guarded, error: Error): void { this[guardedErrors].push(error); if (!this[guardedTimeout]) { this[guardedTimeout] = setTimeout((): void => { @@ -55,14 +57,13 @@ const defaultErrorListener = function(this: Guarded, error: Error): void { logger.error(message, { error }); }, 1000); } -}; +} /** * Callback that is used when a new listener is attached to remove the current error-related fallback functions, * or to emit an error if one was thrown in the meantime. */ -const removeDefaultErrorListener = function(this: Guarded, event: string): -void { +function removeDefaultErrorListener(this: Guarded, event: string): void { if (event === 'error') { // Remove default guard listeners (but reattach when all error listeners are removed) this.removeListener('error', defaultErrorListener); @@ -86,7 +87,7 @@ void { }); } } -}; +} /** * Callback that is used to make sure the error-related fallback functions are re-applied diff --git a/src/util/HeaderUtil.ts b/src/util/HeaderUtil.ts index fa1bc5f74..7c9d47276 100644 --- a/src/util/HeaderUtil.ts +++ b/src/util/HeaderUtil.ts @@ -108,7 +108,7 @@ const token = /^[a-zA-Z0-9!#$%&'*+-.^_`|~]+$/u; * * @returns The transformed string and a map with keys `"0"`, etc. and values the original string that was there. */ -export const transformQuotedStrings = (input: string): { result: string; replacements: Record } => { +export function transformQuotedStrings(input: string): { result: string; replacements: Record } { let idx = 0; const replacements: Record = {}; const result = input.replace(/"(?:[^"\\]|\\.)*"/gu, (match): string => { @@ -123,17 +123,18 @@ export const transformQuotedStrings = (input: string): { result: string; replace return replacement; }); return { result, replacements }; -}; +} /** * Splits the input string on commas, trims all parts and filters out empty ones. * * @param input - Input header string. */ -export const splitAndClean = (input: string): string[] => - input.split(',') +export function splitAndClean(input: string): string[] { + return input.split(',') .map((part): string => part.trim()) .filter((part): boolean => part.length > 0); +} /** * Checks if the input string matches the qvalue regex. @@ -143,14 +144,14 @@ export const splitAndClean = (input: string): string[] => * @throws {@link BadRequestHttpError} * Thrown on invalid syntax. */ -const testQValue = (qvalue: string): void => { +function testQValue(qvalue: string): void { if (!/^(?:(?:0(?:\.\d{0,3})?)|(?:1(?:\.0{0,3})?))$/u.test(qvalue)) { logger.warn(`Invalid q value: ${qvalue}`); throw new BadRequestHttpError( `Invalid q value: ${qvalue} does not match ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] ).`, ); } -}; +} /** * Parses a list of split parameters and checks their validity. @@ -164,28 +165,30 @@ const testQValue = (qvalue: string): void => { * * @returns An array of name/value objects corresponding to the parameters. */ -export const parseParameters = (parameters: string[], replacements: Record): -{ name: string; value: string }[] => parameters.map((param): { name: string; value: string } => { - const [ name, rawValue ] = param.split('=').map((str): string => str.trim()); +export function parseParameters(parameters: string[], replacements: Record): +{ name: string; value: string }[] { + return parameters.map((param): { name: string; value: string } => { + const [ name, rawValue ] = param.split('=').map((str): string => str.trim()); - // Test replaced string for easier check - // parameter = token "=" ( token / quoted-string ) - // second part is optional for certain parameters - if (!(token.test(name) && (!rawValue || /^"\d+"$/u.test(rawValue) || token.test(rawValue)))) { - logger.warn(`Invalid parameter value: ${name}=${replacements[rawValue] || rawValue}`); - throw new BadRequestHttpError( - `Invalid parameter value: ${name}=${replacements[rawValue] || rawValue} ` + - `does not match (token ( "=" ( token / quoted-string ))?). `, - ); - } + // Test replaced string for easier check + // parameter = token "=" ( token / quoted-string ) + // second part is optional for certain parameters + if (!(token.test(name) && (!rawValue || /^"\d+"$/u.test(rawValue) || token.test(rawValue)))) { + logger.warn(`Invalid parameter value: ${name}=${replacements[rawValue] || rawValue}`); + throw new BadRequestHttpError( + `Invalid parameter value: ${name}=${replacements[rawValue] || rawValue} ` + + `does not match (token ( "=" ( token / quoted-string ))?). `, + ); + } - let value = rawValue; - if (value in replacements) { - value = replacements[rawValue]; - } + let value = rawValue; + if (value in replacements) { + value = replacements[rawValue]; + } - return { name, value }; -}); + return { name, value }; + }); +} /** * Parses a single media range with corresponding parameters from an Accept header. @@ -201,7 +204,7 @@ export const parseParameters = (parameters: string[], replacements: Record): Accept => { +function parseAcceptPart(part: string, replacements: Record): Accept { const [ range, ...parameters ] = part.split(';').map((param): string => param.trim()); // No reason to test differently for * since we don't check if the type exists @@ -242,7 +245,7 @@ const parseAcceptPart = (part: string, replacements: Record): Ac extension: extensionParams, }, }; -}; +} /** * Parses an Accept-* header where each part is only a value and a weight, so roughly /.*(q=.*)?/ separated by commas. @@ -253,7 +256,7 @@ const parseAcceptPart = (part: string, replacements: Record): Ac * * @returns An array of ranges and weights. */ -const parseNoParameters = (input: string): AcceptHeader[] => { +function parseNoParameters(input: string): AcceptHeader[] { const parts = splitAndClean(input); return parts.map((part): AcceptHeader => { @@ -270,7 +273,7 @@ const parseNoParameters = (input: string): AcceptHeader[] => { } return result; }).sort((left, right): number => right.weight - left.weight); -}; +} // EXPORTED FUNCTIONS @@ -284,13 +287,13 @@ const parseNoParameters = (input: string): AcceptHeader[] => { * * @returns An array of {@link Accept} objects, sorted by weight. */ -export const parseAccept = (input: string): Accept[] => { +export function parseAccept(input: string): Accept[] { // Quoted strings could prevent split from having correct results const { result, replacements } = transformQuotedStrings(input); return splitAndClean(result) .map((part): Accept => parseAcceptPart(part, replacements)) .sort((left, right): number => right.weight - left.weight); -}; +} /** * Parses an Accept-Charset header string. @@ -302,7 +305,7 @@ export const parseAccept = (input: string): Accept[] => { * * @returns An array of {@link AcceptCharset} objects, sorted by weight. */ -export const parseAcceptCharset = (input: string): AcceptCharset[] => { +export function parseAcceptCharset(input: string): AcceptCharset[] { const results = parseNoParameters(input); results.forEach((result): void => { if (!token.test(result.range)) { @@ -313,7 +316,7 @@ export const parseAcceptCharset = (input: string): AcceptCharset[] => { } }); return results; -}; +} /** * Parses an Accept-Encoding header string. @@ -325,7 +328,7 @@ export const parseAcceptCharset = (input: string): AcceptCharset[] => { * * @returns An array of {@link AcceptEncoding} objects, sorted by weight. */ -export const parseAcceptEncoding = (input: string): AcceptEncoding[] => { +export function parseAcceptEncoding(input: string): AcceptEncoding[] { const results = parseNoParameters(input); results.forEach((result): void => { if (!token.test(result.range)) { @@ -334,7 +337,7 @@ export const parseAcceptEncoding = (input: string): AcceptEncoding[] => { } }); return results; -}; +} /** * Parses an Accept-Language header string. @@ -346,7 +349,7 @@ export const parseAcceptEncoding = (input: string): AcceptEncoding[] => { * * @returns An array of {@link AcceptLanguage} objects, sorted by weight. */ -export const parseAcceptLanguage = (input: string): AcceptLanguage[] => { +export function parseAcceptLanguage(input: string): AcceptLanguage[] { const results = parseNoParameters(input); results.forEach((result): void => { // (1*8ALPHA *("-" 1*8alphanum)) / "*" @@ -360,7 +363,7 @@ export const parseAcceptLanguage = (input: string): AcceptLanguage[] => { } }); return results; -}; +} // eslint-disable-next-line max-len const rfc1123Date = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/u; @@ -372,7 +375,7 @@ const rfc1123Date = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr| * * @returns An array with a single {@link AcceptDatetime} object. */ -export const parseAcceptDateTime = (input: string): AcceptDatetime[] => { +export function parseAcceptDateTime(input: string): AcceptDatetime[] { const results: AcceptDatetime[] = []; const range = input.trim(); if (range) { @@ -387,12 +390,12 @@ export const parseAcceptDateTime = (input: string): AcceptDatetime[] => { results.push({ range, weight: 1 }); } return results; -}; +} /** * Adds a header value without overriding previous values. */ -export const addHeader = (response: HttpResponse, name: string, value: string | string[]): void => { +export function addHeader(response: HttpResponse, name: string, value: string | string[]): void { let allValues: string[] = []; if (response.hasHeader(name)) { let oldValues = response.getHeader(name)!; @@ -409,7 +412,7 @@ export const addHeader = (response: HttpResponse, name: string, value: string | allValues.push(value); } response.setHeader(name, allValues.length === 1 ? allValues[0] : allValues); -}; +} /** * The Forwarded header from RFC7239 @@ -432,7 +435,7 @@ export interface Forwarded { * * @returns The parsed Forwarded header. */ -export const parseForwarded = (value = ''): Forwarded => { +export function parseForwarded(value = ''): Forwarded { const forwarded: Record = {}; if (value) { for (const pair of value.replace(/\s*,.*$/u, '').split(';')) { @@ -443,4 +446,4 @@ export const parseForwarded = (value = ''): Forwarded => { } } return forwarded; -}; +} diff --git a/src/util/PathUtil.ts b/src/util/PathUtil.ts index a25966f16..57e8e7d39 100644 --- a/src/util/PathUtil.ts +++ b/src/util/PathUtil.ts @@ -8,7 +8,9 @@ import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifie * * @returns The potentially changed path (POSIX). */ -const windowsToPosixPath = (path: string): string => path.replace(/\\+/gu, '/'); +function windowsToPosixPath(path: string): string { + return path.replace(/\\+/gu, '/'); +} /** * Resolves relative segments in the path/ @@ -17,8 +19,9 @@ const windowsToPosixPath = (path: string): string => path.replace(/\\+/gu, '/'); * * @returns The potentially changed path (POSIX). */ -export const normalizeFilePath = (path: string): string => - posix.normalize(windowsToPosixPath(path)); +export function normalizeFilePath(path: string): string { + return posix.normalize(windowsToPosixPath(path)); +} /** * Adds the paths to the base path. @@ -28,8 +31,9 @@ export const normalizeFilePath = (path: string): string => * * @returns The potentially changed path (POSIX). */ -export const joinFilePath = (basePath: string, ...paths: string[]): string => - posix.join(windowsToPosixPath(basePath), ...paths); +export function joinFilePath(basePath: string, ...paths: string[]): string { + return posix.join(windowsToPosixPath(basePath), ...paths); +} /** * Converts the path into an OS-dependent path. @@ -38,8 +42,9 @@ export const joinFilePath = (basePath: string, ...paths: string[]): string => * * @returns The potentially changed path (OS-dependent). */ -export const toSystemFilePath = (path: string): string => - platform.normalize(path); +export function toSystemFilePath(path: string): string { + return platform.normalize(path); +} /** * Makes sure the input path has exactly 1 slash at the end. @@ -50,7 +55,9 @@ export const toSystemFilePath = (path: string): string => * * @returns The potentially changed path. */ -export const ensureTrailingSlash = (path: string): string => path.replace(/\/*$/u, '/'); +export function ensureTrailingSlash(path: string): string { + return path.replace(/\/*$/u, '/'); +} /** * Makes sure the input path has no slashes at the end. @@ -59,34 +66,46 @@ export const ensureTrailingSlash = (path: string): string => path.replace(/\/*$/ * * @returns The potentially changed path. */ -export const trimTrailingSlashes = (path: string): string => path.replace(/\/+$/u, ''); +export function trimTrailingSlashes(path: string): string { + return path.replace(/\/+$/u, ''); +} /** * Converts a URI path to the canonical version by splitting on slashes, * decoding any percent-based encodings, * and then encoding any special characters. */ -export const toCanonicalUriPath = (path: string): string => path.split('/').map((part): string => - encodeURIComponent(decodeURIComponent(part))).join('/'); +export function toCanonicalUriPath(path: string): string { + return path.split('/').map((part): string => + encodeURIComponent(decodeURIComponent(part))).join('/'); +} /** * Decodes all components of a URI path. */ -export const decodeUriPathComponents = (path: string): string => path.split('/').map(decodeURIComponent).join('/'); +export function decodeUriPathComponents(path: string): string { + return path.split('/').map(decodeURIComponent).join('/'); +} /** * Encodes all (non-slash) special characters in a URI path. */ -export const encodeUriPathComponents = (path: string): string => path.split('/').map(encodeURIComponent).join('/'); +export function encodeUriPathComponents(path: string): string { + return path.split('/').map(encodeURIComponent).join('/'); +} /** * Checks if the path corresponds to a container path (ending in a /). * @param path - Path to check. */ -export const isContainerPath = (path: string): boolean => path.endsWith('/'); +export function isContainerPath(path: string): boolean { + return path.endsWith('/'); +} /** * Checks if the identifier corresponds to a container identifier. * @param identifier - Identifier to check. */ -export const isContainerIdentifier = (identifier: ResourceIdentifier): boolean => isContainerPath(identifier.path); +export function isContainerIdentifier(identifier: ResourceIdentifier): boolean { + return isContainerPath(identifier.path); +} diff --git a/src/util/QuadUtil.ts b/src/util/QuadUtil.ts index 1c6dd4082..1a1299c5c 100644 --- a/src/util/QuadUtil.ts +++ b/src/util/QuadUtil.ts @@ -10,14 +10,14 @@ import { toSubjectTerm, toPredicateTerm, toObjectTerm } from './TermUtil'; /** * Generates a quad with the given subject/predicate/object and pushes it to the given array. */ -export const pushQuad = ( +export function pushQuad( quads: Quad[] | PassThrough, subject: string | NamedNode, predicate: string | NamedNode, object: string | NamedNode | Literal, -): void => { +): void { quads.push(DataFactory.quad(toSubjectTerm(subject), toPredicateTerm(predicate), toObjectTerm(object))); -}; +} /** * Helper function for serializing an array of quads, with as result a Readable object. @@ -26,8 +26,9 @@ export const pushQuad = ( * * @returns The Readable object. */ -export const serializeQuads = (quads: Quad[], contentType?: string): Guarded => - pipeSafely(streamifyArray(quads), new StreamWriter({ format: contentType })); +export function serializeQuads(quads: Quad[], contentType?: string): Guarded { + return pipeSafely(streamifyArray(quads), new StreamWriter({ format: contentType })); +} /** * Helper function to convert a Readable into an array of quads. @@ -36,5 +37,6 @@ export const serializeQuads = (quads: Quad[], contentType?: string): Guarded, contentType?: string): Promise => - arrayifyStream(pipeSafely(readable, new StreamParser({ format: contentType }))); +export async function parseQuads(readable: Guarded, contentType?: string): Promise { + return arrayifyStream(pipeSafely(readable, new StreamParser({ format: contentType }))); +} diff --git a/src/util/ResourceUtil.ts b/src/util/ResourceUtil.ts index 98ce2f9a7..6c6482b67 100644 --- a/src/util/ResourceUtil.ts +++ b/src/util/ResourceUtil.ts @@ -11,7 +11,7 @@ import { LDP, RDF } from './Vocabularies'; * * @returns The generated quads. */ -export const generateResourceQuads = (subject: NamedNode, isContainer: boolean): Quad[] => { +export function generateResourceQuads(subject: NamedNode, isContainer: boolean): Quad[] { const quads: Quad[] = []; if (isContainer) { pushQuad(quads, subject, RDF.terms.type, LDP.terms.Container); @@ -20,7 +20,7 @@ export const generateResourceQuads = (subject: NamedNode, isContainer: boolean): pushQuad(quads, subject, RDF.terms.type, LDP.terms.Resource); return quads; -}; +} /** * Helper function to generate the quads describing that the resource URIs are children of the container URI. @@ -29,5 +29,7 @@ export const generateResourceQuads = (subject: NamedNode, isContainer: boolean): * * @returns The generated quads. */ -export const generateContainmentQuads = (containerURI: NamedNode, childURIs: string[]): Quad[] => - new RepresentationMetadata(containerURI, { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads(); +export function generateContainmentQuads(containerURI: NamedNode, childURIs: string[]): Quad[] { + return new RepresentationMetadata(containerURI, + { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads(); +} diff --git a/src/util/StreamUtil.ts b/src/util/StreamUtil.ts index e5198cb13..6e3ab02c9 100644 --- a/src/util/StreamUtil.ts +++ b/src/util/StreamUtil.ts @@ -13,7 +13,9 @@ const logger = getLoggerFor('StreamUtil'); * * @returns The joined string. */ -export const readableToString = async(stream: Readable): Promise => (await arrayifyStream(stream)).join(''); +export async function readableToString(stream: Readable): Promise { + return (await arrayifyStream(stream)).join(''); +} /** * Pipes one stream into another and emits errors of the first stream with the second. @@ -25,8 +27,8 @@ export const readableToString = async(stream: Readable): Promise => (awa * * @returns The destination stream. */ -export const pipeSafely = (readable: NodeJS.ReadableStream, destination: T, - mapError?: (error: Error) => Error): Guarded => { +export function pipeSafely(readable: NodeJS.ReadableStream, destination: T, + mapError?: (error: Error) => Error): Guarded { // Not using `stream.pipeline` since the result there only emits an error event if the last stream has the error readable.pipe(destination); readable.on('error', (error): void => { @@ -39,12 +41,13 @@ export const pipeSafely = (readable: NodeJS.ReadableStream, destination.destroy(mapError ? mapError(error) : error); }); return guardStream(destination); -}; +} /** * Converts an iterable to a stream and applies an error guard so that it is {@link Guarded}. * @param iterable - Data to stream. * @param options - Options to pass to the Readable constructor. See {@link Readable.from}. */ -export const guardedStreamFrom = (iterable: Iterable, options?: ReadableOptions): Guarded => - guardStream(Readable.from(iterable, options)); +export function guardedStreamFrom(iterable: Iterable, options?: ReadableOptions): Guarded { + return guardStream(Readable.from(iterable, options)); +} diff --git a/src/util/TermUtil.ts b/src/util/TermUtil.ts index 940e2bf00..51d5f6c1a 100644 --- a/src/util/TermUtil.ts +++ b/src/util/TermUtil.ts @@ -20,7 +20,7 @@ const cachedNamedNodes: Record = { * so only use this for internal constants! * @param name - Predicate to potentially transform. */ -export const toCachedNamedNode = (name: NamedNode | string): NamedNode => { +export function toCachedNamedNode(name: NamedNode | string): NamedNode { if (typeof name !== 'string') { return name; } @@ -28,20 +28,22 @@ export const toCachedNamedNode = (name: NamedNode | string): NamedNode => { cachedNamedNodes[name] = namedNode(name); } return cachedNamedNodes[name]; -}; +} /** * @param input - Checks if this is a {@link Term}. */ -export const isTerm = (input?: any): input is Term => - input && typeof input.termType === 'string'; +export function isTerm(input?: any): input is Term { + return input && typeof input.termType === 'string'; +} /** * Converts a subject to a named node when needed. * @param subject - Subject to potentially transform. */ -export const toSubjectTerm = (subject: NamedNode | string): NamedNode => - typeof subject === 'string' ? namedNode(subject) : subject; +export function toSubjectTerm(subject: NamedNode | string): NamedNode { + return typeof subject === 'string' ? namedNode(subject) : subject; +} export const toPredicateTerm = toSubjectTerm; @@ -50,17 +52,18 @@ export const toPredicateTerm = toSubjectTerm; * @param object - Object to potentially transform. * @param preferLiteral - Whether strings are converted to literals or named nodes. */ -export const toObjectTerm = (object: T | string, preferLiteral = false): T => { +export function toObjectTerm(object: T | string, preferLiteral = false): T { if (typeof object === 'string') { return (preferLiteral ? literal(object) : namedNode(object)) as any; } return object; -}; +} /** * Creates a literal by first converting the dataType string to a named node. * @param object - Object value. * @param dataType - Object data type (as string). */ -export const toLiteral = (object: string | number, dataType: NamedNode): Literal => - literal(object, dataType); +export function toLiteral(object: string | number, dataType: NamedNode): Literal { + return literal(`${object}`, dataType); +} diff --git a/src/util/Vocabularies.ts b/src/util/Vocabularies.ts index f18fefa57..752b68c84 100644 --- a/src/util/Vocabularies.ts +++ b/src/util/Vocabularies.ts @@ -12,11 +12,11 @@ export type Namespace = * Creates a function that expands local names from the given base URI, * and exports the given local names as properties on the returned object. */ -export const createNamespace = ( +export function createNamespace( baseUri: string, toValue: (expanded: string) => TValue, ...localNames: TKey[]): -Namespace => { + Namespace { // Create a function that expands local names const expanded = {} as Record; const namespace = ((localName: string): TValue => { @@ -31,33 +31,36 @@ Namespace => { (namespace as RecordOf)[localName] = namespace(localName); } return namespace; -}; +} /** * Creates a function that expands local names from the given base URI into strings, * and exports the given local names as properties on the returned object. */ -export const createUriNamespace = (baseUri: string, ...localNames: T[]): -Namespace => - createNamespace(baseUri, (expanded): string => expanded, ...localNames); +export function createUriNamespace(baseUri: string, ...localNames: T[]): +Namespace { + return createNamespace(baseUri, (expanded): string => expanded, ...localNames); +} /** * Creates a function that expands local names from the given base URI into named nodes, * and exports the given local names as properties on the returned object. */ -export const createTermNamespace = (baseUri: string, ...localNames: T[]): -Namespace => - createNamespace(baseUri, namedNode, ...localNames); +export function createTermNamespace(baseUri: string, ...localNames: T[]): +Namespace { + return createNamespace(baseUri, namedNode, ...localNames); +} /** * Creates a function that expands local names from the given base URI into string, * and exports the given local names as properties on the returned object. * Under the `terms` property, it exposes the expanded local names as named nodes. */ -export const createUriAndTermNamespace = (baseUri: string, ...localNames: T[]): -Namespace & { terms: Namespace } => - Object.assign(createUriNamespace(baseUri, ...localNames), +export function createUriAndTermNamespace(baseUri: string, ...localNames: T[]): +Namespace & { terms: Namespace } { + return Object.assign(createUriNamespace(baseUri, ...localNames), { terms: createTermNamespace(baseUri, ...localNames) }); +} export const ACL = createUriAndTermNamespace('http://www.w3.org/ns/auth/acl#', 'accessTo', diff --git a/src/util/errors/SystemError.ts b/src/util/errors/SystemError.ts index 5d85e9a7a..ce92edde1 100644 --- a/src/util/errors/SystemError.ts +++ b/src/util/errors/SystemError.ts @@ -41,4 +41,6 @@ export interface SystemError extends Error { syscall: string; } -export const isSystemError = (error: any): error is SystemError => error.code && error.syscall; +export function isSystemError(error: any): error is SystemError { + return error.code && error.syscall; +} diff --git a/test/integration/Config.ts b/test/integration/Config.ts index c486d1f28..b1d1b395e 100644 --- a/test/integration/Config.ts +++ b/test/integration/Config.ts @@ -8,8 +8,8 @@ export const BASE = 'http://test.com'; /** * Returns a component instantiated from a Components.js configuration. */ -export const instantiateFromConfig = async(componentUrl: string, configFile: string, - variables?: Record): Promise => { +export async function instantiateFromConfig(componentUrl: string, configFile: string, + variables?: Record): Promise { // Initialize the Components.js loader const mainModulePath = joinFilePath(__dirname, '../../'); const loader = new Loader({ mainModulePath }); @@ -18,15 +18,16 @@ export const instantiateFromConfig = async(componentUrl: string, configFile: str // Instantiate the component from the config const configPath = toSystemFilePath(joinFilePath(__dirname, 'config', configFile)); return loader.instantiateFromUrl(componentUrl, configPath, undefined, { variables }); -}; +} -export const getTestFolder = (name: string): string => - joinFilePath(__dirname, '../tmp', name); +export function getTestFolder(name: string): string { + return joinFilePath(__dirname, '../tmp', name); +} -export const createFolder = (folder: string): void => { +export function createFolder(folder: string): void { mkdirSync(folder, { recursive: true }); -}; +} -export const removeFolder = (folder: string): void => { +export function removeFolder(folder: string): void { rimraf.sync(folder, { glob: false }); -}; +} diff --git a/test/unit/pods/generate/TemplatedResourcesGenerator.test.ts b/test/unit/pods/generate/TemplatedResourcesGenerator.test.ts index 531bd5279..5f387c580 100644 --- a/test/unit/pods/generate/TemplatedResourcesGenerator.test.ts +++ b/test/unit/pods/generate/TemplatedResourcesGenerator.test.ts @@ -29,13 +29,13 @@ class DummyFactory implements FileIdentifierMapperFactory { } } -const genToArray = async(iterable: AsyncIterable): Promise => { +async function genToArray(iterable: AsyncIterable): Promise { const arr: T[] = []; for await (const result of iterable) { arr.push(result); } return arr; -}; +} describe('A TemplatedResourcesGenerator', (): void => { const rootFilePath = 'templates'; diff --git a/test/unit/storage/LockingResourceStore.test.ts b/test/unit/storage/LockingResourceStore.test.ts index d53da2d55..1c5b741b8 100644 --- a/test/unit/storage/LockingResourceStore.test.ts +++ b/test/unit/storage/LockingResourceStore.test.ts @@ -21,13 +21,13 @@ describe('A LockingResourceStore', (): void => { jest.clearAllMocks(); order = []; - const delayedResolve = (resolve: (resolveParams: any) => void, name: string, resolveParams?: any): void => { + function delayedResolve(resolve: (value: any) => void, name: string, resolveValue?: any): void { // `setImmediate` is introduced to make sure the promise doesn't execute immediately setImmediate((): void => { order.push(name); - resolve(resolveParams); + resolve(resolveValue); }); - }; + } const readable = streamifyArray([ 1, 2, 3 ]); source = { @@ -70,14 +70,14 @@ describe('A LockingResourceStore', (): void => { store = new LockingResourceStore(source, locker); }); - const registerEventOrder = async(eventSource: EventEmitter, event: string): Promise => { + async function registerEventOrder(eventSource: EventEmitter, event: string): Promise { await new Promise((resolve): any => { eventSource.prependListener(event, (): any => { order.push(event); resolve(); }); }); - }; + } it('acquires a lock on the container when adding a representation.', async(): Promise => { await store.addResource({ path: 'path' }, {} as Representation); diff --git a/test/unit/storage/accessors/SparqlDataAccessor.test.ts b/test/unit/storage/accessors/SparqlDataAccessor.test.ts index 98d77b549..bd4cc14d2 100644 --- a/test/unit/storage/accessors/SparqlDataAccessor.test.ts +++ b/test/unit/storage/accessors/SparqlDataAccessor.test.ts @@ -20,12 +20,12 @@ const { literal, namedNode, quad } = DataFactory; jest.mock('fetch-sparql-endpoint'); -const simplifyQuery = (query: string | string[]): string => { +function simplifyQuery(query: string | string[]): string { if (Array.isArray(query)) { query = query.join(' '); } return query.replace(/\n/gu, ' ').trim(); -}; +} describe('A SparqlDataAccessor', (): void => { const endpoint = 'http://test.com/sparql'; diff --git a/test/unit/storage/patch/SparqlUpdatePatchHandler.test.ts b/test/unit/storage/patch/SparqlUpdatePatchHandler.test.ts index cd611760d..d16e969f6 100644 --- a/test/unit/storage/patch/SparqlUpdatePatchHandler.test.ts +++ b/test/unit/storage/patch/SparqlUpdatePatchHandler.test.ts @@ -65,7 +65,7 @@ describe('A SparqlUpdatePatchHandler', (): void => { handler = new SparqlUpdatePatchHandler(source, locker); }); - const basicChecks = async(quads: Quad[]): Promise => { + async function basicChecks(quads: Quad[]): Promise { expect(source.getRepresentation).toHaveBeenCalledTimes(1); expect(source.getRepresentation).toHaveBeenLastCalledWith( { path: 'path' }, { type: { [INTERNAL_QUADS]: 1 }}, @@ -81,7 +81,7 @@ describe('A SparqlUpdatePatchHandler', (): void => { expect(setParams[1].metadata.contentType).toEqual(INTERNAL_QUADS); await expect(arrayifyStream(setParams[1].data)).resolves.toBeRdfIsomorphic(quads); return true; - }; + } it('only accepts SPARQL updates.', async(): Promise => { const input = { identifier: { path: 'path' }, diff --git a/test/unit/util/locking/WrappedExpiringResourceLocker.test.ts b/test/unit/util/locking/WrappedExpiringResourceLocker.test.ts index 99b30a042..ed54c1fee 100644 --- a/test/unit/util/locking/WrappedExpiringResourceLocker.test.ts +++ b/test/unit/util/locking/WrappedExpiringResourceLocker.test.ts @@ -9,14 +9,14 @@ describe('A WrappedExpiringResourceLocker', (): void => { order = []; }); - const registerEventOrder = async(eventSource: EventEmitter, event: string): Promise => { + async function registerEventOrder(eventSource: EventEmitter, event: string): Promise { await new Promise((resolve): any => { eventSource.prependListener(event, (): any => { order.push(event); resolve(); }); }); - }; + } it('emits an error event when releasing the lock errors.', async(): Promise => { jest.useFakeTimers(); diff --git a/test/util/TestHelpers.ts b/test/util/TestHelpers.ts index 7f1c5847c..f50838879 100644 --- a/test/util/TestHelpers.ts +++ b/test/util/TestHelpers.ts @@ -199,9 +199,9 @@ export class ResourceHelper { } } -export const describeIf = (envFlag: string, name: string, fn: () => void): void => { +export function describeIf(envFlag: string, name: string, fn: () => void): void { const flag = `TEST_${envFlag.toUpperCase()}`; const enabled = !/^(|0|false)$/iu.test(process.env[flag] ?? ''); // eslint-disable-next-line jest/valid-describe, jest/valid-title, jest/no-disabled-tests return enabled ? describe(name, fn) : describe.skip(name, fn); -}; +} diff --git a/test/util/Util.ts b/test/util/Util.ts index 98b227345..9aa69afc8 100644 --- a/test/util/Util.ts +++ b/test/util/Util.ts @@ -9,13 +9,13 @@ import type { HttpHandler } from '../../src/server/HttpHandler'; import type { HttpRequest } from '../../src/server/HttpRequest'; import type { SystemError } from '../../src/util/errors/SystemError'; -export const performRequest = async( +export async function performRequest( handler: HttpHandler, requestUrl: URL, method: string, headers: IncomingHttpHeaders, data: string[], -): Promise> => { +): Promise> { const request = streamifyArray(data) as HttpRequest; request.url = requestUrl.pathname; request.method = method; @@ -36,7 +36,7 @@ export const performRequest = async( await endPromise; return response; -}; +} /** * Mocks (some) functions of the fs system library. @@ -56,21 +56,21 @@ export const performRequest = async( * @param rootFilepath - The name of the root folder in which fs will start. * @param time - The date object to use for time functions (currently only mtime from lstats) */ -export const mockFs = (rootFilepath?: string, time?: Date): { data: any } => { +export function mockFs(rootFilepath?: string, time?: Date): { data: any } { const cache: { data: any } = { data: {}}; rootFilepath = rootFilepath ?? 'folder'; time = time ?? new Date(); // eslint-disable-next-line unicorn/consistent-function-scoping - const throwSystemError = (code: string): void => { + function throwSystemError(code: string): void { const error = new Error('error') as SystemError; error.code = code; error.syscall = 'this exists for isSystemError'; throw error; - }; + } - const getFolder = (path: string): { folder: any; name: string } => { + function getFolder(path: string): { folder: any; name: string } { let parts = path.slice(rootFilepath!.length).split('/').filter((part): boolean => part.length > 0); if (parts.length === 0) { @@ -91,7 +91,7 @@ export const mockFs = (rootFilepath?: string, time?: Date): { data: any } => { }); return { folder, name }; - }; + } const mock = { createReadStream(path: string): any { @@ -171,4 +171,4 @@ export const mockFs = (rootFilepath?: string, time?: Date): { data: any } => { Object.assign(fs, mock); return cache; -}; +}