or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

federation.mdindex.mdmodule-configuration.mdresolvers.mdschema-building.mdschema-decorators.mdservices.mdsubscriptions.mdtype-system.md

resolvers.mddocs/

0

# Resolver Development

1

2

Tools and utilities for building GraphQL resolvers including field resolvers, context access, argument handling, and execution context management. This module provides the runtime infrastructure for GraphQL query execution in NestJS applications.

3

4

## Capabilities

5

6

### Field Resolvers

7

8

Decorators and utilities for creating computed fields and reference resolvers in GraphQL schemas.

9

10

```typescript { .api }

11

/**

12

* Marks a method as a GraphQL Field Resolver for computed fields

13

* @param name - Optional field name (defaults to method name)

14

* @param options - Configuration options for the field resolver

15

*/

16

function ResolveField(name?: string, options?: FieldOptions): MethodDecorator;

17

18

/**

19

* Marks a method as a GraphQL Reference Resolver for Apollo Federation

20

* Used to resolve entity references across federated services

21

*/

22

function ResolveReference(): MethodDecorator;

23

24

/**

25

* Legacy alias for ResolveField (deprecated in favor of ResolveField)

26

* @param name - Optional field name

27

* @param options - Configuration options

28

*/

29

function ResolveProperty(name?: string, options?: FieldOptions): MethodDecorator;

30

```

31

32

**Usage Examples:**

33

34

```typescript

35

import { Resolver, ResolveField, ResolveReference, Parent, Args } from "@nestjs/graphql";

36

37

@Resolver(() => User)

38

class UserResolver {

39

// Computed field resolver

40

@ResolveField(() => String)

41

fullName(@Parent() user: User): string {

42

return `${user.firstName} ${user.lastName}`;

43

}

44

45

// Async field resolver with database lookup

46

@ResolveField(() => [Post])

47

async posts(@Parent() user: User): Promise<Post[]> {

48

return this.postService.findByUserId(user.id);

49

}

50

51

// Field resolver with arguments

52

@ResolveField(() => [Post])

53

recentPosts(

54

@Parent() user: User,

55

@Args('limit', { defaultValue: 10 }) limit: number

56

): Promise<Post[]> {

57

return this.postService.findRecentByUserId(user.id, limit);

58

}

59

60

// Federation reference resolver

61

@ResolveReference()

62

resolveReference(reference: { __typename: string; id: string }): Promise<User> {

63

return this.userService.findById(reference.id);

64

}

65

}

66

```

67

68

### Execution Context

69

70

Utilities for accessing GraphQL-specific execution context within resolvers and guards.

71

72

```typescript { .api }

73

/**

74

* GraphQL-specific execution context wrapper providing access to GraphQL resolver arguments

75

*/

76

export class GqlExecutionContext {

77

/**

78

* Create GraphQL execution context from standard NestJS execution context

79

* @param context - Standard NestJS execution context

80

* @returns GraphQL-specific execution context

81

*/

82

static create(context: ExecutionContext): GqlExecutionContext;

83

84

/**

85

* Get the context type (always returns 'graphql')

86

* @returns Context type string

87

*/

88

getType(): string;

89

90

/**

91

* Get the GraphQL root/parent object

92

* @returns Root object for the current resolver

93

*/

94

getRoot<T = any>(): T;

95

96

/**

97

* Get GraphQL resolver arguments

98

* @returns Arguments object passed to the resolver

99

*/

100

getArgs<T = any>(): T;

101

102

/**

103

* Get GraphQL context object

104

* @returns GraphQL context containing request, response, and custom data

105

*/

106

getContext<T = any>(): T;

107

108

/**

109

* Get GraphQL resolve info object

110

* @returns GraphQL resolve info containing field selection and metadata

111

*/

112

getInfo(): GraphQLResolveInfo;

113

}

114

115

/**

116

* Type alias for GraphQL execution context

117

*/

118

type GraphQLExecutionContext = GqlExecutionContext;

119

120

/**

121

* Union type for GraphQL context types

122

*/

123

type GqlContextType = 'graphql';

124

```

125

126

**Usage Examples:**

127

128

```typescript

129

import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";

130

import { GqlExecutionContext } from "@nestjs/graphql";

131

132

// Using in a Guard

133

@Injectable()

134

export class AuthGuard implements CanActivate {

135

canActivate(context: ExecutionContext): boolean {

136

const gqlContext = GqlExecutionContext.create(context);

137

const ctx = gqlContext.getContext();

138

const user = ctx.req.user;

139

return !!user;

140

}

141

}

142

143

// Using in an Interceptor

144

@Injectable()

145

export class LoggingInterceptor implements NestInterceptor {

146

intercept(context: ExecutionContext, next: CallHandler): Observable<any> {

147

const gqlContext = GqlExecutionContext.create(context);

148

const info = gqlContext.getInfo();

149

console.log(`Executing GraphQL field: ${info.fieldName}`);

150

return next.handle();

151

}

152

}

153

```

154

155

### Arguments Host

156

157

Service for accessing GraphQL resolver arguments in a structured way.

158

159

```typescript { .api }

160

/**

161

* Host service for accessing GraphQL resolver arguments

162

*/

163

export class GqlArgumentsHost {

164

/**

165

* Get the GraphQL root/parent object

166

* @returns Root object for the current resolver

167

*/

168

getRoot<T = any>(): T;

169

170

/**

171

* Get GraphQL resolver arguments

172

* @returns Arguments object passed to the resolver

173

*/

174

getArgs<T = any>(): T;

175

176

/**

177

* Get GraphQL context object

178

* @returns GraphQL context containing request, response, and custom data

179

*/

180

getContext<T = any>(): T;

181

182

/**

183

* Get GraphQL resolve info object

184

* @returns GraphQL resolve info containing field selection and metadata

185

*/

186

getInfo(): GraphQLResolveInfo;

187

}

188

189

/**

190

* Interface for GraphQL arguments host

191

*/

192

interface GraphQLArgumentsHost {

193

getRoot<T = any>(): T;

194

getArgs<T = any>(): T;

195

getContext<T = any>(): T;

196

getInfo(): GraphQLResolveInfo;

197

}

198

```

199

200

### Base Explorer Service

201

202

Base service class for exploring and processing GraphQL metadata from NestJS modules.

203

204

```typescript { .api }

205

/**

206

* Base class for services that explore NestJS modules for GraphQL metadata

207

*/

208

export abstract class BaseExplorerService {

209

/**

210

* Explore modules and extract metadata

211

* @param modules - Array of NestJS modules to explore

212

* @returns Extracted metadata

213

*/

214

protected abstract explore(modules: any[]): any;

215

216

/**

217

* Filter and process discovered providers

218

* @param providers - Array of providers to process

219

* @returns Processed providers

220

*/

221

protected abstract filterProviders(providers: any[]): any[];

222

}

223

```

224

225

### Resolver Context Types

226

227

Type definitions for resolver context handling and argument extraction.

228

229

```typescript { .api }

230

/**

231

* Interface for GraphQL context containing request and response objects

232

*/

233

interface GraphQLContext {

234

/** HTTP request object */

235

req: any;

236

/** HTTP response object */

237

res: any;

238

/** Connection object for subscriptions */

239

connection?: any;

240

/** Additional context data */

241

[key: string]: any;

242

}

243

244

/**

245

* Type for resolver function signatures

246

*/

247

type ResolverFn<TSource = any, TContext = any, TArgs = any, TResult = any> = (

248

source: TSource,

249

args: TArgs,

250

context: TContext,

251

info: GraphQLResolveInfo

252

) => TResult | Promise<TResult>;

253

254

/**

255

* Type for field resolver functions

256

*/

257

type FieldResolverFn<TSource = any, TContext = any, TArgs = any, TResult = any> = (

258

source: TSource,

259

args: TArgs,

260

context: TContext,

261

info: GraphQLResolveInfo

262

) => TResult | Promise<TResult>;

263

```

264

265

### Advanced Resolver Patterns

266

267

Common patterns and utilities for building complex GraphQL resolvers.

268

269

```typescript { .api }

270

/**

271

* Interface for implementing resolve type functions for union and interface types

272

*/

273

interface ResolveTypeFn<TSource = any, TContext = any> {

274

(value: TSource, context: TContext, info: GraphQLResolveInfo): string | Promise<string>;

275

}

276

277

/**

278

* Options for configuring resolver validation

279

*/

280

interface ResolverValidationOptions {

281

/** Whether to require resolvers for all fields */

282

requireResolversForResolveType?: boolean;

283

/** Whether to require resolvers for all args */

284

requireResolversForArgs?: boolean;

285

/** Whether to require resolvers for non-scalar fields */

286

requireResolversForNonScalar?: boolean;

287

/** Whether to require resolvers for all fields */

288

requireResolversForAllFields?: boolean;

289

}

290

```

291

292

**Advanced Usage Examples:**

293

294

```typescript

295

import { Resolver, ResolveField, Parent, Args, Context, Info } from "@nestjs/graphql";

296

import { GraphQLResolveInfo } from "graphql";

297

298

@Resolver(() => User)

299

export class AdvancedUserResolver {

300

constructor(

301

private userService: UserService,

302

private postService: PostService,

303

private dataLoader: DataLoaderService

304

) {}

305

306

// Resolver with data loader for N+1 problem prevention

307

@ResolveField(() => [Post])

308

async posts(@Parent() user: User): Promise<Post[]> {

309

return this.dataLoader.postsByUserId.load(user.id);

310

}

311

312

// Resolver with field selection optimization

313

@ResolveField(() => Profile)

314

async profile(

315

@Parent() user: User,

316

@Info() info: GraphQLResolveInfo

317

): Promise<Profile> {

318

const selectedFields = this.getSelectedFields(info);

319

return this.userService.findProfileWithFields(user.id, selectedFields);

320

}

321

322

// Resolver with complex arguments and validation

323

@ResolveField(() => [Post])

324

async postsByCategory(

325

@Parent() user: User,

326

@Args('category') category: string,

327

@Args('pagination') pagination: PaginationArgs,

328

@Context() context: GraphQLContext

329

): Promise<Post[]> {

330

// Access user from context for authorization

331

const currentUser = context.req.user;

332

return this.postService.findByUserAndCategory(

333

user.id,

334

category,

335

pagination,

336

currentUser

337

);

338

}

339

340

// Federation resolver with error handling

341

@ResolveReference()

342

async resolveReference(

343

reference: { __typename: string; id: string }

344

): Promise<User | null> {

345

try {

346

return await this.userService.findById(reference.id);

347

} catch (error) {

348

// Log error and return null for graceful degradation

349

console.error(`Failed to resolve user reference: ${reference.id}`, error);

350

return null;

351

}

352

}

353

354

private getSelectedFields(info: GraphQLResolveInfo): string[] {

355

// Helper method to extract selected fields from GraphQL info

356

// Implementation would parse the selection set

357

return [];

358

}

359

}

360

361

// Union type resolver

362

@Resolver(() => SearchResult)

363

export class SearchResultResolver {

364

@ResolveField()

365

__resolveType(value: any): string {

366

if (value instanceof User) return 'User';

367

if (value instanceof Post) return 'Post';

368

return null;

369

}

370

}

371

```

372

373

### Error Handling in Resolvers

374

375

Best practices and utilities for handling errors in GraphQL resolvers.

376

377

```typescript { .api }

378

/**

379

* GraphQL-specific error types

380

*/

381

import {

382

GraphQLError,

383

UserInputError,

384

AuthenticationError,

385

ForbiddenError,

386

ApolloError

387

} from 'apollo-server-express';

388

389

/**

390

* Custom GraphQL error with extensions

391

*/

392

class CustomGraphQLError extends GraphQLError {

393

constructor(

394

message: string,

395

code: string,

396

extensions?: Record<string, any>

397

) {

398

super(message, null, null, null, null, null, {

399

code,

400

...extensions,

401

});

402

}

403

}

404

```

405

406

**Error Handling Examples:**

407

408

```typescript

409

import { UserInputError, AuthenticationError } from 'apollo-server-express';

410

411

@Resolver(() => User)

412

export class UserResolver {

413

@Query(() => User)

414

async user(@Args('id') id: string, @Context() context: any): Promise<User> {

415

// Authentication check

416

if (!context.user) {

417

throw new AuthenticationError('You must be logged in to view user details');

418

}

419

420

// Input validation

421

if (!id || typeof id !== 'string') {

422

throw new UserInputError('Invalid user ID provided', {

423

invalidArgs: ['id'],

424

});

425

}

426

427

const user = await this.userService.findById(id);

428

429

if (!user) {

430

throw new UserInputError('User not found', {

431

code: 'USER_NOT_FOUND',

432

userId: id,

433

});

434

}

435

436

return user;

437

}

438

}

439

```