@boost/common
Advanced tools
Comparing version 2.8.2 to 3.0.0
@@ -1,2 +0,2 @@ | ||
import { Blueprint, Predicates } from 'optimal'; | ||
import { Blueprint, Schemas } from 'optimal'; | ||
import { Optionable } from './types'; | ||
@@ -32,4 +32,4 @@ export declare abstract class Contract<T extends object = {}> implements Optionable<T> { | ||
*/ | ||
abstract blueprint(predicates: Predicates, onConstruction?: boolean): Blueprint<object>; | ||
abstract blueprint(schemas: Schemas, onConstruction?: boolean): Blueprint<object>; | ||
} | ||
//# sourceMappingURL=Contract.d.ts.map |
@@ -6,6 +6,7 @@ import { Blueprint } from 'optimal'; | ||
* [optimal](https://github.com/milesj/optimal) checks. All supported optimal | ||
* predicates are passed as an object to the factory. | ||
* schemas are passed as an object to the factory. | ||
* | ||
* ```ts | ||
* import { optimal, createBlueprint } from '@boost/common'; | ||
* import { createBlueprint } from '@boost/common'; | ||
* import { optimal } from '@boost/common/optimal'; | ||
* | ||
@@ -17,3 +18,3 @@ * const blueprint = createBlueprint(({ string, number }) => ({ | ||
* | ||
* const data = optimal({}, blueprint); | ||
* const object = optimal(blueprint).validate({}); | ||
* ``` | ||
@@ -20,0 +21,0 @@ */ |
@@ -11,6 +11,3 @@ export * from './createBlueprint'; | ||
export * from './isPlainObject'; | ||
export * from './parseFile'; | ||
export * from './requireModule'; | ||
export * from './requireTypedModule'; | ||
export * from './toArray'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import { ModuleName } from '../types'; | ||
import { ModuleID } from '../types'; | ||
/** | ||
@@ -16,3 +16,3 @@ * Returns `true` if a string is a valid Node module package name, | ||
*/ | ||
export declare function isModuleName(name: ModuleName): boolean; | ||
export declare function isModuleName(name: ModuleID): boolean; | ||
//# sourceMappingURL=isModuleName.d.ts.map |
@@ -5,3 +5,2 @@ /** | ||
*/ | ||
import optimal, { Blueprint, Predicates, predicates } from 'optimal'; | ||
export * from './CommonError'; | ||
@@ -12,2 +11,3 @@ export * from './constants'; | ||
export * from './helpers'; | ||
export * from './ModulePath'; | ||
export * from './PackageGraph'; | ||
@@ -21,4 +21,3 @@ export * from './Path'; | ||
export * from '@boost/decorators'; | ||
export { optimal, predicates }; | ||
export type { Blueprint, Predicates }; | ||
export type { Blueprint, DeepPartial, Schemas } from 'optimal'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,14 +0,17 @@ | ||
import { FilePath, PortablePath } from './types'; | ||
export declare class Path { | ||
import { FilePath, Pathable, PortablePath } from './types'; | ||
/** | ||
* An immutable class for operating on file system paths. | ||
*/ | ||
export declare class Path implements Pathable { | ||
static DELIMITER: string; | ||
static SEP: string; | ||
private internalPath; | ||
private isNormalized; | ||
constructor(...parts: PortablePath[]); | ||
/** | ||
* Create and return a new `Path` instance if a string. | ||
* If already a `Path`, return as is. | ||
* Create and return a new `Path` instance. | ||
*/ | ||
static create(filePath: PortablePath): Path; | ||
/** | ||
* Like `create()` but also resolves the path against CWD. | ||
* Like `create()` but also resolves the path against a working directory. | ||
*/ | ||
@@ -73,3 +76,3 @@ static resolve(filePath: PortablePath, cwd?: PortablePath): Path; | ||
* Return a new `Path` instance where the current path is accurately | ||
* resolved against the defined current working directory. | ||
* resolved against the defined working directory. | ||
*/ | ||
@@ -76,0 +79,0 @@ resolve(cwd?: PortablePath): Path; |
@@ -1,3 +0,2 @@ | ||
import { Path } from './Path'; | ||
import { LookupType, ModuleResolver, PortablePath } from './types'; | ||
import { ModuleResolver, Pathable, PortablePath, ResolvedLookup } from './types'; | ||
export declare class PathResolver { | ||
@@ -7,2 +6,3 @@ private lookups; | ||
constructor(resolver?: ModuleResolver); | ||
static defaultResolver(path: string, startDir?: string): Promise<string>; | ||
/** | ||
@@ -18,20 +18,21 @@ * Return a list of all lookup paths. | ||
/** | ||
* Add a file system path with a list of possible extensions to look for, | ||
* resolved against the defined current working directory (or `process.cwd()` otherwise). | ||
*/ | ||
lookupFilePathWithExts(filePath: PortablePath, exts: string[], cwd?: PortablePath): this; | ||
/** | ||
* Add a Node.js module, either by name or relative path, to look for. | ||
*/ | ||
lookupNodeModule(modulePath: PortablePath): this; | ||
lookupNodeModule(moduleId: PortablePath): this; | ||
/** | ||
* Given a list of lookups, attempt to find the first real/existing path and | ||
* return a resolved absolute path. If a file system path, will check using `fs.exists`. | ||
* If a node module path, will check using `require.resolve`. | ||
* If a node module path, will check using the provided resolver. | ||
*/ | ||
resolve(): { | ||
originalPath: Path; | ||
resolvedPath: Path; | ||
type: LookupType; | ||
}; | ||
resolve(startDir?: PortablePath): Promise<ResolvedLookup>; | ||
/** | ||
* Like `resolve()` but only returns the resolved path. | ||
* Like `resolve()` but only returns the resolved file path. | ||
*/ | ||
resolvePath(): Path; | ||
resolvePath(): Promise<Pathable>; | ||
} | ||
//# sourceMappingURL=PathResolver.d.ts.map |
import { Path } from './Path'; | ||
import { FilePath, PackageStructure, PortablePath, WorkspaceMetadata, WorkspacePackage } from './types'; | ||
import { PackageStructure, PortablePath, WorkspaceMetadata, WorkspacePackage } from './types'; | ||
export interface ProjectSearchOptions { | ||
@@ -10,2 +10,7 @@ relative?: boolean; | ||
/** | ||
* Normalize a glob pattern or path for use on POSIX and Windows machines. | ||
* @link https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows | ||
*/ | ||
static normalizeGlob(pattern: string): string; | ||
/** | ||
* Create a workspace metadata object composed of absolute file paths. | ||
@@ -20,5 +25,6 @@ */ | ||
* Return a list of all workspace globs as they are configured | ||
* in `package.json` or `lerna.json`. | ||
* in `package.json` or `lerna.json`. Glob patterns will _always_ | ||
* use forward slashes, regardless of OS. | ||
*/ | ||
getWorkspaceGlobs(options?: ProjectSearchOptions): FilePath[]; | ||
getWorkspaceGlobs(options?: ProjectSearchOptions): string[]; | ||
/** | ||
@@ -31,5 +37,6 @@ * Return all `package.json`s across all workspaces and their packages. | ||
* Return a list of all workspace package paths, resolved against the file system. | ||
* Absolute file paths are returned unless the `relative` option is true. | ||
*/ | ||
getWorkspacePackagePaths(options?: ProjectSearchOptions): FilePath[]; | ||
getWorkspacePackagePaths(options?: ProjectSearchOptions): Path[]; | ||
} | ||
//# sourceMappingURL=Project.d.ts.map |
@@ -0,1 +1,2 @@ | ||
import { PortablePath } from '../types'; | ||
export declare type JSONReviver = (key: string, value: unknown) => unknown; | ||
@@ -9,2 +10,3 @@ export interface JSONStringifyOptions { | ||
export declare function stringify(content: unknown, options?: JSONStringifyOptions): string; | ||
export declare function load<T>(path: PortablePath): T; | ||
//# sourceMappingURL=json.d.ts.map |
import YAML from 'yaml'; | ||
import { PortablePath } from '../types'; | ||
export declare function parse<T = object>(content: string, options?: YAML.Options): T; | ||
export declare function stringify(content: unknown, options?: YAML.Options): string; | ||
export declare function load<T>(path: PortablePath): T; | ||
//# sourceMappingURL=yaml.d.ts.map |
@@ -1,25 +0,32 @@ | ||
import { Blueprint, Predicates } from 'optimal'; | ||
import type { Blueprint, Schemas } from 'optimal'; | ||
import type { Path } from './Path'; | ||
export declare type ModuleName = string; | ||
export interface Pathable { | ||
path: () => string; | ||
toString: () => string; | ||
} | ||
export declare type PortablePath = FilePath | ModuleID | Pathable; | ||
export declare type ModuleID = string; | ||
export declare type ModuleResolver = (id: ModuleID, startDir?: FilePath) => FilePath | Promise<FilePath>; | ||
export declare type FilePath = string; | ||
export declare type PortablePath = FilePath | Path; | ||
export declare enum LookupType { | ||
FILE_SYSTEM = "FILE_SYSTEM", | ||
NODE_MODULE = "NODE_MODULE" | ||
} | ||
export declare type LookupType = 'file-system' | 'node-module'; | ||
export interface Lookup { | ||
path: Path; | ||
raw: Path; | ||
path: Pathable; | ||
raw: Pathable; | ||
type: LookupType; | ||
} | ||
export declare type ModuleResolver = (path: ModuleName) => FilePath; | ||
export declare type AbstractConstructor<T> = Function & { | ||
prototype: T; | ||
}; | ||
export declare type ConcreteConstructor<T> = new (...args: unknown[]) => T; | ||
export interface ResolvedLookup { | ||
/** Original file path or module ID of the lookup. */ | ||
originalSource: Pathable; | ||
/** Resolved absolute *file* path for the found lookup. */ | ||
resolvedPath: Path; | ||
/** The type of lookup that was found. */ | ||
type: LookupType; | ||
} | ||
export declare type AbstractConstructor<T> = abstract new (...args: any[]) => T; | ||
export declare type ConcreteConstructor<T> = new (...args: any[]) => T; | ||
export declare type Constructor<T> = AbstractConstructor<T> | ConcreteConstructor<T>; | ||
export declare type BlueprintFactory<T extends object> = (predicates: Predicates, onConstruction?: boolean) => Blueprint<T>; | ||
export declare type BlueprintFactory<T extends object> = (schemas: Schemas, onConstruction?: boolean) => Blueprint<T>; | ||
export interface Optionable<T extends object = {}> { | ||
/** Validated and configured options. */ | ||
readonly options: Required<T>; | ||
readonly options: Readonly<Required<T>>; | ||
/** | ||
@@ -126,6 +133,6 @@ * Define an `optimal` blueprint in which to validate and build the | ||
export interface WorkspaceMetadata { | ||
jsonPath: string; | ||
packagePath: string; | ||
jsonPath: Path; | ||
packagePath: Path; | ||
packageName: string; | ||
workspacePath: string; | ||
workspacePath: Path; | ||
workspaceName: string; | ||
@@ -132,0 +139,0 @@ } |
@@ -484,3 +484,3 @@ 'use strict'; | ||
if (typeof Object.getOwnPropertySymbols === 'function') { | ||
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { | ||
ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(source, sym).enumerable; | ||
@@ -1665,2 +1665,20 @@ })); | ||
function _checkPrivateRedeclaration(obj, privateCollection) { | ||
if (privateCollection.has(obj)) { | ||
throw new TypeError("Cannot initialize the same private elements twice on an object"); | ||
} | ||
} | ||
function _classPrivateFieldInitSpec(obj, privateMap, value) { | ||
_checkPrivateRedeclaration(obj, privateMap); | ||
privateMap.set(obj, value); | ||
} | ||
function _classPrivateMethodInitSpec(obj, privateSet) { | ||
_checkPrivateRedeclaration(obj, privateSet); | ||
privateSet.add(obj); | ||
} | ||
function _classPrivateMethodSet() { | ||
@@ -1681,2 +1699,3 @@ throw new TypeError("attempted to reassign private method"); | ||
exports.awaitAsyncGenerator = _awaitAsyncGenerator; | ||
exports.checkPrivateRedeclaration = _checkPrivateRedeclaration; | ||
exports.classApplyDescriptorDestructureSet = _classApplyDescriptorDestructureSet; | ||
@@ -1692,2 +1711,3 @@ exports.classApplyDescriptorGet = _classApplyDescriptorGet; | ||
exports.classPrivateFieldGet = _classPrivateFieldGet; | ||
exports.classPrivateFieldInitSpec = _classPrivateFieldInitSpec; | ||
exports.classPrivateFieldLooseBase = _classPrivateFieldLooseBase; | ||
@@ -1697,2 +1717,3 @@ exports.classPrivateFieldLooseKey = _classPrivateFieldLooseKey; | ||
exports.classPrivateMethodGet = _classPrivateMethodGet; | ||
exports.classPrivateMethodInitSpec = _classPrivateMethodInitSpec; | ||
exports.classPrivateMethodSet = _classPrivateMethodSet; | ||
@@ -1713,3 +1734,3 @@ exports.classStaticPrivateFieldDestructureSet = _classStaticPrivateFieldDestructureSet; | ||
exports.defineProperty = _defineProperty; | ||
exports['extends'] = _extends; | ||
exports.extends = _extends; | ||
exports.get = _get; | ||
@@ -1721,3 +1742,3 @@ exports.getPrototypeOf = _getPrototypeOf; | ||
exports.initializerWarningHelper = _initializerWarningHelper; | ||
exports['instanceof'] = _instanceof; | ||
exports.instanceof = _instanceof; | ||
exports.interopRequireDefault = _interopRequireDefault; | ||
@@ -1757,3 +1778,3 @@ exports.interopRequireWildcard = _interopRequireWildcard; | ||
exports.toPropertyKey = _toPropertyKey; | ||
exports['typeof'] = _typeof; | ||
exports.typeof = _typeof; | ||
exports.unsupportedIterableToArray = _unsupportedIterableToArray; | ||
@@ -1760,0 +1781,0 @@ exports.wrapAsyncGenerator = _wrapAsyncGenerator; |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var internal = require('@boost/internal'); | ||
const internal = require('@boost/internal'); | ||
@@ -10,0 +10,0 @@ const errors = { |
@@ -13,12 +13,4 @@ 'use strict'; | ||
var optimal = require('optimal'); | ||
const optimal = require('optimal'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
var optimal__default = /*#__PURE__*/_interopDefault(optimal); | ||
class Contract { | ||
@@ -53,5 +45,5 @@ /** Validated and configured options. */ | ||
this.options = Object.freeze(optimal__default['default'](_objectSpread(_objectSpread({}, this.options), nextOptions), this.blueprint(optimal.predicates, this.options === undefined), { | ||
this.options = Object.freeze(optimal.optimal(this.blueprint(optimal.schemas, this.options === undefined), { | ||
name: this.constructor.name | ||
})); | ||
}).validate(_objectSpread(_objectSpread({}, this.options), nextOptions))); | ||
return this.options; | ||
@@ -58,0 +50,0 @@ } |
@@ -7,10 +7,11 @@ 'use strict'; | ||
var optimal = require('optimal'); | ||
const optimal = require('optimal'); | ||
/** | ||
* Can be used to generate a blueprint object for use within | ||
* [optimal](https://github.com/milesj/optimal) checks. All supported optimal | ||
* predicates are passed as an object to the factory. | ||
* schemas are passed as an object to the factory. | ||
* | ||
* ```ts | ||
* import { optimal, createBlueprint } from '@boost/common'; | ||
* import { createBlueprint } from '@boost/common'; | ||
* import { optimal } from '@boost/common/optimal'; | ||
* | ||
@@ -22,3 +23,3 @@ * const blueprint = createBlueprint(({ string, number }) => ({ | ||
* | ||
* const data = optimal({}, blueprint); | ||
* const object = optimal(blueprint).validate({}); | ||
* ``` | ||
@@ -29,3 +30,3 @@ */ | ||
function createBlueprint(factory) { | ||
return factory(optimal.predicates); | ||
return factory(optimal.schemas); | ||
} | ||
@@ -32,0 +33,0 @@ |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var isPlainObject = require('./isPlainObject.js'); | ||
const isPlainObject = require('./isPlainObject.js'); | ||
/** | ||
@@ -10,0 +10,0 @@ * Can be used to recursively freeze plain objects with `Object.freeze`. |
@@ -13,3 +13,3 @@ 'use strict'; | ||
var isObject = require('./isObject.js'); | ||
const isObject = require('./isObject.js'); | ||
@@ -16,0 +16,0 @@ function merge(prev, next) { |
@@ -13,11 +13,9 @@ 'use strict'; | ||
var prettyMs = require('pretty-ms'); | ||
const prettyMs = require('pretty-ms'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
var prettyMs__default = /*#__PURE__*/_interopDefault(prettyMs); | ||
const prettyMs__default = /*#__PURE__*/_interopDefault(prettyMs); | ||
/** | ||
@@ -41,3 +39,3 @@ * Can be used to format a UNIX timestamp in milliseconds into a shorthand human readable format. | ||
return prettyMs__default['default'](ms, _objectSpread({ | ||
return prettyMs__default.default(ms, _objectSpread({ | ||
keepDecimalsOnWholeSeconds: true | ||
@@ -44,0 +42,0 @@ }, options)); |
@@ -7,30 +7,24 @@ 'use strict'; | ||
var createBlueprint = require('./createBlueprint.js'); | ||
const createBlueprint = require('./createBlueprint.js'); | ||
var deepFreeze = require('./deepFreeze.js'); | ||
const deepFreeze = require('./deepFreeze.js'); | ||
var deepMerge = require('./deepMerge.js'); | ||
const deepMerge = require('./deepMerge.js'); | ||
var formatMs = require('./formatMs.js'); | ||
const formatMs = require('./formatMs.js'); | ||
var instanceOf = require('./instanceOf.js'); | ||
const instanceOf = require('./instanceOf.js'); | ||
var isEmpty = require('./isEmpty.js'); | ||
const isEmpty = require('./isEmpty.js'); | ||
var isFilePath = require('./isFilePath.js'); | ||
const isFilePath = require('./isFilePath.js'); | ||
var isModuleName = require('./isModuleName.js'); | ||
const isModuleName = require('./isModuleName.js'); | ||
var isObject = require('./isObject.js'); | ||
const isObject = require('./isObject.js'); | ||
var isPlainObject = require('./isPlainObject.js'); | ||
const isPlainObject = require('./isPlainObject.js'); | ||
var parseFile = require('./parseFile.js'); | ||
const toArray = require('./toArray.js'); | ||
var requireModule = require('./requireModule.js'); | ||
var requireTypedModule = require('./requireTypedModule.js'); | ||
var toArray = require('./toArray.js'); | ||
exports.createBlueprint = createBlueprint.createBlueprint; | ||
@@ -46,6 +40,3 @@ exports.deepFreeze = deepFreeze.deepFreeze; | ||
exports.isPlainObject = isPlainObject.isPlainObject; | ||
exports.parseFile = parseFile.parseFile; | ||
exports.requireModule = requireModule.requireModule; | ||
exports.requireTypedModule = requireTypedModule.requireTypedModule; | ||
exports.toArray = toArray.toArray; | ||
//# sourceMappingURL=index.js.map |
@@ -56,3 +56,4 @@ 'use strict'; | ||
if (current.constructor.name === declaration.name || current instanceof Error && current.name === declaration.name) { | ||
if (current.constructor.name === declaration.name || // istanbul ignore next | ||
current instanceof Error && current.name === declaration.name) { | ||
return true; | ||
@@ -59,0 +60,0 @@ } // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var isObject = require('./isObject.js'); | ||
const isObject = require('./isObject.js'); | ||
/** | ||
@@ -10,0 +10,0 @@ * Returns `true` if an object has no properties, an array has no items, |
@@ -6,5 +6,2 @@ 'use strict'; | ||
}); | ||
var Path = require('../Path.js'); | ||
const NIX_START = /^(\/|\.)/u; | ||
@@ -28,3 +25,3 @@ const WIN_START = /^([A-Z]:|\.)/u; | ||
function isFilePath(path) { | ||
const filePath = path instanceof Path.Path ? path.path() : path; | ||
const filePath = String(path); | ||
@@ -31,0 +28,0 @@ if (filePath === '') { |
@@ -7,5 +7,5 @@ 'use strict'; | ||
var module$1 = require('module'); | ||
const module$1 = require('module'); | ||
var constants = require('../constants.js'); | ||
const constants = require('../constants.js'); | ||
@@ -12,0 +12,0 @@ const RESERVED = new Set([...module$1.builtinModules, 'node_modules', 'favicon.ico']); |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var isObject = require('./isObject.js'); | ||
const isObject = require('./isObject.js'); | ||
/** | ||
@@ -32,3 +32,4 @@ * Like `isObject` but only returns true if the value is a plain object | ||
if (value.constructor === Object || proto === Object.prototype || proto === null || loose && value.constructor.name === 'Object') { | ||
if (value.constructor === Object || proto === Object.prototype || proto === null || // This is to support cross-realm checks | ||
loose && value.constructor.name === 'Object') { | ||
return true; | ||
@@ -35,0 +36,0 @@ } |
@@ -7,65 +7,51 @@ 'use strict'; | ||
var optimal = require('optimal'); | ||
const CommonError = require('./CommonError.js'); | ||
var CommonError = require('./CommonError.js'); | ||
const constants = require('./constants.js'); | ||
var constants = require('./constants.js'); | ||
const Contract = require('./Contract.js'); | ||
var Contract = require('./Contract.js'); | ||
const ExitError = require('./ExitError.js'); | ||
var ExitError = require('./ExitError.js'); | ||
require('./helpers/index.js'); | ||
var PackageGraph = require('./PackageGraph.js'); | ||
const ModulePath = require('./ModulePath.js'); | ||
var Path = require('./Path.js'); | ||
const PackageGraph = require('./PackageGraph.js'); | ||
var PathResolver = require('./PathResolver.js'); | ||
const Path = require('./Path.js'); | ||
var Project = require('./Project.js'); | ||
const PathResolver = require('./PathResolver.js'); | ||
var json$1 = require('./serializers/json.js'); | ||
const Project = require('./Project.js'); | ||
var yaml$1 = require('./serializers/yaml.js'); | ||
const json$1 = require('./serializers/json.js'); | ||
var types = require('./types.js'); | ||
const yaml$1 = require('./serializers/yaml.js'); | ||
var decorators = require('@boost/decorators'); | ||
require('./types.js'); | ||
var createBlueprint = require('./helpers/createBlueprint.js'); | ||
const decorators = require('@boost/decorators'); | ||
var deepFreeze = require('./helpers/deepFreeze.js'); | ||
const createBlueprint = require('./helpers/createBlueprint.js'); | ||
var deepMerge = require('./helpers/deepMerge.js'); | ||
const deepFreeze = require('./helpers/deepFreeze.js'); | ||
var formatMs = require('./helpers/formatMs.js'); | ||
const deepMerge = require('./helpers/deepMerge.js'); | ||
var instanceOf = require('./helpers/instanceOf.js'); | ||
const formatMs = require('./helpers/formatMs.js'); | ||
var isEmpty = require('./helpers/isEmpty.js'); | ||
const instanceOf = require('./helpers/instanceOf.js'); | ||
var isFilePath = require('./helpers/isFilePath.js'); | ||
const isEmpty = require('./helpers/isEmpty.js'); | ||
var isModuleName = require('./helpers/isModuleName.js'); | ||
const isFilePath = require('./helpers/isFilePath.js'); | ||
var isObject = require('./helpers/isObject.js'); | ||
const isModuleName = require('./helpers/isModuleName.js'); | ||
var isPlainObject = require('./helpers/isPlainObject.js'); | ||
const isObject = require('./helpers/isObject.js'); | ||
var parseFile = require('./helpers/parseFile.js'); | ||
const isPlainObject = require('./helpers/isPlainObject.js'); | ||
var requireModule = require('./helpers/requireModule.js'); | ||
var requireTypedModule = require('./helpers/requireTypedModule.js'); | ||
var toArray = require('./helpers/toArray.js'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
var optimal__default = /*#__PURE__*/_interopDefault(optimal); | ||
const toArray = require('./helpers/toArray.js'); | ||
/** | ||
@@ -77,14 +63,2 @@ * @copyright 2020, Miles Johnson | ||
Object.defineProperty(exports, 'optimal', { | ||
enumerable: true, | ||
get: function () { | ||
return optimal__default['default']; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'predicates', { | ||
enumerable: true, | ||
get: function () { | ||
return optimal.predicates; | ||
} | ||
}); | ||
exports.CommonError = CommonError.CommonError; | ||
@@ -95,2 +69,3 @@ exports.MODULE_NAME_PART = constants.MODULE_NAME_PART; | ||
exports.ExitError = ExitError.ExitError; | ||
exports.ModulePath = ModulePath.ModulePath; | ||
exports.PackageGraph = PackageGraph.PackageGraph; | ||
@@ -102,8 +77,2 @@ exports.Path = Path.Path; | ||
exports.yaml = yaml$1; | ||
Object.defineProperty(exports, 'LookupType', { | ||
enumerable: true, | ||
get: function () { | ||
return types.LookupType; | ||
} | ||
}); | ||
exports.createBlueprint = createBlueprint.createBlueprint; | ||
@@ -119,14 +88,10 @@ exports.deepFreeze = deepFreeze.deepFreeze; | ||
exports.isPlainObject = isPlainObject.isPlainObject; | ||
exports.parseFile = parseFile.parseFile; | ||
exports.requireModule = requireModule.requireModule; | ||
exports.requireTypedModule = requireTypedModule.requireTypedModule; | ||
exports.toArray = toArray.toArray; | ||
Object.keys(decorators).forEach(function (k) { | ||
for (const k in decorators) { | ||
if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, { | ||
enumerable: true, | ||
get: function () { | ||
return decorators[k]; | ||
} | ||
get: () => decorators[k] | ||
}); | ||
}); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -7,25 +7,26 @@ 'use strict'; | ||
var fs = require('fs'); | ||
const fs = require('fs'); | ||
var path = require('path'); | ||
const path = require('path'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
var fs__default = /*#__PURE__*/_interopDefault(fs); | ||
const fs__default = /*#__PURE__*/_interopDefault(fs); | ||
var path__default = /*#__PURE__*/_interopDefault(path); | ||
const path__default = /*#__PURE__*/_interopDefault(path); | ||
/** | ||
* An immutable class for operating on file system paths. | ||
*/ | ||
class Path { | ||
constructor(...parts) { | ||
this.internalPath = ''; // Always use forward slashes for better interop | ||
this.internalPath = path__default['default'].normalize(path__default['default'].join(...parts.map(String))).replace(/\\/gu, Path.SEP); | ||
this.internalPath = ''; | ||
this.isNormalized = false; | ||
this.internalPath = path__default.default.join(...parts.map(String)); | ||
} | ||
/** | ||
* Create and return a new `Path` instance if a string. | ||
* If already a `Path`, return as is. | ||
* Create and return a new `Path` instance. | ||
*/ | ||
@@ -35,6 +36,6 @@ | ||
static create(filePath) { | ||
return filePath instanceof Path ? filePath : new Path(filePath); | ||
return new Path(filePath); | ||
} | ||
/** | ||
* Like `create()` but also resolves the path against CWD. | ||
* Like `create()` but also resolves the path against a working directory. | ||
*/ | ||
@@ -69,3 +70,3 @@ | ||
ext(withoutPeriod = false) { | ||
const ext = path__default['default'].extname(this.internalPath); | ||
const ext = path__default.default.extname(this.path()); | ||
return withoutPeriod && ext.startsWith('.') ? ext.slice(1) : ext; | ||
@@ -79,3 +80,3 @@ } | ||
exists() { | ||
return fs__default['default'].existsSync(this.internalPath); | ||
return fs__default.default.existsSync(this.path()); | ||
} | ||
@@ -88,3 +89,3 @@ /** | ||
isAbsolute() { | ||
return path__default['default'].isAbsolute(this.internalPath); | ||
return path__default.default.isAbsolute(this.path()); | ||
} | ||
@@ -97,3 +98,3 @@ /** | ||
isDirectory() { | ||
return fs__default['default'].statSync(this.internalPath).isDirectory(); | ||
return fs__default.default.statSync(this.path()).isDirectory(); | ||
} | ||
@@ -106,3 +107,3 @@ /** | ||
isFile() { | ||
return fs__default['default'].statSync(this.internalPath).isFile(); | ||
return fs__default.default.statSync(this.path()).isFile(); | ||
} | ||
@@ -115,3 +116,3 @@ /** | ||
name(withoutExtension = false) { | ||
let name = path__default['default'].basename(this.internalPath); | ||
let name = path__default.default.basename(this.path()); | ||
@@ -130,3 +131,3 @@ if (withoutExtension) { | ||
parent() { | ||
return new Path(path__default['default'].dirname(this.internalPath)); | ||
return new Path(path__default.default.dirname(this.internalPath)); | ||
} | ||
@@ -139,2 +140,7 @@ /** | ||
path() { | ||
if (!this.isNormalized) { | ||
this.isNormalized = true; | ||
this.internalPath = path__default.default.normalize(this.internalPath); | ||
} | ||
return this.internalPath; | ||
@@ -158,3 +164,3 @@ } | ||
realPath() { | ||
return fs__default['default'].realpathSync.native(this.path()); | ||
return fs__default.default.realpathSync.native(this.path()); | ||
} | ||
@@ -168,7 +174,7 @@ /** | ||
relativeTo(to) { | ||
return new Path(path__default['default'].relative(this.path(), String(to))); | ||
return new Path(path__default.default.relative(this.internalPath, String(to))); | ||
} | ||
/** | ||
* Return a new `Path` instance where the current path is accurately | ||
* resolved against the defined current working directory. | ||
* resolved against the defined working directory. | ||
*/ | ||
@@ -178,3 +184,3 @@ | ||
resolve(cwd) { | ||
return new Path(path__default['default'].resolve(String(cwd !== null && cwd !== void 0 ? cwd : process.cwd()), this.internalPath)); | ||
return new Path(path__default.default.resolve(String(cwd !== null && cwd !== void 0 ? cwd : process.cwd()), this.internalPath)); | ||
} | ||
@@ -192,5 +198,5 @@ | ||
Path.DELIMITER = path__default['default'].delimiter; | ||
Path.SEP = '/'; | ||
Path.DELIMITER = path__default.default.delimiter; | ||
Path.SEP = path__default.default.sep; | ||
exports.Path = Path; | ||
//# sourceMappingURL=Path.js.map |
@@ -7,8 +7,16 @@ 'use strict'; | ||
var CommonError = require('./CommonError.js'); | ||
const doResolve = require('resolve'); | ||
var Path = require('./Path.js'); | ||
const CommonError = require('./CommonError.js'); | ||
var types = require('./types.js'); | ||
const ModulePath = require('./ModulePath.js'); | ||
const Path = require('./Path.js'); | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
const doResolve__default = /*#__PURE__*/_interopDefault(doResolve); | ||
class PathResolver { | ||
@@ -18,4 +26,20 @@ constructor(resolver) { | ||
this.resolver = void 0; | ||
this.resolver = resolver !== null && resolver !== void 0 ? resolver : require.resolve; | ||
this.resolver = resolver !== null && resolver !== void 0 ? resolver : PathResolver.defaultResolver; | ||
} | ||
static async defaultResolver(path, startDir) { | ||
return new Promise((resolve, reject) => { | ||
// eslint-disable-next-line promise/prefer-await-to-callbacks | ||
doResolve__default.default(path, { | ||
basedir: startDir, | ||
includeCoreModules: false | ||
}, (error, foundPath) => { | ||
if (error || !foundPath) { | ||
reject(error); | ||
} else { | ||
resolve(foundPath); | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
@@ -39,3 +63,3 @@ * Return a list of all lookup paths. | ||
raw: Path.Path.create(filePath), | ||
type: types.LookupType.FILE_SYSTEM | ||
type: 'file-system' | ||
}); | ||
@@ -45,2 +69,15 @@ return this; | ||
/** | ||
* Add a file system path with a list of possible extensions to look for, | ||
* resolved against the defined current working directory (or `process.cwd()` otherwise). | ||
*/ | ||
lookupFilePathWithExts(filePath, exts, cwd) { | ||
exts.forEach(ext => { | ||
const extWithPeriod = ext.startsWith('.') ? ext : `.${ext}`; | ||
this.lookupFilePath(`${filePath}${extWithPeriod}`, cwd); | ||
}); | ||
return this; | ||
} | ||
/** | ||
* Add a Node.js module, either by name or relative path, to look for. | ||
@@ -50,8 +87,7 @@ */ | ||
lookupNodeModule(modulePath) { | ||
const path = Path.Path.create(modulePath); | ||
lookupNodeModule(moduleId) { | ||
this.lookups.push({ | ||
path, | ||
raw: path, | ||
type: types.LookupType.NODE_MODULE | ||
path: ModulePath.ModulePath.create(moduleId), | ||
raw: ModulePath.ModulePath.create(moduleId), | ||
type: 'node-module' | ||
}); | ||
@@ -63,38 +99,37 @@ return this; | ||
* return a resolved absolute path. If a file system path, will check using `fs.exists`. | ||
* If a node module path, will check using `require.resolve`. | ||
* If a node module path, will check using the provided resolver. | ||
*/ | ||
resolve() { | ||
async resolve(startDir) { | ||
let resolvedPath = ''; | ||
let resolvedLookup; | ||
this.lookups.some(lookup => { | ||
let resolvedLookup; // TODO: Switch to Promise.any() in Node.js v15 | ||
for (const lookup of this.lookups) { | ||
// Check that the file exists on the file system. | ||
if (lookup.type === types.LookupType.FILE_SYSTEM) { | ||
if (lookup.path.exists()) { | ||
resolvedPath = lookup.path; | ||
resolvedLookup = lookup; | ||
} else { | ||
return false; | ||
} // Check that the module path exists using Node's module resolution. | ||
// The `require.resolve` function will throw an error if not found. | ||
if (lookup.type === 'file-system' && lookup.path.exists()) { | ||
resolvedPath = lookup.path; | ||
resolvedLookup = lookup; | ||
break; | ||
} // Check that the module path exists using Node's module resolution. | ||
// The resolver function will throw an error if not found. | ||
} else if (lookup.type === types.LookupType.NODE_MODULE) { | ||
if (lookup.type === 'node-module') { | ||
try { | ||
resolvedPath = this.resolver(lookup.path.path()); | ||
// eslint-disable-next-line no-await-in-loop | ||
resolvedPath = await this.resolver(lookup.path.path(), startDir ? String(startDir) : undefined); | ||
resolvedLookup = lookup; | ||
} catch { | ||
return false; | ||
break; | ||
} catch {// Display errors? | ||
} | ||
} | ||
} | ||
return true; | ||
}); | ||
if (!resolvedPath || !resolvedLookup) { | ||
throw new CommonError.CommonError('PATH_RESOLVE_LOOKUPS', [this.lookups.map(lookup => ` - ${lookup.path} (${lookup.type})`).join('\n')]); | ||
throw new CommonError.CommonError('PATH_RESOLVE_LOOKUPS', [this.lookups.map(lookup => ` - ${lookup.path} (${lookup.type.replace('-', ' ')})`).join('\n')]); | ||
} | ||
return { | ||
originalPath: resolvedLookup.raw, | ||
originalSource: resolvedLookup.raw, | ||
resolvedPath: Path.Path.create(resolvedPath), | ||
@@ -105,8 +140,8 @@ type: resolvedLookup.type | ||
/** | ||
* Like `resolve()` but only returns the resolved path. | ||
* Like `resolve()` but only returns the resolved file path. | ||
*/ | ||
resolvePath() { | ||
return this.resolve().resolvedPath; | ||
async resolvePath() { | ||
return (await this.resolve()).resolvedPath; | ||
} | ||
@@ -113,0 +148,0 @@ |
@@ -7,22 +7,22 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
const _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
var glob = require('fast-glob'); | ||
const glob = require('fast-glob'); | ||
var decorators = require('@boost/decorators'); | ||
const decorators = require('@boost/decorators'); | ||
var CommonError = require('./CommonError.js'); | ||
const CommonError = require('./CommonError.js'); | ||
var parseFile = require('./helpers/parseFile.js'); | ||
const Path = require('./Path.js'); | ||
var Path = require('./Path.js'); | ||
const json = require('./serializers/json.js'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
const yaml = require('./serializers/yaml.js'); | ||
var glob__default = /*#__PURE__*/_interopDefault(glob); | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
const glob__default = /*#__PURE__*/_interopDefault(glob); | ||
var _dec, _dec2, _dec3, _class; | ||
@@ -36,2 +36,11 @@ | ||
/** | ||
* Normalize a glob pattern or path for use on POSIX and Windows machines. | ||
* @link https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows | ||
*/ | ||
static normalizeGlob(pattern) { | ||
return pattern.replace(/\\/g, '/'); | ||
} | ||
/** | ||
* Create a workspace metadata object composed of absolute file paths. | ||
@@ -46,6 +55,6 @@ */ | ||
const wsPath = pkgPath.parent(); | ||
metadata.jsonPath = filePath.path(); | ||
metadata.packagePath = pkgPath.path(); | ||
metadata.jsonPath = filePath; | ||
metadata.packagePath = pkgPath; | ||
metadata.packageName = pkgPath.name(); | ||
metadata.workspacePath = wsPath.path(); | ||
metadata.workspacePath = wsPath; | ||
metadata.workspaceName = wsPath.name(); | ||
@@ -66,9 +75,9 @@ return metadata; | ||
return parseFile.parseFile(pkgPath); | ||
return json.load(pkgPath); | ||
} | ||
/** | ||
* Return a list of all workspace globs as they are configured | ||
* in `package.json` or `lerna.json`. | ||
* in `package.json` or `lerna.json`. Glob patterns will _always_ | ||
* use forward slashes, regardless of OS. | ||
*/ | ||
// eslint-disable-next-line complexity | ||
@@ -83,3 +92,3 @@ | ||
if (pkgPath.exists()) { | ||
const pkg = parseFile.parseFile(pkgPath); | ||
const pkg = json.load(pkgPath); | ||
@@ -97,3 +106,3 @@ if (pkg.workspaces) { | ||
if (workspacePaths.length === 0 && lernaPath.exists()) { | ||
const lerna = parseFile.parseFile(lernaPath); | ||
const lerna = json.load(lernaPath); | ||
@@ -107,3 +116,3 @@ if (Array.isArray(lerna.packages)) { | ||
if (workspacePaths.length === 0 && pnpmPath.exists()) { | ||
const pnpm = parseFile.parseFile(pnpmPath); | ||
const pnpm = yaml.load(pnpmPath); | ||
@@ -115,7 +124,6 @@ if (Array.isArray(pnpm.packages)) { | ||
if (options.relative) { | ||
return workspacePaths; | ||
} | ||
return workspacePaths.map(workspace => this.root.append(workspace).path()); | ||
return workspacePaths.map(workspace => { | ||
const path = options.relative ? new Path.Path(workspace).path() : this.root.append(workspace).path(); | ||
return Project.normalizeGlob(path); | ||
}); | ||
} | ||
@@ -129,3 +137,3 @@ /** | ||
getWorkspacePackages() { | ||
return glob__default['default'].sync(this.getWorkspaceGlobs({ | ||
return glob__default.default.sync(this.getWorkspaceGlobs({ | ||
relative: true | ||
@@ -140,3 +148,3 @@ }), { | ||
metadata: this.createWorkspaceMetadata(filePath), | ||
package: parseFile.parseFile(filePath) | ||
package: json.load(filePath) | ||
}; | ||
@@ -147,2 +155,3 @@ }); | ||
* Return a list of all workspace package paths, resolved against the file system. | ||
* Absolute file paths are returned unless the `relative` option is true. | ||
*/ | ||
@@ -152,3 +161,3 @@ | ||
getWorkspacePackagePaths(options = {}) { | ||
return glob__default['default'].sync(this.getWorkspaceGlobs({ | ||
return glob__default.default.sync(this.getWorkspaceGlobs({ | ||
relative: true | ||
@@ -160,3 +169,3 @@ }), { | ||
onlyFiles: false | ||
}); | ||
}).map(Path.Path.create); | ||
} | ||
@@ -163,0 +172,0 @@ |
@@ -7,22 +7,29 @@ 'use strict'; | ||
var JSON = require('json5'); | ||
const fs = require('fs'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
const JSON = require('json5'); | ||
var JSON__default = /*#__PURE__*/_interopDefault(JSON); | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
const fs__default = /*#__PURE__*/_interopDefault(fs); | ||
const JSON__default = /*#__PURE__*/_interopDefault(JSON); | ||
function parse(content, reviver) { | ||
return JSON__default['default'].parse(content, reviver); | ||
return JSON__default.default.parse(content, reviver); | ||
} | ||
function stringify(content, options = {}) { | ||
return JSON__default['default'].stringify(content, options); | ||
return JSON__default.default.stringify(content, options); | ||
} | ||
function load(path) { | ||
return parse(fs__default.default.readFileSync(String(path), 'utf8')); | ||
} | ||
exports.load = load; | ||
exports.parse = parse; | ||
exports.stringify = stringify; | ||
//# sourceMappingURL=json.js.map |
@@ -7,22 +7,29 @@ 'use strict'; | ||
var YAML = require('yaml'); | ||
const fs = require('fs'); | ||
function _interopDefault(e) { | ||
return e && e.__esModule ? e : { | ||
'default': e | ||
}; | ||
} | ||
const YAML = require('yaml'); | ||
var YAML__default = /*#__PURE__*/_interopDefault(YAML); | ||
const _interopDefault = e => e && e.__esModule ? e : { | ||
default: e | ||
}; | ||
const fs__default = /*#__PURE__*/_interopDefault(fs); | ||
const YAML__default = /*#__PURE__*/_interopDefault(YAML); | ||
function parse(content, options) { | ||
return YAML__default['default'].parse(content, options); | ||
return YAML__default.default.parse(content, options); | ||
} | ||
function stringify(content, options) { | ||
return YAML__default['default'].stringify(content, options); | ||
return YAML__default.default.stringify(content, options); | ||
} | ||
function load(path) { | ||
return parse(fs__default.default.readFileSync(String(path), 'utf8')); | ||
} | ||
exports.load = load; | ||
exports.parse = parse; | ||
exports.stringify = stringify; | ||
//# sourceMappingURL=yaml.js.map |
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
}); // NODE | ||
// FILE SYSTEM | ||
exports.LookupType = void 0; | ||
(function (LookupType) { | ||
LookupType["FILE_SYSTEM"] = "FILE_SYSTEM"; | ||
LookupType["NODE_MODULE"] = "NODE_MODULE"; | ||
})(exports.LookupType || (exports.LookupType = {})); | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "@boost/common", | ||
"version": "2.8.2", | ||
"version": "3.0.0", | ||
"release": "1594765247526", | ||
@@ -17,7 +17,11 @@ "description": "A collection of common utilities, classes, and helpers.", | ||
"lib/**/*.{js,map}", | ||
"src/**/*.{ts,tsx,json}" | ||
"optimal.d.ts", | ||
"optimal.js", | ||
"src/**/*.{ts,tsx,json}", | ||
"test.d.ts", | ||
"test.js" | ||
], | ||
"engines": { | ||
"node": ">=10.3.0", | ||
"npm": ">=6.1.0" | ||
"node": ">=12.17.0", | ||
"npm": ">=6.13.0" | ||
}, | ||
@@ -35,12 +39,14 @@ "repository": { | ||
"dependencies": { | ||
"@boost/decorators": "^2.1.4", | ||
"@boost/internal": "^2.2.3", | ||
"@boost/decorators": "^3.0.0", | ||
"@boost/internal": "^3.0.0", | ||
"fast-glob": "^3.2.7", | ||
"json5": "^2.2.0", | ||
"optimal": "^4.3.0", | ||
"optimal": "^5.1.0", | ||
"pretty-ms": "^7.0.1", | ||
"resolve": "^1.20.0", | ||
"yaml": "^1.10.2" | ||
}, | ||
"devDependencies": { | ||
"@boost/test-utils": "^2.3.2" | ||
"@boost/test-utils": "^3.0.0", | ||
"@types/resolve": "^1.20.1" | ||
}, | ||
@@ -61,6 +67,5 @@ "peerDependencies": { | ||
"format": "lib", | ||
"support": "legacy", | ||
"platform": "node" | ||
}, | ||
"gitHead": "a44772937c04f8f818884444faee5c2a9f44b5ac" | ||
"gitHead": "3934541f918ab3c6a1b53e34f302121ccdd23b83" | ||
} |
@@ -1,2 +0,2 @@ | ||
import optimal, { Blueprint, Predicates, predicates } from 'optimal'; | ||
import { Blueprint, DeepPartial, optimal, Schemas, schemas } from 'optimal'; | ||
import { Optionable } from './types'; | ||
@@ -35,9 +35,5 @@ | ||
this.options = Object.freeze( | ||
optimal( | ||
{ ...this.options, ...nextOptions }, | ||
this.blueprint(predicates, this.options === undefined) as Blueprint<T>, | ||
{ | ||
name: this.constructor.name, | ||
}, | ||
), | ||
optimal(this.blueprint(schemas, this.options === undefined) as Blueprint<T>, { | ||
name: this.constructor.name, | ||
}).validate({ ...this.options, ...nextOptions } as DeepPartial<T>), | ||
); | ||
@@ -56,3 +52,3 @@ | ||
*/ | ||
abstract blueprint(predicates: Predicates, onConstruction?: boolean): Blueprint<object>; | ||
abstract blueprint(schemas: Schemas, onConstruction?: boolean): Blueprint<object>; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Blueprint, predicates } from 'optimal'; | ||
import { Blueprint, schemas } from 'optimal'; | ||
import { BlueprintFactory } from '../types'; | ||
@@ -7,6 +7,7 @@ | ||
* [optimal](https://github.com/milesj/optimal) checks. All supported optimal | ||
* predicates are passed as an object to the factory. | ||
* schemas are passed as an object to the factory. | ||
* | ||
* ```ts | ||
* import { optimal, createBlueprint } from '@boost/common'; | ||
* import { createBlueprint } from '@boost/common'; | ||
* import { optimal } from '@boost/common/optimal'; | ||
* | ||
@@ -18,7 +19,7 @@ * const blueprint = createBlueprint(({ string, number }) => ({ | ||
* | ||
* const data = optimal({}, blueprint); | ||
* const object = optimal(blueprint).validate({}); | ||
* ``` | ||
*/ | ||
export function createBlueprint<T extends object>(factory: BlueprintFactory<T>): Blueprint<T> { | ||
return factory(predicates); | ||
return factory(schemas); | ||
} |
@@ -11,5 +11,2 @@ export * from './createBlueprint'; | ||
export * from './isPlainObject'; | ||
export * from './parseFile'; | ||
export * from './requireModule'; | ||
export * from './requireTypedModule'; | ||
export * from './toArray'; |
@@ -1,2 +0,1 @@ | ||
import { Path } from '../Path'; | ||
import { PortablePath } from '../types'; | ||
@@ -22,3 +21,3 @@ | ||
export function isFilePath(path: PortablePath): boolean { | ||
const filePath = path instanceof Path ? path.path() : path; | ||
const filePath = String(path); | ||
@@ -25,0 +24,0 @@ if (filePath === '') { |
import { builtinModules } from 'module'; | ||
import { MODULE_NAME_PATTERN } from '../constants'; | ||
import { ModuleName } from '../types'; | ||
import { ModuleID } from '../types'; | ||
@@ -21,3 +21,3 @@ const RESERVED = new Set([...builtinModules, 'node_modules', 'favicon.ico']); | ||
*/ | ||
export function isModuleName(name: ModuleName): boolean { | ||
export function isModuleName(name: ModuleID): boolean { | ||
if (RESERVED.has(name)) { | ||
@@ -24,0 +24,0 @@ return false; |
@@ -6,4 +6,2 @@ /** | ||
import optimal, { Blueprint, Predicates, predicates } from 'optimal'; | ||
export * from './CommonError'; | ||
@@ -14,2 +12,3 @@ export * from './constants'; | ||
export * from './helpers'; | ||
export * from './ModulePath'; | ||
export * from './PackageGraph'; | ||
@@ -23,4 +22,2 @@ export * from './Path'; | ||
export * from '@boost/decorators'; | ||
export { optimal, predicates }; | ||
export type { Blueprint, Predicates }; | ||
export type { Blueprint, DeepPartial, Schemas } from 'optimal'; |
import fs from 'fs'; | ||
import path from 'path'; | ||
import { FilePath, PortablePath } from './types'; | ||
import { FilePath, Pathable, PortablePath } from './types'; | ||
export class Path { | ||
/** | ||
* An immutable class for operating on file system paths. | ||
*/ | ||
export class Path implements Pathable { | ||
static DELIMITER = path.delimiter; | ||
static SEP = '/'; | ||
static SEP = path.sep; | ||
private internalPath: string = ''; | ||
private isNormalized: boolean = false; | ||
constructor(...parts: PortablePath[]) { | ||
// Always use forward slashes for better interop | ||
this.internalPath = path.normalize(path.join(...parts.map(String))).replace(/\\/gu, Path.SEP); | ||
this.internalPath = path.join(...parts.map(String)); | ||
} | ||
/** | ||
* Create and return a new `Path` instance if a string. | ||
* If already a `Path`, return as is. | ||
* Create and return a new `Path` instance. | ||
*/ | ||
static create(filePath: PortablePath): Path { | ||
return filePath instanceof Path ? filePath : new Path(filePath); | ||
return new Path(filePath); | ||
} | ||
/** | ||
* Like `create()` but also resolves the path against CWD. | ||
* Like `create()` but also resolves the path against a working directory. | ||
*/ | ||
@@ -51,3 +54,3 @@ static resolve(filePath: PortablePath, cwd?: PortablePath): Path { | ||
ext(withoutPeriod: boolean = false): string { | ||
const ext = path.extname(this.internalPath); | ||
const ext = path.extname(this.path()); | ||
@@ -61,3 +64,3 @@ return withoutPeriod && ext.startsWith('.') ? ext.slice(1) : ext; | ||
exists(): boolean { | ||
return fs.existsSync(this.internalPath); | ||
return fs.existsSync(this.path()); | ||
} | ||
@@ -69,3 +72,3 @@ | ||
isAbsolute(): boolean { | ||
return path.isAbsolute(this.internalPath); | ||
return path.isAbsolute(this.path()); | ||
} | ||
@@ -77,3 +80,3 @@ | ||
isDirectory(): boolean { | ||
return fs.statSync(this.internalPath).isDirectory(); | ||
return fs.statSync(this.path()).isDirectory(); | ||
} | ||
@@ -85,3 +88,3 @@ | ||
isFile(): boolean { | ||
return fs.statSync(this.internalPath).isFile(); | ||
return fs.statSync(this.path()).isFile(); | ||
} | ||
@@ -93,3 +96,3 @@ | ||
name(withoutExtension: boolean = false): string { | ||
let name = path.basename(this.internalPath); | ||
let name = path.basename(this.path()); | ||
@@ -114,2 +117,7 @@ if (withoutExtension) { | ||
path(): FilePath { | ||
if (!this.isNormalized) { | ||
this.isNormalized = true; | ||
this.internalPath = path.normalize(this.internalPath); | ||
} | ||
return this.internalPath; | ||
@@ -139,3 +147,3 @@ } | ||
relativeTo(to: PortablePath): Path { | ||
return new Path(path.relative(this.path(), String(to))); | ||
return new Path(path.relative(this.internalPath, String(to))); | ||
} | ||
@@ -145,3 +153,3 @@ | ||
* Return a new `Path` instance where the current path is accurately | ||
* resolved against the defined current working directory. | ||
* resolved against the defined working directory. | ||
*/ | ||
@@ -148,0 +156,0 @@ resolve(cwd?: PortablePath): Path { |
@@ -0,4 +1,6 @@ | ||
import doResolve from 'resolve'; | ||
import { CommonError } from './CommonError'; | ||
import { ModulePath } from './ModulePath'; | ||
import { Path } from './Path'; | ||
import { Lookup, LookupType, ModuleResolver, PortablePath } from './types'; | ||
import { Lookup, ModuleResolver, Pathable, PortablePath, ResolvedLookup } from './types'; | ||
@@ -11,5 +13,18 @@ export class PathResolver { | ||
constructor(resolver?: ModuleResolver) { | ||
this.resolver = resolver ?? require.resolve; | ||
this.resolver = resolver ?? PathResolver.defaultResolver; | ||
} | ||
static async defaultResolver(path: string, startDir?: string): Promise<string> { | ||
return new Promise((resolve, reject) => { | ||
// eslint-disable-next-line promise/prefer-await-to-callbacks | ||
doResolve(path, { basedir: startDir, includeCoreModules: false }, (error, foundPath) => { | ||
if (error || !foundPath) { | ||
reject(error); | ||
} else { | ||
resolve(foundPath); | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
@@ -30,3 +45,3 @@ * Return a list of all lookup paths. | ||
raw: Path.create(filePath), | ||
type: LookupType.FILE_SYSTEM, | ||
type: 'file-system', | ||
}); | ||
@@ -38,11 +53,23 @@ | ||
/** | ||
* Add a file system path with a list of possible extensions to look for, | ||
* resolved against the defined current working directory (or `process.cwd()` otherwise). | ||
*/ | ||
lookupFilePathWithExts(filePath: PortablePath, exts: string[], cwd?: PortablePath): this { | ||
exts.forEach((ext) => { | ||
const extWithPeriod = ext.startsWith('.') ? ext : `.${ext}`; | ||
this.lookupFilePath(`${filePath}${extWithPeriod}`, cwd); | ||
}); | ||
return this; | ||
} | ||
/** | ||
* Add a Node.js module, either by name or relative path, to look for. | ||
*/ | ||
lookupNodeModule(modulePath: PortablePath): this { | ||
const path = Path.create(modulePath); | ||
lookupNodeModule(moduleId: PortablePath): this { | ||
this.lookups.push({ | ||
path, | ||
raw: path, | ||
type: LookupType.NODE_MODULE, | ||
path: ModulePath.create(moduleId), | ||
raw: ModulePath.create(moduleId), | ||
type: 'node-module', | ||
}); | ||
@@ -56,39 +83,39 @@ | ||
* return a resolved absolute path. If a file system path, will check using `fs.exists`. | ||
* If a node module path, will check using `require.resolve`. | ||
* If a node module path, will check using the provided resolver. | ||
*/ | ||
resolve(): { | ||
originalPath: Path; | ||
resolvedPath: Path; | ||
type: LookupType; | ||
} { | ||
async resolve(startDir?: PortablePath): Promise<ResolvedLookup> { | ||
let resolvedPath: PortablePath = ''; | ||
let resolvedLookup: Lookup | undefined; | ||
this.lookups.some((lookup) => { | ||
// TODO: Switch to Promise.any() in Node.js v15 | ||
for (const lookup of this.lookups) { | ||
// Check that the file exists on the file system. | ||
if (lookup.type === LookupType.FILE_SYSTEM) { | ||
if (lookup.path.exists()) { | ||
resolvedPath = lookup.path; | ||
resolvedLookup = lookup; | ||
} else { | ||
return false; | ||
} | ||
if (lookup.type === 'file-system' && (lookup.path as Path).exists()) { | ||
resolvedPath = lookup.path; | ||
resolvedLookup = lookup; | ||
break; | ||
} | ||
// Check that the module path exists using Node's module resolution. | ||
// The `require.resolve` function will throw an error if not found. | ||
} else if (lookup.type === LookupType.NODE_MODULE) { | ||
// Check that the module path exists using Node's module resolution. | ||
// The resolver function will throw an error if not found. | ||
if (lookup.type === 'node-module') { | ||
try { | ||
resolvedPath = this.resolver(lookup.path.path()); | ||
// eslint-disable-next-line no-await-in-loop | ||
resolvedPath = await this.resolver( | ||
lookup.path.path(), | ||
startDir ? String(startDir) : undefined, | ||
); | ||
resolvedLookup = lookup; | ||
break; | ||
} catch { | ||
return false; | ||
// Display errors? | ||
} | ||
} | ||
} | ||
return true; | ||
}); | ||
if (!resolvedPath || !resolvedLookup) { | ||
throw new CommonError('PATH_RESOLVE_LOOKUPS', [ | ||
this.lookups.map((lookup) => ` - ${lookup.path} (${lookup.type})`).join('\n'), | ||
this.lookups | ||
.map((lookup) => ` - ${lookup.path} (${lookup.type.replace('-', ' ')})`) | ||
.join('\n'), | ||
]); | ||
@@ -98,3 +125,3 @@ } | ||
return { | ||
originalPath: resolvedLookup.raw, | ||
originalSource: resolvedLookup.raw, | ||
resolvedPath: Path.create(resolvedPath), | ||
@@ -106,7 +133,7 @@ type: resolvedLookup.type, | ||
/** | ||
* Like `resolve()` but only returns the resolved path. | ||
* Like `resolve()` but only returns the resolved file path. | ||
*/ | ||
resolvePath(): Path { | ||
return this.resolve().resolvedPath; | ||
async resolvePath(): Promise<Pathable> { | ||
return (await this.resolve()).resolvedPath; | ||
} | ||
} |
@@ -6,11 +6,6 @@ /* eslint-disable @typescript-eslint/member-ordering */ | ||
import { CommonError } from './CommonError'; | ||
import { parseFile } from './helpers/parseFile'; | ||
import { Path } from './Path'; | ||
import { | ||
FilePath, | ||
PackageStructure, | ||
PortablePath, | ||
WorkspaceMetadata, | ||
WorkspacePackage, | ||
} from './types'; | ||
import * as json from './serializers/json'; | ||
import * as yaml from './serializers/yaml'; | ||
import { PackageStructure, PortablePath, WorkspaceMetadata, WorkspacePackage } from './types'; | ||
@@ -29,2 +24,10 @@ export interface ProjectSearchOptions { | ||
/** | ||
* Normalize a glob pattern or path for use on POSIX and Windows machines. | ||
* @link https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows | ||
*/ | ||
static normalizeGlob(pattern: string): string { | ||
return pattern.replace(/\\/g, '/'); | ||
} | ||
/** | ||
* Create a workspace metadata object composed of absolute file paths. | ||
@@ -38,6 +41,6 @@ */ | ||
metadata.jsonPath = filePath.path(); | ||
metadata.packagePath = pkgPath.path(); | ||
metadata.jsonPath = filePath; | ||
metadata.packagePath = pkgPath; | ||
metadata.packageName = pkgPath.name(); | ||
metadata.workspacePath = wsPath.path(); | ||
metadata.workspacePath = wsPath; | ||
metadata.workspaceName = wsPath.name(); | ||
@@ -58,3 +61,3 @@ | ||
return parseFile<T>(pkgPath); | ||
return json.load<T>(pkgPath); | ||
} | ||
@@ -64,7 +67,7 @@ | ||
* Return a list of all workspace globs as they are configured | ||
* in `package.json` or `lerna.json`. | ||
* in `package.json` or `lerna.json`. Glob patterns will _always_ | ||
* use forward slashes, regardless of OS. | ||
*/ | ||
@Memoize() | ||
// eslint-disable-next-line complexity | ||
getWorkspaceGlobs(options: ProjectSearchOptions = {}): FilePath[] { | ||
getWorkspaceGlobs(options: ProjectSearchOptions = {}): string[] { | ||
const pkgPath = this.root.append('package.json'); | ||
@@ -77,3 +80,3 @@ const lernaPath = this.root.append('lerna.json'); | ||
if (pkgPath.exists()) { | ||
const pkg = parseFile<PackageStructure>(pkgPath); | ||
const pkg = json.load<PackageStructure>(pkgPath); | ||
@@ -91,3 +94,3 @@ if (pkg.workspaces) { | ||
if (workspacePaths.length === 0 && lernaPath.exists()) { | ||
const lerna = parseFile<{ packages: string[] }>(lernaPath); | ||
const lerna = json.load<{ packages: string[] }>(lernaPath); | ||
@@ -101,3 +104,3 @@ if (Array.isArray(lerna.packages)) { | ||
if (workspacePaths.length === 0 && pnpmPath.exists()) { | ||
const pnpm = parseFile<{ packages: string[] }>(pnpmPath); | ||
const pnpm = yaml.load<{ packages: string[] }>(pnpmPath); | ||
@@ -109,7 +112,9 @@ if (Array.isArray(pnpm.packages)) { | ||
if (options.relative) { | ||
return workspacePaths; | ||
} | ||
return workspacePaths.map((workspace) => { | ||
const path = options.relative | ||
? new Path(workspace).path() | ||
: this.root.append(workspace).path(); | ||
return workspacePaths.map((workspace) => this.root.append(workspace).path()); | ||
return Project.normalizeGlob(path); | ||
}); | ||
} | ||
@@ -134,3 +139,3 @@ | ||
metadata: this.createWorkspaceMetadata(filePath), | ||
package: parseFile<T>(filePath), | ||
package: json.load<T>(filePath), | ||
}; | ||
@@ -142,12 +147,15 @@ }); | ||
* Return a list of all workspace package paths, resolved against the file system. | ||
* Absolute file paths are returned unless the `relative` option is true. | ||
*/ | ||
@Memoize() | ||
getWorkspacePackagePaths(options: ProjectSearchOptions = {}): FilePath[] { | ||
return glob.sync(this.getWorkspaceGlobs({ relative: true }), { | ||
absolute: !options.relative, | ||
cwd: this.root.path(), | ||
onlyDirectories: true, | ||
onlyFiles: false, | ||
}); | ||
getWorkspacePackagePaths(options: ProjectSearchOptions = {}): Path[] { | ||
return glob | ||
.sync(this.getWorkspaceGlobs({ relative: true }), { | ||
absolute: !options.relative, | ||
cwd: this.root.path(), | ||
onlyDirectories: true, | ||
onlyFiles: false, | ||
}) | ||
.map(Path.create); | ||
} | ||
} |
@@ -0,2 +1,4 @@ | ||
import fs from 'fs'; | ||
import JSON from 'json5'; | ||
import { PortablePath } from '../types'; | ||
@@ -18,1 +20,5 @@ export type JSONReviver = (key: string, value: unknown) => unknown; | ||
} | ||
export function load<T>(path: PortablePath): T { | ||
return parse(fs.readFileSync(String(path), 'utf8')); | ||
} |
@@ -0,2 +1,4 @@ | ||
import fs from 'fs'; | ||
import YAML from 'yaml'; | ||
import { PortablePath } from '../types'; | ||
@@ -10,1 +12,5 @@ export function parse<T = object>(content: string, options?: YAML.Options): T { | ||
} | ||
export function load<T>(path: PortablePath): T { | ||
return parse(fs.readFileSync(String(path), 'utf8')); | ||
} |
@@ -1,8 +0,19 @@ | ||
import { Blueprint, Predicates } from 'optimal'; | ||
import type { Blueprint, Schemas } from 'optimal'; | ||
import type { Path } from './Path'; | ||
// NODE | ||
// PATHS | ||
export type ModuleName = string; | ||
export interface Pathable { | ||
path: () => string; | ||
toString: () => string; | ||
} | ||
export type PortablePath = FilePath | ModuleID | Pathable; | ||
// NODE MODULES | ||
export type ModuleID = string; | ||
export type ModuleResolver = (id: ModuleID, startDir?: FilePath) => FilePath | Promise<FilePath>; | ||
// FILE SYSTEM | ||
@@ -12,22 +23,24 @@ | ||
export type PortablePath = FilePath | Path; | ||
export type LookupType = 'file-system' | 'node-module'; | ||
export enum LookupType { | ||
FILE_SYSTEM = 'FILE_SYSTEM', | ||
NODE_MODULE = 'NODE_MODULE', | ||
export interface Lookup { | ||
path: Pathable; | ||
raw: Pathable; | ||
type: LookupType; | ||
} | ||
export interface Lookup { | ||
path: Path; | ||
raw: Path; | ||
export interface ResolvedLookup { | ||
/** Original file path or module ID of the lookup. */ | ||
originalSource: Pathable; | ||
/** Resolved absolute *file* path for the found lookup. */ | ||
resolvedPath: Path; | ||
/** The type of lookup that was found. */ | ||
type: LookupType; | ||
} | ||
export type ModuleResolver = (path: ModuleName) => FilePath; | ||
// CLASSES | ||
export type AbstractConstructor<T> = Function & { prototype: T }; | ||
export type AbstractConstructor<T> = abstract new (...args: any[]) => T; | ||
export type ConcreteConstructor<T> = new (...args: unknown[]) => T; | ||
export type ConcreteConstructor<T> = new (...args: any[]) => T; | ||
@@ -39,3 +52,3 @@ export type Constructor<T> = AbstractConstructor<T> | ConcreteConstructor<T>; | ||
export type BlueprintFactory<T extends object> = ( | ||
predicates: Predicates, | ||
schemas: Schemas, | ||
onConstruction?: boolean, | ||
@@ -46,3 +59,3 @@ ) => Blueprint<T>; | ||
/** Validated and configured options. */ | ||
readonly options: Required<T>; | ||
readonly options: Readonly<Required<T>>; | ||
@@ -173,6 +186,6 @@ /** | ||
export interface WorkspaceMetadata { | ||
jsonPath: string; | ||
packagePath: string; | ||
jsonPath: Path; | ||
packagePath: Path; | ||
packageName: string; | ||
workspacePath: string; | ||
workspacePath: Path; | ||
workspaceName: string; | ||
@@ -179,0 +192,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
4
199578
9
2
4904
+ Addedresolve@^1.20.0
+ Added@boost/decorators@3.0.0(transitive)
+ Added@boost/internal@3.0.1(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedis-core-module@2.15.1(transitive)
+ Addedoptimal@5.1.1(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedresolve@1.22.8(transitive)
+ Addedsupports-preserve-symlinks-flag@1.0.0(transitive)
- Removed@boost/decorators@2.1.4(transitive)
- Removed@boost/internal@2.2.3(transitive)
- Removedoptimal@4.3.0(transitive)
Updated@boost/decorators@^3.0.0
Updated@boost/internal@^3.0.0
Updatedoptimal@^5.1.0