From 32fa3d4b0ad4f68343699cb34cf2b87e9aaee4c2 Mon Sep 17 00:00:00 2001 From: Jack Ellis Date: Tue, 18 Aug 2020 06:22:59 +0100 Subject: [PATCH] feat: add flags for node modules, globals, and optional closes #75 --- CHANGELOG.md | 2 + src/Jpex.ts | 61 ++++++------------------- src/{factories => built-ins}/index.ts | 0 src/{factories => built-ins}/resolve.ts | 0 src/clearCache.ts | 17 +++++++ src/encase.ts | 35 ++++++++++++++ src/index.ts | 2 +- src/{deps => registers}/alias.ts | 0 src/{deps => registers}/constant.ts | 0 src/{deps => registers}/factory.ts | 2 +- src/{deps => registers}/index.ts | 0 src/{deps => registers}/service.ts | 0 src/{deps => registers}/wrapper.ts | 0 src/resolver/resolve.ts | 2 +- src/resolver/utils.ts | 13 ++++-- src/types/JpexInstance.ts | 9 +++- src/types/index.ts | 5 +- 17 files changed, 93 insertions(+), 55 deletions(-) rename src/{factories => built-ins}/index.ts (100%) rename src/{factories => built-ins}/resolve.ts (100%) create mode 100644 src/clearCache.ts create mode 100644 src/encase.ts rename src/{deps => registers}/alias.ts (100%) rename src/{deps => registers}/constant.ts (100%) rename src/{deps => registers}/factory.ts (95%) rename src/{deps => registers}/index.ts (100%) rename src/{deps => registers}/service.ts (100%) rename src/{deps => registers}/wrapper.ts (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ec77b8..c08259a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ Change Log ========== ### 4.0.0 - global dependencies such as `Window` and `Document` are now automatically resolved (unless you register your own dependency of the same name) +- you can now control dependency resolution with config flags `nodeModules` and `globals` +- you can also specify whether dependencies should be optional-by-default with an `optional` flag ### 3.5.1 - building with webpack was giving warnings about `require` being used which meant it couldn't make optimizations diff --git a/src/Jpex.ts b/src/Jpex.ts index d13bd74..9d65179 100644 --- a/src/Jpex.ts +++ b/src/Jpex.ts @@ -1,7 +1,6 @@ import { JpexInstance as IJpex, AnyFunction, - Dependency, Factory, SetupConfig, } from './types'; @@ -13,20 +12,17 @@ import { factory, service, alias as createAlias, -} from './deps'; +} from './registers'; import { resolve, - resolveDependencies, - allResolved, getFactory, } from './resolver'; -import { - extractParameters, -} from './utils'; +import encase from './encase'; +import clearCache from './clearCache'; class Jpex implements IJpex { decorate: any; - $$defaultLifecycle: Lifecycle; + $$config: IJpex['$$config']; $$parent: IJpex; $$factories: { [key: string]: Factory, @@ -38,11 +34,17 @@ class Jpex implements IJpex { constructor(options: SetupConfig = {}, parent?: IJpex) { const { inherit = true, - lifecycle = (inherit ? parent?.$$defaultLifecycle : void 0) ?? Lifecycle.CLASS, + ...config } = options; this.$$parent = parent; - this.$$defaultLifecycle = lifecycle; + this.$$config = { + lifecycle: inherit ? parent?.$$config.lifecycle : void 0 ?? Lifecycle.CLASS, + globals: true, + nodeModules: true, + optional: false, + ...config, + }; if (parent && inherit) { this.$$factories = Object.create(parent.$$factories); @@ -76,45 +78,12 @@ class Jpex implements IJpex { return getFactory(this, name, false).fn; } - encase>(_deps: any, _fn?: any): any { - const [ dependencies, fn ] = ((): [ Dependency[], G ] => { - if (typeof _deps === 'function') { - return [ extractParameters(_deps), _deps ]; - } - return [ _deps, _fn ]; - })(); - let result: AnyFunction; - const jpex = this; - - const encased = function(...args: Parameters) { - /* eslint-disable no-invalid-this */ - if (result && allResolved(jpex, dependencies)) { - return result.apply(this, args); - } - const deps = resolveDependencies(jpex, { dependencies }); - - result = fn.apply(this, deps); - - return result.apply(this, args); - /* eslint-enable */ - }; - encased.encased = fn; - - return encased; + encase>(deps: any, fn?: any): any { + return encase(this, deps, fn); } clearCache(names?: any): any { - names = [].concat(names || []); - for (const key in this.$$factories) { - if (!names.length || names.indexOf(key) > -1) { - this.$$factories[key].resolved = false; - } - } - for (const key in this.$$resolved) { - if (!names.length || names.indexOf(key) > -1) { - delete this.$$resolved[key]; - } - } + return clearCache(this, names); } infer() { diff --git a/src/factories/index.ts b/src/built-ins/index.ts similarity index 100% rename from src/factories/index.ts rename to src/built-ins/index.ts diff --git a/src/factories/resolve.ts b/src/built-ins/resolve.ts similarity index 100% rename from src/factories/resolve.ts rename to src/built-ins/resolve.ts diff --git a/src/clearCache.ts b/src/clearCache.ts new file mode 100644 index 0000000..9e7f139 --- /dev/null +++ b/src/clearCache.ts @@ -0,0 +1,17 @@ +import { JpexInstance } from './types'; + +const clearCache = (jpex: JpexInstance, names?: any): any => { + names = [].concat(names || []); + for (const key in jpex.$$factories) { + if (!names.length || names.indexOf(key) > -1) { + jpex.$$factories[key].resolved = false; + } + } + for (const key in jpex.$$resolved) { + if (!names.length || names.indexOf(key) > -1) { + delete jpex.$$resolved[key]; + } + } +}; + +export default clearCache; diff --git a/src/encase.ts b/src/encase.ts new file mode 100644 index 0000000..5424ef8 --- /dev/null +++ b/src/encase.ts @@ -0,0 +1,35 @@ +import { JpexInstance, Dependency, AnyFunction } from './types'; +import { extractParameters } from './utils'; +import { allResolved, resolveDependencies } from './resolver'; + +const encase = ( + jpex: JpexInstance, + _deps: string[], + _fn?: any, +): any => { + const [ dependencies, fn ] = ((): [ Dependency[], any ] => { + if (typeof _deps === 'function') { + return [ extractParameters(_deps), _deps ]; + } + return [ _deps, _fn ]; + })(); + let result: AnyFunction; + + const encased = function(...args: Parameters) { + /* eslint-disable no-invalid-this */ + if (result && allResolved(jpex, dependencies)) { + return result.apply(this, args); + } + const deps = resolveDependencies(jpex, { dependencies }); + + result = fn.apply(this, deps); + + return result.apply(this, args); + /* eslint-enable */ + }; + encased.encased = fn; + + return encased; +}; + +export default encase; diff --git a/src/index.ts b/src/index.ts index d9a407e..f6b03d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import Jpex from './Jpex'; -import { resolve as registerResolveFactory } from './factories'; +import { resolve as registerResolveFactory } from './built-ins'; import type { JpexInstance, SetupConfig, diff --git a/src/deps/alias.ts b/src/registers/alias.ts similarity index 100% rename from src/deps/alias.ts rename to src/registers/alias.ts diff --git a/src/deps/constant.ts b/src/registers/constant.ts similarity index 100% rename from src/deps/constant.ts rename to src/registers/constant.ts diff --git a/src/deps/factory.ts b/src/registers/factory.ts similarity index 95% rename from src/deps/factory.ts rename to src/registers/factory.ts index fbd7381..2d19817 100644 --- a/src/deps/factory.ts +++ b/src/registers/factory.ts @@ -30,7 +30,7 @@ function factory( const f: Factory = { fn, dependencies, - lifecycle: jpex.$$defaultLifecycle, + lifecycle: jpex.$$config.lifecycle, }; jpex.$$factories[name as string] = f; diff --git a/src/deps/index.ts b/src/registers/index.ts similarity index 100% rename from src/deps/index.ts rename to src/registers/index.ts diff --git a/src/deps/service.ts b/src/registers/service.ts similarity index 100% rename from src/deps/service.ts rename to src/registers/service.ts diff --git a/src/deps/wrapper.ts b/src/registers/wrapper.ts similarity index 100% rename from src/deps/wrapper.ts rename to src/registers/wrapper.ts diff --git a/src/resolver/resolve.ts b/src/resolver/resolve.ts index fe08987..2806ff9 100644 --- a/src/resolver/resolve.ts +++ b/src/resolver/resolve.ts @@ -34,7 +34,7 @@ export const resolveOne = ( } // Optional dependencies - let optional = false; + let optional = jpex.$$config.optional; const optionalCheck = checkOptional(name); if (optionalCheck) { console.warn('jpex: __ optional syntax has been deprecated and will be removed in v4.0.0'); diff --git a/src/resolver/utils.ts b/src/resolver/utils.ts index 4071b1d..882ad6f 100644 --- a/src/resolver/utils.ts +++ b/src/resolver/utils.ts @@ -31,6 +31,9 @@ const getFromNodeModules = (jpex: JpexInstance, target: string): Factory => { if (!isNode) { return; } + if (!jpex.$$config.nodeModules) { + return; + } try { const value = unsafeRequire(target); @@ -75,6 +78,10 @@ const getGlobalProperty = (name: string) => { } }; const getFromGlobal = (jpex: JpexInstance, name: string): Factory => { + if (!jpex.$$config.globals) { + return; + } + const value = getGlobalProperty(name); if (value !== void 0) { @@ -87,12 +94,12 @@ export const getFactory = (jpex: JpexInstance, name: string, optional: boolean) if (typeof name !== 'string') { throw new JpexError(`Name must be a string, but recevied ${typeof name}`); } - let factory: Factory = jpex.$$resolved[name as string]; + let factory: Factory = jpex.$$resolved[name]; if (isValidFactory(factory)) { return factory; } - factory = jpex.$$factories[name as string]; + factory = jpex.$$factories[name]; if (isValidFactory(factory)) { return factory; } @@ -102,7 +109,7 @@ export const getFactory = (jpex: JpexInstance, name: string, optional: boolean) return factory; } - factory = getFromNodeModules(jpex, name as string); + factory = getFromNodeModules(jpex, name); if (isValidFactory(factory)) { return factory; } diff --git a/src/types/JpexInstance.ts b/src/types/JpexInstance.ts index 1f10d0b..8f02ca7 100644 --- a/src/types/JpexInstance.ts +++ b/src/types/JpexInstance.ts @@ -1,5 +1,5 @@ import { Lifecycle } from '../constants'; -import { Wrapper } from '../deps/wrapper'; +import { Wrapper } from '../registers/wrapper'; import { AnyFunction, Dependency, @@ -62,11 +62,16 @@ export interface JpexInstance { infer(): string, $$parent: JpexInstance, - $$defaultLifecycle: Lifecycle, $$factories: { [key: string]: Factory, }, $$resolved: { [key: string]: any, }, + $$config: { + lifecycle: Lifecycle, + optional: boolean, + nodeModules: boolean, + globals: boolean, + }, } diff --git a/src/types/index.ts b/src/types/index.ts index fde8b09..1acf2f4 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -8,8 +8,11 @@ export interface AnyConstructor { } export interface SetupConfig { - lifecycle?: Lifecycle, inherit?: boolean, + lifecycle?: Lifecycle, + optional?: boolean, + nodeModules?: boolean, + globals?: boolean, } export type Dependency = string | { [key: string]: any };