Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): extract instance wrapper merge logic #9915

Merged
merged 15 commits into from
Jul 13, 2022

Conversation

thiagomini
Copy link
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

The InstanceWrapper#mergeWith method was using some verifications to determine how it would merge with a given provider. I extracted this logic to another file to improve its readability and also because it could be potentially used by other classes.

Moreover, I added some missing test cases for it.

What is the new behavior?

No new behavior, only refactor of existing one.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

ensure isClassProvider works as expected
ensure isValueProvider returns true when useValue is defined
ensure useValue returns false for undefined values
ensure isValueProvider returns false when useValue is not present
ensure isValueProvider returns false when given provider is undefined
ensure isFactoryProvider returns true when useFactory is present
ensure isFactoryProvider returns false when useFactory is not present
ensure isFactoryProvider returns false when useFactory is undefined
ensure isValueProvider returns true for falsy values
refactor instance-wrapper to use provider classifier methods
ensure mergeWith handles ValueProviders
ensure mergeWith handles ClassProviders
ensure mergeWith handles FactoryProviders with injected dependencies
ensure mergeWith handles FactoryProviders with no depencies
@thiagomini thiagomini changed the title Refactor/instance wrapper refactor(core): extract merge with logic Jul 11, 2022
@thiagomini thiagomini changed the title refactor(core): extract merge with logic refactor(core): extract instance wrapper merge logic Jul 11, 2022
@coveralls
Copy link

coveralls commented Jul 11, 2022

Pull Request Test Coverage Report for Build 6b68e907-67bc-4104-9eab-f1293def3c0e

  • 15 of 15 (100.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 94.089%

Totals Coverage Status
Change from base Build 2aff2745-a19a-4be0-8eb0-e6fb174d4239: 0.2%
Covered Lines: 6049
Relevant Lines: 6429

💛 - Coveralls

@@ -384,7 +389,7 @@ export class InstanceWrapper<T = any> {
}

public mergeWith(provider: Provider) {
if (!isUndefined((provider as ValueProvider).useValue)) {
if (isValueProvider(provider)) {
this.metatype = null;
this.inject = null;
this.scope = Scope.DEFAULT;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why do we have to set the scope to DEFAULT in this case? @kamilmysliwiec

Copy link
Member

Choose a reason for hiding this comment

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

@thiagomini static values are always singletons

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, thanks for the reply!

} from '../../../injector/helpers/provider-classifier';

describe('provider classifier', () => {
describe('isClassProvider', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For each of these utility functions, it may be useful to have some runtime checks to guarantee we're dealing with correct providers. For instance, in the case of a FactoryProvider that provides something like:

const wrongFactoryProvider = {
  provide: 'token',
  useFactory: {}
} as FactoryProvider

The object itself is not a real function. Should this really be recognized as a FactoryProvider in this case? Or we should rather throw an error informing the given value is not a real function?


describe('mergeWith', () => {
describe('when provider is a ValueProvider', () => {
it('should provide the given value in the STATIC_CONTEXT', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I appreciate a careful review of these tests to guarantee I tested the correct outcome for each case

} from '@nestjs/common';
import { isUndefined } from '@nestjs/common/utils/shared.utils';

export function isClassProvider(provider: Provider): boolean {
Copy link
Member

@micalevisk micalevisk Jul 12, 2022

Choose a reason for hiding this comment

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

I guess we could use ts guards here like

Suggested change
export function isClassProvider(provider: Provider): boolean {
export function isClassProvider<T = any>(provider: Provider): provider is ClassProvider<T> {

then we'll be able to remove those type assertions on statements below isClassProvider calls, I guess

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 suggestion Micael! Thanks 👍

change provider classifier functions to work as type guards
@kamilmysliwiec
Copy link
Member

LGTM

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

Successfully merging this pull request may close these issues.

4 participants