Repository: krislefeber/nestjs-dataloader
Branch: master
Commit: f3acaf5570d7
Files: 20
Total size: 17.5 KB
Directory structure:
gitextract_g1ppmali/
├── .github/
│ └── workflows/
│ └── nodejs.yml
├── .gitignore
├── LICENSE
├── README.md
├── _config.yml
├── example/
│ ├── __tests__/
│ │ └── app.e2e-spec.ts
│ ├── src/
│ │ ├── account/
│ │ │ ├── account.entity.ts
│ │ │ ├── account.loader.ts
│ │ │ ├── account.module.ts
│ │ │ ├── account.resolver.spec.ts
│ │ │ ├── account.resolver.ts
│ │ │ ├── account.service.spec.ts
│ │ │ └── account.service.ts
│ │ ├── app.module.ts
│ │ └── main.ts
│ └── tsconfig.json
├── index.ts
├── nest-cli.json
├── package.json
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/nodejs.yml
================================================
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
push:
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn install --frozen-lockfile
- run: yarn tsc -p . --noEmit
- run: yarn test
env:
CI: true
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
.vscode/
dist/
### https://raw.github.com/github/gitignore/994f99fc353f523dfe5633067805a1dd4a53040f/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.pnp.*
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Kris Lefeber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# NestJS Dataloader

[](https://coveralls.io/github/krislefeber/nestjs-dataloader?branch=master)
NestJS dataloader simplifies adding [graphql/dataloader](https://github.com/graphql/dataloader) to your NestJS project. DataLoader aims to solve the common N+1 loading problem.
## Installation
Install with yarn
```bash
yarn add nestjs-dataloader
```
Install with npm
```bash
npm install --save nestjs-dataloader
```
## Usage
### NestDataLoader Creation
We start by implementing the `NestDataLoader` interface. This tells `DataLoader` how to load our objects.
```typescript
import * as DataLoader from 'dataloader';
import { Injectable } from '@nestjs/common';
import { NestDataLoader } from 'nestjs-dataloader';
...
@Injectable()
export class AccountLoader implements NestDataLoader<string, Account> {
constructor(private readonly accountService: AccountService) { }
generateDataLoader(): DataLoader<string, Account> {
return new DataLoader<string, Account>(keys => this.accountService.findByIds(keys));
}
}
```
The first generic of the interface is the type of ID the datastore uses. The second generic is the type of object that will be returned. In the above instance, we want `DataLoader` to return instances of the `Account` class.
### Providing the NestDataLoader
For each NestDataLoader we create, we need to provide it to our module.
```typescript
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import {DataLoaderInterceptor} from 'nestjs-dataloader'
...
@Module({
providers: [
AccountResolver,
AccountLoader,
{
provide: APP_INTERCEPTOR,
useClass: DataLoaderInterceptor,
},
],
})
export class ResolversModule { }
```
### Using the NestDataLoader
Now that we have a dataloader and our module is aware of it, we need to pass it as a parameter to an endpoint in our graphQL resolver.
```typescript
import * as DataLoader from 'dataloader';
import { Loader } from 'nestjs-dataloader';
...
@Resolver(Account)
export class AccountResolver {
@Query(() => [Account])
public getAccounts(
@Args({ name: 'ids', type: () => [String] }) ids: string[],
@Loader(AccountLoader) accountLoader: DataLoader<Account['id'], Account>): Promise<Account[]> {
return accountLoader.loadMany(ids);
}
}
```
The important thing to note is that the parameter of the `@Loader` decorator is the entity/class of the `NestDataLoader` we want to be injected to the method. The DataLoader library will handle bulk retrieval and caching of our requests. Note that the caching is stored on a per-request basis.
## Contributing
Pull requests are always welcome. For major changes, please open an issue first to discuss what you would like to change.
================================================
FILE: _config.yml
================================================
theme: jekyll-theme-slate
================================================
FILE: example/__tests__/app.e2e-spec.ts
================================================
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import request from 'supertest';
import gql from "graphql-tag";
import { AppModule } from "./../src/app.module";
import { Factory } from 'typeorm-factory'
import { Account } from "../src/account/account.entity";
describe("AppModule", () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(() => app.close());
it("defined", () => expect(app).toBeDefined());
it("/graphql(POST) getAccounts", async () => {
const f = new Factory(Account).attr('name', 'name')
const account = await f.create()
const query = request(app.getHttpServer()).post;
const result = await query('/graphql',{
query: gql`
query q($ids: [ID!]!) {
getAccounts(ids: $ids) {
id
}
}
`,
variables: {
ids: [account.id],
},
});
expect(result.errors).toBeUndefined()
});
});
================================================
FILE: example/src/account/account.entity.ts
================================================
import { ObjectType, Field, ID } from "@nestjs/graphql";
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity("accounts")
@ObjectType()
export class Account {
@PrimaryGeneratedColumn()
@Field(() => ID)
readonly id: string;
@Column()
readonly name: string;
}
================================================
FILE: example/src/account/account.loader.ts
================================================
import DataLoader = require("dataloader");
import { Injectable } from "@nestjs/common";
import { NestDataLoader } from "../../..";
import { AccountService } from "./account.service";
import { Account } from "./account.entity";
@Injectable()
export class AccountLoader implements NestDataLoader<string, Account> {
constructor(private readonly accountService: AccountService) {}
generateDataLoader(): DataLoader<string, Account> {
return new DataLoader<string, Account>(keys =>
this.accountService.findByIds(keys)
);
}
}
================================================
FILE: example/src/account/account.module.ts
================================================
import { Module } from "@nestjs/common";
import { AccountResolver } from "./account.resolver";
import { AccountService } from "./account.service";
import { APP_INTERCEPTOR } from "@nestjs/core/constants";
import { DataLoaderInterceptor } from "../../../index";
import { Account } from "./account.entity";
import { TypeOrmModule } from "@nestjs/typeorm";
import { AccountLoader } from "./account.loader";
@Module({
imports: [TypeOrmModule.forFeature([Account])],
providers: [
AccountResolver,
AccountService,
AccountLoader,
{
provide: APP_INTERCEPTOR,
useClass: DataLoaderInterceptor,
},
],
})
export class AccountModule {}
================================================
FILE: example/src/account/account.resolver.spec.ts
================================================
import { Test, TestingModule } from "@nestjs/testing";
import { AccountResolver } from "./account.resolver";
describe("AccountResolver", () => {
let resolver: AccountResolver;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AccountResolver],
}).compile();
resolver = module.get<AccountResolver>(AccountResolver);
});
it("should be defined", () => expect(resolver).toBeDefined());
});
================================================
FILE: example/src/account/account.resolver.ts
================================================
import { Resolver, Args, Query, ID } from "@nestjs/graphql";
import * as DataLoader from "dataloader";
import { Loader } from "../../../index";
import { Account } from "./account.entity";
import { AccountLoader } from "./account.loader";
@Resolver("Account")
export class AccountResolver {
@Query(() => [Account])
public getAccounts(
@Args({ name: "ids", type: () => [ID] }) ids: string[],
@Loader(AccountLoader)
accountLoader: DataLoader<Account["id"], Account>
): Promise<(Account | Error)[]> {
return accountLoader.loadMany(ids);
}
}
================================================
FILE: example/src/account/account.service.spec.ts
================================================
import { Test, TestingModule } from "@nestjs/testing";
import { AccountService } from "./account.service";
import { Account } from "./account.entity";
import { getRepositoryToken } from "@nestjs/typeorm";
describe("AccountService", () => {
let service: AccountService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
AccountService,
{
provide: getRepositoryToken(Account),
useValue: {},
},
],
}).compile();
service = module.get<AccountService>(AccountService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
});
================================================
FILE: example/src/account/account.service.ts
================================================
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Account } from "./account.entity";
import { Repository, In } from "typeorm";
@Injectable()
export class AccountService {
constructor(
@InjectRepository(Account)
private readonly accounts: Repository<Account>
) {}
async findByIds(ids: readonly string[]) {
return this.accounts.findByIds(ids as string[]);
}
}
================================================
FILE: example/src/app.module.ts
================================================
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";
import { Module } from "@nestjs/common";
import { GraphQLModule } from "@nestjs/graphql";
import { TypeOrmModule } from "@nestjs/typeorm";
import { join } from "path";
import { AccountModule } from "./account/account.module";
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
debug: true,
}),
TypeOrmModule.forRoot({
type: "sqlite",
database: "sample",
entities: [join(__dirname, "./**/*.entity.[t|j]s")],
synchronize: true,
}),
AccountModule,
]
})
export class AppModule {}
================================================
FILE: example/src/main.ts
================================================
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
================================================
FILE: example/tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "./dist",
"skipLibCheck": true,
},
"include": ["src"],
"exclude": ["node_modules", "*.spec.ts"]
}
================================================
FILE: index.ts
================================================
import {
CallHandler,
createParamDecorator,
ExecutionContext,
Injectable,
InternalServerErrorException,
NestInterceptor,
Type,
} from '@nestjs/common';
import { APP_INTERCEPTOR, ModuleRef, ContextIdFactory } from '@nestjs/core';
import { GqlExecutionContext } from '@nestjs/graphql';
import * as DataLoader from 'dataloader';
import { Observable } from 'rxjs';
/**
* This interface will be used to generate the initial data loader.
* The concrete implementation should be added as a provider to your module.
*/
export interface NestDataLoader<ID, Type> {
/**
* Should return a new instance of dataloader each time
*/
generateDataLoader(): DataLoader<ID, Type>;
}
/**
* Context key where get loader function will be stored.
* This class should be added to your module providers like so:
* {
* provide: APP_INTERCEPTOR,
* useClass: DataLoaderInterceptor,
* },
*/
const NEST_LOADER_CONTEXT_KEY: string = "NEST_LOADER_CONTEXT_KEY";
@Injectable()
export class DataLoaderInterceptor implements NestInterceptor {
constructor(private readonly moduleRef: ModuleRef) { }
/**
* @inheritdoc
*/
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const graphqlExecutionContext = GqlExecutionContext.create(context);
const ctx = graphqlExecutionContext.getContext();
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
ctx[NEST_LOADER_CONTEXT_KEY] = {
contextId: ContextIdFactory.create(),
getLoader: (type: string) : Promise<NestDataLoader<any, any>> => {
if (ctx[type] === undefined) {
try {
ctx[type] = (async () => {
return (await this.moduleRef.resolve<NestDataLoader<any, any>>(type, ctx[NEST_LOADER_CONTEXT_KEY].contextId, { strict: false }))
.generateDataLoader();
})();
} catch (e) {
throw new InternalServerErrorException(`The loader ${type} is not provided` + e);
}
}
return ctx[type];
}
};
}
return next.handle();
}
}
/**
* The decorator to be used within your graphql method.
*/
export const Loader = createParamDecorator(async (data: Type<NestDataLoader<any, any>>, context: ExecutionContext & { [key: string]: any }) => {
const ctx: any = GqlExecutionContext.create(context).getContext();
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
throw new InternalServerErrorException(`
You should provide interceptor ${DataLoaderInterceptor.name} globally with ${APP_INTERCEPTOR}
`);
}
return await ctx[NEST_LOADER_CONTEXT_KEY].getLoader(data);
});
================================================
FILE: nest-cli.json
================================================
{
"collection": "@nestjs/schematics",
"sourceRoot": "example/src",
"compilerOptions": {
"plugins": ["@nestjs/graphql/plugin"]
}
}
================================================
FILE: package.json
================================================
{
"name": "nestjs-dataloader",
"version": "2.0.6",
"description": "A NestJS decorator for dataloader",
"license": "MIT",
"repository": "https://github.com/krislefeber/nestjs-dataloader",
"author": "Kris Lefeber <krislefeber@gmail.com>",
"main": "dist/index.js",
"scripts": {
"build": "tsc -p tsconfig.json",
"prebuild": "rm -rf ./dist",
"prepare": "tsc -p tsconfig.json",
"prestart": "rm -rf ./example/dist",
"start": "nest start example/src/main.ts --watch --path=example/tsconfig.json",
"test": "jest"
},
"keywords": [
"nestjs",
"dataloader",
"graphql"
],
"dependencies": {
"@nestjs/apollo": "^10.0.22",
"dataloader": "^2.1.0",
"rxjs": "^7.5.6"
},
"devDependencies": {
"@nestjs/cli": "^9.1.1",
"@nestjs/common": "^9.0.1",
"@nestjs/core": "^9.0.1",
"@nestjs/graphql": "^10.0.18",
"@nestjs/platform-express": "^9.0.1",
"@nestjs/testing": "^9.0.1",
"@nestjs/typeorm": "^9.0.1",
"@types/jest": "28.1.4",
"apollo-server": "3.9.0",
"apollo-server-express": "^3.9.0",
"graphql": "^16.5.0",
"jest": "28.1.3",
"reflect-metadata": "^0.1.12",
"sqlite3": "^5.0.11",
"supertest": "^6.2.4",
"ts-jest": "^28.0.8",
"typeorm": "0.2.18",
"typeorm-factory": "^0.0.14",
"typescript": "4.7.4"
},
"types": "index.d.ts",
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"collectCoverage": true,
"globals": {
"ts-jest": {
"diagnostics": {
"warnOnly": true
}
}
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.ts$",
"collectCoverageFrom": [
"index.ts"
]
},
"files": [
"dist"
]
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"esModuleInterop": true,
"skipLibCheck": true
},
"exclude": ["node_modules", "dist", "example"]
}
gitextract_g1ppmali/ ├── .github/ │ └── workflows/ │ └── nodejs.yml ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── example/ │ ├── __tests__/ │ │ └── app.e2e-spec.ts │ ├── src/ │ │ ├── account/ │ │ │ ├── account.entity.ts │ │ │ ├── account.loader.ts │ │ │ ├── account.module.ts │ │ │ ├── account.resolver.spec.ts │ │ │ ├── account.resolver.ts │ │ │ ├── account.service.spec.ts │ │ │ └── account.service.ts │ │ ├── app.module.ts │ │ └── main.ts │ └── tsconfig.json ├── index.ts ├── nest-cli.json ├── package.json └── tsconfig.json
SYMBOL INDEX (17 symbols across 8 files)
FILE: example/src/account/account.entity.ts
class Account (line 6) | class Account {
FILE: example/src/account/account.loader.ts
class AccountLoader (line 8) | class AccountLoader implements NestDataLoader<string, Account> {
method constructor (line 9) | constructor(private readonly accountService: AccountService) {}
method generateDataLoader (line 11) | generateDataLoader(): DataLoader<string, Account> {
FILE: example/src/account/account.module.ts
class AccountModule (line 22) | class AccountModule {}
FILE: example/src/account/account.resolver.ts
class AccountResolver (line 8) | class AccountResolver {
method getAccounts (line 10) | public getAccounts(
FILE: example/src/account/account.service.ts
class AccountService (line 7) | class AccountService {
method constructor (line 8) | constructor(
method findByIds (line 13) | async findByIds(ids: readonly string[]) {
FILE: example/src/app.module.ts
class AppModule (line 24) | class AppModule {}
FILE: example/src/main.ts
function bootstrap (line 4) | async function bootstrap() {
FILE: index.ts
type NestDataLoader (line 19) | interface NestDataLoader<ID, Type> {
constant NEST_LOADER_CONTEXT_KEY (line 34) | const NEST_LOADER_CONTEXT_KEY: string = "NEST_LOADER_CONTEXT_KEY";
class DataLoaderInterceptor (line 37) | class DataLoaderInterceptor implements NestInterceptor {
method constructor (line 38) | constructor(private readonly moduleRef: ModuleRef) { }
method intercept (line 42) | intercept(context: ExecutionContext, next: CallHandler): Observable<an...
Condensed preview — 20 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (20K chars).
[
{
"path": ".github/workflows/nodejs.yml",
"chars": 905,
"preview": "# This workflow will do a clean install of node dependencies, build the source code and run tests across different versi"
},
{
"path": ".gitignore",
"chars": 1910,
"preview": ".vscode/\ndist/\n\n### https://raw.github.com/github/gitignore/994f99fc353f523dfe5633067805a1dd4a53040f/Node.gitignore\n\n# L"
},
{
"path": "LICENSE",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2019 Kris Lefeber\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "README.md",
"chars": 2966,
"preview": "# NestJS Dataloader\n\n\n[!"
},
{
"path": "_config.yml",
"chars": 25,
"preview": "theme: jekyll-theme-slate"
},
{
"path": "example/__tests__/app.e2e-spec.ts",
"chars": 1172,
"preview": "import { Test, TestingModule } from \"@nestjs/testing\";\nimport { INestApplication } from \"@nestjs/common\";\nimport request"
},
{
"path": "example/src/account/account.entity.ts",
"chars": 291,
"preview": "import { ObjectType, Field, ID } from \"@nestjs/graphql\";\nimport { Entity, PrimaryGeneratedColumn, Column } from \"typeorm"
},
{
"path": "example/src/account/account.loader.ts",
"chars": 541,
"preview": "import DataLoader = require(\"dataloader\");\nimport { Injectable } from \"@nestjs/common\";\nimport { NestDataLoader } from \""
},
{
"path": "example/src/account/account.module.ts",
"chars": 662,
"preview": "import { Module } from \"@nestjs/common\";\nimport { AccountResolver } from \"./account.resolver\";\nimport { AccountService }"
},
{
"path": "example/src/account/account.resolver.spec.ts",
"chars": 466,
"preview": "import { Test, TestingModule } from \"@nestjs/testing\";\nimport { AccountResolver } from \"./account.resolver\";\n\ndescribe(\""
},
{
"path": "example/src/account/account.resolver.ts",
"chars": 562,
"preview": "import { Resolver, Args, Query, ID } from \"@nestjs/graphql\";\nimport * as DataLoader from \"dataloader\";\nimport { Loader }"
},
{
"path": "example/src/account/account.service.spec.ts",
"chars": 675,
"preview": "import { Test, TestingModule } from \"@nestjs/testing\";\nimport { AccountService } from \"./account.service\";\nimport { Acco"
},
{
"path": "example/src/account/account.service.ts",
"chars": 436,
"preview": "import { Injectable } from \"@nestjs/common\";\nimport { InjectRepository } from \"@nestjs/typeorm\";\nimport { Account } from"
},
{
"path": "example/src/app.module.ts",
"chars": 668,
"preview": "import { ApolloDriver, ApolloDriverConfig } from \"@nestjs/apollo\";\nimport { Module } from \"@nestjs/common\";\nimport { Gra"
},
{
"path": "example/src/main.ts",
"chars": 208,
"preview": "import { NestFactory } from \"@nestjs/core\";\nimport { AppModule } from \"./app.module\";\n\nasync function bootstrap() {\n co"
},
{
"path": "example/tsconfig.json",
"chars": 341,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"commonjs\",\n \"declaration\": true,\n \"removeComments\": true,\n \"emitDecorat"
},
{
"path": "index.ts",
"chars": 2676,
"preview": "import {\n CallHandler,\n createParamDecorator,\n ExecutionContext,\n Injectable,\n InternalServerErrorException,\n Nest"
},
{
"path": "nest-cli.json",
"chars": 142,
"preview": "{\n \"collection\": \"@nestjs/schematics\",\n \"sourceRoot\": \"example/src\",\n \"compilerOptions\": {\n \"plugins\": [\"@nestjs/g"
},
{
"path": "package.json",
"chars": 1784,
"preview": "{\r\n \"name\": \"nestjs-dataloader\",\r\n \"version\": \"2.0.6\",\r\n \"description\": \"A NestJS decorator for dataloader\",\r\n \"lice"
},
{
"path": "tsconfig.json",
"chars": 375,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"commonjs\",\n \"declaration\": true,\n \"removeComments\": false,\n \"emitDecora"
}
]
About this extraction
This page contains the full source code of the krislefeber/nestjs-dataloader GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 20 files (17.5 KB), approximately 4.9k tokens, and a symbol index with 17 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.