Skip to content

Commit

Permalink
feat: add flags for node modules, globals, and optional
Browse files Browse the repository at this point in the history
closes #75
  • Loading branch information
Jack Ellis authored and jackmellis committed Sep 25, 2020
1 parent 8c01223 commit 32fa3d4
Show file tree
Hide file tree
Showing 17 changed files with 93 additions and 55 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 15 additions & 46 deletions src/Jpex.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
JpexInstance as IJpex,
AnyFunction,
Dependency,
Factory,
SetupConfig,
} from './types';
Expand All @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -76,45 +78,12 @@ class Jpex implements IJpex {
return getFactory(this, name, false).fn;
}

encase<F extends AnyFunction, G extends AnyFunction<F>>(_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<F>) {
/* 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<F extends AnyFunction, G extends AnyFunction<F>>(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() {
Expand Down
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions src/clearCache.ts
Original file line number Diff line number Diff line change
@@ -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;
35 changes: 35 additions & 0 deletions src/encase.ts
Original file line number Diff line number Diff line change
@@ -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<any>) {
/* 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;
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/deps/factory.ts → src/registers/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function factory(
const f: Factory = {
fn,
dependencies,
lifecycle: jpex.$$defaultLifecycle,
lifecycle: jpex.$$config.lifecycle,
};
jpex.$$factories[name as string] = f;

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/resolver/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const resolveOne = <R extends any>(
}

// 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');
Expand Down
13 changes: 10 additions & 3 deletions src/resolver/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const getFromNodeModules = (jpex: JpexInstance, target: string): Factory => {
if (!isNode) {
return;
}
if (!jpex.$$config.nodeModules) {
return;
}

try {
const value = unsafeRequire(target);
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
9 changes: 7 additions & 2 deletions src/types/JpexInstance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Lifecycle } from '../constants';
import { Wrapper } from '../deps/wrapper';
import { Wrapper } from '../registers/wrapper';
import {
AnyFunction,
Dependency,
Expand Down Expand Up @@ -62,11 +62,16 @@ export interface JpexInstance {
infer<T>(): string,

$$parent: JpexInstance,
$$defaultLifecycle: Lifecycle,
$$factories: {
[key: string]: Factory,
},
$$resolved: {
[key: string]: any,
},
$$config: {
lifecycle: Lifecycle,
optional: boolean,
nodeModules: boolean,
globals: boolean,
},
}
5 changes: 4 additions & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ export interface AnyConstructor<T = any> {
}

export interface SetupConfig {
lifecycle?: Lifecycle,
inherit?: boolean,
lifecycle?: Lifecycle,
optional?: boolean,
nodeModules?: boolean,
globals?: boolean,
}

export type Dependency = string | { [key: string]: any };
Expand Down

0 comments on commit 32fa3d4

Please sign in to comment.