简体   繁体   中英

nestJs + gql route conflict/override

Hello guys I have an issue with conflicts/overrides inside my nestJS application.

So what is the issue:

I Have Resolver A

@Resolver('ResolverA')
export class SomePageResolver {
  constructor(private readonly someService: someService) {
  }

  @Query(() => someType)
  theThingThatMessesUpStuff(
    @Args('params') params: HttpParamsInput,
    @Context(TokenPipe) authorization: string,
    ): Observable<ActionSetsPageType> {
    return this.someService.doSomething(params, authorization)
  }
}

And a resolver B

@Resolver('ResolverB')
export class SomePageResolver{
  constructor(private readonly someService: someService) {
  }

  @Query(() => someOtherType)
  theThingThatMessesUpStuff(
    @Args('params') params: HttpParamsInput,
    @Context(TokenPipe) authorization: string,
    ): Observable<ActionSetsPageType> {
    return this.someService.doSomethingElse(params, authorization)
  }
}

Respectively Resolver A is part of Module A and Resolver B is part of Module B .

Depending on the build I have, there is a chance that both Module A and Module B are imported in a single module (single parent module), which leads to the overwriting issue. The essence of the issue is that when both modules are part of the build, if the client makes a query for theThingThatMessesUpStuff it will make a query using the module that is imported last

// some code
@Module({
  imports: [
    // some imports
    ModuleB,
    ModuleA
  ]
})
// some more code

If the example configuration from above is used, whenever the client tries to query theThingThatMessesUpStuff field, the query will be resolved by the implementation inside ModuleA , where for some of the features (inside the front end related to this build) the client will expect the implementation inside ModuleB

And now back to the main question, is there a way without involving too many people, to create a validation that will guarantee, that only unique GQL queries exist in the scope of nestJS application.

So far I have figured out two solutions:

  1. Somehow implement across all teams and people part of the project a naming convention, in the form of some kind of prefix, which will do the trick as long every team member knows about it and is vigilant.

  2. Create a decorator function and decorate all queries

const registered = {};

export const uniqueKey = () => {
  return function(_target: any, propertyKey: string) {
    if (registered[propertyKey]) {
      console.error(`${propertyKey} already in used`);
      throw new Error(`Resolver name already in use`);
    } else {
      registered[propertyKey] = true;
    }
  };
};

And this thing will be used as so

@Resolver('ResolverA')
export class SomePageResolver {
  constructor(private readonly someService: someService) {
  }

  @uniqueKey()
  @Query(() => someType)
  theThingThatMessesUpStuff(
    @Args('params') params: HttpParamsInput,
    @Context(TokenPipe) authorization: string,
    ): Observable<ActionSetsPageType> {
    return this.someService.doSomething(params, authorization)
  }
}

With this solution once again the developers should be vigilant and use the decorator everywhere, also this decorator should be applied trough the whole code-base, for consistency (which is quite unpleasant task).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM