├── .github └── workflows │ ├── release.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── ava.config.js ├── demo ├── index.ts ├── knex.ts ├── package.json └── yarn.lock ├── docker-compose.yml ├── package.json ├── src ├── BatchLoader.ts ├── SelectionFilter.ts ├── index.ts └── loaders │ ├── BaseLoaderProps.ts │ ├── createBelongsToLoader.ts │ ├── createHasManyLoader.ts │ ├── createHasManyLoaderWithPage.ts │ ├── createHasManyThroughLoader.ts │ ├── createHasManyThroughLoaderWithPage.ts │ ├── createManyToManyLoader.ts │ └── createManyToManyLoaderWithPage.ts ├── tests ├── BatchLoader.test.ts ├── SelectionFilter.test.ts ├── fixtures.json ├── globalHooks.ts ├── integration.test.ts ├── knex.ts ├── snapshots │ ├── BatchLoader.test.ts.md │ ├── BatchLoader.test.ts.snap │ ├── SelectionFilter.test.ts.md │ ├── SelectionFilter.test.ts.snap │ ├── integration.test.ts.md │ └── integration.test.ts.snap └── util.ts ├── tools └── generate-fixture.ts ├── tsconfig.json ├── tsconfig.prod.json └── yarn.lock /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: ["v*"] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 12.x 15 | - uses: actions/cache@master 16 | with: 17 | path: | 18 | node_modules 19 | key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} 20 | - run: | 21 | test -n "$NPM_TOKEN" 22 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc 23 | yarn install 24 | npm publish 25 | env: 26 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: {} 5 | 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v1 12 | with: 13 | node-version: 14.x 14 | - uses: actions/cache@master 15 | with: 16 | key: v1-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} 17 | path: node_modules 18 | - run: docker-compose up -d 19 | - run: sleep 20 20 | - run: yarn install 21 | - run: cd demo && yarn install 22 | - run: yarn tsc 23 | - run: yarn test 24 | 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kay Gosho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # knex-graphql-utils 2 | 3 | [![npm version](https://badge.fury.io/js/knex-graphql-utils.svg)](https://badge.fury.io/js/knex-graphql-utils) 4 | [![test](https://github.com/acro5piano/knex-graphql-utils/actions/workflows/test.yml/badge.svg)](https://github.com/acro5piano/knex-graphql-utils/actions/workflows/test.yml) 5 | [![release](https://github.com/acro5piano/knex-graphql-utils/actions/workflows/release.yml/badge.svg)](https://github.com/acro5piano/knex-graphql-utils/actions/workflows/release.yml) 6 | 7 | Set of useful functions for Knex + GraphQL. 8 | 9 | - **BatchLoader** Loads and paginates relationship without N+1 problem. 10 | - **SelectionFilter** Filters selected columns based on GraphQL field selection set. 11 | 12 | **Note: Only PostgreSQL is supported for now** 13 | 14 | # tl;dr 15 | 16 | ### Before 17 | 18 | ![image](https://user-images.githubusercontent.com/10719495/126906832-f991dd7d-b563-4fa2-9313-738f476d46c8.png) 19 | 20 | ### After 21 | 22 | ![image](https://user-images.githubusercontent.com/10719495/126906862-71b456bd-82da-46d1-b6d3-acd1c3233885.png) 23 | 24 | # Motivation 25 | 26 | Creating a GraphQL service with a Relational Database is a hard thing. We should take care of: 27 | 28 | - Performance for querying relations. N+1 problem will happen if you don't use Dataloader. 29 | - `select *` make your server slow, but hard to filter columns based on requests. 30 | - Pagination. [Dataloader pattern is hard to implement pagination](https://github.com/graphql/dataloader/issues/231) without a hacky `union` or window functions. `knex-graphql-utils` uses `row_number()` window function to do it. 31 | 32 | With `knex-graphql-utils`, You can build performant GraphQL servers without hassle. 33 | 34 | # Install 35 | 36 | ``` 37 | npm install --save knex-graphql-utils 38 | ``` 39 | 40 | Or if you use Yarn: 41 | 42 | ``` 43 | yarn add knex-graphql-utils 44 | ``` 45 | 46 | # Getting Started 47 | 48 | In this example, I use `mercurius` but this can be applied to any GraphQL frameworks. 49 | 50 | ```typescript 51 | // app.ts 52 | 53 | import Fastify from 'fastify' 54 | import mercurius from 'mercurius' 55 | import { BatchLoader, SelectionFilter } from 'knex-graphql-utils' 56 | 57 | import { knex } from './knex' // Your knex instance 58 | 59 | const app = Fastify() 60 | 61 | const schema = ` 62 | type Query { 63 | user: User 64 | } 65 | type User { 66 | id: ID! 67 | name: String! 68 | posts(page: Int!): [Post!]! 69 | } 70 | type Post { 71 | id: ID! 72 | title: String! 73 | user: User! 74 | } 75 | ` 76 | 77 | const selectionFilter = new SelectionFilter(knex) 78 | 79 | const resolvers = { 80 | Query: { 81 | user: (user, args, ctx, info) => 82 | knex('users') 83 | .select(selectionFilter.reduce({ info, table: 'users' })) 84 | .first(), 85 | }, 86 | User: { 87 | posts: (user, args, ctx) => 88 | ctx.batchLoader 89 | .getLoader({ 90 | type: 'hasMany', 91 | foreignKey: 'userId', 92 | targetTable: 'posts', 93 | page: { 94 | offset: ((args.page || 1) - 1) * 10, 95 | limit: 10, 96 | }, 97 | orderBy: ['createdAt', 'asc'], 98 | queryModifier: (query) => { 99 | query.select(selectionFilter.reduce({ info, table: 'posts' })) 100 | }, 101 | }) 102 | .load(user.id), 103 | }, 104 | Post: { 105 | user: (post, _args, ctx, info) => 106 | ctx.batchLoader 107 | .getLoader({ 108 | type: 'belongsTo', 109 | foreignKey: 'userId', 110 | targetTable: 'users', 111 | queryModifier: (query) => { 112 | query.select(selectionFilter.reduce({ info, table: 'users' })) 113 | }, 114 | }) 115 | .load(post.userId), 116 | }, 117 | } 118 | 119 | app.register(mercurius, { 120 | schema, 121 | resolvers, 122 | context: () => ({ 123 | batchLoader: new BatchLoader(knex), 124 | }), 125 | }) 126 | 127 | app.listen(8877).then(async () => { 128 | await selectionFilter.prepare(['users', 'posts'], /(_id)|(Id)$/) 129 | }) 130 | ``` 131 | 132 | # Integrate `BatchLoader` and `SelectionFilter` 133 | 134 | You can tell `BatchLoader` to use `SelectionFilter`, and the loader automatically reduces the selection based on `info`. 135 | 136 | ```typescript 137 | import { BatchLoader, SelectionFilter } from 'knex-graphql-utils' 138 | 139 | import { knex } from './knex' // Your knex instance 140 | 141 | const selectionFilter = new SelectionFilter(knex) 142 | const context = { 143 | batchLoader: new BatchLoader(knex).useSelectionFilter(selectionFilter), // Attach SelectionFilter into batch loader 144 | } 145 | 146 | const resolver = { 147 | User: { 148 | posts: (user, args, ctx, info) => 149 | ctx.batchLoader 150 | .getLoader({ 151 | type: 'hasMany', 152 | foreignKey: 'userId', 153 | targetTable: 'posts', 154 | info, // By passing `info`, loader automatically reduces the selection 155 | }) 156 | .load(user.id), 157 | }, 158 | } 159 | 160 | await selectionFilter.prepare(['users'], /_id/) 161 | ``` 162 | 163 | # Limitation & Todo 164 | 165 | - Only PostgreSQL is supported for now. 166 | - Primary key is always assumed to be `id`. 167 | - Add `where` clause with paginating relationship. 168 | 169 | # Further reading 170 | 171 | For more details, please visit [demo](https://github.com/acro5piano/knex-graphql-utils/blob/master/demo/index.ts) and [unit tests](https://github.com/acro5piano/knex-graphql-utils/blob/master/tests/BatchLoader.test.ts). 172 | -------------------------------------------------------------------------------- /ava.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | extensions: ['ts'], 3 | require: ['esbuild-register', './tests/globalHooks.ts'], 4 | files: ['tests/**/*.test.ts'], 5 | } 6 | -------------------------------------------------------------------------------- /demo/index.ts: -------------------------------------------------------------------------------- 1 | import Fastify from 'fastify' 2 | import { GraphQLResolveInfo } from 'graphql' 3 | import mercurius from 'mercurius' 4 | // import { BatchLoader, SelectionFilter } from 'knex-graphql-utils' 5 | import { BatchLoader, SelectionFilter } from '../src' 6 | import { users, posts } from '../tests/fixtures.json' 7 | import { knexLittleLogger } from 'knex-little-logger' 8 | 9 | import { knex } from './knex' // Your knex instance 10 | import type { Knex } from 'knex' 11 | 12 | const app = Fastify() 13 | 14 | const gql = String.raw 15 | 16 | const schema = gql` 17 | type Query { 18 | users: [User!]! 19 | user: User 20 | usersWithoutLib: [User!]! 21 | } 22 | type User { 23 | id: ID! 24 | name: String 25 | posts(page: Int = 1): [Post!]! 26 | postsWithoutLib(page: Int = 1): [Post!]! 27 | createdAt: String! 28 | } 29 | type Post { 30 | id: ID! 31 | title: String 32 | user: User! 33 | userWithoutLib: User! 34 | } 35 | ` 36 | 37 | const selectionFilter = new SelectionFilter(knex) 38 | 39 | const resolvers = { 40 | Query: { 41 | users: (_root: any, _args: any, _ctx: any, info: GraphQLResolveInfo) => 42 | knex('users') 43 | .select(selectionFilter.reduce({ info, table: 'users' })) 44 | .limit(10), 45 | usersWithoutLib: () => knex('users').limit(10), 46 | user: (_root: any, _args: any, _ctx: any, info: GraphQLResolveInfo) => 47 | knex('users') 48 | .select(selectionFilter.reduce({ info, table: 'users' })) 49 | .first(), 50 | }, 51 | User: { 52 | postsWithoutLib: (user: any, args: any) => 53 | knex('posts') 54 | .where({ userId: user.id }) 55 | .offset(((args.page || 1) - 1) * 10) 56 | .limit(10), 57 | posts: (user: any, args: any, ctx: any, info: GraphQLResolveInfo) => 58 | ctx.batchLoader 59 | .getLoader({ 60 | type: 'hasMany', 61 | foreignKey: 'userId', 62 | targetTable: 'posts', 63 | page: { 64 | offset: ((args.page || 1) - 1) * 10, 65 | limit: 10, 66 | }, 67 | orderBy: ['createdAt', 'asc'], 68 | queryModifier: (query: Knex) => { 69 | query.select(selectionFilter.reduce({ info, table: 'posts' })) 70 | }, 71 | }) 72 | .load(user.id), 73 | }, 74 | Post: { 75 | user: (post: any, _args: any, ctx: any, info: GraphQLResolveInfo) => 76 | ctx.batchLoader 77 | .getLoader({ 78 | type: 'belongsTo', 79 | foreignKey: 'userId', 80 | targetTable: 'users', 81 | queryModifier: (query: Knex) => { 82 | query.select(selectionFilter.reduce({ info, table: 'users' })) 83 | }, 84 | }) 85 | .load(post.userId), 86 | userWithoutLib: (post: any) => knex('users').where({ id: post.id }).first(), 87 | }, 88 | } 89 | 90 | app.register(mercurius, { 91 | schema, 92 | resolvers, 93 | context: () => ({ 94 | batchLoader: new BatchLoader(knex), 95 | }), 96 | graphiql: true, 97 | }) 98 | 99 | app.listen(8877).then(async () => { 100 | await knex.raw(` 101 | DROP SCHEMA public CASCADE; 102 | CREATE SCHEMA public; 103 | CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 104 | `) 105 | await knex.schema.createTable('users', (t) => { 106 | t.uuid('id').primary().defaultTo(knex.raw('uuid_generate_v4()')) 107 | t.string('name').notNullable() 108 | t.string('email') 109 | t.timestamps(true, true) 110 | }) 111 | await knex.schema.createTable('posts', (t) => { 112 | t.uuid('id').primary().defaultTo(knex.raw('uuid_generate_v4()')) 113 | t.uuid('user_id').notNullable().references('users.id').onDelete('CASCADE') 114 | t.string('title').notNullable() 115 | t.timestamps(true, true) 116 | }) 117 | await selectionFilter.prepare(['users', 'posts'], /(_id)|(Id)$/) 118 | 119 | await knex('users').insert(users) 120 | await knex('posts').insert(posts) 121 | 122 | knexLittleLogger(knex, { bindings: false }) 123 | 124 | console.log('\n=> Open http://localhost:8877/graphiql') 125 | }) 126 | -------------------------------------------------------------------------------- /demo/knex.ts: -------------------------------------------------------------------------------- 1 | import createKnex from 'knex' 2 | 3 | const knexStringcase = require('knex-stringcase') 4 | 5 | export const knex = createKnex( 6 | knexStringcase({ 7 | client: 'pg', 8 | connection: 'postgres://postgres:postgres@127.0.0.1:11155/postgres', 9 | }), 10 | ) 11 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "fastify": "^3.19.2", 8 | "knex": "^0.95.7", 9 | "knex-graphql-utils": "^0.0.6", 10 | "knex-little-logger": "^0.0.2", 11 | "knex-stringcase": "^1.4.5", 12 | "mercurius": "^8.1.0" 13 | }, 14 | "devDependencies": { 15 | "esbuild-register": "^2.6.0", 16 | "typescript": "^4.3.5" 17 | }, 18 | "scripts": { 19 | "start": "node -r esbuild-register index.ts" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@fastify/ajv-compiler@^1.0.0": 6 | version "1.1.0" 7 | resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz#5ce80b1fc8bebffc8c5ba428d5e392d0f9ed10a1" 8 | integrity sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg== 9 | dependencies: 10 | ajv "^6.12.6" 11 | 12 | "@types/isomorphic-form-data@^2.0.0": 13 | version "2.0.0" 14 | resolved "https://registry.yarnpkg.com/@types/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz#2bc88aeada19313027c273fcba7b24823556069c" 15 | integrity sha512-A8DxJ9mtMuWuKIQImQkz+hewSFLbvUPtSVl32rHAdL+22Xn0CWPvk2zjuWSFOM8+p/YYoB5MmQThcJshp3no7A== 16 | dependencies: 17 | form-data "^2.5.1" 18 | 19 | abstract-logging@^2.0.0: 20 | version "2.0.1" 21 | resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" 22 | integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== 23 | 24 | aggregate-error@^3.0.0: 25 | version "3.1.0" 26 | resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" 27 | integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== 28 | dependencies: 29 | clean-stack "^2.0.0" 30 | indent-string "^4.0.0" 31 | 32 | ajv@^6.11.0, ajv@^6.12.2, ajv@^6.12.6: 33 | version "6.12.6" 34 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 35 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 36 | dependencies: 37 | fast-deep-equal "^3.1.1" 38 | fast-json-stable-stringify "^2.0.0" 39 | json-schema-traverse "^0.4.1" 40 | uri-js "^4.2.2" 41 | 42 | ansi-styles@^4.1.0: 43 | version "4.3.0" 44 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 45 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 46 | dependencies: 47 | color-convert "^2.0.1" 48 | 49 | archy@^1.0.0: 50 | version "1.0.0" 51 | resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" 52 | integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= 53 | 54 | array.prototype.map@^1.0.3: 55 | version "1.0.3" 56 | resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.3.tgz#1609623618d3d84134a37d4a220030c2bd18420b" 57 | integrity sha512-nNcb30v0wfDyIe26Yif3PcV1JXQp4zEeEfupG7L4SRjnD6HLbO5b2a7eVSba53bOx4YCHYMBHt+Fp4vYstneRA== 58 | dependencies: 59 | call-bind "^1.0.0" 60 | define-properties "^1.1.3" 61 | es-abstract "^1.18.0-next.1" 62 | es-array-method-boxes-properly "^1.0.0" 63 | is-string "^1.0.5" 64 | 65 | asynckit@^0.4.0: 66 | version "0.4.0" 67 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 68 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 69 | 70 | atomic-sleep@^1.0.0: 71 | version "1.0.0" 72 | resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" 73 | integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== 74 | 75 | avvio@^7.1.2: 76 | version "7.2.2" 77 | resolved "https://registry.yarnpkg.com/avvio/-/avvio-7.2.2.tgz#58e00e7968870026cd7b7d4f689d596db629e251" 78 | integrity sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw== 79 | dependencies: 80 | archy "^1.0.0" 81 | debug "^4.0.0" 82 | fastq "^1.6.1" 83 | queue-microtask "^1.1.2" 84 | 85 | balanced-match@^1.0.0: 86 | version "1.0.2" 87 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 88 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 89 | 90 | brace-expansion@^1.1.7: 91 | version "1.1.11" 92 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 93 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 94 | dependencies: 95 | balanced-match "^1.0.0" 96 | concat-map "0.0.1" 97 | 98 | call-bind@^1.0.0, call-bind@^1.0.2: 99 | version "1.0.2" 100 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 101 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 102 | dependencies: 103 | function-bind "^1.1.1" 104 | get-intrinsic "^1.0.2" 105 | 106 | chalk@^4.1.1: 107 | version "4.1.1" 108 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" 109 | integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== 110 | dependencies: 111 | ansi-styles "^4.1.0" 112 | supports-color "^7.1.0" 113 | 114 | clean-stack@^2.0.0: 115 | version "2.2.0" 116 | resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" 117 | integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== 118 | 119 | color-convert@^2.0.1: 120 | version "2.0.1" 121 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 122 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 123 | dependencies: 124 | color-name "~1.1.4" 125 | 126 | color-name@~1.1.4: 127 | version "1.1.4" 128 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 129 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 130 | 131 | colorette@1.2.1: 132 | version "1.2.1" 133 | resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" 134 | integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== 135 | 136 | combined-stream@^1.0.6: 137 | version "1.0.8" 138 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 139 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 140 | dependencies: 141 | delayed-stream "~1.0.0" 142 | 143 | commander@^7.1.0: 144 | version "7.2.0" 145 | resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" 146 | integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== 147 | 148 | concat-map@0.0.1: 149 | version "0.0.1" 150 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 151 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 152 | 153 | content-disposition@^0.5.3: 154 | version "0.5.3" 155 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" 156 | integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== 157 | dependencies: 158 | safe-buffer "5.1.2" 159 | 160 | cookie@^0.4.0: 161 | version "0.4.1" 162 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" 163 | integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== 164 | 165 | dataloader@^2.0.0: 166 | version "2.0.0" 167 | resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" 168 | integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ== 169 | 170 | debug@2.6.9: 171 | version "2.6.9" 172 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 173 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 174 | dependencies: 175 | ms "2.0.0" 176 | 177 | debug@4.3.2, debug@^4.0.0: 178 | version "4.3.2" 179 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" 180 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== 181 | dependencies: 182 | ms "2.1.2" 183 | 184 | deepmerge@^4.2.2: 185 | version "4.2.2" 186 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" 187 | integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== 188 | 189 | define-properties@^1.1.3: 190 | version "1.1.3" 191 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 192 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== 193 | dependencies: 194 | object-keys "^1.0.12" 195 | 196 | delayed-stream@~1.0.0: 197 | version "1.0.0" 198 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 199 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 200 | 201 | depd@~1.1.2: 202 | version "1.1.2" 203 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 204 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 205 | 206 | destroy@~1.0.4: 207 | version "1.0.4" 208 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 209 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 210 | 211 | ee-first@1.1.1: 212 | version "1.1.1" 213 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 214 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 215 | 216 | encodeurl@~1.0.2: 217 | version "1.0.2" 218 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 219 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 220 | 221 | encoding-negotiator@^2.0.1: 222 | version "2.0.1" 223 | resolved "https://registry.yarnpkg.com/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz#79871bb5473b81f6a0670e8de5303fb5ee0868a3" 224 | integrity sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ== 225 | 226 | end-of-stream@^1.4.4: 227 | version "1.4.4" 228 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 229 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 230 | dependencies: 231 | once "^1.4.0" 232 | 233 | es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: 234 | version "1.18.3" 235 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.3.tgz#25c4c3380a27aa203c44b2b685bba94da31b63e0" 236 | integrity sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw== 237 | dependencies: 238 | call-bind "^1.0.2" 239 | es-to-primitive "^1.2.1" 240 | function-bind "^1.1.1" 241 | get-intrinsic "^1.1.1" 242 | has "^1.0.3" 243 | has-symbols "^1.0.2" 244 | is-callable "^1.2.3" 245 | is-negative-zero "^2.0.1" 246 | is-regex "^1.1.3" 247 | is-string "^1.0.6" 248 | object-inspect "^1.10.3" 249 | object-keys "^1.1.1" 250 | object.assign "^4.1.2" 251 | string.prototype.trimend "^1.0.4" 252 | string.prototype.trimstart "^1.0.4" 253 | unbox-primitive "^1.0.1" 254 | 255 | es-array-method-boxes-properly@^1.0.0: 256 | version "1.0.0" 257 | resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" 258 | integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== 259 | 260 | es-get-iterator@^1.0.2: 261 | version "1.1.2" 262 | resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" 263 | integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== 264 | dependencies: 265 | call-bind "^1.0.2" 266 | get-intrinsic "^1.1.0" 267 | has-symbols "^1.0.1" 268 | is-arguments "^1.1.0" 269 | is-map "^2.0.2" 270 | is-set "^2.0.2" 271 | is-string "^1.0.5" 272 | isarray "^2.0.5" 273 | 274 | es-to-primitive@^1.2.1: 275 | version "1.2.1" 276 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" 277 | integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== 278 | dependencies: 279 | is-callable "^1.1.4" 280 | is-date-object "^1.0.1" 281 | is-symbol "^1.0.2" 282 | 283 | esbuild-register@^2.6.0: 284 | version "2.6.0" 285 | resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-2.6.0.tgz#9f19a54c82be751dd87673d6a66d7b9e1cdd8498" 286 | integrity sha512-2u4AtnCXP5nivtIxZryiZOUcEQkOzFS7UhAqibUEmaTAThJ48gDLYTBF/Fsz+5r0hbV1jrFE6PQvPDUrKZNt/Q== 287 | dependencies: 288 | esbuild "^0.12.8" 289 | jsonc-parser "^3.0.0" 290 | 291 | esbuild@^0.12.8: 292 | version "0.12.15" 293 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.15.tgz#9d99cf39aeb2188265c5983e983e236829f08af0" 294 | integrity sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw== 295 | 296 | escalade@^3.1.1: 297 | version "3.1.1" 298 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 299 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 300 | 301 | escape-html@~1.0.3: 302 | version "1.0.3" 303 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 304 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 305 | 306 | esm@^3.2.25: 307 | version "3.2.25" 308 | resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" 309 | integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== 310 | 311 | etag@~1.8.1: 312 | version "1.8.1" 313 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 314 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= 315 | 316 | events.on@^1.0.1: 317 | version "1.0.1" 318 | resolved "https://registry.yarnpkg.com/events.on/-/events.on-1.0.1.tgz#9fe6c69c0c5da10d4988eeffc476f6f9eeb540a3" 319 | integrity sha512-yT4htzImIQAf7mFV3heqTRNVwysZIgQjrribiCYQk152gcG6shz/WU/6xVGr0oDzkzcDPhMcCYy4lEKBiadSRA== 320 | 321 | fast-decode-uri-component@^1.0.1: 322 | version "1.0.1" 323 | resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" 324 | integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== 325 | 326 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 327 | version "3.1.3" 328 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 329 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 330 | 331 | fast-json-stable-stringify@^2.0.0: 332 | version "2.1.0" 333 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 334 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 335 | 336 | fast-json-stringify@^1.13.0: 337 | version "1.21.0" 338 | resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-1.21.0.tgz#51bc8c6d77d8c7b2cc7e5fa754f7f909f9e1262f" 339 | integrity sha512-xY6gyjmHN3AK1Y15BCbMpeO9+dea5ePVsp3BouHCdukcx0hOHbXwFhRodhcI0NpZIgDChSeAKkHW9YjKvhwKBA== 340 | dependencies: 341 | ajv "^6.11.0" 342 | deepmerge "^4.2.2" 343 | string-similarity "^4.0.1" 344 | 345 | fast-json-stringify@^2.5.2: 346 | version "2.7.7" 347 | resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.7.tgz#9e1c0f238f566559c3d4b99ae17a8e545381c16e" 348 | integrity sha512-2kiwC/hBlK7QiGALsvj0QxtYwaReLOmAwOWJIxt5WHBB9EwXsqbsu8LCel47yh8NV8CEcFmnZYcXh4BionJcwQ== 349 | dependencies: 350 | ajv "^6.11.0" 351 | deepmerge "^4.2.2" 352 | rfdc "^1.2.0" 353 | string-similarity "^4.0.1" 354 | 355 | fast-redact@^3.0.0: 356 | version "3.0.1" 357 | resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.1.tgz#d6015b971e933d03529b01333ba7f22c29961e92" 358 | integrity sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw== 359 | 360 | fast-safe-stringify@^2.0.8: 361 | version "2.0.8" 362 | resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f" 363 | integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== 364 | 365 | fastify-error@^0.3.0, fastify-error@^0.3.1: 366 | version "0.3.1" 367 | resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" 368 | integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== 369 | 370 | fastify-plugin@^3.0.0: 371 | version "3.0.0" 372 | resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.0.tgz#cf1b8c8098e3b5a7c8c30e6aeb06903370c054ca" 373 | integrity sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w== 374 | 375 | fastify-static@^4.2.2: 376 | version "4.2.2" 377 | resolved "https://registry.yarnpkg.com/fastify-static/-/fastify-static-4.2.2.tgz#48bd75bf23f2fb983395ce992a92448d78fe88bb" 378 | integrity sha512-C631EuGdMlUzFXuuP4SqXBoQEiit9S0uYRd97cF2mFhgStvZvQKIjtzUk/GMQu6EfEdm0ddj3UAc0C6dVeNyKA== 379 | dependencies: 380 | content-disposition "^0.5.3" 381 | encoding-negotiator "^2.0.1" 382 | fastify-plugin "^3.0.0" 383 | glob "^7.1.4" 384 | readable-stream "^3.4.0" 385 | send "^0.17.1" 386 | 387 | fastify-warning@^0.2.0: 388 | version "0.2.0" 389 | resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" 390 | integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== 391 | 392 | fastify-websocket@^3.2.0: 393 | version "3.2.0" 394 | resolved "https://registry.yarnpkg.com/fastify-websocket/-/fastify-websocket-3.2.0.tgz#69421740671cec95f2001a9dccd393c923d482c0" 395 | integrity sha512-O1I04Y6aV2rkO+RRMYQzIe2h7omA20p+Nk/HAdJmfHvNErY7OCani06+rDMmQCKYbZT6RWrsy13U+GrJPhSO6Q== 396 | dependencies: 397 | fastify-plugin "^3.0.0" 398 | ws "^7.4.2" 399 | 400 | fastify@^3.19.2: 401 | version "3.19.2" 402 | resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.19.2.tgz#4e592835183a83f5b797897312a1a84eb6ff861d" 403 | integrity sha512-s9naCdC0V1ynEzxMoe/0oX8XgcLk90VAnIms4z6KcF7Rpn1XiguoMyZSviTmv1x5rgy/OjGGBM45sNpMoBzCUQ== 404 | dependencies: 405 | "@fastify/ajv-compiler" "^1.0.0" 406 | abstract-logging "^2.0.0" 407 | avvio "^7.1.2" 408 | fast-json-stringify "^2.5.2" 409 | fastify-error "^0.3.0" 410 | fastify-warning "^0.2.0" 411 | find-my-way "^4.0.0" 412 | flatstr "^1.0.12" 413 | light-my-request "^4.2.0" 414 | pino "^6.13.0" 415 | proxy-addr "^2.0.7" 416 | readable-stream "^3.4.0" 417 | rfdc "^1.1.4" 418 | secure-json-parse "^2.0.0" 419 | semver "^7.3.2" 420 | tiny-lru "^7.0.0" 421 | 422 | fastparallel@^2.3.0: 423 | version "2.4.0" 424 | resolved "https://registry.yarnpkg.com/fastparallel/-/fastparallel-2.4.0.tgz#65fbec1a5e5902494be772cf5765cbaaece08688" 425 | integrity sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ== 426 | dependencies: 427 | reusify "^1.0.4" 428 | xtend "^4.0.2" 429 | 430 | fastq@^1.6.1: 431 | version "1.11.1" 432 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" 433 | integrity sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw== 434 | dependencies: 435 | reusify "^1.0.4" 436 | 437 | find-my-way@^4.0.0: 438 | version "4.3.3" 439 | resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.3.3.tgz#2ab3880a03bcaa8594548d66b0cd1c5a6e98dd44" 440 | integrity sha512-5E4bRdaATB1MewjOCBjx4xvD205a4t2ripCnXB+YFhYEJ0NABtrcC7XLXLq0TPoFe/WYGUFqys3Qk3HCOGeNcw== 441 | dependencies: 442 | fast-decode-uri-component "^1.0.1" 443 | fast-deep-equal "^3.1.3" 444 | safe-regex2 "^2.0.0" 445 | semver-store "^0.3.0" 446 | 447 | flatstr@^1.0.12: 448 | version "1.0.12" 449 | resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" 450 | integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== 451 | 452 | form-data@^2.5.1: 453 | version "2.5.1" 454 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" 455 | integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== 456 | dependencies: 457 | asynckit "^0.4.0" 458 | combined-stream "^1.0.6" 459 | mime-types "^2.1.12" 460 | 461 | forwarded@0.2.0: 462 | version "0.2.0" 463 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 464 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 465 | 466 | fresh@0.5.2: 467 | version "0.5.2" 468 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 469 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 470 | 471 | fs.realpath@^1.0.0: 472 | version "1.0.0" 473 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 474 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 475 | 476 | function-bind@^1.1.1: 477 | version "1.1.1" 478 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 479 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 480 | 481 | generate-function@^2.3.1: 482 | version "2.3.1" 483 | resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" 484 | integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== 485 | dependencies: 486 | is-property "^1.0.2" 487 | 488 | get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: 489 | version "1.1.1" 490 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" 491 | integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== 492 | dependencies: 493 | function-bind "^1.1.1" 494 | has "^1.0.3" 495 | has-symbols "^1.0.1" 496 | 497 | getopts@2.2.5: 498 | version "2.2.5" 499 | resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" 500 | integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA== 501 | 502 | glob@^7.1.4: 503 | version "7.1.7" 504 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" 505 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== 506 | dependencies: 507 | fs.realpath "^1.0.0" 508 | inflight "^1.0.4" 509 | inherits "2" 510 | minimatch "^3.0.4" 511 | once "^1.3.0" 512 | path-is-absolute "^1.0.0" 513 | 514 | graphql-fields-list@^2.2.4: 515 | version "2.2.4" 516 | resolved "https://registry.yarnpkg.com/graphql-fields-list/-/graphql-fields-list-2.2.4.tgz#87a0b24345476400cc027c351550e769b4bf5699" 517 | integrity sha512-dhsMajI/7FMeZ8UWJDiw7iZlwacW5eBM02IVJ6IldFNgmVSDeuS+0+wF3ZOB0zcpYl3Q1spuegPLAFKcriPOCw== 518 | 519 | graphql-jit@^0.5.1: 520 | version "0.5.2" 521 | resolved "https://registry.yarnpkg.com/graphql-jit/-/graphql-jit-0.5.2.tgz#f1fe88e106f6e5b6daa43f9f9a021f733697aee6" 522 | integrity sha512-8XNFsdFTUujjqu2q26Vkh4U6ZJ5dKZ2KxtiuCe95VlHK9Xn4+yz1P/nOj7ipZvXhMG4/s2gwoEhkSig9IEoahQ== 523 | dependencies: 524 | fast-json-stringify "^1.13.0" 525 | generate-function "^2.3.1" 526 | json-schema "^0.2.3" 527 | lodash.memoize "^4.1.2" 528 | lodash.merge "4.6.2" 529 | lodash.mergewith "4.6.2" 530 | 531 | graphql@^15.5.1: 532 | version "15.5.1" 533 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad" 534 | integrity sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw== 535 | 536 | has-bigints@^1.0.1: 537 | version "1.0.1" 538 | resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" 539 | integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== 540 | 541 | has-flag@^4.0.0: 542 | version "4.0.0" 543 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 544 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 545 | 546 | has-symbols@^1.0.1, has-symbols@^1.0.2: 547 | version "1.0.2" 548 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" 549 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== 550 | 551 | has@^1.0.3: 552 | version "1.0.3" 553 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 554 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 555 | dependencies: 556 | function-bind "^1.1.1" 557 | 558 | http-errors@~1.7.2: 559 | version "1.7.3" 560 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" 561 | integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== 562 | dependencies: 563 | depd "~1.1.2" 564 | inherits "2.0.4" 565 | setprototypeof "1.1.1" 566 | statuses ">= 1.5.0 < 2" 567 | toidentifier "1.0.0" 568 | 569 | indent-string@^4.0.0: 570 | version "4.0.0" 571 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 572 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 573 | 574 | inflight@^1.0.4: 575 | version "1.0.6" 576 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 577 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 578 | dependencies: 579 | once "^1.3.0" 580 | wrappy "1" 581 | 582 | inherits@2, inherits@2.0.4, inherits@^2.0.3: 583 | version "2.0.4" 584 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 585 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 586 | 587 | interpret@^2.2.0: 588 | version "2.2.0" 589 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" 590 | integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== 591 | 592 | ipaddr.js@1.9.1: 593 | version "1.9.1" 594 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 595 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 596 | 597 | is-arguments@^1.1.0: 598 | version "1.1.0" 599 | resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" 600 | integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== 601 | dependencies: 602 | call-bind "^1.0.0" 603 | 604 | is-bigint@^1.0.1: 605 | version "1.0.2" 606 | resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" 607 | integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== 608 | 609 | is-boolean-object@^1.1.0: 610 | version "1.1.1" 611 | resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.1.tgz#3c0878f035cb821228d350d2e1e36719716a3de8" 612 | integrity sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng== 613 | dependencies: 614 | call-bind "^1.0.2" 615 | 616 | is-callable@^1.1.4, is-callable@^1.2.3: 617 | version "1.2.3" 618 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" 619 | integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== 620 | 621 | is-core-module@^2.2.0: 622 | version "2.5.0" 623 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" 624 | integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== 625 | dependencies: 626 | has "^1.0.3" 627 | 628 | is-date-object@^1.0.1: 629 | version "1.0.4" 630 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.4.tgz#550cfcc03afada05eea3dd30981c7b09551f73e5" 631 | integrity sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A== 632 | 633 | is-map@^2.0.2: 634 | version "2.0.2" 635 | resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" 636 | integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== 637 | 638 | is-negative-zero@^2.0.1: 639 | version "2.0.1" 640 | resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" 641 | integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== 642 | 643 | is-number-object@^1.0.4: 644 | version "1.0.5" 645 | resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.5.tgz#6edfaeed7950cff19afedce9fbfca9ee6dd289eb" 646 | integrity sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw== 647 | 648 | is-property@^1.0.2: 649 | version "1.0.2" 650 | resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" 651 | integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= 652 | 653 | is-regex@^1.1.3: 654 | version "1.1.3" 655 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" 656 | integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== 657 | dependencies: 658 | call-bind "^1.0.2" 659 | has-symbols "^1.0.2" 660 | 661 | is-set@^2.0.2: 662 | version "2.0.2" 663 | resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" 664 | integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== 665 | 666 | is-string@^1.0.5, is-string@^1.0.6: 667 | version "1.0.6" 668 | resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f" 669 | integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w== 670 | 671 | is-symbol@^1.0.2, is-symbol@^1.0.3: 672 | version "1.0.4" 673 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" 674 | integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== 675 | dependencies: 676 | has-symbols "^1.0.2" 677 | 678 | isarray@^2.0.5: 679 | version "2.0.5" 680 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 681 | integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== 682 | 683 | iterate-iterator@^1.0.1: 684 | version "1.0.1" 685 | resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6" 686 | integrity sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw== 687 | 688 | iterate-value@^1.0.2: 689 | version "1.0.2" 690 | resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" 691 | integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== 692 | dependencies: 693 | es-get-iterator "^1.0.2" 694 | iterate-iterator "^1.0.1" 695 | 696 | json-schema-traverse@^0.4.1: 697 | version "0.4.1" 698 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 699 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 700 | 701 | json-schema@^0.2.3: 702 | version "0.2.5" 703 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.5.tgz#97997f50972dd0500214e208c407efa4b5d7063b" 704 | integrity sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ== 705 | 706 | jsonc-parser@^3.0.0: 707 | version "3.0.0" 708 | resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" 709 | integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== 710 | 711 | knex-graphql-utils@^0.0.6: 712 | version "0.0.6" 713 | resolved "https://registry.yarnpkg.com/knex-graphql-utils/-/knex-graphql-utils-0.0.6.tgz#ea404d5698204c567d41c0461236cf13503dc29b" 714 | integrity sha512-GtFD0aj64yQBNgifefwwDkHoe6afxXjvklmAdB3p6jco4EiVhLqOIDSH5uEORNsBUR4JrDZTAjpxSRYeN621TA== 715 | dependencies: 716 | dataloader "^2.0.0" 717 | graphql-fields-list "^2.2.4" 718 | 719 | knex-little-logger@^0.0.2: 720 | version "0.0.2" 721 | resolved "https://registry.yarnpkg.com/knex-little-logger/-/knex-little-logger-0.0.2.tgz#39813a764498ded5320bb2c6ad866088678722fb" 722 | integrity sha512-z30SxZ1lpH3u85/XPdixtq/p/Q3UJU2qRDf7O7ROS6fr/c7GxN3/PQ91iYOcojfKP/HQjF3NVr+lIDA3J8mG3A== 723 | dependencies: 724 | chalk "^4.1.1" 725 | 726 | knex-stringcase@^1.4.5: 727 | version "1.4.5" 728 | resolved "https://registry.yarnpkg.com/knex-stringcase/-/knex-stringcase-1.4.5.tgz#47761c1ca4fffd1d276cab7bc3c1265e3669972a" 729 | integrity sha512-dO8CzBAfxX6HeZ6BP+5KCMn3450MRoz3xsUascogE3OucUIyv/ki/W30YQz15EuAbHr03s9DfgiNlKfAvD+PvQ== 730 | dependencies: 731 | stringcase "^4.3.1" 732 | 733 | knex@^0.95.7: 734 | version "0.95.7" 735 | resolved "https://registry.yarnpkg.com/knex/-/knex-0.95.7.tgz#9c55c60e3c63077013076b54b5b97376d5a70d41" 736 | integrity sha512-J2X79td0NAcreTyWVmmHHretz5Ox705FHywddjkT3esTtmggphjcfDoaXym18xtsLdjzOvEb53WB/58lqcF14w== 737 | dependencies: 738 | colorette "1.2.1" 739 | commander "^7.1.0" 740 | debug "4.3.2" 741 | escalade "^3.1.1" 742 | esm "^3.2.25" 743 | getopts "2.2.5" 744 | interpret "^2.2.0" 745 | lodash "^4.17.21" 746 | pg-connection-string "2.5.0" 747 | rechoir "^0.7.0" 748 | resolve-from "^5.0.0" 749 | tarn "^3.0.1" 750 | tildify "2.0.0" 751 | 752 | light-my-request@^4.2.0: 753 | version "4.4.1" 754 | resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.4.1.tgz#bfa2220316eef4f6465bf2f0667780da6b7f6a71" 755 | integrity sha512-FDNRF2mYjthIRWE7O8d/X7AzDx4otQHl4/QXbu3Q/FRwBFcgb+ZoDaUd5HwN53uQXLAiw76osN+Va0NEaOW6rQ== 756 | dependencies: 757 | ajv "^6.12.2" 758 | cookie "^0.4.0" 759 | fastify-warning "^0.2.0" 760 | readable-stream "^3.6.0" 761 | set-cookie-parser "^2.4.1" 762 | 763 | lodash.memoize@^4.1.2: 764 | version "4.1.2" 765 | resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" 766 | integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= 767 | 768 | lodash.merge@4.6.2: 769 | version "4.6.2" 770 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 771 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 772 | 773 | lodash.mergewith@4.6.2: 774 | version "4.6.2" 775 | resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" 776 | integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== 777 | 778 | lodash@^4.17.21: 779 | version "4.17.21" 780 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 781 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 782 | 783 | lru-cache@^6.0.0: 784 | version "6.0.0" 785 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 786 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 787 | dependencies: 788 | yallist "^4.0.0" 789 | 790 | mercurius@^8.1.0: 791 | version "8.1.0" 792 | resolved "https://registry.yarnpkg.com/mercurius/-/mercurius-8.1.0.tgz#bd5121f952008a3a0c9ca645c62a674070602ab6" 793 | integrity sha512-QOiSmHyz20m8OJiC2dTK4W48fKVsIe+FcuT+iqYHaPuWkWQyxvRGsu7dXP+Lj9Laoer0SGs97+69EWzGIh78UA== 794 | dependencies: 795 | "@types/isomorphic-form-data" "^2.0.0" 796 | end-of-stream "^1.4.4" 797 | events.on "^1.0.1" 798 | fastify-error "^0.3.1" 799 | fastify-plugin "^3.0.0" 800 | fastify-static "^4.2.2" 801 | fastify-websocket "^3.2.0" 802 | graphql "^15.5.1" 803 | graphql-jit "^0.5.1" 804 | mqemitter "^4.4.1" 805 | p-map "^4.0.0" 806 | promise.allsettled "^1.0.4" 807 | readable-stream "^3.6.0" 808 | secure-json-parse "^2.4.0" 809 | single-user-cache "^0.5.0" 810 | tiny-lru "^7.0.6" 811 | undici "^4.1.0" 812 | ws "^7.5.2" 813 | 814 | mime-db@1.48.0: 815 | version "1.48.0" 816 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" 817 | integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== 818 | 819 | mime-types@^2.1.12: 820 | version "2.1.31" 821 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" 822 | integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== 823 | dependencies: 824 | mime-db "1.48.0" 825 | 826 | mime@1.6.0: 827 | version "1.6.0" 828 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 829 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 830 | 831 | minimatch@^3.0.4: 832 | version "3.0.4" 833 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 834 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 835 | dependencies: 836 | brace-expansion "^1.1.7" 837 | 838 | mqemitter@^4.4.1: 839 | version "4.4.1" 840 | resolved "https://registry.yarnpkg.com/mqemitter/-/mqemitter-4.4.1.tgz#4cd2bc7d2fd5f2ba8c0c33ec68a8d70c9ff994ea" 841 | integrity sha512-tXSsyzhsD70Jc7WFz1tjbfczGOAyObMhJ8O15ZFkpDI+g9ENmWFUo5BseAuS9HCxNnFtnMWo4lHh7yDi5CjVTQ== 842 | dependencies: 843 | fastparallel "^2.3.0" 844 | qlobber "^5.0.0" 845 | 846 | ms@2.0.0: 847 | version "2.0.0" 848 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 849 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 850 | 851 | ms@2.1.1: 852 | version "2.1.1" 853 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 854 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== 855 | 856 | ms@2.1.2: 857 | version "2.1.2" 858 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 859 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 860 | 861 | object-inspect@^1.10.3: 862 | version "1.11.0" 863 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" 864 | integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== 865 | 866 | object-keys@^1.0.12, object-keys@^1.1.1: 867 | version "1.1.1" 868 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 869 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 870 | 871 | object.assign@^4.1.2: 872 | version "4.1.2" 873 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" 874 | integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== 875 | dependencies: 876 | call-bind "^1.0.0" 877 | define-properties "^1.1.3" 878 | has-symbols "^1.0.1" 879 | object-keys "^1.1.1" 880 | 881 | on-finished@~2.3.0: 882 | version "2.3.0" 883 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 884 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 885 | dependencies: 886 | ee-first "1.1.1" 887 | 888 | once@^1.3.0, once@^1.4.0: 889 | version "1.4.0" 890 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 891 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 892 | dependencies: 893 | wrappy "1" 894 | 895 | p-map@^4.0.0: 896 | version "4.0.0" 897 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" 898 | integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== 899 | dependencies: 900 | aggregate-error "^3.0.0" 901 | 902 | path-is-absolute@^1.0.0: 903 | version "1.0.1" 904 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 905 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 906 | 907 | path-parse@^1.0.6: 908 | version "1.0.7" 909 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 910 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 911 | 912 | pg-connection-string@2.5.0: 913 | version "2.5.0" 914 | resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" 915 | integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== 916 | 917 | pino-std-serializers@^3.1.0: 918 | version "3.2.0" 919 | resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz#b56487c402d882eb96cd67c257868016b61ad671" 920 | integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== 921 | 922 | pino@^6.13.0: 923 | version "6.13.0" 924 | resolved "https://registry.yarnpkg.com/pino/-/pino-6.13.0.tgz#41810b9be213af6f8f7c23a1b17058d880267e7b" 925 | integrity sha512-mRXSTfa34tbfrWqCIp1sUpZLqBhcoaGapoyxfEwaWwJGMpLijlRdDKIQUyvq4M3DUfFH5vEglwSw8POZYwbThA== 926 | dependencies: 927 | fast-redact "^3.0.0" 928 | fast-safe-stringify "^2.0.8" 929 | flatstr "^1.0.12" 930 | pino-std-serializers "^3.1.0" 931 | quick-format-unescaped "^4.0.3" 932 | sonic-boom "^1.0.2" 933 | 934 | promise.allsettled@^1.0.4: 935 | version "1.0.4" 936 | resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.4.tgz#65e71f2a604082ed69c548b68603294090ee6803" 937 | integrity sha512-o73CbvQh/OnPFShxHcHxk0baXR2a1m4ozb85ha0H14VEoi/EJJLa9mnPfEWJx9RjA9MLfhdjZ8I6HhWtBa64Ag== 938 | dependencies: 939 | array.prototype.map "^1.0.3" 940 | call-bind "^1.0.2" 941 | define-properties "^1.1.3" 942 | es-abstract "^1.18.0-next.2" 943 | get-intrinsic "^1.0.2" 944 | iterate-value "^1.0.2" 945 | 946 | proxy-addr@^2.0.7: 947 | version "2.0.7" 948 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 949 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 950 | dependencies: 951 | forwarded "0.2.0" 952 | ipaddr.js "1.9.1" 953 | 954 | punycode@^2.1.0: 955 | version "2.1.1" 956 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 957 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 958 | 959 | qlobber@^5.0.0: 960 | version "5.0.3" 961 | resolved "https://registry.yarnpkg.com/qlobber/-/qlobber-5.0.3.tgz#24728d6ba5382d502c7e09f6860b95a9c71615cd" 962 | integrity sha512-wW4GTZPePyh0RgOsM18oDyOUlXfurVRgoNyJfS+y7VWPyd0GYhQp5T2tycZFZjonH+hngxIfklGJhTP/ghidgQ== 963 | 964 | queue-microtask@^1.1.2: 965 | version "1.2.3" 966 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 967 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 968 | 969 | quick-format-unescaped@^4.0.3: 970 | version "4.0.3" 971 | resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz#6d6b66b8207aa2b35eef12be1421bb24c428f652" 972 | integrity sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg== 973 | 974 | range-parser@~1.2.1: 975 | version "1.2.1" 976 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 977 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 978 | 979 | readable-stream@^3.4.0, readable-stream@^3.6.0: 980 | version "3.6.0" 981 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 982 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 983 | dependencies: 984 | inherits "^2.0.3" 985 | string_decoder "^1.1.1" 986 | util-deprecate "^1.0.1" 987 | 988 | rechoir@^0.7.0: 989 | version "0.7.1" 990 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" 991 | integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== 992 | dependencies: 993 | resolve "^1.9.0" 994 | 995 | resolve-from@^5.0.0: 996 | version "5.0.0" 997 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 998 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 999 | 1000 | resolve@^1.9.0: 1001 | version "1.20.0" 1002 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" 1003 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== 1004 | dependencies: 1005 | is-core-module "^2.2.0" 1006 | path-parse "^1.0.6" 1007 | 1008 | ret@~0.2.0: 1009 | version "0.2.2" 1010 | resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" 1011 | integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== 1012 | 1013 | reusify@^1.0.4: 1014 | version "1.0.4" 1015 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 1016 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1017 | 1018 | rfdc@^1.1.4, rfdc@^1.2.0: 1019 | version "1.3.0" 1020 | resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" 1021 | integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== 1022 | 1023 | safe-buffer@5.1.2: 1024 | version "5.1.2" 1025 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1026 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1027 | 1028 | safe-buffer@~5.2.0: 1029 | version "5.2.1" 1030 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1031 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1032 | 1033 | safe-regex2@^2.0.0: 1034 | version "2.0.0" 1035 | resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9" 1036 | integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== 1037 | dependencies: 1038 | ret "~0.2.0" 1039 | 1040 | safe-stable-stringify@^1.1.0: 1041 | version "1.1.1" 1042 | resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz#c8a220ab525cd94e60ebf47ddc404d610dc5d84a" 1043 | integrity sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw== 1044 | 1045 | secure-json-parse@^2.0.0, secure-json-parse@^2.4.0: 1046 | version "2.4.0" 1047 | resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" 1048 | integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== 1049 | 1050 | semver-store@^0.3.0: 1051 | version "0.3.0" 1052 | resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" 1053 | integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== 1054 | 1055 | semver@^7.3.2: 1056 | version "7.3.5" 1057 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 1058 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 1059 | dependencies: 1060 | lru-cache "^6.0.0" 1061 | 1062 | send@^0.17.1: 1063 | version "0.17.1" 1064 | resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" 1065 | integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== 1066 | dependencies: 1067 | debug "2.6.9" 1068 | depd "~1.1.2" 1069 | destroy "~1.0.4" 1070 | encodeurl "~1.0.2" 1071 | escape-html "~1.0.3" 1072 | etag "~1.8.1" 1073 | fresh "0.5.2" 1074 | http-errors "~1.7.2" 1075 | mime "1.6.0" 1076 | ms "2.1.1" 1077 | on-finished "~2.3.0" 1078 | range-parser "~1.2.1" 1079 | statuses "~1.5.0" 1080 | 1081 | set-cookie-parser@^2.4.1: 1082 | version "2.4.8" 1083 | resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" 1084 | integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== 1085 | 1086 | setprototypeof@1.1.1: 1087 | version "1.1.1" 1088 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" 1089 | integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== 1090 | 1091 | single-user-cache@^0.5.0: 1092 | version "0.5.0" 1093 | resolved "https://registry.yarnpkg.com/single-user-cache/-/single-user-cache-0.5.0.tgz#87a33e5cc00c7a429c9575b17b99be4770e0a293" 1094 | integrity sha512-PpQ7w+Y67r3wHjWgM/u18oHtzGWGKXr3Z7FvGzarnDsiFadIWkMAvcXWa6AhcRjB2+28KjqhLNok196nssos3Q== 1095 | dependencies: 1096 | safe-stable-stringify "^1.1.0" 1097 | 1098 | sonic-boom@^1.0.2: 1099 | version "1.4.1" 1100 | resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e" 1101 | integrity sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg== 1102 | dependencies: 1103 | atomic-sleep "^1.0.0" 1104 | flatstr "^1.0.12" 1105 | 1106 | "statuses@>= 1.5.0 < 2", statuses@~1.5.0: 1107 | version "1.5.0" 1108 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 1109 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 1110 | 1111 | string-similarity@^4.0.1: 1112 | version "4.0.4" 1113 | resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" 1114 | integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== 1115 | 1116 | string.prototype.trimend@^1.0.4: 1117 | version "1.0.4" 1118 | resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" 1119 | integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== 1120 | dependencies: 1121 | call-bind "^1.0.2" 1122 | define-properties "^1.1.3" 1123 | 1124 | string.prototype.trimstart@^1.0.4: 1125 | version "1.0.4" 1126 | resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" 1127 | integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== 1128 | dependencies: 1129 | call-bind "^1.0.2" 1130 | define-properties "^1.1.3" 1131 | 1132 | string_decoder@^1.1.1: 1133 | version "1.3.0" 1134 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 1135 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 1136 | dependencies: 1137 | safe-buffer "~5.2.0" 1138 | 1139 | stringcase@^4.3.1: 1140 | version "4.3.1" 1141 | resolved "https://registry.yarnpkg.com/stringcase/-/stringcase-4.3.1.tgz#54279c9dd7379ff50f4e47d50d036b2ac888d34b" 1142 | integrity sha512-Ov7McNX1sFaEX9NWijD1hIOVDDhKdnFzN9tvoa1N8xgrclouhsO4kBPVrTPhjO/zP5mn1Ww03uZ2SThNMXS7zg== 1143 | 1144 | supports-color@^7.1.0: 1145 | version "7.2.0" 1146 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1147 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1148 | dependencies: 1149 | has-flag "^4.0.0" 1150 | 1151 | tarn@^3.0.1: 1152 | version "3.0.1" 1153 | resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.1.tgz#ebac2c6dbc6977d34d4526e0a7814200386a8aec" 1154 | integrity sha512-6usSlV9KyHsspvwu2duKH+FMUhqJnAh6J5J/4MITl8s94iSUQTLkJggdiewKv4RyARQccnigV48Z+khiuVZDJw== 1155 | 1156 | tildify@2.0.0: 1157 | version "2.0.0" 1158 | resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a" 1159 | integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw== 1160 | 1161 | tiny-lru@^7.0.0, tiny-lru@^7.0.6: 1162 | version "7.0.6" 1163 | resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" 1164 | integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== 1165 | 1166 | toidentifier@1.0.0: 1167 | version "1.0.0" 1168 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" 1169 | integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== 1170 | 1171 | typescript@^4.3.5: 1172 | version "4.3.5" 1173 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" 1174 | integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== 1175 | 1176 | unbox-primitive@^1.0.1: 1177 | version "1.0.1" 1178 | resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" 1179 | integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== 1180 | dependencies: 1181 | function-bind "^1.1.1" 1182 | has-bigints "^1.0.1" 1183 | has-symbols "^1.0.2" 1184 | which-boxed-primitive "^1.0.2" 1185 | 1186 | undici@^4.1.0: 1187 | version "4.2.2" 1188 | resolved "https://registry.yarnpkg.com/undici/-/undici-4.2.2.tgz#cde98830799191bd4df033ff8658de7d3557a82a" 1189 | integrity sha512-WeLqJE/N66VjFeNawJkWHGB1qBGL3VHeimAEKhOC7lbeCf7p6daUVYUHYFeTo0V1EDlxdzqpzykImadFHjuXgA== 1190 | 1191 | uri-js@^4.2.2: 1192 | version "4.4.1" 1193 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1194 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1195 | dependencies: 1196 | punycode "^2.1.0" 1197 | 1198 | util-deprecate@^1.0.1: 1199 | version "1.0.2" 1200 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1201 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 1202 | 1203 | which-boxed-primitive@^1.0.2: 1204 | version "1.0.2" 1205 | resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" 1206 | integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== 1207 | dependencies: 1208 | is-bigint "^1.0.1" 1209 | is-boolean-object "^1.1.0" 1210 | is-number-object "^1.0.4" 1211 | is-string "^1.0.5" 1212 | is-symbol "^1.0.3" 1213 | 1214 | wrappy@1: 1215 | version "1.0.2" 1216 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1217 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1218 | 1219 | ws@^7.4.2, ws@^7.5.2: 1220 | version "7.5.3" 1221 | resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" 1222 | integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== 1223 | 1224 | xtend@^4.0.2: 1225 | version "4.0.2" 1226 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 1227 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 1228 | 1229 | yallist@^4.0.0: 1230 | version "4.0.0" 1231 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1232 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1233 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3' 3 | services: 4 | db: 5 | image: postgres:13.2-alpine 6 | ports: 7 | - '11155:5432' 8 | environment: 9 | POSTGRES_PASSWORD: postgres 10 | 11 | 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knex-graphql-utils", 3 | "version": "0.0.7", 4 | "main": "dist/index.js", 5 | "repository": "git@github.com:acro5piano/knex-graphql-utils", 6 | "author": "gosho-kazuya ", 7 | "license": "MIT", 8 | "files": [ 9 | "dist/*", 10 | "dist/*.ts" 11 | ], 12 | "scripts": { 13 | "r": "node -r esbuild-register", 14 | "prepare": "rm -f node_modules/graphql-fields-list/index.ts", 15 | "prepublish": "yarn build", 16 | "pgcli": "pgcli postgres://postgres:postgres@127.0.0.1:11155/postgres", 17 | "test": "ava --serial", 18 | "build": "npm-run-all build:*", 19 | "build:rm": "rimraf dist", 20 | "build:rm-lib-ts": "rm -f node_modules/graphql-fields-list/index.ts", 21 | "build:src": "tsc -p tsconfig.prod.json" 22 | }, 23 | "dependencies": { 24 | "dataloader": "^2.0.0", 25 | "graphql-fields-list": "^2.2.4" 26 | }, 27 | "devDependencies": { 28 | "@graphql-tools/schema": "^7.1.5", 29 | "@types/node": "^16.4.1", 30 | "@types/uuid": "^8.3.1", 31 | "ava": "^3.15.0", 32 | "dayjs": "^1.10.6", 33 | "esbuild-register": "^2.6.0", 34 | "graphql": "^15.5.1", 35 | "knex": "^0.95.7", 36 | "knex-little-logger": "^0.0.2", 37 | "knex-stringcase": "^1.4.5", 38 | "npm-run-all": "^4.1.5", 39 | "pg": "^8.6.0", 40 | "remeda": "^0.0.29", 41 | "sqlite3": "^5.0.2", 42 | "typescript": "^4.3.5", 43 | "uuid": "^8.3.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/BatchLoader.ts: -------------------------------------------------------------------------------- 1 | import Dataloader from 'dataloader' 2 | import type { GraphQLResolveInfo } from 'graphql' 3 | import type { Knex } from 'knex' 4 | import type { SelectionFilter } from './SelectionFilter' 5 | import { createHasManyLoaderWithPage } from './loaders/createHasManyLoaderWithPage' 6 | import { createHasManyLoader } from './loaders/createHasManyLoader' 7 | import { createHasManyThroughLoaderWithPage } from './loaders/createHasManyThroughLoaderWithPage' 8 | import { createManyToManyLoader } from './loaders/createManyToManyLoader' 9 | import { createManyToManyLoaderWithPage } from './loaders/createManyToManyLoaderWithPage' 10 | import { createHasManyThroughLoader } from './loaders/createHasManyThroughLoader' 11 | import { createBelongsToLoader } from './loaders/createBelongsToLoader' 12 | 13 | export type SimplePagenatorArgs = { 14 | limit: number 15 | offset: number 16 | } 17 | 18 | export type OrderByType = 'ASC' | 'DESC' | 'asc' | 'desc' 19 | 20 | /** 21 | * LoaderType represents how to load relationships. 22 | * 23 | * - `hasMany` 1:n relationship 24 | * - `belongsTo` n:1 relationship 25 | * - `hasManyThrough` 1:n relationship through an intermeidate table 26 | */ 27 | export type LoaderType = 28 | | 'hasMany' 29 | | 'hasManyThrough' 30 | | 'belongsTo' 31 | | 'manyToMany' 32 | 33 | export interface GetLoaderProps { 34 | /** 35 | * LoaderType represents how to load relationships. 36 | */ 37 | type: LoaderType 38 | 39 | /** 40 | * Target table to load relations from. 41 | * 42 | * @example `targetTable: 'users'` 43 | */ 44 | targetTable: string 45 | 46 | /** 47 | * Foreign key of `targetTable`. By default, it points to `id`. 48 | * 49 | * @example `foreignKey: 'userId'` 50 | */ 51 | foreignKey?: string 52 | 53 | /** 54 | * Foreign key of `targetTable`. By default, it points to `id`. Required for `hasManyThrough` relations. 55 | * 56 | * @example `join: { form: 'posts.userId', to: 'comments.postId' } 57 | */ 58 | join?: { 59 | from: string 60 | to: string 61 | } 62 | 63 | /** 64 | * How to order the relations. Default to `id` ASC. 65 | * 66 | * @example `orderBy: ['createdAt', 'desc']` 67 | */ 68 | orderBy?: [string, OrderByType | undefined] 69 | 70 | /** 71 | * Adds limit and offset to the relations. Default to nothing, meaning that loads all records of the relationship. 72 | * 73 | * @example `page: { limit: 20, offset: 60 }` 74 | */ 75 | page?: SimplePagenatorArgs 76 | 77 | /** 78 | * Modify knex query after load. 79 | * 80 | * @example `queryModifier: query => query.select(knex.raw("count('id')")).groupBy('id')` 81 | */ 82 | queryModifier?: (query: Knex.QueryBuilder) => void 83 | 84 | /** 85 | * Modify knex query for inner subquery while pagination. 86 | * 87 | * @example `subQueryModifier: query => query.where({ type: 'human' })` 88 | */ 89 | subQueryModifier?: (query: Knex.QueryBuilder) => void 90 | 91 | /** 92 | * If you pass `info` and call `useSelectionFilter` before resolving relationship, BatchLoader will reduce column selections on execution. 93 | */ 94 | info?: GraphQLResolveInfo 95 | } 96 | 97 | export interface CreateLoaderProps extends GetLoaderProps { 98 | knex: Knex 99 | selectionFilter?: SelectionFilter 100 | } 101 | 102 | export class BatchLoader { 103 | private loaderMap = new Map>() 104 | private selectionFilter?: SelectionFilter 105 | 106 | constructor(private knex: Knex) {} 107 | 108 | useSelectionFilter(selectionFilter: SelectionFilter) { 109 | this.selectionFilter = selectionFilter 110 | return this 111 | } 112 | 113 | getLoader({ 114 | type, 115 | targetTable, 116 | foreignKey, 117 | join, 118 | page, 119 | queryModifier, 120 | subQueryModifier, 121 | orderBy, 122 | info, 123 | }: GetLoaderProps) { 124 | const key = [ 125 | type, 126 | targetTable, 127 | foreignKey, 128 | orderBy?.[0], 129 | orderBy?.[1], 130 | page?.limit, 131 | page?.offset, 132 | ].join(':') 133 | const maybeLoader = this.loaderMap.get(key) 134 | if (maybeLoader) { 135 | return maybeLoader 136 | } 137 | const loader = createLoader({ 138 | type, 139 | targetTable, 140 | foreignKey, 141 | join, 142 | page, 143 | queryModifier, 144 | subQueryModifier, 145 | orderBy, 146 | knex: this.knex, 147 | selectionFilter: this.selectionFilter, 148 | info, 149 | }) 150 | this.loaderMap.set(key, loader) 151 | return loader 152 | } 153 | } 154 | 155 | function createLoader({ 156 | type, 157 | targetTable, 158 | foreignKey, 159 | join, 160 | page, 161 | knex, 162 | queryModifier, 163 | subQueryModifier, 164 | orderBy = ['id', 'asc'], 165 | selectionFilter, 166 | info, 167 | }: CreateLoaderProps) { 168 | const modifyQuery = (query: Knex.QueryBuilder) => { 169 | if (queryModifier) { 170 | queryModifier(query) 171 | } 172 | if (selectionFilter && info) { 173 | query.select(selectionFilter.reduce({ info, table: targetTable })) 174 | } 175 | } 176 | const [orderByColumn, orderByType = 'ASC'] = orderBy 177 | if ( 178 | orderByType.toUpperCase() !== 'ASC' && 179 | orderByType.toUpperCase() !== 'DESC' 180 | ) { 181 | throw new Error('[BatchLoader] That order by is not supported') 182 | } 183 | 184 | const commonProps = { 185 | targetTable, 186 | orderByColumn, 187 | orderByType, 188 | knex, 189 | modifyQuery, 190 | modifyInnerQuery: subQueryModifier, 191 | } 192 | 193 | switch (type) { 194 | case 'hasMany': 195 | if (!foreignKey) { 196 | throw new Error( 197 | '[BatchLoader] foreignKey is required when loading hasMany relationship.', 198 | ) 199 | } 200 | if (page) { 201 | return createHasManyLoaderWithPage({ 202 | ...commonProps, 203 | page, 204 | foreignKey, 205 | }) 206 | } else { 207 | return createHasManyLoader({ 208 | ...commonProps, 209 | foreignKey, 210 | }) 211 | } 212 | case 'hasManyThrough': 213 | if (!join) { 214 | throw new Error('[BatchLoader] no `join` key found') 215 | } 216 | const [joinTable, joinColumn] = join.from.split('.') 217 | if (!joinTable || !joinColumn) { 218 | throw new Error('[BatchLoader] Invalid `from` key format') 219 | } 220 | if (page) { 221 | return createHasManyThroughLoaderWithPage({ 222 | ...commonProps, 223 | page, 224 | join, 225 | joinColumn, 226 | joinTable, 227 | }) 228 | } else { 229 | return createHasManyThroughLoader({ 230 | ...commonProps, 231 | join, 232 | joinColumn, 233 | joinTable, 234 | }) 235 | } 236 | case 'manyToMany': { 237 | if (!join) { 238 | throw new Error('[BatchLoader] no `join` key found') 239 | } 240 | const [joinTable, joinColumn] = join.from.split('.') 241 | if (!joinTable || !joinColumn) { 242 | throw new Error('[BatchLoader] Invalid `from` key format') 243 | } 244 | if (page) { 245 | return createManyToManyLoaderWithPage({ 246 | ...commonProps, 247 | page, 248 | join, 249 | joinColumn, 250 | joinTable, 251 | }) 252 | } else { 253 | return createManyToManyLoader({ 254 | ...commonProps, 255 | join, 256 | joinColumn, 257 | joinTable, 258 | }) 259 | } 260 | } 261 | case 'belongsTo': 262 | if (page) { 263 | throw new Error( 264 | '[BatchLoader] Do not add `page` option for relation type `belongsTo.`', 265 | ) 266 | } 267 | return createBelongsToLoader({ ...commonProps }) 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/SelectionFilter.ts: -------------------------------------------------------------------------------- 1 | import type { GraphQLResolveInfo } from 'graphql' 2 | import type { Knex } from 'knex' 3 | import { fieldsList } from 'graphql-fields-list' 4 | 5 | export interface FilterSelectionsProps { 6 | info: GraphQLResolveInfo 7 | 8 | /** 9 | * Table to filter columns. 10 | * 11 | * @example `selectionFilter.reduce({ info, table: 'users' })` 12 | */ 13 | table: string 14 | 15 | /** 16 | * By passing `alwaysLoadColumns`, these columns are always loaded. 17 | * This is useful when a column is depends on other columns and loaded by resolvers. 18 | * 19 | * @example `selectionFilter.reduce({ info, table: 'users', alwaysLoadColumns: ['createdAt'] })` 20 | */ 21 | alwaysLoadColumns?: string[] 22 | } 23 | 24 | export interface DatabaseTableInfo { 25 | tableName: string 26 | columns: string[] 27 | referenceColumns: string[] 28 | } 29 | 30 | export class SelectionFilter { 31 | private tableColumnsMap = new Map() 32 | 33 | constructor(private knex: Knex) {} 34 | 35 | /** 36 | * Prepare selection filter. 37 | * Be aware that you should call this method to make selectionFilter work correctly. 38 | * 39 | * @param tableNames: string[] 40 | * Defines tables to inspect. 41 | * @param ignorePattern: RegExp 42 | * If columns matches this pattern, these columns are always loaded. 43 | * This is useful for foreign keys which should not be filtered to load relations after batch loading. 44 | * @example `prepare(['users', 'posts'], /_id$/)` 45 | */ 46 | async prepare(tableNames: string[], ignorePattern: RegExp) { 47 | await Promise.all( 48 | tableNames.map(async (tableName) => { 49 | const rawColumns = await this.knex(tableName).columnInfo() 50 | const columns = Object.keys(rawColumns) 51 | const referenceColumns = columns.filter((col) => 52 | ignorePattern.test(col), 53 | ) 54 | this.tableColumnsMap.set(tableName, { 55 | tableName, 56 | columns, 57 | referenceColumns, 58 | }) 59 | }), 60 | ) 61 | return this 62 | } 63 | 64 | // Alias method 65 | reduce = this.filterGraphQLSelections.bind(this) 66 | 67 | filterGraphQLSelections({ 68 | info, 69 | table, 70 | alwaysLoadColumns = [], 71 | }: FilterSelectionsProps) { 72 | const existingColumns = this.tableColumnsMap.get(table) 73 | if (!existingColumns) { 74 | // Empty array force Knex to select all columns (select `*`) 75 | return [] 76 | } 77 | const selectionSets = fieldsList(info) 78 | if (!selectionSets.includes('id')) { 79 | selectionSets.push('id') 80 | } 81 | 82 | // Always load foreign key to prepare Dataloader 83 | this.tableColumnsMap.forEach((info) => { 84 | selectionSets.push(...info.referenceColumns) 85 | }) 86 | 87 | return [ 88 | ...existingColumns.columns.filter((c) => selectionSets.includes(c)), 89 | ...alwaysLoadColumns, 90 | ] 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BatchLoader' 2 | export * from './SelectionFilter' 3 | -------------------------------------------------------------------------------- /src/loaders/BaseLoaderProps.ts: -------------------------------------------------------------------------------- 1 | import type { CreateLoaderProps, OrderByType } from '../BatchLoader' 2 | import { Knex } from 'knex' 3 | 4 | export type BaseLoaderProps< 5 | TKey extends keyof CreateLoaderProps = 'targetTable', 6 | > = Required> & { 7 | modifyQuery?: (query: Knex.QueryBuilder) => void 8 | modifyInnerQuery?: (query: Knex.QueryBuilder) => void 9 | orderByType?: OrderByType 10 | orderByColumn?: string 11 | } 12 | 13 | export type BaseJoinableLoaderProps< 14 | TKey extends keyof CreateLoaderProps = 'targetTable', 15 | > = BaseLoaderProps<'join' | TKey> & { 16 | joinTable: string 17 | joinColumn: string 18 | } 19 | -------------------------------------------------------------------------------- /src/loaders/createBelongsToLoader.ts: -------------------------------------------------------------------------------- 1 | import type { BaseLoaderProps } from './BaseLoaderProps' 2 | import Dataloader from 'dataloader' 3 | 4 | export function createBelongsToLoader({ 5 | targetTable, 6 | knex, 7 | orderByType, 8 | orderByColumn, 9 | modifyQuery, 10 | }: BaseLoaderProps) { 11 | return new Dataloader((ids: readonly string[]) => { 12 | const query = knex(targetTable).whereIn('id', ids) 13 | 14 | if (orderByColumn && orderByType) { 15 | query.orderBy(orderByColumn, orderByType) 16 | } 17 | if (modifyQuery) { 18 | modifyQuery(query) 19 | } 20 | return query.then((rows) => 21 | ids.map((id) => rows.find((row) => row.id === id)), 22 | ) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /src/loaders/createHasManyLoader.ts: -------------------------------------------------------------------------------- 1 | import type { BaseLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createHasManyLoader({ 6 | targetTable, 7 | foreignKey, 8 | knex, 9 | orderByType, 10 | orderByColumn, 11 | modifyQuery, 12 | }: BaseLoaderProps<'foreignKey'>) { 13 | return new Dataloader((ids: readonly string[]) => { 14 | const query = knex(targetTable).whereIn(foreignKey, ids) 15 | 16 | if (orderByColumn && orderByType) { 17 | query.orderBy(orderByColumn, orderByType) 18 | } 19 | 20 | if (modifyQuery) { 21 | modifyQuery(query) 22 | } 23 | return query.then((rows) => 24 | ids.map((id) => rows.filter((row) => row[foreignKey] === id)), 25 | ) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /src/loaders/createHasManyLoaderWithPage.ts: -------------------------------------------------------------------------------- 1 | import type { BaseLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createHasManyLoaderWithPage({ 6 | targetTable, 7 | foreignKey, 8 | knex, 9 | page, 10 | orderByType, 11 | orderByColumn, 12 | modifyQuery, 13 | modifyInnerQuery, 14 | }: BaseLoaderProps<'page' | 'foreignKey'>) { 15 | return new Dataloader((ids: readonly string[]) => { 16 | const subQuery = knex(targetTable) 17 | .select('*') 18 | .whereIn(foreignKey, ids) 19 | .as('_t') 20 | if (modifyInnerQuery) { 21 | modifyInnerQuery(subQuery) 22 | } 23 | if (orderByType && orderByColumn) { 24 | subQuery.rowNumber( 25 | 'relation_index', 26 | knex.raw(`partition by ?? order by ?? ${orderByType}`, [ 27 | foreignKey, 28 | orderByColumn, 29 | ]), 30 | ) 31 | } else { 32 | subQuery.rowNumber( 33 | 'relation_index', 34 | knex.raw(`partition by ??`, [foreignKey]), 35 | ) 36 | } 37 | const query = knex(subQuery).whereBetween( 38 | knex.ref('relation_index') as any, 39 | [page.offset, page.offset + page.limit], 40 | ) 41 | if (modifyQuery) { 42 | modifyQuery(query) 43 | } 44 | return query.then((rows) => 45 | ids.map((id) => rows.filter((row) => row[foreignKey] === id)), 46 | ) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /src/loaders/createHasManyThroughLoader.ts: -------------------------------------------------------------------------------- 1 | import type { BaseJoinableLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createHasManyThroughLoader({ 6 | targetTable, 7 | knex, 8 | orderByType, 9 | orderByColumn, 10 | modifyQuery, 11 | join, 12 | joinTable, 13 | joinColumn, 14 | }: BaseJoinableLoaderProps) { 15 | return new Dataloader((ids: readonly string[]) => { 16 | const query = knex(targetTable) 17 | .select(`${targetTable}.*`, join.from) 18 | .innerJoin(joinTable, `${joinTable}.id`, join.to) 19 | .whereIn(join.from, ids) 20 | if (orderByColumn && orderByType) { 21 | query.orderBy(orderByColumn, orderByType) 22 | } 23 | if (modifyQuery) { 24 | modifyQuery(query) 25 | } 26 | return query.then((rows) => 27 | ids.map((id) => rows.filter((row) => row[joinColumn] === id)), 28 | ) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /src/loaders/createHasManyThroughLoaderWithPage.ts: -------------------------------------------------------------------------------- 1 | import type { BaseJoinableLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createHasManyThroughLoaderWithPage({ 6 | targetTable, 7 | knex, 8 | page, 9 | orderByType, 10 | orderByColumn, 11 | modifyQuery, 12 | modifyInnerQuery, 13 | join, 14 | joinTable, 15 | joinColumn, 16 | }: BaseJoinableLoaderProps<'page'>) { 17 | return new Dataloader((ids: readonly string[]) => { 18 | const subQuery = knex(targetTable) 19 | .select(`${targetTable}.*`, join.from) 20 | .innerJoin(joinTable, `${joinTable}.id`, join.to) 21 | .whereIn(join.from, ids) 22 | .as('_t') 23 | if (modifyInnerQuery) { 24 | modifyInnerQuery(subQuery) 25 | } 26 | if (orderByType && orderByColumn) { 27 | subQuery.rowNumber( 28 | 'relation_index', 29 | knex.raw(`partition by ?? order by ?? ${orderByType}`, [ 30 | join.from, 31 | orderByColumn, 32 | ]), 33 | ) 34 | } else { 35 | subQuery.rowNumber( 36 | 'relation_index', 37 | knex.raw(`partition by ??`, [join.from]), 38 | ) 39 | } 40 | const query = knex(subQuery).whereBetween( 41 | knex.ref('relation_index') as any, 42 | [page.offset, page.offset + page.limit], 43 | ) 44 | if (modifyQuery) { 45 | modifyQuery(query) 46 | } 47 | return query.then((rows) => 48 | ids.map((id) => rows.filter((row) => row[joinColumn] === id)), 49 | ) 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /src/loaders/createManyToManyLoader.ts: -------------------------------------------------------------------------------- 1 | import type { BaseJoinableLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createManyToManyLoader({ 6 | targetTable, 7 | knex, 8 | orderByType, 9 | orderByColumn, 10 | modifyQuery, 11 | join, 12 | joinTable, 13 | joinColumn, 14 | }: BaseJoinableLoaderProps) { 15 | return new Dataloader((ids: readonly string[]) => { 16 | const query = knex(targetTable) 17 | .select(`${targetTable}.*`, join.from) 18 | .innerJoin(joinTable, `${targetTable}.id`, join.to) 19 | .whereIn(join.from, ids) 20 | if (orderByColumn && orderByType) { 21 | query.orderBy(orderByColumn, orderByType) 22 | } 23 | if (modifyQuery) { 24 | modifyQuery(query) 25 | } 26 | return query.then((rows) => 27 | ids.map((id) => rows.filter((row) => row[joinColumn] === id)), 28 | ) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /src/loaders/createManyToManyLoaderWithPage.ts: -------------------------------------------------------------------------------- 1 | import type { BaseJoinableLoaderProps } from './BaseLoaderProps' 2 | 3 | import Dataloader from 'dataloader' 4 | 5 | export function createManyToManyLoaderWithPage({ 6 | targetTable, 7 | knex, 8 | orderByType, 9 | orderByColumn, 10 | modifyQuery, 11 | join, 12 | joinTable, 13 | joinColumn, 14 | page, 15 | }: BaseJoinableLoaderProps<'page'>) { 16 | return new Dataloader((ids: readonly string[]) => { 17 | const subQuery = knex(targetTable) 18 | .select(`${targetTable}.*`, join.from) 19 | .innerJoin(joinTable, `${targetTable}.id`, join.to) 20 | .whereIn(join.from, ids) 21 | .as('_t') 22 | if (orderByType && orderByColumn) { 23 | subQuery.rowNumber( 24 | 'relation_index', 25 | knex.raw(`partition by ?? order by ?? ${orderByType}`, [ 26 | join.from, 27 | orderByColumn, 28 | ]), 29 | ) 30 | } else { 31 | subQuery.rowNumber( 32 | 'relation_index', 33 | knex.raw(`partition by ??`, [join.from]), 34 | ) 35 | } 36 | const query = knex(subQuery).whereBetween( 37 | knex.ref('relation_index') as any, 38 | [page.offset, page.offset + page.limit], 39 | ) 40 | if (modifyQuery) { 41 | modifyQuery(query) 42 | } 43 | return query.then((rows) => 44 | ids.map((id) => rows.filter((row) => row[joinColumn] === id)), 45 | ) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /tests/BatchLoader.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { knexWithLog } from './knex' 3 | import { users, posts } from './fixtures.json' 4 | import { BatchLoader } from '../src/index' 5 | 6 | test.serial('BatchLoader - hasMany with custom select', async (t) => { 7 | const batchLoader = new BatchLoader(knexWithLog) 8 | const loader = () => 9 | batchLoader.getLoader({ 10 | foreignKey: 'userId', 11 | page: { offset: 5, limit: 10 }, 12 | targetTable: 'posts', 13 | type: 'hasMany', 14 | orderBy: ['createdAt', 'asc'], 15 | queryModifier: (query) => { 16 | query.select('id', 'userId', 'createdAt').orderBy('createdAt') 17 | }, 18 | }) 19 | await Promise.all([ 20 | loader().load(users[0]!.id), 21 | loader().load(users[1]!.id), 22 | ]).then(t.snapshot) 23 | }) 24 | 25 | test.serial('BatchLoader - hasMany with pagination', async (t) => { 26 | const batchLoader = new BatchLoader(knexWithLog) 27 | const loader = () => 28 | batchLoader.getLoader({ 29 | foreignKey: 'userId', 30 | page: { offset: 5, limit: 10 }, 31 | targetTable: 'posts', 32 | type: 'hasMany', 33 | orderBy: ['createdAt', 'asc'], 34 | }) 35 | await Promise.all([ 36 | loader().load(users[0]!.id), 37 | loader().load(users[1]!.id), 38 | loader().load(users[2]!.id), 39 | loader().load(users[3]!.id), 40 | loader().load(users[4]!.id), 41 | ]).then(t.snapshot) 42 | }) 43 | 44 | test.serial( 45 | 'BatchLoader - hasMany with pagination and modifyInnerQuery', 46 | async (t) => { 47 | const batchLoader = new BatchLoader(knexWithLog) 48 | const loader = () => 49 | batchLoader.getLoader({ 50 | foreignKey: 'userId', 51 | page: { offset: 0, limit: 10 }, 52 | targetTable: 'posts', 53 | type: 'hasMany', 54 | orderBy: ['createdAt', 'asc'], 55 | subQueryModifier: (subQuery) => 56 | subQuery.where({ title: "George Washington's post - 1" }), 57 | }) 58 | await Promise.all([ 59 | loader().load(users[0]!.id), 60 | loader().load(users[1]!.id), 61 | loader().load(users[2]!.id), 62 | loader().load(users[3]!.id), 63 | loader().load(users[4]!.id), 64 | ]).then(t.snapshot) 65 | }, 66 | ) 67 | 68 | test.serial('BatchLoader - hasMany without pagination', async (t) => { 69 | const batchLoader = new BatchLoader(knexWithLog) 70 | const loader = () => 71 | batchLoader.getLoader({ 72 | type: 'hasMany', 73 | foreignKey: 'userId', 74 | targetTable: 'posts', 75 | orderBy: ['createdAt', 'desc'], 76 | }) 77 | await Promise.all([ 78 | loader().load(users[4]!.id), 79 | loader().load(users[5]!.id), 80 | ]).then(t.snapshot) 81 | }) 82 | 83 | test.serial('BatchLoader - belongsTo', async (t) => { 84 | const batchLoader = new BatchLoader(knexWithLog) 85 | const loader = () => 86 | batchLoader.getLoader({ 87 | type: 'belongsTo', 88 | targetTable: 'users', 89 | orderBy: ['createdAt', 'desc'], 90 | }) 91 | await Promise.all([ 92 | loader().load(users[0]!.id), 93 | loader().load(users[1]!.id), 94 | ]).then(t.snapshot) 95 | }) 96 | 97 | test.serial('BatchLoader - hasManyThrough with pagination', async (t) => { 98 | const batchLoader = new BatchLoader(knexWithLog) 99 | const loader = () => 100 | batchLoader.getLoader({ 101 | type: 'hasManyThrough', 102 | join: { 103 | from: 'posts.userId', 104 | to: 'comments.postId', 105 | }, 106 | page: { 107 | limit: 3, 108 | offset: 0, 109 | }, 110 | targetTable: 'comments', 111 | orderBy: ['comments.createdAt', 'desc'], 112 | }) 113 | await Promise.all([ 114 | loader().load(users[0]!.id), 115 | loader().load(users[1]!.id), 116 | ]).then(t.snapshot) 117 | }) 118 | 119 | test.serial('BatchLoader - hasManyThrough without pagination', async (t) => { 120 | const batchLoader = new BatchLoader(knexWithLog) 121 | const loader = () => 122 | batchLoader.getLoader({ 123 | type: 'hasManyThrough', 124 | join: { 125 | from: 'posts.userId', 126 | to: 'comments.postId', 127 | }, 128 | targetTable: 'comments', 129 | orderBy: ['posts.createdAt', 'asc'], 130 | }) 131 | await Promise.all([ 132 | loader().load(users[0]!.id), 133 | loader().load(users[1]!.id), 134 | ]).then(t.snapshot) 135 | }) 136 | 137 | test.serial('BatchLoader - manyToMany with pagination', async (t) => { 138 | const batchLoader = new BatchLoader(knexWithLog) 139 | const loader = () => 140 | batchLoader.getLoader({ 141 | type: 'manyToMany', 142 | join: { 143 | from: 'tagsPosts.postId', 144 | to: 'tagsPosts.tagId', 145 | }, 146 | page: { limit: 5, offset: 0 }, 147 | targetTable: 'tags', 148 | orderBy: ['tags.createdAt', 'asc'], 149 | }) 150 | await Promise.all([ 151 | loader().load(posts[0]!.id), 152 | loader().load(posts[1]!.id), 153 | loader().load(posts[2]!.id), 154 | ]).then(t.snapshot) 155 | }) 156 | 157 | test.serial('BatchLoader - manyToMany without pagination', async (t) => { 158 | const batchLoader = new BatchLoader(knexWithLog) 159 | const loader = () => 160 | batchLoader.getLoader({ 161 | type: 'manyToMany', 162 | join: { 163 | from: 'tagsPosts.postId', 164 | to: 'tagsPosts.tagId', 165 | }, 166 | targetTable: 'tags', 167 | orderBy: ['tags.createdAt', 'asc'], 168 | }) 169 | await Promise.all([ 170 | loader().load(posts[0]!.id), 171 | loader().load(posts[1]!.id), 172 | ]).then(t.snapshot) 173 | }) 174 | -------------------------------------------------------------------------------- /tests/SelectionFilter.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { knexWithLog } from './knex' 3 | import { SelectionFilter } from '../src' 4 | import { 5 | graphql, 6 | GraphQLID, 7 | GraphQLString, 8 | GraphQLList, 9 | GraphQLSchema, 10 | GraphQLObjectType, 11 | } from 'graphql' 12 | 13 | const gql = String.raw 14 | 15 | test.serial('SelectionFilter', async (t) => { 16 | const selectionFilter = new SelectionFilter(knexWithLog) 17 | await selectionFilter.prepare(['users', 'posts'], /_id$/) 18 | 19 | const Post = new GraphQLObjectType({ 20 | name: 'Post', 21 | fields: { 22 | id: { type: GraphQLID }, 23 | title: { type: GraphQLString }, 24 | createdAt: { type: GraphQLString }, 25 | updatedAt: { type: GraphQLString }, 26 | }, 27 | }) 28 | 29 | const User = new GraphQLObjectType({ 30 | name: 'User', 31 | fields: { 32 | id: { type: GraphQLID }, 33 | name: { type: GraphQLString }, 34 | createdAt: { type: GraphQLString }, 35 | updatedAt: { type: GraphQLString }, 36 | posts: { 37 | type: new GraphQLList(Post), 38 | resolve: (user, _args, _ctx, info) => 39 | knexWithLog('posts') 40 | .where({ userId: user.id }) 41 | .select( 42 | selectionFilter.reduce({ 43 | info, 44 | table: 'posts', 45 | }), 46 | ), 47 | }, 48 | }, 49 | }) 50 | 51 | const schema = new GraphQLSchema({ 52 | query: new GraphQLObjectType({ 53 | name: 'Query', 54 | fields: { 55 | user: { 56 | type: User, 57 | resolve: (_root, _args, _ctx, info) => 58 | knexWithLog('users') 59 | .select( 60 | selectionFilter.reduce({ 61 | info, 62 | table: 'users', 63 | }), 64 | ) 65 | .first(), 66 | }, 67 | }, 68 | }), 69 | }) 70 | 71 | knexWithLog.on('query', (q) => { 72 | t.snapshot(q.sql) 73 | }) 74 | 75 | await graphql({ 76 | schema, 77 | source: gql` 78 | query { 79 | user { 80 | id 81 | name 82 | posts { 83 | id 84 | createdAt 85 | } 86 | } 87 | } 88 | `, 89 | }).then(t.snapshot) 90 | }) 91 | -------------------------------------------------------------------------------- /tests/globalHooks.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | import { knex, knexWithLog } from './knex' 4 | import { users, posts, comments, tags, tagsPosts } from './fixtures.json' 5 | 6 | test.before(async () => { 7 | Object.assign(global, { 8 | log: (a: any) => console.log(JSON.stringify(a, undefined, 2)), 9 | }) 10 | 11 | await knex.raw(` 12 | DROP SCHEMA public CASCADE; 13 | CREATE SCHEMA public; 14 | `) 15 | 16 | await knex.schema.createTable('users', (t) => { 17 | t.uuid('id').primary() 18 | t.string('name').notNullable() 19 | t.string('email') 20 | t.timestamps(true, true) 21 | }) 22 | 23 | await knex.schema.createTable('posts', (t) => { 24 | t.uuid('id').primary() 25 | t.uuid('user_id').notNullable().references('users.id').onDelete('CASCADE') 26 | t.string('title').notNullable() 27 | t.timestamps(true, true) 28 | }) 29 | 30 | await knex.schema.createTable('comments', (t) => { 31 | t.uuid('id').primary() 32 | t.uuid('post_id').notNullable().references('posts.id').onDelete('CASCADE') 33 | t.string('content').notNullable() 34 | t.timestamps(true, true) 35 | }) 36 | 37 | await knex.schema.createTable('tags', (t) => { 38 | t.uuid('id').primary() 39 | t.string('name').notNullable() 40 | t.timestamps(true, true) 41 | }) 42 | 43 | await knex.schema.createTable('tags_posts', (t) => { 44 | t.uuid('id').primary() 45 | t.uuid('tag_id').notNullable().references('tags.id').onDelete('CASCADE') 46 | t.uuid('post_id').notNullable().references('posts.id').onDelete('CASCADE') 47 | }) 48 | 49 | // This initialize knex 50 | await knexWithLog.raw("select 'Hey start'") 51 | 52 | await knex('users').insert(users) 53 | await knex('posts').insert(posts) 54 | await knex('comments').insert(comments) 55 | await knex('tags').insert(tags) 56 | await knex('tagsPosts').insert(tagsPosts) 57 | }) 58 | 59 | test.after(async () => { 60 | await knexWithLog.destroy() 61 | await knex.destroy() 62 | }) 63 | -------------------------------------------------------------------------------- /tests/integration.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { knexWithLog } from './knex' 3 | import { BatchLoader, SelectionFilter } from '../src/index' 4 | import { makeExecutableSchema } from '@graphql-tools/schema' 5 | import { gql } from './util' 6 | import { graphql } from 'graphql' 7 | 8 | const typeDefs = gql` 9 | type Query { 10 | user: User 11 | } 12 | type User { 13 | id: ID! 14 | name: String! 15 | posts(page: Int = 1): [Post!]! 16 | createdAt: String! 17 | updatedAt: String! 18 | } 19 | type Post { 20 | id: ID! 21 | user: User! 22 | comments: [Comment!]! 23 | createdAt: String! 24 | updatedAt: String! 25 | } 26 | type Comment { 27 | id: ID! 28 | content: String! 29 | createdAt: String! 30 | updatedAt: String! 31 | } 32 | ` 33 | 34 | test.serial('BatchLoader + SelectionFilter', async (t) => { 35 | const selectionFilter = new SelectionFilter(knexWithLog) 36 | await selectionFilter.prepare(['users', 'posts', 'comments'], /Id$/) 37 | const batchLoader = new BatchLoader(knexWithLog) 38 | batchLoader.useSelectionFilter(selectionFilter) 39 | 40 | const schema = makeExecutableSchema({ 41 | typeDefs, 42 | resolvers: { 43 | Query: { 44 | user: (...params) => { 45 | const [, , , info] = params 46 | return knexWithLog('users') 47 | .select(selectionFilter.reduce({ table: 'users', info })) 48 | .first() 49 | }, 50 | }, 51 | User: { 52 | posts: (...params) => { 53 | const [user, , , info] = params 54 | return batchLoader 55 | .getLoader({ 56 | foreignKey: 'userId', 57 | page: { offset: 0, limit: 5 }, 58 | targetTable: 'posts', 59 | type: 'hasMany', 60 | orderBy: ['createdAt', 'asc'], 61 | info, 62 | }) 63 | .load(user.id) 64 | }, 65 | }, 66 | Post: { 67 | comments: (...params) => { 68 | const [post, , , info] = params 69 | return batchLoader 70 | .getLoader({ 71 | foreignKey: 'postId', 72 | page: { offset: 0, limit: 5 }, 73 | targetTable: 'comments', 74 | type: 'hasMany', 75 | orderBy: ['createdAt', 'asc'], 76 | info, 77 | }) 78 | .load(post.id) 79 | }, 80 | }, 81 | }, 82 | }) 83 | 84 | knexWithLog.on('query', (q) => { 85 | t.snapshot(q.sql) 86 | }) 87 | 88 | await graphql({ 89 | schema, 90 | source: gql` 91 | query { 92 | user { 93 | id 94 | name 95 | posts { 96 | id 97 | comments { 98 | id 99 | content 100 | } 101 | } 102 | } 103 | } 104 | `, 105 | }).then(t.snapshot) 106 | }) 107 | -------------------------------------------------------------------------------- /tests/knex.ts: -------------------------------------------------------------------------------- 1 | import createKnex from 'knex' 2 | import { knexLittleLogger } from 'knex-little-logger' 3 | 4 | const knexStringcase = require('knex-stringcase') 5 | 6 | const options = knexStringcase({ 7 | client: 'pg', 8 | connection: 'postgres://postgres:postgres@127.0.0.1:11155/postgres', 9 | }) 10 | 11 | export const knexWithLog = createKnex(options) 12 | 13 | knexLittleLogger(knexWithLog) 14 | 15 | export const knex = createKnex(options) 16 | -------------------------------------------------------------------------------- /tests/snapshots/BatchLoader.test.ts.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `tests/BatchLoader.test.ts` 2 | 3 | The actual snapshot is saved in `BatchLoader.test.ts.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## BatchLoader - hasMany with custom select 8 | 9 | > Snapshot 1 10 | 11 | [ 12 | [ 13 | { 14 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 15 | id: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 16 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 17 | }, 18 | { 19 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 20 | id: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 21 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 22 | }, 23 | { 24 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 25 | id: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 26 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 27 | }, 28 | { 29 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 30 | id: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 31 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 32 | }, 33 | { 34 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 35 | id: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 36 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 37 | }, 38 | ], 39 | [ 40 | { 41 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 42 | id: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 43 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 44 | }, 45 | { 46 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 47 | id: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 48 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 49 | }, 50 | { 51 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 52 | id: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 53 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 54 | }, 55 | { 56 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 57 | id: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 58 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 59 | }, 60 | { 61 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 62 | id: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 63 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 64 | }, 65 | ], 66 | ] 67 | 68 | ## BatchLoader - hasMany with pagination 69 | 70 | > Snapshot 1 71 | 72 | [ 73 | [ 74 | { 75 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 76 | id: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 77 | relationIndex: '5', 78 | title: 'George Washington\'s post - 5', 79 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 80 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 81 | }, 82 | { 83 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 84 | id: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 85 | relationIndex: '6', 86 | title: 'George Washington\'s post - 6', 87 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 88 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 89 | }, 90 | { 91 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 92 | id: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 93 | relationIndex: '7', 94 | title: 'George Washington\'s post - 7', 95 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 96 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 97 | }, 98 | { 99 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 100 | id: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 101 | relationIndex: '8', 102 | title: 'George Washington\'s post - 8', 103 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 104 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 105 | }, 106 | { 107 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 108 | id: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 109 | relationIndex: '9', 110 | title: 'George Washington\'s post - 9', 111 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 112 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 113 | }, 114 | ], 115 | [ 116 | { 117 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 118 | id: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 119 | relationIndex: '5', 120 | title: 'John Adams\'s post - 5', 121 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 122 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 123 | }, 124 | { 125 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 126 | id: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 127 | relationIndex: '6', 128 | title: 'John Adams\'s post - 6', 129 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 130 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 131 | }, 132 | { 133 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 134 | id: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 135 | relationIndex: '7', 136 | title: 'John Adams\'s post - 7', 137 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 138 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 139 | }, 140 | { 141 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 142 | id: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 143 | relationIndex: '8', 144 | title: 'John Adams\'s post - 8', 145 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 146 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 147 | }, 148 | { 149 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 150 | id: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 151 | relationIndex: '9', 152 | title: 'John Adams\'s post - 9', 153 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 154 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 155 | }, 156 | ], 157 | [ 158 | { 159 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 160 | id: 'fab7fe69-7115-5126-aa0c-d759146a1aea', 161 | relationIndex: '5', 162 | title: 'Thomas Jefferson\'s post - 5', 163 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 164 | userId: '2697ebc9-c8bb-5a78-be26-808fa3dba6d5', 165 | }, 166 | { 167 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 168 | id: '036b617d-93ca-5638-866b-a490a7f3484a', 169 | relationIndex: '6', 170 | title: 'Thomas Jefferson\'s post - 6', 171 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 172 | userId: '2697ebc9-c8bb-5a78-be26-808fa3dba6d5', 173 | }, 174 | { 175 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 176 | id: '58aa34d7-86ae-5ba2-bee5-4c38805bc58b', 177 | relationIndex: '7', 178 | title: 'Thomas Jefferson\'s post - 7', 179 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 180 | userId: '2697ebc9-c8bb-5a78-be26-808fa3dba6d5', 181 | }, 182 | { 183 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 184 | id: '6251b495-6332-5292-9f74-7f57b3043d39', 185 | relationIndex: '8', 186 | title: 'Thomas Jefferson\'s post - 8', 187 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 188 | userId: '2697ebc9-c8bb-5a78-be26-808fa3dba6d5', 189 | }, 190 | { 191 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 192 | id: '4fc06608-d23b-5235-ab0e-fb5cfa7f7f06', 193 | relationIndex: '9', 194 | title: 'Thomas Jefferson\'s post - 9', 195 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 196 | userId: '2697ebc9-c8bb-5a78-be26-808fa3dba6d5', 197 | }, 198 | ], 199 | [ 200 | { 201 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 202 | id: '7a6ba493-51cb-530f-a24e-9ca93329c73d', 203 | relationIndex: '5', 204 | title: 'James Madison\'s post - 5', 205 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 206 | userId: '446c8683-25f5-5fd9-ab3a-2f2ebbadd162', 207 | }, 208 | { 209 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 210 | id: '66b14b6b-45a5-5c9d-8f44-ef70040d45c8', 211 | relationIndex: '6', 212 | title: 'James Madison\'s post - 6', 213 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 214 | userId: '446c8683-25f5-5fd9-ab3a-2f2ebbadd162', 215 | }, 216 | { 217 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 218 | id: '858f1759-5792-5dcb-a44c-1d021a4a7a17', 219 | relationIndex: '7', 220 | title: 'James Madison\'s post - 7', 221 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 222 | userId: '446c8683-25f5-5fd9-ab3a-2f2ebbadd162', 223 | }, 224 | { 225 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 226 | id: '6187c38d-bed7-59ce-8625-50f9786772bf', 227 | relationIndex: '8', 228 | title: 'James Madison\'s post - 8', 229 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 230 | userId: '446c8683-25f5-5fd9-ab3a-2f2ebbadd162', 231 | }, 232 | { 233 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 234 | id: 'a888f378-2e18-5006-87da-fac01cd1131f', 235 | relationIndex: '9', 236 | title: 'James Madison\'s post - 9', 237 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 238 | userId: '446c8683-25f5-5fd9-ab3a-2f2ebbadd162', 239 | }, 240 | ], 241 | [ 242 | { 243 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 244 | id: '8ee669f3-a058-5ac7-b824-76b2189d764b', 245 | relationIndex: '5', 246 | title: 'James Monroe\'s post - 5', 247 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 248 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 249 | }, 250 | { 251 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 252 | id: '0466542f-a13e-5d39-bcb1-1a2240106d76', 253 | relationIndex: '6', 254 | title: 'James Monroe\'s post - 6', 255 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 256 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 257 | }, 258 | { 259 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 260 | id: 'bef751cb-879d-5e88-a49b-cc8fa4e1fc5f', 261 | relationIndex: '7', 262 | title: 'James Monroe\'s post - 7', 263 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 264 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 265 | }, 266 | { 267 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 268 | id: 'b3450982-9613-5db7-bedc-d9c8fdd022f9', 269 | relationIndex: '8', 270 | title: 'James Monroe\'s post - 8', 271 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 272 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 273 | }, 274 | { 275 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 276 | id: '48184a0c-bde8-5ceb-a258-100a2cade20d', 277 | relationIndex: '9', 278 | title: 'James Monroe\'s post - 9', 279 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 280 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 281 | }, 282 | ], 283 | ] 284 | 285 | ## BatchLoader - hasMany with pagination and modifyInnerQuery 286 | 287 | > Snapshot 1 288 | 289 | [ 290 | [ 291 | { 292 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 293 | id: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 294 | relationIndex: '1', 295 | title: 'George Washington\'s post - 1', 296 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 297 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 298 | }, 299 | ], 300 | [], 301 | [], 302 | [], 303 | [], 304 | ] 305 | 306 | ## BatchLoader - hasMany without pagination 307 | 308 | > Snapshot 1 309 | 310 | [ 311 | [ 312 | { 313 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 314 | id: '48184a0c-bde8-5ceb-a258-100a2cade20d', 315 | title: 'James Monroe\'s post - 9', 316 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 317 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 318 | }, 319 | { 320 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 321 | id: 'b3450982-9613-5db7-bedc-d9c8fdd022f9', 322 | title: 'James Monroe\'s post - 8', 323 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 324 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 325 | }, 326 | { 327 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 328 | id: 'bef751cb-879d-5e88-a49b-cc8fa4e1fc5f', 329 | title: 'James Monroe\'s post - 7', 330 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 331 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 332 | }, 333 | { 334 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 335 | id: '0466542f-a13e-5d39-bcb1-1a2240106d76', 336 | title: 'James Monroe\'s post - 6', 337 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 338 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 339 | }, 340 | { 341 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 342 | id: '8ee669f3-a058-5ac7-b824-76b2189d764b', 343 | title: 'James Monroe\'s post - 5', 344 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 345 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 346 | }, 347 | { 348 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 349 | id: '7a0ee8fd-5c60-5c56-a8d1-c7d104bec258', 350 | title: 'James Monroe\'s post - 4', 351 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 352 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 353 | }, 354 | { 355 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 356 | id: '1681668a-a4b9-518c-8b8a-762e60f49e67', 357 | title: 'James Monroe\'s post - 3', 358 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 359 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 360 | }, 361 | { 362 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 363 | id: 'e98c75f3-b57c-5663-b22e-c69bca75200e', 364 | title: 'James Monroe\'s post - 2', 365 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 366 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 367 | }, 368 | { 369 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 370 | id: 'dab40cf1-a937-5dab-be2d-7fc39e47f041', 371 | title: 'James Monroe\'s post - 1', 372 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 373 | userId: '34e760bc-c8c5-534e-ad51-d2a892ebdbd4', 374 | }, 375 | ], 376 | [ 377 | { 378 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 379 | id: '21a9e6eb-4654-5504-b3cd-7be5b1194e77', 380 | title: 'John Quincy Adams\'s post - 9', 381 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 382 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 383 | }, 384 | { 385 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 386 | id: '41039d38-a8b8-5124-a31b-b65b5c9ecab0', 387 | title: 'John Quincy Adams\'s post - 8', 388 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 389 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 390 | }, 391 | { 392 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 393 | id: '6253e9b9-1eb4-5928-bc3c-51b6acb6bca2', 394 | title: 'John Quincy Adams\'s post - 7', 395 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 396 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 397 | }, 398 | { 399 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 400 | id: 'd4fd431e-82f4-544c-a0d5-dc1da2940f56', 401 | title: 'John Quincy Adams\'s post - 6', 402 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 403 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 404 | }, 405 | { 406 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 407 | id: 'ea1e72ee-a4bb-54d0-9bb5-a7759bf3ee69', 408 | title: 'John Quincy Adams\'s post - 5', 409 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 410 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 411 | }, 412 | { 413 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 414 | id: '55c8f351-a425-51ae-bc1a-10fa564189a1', 415 | title: 'John Quincy Adams\'s post - 4', 416 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 417 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 418 | }, 419 | { 420 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 421 | id: 'dc60eb3f-32e9-5b9d-88ba-0f21f9261135', 422 | title: 'John Quincy Adams\'s post - 3', 423 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 424 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 425 | }, 426 | { 427 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 428 | id: '83d4fe16-119d-5af3-a60c-efdc5fefd742', 429 | title: 'John Quincy Adams\'s post - 2', 430 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 431 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 432 | }, 433 | { 434 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 435 | id: '7e46c0f3-5fff-586e-a34a-382097b9c10b', 436 | title: 'John Quincy Adams\'s post - 1', 437 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 438 | userId: '20909dd2-db1f-575b-aaa3-1ca196131f38', 439 | }, 440 | ], 441 | ] 442 | 443 | ## BatchLoader - belongsTo 444 | 445 | > Snapshot 1 446 | 447 | [ 448 | { 449 | createdAt: Date 2021-07-22 08:53:06 74ms UTC {}, 450 | email: null, 451 | id: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 452 | name: 'George Washington', 453 | updatedAt: Date 2021-07-22 08:53:06 74ms UTC {}, 454 | }, 455 | { 456 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 457 | email: null, 458 | id: '8c5c8c10-c821-5115-afa9-8d6330420b43', 459 | name: 'John Adams', 460 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 461 | }, 462 | ] 463 | 464 | ## BatchLoader - hasManyThrough with pagination 465 | 466 | > Snapshot 1 467 | 468 | [ 469 | [ 470 | { 471 | content: 'comment for George Washington\'s post - 4 - 9', 472 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 473 | id: 'a426a263-c533-5c4b-a88b-b2653ef60638', 474 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 475 | relationIndex: '1', 476 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 477 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 478 | }, 479 | { 480 | content: 'comment for George Washington\'s post - 7 - 9', 481 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 482 | id: 'dc2cf8ec-d965-5292-8ea5-6b23ee4f401f', 483 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 484 | relationIndex: '2', 485 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 486 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 487 | }, 488 | { 489 | content: 'comment for George Washington\'s post - 9 - 9', 490 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 491 | id: 'd10bbb30-fc48-5ae1-a25f-03f7ad3f1c2d', 492 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 493 | relationIndex: '3', 494 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 495 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 496 | }, 497 | ], 498 | [ 499 | { 500 | content: 'comment for John Adams\'s post - 5 - 9', 501 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 502 | id: '0949bcbc-7ff5-535d-a7ff-5d0b5f331a22', 503 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 504 | relationIndex: '1', 505 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 506 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 507 | }, 508 | { 509 | content: 'comment for John Adams\'s post - 2 - 9', 510 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 511 | id: 'a1ba0d4b-8b11-5484-b596-d2f08801b9d3', 512 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 513 | relationIndex: '2', 514 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 515 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 516 | }, 517 | { 518 | content: 'comment for John Adams\'s post - 3 - 9', 519 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 520 | id: 'c9a335fb-1a22-5975-941b-620976fb915d', 521 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 522 | relationIndex: '3', 523 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 524 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 525 | }, 526 | ], 527 | ] 528 | 529 | ## BatchLoader - hasManyThrough without pagination 530 | 531 | > Snapshot 1 532 | 533 | [ 534 | [ 535 | { 536 | content: 'comment for George Washington\'s post - 1 - 2', 537 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 538 | id: 'e596c693-9699-55f5-9dda-238366c7dd27', 539 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 540 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 541 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 542 | }, 543 | { 544 | content: 'comment for George Washington\'s post - 1 - 3', 545 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 546 | id: '5ded340e-7a89-5678-99af-e658c3c46976', 547 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 548 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 549 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 550 | }, 551 | { 552 | content: 'comment for George Washington\'s post - 1 - 1', 553 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 554 | id: '4decc497-3e7e-55b0-b775-85502f425040', 555 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 556 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 557 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 558 | }, 559 | { 560 | content: 'comment for George Washington\'s post - 1 - 4', 561 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 562 | id: '71c313fe-80c1-56a3-9013-f423890f4381', 563 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 564 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 565 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 566 | }, 567 | { 568 | content: 'comment for George Washington\'s post - 1 - 5', 569 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 570 | id: '40703794-a38e-57a3-9c65-bf9feecfa2e5', 571 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 572 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 573 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 574 | }, 575 | { 576 | content: 'comment for George Washington\'s post - 1 - 6', 577 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 578 | id: 'ba58433a-9da3-5588-9387-e9d447be0053', 579 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 580 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 581 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 582 | }, 583 | { 584 | content: 'comment for George Washington\'s post - 1 - 7', 585 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 586 | id: '60dca5dd-98b4-571e-a2cc-683ece5649d0', 587 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 588 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 589 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 590 | }, 591 | { 592 | content: 'comment for George Washington\'s post - 1 - 8', 593 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 594 | id: '4ef5304b-e51c-58d7-ad25-7c93179a5715', 595 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 596 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 597 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 598 | }, 599 | { 600 | content: 'comment for George Washington\'s post - 1 - 9', 601 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 602 | id: '5b48d62a-d405-5d64-8f67-36ccc8e34d08', 603 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 604 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 605 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 606 | }, 607 | { 608 | content: 'comment for George Washington\'s post - 2 - 1', 609 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 610 | id: 'ffe6a8aa-909a-5022-817d-00adc9cf3647', 611 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 612 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 613 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 614 | }, 615 | { 616 | content: 'comment for George Washington\'s post - 2 - 2', 617 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 618 | id: 'bf65a3b4-0854-5591-a08c-fa811a8f4a50', 619 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 620 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 621 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 622 | }, 623 | { 624 | content: 'comment for George Washington\'s post - 2 - 3', 625 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 626 | id: '96bf447c-c2a5-5fb7-9b57-b8495f76f7d4', 627 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 628 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 629 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 630 | }, 631 | { 632 | content: 'comment for George Washington\'s post - 2 - 4', 633 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 634 | id: 'bf58d419-f8d4-5fdb-a651-7e4b8cbb33a7', 635 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 636 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 637 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 638 | }, 639 | { 640 | content: 'comment for George Washington\'s post - 2 - 5', 641 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 642 | id: 'b86e8113-0bcd-5bf2-8c5d-8eb7893f86ac', 643 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 644 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 645 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 646 | }, 647 | { 648 | content: 'comment for George Washington\'s post - 2 - 6', 649 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 650 | id: '570565ea-988a-55a8-9523-f3c23c6f638e', 651 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 652 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 653 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 654 | }, 655 | { 656 | content: 'comment for George Washington\'s post - 2 - 7', 657 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 658 | id: 'b34f9a6d-a570-54b0-bba4-2be28ee707ca', 659 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 660 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 661 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 662 | }, 663 | { 664 | content: 'comment for George Washington\'s post - 2 - 8', 665 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 666 | id: 'b5b3b04e-ab37-5731-a883-062d46567d8d', 667 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 668 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 669 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 670 | }, 671 | { 672 | content: 'comment for George Washington\'s post - 2 - 9', 673 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 674 | id: 'e45aa11c-54c2-59c6-bc9c-61a3a1c8cf13', 675 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 676 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 677 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 678 | }, 679 | { 680 | content: 'comment for George Washington\'s post - 3 - 3', 681 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 682 | id: '9a66b891-8d36-5e10-9016-541113fa5cf9', 683 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 684 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 685 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 686 | }, 687 | { 688 | content: 'comment for George Washington\'s post - 3 - 1', 689 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 690 | id: '490a8c4e-dbd1-503b-b89c-aa1eed7062d7', 691 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 692 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 693 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 694 | }, 695 | { 696 | content: 'comment for George Washington\'s post - 3 - 2', 697 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 698 | id: 'b9a067b6-09af-5ac8-a2fb-50a4043849ab', 699 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 700 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 701 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 702 | }, 703 | { 704 | content: 'comment for George Washington\'s post - 3 - 4', 705 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 706 | id: 'ac03696f-1aab-54d5-96f5-9f94bae0eb38', 707 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 708 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 709 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 710 | }, 711 | { 712 | content: 'comment for George Washington\'s post - 3 - 5', 713 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 714 | id: 'c6f9c440-f579-5b67-af57-ae4630e7ba4d', 715 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 716 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 717 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 718 | }, 719 | { 720 | content: 'comment for George Washington\'s post - 3 - 6', 721 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 722 | id: '7e3f993e-1b57-5837-b365-aa5594f96105', 723 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 724 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 725 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 726 | }, 727 | { 728 | content: 'comment for George Washington\'s post - 3 - 7', 729 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 730 | id: '315fc533-d3de-5439-9256-8cc466a70912', 731 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 732 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 733 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 734 | }, 735 | { 736 | content: 'comment for George Washington\'s post - 3 - 8', 737 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 738 | id: '54cab42e-2c09-5dd4-8ed9-57ce60e0e6b9', 739 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 740 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 741 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 742 | }, 743 | { 744 | content: 'comment for George Washington\'s post - 3 - 9', 745 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 746 | id: '7f33cb78-b491-5575-bedb-ee91fc9da007', 747 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 748 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 749 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 750 | }, 751 | { 752 | content: 'comment for George Washington\'s post - 4 - 9', 753 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 754 | id: 'a426a263-c533-5c4b-a88b-b2653ef60638', 755 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 756 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 757 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 758 | }, 759 | { 760 | content: 'comment for George Washington\'s post - 4 - 1', 761 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 762 | id: '505b751c-a5c4-51c5-bf71-4c8e66fcd97f', 763 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 764 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 765 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 766 | }, 767 | { 768 | content: 'comment for George Washington\'s post - 4 - 2', 769 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 770 | id: '0e7816b5-acd1-5286-9e12-a43c4362b60c', 771 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 772 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 773 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 774 | }, 775 | { 776 | content: 'comment for George Washington\'s post - 4 - 3', 777 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 778 | id: '90334f0e-4716-5f60-8ccf-6cdb403cd60d', 779 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 780 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 781 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 782 | }, 783 | { 784 | content: 'comment for George Washington\'s post - 4 - 4', 785 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 786 | id: 'b1551ba5-c724-58eb-b49f-4ab72bc7fac8', 787 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 788 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 789 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 790 | }, 791 | { 792 | content: 'comment for George Washington\'s post - 4 - 5', 793 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 794 | id: '7b29e0ad-fcb1-5afb-8c79-099f7ca2e0d9', 795 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 796 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 797 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 798 | }, 799 | { 800 | content: 'comment for George Washington\'s post - 4 - 6', 801 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 802 | id: '6ab30fdd-9260-5451-be4c-77367cdf0dfc', 803 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 804 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 805 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 806 | }, 807 | { 808 | content: 'comment for George Washington\'s post - 4 - 7', 809 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 810 | id: '9eed2c0b-5316-5f38-bc5e-d570ce6fa4d5', 811 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 812 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 813 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 814 | }, 815 | { 816 | content: 'comment for George Washington\'s post - 4 - 8', 817 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 818 | id: 'd98a4cee-34ed-5f63-8e25-dc58c9b5ae80', 819 | postId: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 820 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 821 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 822 | }, 823 | { 824 | content: 'comment for George Washington\'s post - 5 - 9', 825 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 826 | id: '4dc92e5c-bf0f-5219-b372-e8c344fcfcbd', 827 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 828 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 829 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 830 | }, 831 | { 832 | content: 'comment for George Washington\'s post - 5 - 8', 833 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 834 | id: 'b26680a9-082c-52cb-afac-9af456f6be51', 835 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 836 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 837 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 838 | }, 839 | { 840 | content: 'comment for George Washington\'s post - 5 - 7', 841 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 842 | id: '5e274f24-4148-50c7-bbe5-435ba75a3da2', 843 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 844 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 845 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 846 | }, 847 | { 848 | content: 'comment for George Washington\'s post - 5 - 6', 849 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 850 | id: '6cd37259-5d06-5d4f-b939-d0ff66762191', 851 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 852 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 853 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 854 | }, 855 | { 856 | content: 'comment for George Washington\'s post - 5 - 5', 857 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 858 | id: 'bec1a793-0050-5187-b95b-9604feb42940', 859 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 860 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 861 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 862 | }, 863 | { 864 | content: 'comment for George Washington\'s post - 5 - 4', 865 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 866 | id: '1d233231-7122-5bde-ac62-3779a2aa08b2', 867 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 868 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 869 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 870 | }, 871 | { 872 | content: 'comment for George Washington\'s post - 5 - 3', 873 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 874 | id: '070c45dc-30ea-58e8-a9c4-3ef3f021ef56', 875 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 876 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 877 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 878 | }, 879 | { 880 | content: 'comment for George Washington\'s post - 5 - 2', 881 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 882 | id: 'fd7d56e6-61d2-5fc4-a755-2546b5787c70', 883 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 884 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 885 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 886 | }, 887 | { 888 | content: 'comment for George Washington\'s post - 5 - 1', 889 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 890 | id: 'addce678-3b67-5589-b8e0-bb315e842521', 891 | postId: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 892 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 893 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 894 | }, 895 | { 896 | content: 'comment for George Washington\'s post - 6 - 1', 897 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 898 | id: '69fb84a4-43a9-56c3-a2be-fe60c433b79e', 899 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 900 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 901 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 902 | }, 903 | { 904 | content: 'comment for George Washington\'s post - 6 - 2', 905 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 906 | id: '40ee61c5-caa2-5edd-b352-48a1b5a1d74d', 907 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 908 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 909 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 910 | }, 911 | { 912 | content: 'comment for George Washington\'s post - 6 - 3', 913 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 914 | id: '02d22689-99ae-5746-afa4-dc11a3cac74c', 915 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 916 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 917 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 918 | }, 919 | { 920 | content: 'comment for George Washington\'s post - 6 - 4', 921 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 922 | id: '8d750a8c-3b0b-5b7e-aade-e19161033188', 923 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 924 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 925 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 926 | }, 927 | { 928 | content: 'comment for George Washington\'s post - 6 - 5', 929 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 930 | id: '7ff26bad-facb-54de-8951-38754c5c6402', 931 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 932 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 933 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 934 | }, 935 | { 936 | content: 'comment for George Washington\'s post - 6 - 6', 937 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 938 | id: '9bb42197-cc40-5166-a58d-dbe9c17b937a', 939 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 940 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 941 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 942 | }, 943 | { 944 | content: 'comment for George Washington\'s post - 6 - 7', 945 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 946 | id: 'bca46ea2-4731-5dd0-9ee5-a63e4c0a814a', 947 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 948 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 949 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 950 | }, 951 | { 952 | content: 'comment for George Washington\'s post - 6 - 8', 953 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 954 | id: '1a8fd8ed-0a9c-5990-8b48-800e4e32c2b7', 955 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 956 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 957 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 958 | }, 959 | { 960 | content: 'comment for George Washington\'s post - 6 - 9', 961 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 962 | id: 'cd43ceef-025f-5882-b39f-abd2edf3dcf0', 963 | postId: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 964 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 965 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 966 | }, 967 | { 968 | content: 'comment for George Washington\'s post - 7 - 2', 969 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 970 | id: 'f704acd6-db82-5117-b13b-fde6a3cdd2c9', 971 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 972 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 973 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 974 | }, 975 | { 976 | content: 'comment for George Washington\'s post - 7 - 3', 977 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 978 | id: 'cebc7eb0-d667-5757-8978-67417d8693fa', 979 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 980 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 981 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 982 | }, 983 | { 984 | content: 'comment for George Washington\'s post - 7 - 4', 985 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 986 | id: '50fae4b3-47de-582a-a5d7-b4c967678bbc', 987 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 988 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 989 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 990 | }, 991 | { 992 | content: 'comment for George Washington\'s post - 7 - 5', 993 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 994 | id: '94884e0d-70c6-5992-ae49-b0b764202d6c', 995 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 996 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 997 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 998 | }, 999 | { 1000 | content: 'comment for George Washington\'s post - 7 - 6', 1001 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1002 | id: 'f38d11f0-9838-5e26-8cfe-ced0e2d68d17', 1003 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 1004 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1005 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1006 | }, 1007 | { 1008 | content: 'comment for George Washington\'s post - 7 - 7', 1009 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1010 | id: '9652c61a-9477-5bf0-b82c-5129277236ab', 1011 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 1012 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1013 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1014 | }, 1015 | { 1016 | content: 'comment for George Washington\'s post - 7 - 8', 1017 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1018 | id: '811c7222-76c0-52fa-b9c7-6b41cc83fe25', 1019 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 1020 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1021 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1022 | }, 1023 | { 1024 | content: 'comment for George Washington\'s post - 7 - 9', 1025 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1026 | id: 'dc2cf8ec-d965-5292-8ea5-6b23ee4f401f', 1027 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 1028 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1029 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1030 | }, 1031 | { 1032 | content: 'comment for George Washington\'s post - 7 - 1', 1033 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1034 | id: '27fcbc28-af20-5496-ba2d-21afa9e9ab7f', 1035 | postId: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 1036 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1037 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1038 | }, 1039 | { 1040 | content: 'comment for George Washington\'s post - 8 - 9', 1041 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1042 | id: 'aebebd1e-f694-5c04-a5e2-61bceb1c9c68', 1043 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1044 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1045 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1046 | }, 1047 | { 1048 | content: 'comment for George Washington\'s post - 8 - 8', 1049 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1050 | id: 'a6eba0c9-e9f9-5e3f-86e4-a18c6089b999', 1051 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1052 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1053 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1054 | }, 1055 | { 1056 | content: 'comment for George Washington\'s post - 8 - 7', 1057 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1058 | id: '1ee06753-7590-5d21-8f29-aa4ccae3d6e7', 1059 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1060 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1061 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1062 | }, 1063 | { 1064 | content: 'comment for George Washington\'s post - 8 - 6', 1065 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1066 | id: 'e4f5b2fd-31d6-5f56-ab22-60eb4ea39490', 1067 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1068 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1069 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1070 | }, 1071 | { 1072 | content: 'comment for George Washington\'s post - 8 - 5', 1073 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1074 | id: 'c082b366-66a5-5150-bc19-b65b362beeea', 1075 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1076 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1077 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1078 | }, 1079 | { 1080 | content: 'comment for George Washington\'s post - 8 - 4', 1081 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1082 | id: 'afb73116-4640-5312-ad14-1d77c5d9f0f6', 1083 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1084 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1085 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1086 | }, 1087 | { 1088 | content: 'comment for George Washington\'s post - 8 - 3', 1089 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1090 | id: '6999ac9b-5ef8-5779-849b-861def1b435b', 1091 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1092 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1093 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1094 | }, 1095 | { 1096 | content: 'comment for George Washington\'s post - 8 - 2', 1097 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1098 | id: '0ec2d704-2ddf-50ac-b287-96c083e5855b', 1099 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1100 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1101 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1102 | }, 1103 | { 1104 | content: 'comment for George Washington\'s post - 8 - 1', 1105 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1106 | id: 'f8a75cd3-42bf-5e67-9f5e-42346b21e70e', 1107 | postId: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 1108 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1109 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1110 | }, 1111 | { 1112 | content: 'comment for George Washington\'s post - 9 - 8', 1113 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1114 | id: '772c5029-7276-5aaa-af16-c263fec4b1c9', 1115 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1116 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1117 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1118 | }, 1119 | { 1120 | content: 'comment for George Washington\'s post - 9 - 7', 1121 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1122 | id: 'aeda7bb8-7e53-5b51-a198-69bd2f709137', 1123 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1124 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1125 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1126 | }, 1127 | { 1128 | content: 'comment for George Washington\'s post - 9 - 6', 1129 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1130 | id: 'c9b35db2-8a71-5603-9917-92c0e22fc644', 1131 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1132 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1133 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1134 | }, 1135 | { 1136 | content: 'comment for George Washington\'s post - 9 - 5', 1137 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1138 | id: '3ff36e85-c6d5-5307-aac1-c436f0739c28', 1139 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1140 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1141 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1142 | }, 1143 | { 1144 | content: 'comment for George Washington\'s post - 9 - 4', 1145 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1146 | id: '6e18761f-b0d4-5ad0-84d8-530e55d81b92', 1147 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1148 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1149 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1150 | }, 1151 | { 1152 | content: 'comment for George Washington\'s post - 9 - 3', 1153 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1154 | id: '2c43e54b-04b0-5651-92f4-d54f7904397e', 1155 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1156 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1157 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1158 | }, 1159 | { 1160 | content: 'comment for George Washington\'s post - 9 - 2', 1161 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1162 | id: 'e34422bc-396d-5fd6-aa1a-9fcf89199b50', 1163 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1164 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1165 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1166 | }, 1167 | { 1168 | content: 'comment for George Washington\'s post - 9 - 1', 1169 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1170 | id: '91cae309-ccb6-59ed-b8fd-b55499d9ae41', 1171 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1172 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1173 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1174 | }, 1175 | { 1176 | content: 'comment for George Washington\'s post - 9 - 9', 1177 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1178 | id: 'd10bbb30-fc48-5ae1-a25f-03f7ad3f1c2d', 1179 | postId: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 1180 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1181 | userId: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 1182 | }, 1183 | ], 1184 | [ 1185 | { 1186 | content: 'comment for John Adams\'s post - 1 - 9', 1187 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1188 | id: '509d85a1-4ff7-5d75-9996-840f55cb41af', 1189 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1190 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1191 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1192 | }, 1193 | { 1194 | content: 'comment for John Adams\'s post - 1 - 8', 1195 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1196 | id: '770196a9-a92b-5de7-a351-e8254e0a7836', 1197 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1198 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1199 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1200 | }, 1201 | { 1202 | content: 'comment for John Adams\'s post - 1 - 7', 1203 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1204 | id: '49426957-badc-5824-b7fa-9d0d86e42b46', 1205 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1206 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1207 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1208 | }, 1209 | { 1210 | content: 'comment for John Adams\'s post - 1 - 6', 1211 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1212 | id: '91685bcd-3fa8-5ddd-bbbf-a5a93e5beedd', 1213 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1214 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1215 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1216 | }, 1217 | { 1218 | content: 'comment for John Adams\'s post - 1 - 5', 1219 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1220 | id: '2b2fecc3-d9ce-533f-a542-b642e5e1ca9b', 1221 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1222 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1223 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1224 | }, 1225 | { 1226 | content: 'comment for John Adams\'s post - 1 - 4', 1227 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1228 | id: 'efeffedb-c784-5be2-86e9-7676bf67310d', 1229 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1230 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1231 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1232 | }, 1233 | { 1234 | content: 'comment for John Adams\'s post - 1 - 3', 1235 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1236 | id: '728cb16e-5872-5c19-8ff6-d2b6363772ad', 1237 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1238 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1239 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1240 | }, 1241 | { 1242 | content: 'comment for John Adams\'s post - 1 - 2', 1243 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1244 | id: '9495de86-02a1-57de-aa74-2256b7a5b553', 1245 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1246 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1247 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1248 | }, 1249 | { 1250 | content: 'comment for John Adams\'s post - 1 - 1', 1251 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1252 | id: 'bcf8786f-8320-523b-925d-3d700fd9dffd', 1253 | postId: '0d7c51a1-5a59-5204-83ce-788e9f44e9ae', 1254 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1255 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1256 | }, 1257 | { 1258 | content: 'comment for John Adams\'s post - 2 - 9', 1259 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1260 | id: 'a1ba0d4b-8b11-5484-b596-d2f08801b9d3', 1261 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1262 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1263 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1264 | }, 1265 | { 1266 | content: 'comment for John Adams\'s post - 2 - 8', 1267 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1268 | id: '7675a028-f333-5bfa-9075-67291bbd11b8', 1269 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1270 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1271 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1272 | }, 1273 | { 1274 | content: 'comment for John Adams\'s post - 2 - 7', 1275 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1276 | id: '8d19d8ac-c18d-598a-8e78-31f5229f096c', 1277 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1278 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1279 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1280 | }, 1281 | { 1282 | content: 'comment for John Adams\'s post - 2 - 6', 1283 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1284 | id: 'dd684b44-c1a2-5c45-8786-b52085518f11', 1285 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1286 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1287 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1288 | }, 1289 | { 1290 | content: 'comment for John Adams\'s post - 2 - 5', 1291 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1292 | id: 'd6a9963a-4a35-5cfa-8eb6-784a8876b5b4', 1293 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1294 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1295 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1296 | }, 1297 | { 1298 | content: 'comment for John Adams\'s post - 2 - 4', 1299 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1300 | id: 'fc542839-10e7-551e-a5b7-6aac0ddeeed0', 1301 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1302 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1303 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1304 | }, 1305 | { 1306 | content: 'comment for John Adams\'s post - 2 - 3', 1307 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1308 | id: '4e04fbdf-5658-558c-9ca4-3489c5ed7059', 1309 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1310 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1311 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1312 | }, 1313 | { 1314 | content: 'comment for John Adams\'s post - 2 - 2', 1315 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1316 | id: '48704553-dda7-5177-a16f-9eaf81ece076', 1317 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1318 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1319 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1320 | }, 1321 | { 1322 | content: 'comment for John Adams\'s post - 2 - 1', 1323 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1324 | id: '076c133b-32c6-5371-8fb7-c9db72837e5a', 1325 | postId: 'a1eac789-2556-52f5-809d-0b90251c1b7c', 1326 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1327 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1328 | }, 1329 | { 1330 | content: 'comment for John Adams\'s post - 3 - 1', 1331 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1332 | id: 'd37c0871-a4b7-58e2-ae1f-9834e70a636a', 1333 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1334 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1335 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1336 | }, 1337 | { 1338 | content: 'comment for John Adams\'s post - 3 - 2', 1339 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1340 | id: 'fecf47c9-69b9-53ab-8c03-ece69d39eff8', 1341 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1342 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1343 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1344 | }, 1345 | { 1346 | content: 'comment for John Adams\'s post - 3 - 3', 1347 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1348 | id: '910f27bc-3cbe-5a96-bb72-b4dacb5a977a', 1349 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1350 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1351 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1352 | }, 1353 | { 1354 | content: 'comment for John Adams\'s post - 3 - 4', 1355 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1356 | id: '3eb7267f-bb2b-53bb-8092-4fa7171b7323', 1357 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1358 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1359 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1360 | }, 1361 | { 1362 | content: 'comment for John Adams\'s post - 3 - 5', 1363 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1364 | id: '9a8aab37-1125-5523-8383-85586c714a6c', 1365 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1366 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1367 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1368 | }, 1369 | { 1370 | content: 'comment for John Adams\'s post - 3 - 6', 1371 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1372 | id: '30efcb3e-f570-5a40-a987-f10ef1486e1a', 1373 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1374 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1375 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1376 | }, 1377 | { 1378 | content: 'comment for John Adams\'s post - 3 - 7', 1379 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1380 | id: '9fcbb2ff-2249-595a-96f8-ae0d3fefa71f', 1381 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1382 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1383 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1384 | }, 1385 | { 1386 | content: 'comment for John Adams\'s post - 3 - 8', 1387 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1388 | id: '87269f05-11bf-5951-8a97-9929b1624e45', 1389 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1390 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1391 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1392 | }, 1393 | { 1394 | content: 'comment for John Adams\'s post - 3 - 9', 1395 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1396 | id: 'c9a335fb-1a22-5975-941b-620976fb915d', 1397 | postId: '5d8ff97b-be59-5fdb-ae19-cfe5aa264a4f', 1398 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1399 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1400 | }, 1401 | { 1402 | content: 'comment for John Adams\'s post - 4 - 2', 1403 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1404 | id: '409edb42-b8a4-5c22-bf9d-47833421da76', 1405 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1406 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1407 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1408 | }, 1409 | { 1410 | content: 'comment for John Adams\'s post - 4 - 3', 1411 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1412 | id: '01b31407-7584-5165-9fe2-5c62d03948eb', 1413 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1414 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1415 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1416 | }, 1417 | { 1418 | content: 'comment for John Adams\'s post - 4 - 4', 1419 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1420 | id: 'f08e6eb4-b377-5e6f-be29-778bb90b0850', 1421 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1422 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1423 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1424 | }, 1425 | { 1426 | content: 'comment for John Adams\'s post - 4 - 5', 1427 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1428 | id: '3454706a-7c12-50a0-8ca2-98ceb8bda5c7', 1429 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1430 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1431 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1432 | }, 1433 | { 1434 | content: 'comment for John Adams\'s post - 4 - 6', 1435 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1436 | id: '6531d147-2aa1-5bea-ab60-32e8042bf210', 1437 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1438 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1439 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1440 | }, 1441 | { 1442 | content: 'comment for John Adams\'s post - 4 - 7', 1443 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1444 | id: '05af9029-96ac-5e4c-89ff-440638f1ce2d', 1445 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1446 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1447 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1448 | }, 1449 | { 1450 | content: 'comment for John Adams\'s post - 4 - 8', 1451 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1452 | id: '42f43974-2db6-5841-ad4e-c5de3b5d4969', 1453 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1454 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1455 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1456 | }, 1457 | { 1458 | content: 'comment for John Adams\'s post - 4 - 9', 1459 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1460 | id: '2a05de4f-2d41-51ec-8378-f009506da7b0', 1461 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1462 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1463 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1464 | }, 1465 | { 1466 | content: 'comment for John Adams\'s post - 4 - 1', 1467 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1468 | id: '562d8174-60fe-51d4-b92c-2ab5db279dce', 1469 | postId: '28a1aa56-9b40-5b65-bf73-2b06e5c4b2b9', 1470 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1471 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1472 | }, 1473 | { 1474 | content: 'comment for John Adams\'s post - 5 - 1', 1475 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1476 | id: '95233368-a1ce-5a84-8067-469d3d00aec9', 1477 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1478 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1479 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1480 | }, 1481 | { 1482 | content: 'comment for John Adams\'s post - 5 - 9', 1483 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1484 | id: '0949bcbc-7ff5-535d-a7ff-5d0b5f331a22', 1485 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1486 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1487 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1488 | }, 1489 | { 1490 | content: 'comment for John Adams\'s post - 5 - 8', 1491 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1492 | id: '41a49007-f5db-5957-911d-2ab01f5b4bb2', 1493 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1494 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1495 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1496 | }, 1497 | { 1498 | content: 'comment for John Adams\'s post - 5 - 7', 1499 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1500 | id: '22e639ec-f2fc-57fb-a5a9-21e6b5c3d699', 1501 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1502 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1503 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1504 | }, 1505 | { 1506 | content: 'comment for John Adams\'s post - 5 - 6', 1507 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1508 | id: '5467fc63-eda2-530a-877b-e241e8b5dc7c', 1509 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1510 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1511 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1512 | }, 1513 | { 1514 | content: 'comment for John Adams\'s post - 5 - 5', 1515 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1516 | id: '0d663d7a-c1b2-5c19-8282-190721b73371', 1517 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1518 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1519 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1520 | }, 1521 | { 1522 | content: 'comment for John Adams\'s post - 5 - 4', 1523 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1524 | id: '0f4acf97-8d11-5c11-9e03-5891741c93a2', 1525 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1526 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1527 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1528 | }, 1529 | { 1530 | content: 'comment for John Adams\'s post - 5 - 3', 1531 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1532 | id: '86d603ee-434f-5770-a0af-bf4d60ece8cb', 1533 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1534 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1535 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1536 | }, 1537 | { 1538 | content: 'comment for John Adams\'s post - 5 - 2', 1539 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1540 | id: '07a24c0e-fb0a-5d10-92c3-2e05785942f4', 1541 | postId: '7d9368a4-7842-53d6-bb33-b5e7f8872831', 1542 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1543 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1544 | }, 1545 | { 1546 | content: 'comment for John Adams\'s post - 6 - 9', 1547 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1548 | id: '5a38cd41-d8a7-5a45-9a79-c96d4f1777bc', 1549 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1550 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1551 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1552 | }, 1553 | { 1554 | content: 'comment for John Adams\'s post - 6 - 8', 1555 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1556 | id: 'b5f83251-3544-5cab-920f-96c92e7fca00', 1557 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1558 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1559 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1560 | }, 1561 | { 1562 | content: 'comment for John Adams\'s post - 6 - 7', 1563 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1564 | id: 'd0d6c17c-8cdf-532c-aaab-55875b8913f9', 1565 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1566 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1567 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1568 | }, 1569 | { 1570 | content: 'comment for John Adams\'s post - 6 - 6', 1571 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1572 | id: '3b2406cf-bf8d-5cec-ba24-e6c6f63cf3ff', 1573 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1574 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1575 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1576 | }, 1577 | { 1578 | content: 'comment for John Adams\'s post - 6 - 5', 1579 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1580 | id: 'dd3baf07-6427-5f69-91ff-5b34fac916cb', 1581 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1582 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1583 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1584 | }, 1585 | { 1586 | content: 'comment for John Adams\'s post - 6 - 4', 1587 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1588 | id: '8be9c07c-d022-596d-af76-03be7f44e413', 1589 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1590 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1591 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1592 | }, 1593 | { 1594 | content: 'comment for John Adams\'s post - 6 - 3', 1595 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1596 | id: '4a4fe236-66f8-5aee-a7b4-6c53ac948fd4', 1597 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1598 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1599 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1600 | }, 1601 | { 1602 | content: 'comment for John Adams\'s post - 6 - 2', 1603 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1604 | id: 'ffb8931d-75c6-56ef-bff9-8f0fc31f27e4', 1605 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1606 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1607 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1608 | }, 1609 | { 1610 | content: 'comment for John Adams\'s post - 6 - 1', 1611 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1612 | id: '424eab4c-8b53-54b9-b467-25ca12c6eb2e', 1613 | postId: 'bb83c1e4-55af-50d7-8be9-1c05f566e80a', 1614 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1615 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1616 | }, 1617 | { 1618 | content: 'comment for John Adams\'s post - 7 - 1', 1619 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1620 | id: 'd251d7e8-ab60-5975-8bca-e5ca6a3486d1', 1621 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1622 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1623 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1624 | }, 1625 | { 1626 | content: 'comment for John Adams\'s post - 7 - 2', 1627 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1628 | id: 'c348f296-94a7-5868-b890-f84501aa87ae', 1629 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1630 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1631 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1632 | }, 1633 | { 1634 | content: 'comment for John Adams\'s post - 7 - 3', 1635 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1636 | id: '468c4e00-5824-5e69-bb56-f0c9639e143c', 1637 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1638 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1639 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1640 | }, 1641 | { 1642 | content: 'comment for John Adams\'s post - 7 - 4', 1643 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1644 | id: 'f57abb74-7c45-5dae-923d-2b90fa8e456e', 1645 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1646 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1647 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1648 | }, 1649 | { 1650 | content: 'comment for John Adams\'s post - 7 - 5', 1651 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1652 | id: 'b2f5d137-c32a-5dcb-8072-e8dd6632e49b', 1653 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1654 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1655 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1656 | }, 1657 | { 1658 | content: 'comment for John Adams\'s post - 7 - 6', 1659 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1660 | id: '33420cce-f536-544f-b220-816d36d43387', 1661 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1662 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1663 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1664 | }, 1665 | { 1666 | content: 'comment for John Adams\'s post - 7 - 7', 1667 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1668 | id: '699e053a-63ae-5aa5-b6b1-d8d5b28f27a6', 1669 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1670 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1671 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1672 | }, 1673 | { 1674 | content: 'comment for John Adams\'s post - 7 - 8', 1675 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1676 | id: '21b61233-f9b0-50f9-85a2-12437bd2aa17', 1677 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1678 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1679 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1680 | }, 1681 | { 1682 | content: 'comment for John Adams\'s post - 7 - 9', 1683 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1684 | id: '7901c493-cdbb-59d2-b83e-aa84f410ed90', 1685 | postId: '4c489ab1-2842-58a8-9cae-a5d30e08a9c7', 1686 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1687 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1688 | }, 1689 | { 1690 | content: 'comment for John Adams\'s post - 8 - 1', 1691 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1692 | id: '6ba2b859-80cf-5987-b080-4805e4e717f3', 1693 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1694 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1695 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1696 | }, 1697 | { 1698 | content: 'comment for John Adams\'s post - 8 - 2', 1699 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1700 | id: 'f9a359e8-860a-598b-8f36-9442845aeb40', 1701 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1702 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1703 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1704 | }, 1705 | { 1706 | content: 'comment for John Adams\'s post - 8 - 3', 1707 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1708 | id: '04cc64af-8d7f-5e1e-9911-6f23db547b80', 1709 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1710 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1711 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1712 | }, 1713 | { 1714 | content: 'comment for John Adams\'s post - 8 - 4', 1715 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1716 | id: '9adbd63b-f7eb-5df6-a64e-58422f42ae44', 1717 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1718 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1719 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1720 | }, 1721 | { 1722 | content: 'comment for John Adams\'s post - 8 - 5', 1723 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1724 | id: '69f86bcc-1955-5657-b8e1-332352bddd4e', 1725 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1726 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1727 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1728 | }, 1729 | { 1730 | content: 'comment for John Adams\'s post - 8 - 6', 1731 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1732 | id: '614524a2-7ac2-5101-94be-309cbb1e4b8c', 1733 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1734 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1735 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1736 | }, 1737 | { 1738 | content: 'comment for John Adams\'s post - 8 - 7', 1739 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1740 | id: '3bf3fd25-4177-5b12-87d4-23cb8006a541', 1741 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1742 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1743 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1744 | }, 1745 | { 1746 | content: 'comment for John Adams\'s post - 8 - 8', 1747 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1748 | id: '386ac2c6-74f9-59fb-b4e5-7ea39630e7d7', 1749 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1750 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1751 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1752 | }, 1753 | { 1754 | content: 'comment for John Adams\'s post - 8 - 9', 1755 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1756 | id: '47563e7e-15f2-52fa-a4a5-17c054528252', 1757 | postId: '9bba795f-dc9b-5c2e-ade6-b47b33922325', 1758 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1759 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1760 | }, 1761 | { 1762 | content: 'comment for John Adams\'s post - 9 - 1', 1763 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1764 | id: '7592620f-f61f-552c-addb-fe7dad256ffc', 1765 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1766 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1767 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1768 | }, 1769 | { 1770 | content: 'comment for John Adams\'s post - 9 - 9', 1771 | createdAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1772 | id: 'fa664883-8425-501a-a776-d6197b198997', 1773 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1774 | updatedAt: Date 2021-07-31 08:53:06 74ms UTC {}, 1775 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1776 | }, 1777 | { 1778 | content: 'comment for John Adams\'s post - 9 - 8', 1779 | createdAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1780 | id: 'b7b05a6d-4c7a-5361-9f8a-6d9dda16def0', 1781 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1782 | updatedAt: Date 2021-07-30 08:53:06 74ms UTC {}, 1783 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1784 | }, 1785 | { 1786 | content: 'comment for John Adams\'s post - 9 - 7', 1787 | createdAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1788 | id: 'a5ade79f-73f4-5172-99cb-5ab499b6a41b', 1789 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1790 | updatedAt: Date 2021-07-29 08:53:06 74ms UTC {}, 1791 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1792 | }, 1793 | { 1794 | content: 'comment for John Adams\'s post - 9 - 6', 1795 | createdAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1796 | id: 'ccfd9e38-49d9-57af-a21c-41c3eab0c45b', 1797 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1798 | updatedAt: Date 2021-07-28 08:53:06 74ms UTC {}, 1799 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1800 | }, 1801 | { 1802 | content: 'comment for John Adams\'s post - 9 - 5', 1803 | createdAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1804 | id: 'b0de9aff-4dd5-58ba-b920-8161c6275355', 1805 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1806 | updatedAt: Date 2021-07-27 08:53:06 74ms UTC {}, 1807 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1808 | }, 1809 | { 1810 | content: 'comment for John Adams\'s post - 9 - 4', 1811 | createdAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1812 | id: '285c86f4-7dd5-552d-ba22-5b594ee09ddb', 1813 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1814 | updatedAt: Date 2021-07-26 08:53:06 74ms UTC {}, 1815 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1816 | }, 1817 | { 1818 | content: 'comment for John Adams\'s post - 9 - 3', 1819 | createdAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1820 | id: '63c05a87-9ec8-5c4c-af41-f0daa72b7c46', 1821 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1822 | updatedAt: Date 2021-07-25 08:53:06 74ms UTC {}, 1823 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1824 | }, 1825 | { 1826 | content: 'comment for John Adams\'s post - 9 - 2', 1827 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1828 | id: 'd2c506ed-d956-5826-80a8-b71b3cc0b3f0', 1829 | postId: '4df2c35a-5d7a-570f-b3a3-860218f9aa9d', 1830 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1831 | userId: '8c5c8c10-c821-5115-afa9-8d6330420b43', 1832 | }, 1833 | ], 1834 | ] 1835 | 1836 | ## BatchLoader - manyToMany with pagination 1837 | 1838 | > Snapshot 1 1839 | 1840 | [ 1841 | [ 1842 | { 1843 | createdAt: Date 2021-07-22 08:53:06 74ms UTC {}, 1844 | id: 'ad41ceac-fa6c-58a9-8c2e-31099e52fe93', 1845 | name: 'tag_a', 1846 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 1847 | relationIndex: '1', 1848 | updatedAt: Date 2021-07-22 08:53:06 74ms UTC {}, 1849 | }, 1850 | ], 1851 | [ 1852 | { 1853 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1854 | id: '28e0a040-1aff-5df4-a1c4-b6b76ab66649', 1855 | name: 'tag_b', 1856 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 1857 | relationIndex: '1', 1858 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1859 | }, 1860 | ], 1861 | [ 1862 | { 1863 | createdAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1864 | id: '50ba9883-96ab-5822-a68f-c412a7873a06', 1865 | name: 'tag_c', 1866 | postId: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 1867 | relationIndex: '1', 1868 | updatedAt: Date 2021-07-24 08:53:06 74ms UTC {}, 1869 | }, 1870 | ], 1871 | ] 1872 | 1873 | ## BatchLoader - manyToMany without pagination 1874 | 1875 | > Snapshot 1 1876 | 1877 | [ 1878 | [ 1879 | { 1880 | createdAt: Date 2021-07-22 08:53:06 74ms UTC {}, 1881 | id: 'ad41ceac-fa6c-58a9-8c2e-31099e52fe93', 1882 | name: 'tag_a', 1883 | postId: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 1884 | updatedAt: Date 2021-07-22 08:53:06 74ms UTC {}, 1885 | }, 1886 | ], 1887 | [ 1888 | { 1889 | createdAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1890 | id: '28e0a040-1aff-5df4-a1c4-b6b76ab66649', 1891 | name: 'tag_b', 1892 | postId: '59771563-9b2b-5907-94b1-2e46da2977ee', 1893 | updatedAt: Date 2021-07-23 08:53:06 74ms UTC {}, 1894 | }, 1895 | ], 1896 | ] 1897 | -------------------------------------------------------------------------------- /tests/snapshots/BatchLoader.test.ts.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acro5piano/knex-graphql-utils/a918acba64e5b2ffe6ae29d4b232dbf2e864086d/tests/snapshots/BatchLoader.test.ts.snap -------------------------------------------------------------------------------- /tests/snapshots/SelectionFilter.test.ts.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `tests/SelectionFilter.test.ts` 2 | 3 | The actual snapshot is saved in `SelectionFilter.test.ts.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## SelectionFilter 8 | 9 | > Snapshot 1 10 | 11 | 'select "id", "name" from "users" limit $1' 12 | 13 | > Snapshot 2 14 | 15 | 'select "id", "created_at" from "posts" where "user_id" = $1' 16 | 17 | > Snapshot 3 18 | 19 | { 20 | data: { 21 | user: { 22 | id: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 23 | name: 'George Washington', 24 | posts: [ 25 | { 26 | createdAt: '1627030386074', 27 | id: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 28 | }, 29 | { 30 | createdAt: '1627116786074', 31 | id: '59771563-9b2b-5907-94b1-2e46da2977ee', 32 | }, 33 | { 34 | createdAt: '1627203186074', 35 | id: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 36 | }, 37 | { 38 | createdAt: '1627289586074', 39 | id: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 40 | }, 41 | { 42 | createdAt: '1627375986074', 43 | id: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 44 | }, 45 | { 46 | createdAt: '1627462386074', 47 | id: 'a3fd465a-ca16-57f0-8397-2c70b0a0f417', 48 | }, 49 | { 50 | createdAt: '1627548786074', 51 | id: '62ddbdd2-795c-5c18-acc9-4727133dd58a', 52 | }, 53 | { 54 | createdAt: '1627635186074', 55 | id: '4dafe8ab-80a7-52f5-944a-dad6bb70353b', 56 | }, 57 | { 58 | createdAt: '1627721586074', 59 | id: 'bf67b9fb-1eed-534b-a234-1a83daac11c0', 60 | }, 61 | ], 62 | }, 63 | }, 64 | } 65 | -------------------------------------------------------------------------------- /tests/snapshots/SelectionFilter.test.ts.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acro5piano/knex-graphql-utils/a918acba64e5b2ffe6ae29d4b232dbf2e864086d/tests/snapshots/SelectionFilter.test.ts.snap -------------------------------------------------------------------------------- /tests/snapshots/integration.test.ts.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `tests/integration.test.ts` 2 | 3 | The actual snapshot is saved in `integration.test.ts.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## BatchLoader + SelectionFilter 8 | 9 | > Snapshot 1 10 | 11 | 'select "id", "name" from "users" limit $1' 12 | 13 | > Snapshot 2 14 | 15 | 'select "id", "user_id" from (select *, row_number() over (partition by "user_id" order by "created_at" asc) as relation_index from "posts" where "user_id" in ($1)) as "_t" where "relation_index" between $2 and $3' 16 | 17 | > Snapshot 3 18 | 19 | 'select "id", "post_id", "content" from (select *, row_number() over (partition by "post_id" order by "created_at" asc) as relation_index from "comments" where "post_id" in ($1, $2, $3, $4, $5)) as "_t" where "relation_index" between $6 and $7' 20 | 21 | > Snapshot 4 22 | 23 | { 24 | data: { 25 | user: { 26 | id: '29fc8dca-7230-54cf-96be-7fa1a79c2c1a', 27 | name: 'George Washington', 28 | posts: [ 29 | { 30 | comments: [ 31 | { 32 | content: 'comment for George Washington\'s post - 1 - 1', 33 | id: '4decc497-3e7e-55b0-b775-85502f425040', 34 | }, 35 | { 36 | content: 'comment for George Washington\'s post - 1 - 2', 37 | id: 'e596c693-9699-55f5-9dda-238366c7dd27', 38 | }, 39 | { 40 | content: 'comment for George Washington\'s post - 1 - 3', 41 | id: '5ded340e-7a89-5678-99af-e658c3c46976', 42 | }, 43 | { 44 | content: 'comment for George Washington\'s post - 1 - 4', 45 | id: '71c313fe-80c1-56a3-9013-f423890f4381', 46 | }, 47 | { 48 | content: 'comment for George Washington\'s post - 1 - 5', 49 | id: '40703794-a38e-57a3-9c65-bf9feecfa2e5', 50 | }, 51 | ], 52 | id: '8ef5a19f-63ba-579d-b4e0-af2b67923550', 53 | }, 54 | { 55 | comments: [ 56 | { 57 | content: 'comment for George Washington\'s post - 2 - 1', 58 | id: 'ffe6a8aa-909a-5022-817d-00adc9cf3647', 59 | }, 60 | { 61 | content: 'comment for George Washington\'s post - 2 - 2', 62 | id: 'bf65a3b4-0854-5591-a08c-fa811a8f4a50', 63 | }, 64 | { 65 | content: 'comment for George Washington\'s post - 2 - 3', 66 | id: '96bf447c-c2a5-5fb7-9b57-b8495f76f7d4', 67 | }, 68 | { 69 | content: 'comment for George Washington\'s post - 2 - 4', 70 | id: 'bf58d419-f8d4-5fdb-a651-7e4b8cbb33a7', 71 | }, 72 | { 73 | content: 'comment for George Washington\'s post - 2 - 5', 74 | id: 'b86e8113-0bcd-5bf2-8c5d-8eb7893f86ac', 75 | }, 76 | ], 77 | id: '59771563-9b2b-5907-94b1-2e46da2977ee', 78 | }, 79 | { 80 | comments: [ 81 | { 82 | content: 'comment for George Washington\'s post - 3 - 1', 83 | id: '490a8c4e-dbd1-503b-b89c-aa1eed7062d7', 84 | }, 85 | { 86 | content: 'comment for George Washington\'s post - 3 - 2', 87 | id: 'b9a067b6-09af-5ac8-a2fb-50a4043849ab', 88 | }, 89 | { 90 | content: 'comment for George Washington\'s post - 3 - 3', 91 | id: '9a66b891-8d36-5e10-9016-541113fa5cf9', 92 | }, 93 | { 94 | content: 'comment for George Washington\'s post - 3 - 4', 95 | id: 'ac03696f-1aab-54d5-96f5-9f94bae0eb38', 96 | }, 97 | { 98 | content: 'comment for George Washington\'s post - 3 - 5', 99 | id: 'c6f9c440-f579-5b67-af57-ae4630e7ba4d', 100 | }, 101 | ], 102 | id: 'ae05d502-1d79-5a60-b6ce-b57650e8694e', 103 | }, 104 | { 105 | comments: [ 106 | { 107 | content: 'comment for George Washington\'s post - 4 - 1', 108 | id: '505b751c-a5c4-51c5-bf71-4c8e66fcd97f', 109 | }, 110 | { 111 | content: 'comment for George Washington\'s post - 4 - 2', 112 | id: '0e7816b5-acd1-5286-9e12-a43c4362b60c', 113 | }, 114 | { 115 | content: 'comment for George Washington\'s post - 4 - 3', 116 | id: '90334f0e-4716-5f60-8ccf-6cdb403cd60d', 117 | }, 118 | { 119 | content: 'comment for George Washington\'s post - 4 - 4', 120 | id: 'b1551ba5-c724-58eb-b49f-4ab72bc7fac8', 121 | }, 122 | { 123 | content: 'comment for George Washington\'s post - 4 - 5', 124 | id: '7b29e0ad-fcb1-5afb-8c79-099f7ca2e0d9', 125 | }, 126 | ], 127 | id: '59fdcf6e-f0fa-5b3a-9cb9-3e46cb36086a', 128 | }, 129 | { 130 | comments: [ 131 | { 132 | content: 'comment for George Washington\'s post - 5 - 1', 133 | id: 'addce678-3b67-5589-b8e0-bb315e842521', 134 | }, 135 | { 136 | content: 'comment for George Washington\'s post - 5 - 2', 137 | id: 'fd7d56e6-61d2-5fc4-a755-2546b5787c70', 138 | }, 139 | { 140 | content: 'comment for George Washington\'s post - 5 - 3', 141 | id: '070c45dc-30ea-58e8-a9c4-3ef3f021ef56', 142 | }, 143 | { 144 | content: 'comment for George Washington\'s post - 5 - 4', 145 | id: '1d233231-7122-5bde-ac62-3779a2aa08b2', 146 | }, 147 | { 148 | content: 'comment for George Washington\'s post - 5 - 5', 149 | id: 'bec1a793-0050-5187-b95b-9604feb42940', 150 | }, 151 | ], 152 | id: 'ebcf8f20-0a65-55f7-8828-1f5b275fb6c2', 153 | }, 154 | ], 155 | }, 156 | }, 157 | } 158 | -------------------------------------------------------------------------------- /tests/snapshots/integration.test.ts.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acro5piano/knex-graphql-utils/a918acba64e5b2ffe6ae29d4b232dbf2e864086d/tests/snapshots/integration.test.ts.snap -------------------------------------------------------------------------------- /tests/util.ts: -------------------------------------------------------------------------------- 1 | export const gql = String.raw 2 | -------------------------------------------------------------------------------- /tools/generate-fixture.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | 4 | // Please run `yarn test --update-snapshots` after you execute this script. 5 | import dayjs from 'dayjs' 6 | import * as R from 'remeda' 7 | import { v5 } from 'uuid' 8 | 9 | // prettier-ignore 10 | const presidents = [ 'George Washington', 'John Adams', 'Thomas Jefferson', 'James Madison', 'James Monroe', 'John Quincy Adams', 'Andrew Jackson', 'Martin Van Buren', 'William Henry Harrison', 'John Tyler', 'James K. Polk', 'Zachary Taylor', 'Millard Fillmore', 'Franklin Pierce', 'James Buchanan', 'Abraham Lincoln', 'Andrew Johnson', 'Ulysses S. Grant', 'Rutherford B. Hayes', 'James A. Garfield', 'Chester A. Arthur', 'Grover Cleveland', 'Benjamin Harrison', 'Grover Cleveland (2nd term)', 'William McKinley', 'Theodore Roosevelt', 'William Howard Taft', 'Woodrow Wilson', 'Warren G. Harding', 'Calvin Coolidge', 'Herbert Hoover', 'Franklin D. Roosevelt', 'Harry S. Truman', 'Dwight D. Eisenhower', 'John F. Kennedy', 'Lyndon B. Johnson', 'Richard Nixon', 'Gerald Ford', 'Jimmy Carter', 'Ronald Reagan', 'George H. W. Bush', 'Bill Clinton', 'George W. Bush', 'Barack Obama', 'Donal Trump', 'Joe Biden', ] 11 | // prettier-ignore 12 | const presetTags = [ 'tag_a', 'tag_b', 'tag_c', 'tag_d', 'tag_e' ] 13 | 14 | const t = dayjs('2021-07-22T08:53:06.074Z') 15 | 16 | const getTimeStamps = (index: number) => { 17 | return { 18 | createdAt: t.add(index, 'days').toDate(), 19 | updatedAt: t.add(index, 'days').toDate(), 20 | } 21 | } 22 | 23 | const makeId = (...names: Array) => 24 | v5(names.map(String).join(':'), '15584352-dc37-48bb-8551-bbe5e8366606') 25 | 26 | function repeatArray(arr: Array, n: number) { 27 | return R.range(1, n).flatMap(() => arr) 28 | } 29 | 30 | const users = presidents.map((name, i) => ({ 31 | id: makeId(name, i), 32 | name, 33 | ...getTimeStamps(i), 34 | })) 35 | 36 | const tags = presetTags.map((name, i) => ({ 37 | id: makeId(name, i), 38 | name, 39 | ...getTimeStamps(i), 40 | })) 41 | 42 | const posts = R.pipe( 43 | users, 44 | R.flatMap((user) => 45 | R.pipe( 46 | R.range(1, 10), 47 | R.map((i) => ({ 48 | id: makeId(user.id, i), 49 | userId: user.id, 50 | title: `${user.name}'s post - ${i}`, 51 | ...getTimeStamps(i), 52 | })), 53 | ), 54 | ), 55 | ) 56 | 57 | const tagsPosts = R.zipWith( 58 | repeatArray(tags, 4), 59 | posts.slice(0, 20), 60 | (tag, post) => ({ 61 | id: makeId(tag.id, post.id), 62 | tagId: tag.id, 63 | postId: post.id, 64 | }), 65 | ) 66 | 67 | const comments = R.pipe( 68 | posts, 69 | R.flatMap((post) => 70 | R.pipe( 71 | R.range(1, 10), 72 | R.map((i) => ({ 73 | id: makeId(post.id, i), 74 | postId: post.id, 75 | content: `comment for ${post.title} - ${i}`, 76 | ...getTimeStamps(i), 77 | })), 78 | ), 79 | ), 80 | ) 81 | 82 | fs.writeFileSync( 83 | path.resolve(__dirname, '../tests/fixtures.json'), 84 | JSON.stringify({ users, posts, comments, tags, tagsPosts }, undefined, 2), 85 | 'utf8', 86 | ) 87 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | "lib": ["ESNext"], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | "resolveJsonModule": true, 12 | // "checkJs": true, /* Report errors in .js files. */ 13 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ 14 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 15 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 16 | "sourceMap": true, /* Generates corresponding '.map' file. */ 17 | // "outFile": "./", /* Concatenate and emit output to single file. */ 18 | "outDir": "./dist", /* Redirect output structure to the directory. */ 19 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 20 | // "composite": true, /* Enable project compilation */ 21 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 22 | "removeComments": false, /* Do not emit comments to output. */ 23 | // "noEmit": true, /* Do not emit outputs. */ 24 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 25 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 26 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 27 | 28 | /* Strict Type-Checking Options */ 29 | "strict": true, /* Enable all strict type-checking options. */ 30 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 31 | // "strictNullChecks": true, /* Enable strict null checks. */ 32 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 33 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 34 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 35 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 36 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 37 | 38 | /* Additional Checks */ 39 | "noUnusedLocals": true, /* Report errors on unused locals. */ 40 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 41 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 42 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 43 | "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 44 | "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ 45 | "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ 46 | 47 | /* Module Resolution Options */ 48 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 49 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 50 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 51 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 52 | // "typeRoots": [], /* List of folders to include type definitions from. */ 53 | // "types": [], /* Type declaration files to be included in compilation. */ 54 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 55 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 56 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 57 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 58 | 59 | /* Source Map Options */ 60 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 61 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 62 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 63 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 64 | 65 | /* Experimental Options */ 66 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 67 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 68 | 69 | /* Advanced Options */ 70 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 71 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src"], 4 | "exclude": ["build"] 5 | } 6 | --------------------------------------------------------------------------------