Skip to content

Conversation

@raymondfeng
Copy link
Contributor

@raymondfeng raymondfeng commented Jan 11, 2018

Add @inject.tag decorator to allow injection of an array of bound values by a tag.

This DI can be used with the extension point/extension pattern so that the extension point can receive injection all extensions.

This is a spin-off from #671. The PR will be enhanced with ResolutionSession once #852 is landed.

Checklist

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • Related API Documentation was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in packages/example-* were updated

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

The PR will be enhanced with ResolutionSession once #852 is landed.

I think it may be better to land this right now and apply resolution session tracking in a follow-up pull request. Whatever works for you best.

await ctx.get('store');
throw new Error('An error should have been thrown');
} catch (e) {
expect(e.message).to.eql('Bad');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use rejectedWith as we discussed recently in another pull request.

values[i] = val;
}
}
if (asyncResolvers.length) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably out of scope of this pull request: I feel we are repeating the asyncResolvers pattern in too many places. It would be good to extract a shared helper function.

A mock-up to illustrate my point:

function resolveByTag(ctx: Context, injection: Injection) {
  const tag: string | RegExp = injection.metadata!.tag;
  const bindings = ctx.findByTag(tag);
  
  return mapValuesOrPromises(bindings, b => b.getValue(ctx));
}

function mapValuesOrPromises<T, O>(
  list: ValueOrPromise<T>, 
  fn: (item: T) => ValueOrPromise<O>,
): ValueOrPromise<O[]> {
  const values: O[] = new Array(list.length);
  const asyncResolvers: PromiseLike<O>[] = [];

  const valSetter = (i: number) => (val: BoundValue) => (values[i] = val);
  
  // tslint:disable-next-line:prefer-for-of
  for (let i = 0; i < bindings.length; i++) {
    const val = fn(list[i]);
    if (isPromise(val)) {
      asyncResolvers.push(val.then(valSetter(i)));
    } else {
      values[i] = val;
    }
  }

  return asyncResolvers.length ?
    Promise.all(asyncResolvers).then(_ => values):
    values;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. See #871

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants