New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

jpex

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jpex - npm Package Compare versions

Comparing version 4.3.0 to 4.3.1

dist/ts/types/base.d.ts

145

CHANGELOG.md

@@ -1,6 +0,7 @@

Change Log
==========
# Change Log
Further change logs can be found on the [releases](https://github.com/jpex-js/jpex/releases) page
### 4.0.0
- global dependencies such as `Window` and `Document` are now automatically resolved (unless you register your own dependency of the same name)

@@ -21,2 +22,3 @@ - you can now control dependency resolution with config flags `nodeModules` and `globals`

#### Breaking Changes
- if you attempt to resolve a global like `Window` without registering it first, rather than throw an error, you will now get the global variable

@@ -33,8 +35,11 @@ - You can no longer do `jpex.factory('foo', (depA, depB) => { ... })` as we no longer parse the function and extract the dependencies.

### 3.5.1
- building with webpack was giving warnings about `require` being used which meant it couldn't make optimizations
### 3.5.0
- add some deprecation warnings for pre-4.0.0 changes
### 3.4.0
- clearCache now supports type inference

@@ -45,20 +50,27 @@ - you can now pass `publicPath: true` and it will use the `name` property of your app's `package.json` as the public path

### 3.3.3
- array dependencies were being incorrectly flattened
### 3.3.1
- publicPath relative imports was checking the incorrect path property
### 3.3.0
- add `jpex.extend` option: `inherit` (defaults to `true`). Determines if the extended container should inherit factories
### 3.2.3
- publicPath should be operate on relative `.` imports
### 3.2.2
- publicPath option was not working correctly for complex relative imports
### 3.2.1
- support `useResolve` taking a dependency array
## 3.2.0
- add `jpex.raw` function for extracting a factory function

@@ -69,5 +81,7 @@ - add publicPath babel config option

## 3.1.0
- global types like `Window` and `Document` can now be used to register dependencies
## 3.0.1
- encase now caches the wrapped function for better performance

@@ -79,2 +93,3 @@ - alias is now bidirectional, so it determines which is the alias and which is the original

## 3.0.0
- Complete rewrite of the entire library

@@ -94,2 +109,3 @@ - Typescript support

## 2.1.0
- if an option in the `properties` config is null, jpex will no longer throw an error

@@ -100,65 +116,82 @@ - Passing `$options` into a `Jpex as a Service` service now works

## 2.0.0
### Features
- Can now pass in a `config` option when extending a class. Any properties of the config option will be used as default values for that class and its descendants.
- The default lifecycle for factories registered against a class can now be configured using the `defaultLifecycle` option.
- Methods option has been added (which replaces the *prototype* option from v1).
- Properties option has been added, allowing you to predefine getters, setters, and watchers on any instance properties.
- the `bindToInstance` option can now accept a nested property name, i.e. `bindToInstance : 'foo.bah'`
- Node-specific code has been isolated so the core *jpex* module can be included in any webpack/browserify build. (*see depcrecation of jpex-web below*)
- Added a pre-compiled build of Jpex at `jpex/dist/jpex.js` and `jpex/dist/jpex.min.js`
- Default factories (`$timeout`, `$promise`, etc.) have been separated from the core module. They now must be installed separately from the **jpex-defaults**, **jpex-node**, and **jpex-web** packages.
- The `$resolve` method is now available as a static method on every class, so dependencies can be resolved with `Class.$resolve(name)`. This allows for **Jpex** to be used as a container rather than forcing the class instantiation pattern.
- `$resolve` can be called with an array of dependencies to resolve instead of just one.
- Cached factories (i.e. with a `class` or `application` lifecycle) can be cleared with `Class.$clearCache()`.
- Added `decorators` that allow a factory to be altered before being resolved. Can be registered like normal factories i.e. `Class.register.decorator(name, fn)`
- A complete plugin API has been created that allows plugins to hook into a number of lifecycle events.
## 2.0.0
### Breaking Changes
- The `prototype` option has been replaced with `methods`
- The **jpex-web** version of Jpex has been deprecated. Instead, Jpex can be `required`'d with *webpack/browserify*, or a web-safe js file can be found at `jpex/dist/jpex.js/`
- Internal variables have been renamed. e.g. `Class._factories` is now `Class.$$factories`.
### Features
- Can now pass in a `config` option when extending a class. Any properties of the config option will be used as default values for that class and its descendants.
- The default lifecycle for factories registered against a class can now be configured using the `defaultLifecycle` option.
- Methods option has been added (which replaces the _prototype_ option from v1).
- Properties option has been added, allowing you to predefine getters, setters, and watchers on any instance properties.
- the `bindToInstance` option can now accept a nested property name, i.e. `bindToInstance : 'foo.bah'`
- Node-specific code has been isolated so the core _jpex_ module can be included in any webpack/browserify build. (_see depcrecation of jpex-web below_)
- Added a pre-compiled build of Jpex at `jpex/dist/jpex.js` and `jpex/dist/jpex.min.js`
- Default factories (`$timeout`, `$promise`, etc.) have been separated from the core module. They now must be installed separately from the **jpex-defaults**, **jpex-node**, and **jpex-web** packages.
- After deprecating its use in v1.3.0, the `singleton` option has been removed from factory registration. `Class.register.factory(name, fn, true/false)` should now be written as `Class.register.factory(name, fn).lifecycle.application()`
- Following depcrecation in v1.4.0, the static methods `Typeof` and `Copy` have been removed.
- Factory registration methods have been renamed to camelCase: `Jpex.Register.Factory` becomes `Jpex.register.factory`, for example.
- `Interfaces` have been completely removed from the module. This was an experimental feature that in the end was more overhead than it was worth.
- A number of spurious factory types have been removed: *enum, errorType, file, folder, interface, nodeModule* - although the *nodeModule* factory type is still available via the **jpex-node** package as `Class.register.node_module`.
- Ancestoral dependencies have been removed so depending on `["^someParentFactory"]` will no longer work. The equivalent can now be achieved with *decorators*.
- The `$resolve` method is now available as a static method on every class, so dependencies can be resolved with `Class.$resolve(name)`. This allows for **Jpex** to be used as a container rather than forcing the class instantiation pattern.
- `$resolve` can be called with an array of dependencies to resolve instead of just one.
- Cached factories (i.e. with a `class` or `application` lifecycle) can be cleared with `Class.$clearCache()`.
- Added `decorators` that allow a factory to be altered before being resolved. Can be registered like normal factories i.e. `Class.register.decorator(name, fn)`
- A complete plugin API has been created that allows plugins to hook into a number of lifecycle events.
## 1.4.1
### Bugs
- `$copy.extend` no longer combines arrays, but instead replaces the previous array value.
- `$timeout $immediate $interval $tick` bug fixed when attaching to a class instance.
- Added a `clear()` method to the timer factories that clear the respective timeouts.
### Breaking Changes
## 1.4.0
### Features
- $typeof factory is available which returns the type of an object.
- $copy factory allows you create a deep or shallow copy of an object, or combine multiple objects.
- $itypeof and $icopy interfaces
- The static methods Jpex.Typeof and Jpex.Copy have been deprecated and will be removed in a future release.
- $resolve factory which allows lazy loading of dependencies.
### Breaking Changes
- Calling `Class()` is now the same as calling `new Class()` so calls like `Class.call(obj)===obj` will no longer work.
- The `prototype` option has been replaced with `methods`
- The **jpex-web** version of Jpex has been deprecated. Instead, Jpex can be `required`'d with _webpack/browserify_, or a web-safe js file can be found at `jpex/dist/jpex.js/`
- Internal variables have been renamed. e.g. `Class._factories` is now `Class.$$factories`.
- Default factories (`$timeout`, `$promise`, etc.) have been separated from the core module. They now must be installed separately from the **jpex-defaults**, **jpex-node**, and **jpex-web** packages.
- After deprecating its use in v1.3.0, the `singleton` option has been removed from factory registration. `Class.register.factory(name, fn, true/false)` should now be written as `Class.register.factory(name, fn).lifecycle.application()`
- Following depcrecation in v1.4.0, the static methods `Typeof` and `Copy` have been removed.
- Factory registration methods have been renamed to camelCase: `Jpex.Register.Factory` becomes `Jpex.register.factory`, for example.
- `Interfaces` have been completely removed from the module. This was an experimental feature that in the end was more overhead than it was worth.
- A number of spurious factory types have been removed: _enum, errorType, file, folder, interface, nodeModule_ - although the _nodeModule_ factory type is still available via the **jpex-node** package as `Class.register.node_module`.
- Ancestoral dependencies have been removed so depending on `["^someParentFactory"]` will no longer work. The equivalent can now be achieved with _decorators_.
## 1.3.1
### Bugs
- Fixed issues where `require`-based functions were not requiring from the correct location.
## 1.4.1
### Bugs
- `$copy.extend` no longer combines arrays, but instead replaces the previous array value.
- `$timeout $immediate $interval $tick` bug fixed when attaching to a class instance.
- Added a `clear()` method to the timer factories that clear the respective timeouts.
## 1.4.0
### Features
- $typeof factory is available which returns the type of an object.
- $copy factory allows you create a deep or shallow copy of an object, or combine multiple objects.
- $itypeof and $icopy interfaces
- The static methods Jpex.Typeof and Jpex.Copy have been deprecated and will be removed in a future release.
- $resolve factory which allows lazy loading of dependencies.
### Breaking Changes
- Calling `Class()` is now the same as calling `new Class()` so calls like `Class.call(obj)===obj` will no longer work.
## 1.3.1
### Bugs
- Fixed issues where `require`-based functions were not requiring from the correct location.
## 1.3.0
### Features
- Interfaces functionality added
- Registering a factory returns an object with additional option methods (currently only contains the *interface()* method)
- It is now possible to specify the life cycle of a factory or service using the `.lifecycle.x()` syntax. Possible options are `application`, `class`, `instance`, `none`
- Due to the introduction of life cycles, the *singleton* parameter has been deprecated.
- Interfaces functionality added
- Registering a factory returns an object with additional option methods (currently only contains the _interface()_ method)
- It is now possible to specify the life cycle of a factory or service using the `.lifecycle.x()` syntax. Possible options are `application`, `class`, `instance`, `none`
- Due to the introduction of life cycles, the _singleton_ parameter has been deprecated.
### Breaking Changes
- All $ factories now have interfaces (i.e. *$ipromise*). If you have overwritten a default factory that is used by another default factory, it will need to include the interface in order to work. i.e. *$fs* used to depend on *$promise* but it now depends on $ipromise.
## 1.2.0
### Features
- Added detailed documentation
- $error factory and $errorFactory factory
- ErrorType Factory i.e. `jpex.Register.ErrorType('Custom')`
- Ancestoral dependencies i.e. `['^$errorFactory']`
- Deprecated jpex-fs as it is now included in the standard jpex build
- All $ factories now have interfaces (i.e. _$ipromise_). If you have overwritten a default factory that is used by another default factory, it will need to include the interface in order to work. i.e. _$fs_ used to depend on _$promise_ but it now depends on $ipromise.
## 1.2.0
### Features
- Added detailed documentation
- $error factory and $errorFactory factory
- ErrorType Factory i.e. `jpex.Register.ErrorType('Custom')`
- Ancestoral dependencies i.e. `['^$errorFactory']`
- Deprecated jpex-fs as it is now included in the standard jpex build

@@ -5,31 +5,40 @@ 'use strict';

function constant(name, obj) {
return this.factory(name, [], () => obj, {
lifecycle: 'application'
});
}
const isString = obj => typeof obj === 'string';
const isFunction = obj => typeof obj === 'function';
const validateName = name => {
if (!isString(name)) {
throw new Error(`Name must be a string, but recevied ${typeof name}`);
}
};
const validateDependencies = dependencies => {
if (!Array.isArray(dependencies)) {
throw new Error(`Expected an array of dependencies, but was called with [${typeof dependencies}]`);
}
};
const validateFactory = (name, fn) => {
if (!isFunction(fn)) {
throw new Error(`Factory ${name} must be a [Function]`);
}
};
const validateArgs = (name, dependencies, fn) => {
validateName(name);
validateDependencies(dependencies);
validateFactory(name, fn);
};
const isPassive = (name, jpex, precedence) => {
return (precedence || jpex.$$config.precedence) === 'passive' && jpex.$$factories[name] != null;
};
const instantiate = (context, args) => {
// eslint-disable-next-line new-parens
return new (Function.prototype.bind.apply(context, args))();
};
const isNode = () => {
let _process; // eslint-disable-line no-underscore-dangle
let _process;
try {
// eslint-disable-next-line no-new-func
_process = new Function('return process')();
} catch (e) {// No process
} // eslint-disable-next-line max-len
} catch (e) {
}
return typeof _process === 'object' && _process.toString && _process.toString() === '[object process]';
}; // eslint-disable-next-line no-new-func
};
const doUnsafeRequire = new Function('require', 'target', 'return require.main.require(target)');
const unsafeRequire = target => {
// eslint-disable-next-line no-eval
return doUnsafeRequire(eval('require'), target);

@@ -41,7 +50,5 @@ };

}
if (Array.isArray(arr)) {
return arr;
}
return [arr];

@@ -51,28 +58,24 @@ };

const validateArgs = (name, dependencies, fn) => {
if (!isString(name)) {
throw new Error(`Factories must be given a name, but was called with [${typeof name}]`);
function constant(name, obj) {
validateName(name);
if (isPassive(name, this)) {
return;
}
this.$$factories[name] = {
fn: () => obj,
lifecycle: 'application',
value: obj,
resolved: true
};
}
if (!Array.isArray(dependencies)) {
throw new Error(`Expected an array of dependencies, but was called with [${typeof dependencies}]`);
}
if (!isFunction(fn)) {
throw new Error(`Factory ${name} must be a [Function]`);
}
};
function factory(name, dependencies, fn, opts = {}) {
validateArgs(name, dependencies, fn);
if (!hasLength(dependencies)) {
dependencies = null;
} // eslint-disable-next-line max-len
if ((opts.precedence || this.$$config.precedence) === 'passive' && this.$$factories[name] != null) {
}
if (isPassive(name, this, opts.precedence)) {
return;
}
const f = {
this.$$factories[name] = {
fn,

@@ -82,4 +85,2 @@ dependencies,

};
this.$$factories[name] = f;
if (opts.alias) {

@@ -92,6 +93,4 @@ ensureArray(opts.alias).forEach(alias => this.alias(alias, name));

validateArgs(name, dependencies, fn);
function factory(...args) {
const context = {};
if (opts.bindToInstance) {

@@ -102,6 +101,4 @@ dependencies.forEach((key, i) => {

}
return instantiate(fn, [context, ...args]);
}
return this.factory(name, dependencies, factory, opts);

@@ -114,3 +111,2 @@ }

}
if (this.$$alias[name] == null || this.$$config.precedence === 'active') {

@@ -126,9 +122,5 @@ this.$$alias[name] = alias;

const getFromNodeModules = (jpex, target) => {
// in order to stop webpack environments from including every possible
// import source in the bundle, we have to stick all node require stuff
// inside an eval setup
if (!jpex.$$config.nodeModules || !isNode()) {
return;
}
try {

@@ -140,42 +132,26 @@ const value = unsafeRequire(target);

var _e$message;
if ((_e$message = e.message) != null && _e$message.includes != null && _e$message.includes(`Cannot find module '${target}'`)) {
// not found in node modules, just continue
return;
}
throw e;
}
};
const getGlobalObject = () => {
if (typeof global !== VOID) {
// eslint-disable-next-line no-undef
return global;
}
if (typeof globalThis !== VOID) {
// eslint-disable-next-line no-undef
return globalThis;
}
if (typeof window !== VOID) {
return window;
}
return {};
};
const getGlobalProperty = name => {
const global = getGlobalObject();
if (global[name] !== void 0) {
return global[name];
} // we need to handle inferred types as well
// this gets a little bit hacky...
}
if (name.startsWith(GLOBAL_TYPE_PREFIX)) {
// most global types will just be the name of the property in pascal case
// i.e. window = Window / document = Document
const len = GLOBAL_TYPE_PREFIX.length;

@@ -186,3 +162,2 @@ const inferredName = name.charAt(len).toLowerCase() + name.substr(len + 1);

};
const getFromGlobal = (jpex, name) => {

@@ -192,5 +167,3 @@ if (!jpex.$$config.globals) {

}
const value = getGlobalProperty(name);
if (value !== void 0) {

@@ -201,12 +174,4 @@ jpex.constant(name, value);

};
const validateArgs$1 = name => {
if (!isString(name)) {
throw new Error(`Name must be a string, but recevied ${typeof name}`);
}
};
const getFromAlias = (jpex, alias) => {
const name = jpex.$$alias[alias];
if (name != null) {

@@ -216,20 +181,14 @@ return jpex.$$factories[name];

};
const getFromResolved = (jpex, name) => {
return jpex.$$resolved[name];
};
const getFromRegistry = (jpex, name) => {
return jpex.$$factories[name];
};
const getFactory = (jpex, name, opts = {}) => {
var _opts$optional;
validateArgs$1(name);
validateName(name);
const fns = [getFromResolved, getFromRegistry, getFromAlias, getFromGlobal, getFromNodeModules];
while (fns.length) {
const factory = fns.shift()(jpex, name);
if (factory != null) {

@@ -239,10 +198,8 @@ return factory;

}
if ((_opts$optional = opts.optional) != null ? _opts$optional : jpex.$$config.optional) {
return;
}
throw new Error(`Unable to find required dependency [${name}]`);
};
const cacheResult = (jpex, name, factory, value, namedParameters) => {
const cacheResult = (jpex, name, factory, value, namedParameters, withArg) => {
switch (factory.lifecycle) {

@@ -252,41 +209,29 @@ case 'application':

factory.value = value;
factory.with = withArg;
break;
case 'class':
jpex.$$resolved[name] = {
jpex.$$resolved[name] = { ...factory,
resolved: true,
value
value,
with: withArg
};
break;
case 'none':
break;
case 'instance':
default:
// instance
namedParameters[name] = value;
break;
}
}; // Ensure we're not stuck in a recursive loop
};
const checkStack = (jpex, name, stack) => {
if (!hasLength(stack)) {
// This is the first loop
return false;
}
if (!stack.includes(name)) {
// We've definitely not tried to resolve this one before
return false;
}
if (stack[stack.length - 1] === name) {
var _jpex$$$parent;
// We've tried to resolve this one before, but...
// if this factory has overridden a parent factory
// we should assume it actually wants to resolve the parent
const parent = (_jpex$$$parent = jpex.$$parent) == null ? void 0 : _jpex$$$parent.$$factories[name];
if (parent != null) {

@@ -296,3 +241,2 @@ return true;

}
throw new Error(`Recursive loop for dependency ${name} encountered`);

@@ -305,3 +249,2 @@ };

}
if (opts.with) {

@@ -311,67 +254,47 @@ return { ...opts.with

}
return {};
};
const isResolvedWithParams = (factory, opts = {}) => {
if (!factory.with && !opts.with) {
return true;
}
const keys = [...new Set([...Object.keys((opts == null ? void 0 : opts.with) || {}), ...Object.keys(factory.with || {})])];
return keys.every(key => {
var _opts$with;
return (opts == null ? void 0 : (_opts$with = opts.with) == null ? void 0 : _opts$with[key]) === factory.with[key];
});
};
const resolveFactory = (jpex, name, factory, namedParameters, opts, stack) => {
if (factory == null) {
return;
} // Check if it's already been resolved
if (factory.resolved) {
}
if (factory.resolved && isResolvedWithParams(factory, opts)) {
return factory.value;
} // Work out dependencies
}
let args = [];
if (hasLength(factory.dependencies)) {
// eslint-disable-next-line no-use-before-define
args = resolveMany(jpex, factory, namedParameters, opts, [...stack, name]);
} // Invoke the factory
const value = factory.fn.apply(jpex, args); // Cache the result
cacheResult(jpex, name, factory, value, namedParameters);
}
const value = factory.fn.apply(jpex, args);
cacheResult(jpex, name, factory, value, namedParameters, opts == null ? void 0 : opts.with);
return value;
};
const resolveOne = (jpex, name, initialParameters, opts, stack) => {
const namedParameters = getNamedParameters(initialParameters, opts); // Check named parameters
// if we have a named parameter for this dependency
// we don't need to do any resolution, we can just return the value
const namedParameters = getNamedParameters(initialParameters, opts);
if (Object.hasOwnProperty.call(namedParameters, name)) {
return namedParameters[name];
} // Special keys
}
if (name === NAMED_PARAMS || name === "type:jpex/NamedParameters") {
return namedParameters;
}
if (checkStack(jpex, name, stack)) {
// Yes we have tried to resolve this one before, but we could
// actually just be resolving an inherited factory
return resolveOne(jpex.$$parent, name, namedParameters, opts, []);
} // Get the factory
// This will either return the factory,
// return null (meaning it's an optional dependency)
// or throw an error
}
const factory = getFactory(jpex, name, opts);
return resolveFactory(jpex, name, factory, namedParameters, opts, stack);
};
const resolveMany = (jpex, definition, namedParameters, opts, stack) => {
const resolveMany = (jpex, definition, namedParameters, opts, stack = []) => {
if (!hasLength(definition.dependencies)) {
return [];
}
if (!stack) {
stack = [];
}
const dependencies = ensureArray(definition.dependencies);

@@ -392,11 +315,8 @@ const values = dependencies.map(dependency => {

var _this$$$factories$dep;
if (!isString(dependency)) {
return false;
}
if (this.$$resolved[dependency] != null) {
return true;
}
return ((_this$$$factories$dep = this.$$factories[dependency]) == null ? void 0 : _this$$$factories$dep.resolved) === true;

@@ -411,9 +331,6 @@ }

let result;
const encased = function (...args) {
/* eslint-disable no-invalid-this */
const encased = function encased(...args) {
if (result && allResolved.call(jpex, dependencies)) {
return result.apply(this, args);
}
const deps = resolveDependencies.call(jpex, {

@@ -424,5 +341,3 @@ dependencies

return result.apply(this, args);
/* eslint-enable */
};
encased.encased = fn;

@@ -434,3 +349,2 @@ return encased;

names = ensureArray(names);
for (const key in this.$$factories) {

@@ -441,3 +355,2 @@ if (!hasLength(names) || names.includes(key)) {

}
for (const key in this.$$resolved) {

@@ -477,7 +390,5 @@ if (!hasLength(names) || names.includes(key)) {

clearCache,
extend(config) {
return makeJpex(config, this);
},
resolveWith(name, namedParameters, opts) {

@@ -489,7 +400,5 @@ return this.resolve(name, {

},
raw(name) {
return getFactory(this, name, {}).fn;
},
infer: () => ''

@@ -496,0 +405,0 @@ };

@@ -1,30 +0,39 @@

function constant(name, obj) {
return this.factory(name, [], () => obj, {
lifecycle: 'application'
});
}
const isString = obj => typeof obj === 'string';
const isFunction = obj => typeof obj === 'function';
const validateName = name => {
if (!isString(name)) {
throw new Error(`Name must be a string, but recevied ${typeof name}`);
}
};
const validateDependencies = dependencies => {
if (!Array.isArray(dependencies)) {
throw new Error(`Expected an array of dependencies, but was called with [${typeof dependencies}]`);
}
};
const validateFactory = (name, fn) => {
if (!isFunction(fn)) {
throw new Error(`Factory ${name} must be a [Function]`);
}
};
const validateArgs = (name, dependencies, fn) => {
validateName(name);
validateDependencies(dependencies);
validateFactory(name, fn);
};
const isPassive = (name, jpex, precedence) => {
return (precedence || jpex.$$config.precedence) === 'passive' && jpex.$$factories[name] != null;
};
const instantiate = (context, args) => {
// eslint-disable-next-line new-parens
return new (Function.prototype.bind.apply(context, args))();
};
const isNode = () => {
let _process; // eslint-disable-line no-underscore-dangle
let _process;
try {
// eslint-disable-next-line no-new-func
_process = new Function('return process')();
} catch (e) {// No process
} // eslint-disable-next-line max-len
} catch (e) {
}
return typeof _process === 'object' && _process.toString && _process.toString() === '[object process]';
}; // eslint-disable-next-line no-new-func
};
const doUnsafeRequire = new Function('require', 'target', 'return require.main.require(target)');
const unsafeRequire = target => {
// eslint-disable-next-line no-eval
return doUnsafeRequire(eval('require'), target);

@@ -36,7 +45,5 @@ };

}
if (Array.isArray(arr)) {
return arr;
}
return [arr];

@@ -46,28 +53,24 @@ };

const validateArgs = (name, dependencies, fn) => {
if (!isString(name)) {
throw new Error(`Factories must be given a name, but was called with [${typeof name}]`);
function constant(name, obj) {
validateName(name);
if (isPassive(name, this)) {
return;
}
this.$$factories[name] = {
fn: () => obj,
lifecycle: 'application',
value: obj,
resolved: true
};
}
if (!Array.isArray(dependencies)) {
throw new Error(`Expected an array of dependencies, but was called with [${typeof dependencies}]`);
}
if (!isFunction(fn)) {
throw new Error(`Factory ${name} must be a [Function]`);
}
};
function factory(name, dependencies, fn, opts = {}) {
validateArgs(name, dependencies, fn);
if (!hasLength(dependencies)) {
dependencies = null;
} // eslint-disable-next-line max-len
if ((opts.precedence || this.$$config.precedence) === 'passive' && this.$$factories[name] != null) {
}
if (isPassive(name, this, opts.precedence)) {
return;
}
const f = {
this.$$factories[name] = {
fn,

@@ -77,4 +80,2 @@ dependencies,

};
this.$$factories[name] = f;
if (opts.alias) {

@@ -87,6 +88,4 @@ ensureArray(opts.alias).forEach(alias => this.alias(alias, name));

validateArgs(name, dependencies, fn);
function factory(...args) {
const context = {};
if (opts.bindToInstance) {

@@ -97,6 +96,4 @@ dependencies.forEach((key, i) => {

}
return instantiate(fn, [context, ...args]);
}
return this.factory(name, dependencies, factory, opts);

@@ -109,3 +106,2 @@ }

}
if (this.$$alias[name] == null || this.$$config.precedence === 'active') {

@@ -121,9 +117,5 @@ this.$$alias[name] = alias;

const getFromNodeModules = (jpex, target) => {
// in order to stop webpack environments from including every possible
// import source in the bundle, we have to stick all node require stuff
// inside an eval setup
if (!jpex.$$config.nodeModules || !isNode()) {
return;
}
try {

@@ -135,42 +127,26 @@ const value = unsafeRequire(target);

var _e$message;
if ((_e$message = e.message) != null && _e$message.includes != null && _e$message.includes(`Cannot find module '${target}'`)) {
// not found in node modules, just continue
return;
}
throw e;
}
};
const getGlobalObject = () => {
if (typeof global !== VOID) {
// eslint-disable-next-line no-undef
return global;
}
if (typeof globalThis !== VOID) {
// eslint-disable-next-line no-undef
return globalThis;
}
if (typeof window !== VOID) {
return window;
}
return {};
};
const getGlobalProperty = name => {
const global = getGlobalObject();
if (global[name] !== void 0) {
return global[name];
} // we need to handle inferred types as well
// this gets a little bit hacky...
}
if (name.startsWith(GLOBAL_TYPE_PREFIX)) {
// most global types will just be the name of the property in pascal case
// i.e. window = Window / document = Document
const len = GLOBAL_TYPE_PREFIX.length;

@@ -181,3 +157,2 @@ const inferredName = name.charAt(len).toLowerCase() + name.substr(len + 1);

};
const getFromGlobal = (jpex, name) => {

@@ -187,5 +162,3 @@ if (!jpex.$$config.globals) {

}
const value = getGlobalProperty(name);
if (value !== void 0) {

@@ -196,12 +169,4 @@ jpex.constant(name, value);

};
const validateArgs$1 = name => {
if (!isString(name)) {
throw new Error(`Name must be a string, but recevied ${typeof name}`);
}
};
const getFromAlias = (jpex, alias) => {
const name = jpex.$$alias[alias];
if (name != null) {

@@ -211,20 +176,14 @@ return jpex.$$factories[name];

};
const getFromResolved = (jpex, name) => {
return jpex.$$resolved[name];
};
const getFromRegistry = (jpex, name) => {
return jpex.$$factories[name];
};
const getFactory = (jpex, name, opts = {}) => {
var _opts$optional;
validateArgs$1(name);
validateName(name);
const fns = [getFromResolved, getFromRegistry, getFromAlias, getFromGlobal, getFromNodeModules];
while (fns.length) {
const factory = fns.shift()(jpex, name);
if (factory != null) {

@@ -234,10 +193,8 @@ return factory;

}
if ((_opts$optional = opts.optional) != null ? _opts$optional : jpex.$$config.optional) {
return;
}
throw new Error(`Unable to find required dependency [${name}]`);
};
const cacheResult = (jpex, name, factory, value, namedParameters) => {
const cacheResult = (jpex, name, factory, value, namedParameters, withArg) => {
switch (factory.lifecycle) {

@@ -247,41 +204,29 @@ case 'application':

factory.value = value;
factory.with = withArg;
break;
case 'class':
jpex.$$resolved[name] = {
jpex.$$resolved[name] = { ...factory,
resolved: true,
value
value,
with: withArg
};
break;
case 'none':
break;
case 'instance':
default:
// instance
namedParameters[name] = value;
break;
}
}; // Ensure we're not stuck in a recursive loop
};
const checkStack = (jpex, name, stack) => {
if (!hasLength(stack)) {
// This is the first loop
return false;
}
if (!stack.includes(name)) {
// We've definitely not tried to resolve this one before
return false;
}
if (stack[stack.length - 1] === name) {
var _jpex$$$parent;
// We've tried to resolve this one before, but...
// if this factory has overridden a parent factory
// we should assume it actually wants to resolve the parent
const parent = (_jpex$$$parent = jpex.$$parent) == null ? void 0 : _jpex$$$parent.$$factories[name];
if (parent != null) {

@@ -291,3 +236,2 @@ return true;

}
throw new Error(`Recursive loop for dependency ${name} encountered`);

@@ -300,3 +244,2 @@ };

}
if (opts.with) {

@@ -306,67 +249,47 @@ return { ...opts.with

}
return {};
};
const isResolvedWithParams = (factory, opts = {}) => {
if (!factory.with && !opts.with) {
return true;
}
const keys = [...new Set([...Object.keys((opts == null ? void 0 : opts.with) || {}), ...Object.keys(factory.with || {})])];
return keys.every(key => {
var _opts$with;
return (opts == null ? void 0 : (_opts$with = opts.with) == null ? void 0 : _opts$with[key]) === factory.with[key];
});
};
const resolveFactory = (jpex, name, factory, namedParameters, opts, stack) => {
if (factory == null) {
return;
} // Check if it's already been resolved
if (factory.resolved) {
}
if (factory.resolved && isResolvedWithParams(factory, opts)) {
return factory.value;
} // Work out dependencies
}
let args = [];
if (hasLength(factory.dependencies)) {
// eslint-disable-next-line no-use-before-define
args = resolveMany(jpex, factory, namedParameters, opts, [...stack, name]);
} // Invoke the factory
const value = factory.fn.apply(jpex, args); // Cache the result
cacheResult(jpex, name, factory, value, namedParameters);
}
const value = factory.fn.apply(jpex, args);
cacheResult(jpex, name, factory, value, namedParameters, opts == null ? void 0 : opts.with);
return value;
};
const resolveOne = (jpex, name, initialParameters, opts, stack) => {
const namedParameters = getNamedParameters(initialParameters, opts); // Check named parameters
// if we have a named parameter for this dependency
// we don't need to do any resolution, we can just return the value
const namedParameters = getNamedParameters(initialParameters, opts);
if (Object.hasOwnProperty.call(namedParameters, name)) {
return namedParameters[name];
} // Special keys
}
if (name === NAMED_PARAMS || name === "type:jpex/NamedParameters") {
return namedParameters;
}
if (checkStack(jpex, name, stack)) {
// Yes we have tried to resolve this one before, but we could
// actually just be resolving an inherited factory
return resolveOne(jpex.$$parent, name, namedParameters, opts, []);
} // Get the factory
// This will either return the factory,
// return null (meaning it's an optional dependency)
// or throw an error
}
const factory = getFactory(jpex, name, opts);
return resolveFactory(jpex, name, factory, namedParameters, opts, stack);
};
const resolveMany = (jpex, definition, namedParameters, opts, stack) => {
const resolveMany = (jpex, definition, namedParameters, opts, stack = []) => {
if (!hasLength(definition.dependencies)) {
return [];
}
if (!stack) {
stack = [];
}
const dependencies = ensureArray(definition.dependencies);

@@ -387,11 +310,8 @@ const values = dependencies.map(dependency => {

var _this$$$factories$dep;
if (!isString(dependency)) {
return false;
}
if (this.$$resolved[dependency] != null) {
return true;
}
return ((_this$$$factories$dep = this.$$factories[dependency]) == null ? void 0 : _this$$$factories$dep.resolved) === true;

@@ -406,9 +326,6 @@ }

let result;
const encased = function (...args) {
/* eslint-disable no-invalid-this */
const encased = function encased(...args) {
if (result && allResolved.call(jpex, dependencies)) {
return result.apply(this, args);
}
const deps = resolveDependencies.call(jpex, {

@@ -419,5 +336,3 @@ dependencies

return result.apply(this, args);
/* eslint-enable */
};
encased.encased = fn;

@@ -429,3 +344,2 @@ return encased;

names = ensureArray(names);
for (const key in this.$$factories) {

@@ -436,3 +350,2 @@ if (!hasLength(names) || names.includes(key)) {

}
for (const key in this.$$resolved) {

@@ -472,7 +385,5 @@ if (!hasLength(names) || names.includes(key)) {

clearCache,
extend(config) {
return makeJpex(config, this);
},
resolveWith(name, namedParameters, opts) {

@@ -484,7 +395,5 @@ return this.resolve(name, {

},
raw(name) {
return getFactory(this, name, {}).fn;
},
infer: () => ''

@@ -491,0 +400,0 @@ };

@@ -38,10 +38,2 @@ 'use strict';

function constant(name, obj) {
return this.factory(name, [], function () {
return obj;
}, {
lifecycle: 'application'
});
}
var isString = function isString(obj) {

@@ -53,23 +45,38 @@ return typeof obj === 'string';

};
var validateName = function validateName(name) {
if (!isString(name)) {
throw new Error("Name must be a string, but recevied " + typeof name);
}
};
var validateDependencies = function validateDependencies(dependencies) {
if (!Array.isArray(dependencies)) {
throw new Error("Expected an array of dependencies, but was called with [" + typeof dependencies + "]");
}
};
var validateFactory = function validateFactory(name, fn) {
if (!isFunction(fn)) {
throw new Error("Factory " + name + " must be a [Function]");
}
};
var validateArgs = function validateArgs(name, dependencies, fn) {
validateName(name);
validateDependencies(dependencies);
validateFactory(name, fn);
};
var isPassive = function isPassive(name, jpex, precedence) {
return (precedence || jpex.$$config.precedence) === 'passive' && jpex.$$factories[name] != null;
};
var instantiate = function instantiate(context, args) {
// eslint-disable-next-line new-parens
return new (Function.prototype.bind.apply(context, args))();
};
var isNode = function isNode() {
var _process; // eslint-disable-line no-underscore-dangle
var _process;
try {
// eslint-disable-next-line no-new-func
_process = new Function('return process')();
} catch (e) {// No process
} // eslint-disable-next-line max-len
} catch (e) {
}
return typeof _process === 'object' && _process.toString && _process.toString() === '[object process]';
}; // eslint-disable-next-line no-new-func
};
var doUnsafeRequire = new Function('require', 'target', 'return require.main.require(target)');
var unsafeRequire = function unsafeRequire(target) {
// eslint-disable-next-line no-eval
return doUnsafeRequire(eval('require'), target);

@@ -81,7 +88,5 @@ };

}
if (Array.isArray(arr)) {
return arr;
}
return [arr];

@@ -93,34 +98,30 @@ };

var validateArgs = function validateArgs(name, dependencies, fn) {
if (!isString(name)) {
throw new Error("Factories must be given a name, but was called with [" + typeof name + "]");
function constant(name, obj) {
validateName(name);
if (isPassive(name, this)) {
return;
}
this.$$factories[name] = {
fn: function fn() {
return obj;
},
lifecycle: 'application',
value: obj,
resolved: true
};
}
if (!Array.isArray(dependencies)) {
throw new Error("Expected an array of dependencies, but was called with [" + typeof dependencies + "]");
}
if (!isFunction(fn)) {
throw new Error("Factory " + name + " must be a [Function]");
}
};
function factory(name, dependencies, fn, opts) {
var _this = this;
if (opts === void 0) {
opts = {};
}
validateArgs(name, dependencies, fn);
if (!hasLength(dependencies)) {
dependencies = null;
} // eslint-disable-next-line max-len
if ((opts.precedence || this.$$config.precedence) === 'passive' && this.$$factories[name] != null) {
}
if (isPassive(name, this, opts.precedence)) {
return;
}
var f = {
this.$$factories[name] = {
fn: fn,

@@ -130,4 +131,2 @@ dependencies: dependencies,

};
this.$$factories[name] = f;
if (opts.alias) {

@@ -144,5 +143,3 @@ ensureArray(opts.alias).forEach(function (alias) {

}
validateArgs(name, dependencies, fn);
function factory() {

@@ -152,5 +149,3 @@ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {

}
var context = {};
if (opts.bindToInstance) {

@@ -161,6 +156,4 @@ dependencies.forEach(function (key, i) {

}
return instantiate(fn, [context].concat(args));
}
return this.factory(name, dependencies, factory, opts);

@@ -173,3 +166,2 @@ }

}
if (this.$$alias[name] == null || this.$$config.precedence === 'active') {

@@ -185,9 +177,5 @@ this.$$alias[name] = alias;

var getFromNodeModules = function getFromNodeModules(jpex, target) {
// in order to stop webpack environments from including every possible
// import source in the bundle, we have to stick all node require stuff
// inside an eval setup
if (!jpex.$$config.nodeModules || !isNode()) {
return;
}
try {

@@ -199,42 +187,26 @@ var value = unsafeRequire(target);

var _e$message;
if ((_e$message = e.message) != null && _e$message.includes != null && _e$message.includes("Cannot find module '" + target + "'")) {
// not found in node modules, just continue
return;
}
throw e;
}
};
var getGlobalObject = function getGlobalObject() {
if (typeof global !== VOID) {
// eslint-disable-next-line no-undef
return global;
}
if (typeof globalThis !== VOID) {
// eslint-disable-next-line no-undef
return globalThis;
}
if (typeof window !== VOID) {
return window;
}
return {};
};
var getGlobalProperty = function getGlobalProperty(name) {
var global = getGlobalObject();
if (global[name] !== void 0) {
return global[name];
} // we need to handle inferred types as well
// this gets a little bit hacky...
}
if (name.startsWith(GLOBAL_TYPE_PREFIX)) {
// most global types will just be the name of the property in pascal case
// i.e. window = Window / document = Document
var len = GLOBAL_TYPE_PREFIX.length;

@@ -245,3 +217,2 @@ var inferredName = name.charAt(len).toLowerCase() + name.substr(len + 1);

};
var getFromGlobal = function getFromGlobal(jpex, name) {

@@ -251,5 +222,3 @@ if (!jpex.$$config.globals) {

}
var value = getGlobalProperty(name);
if (value !== void 0) {

@@ -260,12 +229,4 @@ jpex.constant(name, value);

};
var validateArgs$1 = function validateArgs(name) {
if (!isString(name)) {
throw new Error("Name must be a string, but recevied " + typeof name);
}
};
var getFromAlias = function getFromAlias(jpex, alias) {
var name = jpex.$$alias[alias];
if (name != null) {

@@ -275,24 +236,17 @@ return jpex.$$factories[name];

};
var getFromResolved = function getFromResolved(jpex, name) {
return jpex.$$resolved[name];
};
var getFromRegistry = function getFromRegistry(jpex, name) {
return jpex.$$factories[name];
};
var getFactory = function getFactory(jpex, name, opts) {
var _opts$optional;
if (opts === void 0) {
opts = {};
}
validateArgs$1(name);
validateName(name);
var fns = [getFromResolved, getFromRegistry, getFromAlias, getFromGlobal, getFromNodeModules];
while (fns.length) {
var factory = fns.shift()(jpex, name);
if (factory != null) {

@@ -302,10 +256,8 @@ return factory;

}
if ((_opts$optional = opts.optional) != null ? _opts$optional : jpex.$$config.optional) {
return;
}
throw new Error("Unable to find required dependency [" + name + "]");
};
var cacheResult = function cacheResult(jpex, name, factory, value, namedParameters) {
var cacheResult = function cacheResult(jpex, name, factory, value, namedParameters, withArg) {
switch (factory.lifecycle) {

@@ -315,41 +267,29 @@ case 'application':

factory.value = value;
factory.with = withArg;
break;
case 'class':
jpex.$$resolved[name] = {
jpex.$$resolved[name] = _extends({}, factory, {
resolved: true,
value: value
};
value: value,
with: withArg
});
break;
case 'none':
break;
case 'instance':
default:
// instance
namedParameters[name] = value;
break;
}
}; // Ensure we're not stuck in a recursive loop
};
var checkStack = function checkStack(jpex, name, stack) {
if (!hasLength(stack)) {
// This is the first loop
return false;
}
if (!stack.includes(name)) {
// We've definitely not tried to resolve this one before
return false;
}
if (stack[stack.length - 1] === name) {
var _jpex$$$parent;
// We've tried to resolve this one before, but...
// if this factory has overridden a parent factory
// we should assume it actually wants to resolve the parent
var parent = (_jpex$$$parent = jpex.$$parent) == null ? void 0 : _jpex$$$parent.$$factories[name];
if (parent != null) {

@@ -359,3 +299,2 @@ return true;

}
throw new Error("Recursive loop for dependency " + name + " encountered");

@@ -368,63 +307,50 @@ };

}
if (namedParameters) {
return namedParameters;
}
if (opts.with) {
return _extends({}, opts.with);
}
return {};
};
var isResolvedWithParams = function isResolvedWithParams(factory, opts) {
var _opts;
if (opts === void 0) {
opts = {};
}
if (!factory.with && !opts.with) {
return true;
}
var keys = [].concat(new Set([].concat(Object.keys(((_opts = opts) == null ? void 0 : _opts.with) || {}), Object.keys(factory.with || {}))));
return keys.every(function (key) {
var _opts2, _opts2$with;
return ((_opts2 = opts) == null ? void 0 : (_opts2$with = _opts2.with) == null ? void 0 : _opts2$with[key]) === factory.with[key];
});
};
var resolveFactory = function resolveFactory(jpex, name, factory, namedParameters, opts, stack) {
if (factory == null) {
return;
} // Check if it's already been resolved
if (factory.resolved) {
}
if (factory.resolved && isResolvedWithParams(factory, opts)) {
return factory.value;
} // Work out dependencies
}
var args = [];
if (hasLength(factory.dependencies)) {
// eslint-disable-next-line no-use-before-define
args = resolveMany(jpex, factory, namedParameters, opts, [].concat(stack, [name]));
} // Invoke the factory
var value = factory.fn.apply(jpex, args); // Cache the result
cacheResult(jpex, name, factory, value, namedParameters);
}
var value = factory.fn.apply(jpex, args);
cacheResult(jpex, name, factory, value, namedParameters, opts == null ? void 0 : opts.with);
return value;
};
var resolveOne = function resolveOne(jpex, name, initialParameters, opts, stack) {
var namedParameters = getNamedParameters(initialParameters, opts); // Check named parameters
// if we have a named parameter for this dependency
// we don't need to do any resolution, we can just return the value
var namedParameters = getNamedParameters(initialParameters, opts);
if (Object.hasOwnProperty.call(namedParameters, name)) {
return namedParameters[name];
} // Special keys
}
if (name === NAMED_PARAMS || name === "type:jpex/NamedParameters") {
return namedParameters;
}
if (checkStack(jpex, name, stack)) {
// Yes we have tried to resolve this one before, but we could
// actually just be resolving an inherited factory
return resolveOne(jpex.$$parent, name, namedParameters, opts, []);
} // Get the factory
// This will either return the factory,
// return null (meaning it's an optional dependency)
// or throw an error
}
var factory = getFactory(jpex, name, opts);

@@ -434,10 +360,8 @@ return resolveFactory(jpex, name, factory, namedParameters, opts, stack);

var resolveMany = function resolveMany(jpex, definition, namedParameters, opts, stack) {
if (stack === void 0) {
stack = [];
}
if (!hasLength(definition.dependencies)) {
return [];
}
if (!stack) {
stack = [];
}
var dependencies = ensureArray(definition.dependencies);

@@ -458,11 +382,8 @@ var values = dependencies.map(function (dependency) {

var _this$$$factories$dep;
if (!isString(dependency)) {
return false;
}
if (this.$$resolved[dependency] != null) {
return true;
}
return ((_this$$$factories$dep = this.$$factories[dependency]) == null ? void 0 : _this$$$factories$dep.resolved) === true;

@@ -477,3 +398,2 @@ }

var result;
var encased = function encased() {

@@ -483,8 +403,5 @@ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {

}
/* eslint-disable no-invalid-this */
if (result && allResolved.call(jpex, dependencies)) {
return result.apply(this, args);
}
var deps = resolveDependencies.call(jpex, {

@@ -495,5 +412,3 @@ dependencies: dependencies

return result.apply(this, args);
/* eslint-enable */
};
encased.encased = fn;

@@ -507,5 +422,3 @@ return encased;

}
names = ensureArray(names);
for (var key in this.$$factories) {

@@ -516,3 +429,2 @@ if (!hasLength(names) || names.includes(key)) {

}
for (var _key2 in this.$$resolved) {

@@ -537,3 +449,2 @@ if (!hasLength(names) || names.includes(_key2)) {

config = _objectWithoutPropertiesLoose(_ref, ["inherit"]);
var jpex = {

@@ -540,0 +451,0 @@ $$parent: parent,

import type { JpexInstance, SetupConfig, NamedParameters, Lifecycle, Precedence, FactoryOpts, ResolveOpts, ServiceOpts, NodeModule, Global } from './types';
declare const jpex: JpexInstance;
export { jpex, };
export { jpex };
export type { Lifecycle, JpexInstance, JpexInstance as Jpex, SetupConfig, NamedParameters, Precedence, FactoryOpts, ServiceOpts, ResolveOpts, NodeModule, Global, };
export default jpex;
import { JpexInstance, Dependency, AnyFunction, FactoryOpts } from '../types';
export declare const validateArgs: (name: string, dependencies: Dependency[], fn: AnyFunction) => void;
export default function factory<T>(this: JpexInstance, name: string, dependencies: Dependency[], fn: AnyFunction<T>, opts?: FactoryOpts): void;
import { JpexInstance, Dependency, ServiceOpts } from '../types';
declare function service(this: JpexInstance, name: string, dependencies: Dependency[], fn: any, opts?: ServiceOpts): void;
export default service;
export default function service(this: JpexInstance, name: string, dependencies: Dependency[], fn: any, opts?: ServiceOpts): void;
import { JpexInstance, Dependency, Definition, NamedParameters, ResolveOpts } from '../types';
export declare const resolveOne: <R extends unknown>(jpex: JpexInstance, name: Dependency, initialParameters: NamedParameters, opts: ResolveOpts, stack: string[]) => R;
export declare const resolveMany: <R extends any[]>(jpex: JpexInstance, definition: Definition, namedParameters: NamedParameters, opts: ResolveOpts, stack: string[]) => R;
export declare const resolveMany: <R extends any[]>(jpex: JpexInstance, definition: Definition, namedParameters: NamedParameters, opts: ResolveOpts, stack?: string[]) => R;
import { Factory, JpexInstance, ResolveOpts, NamedParameters, Dependency } from '../types';
export declare const getFactory: (jpex: JpexInstance, name: string, opts?: ResolveOpts) => Factory;
export declare const cacheResult: (jpex: JpexInstance, name: string, factory: Factory, value: any, namedParameters: NamedParameters) => void;
export declare const getFactory: (jpex: JpexInstance, name: string, opts?: ResolveOpts) => import("../types/base").Factory;
export declare const cacheResult: (jpex: JpexInstance, name: string, factory: Factory, value: any, namedParameters: NamedParameters, withArg: Record<string, any>) => void;
export declare const checkStack: (jpex: JpexInstance, name: Dependency, stack: string[]) => boolean;

@@ -0,1 +1,2 @@

export * from './base';
export * from './JpexInstance';

@@ -19,2 +20,3 @@ export * from './BuiltIns';

value?: any;
with?: Record<string, any>;
}

@@ -1,2 +0,3 @@

import { Lifecycle, AnyFunction, Dependency, AnyConstructor, Factory, Precedence, NamedParameters } from './';
import type { Lifecycle, AnyFunction, Dependency, AnyConstructor, Factory, Precedence } from './base';
import { NamedParameters } from './BuiltIns';
export interface SetupConfig {

@@ -3,0 +4,0 @@ inherit?: boolean;

@@ -0,3 +1,9 @@

import { Dependency, JpexInstance, Precedence } from '../types';
export declare const isString: (obj: any) => obj is string;
export declare const isFunction: (obj: any) => obj is Function;
export declare const isFunction: (obj: any) => obj is (...args: any[]) => any;
export declare const validateName: (name: string) => void;
export declare const validateDependencies: (dependencies: Dependency[]) => void;
export declare const validateFactory: (name: string, fn: (...args: any[]) => any) => void;
export declare const validateArgs: (name: string, dependencies: Dependency[], fn: (...args: any[]) => any) => void;
export declare const isPassive: (name: string, jpex: JpexInstance, precedence?: Precedence) => boolean;
export declare const instantiate: (context: any, args: any[]) => any;

@@ -4,0 +10,0 @@ export declare const isNode: () => boolean;

{
"name": "jpex",
"version": "4.3.0",
"version": "4.3.1",
"description": "Javascript Prototype Extension",

@@ -10,9 +10,8 @@ "main": "dist/cjs/jpex.js",

"clear-cache": "rm -rf node_modules/.cache",
"test": "ava",
"test:debug": "ava debug",
"coverage": "nyc ava",
"test": "jest",
"coverage": "jest --coverage",
"lint": "eslint './src/**/*.ts' --fix && tsc --noEmit",
"build:prepare": "rm -rf dist",
"build:js": "rollup --config ./rollup.config.js",
"build:ts": "tsc -d --outDir dist/ts --emitDeclarationOnly ./src/index.ts",
"build:ts": "tsc -d --outDir dist/ts --emitDeclarationOnly --downlevelIteration ./src/index.ts",
"build:post": "node ./postbuild-checks.js",

@@ -22,17 +21,10 @@ "build": "yarn build:prepare && yarn build:js && yarn build:ts && yarn build:post",

"semantic-release": "semantic-release",
"ci": "yarn lint && yarn test && yarn build"
"ci": "yarn lint && yarn test && yarn build",
"prepare": "husky install"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint --edit"
}
},
"lint-staged": {
"linters": {
"src/**/*.{js,ts}": [
"eslint",
"git add"
]
}
"src/**/*.{js,ts}": [
"eslint",
"prettier --write --ignore-unknown"
]
},

@@ -50,34 +42,25 @@ "repository": {

"devDependencies": {
"@ava/babel": "^1.0.1",
"@babel/cli": "^7.8.4",
"@babel/core": "^7.7.7",
"@babel/plugin-external-helpers": "^7.8.3",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-class-properties": "^7.8.3",
"@babel/plugin-syntax-typescript": "^7.8.3",
"@babel/preset-env": "^7.7.7",
"@babel/preset-typescript": "^7.8.3",
"@babel/register": "^7.7.7",
"@commitlint/cli": "^8.3.4",
"@commitlint/config-conventional": "^8.3.4",
"@types/babel__core": "^7.1.9",
"@types/mocha": "^8.0.0",
"@types/jest": "^26.0.20",
"@types/node": "^14.0.26",
"@types/sinon": "^9.0.4",
"@typescript-eslint/eslint-plugin": "^4.2.0",
"@typescript-eslint/parser": "^4.2.0",
"ava": "^3.0.0",
"browser-env": "^3.3.0",
"eslint": "^7.5.0",
"eslint-config-airbnb-typescript-prettier": "^4.1.0",
"eslint-plugin-import": "^2.22.1",
"husky": "^4.0.3",
"lint-staged": "^8.1.5",
"nyc": "^15.1.0",
"eslint-plugin-jest": "^24.1.5",
"husky": "^5.1.3",
"jest": "^26.6.3",
"lint-staged": "^10.5.4",
"prettier": "^2.2.1",
"rollup": "^2.23.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-node-resolve": "^5.2.0",
"semantic-release": "^17.1.1",
"sinon": "^9.0.2",
"typescript": "^4.0.3"

@@ -84,0 +67,0 @@ },

@@ -0,6 +1,4 @@

# ![Jpex](https://jpex-js.github.io/dist/jpex.svg)
![Jpex](https://jpex-js.github.io/dist/jpex.svg)
===========
Easy Dependency Injection
--------------------------
## Easy Dependency Injection

@@ -15,2 +13,3 @@ [![Build Status](https://travis-ci.org/jpex-js/jpex.svg?branch=master)](https://travis-ci.org/jackmellis/jpex)

## Contents
- [Getting Started](#getting-started)

@@ -20,27 +19,27 @@ - [Registering Dependencies](#registering-dependencies)

- [API](#api)
+ [jpex](#jpex)
- [jpex](#jpex)
- [constant](#jpexconstant)
- [factory](#jpexfactory)
* [lifecycle](#lifecycle)
* [precedence](#precedence)
* [bindToInstance](#bindtoinstance)
* [alias](#alias)
- [lifecycle](#lifecycle)
- [precedence](#precedence)
- [bindToInstance](#bindtoinstance)
- [alias](#alias)
- [service](#jpexservice)
- [alias](#jpexalias)
- [resolve](#jpexresolve)
* [optional](#optional)
* [with](#with)
- [optional](#optional)
- [with](#with)
- [resolveWith](#jpexresolvewith)
- [encase](#jpexencase)
- [extend](#jpexextend)
* [inherit](#inherit)
* [lifecycle](#lifecycle-1)
* [precedence](#precedence-1)
* [optional](#optional-1)
* [nodeModules](#nodemodules)
* [globals](#globals)
- [inherit](#inherit)
- [lifecycle](#lifecycle-1)
- [precedence](#precedence-1)
- [optional](#optional-1)
- [nodeModules](#nodemodules)
- [globals](#globals)
- [raw](#jpexraw)
- [clearCache](#jpexclearcache)
- [infer](#jpexinfer)
+ [Types](#types)
- [Types](#types)
- [Jpex](#jpex)

@@ -56,2 +55,3 @@ - [NodeModule](#nodemodule)

### Install
```

@@ -62,2 +62,3 @@ npm install jpex

### Plugin
Jpex uses babel to infer type interfaces at build time. You can do this with one of several methods:

@@ -69,2 +70,3 @@ [@jpex-js/babel-plugin](https://github.com/jpex-js/babel-plugin)

Jpex comes bundled with the `@jpex-js/babel-plugin` so you can easily get started with a `.babelrc` like this:
```js

@@ -79,2 +81,3 @@ // .bablerc

### Usage
```ts

@@ -89,8 +92,10 @@ import jpex from 'jpex';

------
---
## Registering Dependencies
Services and factories are small modules or functions that provide a common piece of functionality.
### factories
```ts

@@ -105,2 +110,3 @@ type MyFactory = {};

### services
```ts

@@ -117,2 +123,3 @@ class MyService = {

### constants
```ts

@@ -123,7 +130,10 @@ type MyConstant = string;

------
---
## Consuming Dependencies
### resolve
You can then resolve a dependency anywhere in your app:
```ts

@@ -134,3 +144,5 @@ const value = jpex.resolve<MyFactory>();

### dependent factories
A factory can request another dependency and jpex will resolve it on the fly:
```ts

@@ -147,3 +159,5 @@ jpex.constant<MyConstant>('foo');

### encase
Or you can *encase* a regular function so that dependencies are injected into it when called:
Or you can _encase_ a regular function so that dependencies are injected into it when called:
```ts

@@ -157,16 +171,22 @@ const fn = jpex.encase((value: MyFactory) => (arg1, arg2) => {

-------
---
## API
### jpex
#### jpex.constant
```ts
<T>(obj: T): void
```
Registers a constant value.
#### jpex.factory
```ts
<T>(fn: (...deps: any[] => T), opts?: object): void
```
Registers a factory function against the given type. Jpex works out the types of `deps` and injects them at resolution time, then returns the resulting value `T`.

@@ -185,5 +205,7 @@

##### lifecycle
```ts
'application' | 'class' | 'instance' | 'none'
'application' | 'class' | 'instance' | 'none';
```
Determines how long the factory is cached for once resolved.

@@ -199,5 +221,7 @@

##### precedence
```ts
'active' | 'passive'
'active' | 'passive';
```
Determines the behavior when the same factory is registered multiple times.

@@ -211,17 +235,23 @@

##### bindToInstance
```ts
boolean
boolean;
```
Specifically for services, automatically binds all of the dependencies to the service instance.
##### alias
```ts
string | string[]
```
Creates aliases for the factory. This is essentially just shorthand for writing `jpex.factory(...); jpex.alias(...);`
#### jpex.service
```ts
<T>(class: ClassWithConstructor, opts?: object): void
```
Registers a service. A service is like a factory but instantiates a class instead.

@@ -240,2 +270,3 @@

If a class `implements` an interface, you can actually use it to resolve the class:
```ts

@@ -252,11 +283,15 @@ interface IFoo {}

#### jpex.alias
```ts
<T>(alias: string): void
```
Creates an alias to another factory
#### jpex.resolve
```ts
<T>(opts?: object): T
```
Locates and resolves the desired factory.

@@ -271,21 +306,27 @@

##### optional
```ts
boolean
boolean;
```
When `true` if the dependency cannot be found or resolved, it will just return `undefined` rather than throwing an error.
#### jpex.resolveWith
```ts
<T, ...Rest[]>(values: Rest, opts?: object): T
```
Resolves a factory while substituting dependencies for the given values
```ts
const foo = jpex.resolveWith<Foo, Bah, Baz>([ 'bah', 'baz' ]);
const foo = jpex.resolveWith<Foo, Bah, Baz>(['bah', 'baz']);
```
#### jpex.encase
```ts
(...deps: any[]): (...args: any[]) => any
```
Wraps a function and injects values into it, it then returns the inner function for use.

@@ -308,5 +349,7 @@

#### jpex.extend
```ts
(config?: object): Jpex
```
creates a new container, using the current one as a base.

@@ -319,2 +362,3 @@

##### inherit
`boolean`

@@ -325,2 +369,3 @@

##### lifecycle
`'application' | 'class' | 'instance' | 'none'`

@@ -331,2 +376,3 @@

##### precedence
`'active' | 'passive'`

@@ -337,2 +383,3 @@

##### optional
`boolean`

@@ -343,2 +390,3 @@

##### nodeModules
`boolean`

@@ -349,2 +397,3 @@

##### globals
`boolean`

@@ -355,4 +404,5 @@

#### jpex.raw
```ts
<T>() => (...deps: any[]) => T
<T>() => (...deps: any[]) => T;
```

@@ -363,2 +413,3 @@

#### jpex.clearCache
```ts

@@ -372,4 +423,5 @@ () => void

#### jpex.infer
```ts
<T>() => string
<T>() => string;
```

@@ -380,9 +432,13 @@

### Types
#### Jpex
This is the type definition for the jpex container
#### NodeModule
This is a special type that lets you automatically inject a node module with type inference.
For example:
```ts

@@ -396,2 +452,3 @@ import jpex, { NodeModule } from 'jpex';

The default return type will be `any` but you can specify one explicitly with the second type parameter:
```ts

@@ -405,5 +462,7 @@ import type fstype from 'fs';

#### Global
This is another special type that lets you automatically inject a global property with type inference.
For built-in types you can do this without any helpers:
```ts

@@ -416,2 +475,3 @@ import jpex from 'jpex';

But for custom globals, or properties that don't have built-in types, you can use the `Global` type:
```ts

@@ -424,3 +484,5 @@ import jpex, { Global } from 'jpex';

## caveats
There are a few caveats to be aware of:
- Only named types/interfaces are supported so you can't do `jpex.factory<{}>()`

@@ -432,2 +494,3 @@ - There is not yet a concept of extending types, so if you do `interface Bah extends Foo {}` you can't then try to resolve `Foo` and expect to be given `Bah`, they are treated as 2 separate things

## react
Jpex is a really good fit with React as it offers a good way to inject impure effects into pure components. There is a `react-jpex` library that exposes a few hooks.

@@ -447,3 +510,3 @@

<div>
<MyForm/>
<MyForm />
<button onClick={onSubmit}>Submit</button>

@@ -466,7 +529,7 @@ </div>

// register our stub dependency on an isolated container
onMount={jpex => jpex.constant<SaveData>(saveData)}
onMount={(jpex) => jpex.constant<SaveData>(saveData)}
>
{/* when we render MyComponent, it will be given our stubbed dependency */}
<MyComponent/>
</Provider>
{/* when we render MyComponent, it will be given our stubbed dependency */}
<MyComponent />
</Provider>,
);

@@ -481,2 +544,3 @@

## Vanilla JS mode
Perhaps you hate typescript, or babel, or both. Or perhaps you don't have the luxury of a build pipeline in your application. That's fine because jpex supports vanilla js as well, you just have to explicitly state your dependencies up front:

@@ -488,3 +552,3 @@

jpex.constant('foo', 'foo');
jpex.factory('bah', [ 'foo' ], (foo) => foo + 'bah');
jpex.factory('bah', ['foo'], (foo) => foo + 'bah');

@@ -491,0 +555,0 @@ const value = jpex.resolve('bah');

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc