From 0a420d402f4315e151a96292c08fb215d7487d7a Mon Sep 17 00:00:00 2001 From: Rafa Mel Date: Fri, 3 May 2019 08:11:22 +0200 Subject: [PATCH] fix: overwrites error constructors and helpers for locally imported kpo instances --- src/bin/kpo.ts | 4 ++-- src/core/index.ts | 2 ++ src/core/load.ts | 12 ++++++++---- src/core/options.ts | 2 ++ src/core/paths/index.ts | 4 ++-- src/core/run.ts | 4 ++-- src/core/tasks/from-kpo.ts | 4 ++-- src/core/tasks/index.ts | 6 ++++-- src/index.ts | 1 + src/public/exec/parallel.ts | 4 ++-- src/public/exec/stream.ts | 8 ++++++-- src/public/kpo/options.ts | 4 ++-- src/public/prompts/confirm.ts | 2 +- src/utils/errors.ts | 21 ++++++++++++++++----- src/utils/expose.ts | 4 ++-- 15 files changed, 54 insertions(+), 28 deletions(-) diff --git a/src/bin/kpo.ts b/src/bin/kpo.ts index 57206a9..d1b6a66 100644 --- a/src/bin/kpo.ts +++ b/src/bin/kpo.ts @@ -4,12 +4,12 @@ import main from './main'; import core from '~/core'; import { error } from 'cli-belt'; import logger from '~/utils/logger'; -import { OpenError } from '~/utils/errors'; +import errors from '~/utils/errors'; import { ensure } from 'errorish'; main(process.argv.slice(2)).catch(async (err) => { err = ensure(err); - const isOpen = err instanceof OpenError; + const isOpen = err instanceof errors.OpenError; return error(err, { exit: (await core.get('silent').catch(() => false)) ? 0 : 1, diff --git a/src/core/index.ts b/src/core/index.ts index a93b7ef..fd496a6 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -28,6 +28,8 @@ function cache(fn: () => T): () => T { return _cache(() => options.id, fn); } +// Core changes might constitute major version changes even if internal, as +// core is used overwritten for different kpo instances on load (requireLocal) const core = { get options() { return options; diff --git a/src/core/load.ts b/src/core/load.ts index e44fd95..41237e9 100644 --- a/src/core/load.ts +++ b/src/core/load.ts @@ -2,7 +2,7 @@ import path from 'path'; import fs from 'fs-extra'; import yaml from 'js-yaml'; import { rejects } from 'errorish'; -import { open } from '~/utils/errors'; +import errors from '~/utils/errors'; import { ILoaded, IPaths } from './types'; import { IOfType, IPackageOptions, TCoreOptions } from '~/types'; import options from './options'; @@ -88,7 +88,7 @@ export async function requireLocal( kpoPath = require.resolve('kpo', { paths: [file] }); } catch (_) {} if (kpoPath) { - const local = open.throws(() => require(kpoPath as string)); + const local = errors.open.throws(() => require(kpoPath as string)); if (!local || !local.core || !local.core.version) { throw Error( @@ -105,12 +105,16 @@ export async function requireLocal( (verDiff && version[0] === '0') ) { throw Error( - `Locally imported kpo version (${localVersion}) doesn't match executing instance version (${version})` + `Locally imported kpo version (${localVersion})` + + ` doesn't match executing instance version (${version})` ); } + // Overwrite options local.core.options.setBase(raw, 'post'); + // Overwrite error constructors and helpers + Object.assign(local.errors, errors); } - return open.throws(() => require(file)); + return errors.open.throws(() => require(file)); } diff --git a/src/core/options.ts b/src/core/options.ts index 6348a4a..a90946f 100644 --- a/src/core/options.ts +++ b/src/core/options.ts @@ -3,6 +3,8 @@ import { DEFAULT_LOG_LEVEL } from '~/constants'; import { setLevel } from '~/utils/logger'; import hash from 'object-hash'; +// Option changes should constitute major version changes even if internal, +// as they're overwritten for different kpo instances on load (requireLocal) export const state = { base: { force: 0, diff --git a/src/core/paths/index.ts b/src/core/paths/index.ts index d19e0be..eb60c18 100644 --- a/src/core/paths/index.ts +++ b/src/core/paths/index.ts @@ -1,7 +1,7 @@ import path from 'path'; import { IPaths } from '../types'; import getPaths from './paths'; -import { WrappedError } from '~/utils/errors'; +import errors from '~/utils/errors'; import { absolute } from '~/utils/file'; /** @@ -33,7 +33,7 @@ export async function getRootPaths(directories: { return await getPaths({ directory }, Boolean(root)); } catch (err) { if (!root) return null; - throw new WrappedError( + throw new errors.WrappedError( `root scope couldn't be retrieved: ${root}`, null, err diff --git a/src/core/run.ts b/src/core/run.ts index f36947f..153e97d 100644 --- a/src/core/run.ts +++ b/src/core/run.ts @@ -1,6 +1,6 @@ import logger from '~/utils/logger'; import { TScript } from '~/types'; -import { open } from '~/utils/errors'; +import errors from '~/utils/errors'; export default async function run( script: TScript, @@ -23,7 +23,7 @@ export default async function run( try { res = await runner(script); } catch (err) { - throw open.ensure(err); + throw errors.open.ensure(err); } await run(res, runner); } else if (Array.isArray(script)) { diff --git a/src/core/tasks/from-kpo.ts b/src/core/tasks/from-kpo.ts index 56a752f..2cd2a95 100644 --- a/src/core/tasks/from-kpo.ts +++ b/src/core/tasks/from-kpo.ts @@ -1,7 +1,7 @@ import { ITask } from '../types'; import { IScripts } from '~/types'; import purePath from './pure-path'; -import { CustomError } from '~/utils/errors'; +import errors from '~/utils/errors'; export default function getFromKpo(path: string, kpo: IScripts): ITask { const task = trunk(purePath(path).split('.'), kpo, ''); @@ -42,7 +42,7 @@ export function trunk(arr: string[], obj: any, path: string): ITask { ); } if (!props.length) { - throw new CustomError( + throw new errors.CustomError( `There are no tasks matching ${purePath(path ? `${path}.${key}` : key)}`, { type: 'NotFound' } ); diff --git a/src/core/tasks/index.ts b/src/core/tasks/index.ts index b9c11fa..13f13e6 100644 --- a/src/core/tasks/index.ts +++ b/src/core/tasks/index.ts @@ -3,7 +3,7 @@ import getFromKpo from './from-kpo'; import getFromPackage from './from-package'; import { ITask, ITasks } from '../types'; import recursiveFields from './recursive-fields'; -import { CustomError } from '~/utils/errors'; +import errors from '~/utils/errors'; export function getTask( path: string, @@ -12,7 +12,9 @@ export function getTask( ): ITask { try { if (kpo) return getFromKpo(path, kpo); - throw new CustomError(`Task ${path} not found`, { type: 'NotFound' }); + throw new errors.CustomError(`Task ${path} not found`, { + type: 'NotFound' + }); } catch (err) { if (!pkg || !err.data || !err.data.type || err.data.type !== 'NotFound') { throw err; diff --git a/src/index.ts b/src/index.ts index 06cb89c..cc8d697 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ export * from './public'; export { default as core } from './core'; +export { default as errors } from './utils/errors'; export * from './types'; diff --git a/src/public/exec/parallel.ts b/src/public/exec/parallel.ts index 08259d2..597bc0c 100644 --- a/src/public/exec/parallel.ts +++ b/src/public/exec/parallel.ts @@ -1,7 +1,7 @@ import core from '~/core'; import { IOfType, IMultiExecOptions } from '~/types'; import logger from '~/utils/logger'; -import { WrappedError } from '~/utils/errors'; +import errors from '~/utils/errors'; import expose from '~/utils/expose'; import join from 'command-join'; import { CONCURRENTLY_PATH } from '~/constants'; @@ -62,7 +62,7 @@ export function create(): IParallel { try { await core.exec(CONCURRENTLY_PATH, argv, true, options); } catch (e) { - const err = new WrappedError( + const err = new errors.WrappedError( 'Parallel commands execution failed', null, e diff --git a/src/public/exec/stream.ts b/src/public/exec/stream.ts index d355336..9d6ca37 100644 --- a/src/public/exec/stream.ts +++ b/src/public/exec/stream.ts @@ -8,7 +8,7 @@ import { NODE_PATH, KPO_PATH } from '~/constants'; import { IMultiExecOptions } from '~/types'; import chalk from 'chalk'; import { oneLine } from 'common-tags'; -import { WrappedError } from '~/utils/errors'; +import errors from '~/utils/errors'; /** * Options taken by `stream` @@ -89,7 +89,11 @@ function stream( ), { ...options, cwd: undefined } )(args).catch(async (err) => { - throw new WrappedError('Series commands execution failed', null, err); + throw new errors.WrappedError( + 'Series commands execution failed', + null, + err + ); })); }; } diff --git a/src/public/kpo/options.ts b/src/public/kpo/options.ts index 4228d9e..e56d279 100644 --- a/src/public/kpo/options.ts +++ b/src/public/kpo/options.ts @@ -1,10 +1,10 @@ import { options as _options } from '~/core'; import { IScopeOptions } from '~/types'; -import { wrap } from '~/utils/errors'; +import errors from '~/utils/errors'; /** * Programmatically sets *kpo* options. */ export default function options(opts: IScopeOptions): void { - return wrap.throws(() => _options.setScope(opts)); + return errors.wrap.throws(() => _options.setScope(opts)); } diff --git a/src/public/prompts/confirm.ts b/src/public/prompts/confirm.ts index 2f6e53d..1d5e41e 100644 --- a/src/public/prompts/confirm.ts +++ b/src/public/prompts/confirm.ts @@ -1,4 +1,4 @@ -// +// force import of transpiled prompts import prompts from 'prompts/dist'; import { TScript } from '~/types'; import { status } from 'promist'; diff --git a/src/utils/errors.ts b/src/utils/errors.ts index acab18e..5cb52fc 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,25 +1,36 @@ import { scope, Errorish } from 'errorish'; -export class CustomError extends Errorish {} +// Error changes might constitute major version changes even if internal, +// as they're overwritten for different kpo instances on load (requireLocal) -export class OpenError extends CustomError { +class CustomError extends Errorish {} + +class OpenError extends CustomError { public get name(): string { return 'OpenError'; } } -export class WrappedError extends CustomError { +class WrappedError extends CustomError { public get name(): string { return 'WrappedError'; } } -export const open = scope.set('_kpo_open_', { +const open = scope.set('_kpo_open_', { Error: CustomError, Errorish: OpenError }); -export const wrap = scope.set('_kpo_wrap_', { +const wrap = scope.set('_kpo_wrap_', { Error: CustomError, Errorish: WrappedError }); + +export default { + CustomError, + OpenError, + WrappedError, + open, + wrap +}; diff --git a/src/utils/expose.ts b/src/utils/expose.ts index 48e63bf..5ef95f1 100644 --- a/src/utils/expose.ts +++ b/src/utils/expose.ts @@ -1,5 +1,5 @@ import { TScriptFn } from '~/types'; -import { wrap } from './errors'; +import errors from './errors'; export type TExposedOverload< T extends (...args: any[]) => TScriptFn, @@ -21,7 +21,7 @@ export default function expose TScriptFn>( ): TExposed { const exposed = function(...args: any[]): any { return (argv?: string[]) => { - return wrap.throws(() => fn(...args)(argv)); + return errors.wrap.throws(() => fn(...args)(argv)); }; }; exposed.fn = function(...args: any[]) {