refactor: Use declarations style for functions.

This commit is contained in:
Ruben Verborgh 2021-01-06 11:24:43 +01:00
parent e70e060225
commit f9a20799eb
23 changed files with 208 additions and 162 deletions

View File

@ -48,6 +48,8 @@ module.exports = {
'class-methods-use-this': 'off', 'class-methods-use-this': 'off',
'comma-dangle': [ 'error', 'always-multiline' ], 'comma-dangle': [ 'error', 'always-multiline' ],
'dot-location': [ 'error', 'property' ], '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' ], 'generator-star-spacing': [ 'error', 'after' ],
// Conflicts with padded-blocks // Conflicts with padded-blocks
'lines-around-comment': 'off', 'lines-around-comment': 'off',

View File

@ -12,9 +12,9 @@ export type MetadataOverrideValue = NamedNode | Literal | string | (NamedNode |
/** /**
* Determines whether the object is a `RepresentationMetadata`. * 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'; return typeof object?.setMetadata === 'function';
}; }
/** /**
* Stores the metadata triples and provides methods for easy access. * Stores the metadata triples and provides methods for easy access.

View File

@ -11,6 +11,6 @@ export interface ResourceIdentifier {
/** /**
* Determines whether the object is a `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'); return object && (typeof object.path === 'string');
}; }

View File

@ -20,17 +20,19 @@ import type { LoggerFactory } from './LoggerFactory';
* *
* @param loggable - A class instance or a class string name. * @param loggable - A class instance or a class string name.
*/ */
export const getLoggerFor = (loggable: string | Instance): Logger => LazyLoggerFactory.getInstance() export function getLoggerFor(loggable: string | Instance): Logger {
.createLogger(typeof loggable === 'string' ? loggable : loggable.constructor.name); return LazyLoggerFactory.getInstance()
.createLogger(typeof loggable === 'string' ? loggable : loggable.constructor.name);
}
/** /**
* Sets the global logger factory. * Sets the global logger factory.
* This will cause all loggers created by {@link getLoggerFor} to be delegated to a logger from the given 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. * @param loggerFactory - A logger factory.
*/ */
export const setGlobalLoggerFactory = (loggerFactory: LoggerFactory): void => { export function setGlobalLoggerFactory(loggerFactory: LoggerFactory): void {
LazyLoggerFactory.getInstance().loggerFactory = loggerFactory; LazyLoggerFactory.getInstance().loggerFactory = loggerFactory;
}; }
/** /**
* Resets the global logger factory to undefined. * 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. * This typically only needs to be called during testing.
* Call this at your own risk. * 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. * Helper interface to identify class instances.

View File

@ -18,8 +18,8 @@ import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpErr
* *
* @returns The weighted and filtered list of matching types. * @returns The weighted and filtered list of matching types.
*/ */
export const matchingMediaTypes = (preferredTypes: ValuePreferences = {}, availableTypes: ValuePreferences = {}): export function matchingMediaTypes(preferredTypes: ValuePreferences = {}, availableTypes: ValuePreferences = {}):
string[] => { string[] {
// No preference means anything is acceptable // No preference means anything is acceptable
const preferred = { ...preferredTypes }; const preferred = { ...preferredTypes };
if (Object.keys(preferredTypes).length === 0) { if (Object.keys(preferredTypes).length === 0) {
@ -53,7 +53,7 @@ string[] => {
.filter(([ , weight ]): boolean => weight !== 0) .filter(([ , weight ]): boolean => weight !== 0)
.sort(([ , weightA ], [ , weightB ]): number => weightB - weightA) .sort(([ , weightA ], [ , weightB ]): number => weightB - weightA)
.map(([ type ]): string => type); .map(([ type ]): string => type);
}; }
/** /**
* Checks if the given two media types/ranges match each other. * 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. * @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) { if (mediaA === mediaB) {
return true; return true;
} }
@ -80,7 +80,7 @@ export const matchesMediaType = (mediaA: string, mediaB: string): boolean => {
return true; return true;
} }
return subTypeA === subTypeB; return subTypeA === subTypeB;
}; }
/** /**
* Determines whether the given conversion request is supported, * 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 convertorIn - Media types that can be parsed by the converter.
* @param convertorOut - Media types that can be produced by the converter. * @param convertorOut - Media types that can be produced by the converter.
*/ */
export const supportsMediaTypeConversion = ( export function supportsMediaTypeConversion(
inputType = 'unknown', outputTypes: ValuePreferences = {}, inputType = 'unknown', outputTypes: ValuePreferences = {},
convertorIn: ValuePreferences = {}, convertorOut: ValuePreferences = {}, convertorIn: ValuePreferences = {}, convertorOut: ValuePreferences = {},
): void => { ): void {
if (!Object.keys(convertorIn).some((type): boolean => matchesMediaType(inputType, type)) || if (!Object.keys(convertorIn).some((type): boolean => matchesMediaType(inputType, type)) ||
matchingMediaTypes(outputTypes, convertorOut).length === 0) { matchingMediaTypes(outputTypes, convertorOut).length === 0) {
throw new NotImplementedHttpError( throw new NotImplementedHttpError(
@ -105,4 +105,4 @@ export const supportsMediaTypeConversion = (
}, only from ${Object.keys(convertorIn)} to ${Object.keys(convertorOut)}.`, }, only from ${Object.keys(convertorIn)} to ${Object.keys(convertorOut)}.`,
); );
} }
}; }

View File

@ -14,8 +14,9 @@ const logger = getLoggerFor('MapperUtil');
* *
* @returns Absolute path of the file. * @returns Absolute path of the file.
*/ */
export const getAbsolutePath = (rootFilepath: string, path: string, identifier = ''): string => export function getAbsolutePath(rootFilepath: string, path: string, identifier = ''): string {
joinFilePath(rootFilepath, path, identifier); return joinFilePath(rootFilepath, path, identifier);
}
/** /**
* Strips the baseRequestURI from the identifier and checks if the stripped base URI matches the store's one. * 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. * @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)) { if (!identifier.path.startsWith(baseRequestURI)) {
logger.warn(`The URL ${identifier.path} is outside of the scope ${baseRequestURI}`); logger.warn(`The URL ${identifier.path} is outside of the scope ${baseRequestURI}`);
throw new NotFoundHttpError(); throw new NotFoundHttpError();
} }
return decodeUriPathComponents(identifier.path.slice(baseRequestURI.length)); return decodeUriPathComponents(identifier.path.slice(baseRequestURI.length));
}; }
/** /**
* Check if the given relative path is valid. * 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 path - A relative path, as generated by {@link getRelativePath}.
* @param identifier - A resource identifier. * @param identifier - A resource identifier.
*/ */
export const validateRelativePath = (path: string, identifier: ResourceIdentifier): void => { export function validateRelativePath(path: string, identifier: ResourceIdentifier): void {
if (!path.startsWith('/')) { if (!path.startsWith('/')) {
logger.warn(`URL ${identifier.path} needs a / after the base`); logger.warn(`URL ${identifier.path} needs a / after the base`);
throw new BadRequestHttpError('URL 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}.`); logger.warn(`Disallowed /.. segment in URL ${identifier.path}.`);
throw new BadRequestHttpError('Disallowed /.. segment in URL'); throw new BadRequestHttpError('Disallowed /.. segment in URL');
} }
}; }

View File

@ -24,7 +24,9 @@ export type Guarded<T extends NodeJS.EventEmitter = NodeJS.EventEmitter> = T & G
/** /**
* Determines whether the stream is guarded from emitting errors. * Determines whether the stream is guarded from emitting errors.
*/ */
export const isGuarded = <T extends NodeJS.EventEmitter>(stream: T): stream is Guarded<T> => guardedErrors in stream; export function isGuarded<T extends NodeJS.EventEmitter>(stream: T): stream is Guarded<T> {
return guardedErrors in stream;
}
/** /**
* Makes sure that listeners always receive the error event of a stream, * Makes sure that listeners always receive the error event of a stream,
@ -34,20 +36,20 @@ export const isGuarded = <T extends NodeJS.EventEmitter>(stream: T): stream is G
* *
* @returns The stream. * @returns The stream.
*/ */
export const guardStream = <T extends NodeJS.EventEmitter>(stream: T): Guarded<T> => { export function guardStream<T extends NodeJS.EventEmitter>(stream: T): Guarded<T> {
const guarded = stream as Guarded<T>; const guarded = stream as Guarded<T>;
if (!isGuarded(stream)) { if (!isGuarded(stream)) {
guarded[guardedErrors] = []; guarded[guardedErrors] = [];
attachDefaultErrorListener.call(guarded, 'error'); attachDefaultErrorListener.call(guarded, 'error');
} }
return guarded; return guarded;
}; }
/** /**
* Callback that is used when a stream emits an error and no error listener is attached. * 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. * 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); this[guardedErrors].push(error);
if (!this[guardedTimeout]) { if (!this[guardedTimeout]) {
this[guardedTimeout] = setTimeout((): void => { this[guardedTimeout] = setTimeout((): void => {
@ -55,14 +57,13 @@ const defaultErrorListener = function(this: Guarded, error: Error): void {
logger.error(message, { error }); logger.error(message, { error });
}, 1000); }, 1000);
} }
}; }
/** /**
* Callback that is used when a new listener is attached to remove the current error-related fallback functions, * 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. * or to emit an error if one was thrown in the meantime.
*/ */
const removeDefaultErrorListener = function(this: Guarded, event: string): function removeDefaultErrorListener(this: Guarded, event: string): void {
void {
if (event === 'error') { if (event === 'error') {
// Remove default guard listeners (but reattach when all error listeners are removed) // Remove default guard listeners (but reattach when all error listeners are removed)
this.removeListener('error', defaultErrorListener); this.removeListener('error', defaultErrorListener);
@ -86,7 +87,7 @@ void {
}); });
} }
} }
}; }
/** /**
* Callback that is used to make sure the error-related fallback functions are re-applied * Callback that is used to make sure the error-related fallback functions are re-applied

View File

@ -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. * @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<string, string> } => { export function transformQuotedStrings(input: string): { result: string; replacements: Record<string, string> } {
let idx = 0; let idx = 0;
const replacements: Record<string, string> = {}; const replacements: Record<string, string> = {};
const result = input.replace(/"(?:[^"\\]|\\.)*"/gu, (match): string => { const result = input.replace(/"(?:[^"\\]|\\.)*"/gu, (match): string => {
@ -123,17 +123,18 @@ export const transformQuotedStrings = (input: string): { result: string; replace
return replacement; return replacement;
}); });
return { result, replacements }; return { result, replacements };
}; }
/** /**
* Splits the input string on commas, trims all parts and filters out empty ones. * Splits the input string on commas, trims all parts and filters out empty ones.
* *
* @param input - Input header string. * @param input - Input header string.
*/ */
export const splitAndClean = (input: string): string[] => export function splitAndClean(input: string): string[] {
input.split(',') return input.split(',')
.map((part): string => part.trim()) .map((part): string => part.trim())
.filter((part): boolean => part.length > 0); .filter((part): boolean => part.length > 0);
}
/** /**
* Checks if the input string matches the qvalue regex. * Checks if the input string matches the qvalue regex.
@ -143,14 +144,14 @@ export const splitAndClean = (input: string): string[] =>
* @throws {@link BadRequestHttpError} * @throws {@link BadRequestHttpError}
* Thrown on invalid syntax. * 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)) { if (!/^(?:(?:0(?:\.\d{0,3})?)|(?:1(?:\.0{0,3})?))$/u.test(qvalue)) {
logger.warn(`Invalid q value: ${qvalue}`); logger.warn(`Invalid q value: ${qvalue}`);
throw new BadRequestHttpError( throw new BadRequestHttpError(
`Invalid q value: ${qvalue} does not match ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] ).`, `Invalid q value: ${qvalue} does not match ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] ).`,
); );
} }
}; }
/** /**
* Parses a list of split parameters and checks their validity. * 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. * @returns An array of name/value objects corresponding to the parameters.
*/ */
export const parseParameters = (parameters: string[], replacements: Record<string, string>): export function parseParameters(parameters: string[], replacements: Record<string, string>):
{ name: string; value: string }[] => parameters.map((param): { name: string; value: string } => { { name: string; value: string }[] {
const [ name, rawValue ] = param.split('=').map((str): string => str.trim()); return parameters.map((param): { name: string; value: string } => {
const [ name, rawValue ] = param.split('=').map((str): string => str.trim());
// Test replaced string for easier check // Test replaced string for easier check
// parameter = token "=" ( token / quoted-string ) // parameter = token "=" ( token / quoted-string )
// second part is optional for certain parameters // second part is optional for certain parameters
if (!(token.test(name) && (!rawValue || /^"\d+"$/u.test(rawValue) || token.test(rawValue)))) { if (!(token.test(name) && (!rawValue || /^"\d+"$/u.test(rawValue) || token.test(rawValue)))) {
logger.warn(`Invalid parameter value: ${name}=${replacements[rawValue] || rawValue}`); logger.warn(`Invalid parameter value: ${name}=${replacements[rawValue] || rawValue}`);
throw new BadRequestHttpError( throw new BadRequestHttpError(
`Invalid parameter value: ${name}=${replacements[rawValue] || rawValue} ` + `Invalid parameter value: ${name}=${replacements[rawValue] || rawValue} ` +
`does not match (token ( "=" ( token / quoted-string ))?). `, `does not match (token ( "=" ( token / quoted-string ))?). `,
); );
} }
let value = rawValue; let value = rawValue;
if (value in replacements) { if (value in replacements) {
value = replacements[rawValue]; value = replacements[rawValue];
} }
return { name, value }; return { name, value };
}); });
}
/** /**
* Parses a single media range with corresponding parameters from an Accept header. * Parses a single media range with corresponding parameters from an Accept header.
@ -201,7 +204,7 @@ export const parseParameters = (parameters: string[], replacements: Record<strin
* *
* @returns {@link Accept} object corresponding to the header string. * @returns {@link Accept} object corresponding to the header string.
*/ */
const parseAcceptPart = (part: string, replacements: Record<string, string>): Accept => { function parseAcceptPart(part: string, replacements: Record<string, string>): Accept {
const [ range, ...parameters ] = part.split(';').map((param): string => param.trim()); 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 // 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<string, string>): Ac
extension: extensionParams, extension: extensionParams,
}, },
}; };
}; }
/** /**
* Parses an Accept-* header where each part is only a value and a weight, so roughly /.*(q=.*)?/ separated by commas. * 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<string, string>): Ac
* *
* @returns An array of ranges and weights. * @returns An array of ranges and weights.
*/ */
const parseNoParameters = (input: string): AcceptHeader[] => { function parseNoParameters(input: string): AcceptHeader[] {
const parts = splitAndClean(input); const parts = splitAndClean(input);
return parts.map((part): AcceptHeader => { return parts.map((part): AcceptHeader => {
@ -270,7 +273,7 @@ const parseNoParameters = (input: string): AcceptHeader[] => {
} }
return result; return result;
}).sort((left, right): number => right.weight - left.weight); }).sort((left, right): number => right.weight - left.weight);
}; }
// EXPORTED FUNCTIONS // EXPORTED FUNCTIONS
@ -284,13 +287,13 @@ const parseNoParameters = (input: string): AcceptHeader[] => {
* *
* @returns An array of {@link Accept} objects, sorted by weight. * @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 // Quoted strings could prevent split from having correct results
const { result, replacements } = transformQuotedStrings(input); const { result, replacements } = transformQuotedStrings(input);
return splitAndClean(result) return splitAndClean(result)
.map((part): Accept => parseAcceptPart(part, replacements)) .map((part): Accept => parseAcceptPart(part, replacements))
.sort((left, right): number => right.weight - left.weight); .sort((left, right): number => right.weight - left.weight);
}; }
/** /**
* Parses an Accept-Charset header string. * 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. * @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); const results = parseNoParameters(input);
results.forEach((result): void => { results.forEach((result): void => {
if (!token.test(result.range)) { if (!token.test(result.range)) {
@ -313,7 +316,7 @@ export const parseAcceptCharset = (input: string): AcceptCharset[] => {
} }
}); });
return results; return results;
}; }
/** /**
* Parses an Accept-Encoding header string. * 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. * @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); const results = parseNoParameters(input);
results.forEach((result): void => { results.forEach((result): void => {
if (!token.test(result.range)) { if (!token.test(result.range)) {
@ -334,7 +337,7 @@ export const parseAcceptEncoding = (input: string): AcceptEncoding[] => {
} }
}); });
return results; return results;
}; }
/** /**
* Parses an Accept-Language header string. * 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. * @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); const results = parseNoParameters(input);
results.forEach((result): void => { results.forEach((result): void => {
// (1*8ALPHA *("-" 1*8alphanum)) / "*" // (1*8ALPHA *("-" 1*8alphanum)) / "*"
@ -360,7 +363,7 @@ export const parseAcceptLanguage = (input: string): AcceptLanguage[] => {
} }
}); });
return results; return results;
}; }
// eslint-disable-next-line max-len // 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; 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. * @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 results: AcceptDatetime[] = [];
const range = input.trim(); const range = input.trim();
if (range) { if (range) {
@ -387,12 +390,12 @@ export const parseAcceptDateTime = (input: string): AcceptDatetime[] => {
results.push({ range, weight: 1 }); results.push({ range, weight: 1 });
} }
return results; return results;
}; }
/** /**
* Adds a header value without overriding previous values. * 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[] = []; let allValues: string[] = [];
if (response.hasHeader(name)) { if (response.hasHeader(name)) {
let oldValues = response.getHeader(name)!; let oldValues = response.getHeader(name)!;
@ -409,7 +412,7 @@ export const addHeader = (response: HttpResponse, name: string, value: string |
allValues.push(value); allValues.push(value);
} }
response.setHeader(name, allValues.length === 1 ? allValues[0] : allValues); response.setHeader(name, allValues.length === 1 ? allValues[0] : allValues);
}; }
/** /**
* The Forwarded header from RFC7239 * The Forwarded header from RFC7239
@ -432,7 +435,7 @@ export interface Forwarded {
* *
* @returns The parsed Forwarded header. * @returns The parsed Forwarded header.
*/ */
export const parseForwarded = (value = ''): Forwarded => { export function parseForwarded(value = ''): Forwarded {
const forwarded: Record<string, string> = {}; const forwarded: Record<string, string> = {};
if (value) { if (value) {
for (const pair of value.replace(/\s*,.*$/u, '').split(';')) { for (const pair of value.replace(/\s*,.*$/u, '').split(';')) {
@ -443,4 +446,4 @@ export const parseForwarded = (value = ''): Forwarded => {
} }
} }
return forwarded; return forwarded;
}; }

View File

@ -8,7 +8,9 @@ import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifie
* *
* @returns The potentially changed path (POSIX). * @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/ * Resolves relative segments in the path/
@ -17,8 +19,9 @@ const windowsToPosixPath = (path: string): string => path.replace(/\\+/gu, '/');
* *
* @returns The potentially changed path (POSIX). * @returns The potentially changed path (POSIX).
*/ */
export const normalizeFilePath = (path: string): string => export function normalizeFilePath(path: string): string {
posix.normalize(windowsToPosixPath(path)); return posix.normalize(windowsToPosixPath(path));
}
/** /**
* Adds the paths to the base path. * Adds the paths to the base path.
@ -28,8 +31,9 @@ export const normalizeFilePath = (path: string): string =>
* *
* @returns The potentially changed path (POSIX). * @returns The potentially changed path (POSIX).
*/ */
export const joinFilePath = (basePath: string, ...paths: string[]): string => export function joinFilePath(basePath: string, ...paths: string[]): string {
posix.join(windowsToPosixPath(basePath), ...paths); return posix.join(windowsToPosixPath(basePath), ...paths);
}
/** /**
* Converts the path into an OS-dependent path. * 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). * @returns The potentially changed path (OS-dependent).
*/ */
export const toSystemFilePath = (path: string): string => export function toSystemFilePath(path: string): string {
platform.normalize(path); return platform.normalize(path);
}
/** /**
* Makes sure the input path has exactly 1 slash at the end. * 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. * @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. * 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. * @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, * Converts a URI path to the canonical version by splitting on slashes,
* decoding any percent-based encodings, * decoding any percent-based encodings,
* and then encoding any special characters. * and then encoding any special characters.
*/ */
export const toCanonicalUriPath = (path: string): string => path.split('/').map((part): string => export function toCanonicalUriPath(path: string): string {
encodeURIComponent(decodeURIComponent(part))).join('/'); return path.split('/').map((part): string =>
encodeURIComponent(decodeURIComponent(part))).join('/');
}
/** /**
* Decodes all components of a URI path. * 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. * 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 /). * Checks if the path corresponds to a container path (ending in a /).
* @param path - Path to check. * @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. * Checks if the identifier corresponds to a container identifier.
* @param identifier - Identifier to check. * @param identifier - Identifier to check.
*/ */
export const isContainerIdentifier = (identifier: ResourceIdentifier): boolean => isContainerPath(identifier.path); export function isContainerIdentifier(identifier: ResourceIdentifier): boolean {
return isContainerPath(identifier.path);
}

View File

@ -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. * 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, quads: Quad[] | PassThrough,
subject: string | NamedNode, subject: string | NamedNode,
predicate: string | NamedNode, predicate: string | NamedNode,
object: string | NamedNode | Literal, object: string | NamedNode | Literal,
): void => { ): void {
quads.push(DataFactory.quad(toSubjectTerm(subject), toPredicateTerm(predicate), toObjectTerm(object))); quads.push(DataFactory.quad(toSubjectTerm(subject), toPredicateTerm(predicate), toObjectTerm(object)));
}; }
/** /**
* Helper function for serializing an array of quads, with as result a Readable 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. * @returns The Readable object.
*/ */
export const serializeQuads = (quads: Quad[], contentType?: string): Guarded<Readable> => export function serializeQuads(quads: Quad[], contentType?: string): Guarded<Readable> {
pipeSafely(streamifyArray(quads), new StreamWriter({ format: contentType })); return pipeSafely(streamifyArray(quads), new StreamWriter({ format: contentType }));
}
/** /**
* Helper function to convert a Readable into an array of quads. * Helper function to convert a Readable into an array of quads.
@ -36,5 +37,6 @@ export const serializeQuads = (quads: Quad[], contentType?: string): Guarded<Rea
* *
* @returns A promise containing the array of quads. * @returns A promise containing the array of quads.
*/ */
export const parseQuads = async(readable: Guarded<Readable>, contentType?: string): Promise<Quad[]> => export async function parseQuads(readable: Guarded<Readable>, contentType?: string): Promise<Quad[]> {
arrayifyStream(pipeSafely(readable, new StreamParser({ format: contentType }))); return arrayifyStream(pipeSafely(readable, new StreamParser({ format: contentType })));
}

View File

@ -11,7 +11,7 @@ import { LDP, RDF } from './Vocabularies';
* *
* @returns The generated quads. * @returns The generated quads.
*/ */
export const generateResourceQuads = (subject: NamedNode, isContainer: boolean): Quad[] => { export function generateResourceQuads(subject: NamedNode, isContainer: boolean): Quad[] {
const quads: Quad[] = []; const quads: Quad[] = [];
if (isContainer) { if (isContainer) {
pushQuad(quads, subject, RDF.terms.type, LDP.terms.Container); 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); pushQuad(quads, subject, RDF.terms.type, LDP.terms.Resource);
return quads; return quads;
}; }
/** /**
* Helper function to generate the quads describing that the resource URIs are children of the container URI. * 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. * @returns The generated quads.
*/ */
export const generateContainmentQuads = (containerURI: NamedNode, childURIs: string[]): Quad[] => export function generateContainmentQuads(containerURI: NamedNode, childURIs: string[]): Quad[] {
new RepresentationMetadata(containerURI, { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads(); return new RepresentationMetadata(containerURI,
{ [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads();
}

View File

@ -13,7 +13,9 @@ const logger = getLoggerFor('StreamUtil');
* *
* @returns The joined string. * @returns The joined string.
*/ */
export const readableToString = async(stream: Readable): Promise<string> => (await arrayifyStream(stream)).join(''); export async function readableToString(stream: Readable): Promise<string> {
return (await arrayifyStream(stream)).join('');
}
/** /**
* Pipes one stream into another and emits errors of the first stream with the second. * 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<string> => (awa
* *
* @returns The destination stream. * @returns The destination stream.
*/ */
export const pipeSafely = <T extends Writable>(readable: NodeJS.ReadableStream, destination: T, export function pipeSafely<T extends Writable>(readable: NodeJS.ReadableStream, destination: T,
mapError?: (error: Error) => Error): Guarded<T> => { mapError?: (error: Error) => Error): Guarded<T> {
// Not using `stream.pipeline` since the result there only emits an error event if the last stream has the error // Not using `stream.pipeline` since the result there only emits an error event if the last stream has the error
readable.pipe(destination); readable.pipe(destination);
readable.on('error', (error): void => { readable.on('error', (error): void => {
@ -39,12 +41,13 @@ export const pipeSafely = <T extends Writable>(readable: NodeJS.ReadableStream,
destination.destroy(mapError ? mapError(error) : error); destination.destroy(mapError ? mapError(error) : error);
}); });
return guardStream(destination); return guardStream(destination);
}; }
/** /**
* Converts an iterable to a stream and applies an error guard so that it is {@link Guarded}. * Converts an iterable to a stream and applies an error guard so that it is {@link Guarded}.
* @param iterable - Data to stream. * @param iterable - Data to stream.
* @param options - Options to pass to the Readable constructor. See {@link Readable.from}. * @param options - Options to pass to the Readable constructor. See {@link Readable.from}.
*/ */
export const guardedStreamFrom = (iterable: Iterable<any>, options?: ReadableOptions): Guarded<Readable> => export function guardedStreamFrom(iterable: Iterable<any>, options?: ReadableOptions): Guarded<Readable> {
guardStream(Readable.from(iterable, options)); return guardStream(Readable.from(iterable, options));
}

View File

@ -20,7 +20,7 @@ const cachedNamedNodes: Record<string, NamedNode> = {
* so only use this for internal constants! * so only use this for internal constants!
* @param name - Predicate to potentially transform. * @param name - Predicate to potentially transform.
*/ */
export const toCachedNamedNode = (name: NamedNode | string): NamedNode => { export function toCachedNamedNode(name: NamedNode | string): NamedNode {
if (typeof name !== 'string') { if (typeof name !== 'string') {
return name; return name;
} }
@ -28,20 +28,22 @@ export const toCachedNamedNode = (name: NamedNode | string): NamedNode => {
cachedNamedNodes[name] = namedNode(name); cachedNamedNodes[name] = namedNode(name);
} }
return cachedNamedNodes[name]; return cachedNamedNodes[name];
}; }
/** /**
* @param input - Checks if this is a {@link Term}. * @param input - Checks if this is a {@link Term}.
*/ */
export const isTerm = (input?: any): input is Term => export function isTerm(input?: any): input is Term {
input && typeof input.termType === 'string'; return input && typeof input.termType === 'string';
}
/** /**
* Converts a subject to a named node when needed. * Converts a subject to a named node when needed.
* @param subject - Subject to potentially transform. * @param subject - Subject to potentially transform.
*/ */
export const toSubjectTerm = (subject: NamedNode | string): NamedNode => export function toSubjectTerm(subject: NamedNode | string): NamedNode {
typeof subject === 'string' ? namedNode(subject) : subject; return typeof subject === 'string' ? namedNode(subject) : subject;
}
export const toPredicateTerm = toSubjectTerm; export const toPredicateTerm = toSubjectTerm;
@ -50,17 +52,18 @@ export const toPredicateTerm = toSubjectTerm;
* @param object - Object to potentially transform. * @param object - Object to potentially transform.
* @param preferLiteral - Whether strings are converted to literals or named nodes. * @param preferLiteral - Whether strings are converted to literals or named nodes.
*/ */
export const toObjectTerm = <T extends Term>(object: T | string, preferLiteral = false): T => { export function toObjectTerm<T extends Term>(object: T | string, preferLiteral = false): T {
if (typeof object === 'string') { if (typeof object === 'string') {
return (preferLiteral ? literal(object) : namedNode(object)) as any; return (preferLiteral ? literal(object) : namedNode(object)) as any;
} }
return object; return object;
}; }
/** /**
* Creates a literal by first converting the dataType string to a named node. * Creates a literal by first converting the dataType string to a named node.
* @param object - Object value. * @param object - Object value.
* @param dataType - Object data type (as string). * @param dataType - Object data type (as string).
*/ */
export const toLiteral = (object: string | number, dataType: NamedNode): Literal => export function toLiteral(object: string | number, dataType: NamedNode): Literal {
literal(object, dataType); return literal(`${object}`, dataType);
}

View File

@ -12,11 +12,11 @@ export type Namespace<TKey extends any[], TValue> =
* Creates a function that expands local names from the given base URI, * Creates a function that expands local names from the given base URI,
* and exports the given local names as properties on the returned object. * and exports the given local names as properties on the returned object.
*/ */
export const createNamespace = <TKey extends string, TValue>( export function createNamespace<TKey extends string, TValue>(
baseUri: string, baseUri: string,
toValue: (expanded: string) => TValue, toValue: (expanded: string) => TValue,
...localNames: TKey[]): ...localNames: TKey[]):
Namespace<typeof localNames, TValue> => { Namespace<typeof localNames, TValue> {
// Create a function that expands local names // Create a function that expands local names
const expanded = {} as Record<string, TValue>; const expanded = {} as Record<string, TValue>;
const namespace = ((localName: string): TValue => { const namespace = ((localName: string): TValue => {
@ -31,33 +31,36 @@ Namespace<typeof localNames, TValue> => {
(namespace as RecordOf<typeof localNames, TValue>)[localName] = namespace(localName); (namespace as RecordOf<typeof localNames, TValue>)[localName] = namespace(localName);
} }
return namespace; return namespace;
}; }
/** /**
* Creates a function that expands local names from the given base URI into strings, * 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. * and exports the given local names as properties on the returned object.
*/ */
export const createUriNamespace = <T extends string>(baseUri: string, ...localNames: T[]): export function createUriNamespace<T extends string>(baseUri: string, ...localNames: T[]):
Namespace<typeof localNames, string> => Namespace<typeof localNames, string> {
createNamespace(baseUri, (expanded): string => expanded, ...localNames); return createNamespace(baseUri, (expanded): string => expanded, ...localNames);
}
/** /**
* Creates a function that expands local names from the given base URI into named nodes, * 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. * and exports the given local names as properties on the returned object.
*/ */
export const createTermNamespace = <T extends string>(baseUri: string, ...localNames: T[]): export function createTermNamespace<T extends string>(baseUri: string, ...localNames: T[]):
Namespace<typeof localNames, NamedNode> => Namespace<typeof localNames, NamedNode> {
createNamespace(baseUri, namedNode, ...localNames); return createNamespace(baseUri, namedNode, ...localNames);
}
/** /**
* Creates a function that expands local names from the given base URI into string, * 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. * 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. * Under the `terms` property, it exposes the expanded local names as named nodes.
*/ */
export const createUriAndTermNamespace = <T extends string>(baseUri: string, ...localNames: T[]): export function createUriAndTermNamespace<T extends string>(baseUri: string, ...localNames: T[]):
Namespace<typeof localNames, string> & { terms: Namespace<typeof localNames, NamedNode> } => Namespace<typeof localNames, string> & { terms: Namespace<typeof localNames, NamedNode> } {
Object.assign(createUriNamespace(baseUri, ...localNames), return Object.assign(createUriNamespace(baseUri, ...localNames),
{ terms: createTermNamespace(baseUri, ...localNames) }); { terms: createTermNamespace(baseUri, ...localNames) });
}
export const ACL = createUriAndTermNamespace('http://www.w3.org/ns/auth/acl#', export const ACL = createUriAndTermNamespace('http://www.w3.org/ns/auth/acl#',
'accessTo', 'accessTo',

View File

@ -41,4 +41,6 @@ export interface SystemError extends Error {
syscall: string; 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;
}

View File

@ -8,8 +8,8 @@ export const BASE = 'http://test.com';
/** /**
* Returns a component instantiated from a Components.js configuration. * Returns a component instantiated from a Components.js configuration.
*/ */
export const instantiateFromConfig = async(componentUrl: string, configFile: string, export async function instantiateFromConfig(componentUrl: string, configFile: string,
variables?: Record<string, any>): Promise<any> => { variables?: Record<string, any>): Promise<any> {
// Initialize the Components.js loader // Initialize the Components.js loader
const mainModulePath = joinFilePath(__dirname, '../../'); const mainModulePath = joinFilePath(__dirname, '../../');
const loader = new Loader({ mainModulePath }); const loader = new Loader({ mainModulePath });
@ -18,15 +18,16 @@ export const instantiateFromConfig = async(componentUrl: string, configFile: str
// Instantiate the component from the config // Instantiate the component from the config
const configPath = toSystemFilePath(joinFilePath(__dirname, 'config', configFile)); const configPath = toSystemFilePath(joinFilePath(__dirname, 'config', configFile));
return loader.instantiateFromUrl(componentUrl, configPath, undefined, { variables }); return loader.instantiateFromUrl(componentUrl, configPath, undefined, { variables });
}; }
export const getTestFolder = (name: string): string => export function getTestFolder(name: string): string {
joinFilePath(__dirname, '../tmp', name); return joinFilePath(__dirname, '../tmp', name);
}
export const createFolder = (folder: string): void => { export function createFolder(folder: string): void {
mkdirSync(folder, { recursive: true }); mkdirSync(folder, { recursive: true });
}; }
export const removeFolder = (folder: string): void => { export function removeFolder(folder: string): void {
rimraf.sync(folder, { glob: false }); rimraf.sync(folder, { glob: false });
}; }

View File

@ -29,13 +29,13 @@ class DummyFactory implements FileIdentifierMapperFactory {
} }
} }
const genToArray = async<T>(iterable: AsyncIterable<T>): Promise<T[]> => { async function genToArray<T>(iterable: AsyncIterable<T>): Promise<T[]> {
const arr: T[] = []; const arr: T[] = [];
for await (const result of iterable) { for await (const result of iterable) {
arr.push(result); arr.push(result);
} }
return arr; return arr;
}; }
describe('A TemplatedResourcesGenerator', (): void => { describe('A TemplatedResourcesGenerator', (): void => {
const rootFilePath = 'templates'; const rootFilePath = 'templates';

View File

@ -21,13 +21,13 @@ describe('A LockingResourceStore', (): void => {
jest.clearAllMocks(); jest.clearAllMocks();
order = []; 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` is introduced to make sure the promise doesn't execute immediately
setImmediate((): void => { setImmediate((): void => {
order.push(name); order.push(name);
resolve(resolveParams); resolve(resolveValue);
}); });
}; }
const readable = streamifyArray([ 1, 2, 3 ]); const readable = streamifyArray([ 1, 2, 3 ]);
source = { source = {
@ -70,14 +70,14 @@ describe('A LockingResourceStore', (): void => {
store = new LockingResourceStore(source, locker); store = new LockingResourceStore(source, locker);
}); });
const registerEventOrder = async(eventSource: EventEmitter, event: string): Promise<void> => { async function registerEventOrder(eventSource: EventEmitter, event: string): Promise<void> {
await new Promise((resolve): any => { await new Promise((resolve): any => {
eventSource.prependListener(event, (): any => { eventSource.prependListener(event, (): any => {
order.push(event); order.push(event);
resolve(); resolve();
}); });
}); });
}; }
it('acquires a lock on the container when adding a representation.', async(): Promise<void> => { it('acquires a lock on the container when adding a representation.', async(): Promise<void> => {
await store.addResource({ path: 'path' }, {} as Representation); await store.addResource({ path: 'path' }, {} as Representation);

View File

@ -20,12 +20,12 @@ const { literal, namedNode, quad } = DataFactory;
jest.mock('fetch-sparql-endpoint'); jest.mock('fetch-sparql-endpoint');
const simplifyQuery = (query: string | string[]): string => { function simplifyQuery(query: string | string[]): string {
if (Array.isArray(query)) { if (Array.isArray(query)) {
query = query.join(' '); query = query.join(' ');
} }
return query.replace(/\n/gu, ' ').trim(); return query.replace(/\n/gu, ' ').trim();
}; }
describe('A SparqlDataAccessor', (): void => { describe('A SparqlDataAccessor', (): void => {
const endpoint = 'http://test.com/sparql'; const endpoint = 'http://test.com/sparql';

View File

@ -65,7 +65,7 @@ describe('A SparqlUpdatePatchHandler', (): void => {
handler = new SparqlUpdatePatchHandler(source, locker); handler = new SparqlUpdatePatchHandler(source, locker);
}); });
const basicChecks = async(quads: Quad[]): Promise<boolean> => { async function basicChecks(quads: Quad[]): Promise<boolean> {
expect(source.getRepresentation).toHaveBeenCalledTimes(1); expect(source.getRepresentation).toHaveBeenCalledTimes(1);
expect(source.getRepresentation).toHaveBeenLastCalledWith( expect(source.getRepresentation).toHaveBeenLastCalledWith(
{ path: 'path' }, { type: { [INTERNAL_QUADS]: 1 }}, { path: 'path' }, { type: { [INTERNAL_QUADS]: 1 }},
@ -81,7 +81,7 @@ describe('A SparqlUpdatePatchHandler', (): void => {
expect(setParams[1].metadata.contentType).toEqual(INTERNAL_QUADS); expect(setParams[1].metadata.contentType).toEqual(INTERNAL_QUADS);
await expect(arrayifyStream(setParams[1].data)).resolves.toBeRdfIsomorphic(quads); await expect(arrayifyStream(setParams[1].data)).resolves.toBeRdfIsomorphic(quads);
return true; return true;
}; }
it('only accepts SPARQL updates.', async(): Promise<void> => { it('only accepts SPARQL updates.', async(): Promise<void> => {
const input = { identifier: { path: 'path' }, const input = { identifier: { path: 'path' },

View File

@ -9,14 +9,14 @@ describe('A WrappedExpiringResourceLocker', (): void => {
order = []; order = [];
}); });
const registerEventOrder = async(eventSource: EventEmitter, event: string): Promise<void> => { async function registerEventOrder(eventSource: EventEmitter, event: string): Promise<void> {
await new Promise((resolve): any => { await new Promise((resolve): any => {
eventSource.prependListener(event, (): any => { eventSource.prependListener(event, (): any => {
order.push(event); order.push(event);
resolve(); resolve();
}); });
}); });
}; }
it('emits an error event when releasing the lock errors.', async(): Promise<void> => { it('emits an error event when releasing the lock errors.', async(): Promise<void> => {
jest.useFakeTimers(); jest.useFakeTimers();

View File

@ -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 flag = `TEST_${envFlag.toUpperCase()}`;
const enabled = !/^(|0|false)$/iu.test(process.env[flag] ?? ''); const enabled = !/^(|0|false)$/iu.test(process.env[flag] ?? '');
// eslint-disable-next-line jest/valid-describe, jest/valid-title, jest/no-disabled-tests // eslint-disable-next-line jest/valid-describe, jest/valid-title, jest/no-disabled-tests
return enabled ? describe(name, fn) : describe.skip(name, fn); return enabled ? describe(name, fn) : describe.skip(name, fn);
}; }

View File

@ -9,13 +9,13 @@ import type { HttpHandler } from '../../src/server/HttpHandler';
import type { HttpRequest } from '../../src/server/HttpRequest'; import type { HttpRequest } from '../../src/server/HttpRequest';
import type { SystemError } from '../../src/util/errors/SystemError'; import type { SystemError } from '../../src/util/errors/SystemError';
export const performRequest = async( export async function performRequest(
handler: HttpHandler, handler: HttpHandler,
requestUrl: URL, requestUrl: URL,
method: string, method: string,
headers: IncomingHttpHeaders, headers: IncomingHttpHeaders,
data: string[], data: string[],
): Promise<MockResponse<any>> => { ): Promise<MockResponse<any>> {
const request = streamifyArray(data) as HttpRequest; const request = streamifyArray(data) as HttpRequest;
request.url = requestUrl.pathname; request.url = requestUrl.pathname;
request.method = method; request.method = method;
@ -36,7 +36,7 @@ export const performRequest = async(
await endPromise; await endPromise;
return response; return response;
}; }
/** /**
* Mocks (some) functions of the fs system library. * 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 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) * @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: {}}; const cache: { data: any } = { data: {}};
rootFilepath = rootFilepath ?? 'folder'; rootFilepath = rootFilepath ?? 'folder';
time = time ?? new Date(); time = time ?? new Date();
// eslint-disable-next-line unicorn/consistent-function-scoping // 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; const error = new Error('error') as SystemError;
error.code = code; error.code = code;
error.syscall = 'this exists for isSystemError'; error.syscall = 'this exists for isSystemError';
throw error; 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); let parts = path.slice(rootFilepath!.length).split('/').filter((part): boolean => part.length > 0);
if (parts.length === 0) { if (parts.length === 0) {
@ -91,7 +91,7 @@ export const mockFs = (rootFilepath?: string, time?: Date): { data: any } => {
}); });
return { folder, name }; return { folder, name };
}; }
const mock = { const mock = {
createReadStream(path: string): any { createReadStream(path: string): any {
@ -171,4 +171,4 @@ export const mockFs = (rootFilepath?: string, time?: Date): { data: any } => {
Object.assign(fs, mock); Object.assign(fs, mock);
return cache; return cache;
}; }