-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: convert to full Nest.js module
- Loading branch information
1 parent
409990a
commit d83bfa0
Showing
6 changed files
with
100 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { DynamicModule, Module } from '@nestjs/common' | ||
import { APP_INTERCEPTOR } from '@nestjs/core' | ||
import { DataloaderInterceptor } from './Dataloader.interceptor.js' | ||
|
||
@Module({ | ||
providers: [ | ||
{ provide: APP_INTERCEPTOR, useClass: DataloaderInterceptor }, | ||
], | ||
}) | ||
class DataloaderModule { | ||
static forRoot(): DynamicModule { | ||
return { | ||
module: DataloaderModule, | ||
} | ||
} | ||
} | ||
|
||
export { | ||
DataloaderModule, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { createParamDecorator, type ExecutionContext } from '@nestjs/common' | ||
import { ctxkey, store, type Factory } from './internal.js' | ||
|
||
/** | ||
* Load a `Dataloader` factory into the decorated parameter | ||
* The factory class must be an implementation of the `DataloaderFactory` abstract class. | ||
*/ | ||
const Loader = createParamDecorator((Factory: Factory, context: ExecutionContext) => { | ||
const item = store.get(ctxkey(context)) | ||
|
||
if (!item) { | ||
throw new Error('DataLoaderInterceptor not registered in this Nest.js application') | ||
} | ||
|
||
if (!item.dataloaders.has(Factory)) { | ||
// We don't have this dataloader created yet for this request, let's instantiate it and save it | ||
const factory = item.moduleRef.get(Factory, { strict: false }) | ||
item.dataloaders.set(Factory, factory.create(context)) | ||
} | ||
|
||
return item.dataloaders.get(Factory) | ||
}) | ||
|
||
export { | ||
Loader, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { DataloaderInterceptor, Loader } from './Dataloader.interceptor.js' | ||
export { Loader } from './Loader.decorator.js' | ||
export { DataloaderFactory, LoaderFrom, Aggregated } from './DataloaderFactory.js' | ||
export { DataloaderModule } from './Dataloader.module.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { type ExecutionContext, type Type } from '@nestjs/common' | ||
import { type ModuleRef } from '@nestjs/core' | ||
import { GqlExecutionContext, type GqlContextType } from '@nestjs/graphql' | ||
import type DataLoader from 'dataloader' | ||
import { type DataloaderFactory } from './DataloaderFactory.js' | ||
|
||
/** | ||
* DataloaderFactory constructor type | ||
* @private | ||
*/ | ||
type Factory = Type<DataloaderFactory<unknown, unknown>> | ||
|
||
/** @private */ | ||
interface StoreItem { | ||
/** ModuleRef is used by the `@Loader()` decorator to pull the Factory instance from Nest's DI container */ | ||
moduleRef: ModuleRef | ||
/** Dataloaders already constructed by a given Factory for this request. */ | ||
dataloaders: Map<Factory, DataLoader<unknown, unknown>> | ||
} | ||
|
||
/** | ||
* A weak map that tracks the requests and the dataloaders created for those requests | ||
* @private | ||
*/ | ||
const store = new WeakMap<object, StoreItem>() | ||
|
||
/** | ||
* Given Nestjs execution context, obtain something that is scoped to the lifetime of the current request and does not | ||
* change (same instance). | ||
* @private | ||
*/ | ||
function ctxkey(context: ExecutionContext) { | ||
const type = context.getType<GqlContextType>() | ||
|
||
switch (type) { | ||
case 'graphql': return GqlExecutionContext.create(context).getContext<{ req: object }>().req | ||
case 'http': return context.switchToHttp().getRequest<object>() | ||
// Support for other request types can be added later, we just did not need them yet. | ||
default: throw new Error(`Unknown or unsupported context type: ${type}`) | ||
} | ||
} | ||
|
||
export { | ||
store, | ||
Factory, | ||
ctxkey, | ||
} |