Skip to content

Commit

Permalink
feat: change signatures
Browse files Browse the repository at this point in the history
- dependencies are no longer determined by reading the factory function. Either use `TS` inference, or explicitly pass an array of deps
- changed format of `.factory` `.service` and `.resolve`
- you can now pass an `opts` parameter when registering a factory i.e. `.factory<A>(fn, { lifecycle: 'none' })`
- you can now pass an `opts` parameter when resolving i.e. `.resolve<A>({ optional: true })`
- rather than calling `.factory<A>(fn).lifecycle.application()` you must now do `.factory<A>(fn, { lifecycle: 'application' })`
- clearCache now takes an arity of names, i.e. `clearCache('a', 'b', 'c')` whereas previous it took an array
- you can no longer mix ts and js modes i.e. you cannot do `.factory<A>([ 'b' ], fn)`
- `Lifecycle` is now a type rather than an enum
- wrapping a name in `__` will no longer make it optional, you must explicitly pass the optional flag

closes #68
  • Loading branch information
Jack Ellis committed Aug 23, 2020
1 parent 191777a commit 6ecb1c3
Show file tree
Hide file tree
Showing 28 changed files with 179 additions and 322 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ Change Log
- 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
- dependencies are no longer determined by reading the factory function. Either use `TS` inference, or explicitly pass an array of deps
- changed format of `.factory` `.service` and `.resolve`
- you can now pass an `opts` parameter when registering a factory i.e. `.factory<A>(fn, { lifecycle: 'none' })`
- you can now pass an `opts` parameter when resolving i.e. `.resolve<A>({ optional: true })`

#### 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
- You can no longer do `jpex.factory('foo', (depA, depB) => { ... })` as we no longer parse the function and extract the dependencies
- You can no longer do `jpex.factory('foo', (depA, depB) => { ... })` as we no longer parse the function and extract the dependencies.
- rather than calling `.factory<A>(fn).lifecycle.application()` you must now do `.factory<A>(fn, { lifecycle: 'application' })`
- clearCache now takes an arity of names, i.e. `clearCache('a', 'b', 'c')` whereas previous it took an array
- you can no longer mix ts and js modes i.e. you cannot do `.factory<A>([ 'b' ], fn)`
- `Lifecycle` is now a type rather than an enum
- wrapping a name in `__` will no longer make it optional, you must explicitly pass the optional flag

### 3.5.0
- add some deprecation warnings for pre-4.0.0 changes
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"types": "dist/es/index.d.ts",
"scripts": {
"test": "ava",
"test:debug": "ava debug",
"coverage": "nyc ava",
"lint": "eslint './src/**/*.ts' && eslint './plugin/**/*.ts' && tsc --noEmit",
"build:prepare": "rm -rf dist",
Expand Down
4 changes: 1 addition & 3 deletions plugin/encase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ const encase = (

const arg = path.get('arguments.0') as NodePath<any>;
const deps = extractFunctionParameterTypes(programPath, arg, filename, publicPath);
if (deps.length) {
path.node.arguments.splice(0, 0, t.arrayExpression(deps.map((dep) => t.stringLiteral(dep))));
}
path.node.arguments.splice(0, 0, t.arrayExpression(deps.map((dep) => t.stringLiteral(dep))));
};

export default encase;
20 changes: 10 additions & 10 deletions plugin/factories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,27 @@ const factories = (
return;
}

if (args.length > 2) {
return;
}

// do we have an interface to use as the registrant name?
// if there is only 1 arg then we can't possibly have been given the name
// if the first arg isn't a string, then we also don't have a name
if (args.length === 1 || !t.isStringLiteral(args[0])) {
const type = getTypeParameter(path);
const type = getTypeParameter(path);

const name = getConcreteTypeName(type, filename, publicPath, programPath);
if (name != null) {
args.unshift(t.stringLiteral(name));
}
const name = getConcreteTypeName(type, filename, publicPath, programPath);
if (name != null) {
args.unshift(t.stringLiteral(name));
}

// do we need to infer the dependencies?
// ignore constants as there are no dependencies
// if the second parameter isn't an array of dependencies, it means it's inferred
if (callee.property.name !== 'constant' && !t.isArrayExpression(path.node.arguments[1])) {
if (callee.property.name !== 'constant') {
const arg = path.get('arguments.1') as NodePath<any>;
const deps = extractFunctionParameterTypes(programPath, arg, filename, publicPath);
if (deps.length) {
path.node.arguments.splice(1, 0, t.arrayExpression(deps.map((dep) => t.stringLiteral(dep))));
}
path.node.arguments.splice(1, 0, t.arrayExpression(deps.map((dep) => t.stringLiteral(dep))));
}
};

Expand Down
4 changes: 0 additions & 4 deletions plugin/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ const resolve = (
return;
}

if (args.length) {
return;
}

const type = getTypeParameter(path);
const name = getConcreteTypeName(type, filename, publicPath, programPath);
if (name != null) {
Expand Down
3 changes: 0 additions & 3 deletions plugin/resolveWith.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ const resolveWith = (
if (!isJpexCall(path, identifier, 'resolveWith')) {
return;
}
if (args.length > 1) {
return;
}

const type = getTypeParameter(path);
const name = getConcreteTypeName(type, filename, publicPath, programPath);
Expand Down
3 changes: 0 additions & 3 deletions plugin/useResolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ const useResolve = (
return;
}

if (args.length > 1) {
return;
}
if (args.length === 1) {
if (!t.isArrayExpression(args[0])) {
return;
Expand Down
30 changes: 15 additions & 15 deletions src/Jpex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import {
Factory,
SetupConfig,
} from './types';
import {
Lifecycle,
} from './constants';
import {
constant,
factory,
Expand Down Expand Up @@ -39,7 +36,7 @@ class Jpex implements IJpex {

this.$$parent = parent;
this.$$config = {
lifecycle: inherit ? parent?.$$config.lifecycle : void 0 ?? Lifecycle.CLASS,
lifecycle: (inherit ? parent?.$$config.lifecycle : void 0) ?? 'class',
globals: true,
nodeModules: true,
optional: false,
Expand All @@ -55,34 +52,37 @@ class Jpex implements IJpex {
return new Jpex(config, this);
}

constant(name: any, obj?: any): any {
constant(name: string, obj?: any) {
return constant(this, name, obj);
}
factory(name: any, deps?: any, fn?: any): any {
return factory(this, name, deps, fn);
factory(name: any, deps?: any, fn?: any, opts?: any): any {
return factory(this, name, deps, fn, opts);
}
service(name: any, deps?: any, fn?: any): any {
return service(this, name, deps, fn);
service(name: any, deps?: any, fn?: any, opts?: any): any {
return service(this, name, deps, fn, opts);
}
alias(alias?: any, name?: any): any {
return createAlias(this, alias, name);
}
resolve(name?: any): any {
return resolve(this, name);
resolve(name?: any, opts?: any): any {
return resolve(this, name, opts);
}
resolveWith(name: any, namedParameters?: any): any {
return resolve(this, name, namedParameters);
resolveWith(name: any, namedParameters?: any, opts?: any): any {
return resolve(this, name, {
with: namedParameters,
...opts,
});
}

raw(name?: any): any {
return getFactory(this, name, false).fn;
return getFactory(this, name, {}).fn;
}

encase<F extends AnyFunction, G extends AnyFunction<F>>(deps: any, fn?: any): any {
return encase(this, deps, fn);
}

clearCache(names?: any): any {
clearCache(...names: any[]): any {
return clearCache(this, names);
}

Expand Down
12 changes: 1 addition & 11 deletions src/__tests__/$resolve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,7 @@ test('errors if dependency cannot be resolved', (t) => {

test('accepts named parameters', (t) => {
const { resolve } = t.context;
const test = resolve('foo', { foo: 'bah' });
const test = resolve('foo', { with: { foo: 'bah' } });

t.is(test, 'bah');
});

test('resolves multiple dependencies', (t) => {
const { resolve } = t.context;
const test = resolve([ 'path', 'fs' ]);

t.true(Array.isArray(test));
t.is(test.length, 2);
t.truthy(test[0].dirname);
t.truthy(test[1].readFile);
});
20 changes: 10 additions & 10 deletions src/__tests__/clearCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test.beforeEach((t) => {
test('sets a factory to resolved once resolved', (t) => {
const { jpex } = t.context;

jpex.factory('instance', () => ({})).lifecycle.application();
jpex.factory('instance', [], () => ({}), { lifecycle: 'application' });
t.is(jpex.$$factories.instance.resolved, void 0);

jpex.resolve('instance');
Expand All @@ -26,7 +26,7 @@ test('sets a factory to resolved once resolved', (t) => {
test('clears the cache', (t) => {
const { jpex } = t.context;

jpex.factory('instance', () => ({})).lifecycle.application();
jpex.factory('instance', [], () => ({}), { lifecycle: 'application' });

t.is(jpex.$$factories.instance.resolved, void 0);
jpex.resolve('instance');
Expand All @@ -38,7 +38,7 @@ test('clears the cache', (t) => {
});

test('returns a new instance once the cache is cleared', (t) => {
jpex.factory('instance', () => ({})).lifecycle.application();
jpex.factory('instance', [], () => ({}), { lifecycle: 'application' });

const a = jpex.resolve('instance');
const b = jpex.resolve('instance');
Expand All @@ -50,9 +50,9 @@ test('returns a new instance once the cache is cleared', (t) => {
});

test('clears specific factories', (t) => {
jpex.factory('a', () => ({})).lifecycle.application();
jpex.factory('b', () => ({})).lifecycle.application();
jpex.factory('c', () => ({})).lifecycle.application();
jpex.factory('a', [], () => ({}), { lifecycle: 'application' });
jpex.factory('b', [], () => ({}), { lifecycle: 'application' });
jpex.factory('c', [], () => ({}), { lifecycle: 'application' });
jpex.resolve('a');
jpex.resolve('b');
jpex.resolve('c');
Expand All @@ -61,7 +61,7 @@ test('clears specific factories', (t) => {
t.true(jpex.$$factories.b.resolved);
t.true(jpex.$$factories.c.resolved);

jpex.clearCache([ 'a', 'b' ]);
jpex.clearCache('a', 'b');

t.false(jpex.$$factories.a.resolved);
t.false(jpex.$$factories.b.resolved);
Expand All @@ -71,8 +71,8 @@ test('clears specific factories', (t) => {
test('clears a cache using type inference', (t) => {
type A = string;
type B = string;
jpex.factory<A>(() => 'a').lifecycle.application();
jpex.factory<B>(() => 'b').lifecycle.application();
jpex.factory<A>(() => 'a', { lifecycle: 'application' });
jpex.factory<B>(() => 'b', { lifecycle: 'application' });
jpex.resolve<A>();
jpex.resolve<B>();

Expand All @@ -86,7 +86,7 @@ test('clears a cache using type inference', (t) => {
});

test('should clear Class-based caches', (t) => {
jpex.factory('a', () => ({})).lifecycle.class();
jpex.factory('a', [], () => ({}), { lifecycle: 'class' });
jpex.resolve('a');

t.is(typeof jpex.$$resolved.a, 'object');
Expand Down
14 changes: 7 additions & 7 deletions src/__tests__/lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test('application returns the same instance for all classes', (t) => {
jpex3,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.application();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'application' });

const a = jpex.resolve('factory');
const b = jpex2.resolve('factory');
Expand All @@ -48,7 +48,7 @@ test('application uses the first resolution forever', (t) => {
jpex3,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.application();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'application' });

const c = jpex3.resolve('factory');
const a = jpex.resolve('factory');
Expand All @@ -66,7 +66,7 @@ test('class returns different instances for each class', (t) => {
jpex3,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.class();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'class' });

const a = jpex.resolve('factory');
const b = jpex2.resolve('factory');
Expand All @@ -84,7 +84,7 @@ test('class returns the same instance within a single class', (t) => {
jpex,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.class();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'class' });

const a = jpex.resolve('factory');
const b = jpex.resolve('factory');
Expand All @@ -99,7 +99,7 @@ test('instance returns a new instance for each separate call', (t) => {
jpex,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.instance();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'instance' });

const a = jpex.resolve('factory');
const b = jpex.resolve('factory');
Expand All @@ -114,7 +114,7 @@ test('instance returns a single instance within a single call', (t) => {
jpex,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.instance();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'instance' });
jpex.factory('test', [ 'factory', 'factory' ], (a, b) => {
t.is(a, b);
});
Expand All @@ -127,7 +127,7 @@ test('none should return a different instance within a single call', (t) => {
jpex,
} = t.context;

jpex.factory('factory', (foo) => ({ foo })).lifecycle.none();
jpex.factory('factory', [ 'foo' ], (foo) => ({ foo }), { lifecycle: 'none' });
jpex.factory('test', [ 'factory', 'factory' ], (a, b) => {
t.not(a, b);
t.deepEqual(a, b);
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/raw.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('it returns the raw factory by name', (t) => {
.join('');
});

const factory = jpex.raw<Factory>('factory');
const factory = jpex.raw('factory');
const result = factory('bah');

t.is(result, 'hab');
Expand Down
Loading

0 comments on commit 6ecb1c3

Please sign in to comment.