UNPKG

@zenfs/core

Version:

A filesystem, anywhere

73 lines (72 loc) 2.9 kB
// SPDX-License-Identifier: LGPL-3.0-or-later /* eslint-disable @typescript-eslint/no-redundant-type-constituents */ import { withErrno } from 'kerium'; import { debug, err } from 'kerium/log'; /** * @category Backends and Configuration * @internal */ export function isBackend(arg) { return arg != null && typeof arg == 'object' && 'create' in arg && typeof arg.create == 'function'; } /** * Use a function as the type of an option, but don't treat it as a class. * * Optionally sets the name of a function, useful for error messages. * @category Backends and Configuration * @internal */ export function _fnOpt(name, fn) { Object.defineProperty(fn, 'prototype', { value: undefined }); if (name) Object.defineProperty(fn, 'name', { value: name }); return fn; } function _isClass(func) { if (!(func && func.constructor === Function) || func.prototype === undefined) return false; if (Function.prototype !== Object.getPrototypeOf(func)) return true; return Object.getOwnPropertyNames(func.prototype).length > 1; } /** * Checks that `options` object is valid for the file system options. * @category Backends and Configuration * @internal */ export function checkOptions(backend, options) { if (typeof options != 'object' || options === null) { throw err(withErrno('EINVAL', 'Invalid options')); } // Check for required options. for (const [optName, opt] of Object.entries(backend.options)) { const value = options?.[optName]; if (value === undefined || value === null) { if (!opt.required) { debug('Using default for option: ' + optName); continue; } throw err(withErrno('EINVAL', 'Missing required option: ' + optName)); } const isType = (type, _ = value) => typeof type == 'function' ? _isClass(type) ? value instanceof type : type(value) : typeof value === type || value?.constructor?.name === type; if (Array.isArray(opt.type) ? opt.type.some(v => isType(v)) : isType(opt.type)) continue; // The type of the value as a string const type = typeof value == 'object' && 'constructor' in value ? value.constructor.name : typeof value; // The expected type (as a string) const name = (type) => (typeof type == 'function' ? (type.name != 'type' ? type.name : type.toString()) : type); const expected = Array.isArray(opt.type) ? `one of ${opt.type.map(name).join(', ')}` : name(opt.type); throw err(withErrno('EINVAL', `Incorrect type for "${optName}": ${type} (expected ${expected})`)); } } /** * @internal * @category Backends and Configuration */ export function isBackendConfig(arg) { return arg != null && typeof arg == 'object' && 'backend' in arg && isBackend(arg.backend); }