diff --git a/examples/federation-v2/graphql-gateway/src/app.module.ts b/examples/federation-v2/graphql-gateway/src/app.module.ts new file mode 100644 index 000000000..b32ee1760 --- /dev/null +++ b/examples/federation-v2/graphql-gateway/src/app.module.ts @@ -0,0 +1,23 @@ +import { IntrospectAndCompose } from '@apollo/gateway' +import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo' +import { Module } from '@nestjs/common' +import { GraphQLModule } from '@nestjs/graphql' + +@Module({ + imports: [ + GraphQLModule.forRoot({ + driver: ApolloGatewayDriver, + gateway: { + supergraphSdl: new IntrospectAndCompose({ + subgraphs: [ + { name: 'todo-items', url: 'http://localhost:3001/graphql' }, + { name: 'sub-tasks', url: 'http://localhost:3002/graphql' }, + { name: 'tags', url: 'http://localhost:3003/graphql' }, + { name: 'user', url: 'http://localhost:3004/graphql' } + ] + }) + } + }) + ] +}) +export class AppModule {} diff --git a/examples/federation-v2/graphql-gateway/src/main.ts b/examples/federation-v2/graphql-gateway/src/main.ts new file mode 100644 index 000000000..6ac9c983a --- /dev/null +++ b/examples/federation-v2/graphql-gateway/src/main.ts @@ -0,0 +1,23 @@ +import { ValidationPipe } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' + +import { AppModule } from './app.module' + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.listen(3000) +} + +// eslint-disable-next-line no-void +void bootstrap() diff --git a/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/graphql-fragments.ts b/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/graphql-fragments.ts new file mode 100644 index 000000000..64f834801 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/graphql-fragments.ts @@ -0,0 +1,29 @@ +export const todoItemFields = ` + id + ` + +export const subTaskFields = ` +id +title +description +completed +todoItemId +` + +export const pageInfoField = ` +pageInfo{ + hasNextPage + hasPreviousPage + startCursor + endCursor +} +` + +export const edgeNodes = (fields: string): string => ` + edges { + node{ + ${fields} + } + cursor + } + ` diff --git a/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/index.ts b/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/index.ts new file mode 100644 index 000000000..470528082 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/e2e/__fixtures__/index.ts @@ -0,0 +1,34 @@ +import { Connection } from 'typeorm' + +import { executeTruncate } from '../../../../helpers' +import { SubTaskEntity } from '../../src/sub-task/sub-task.entity' + +const tables = ['sub_task'] +export const truncate = async (connection: Connection): Promise => executeTruncate(connection, tables) + +export const refresh = async (connection: Connection): Promise => { + await truncate(connection) + + const todoItems = [ + { id: 1, title: 'Create Nest App' }, + { id: 2, title: 'Create Entity' }, + { id: 3, title: 'Create Entity Service' }, + { id: 4, title: 'Add Todo Item Resolver' }, + { id: 5, title: 'How to create item With Sub Tasks' } + ] + const subTaskRepo = connection.getRepository(SubTaskEntity) + + await subTaskRepo.save( + todoItems.reduce( + (subTasks, todo) => [ + ...subTasks, + { completed: true, title: `${todo.title} - Sub Task 1`, todoItemId: todo.id }, + { completed: false, title: `${todo.title} - Sub Task 2`, todoItemId: todo.id }, + { completed: false, title: `${todo.title} - Sub Task 3`, todoItemId: todo.id } + ], + [] as Partial[] + ) + ) +} + +export * from './graphql-fragments' diff --git a/examples/federation-v2/sub-task-graphql/e2e/sub-task.resolver.spec.ts b/examples/federation-v2/sub-task-graphql/e2e/sub-task.resolver.spec.ts new file mode 100644 index 000000000..2cc85ab9a --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/e2e/sub-task.resolver.spec.ts @@ -0,0 +1,695 @@ +import { INestApplication, ValidationPipe } from '@nestjs/common' +import { Test } from '@nestjs/testing' +import { CursorConnectionType } from '@ptc-org/nestjs-query-graphql' +import request from 'supertest' +import { Connection } from 'typeorm' + +import { AppModule } from '../src/app.module' +import { SubTaskDTO } from '../src/sub-task/dto/sub-task.dto' +import { edgeNodes, pageInfoField, refresh, subTaskFields, todoItemFields } from './__fixtures__' + +describe('Federated v2 - SubTaskResolver (e2e)', () => { + let app: INestApplication + + beforeAll(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [AppModule] + }).compile() + + app = moduleRef.createNestApplication() + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.init() + await refresh(app.get(Connection)) + }) + + afterAll(() => refresh(app.get(Connection))) + + const subTasks = [ + { id: '1', title: 'Create Nest App - Sub Task 1', completed: true, description: null, todoItemId: 1 }, + { id: '2', title: 'Create Nest App - Sub Task 2', completed: false, description: null, todoItemId: 1 }, + { id: '3', title: 'Create Nest App - Sub Task 3', completed: false, description: null, todoItemId: 1 }, + { id: '4', title: 'Create Entity - Sub Task 1', completed: true, description: null, todoItemId: 2 }, + { id: '5', title: 'Create Entity - Sub Task 2', completed: false, description: null, todoItemId: 2 }, + { id: '6', title: 'Create Entity - Sub Task 3', completed: false, description: null, todoItemId: 2 }, + { + id: '7', + title: 'Create Entity Service - Sub Task 1', + completed: true, + description: null, + todoItemId: 3 + }, + { + id: '8', + title: 'Create Entity Service - Sub Task 2', + completed: false, + description: null, + todoItemId: 3 + }, + { + id: '9', + title: 'Create Entity Service - Sub Task 3', + completed: false, + description: null, + todoItemId: 3 + }, + { + id: '10', + title: 'Add Todo Item Resolver - Sub Task 1', + completed: true, + description: null, + todoItemId: 4 + }, + { + completed: false, + description: null, + id: '11', + title: 'Add Todo Item Resolver - Sub Task 2', + todoItemId: 4 + }, + { + completed: false, + description: null, + id: '12', + title: 'Add Todo Item Resolver - Sub Task 3', + todoItemId: 4 + }, + { + completed: true, + description: null, + id: '13', + title: 'How to create item With Sub Tasks - Sub Task 1', + todoItemId: 5 + }, + { + completed: false, + description: null, + id: '14', + title: 'How to create item With Sub Tasks - Sub Task 2', + todoItemId: 5 + }, + { + completed: false, + description: null, + id: '15', + title: 'How to create item With Sub Tasks - Sub Task 3', + todoItemId: 5 + } + ] + + describe('find one', () => { + it(`should a sub task by id`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTask(id: 1) { + ${subTaskFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + subTask: { + id: '1', + title: 'Create Nest App - Sub Task 1', + completed: true, + description: null, + todoItemId: 1 + } + } + }) + })) + + it(`should throw item not found on non existing sub task`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTask(id: 100) { + ${subTaskFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toContain('Unable to find') + })) + + it(`should return a todo item`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTask(id: 1) { + todoItem { + ${todoItemFields} + } + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + subTask: { + todoItem: { + id: '1' + } + } + } + }) + })) + }) + + describe('query', () => { + it(`should return a connection`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTasks { + ${pageInfoField} + ${edgeNodes(subTaskFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.subTasks + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjk=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(10) + expect(edges.map((e) => e.node)).toEqual(subTasks.slice(0, 10)) + })) + + it(`should allow querying`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTasks(filter: { id: { in: [1, 2, 3] } }) { + ${pageInfoField} + ${edgeNodes(subTaskFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.subTasks + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(3) + expect(edges.map((e) => e.node)).toEqual(subTasks.slice(0, 3)) + })) + + it(`should allow sorting`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTasks(sorting: [{field: id, direction: DESC}]) { + ${pageInfoField} + ${edgeNodes(subTaskFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.subTasks + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjk=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(10) + expect(edges.map((e) => e.node)).toEqual(subTasks.slice().reverse().slice(0, 10)) + })) + + describe('paging', () => { + it(`should allow paging with the 'first' field`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTasks(paging: {first: 2}) { + ${pageInfoField} + ${edgeNodes(subTaskFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.subTasks + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual(subTasks.slice(0, 2)) + })) + + it(`should allow paging with the 'first' field and 'after'`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + subTasks(paging: {first: 2, after: "YXJyYXljb25uZWN0aW9uOjE="}) { + ${pageInfoField} + ${edgeNodes(subTaskFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.subTasks + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjM=', + hasNextPage: true, + hasPreviousPage: true, + startCursor: 'YXJyYXljb25uZWN0aW9uOjI=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual(subTasks.slice(2, 4)) + })) + }) + }) + + describe('create one', () => { + it('should allow creating a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneSubTask( + input: { + subTask: { title: "Test SubTask", completed: false, todoItemId: "1" } + } + ) { + ${subTaskFields} + } + }` + }) + .expect(200, { + data: { + createOneSubTask: { + id: '16', + title: 'Test SubTask', + description: null, + completed: false, + todoItemId: 1 + } + } + })) + + it('should validate a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneSubTask( + input: { + subTask: { title: "", completed: false, todoItemId: "1" } + } + ) { + ${subTaskFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title should not be empty') + })) + }) + + describe('create many', () => { + it('should allow creating a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManySubTasks( + input: { + subTasks: [ + { title: "Test Create Many SubTask - 1", completed: false, todoItemId: "2" }, + { title: "Test Create Many SubTask - 2", completed: true, todoItemId: "2" }, + ] + } + ) { + ${subTaskFields} + } + }` + }) + .expect(200, { + data: { + createManySubTasks: [ + { id: '17', title: 'Test Create Many SubTask - 1', description: null, completed: false, todoItemId: 2 }, + { id: '18', title: 'Test Create Many SubTask - 2', description: null, completed: true, todoItemId: 2 } + ] + } + })) + + it('should validate a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManySubTasks( + input: { + subTasks: [{ title: "", completed: false, todoItemId: "2" }] + } + ) { + ${subTaskFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title should not be empty') + })) + }) + + describe('update one', () => { + it('should allow updating a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneSubTask( + input: { + id: "16", + update: { title: "Update Test Sub Task", completed: true } + } + ) { + ${subTaskFields} + } + }` + }) + .expect(200, { + data: { + updateOneSubTask: { + id: '16', + title: 'Update Test Sub Task', + description: null, + completed: true, + todoItemId: 1 + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneSubTask( + input: { + update: { title: "Update Test Sub Task" } + } + ) { + id + title + completed + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "UpdateOneSubTaskInput.id" of required type "ID!" was not provided.') + })) + + it('should validate an update', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneSubTask( + input: { + id: "16", + update: { title: "" } + } + ) { + id + title + completed + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title should not be empty') + })) + }) + + describe('update many', () => { + it('should allow updating a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManySubTasks( + input: { + filter: {id: { in: ["17", "18"]} }, + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(200, { + data: { + updateManySubTasks: { + updatedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManySubTasks( + input: { + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "UpdateManySubTasksInput.filter" of required type "SubTaskUpdateFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManySubTasks( + input: { + filter: { }, + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + describe('delete one', () => { + it('should allow deleting a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneSubTask( + input: { id: "16" } + ) { + ${subTaskFields} + } + }` + }) + .expect(200, { + data: { + deleteOneSubTask: { + id: null, + title: 'Update Test Sub Task', + completed: true, + description: null, + todoItemId: 1 + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneSubTask( + input: { } + ) { + ${subTaskFields} + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "DeleteOneSubTaskInput.id" of required type "ID!" was not provided.') + })) + }) + + describe('delete many', () => { + it('should allow updating a subTask', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManySubTasks( + input: { + filter: {id: { in: ["17", "18"]} }, + } + ) { + deletedCount + } + }` + }) + .expect(200, { + data: { + deleteManySubTasks: { + deletedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManySubTasks( + input: { } + ) { + deletedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "DeleteManySubTasksInput.filter" of required type "SubTaskDeleteFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManySubTasks( + input: { + filter: { }, + } + ) { + deletedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + afterAll(async () => { + await app.close() + }) +}) diff --git a/examples/federation-v2/sub-task-graphql/schema.gql b/examples/federation-v2/sub-task-graphql/schema.gql new file mode 100644 index 000000000..d9cefbb04 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/schema.gql @@ -0,0 +1,327 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +type TodoItem { + id: ID! + subTasks( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: SubTaskFilter! = {} + + """Specify to sort results.""" + sorting: [SubTaskSort!]! = [] + ): TodoItemSubTasksConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +input SubTaskFilter { + and: [SubTaskFilter!] + or: [SubTaskFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input BooleanFieldComparison { + is: Boolean + isNot: Boolean +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input NumberFieldComparison { + is: Boolean + isNot: Boolean + eq: Float + neq: Float + gt: Float + gte: Float + lt: Float + lte: Float + in: [Float!] + notIn: [Float!] + between: NumberFieldComparisonBetween + notBetween: NumberFieldComparisonBetween +} + +input NumberFieldComparisonBetween { + lower: Float! + upper: Float! +} + +input SubTaskSort { + field: SubTaskSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum SubTaskSortFields { + id + title + description + completed + created + updated + todoItemId +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type SubTask { + id: ID! + title: String! + description: String + completed: Boolean! + created: DateTime! + updated: DateTime! + todoItemId: Float! + todoItem: TodoItem! +} + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type SubTaskDeleteResponse { + id: ID + title: String + description: String + completed: Boolean + created: DateTime + updated: DateTime + todoItemId: Float +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type SubTaskEdge { + """The node containing the SubTask""" + node: SubTask! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type SubTaskConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [SubTaskEdge!]! +} + +type TodoItemSubTasksConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [SubTaskEdge!]! +} + +type Query { + subTask( + """The id of the record to find.""" + id: ID! + ): SubTask! + subTasks( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: SubTaskFilter! = {} + + """Specify to sort results.""" + sorting: [SubTaskSort!]! = [] + ): SubTaskConnection! +} + +type Mutation { + createOneSubTask(input: CreateOneSubTaskInput!): SubTask! + createManySubTasks(input: CreateManySubTasksInput!): [SubTask!]! + updateOneSubTask(input: UpdateOneSubTaskInput!): SubTask! + updateManySubTasks(input: UpdateManySubTasksInput!): UpdateManyResponse! + deleteOneSubTask(input: DeleteOneSubTaskInput!): SubTaskDeleteResponse! + deleteManySubTasks(input: DeleteManySubTasksInput!): DeleteManyResponse! +} + +input CreateOneSubTaskInput { + """The record to create""" + subTask: SubTaskInput! +} + +input SubTaskInput { + title: String! + description: String + completed: Boolean! + todoItemId: ID! +} + +input CreateManySubTasksInput { + """Array of records to create""" + subTasks: [SubTaskInput!]! +} + +input UpdateOneSubTaskInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: SubTaskUpdate! +} + +input SubTaskUpdate { + title: String! + description: String + completed: Boolean + todoItemId: Float +} + +input UpdateManySubTasksInput { + """Filter used to find fields to update""" + filter: SubTaskUpdateFilter! + + """The update to apply to all records found using the filter""" + update: SubTaskUpdate! +} + +input SubTaskUpdateFilter { + and: [SubTaskUpdateFilter!] + or: [SubTaskUpdateFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} + +input DeleteOneSubTaskInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManySubTasksInput { + """Filter to find records to delete""" + filter: SubTaskDeleteFilter! +} + +input SubTaskDeleteFilter { + and: [SubTaskDeleteFilter!] + or: [SubTaskDeleteFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} \ No newline at end of file diff --git a/examples/federation-v2/sub-task-graphql/src/app.module.ts b/examples/federation-v2/sub-task-graphql/src/app.module.ts new file mode 100644 index 000000000..0966df61f --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/app.module.ts @@ -0,0 +1,22 @@ +import { ApolloFederationDriver } from '@nestjs/apollo' +import { Module } from '@nestjs/common' +import { GraphQLModule } from '@nestjs/graphql' +import { TypeOrmModule } from '@nestjs/typeorm' + +import { typeormOrmConfig } from '../../../helpers' +import { SubTaskModule } from './sub-task/sub-task.module' + +@Module({ + imports: [ + TypeOrmModule.forRoot(typeormOrmConfig('federation_sub_task')), + GraphQLModule.forRoot({ + driver: ApolloFederationDriver, + autoSchemaFile: { + federation: 2, + path: 'examples/federation-v2/sub-task-graphql/schema.gql' + } + }), + SubTaskModule + ] +}) +export class AppModule {} diff --git a/examples/federation-v2/sub-task-graphql/src/main.ts b/examples/federation-v2/sub-task-graphql/src/main.ts new file mode 100644 index 000000000..ef31cf2ba --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/main.ts @@ -0,0 +1,23 @@ +import { ValidationPipe } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' + +import { AppModule } from './app.module' + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.listen(3002) +} + +// eslint-disable-next-line no-void +void bootstrap() diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/dto/sub-task.dto.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/sub-task.dto.ts new file mode 100644 index 000000000..959565e9a --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/sub-task.dto.ts @@ -0,0 +1,29 @@ +import { GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql' +import { FilterableField, Reference } from '@ptc-org/nestjs-query-graphql' + +import { TodoItemReferenceDTO } from './todo-item-reference.dto' + +@ObjectType('SubTask') +@Reference('todoItem', () => TodoItemReferenceDTO, { id: 'todoItemId' }) +export class SubTaskDTO { + @FilterableField(() => ID) + id!: number + + @FilterableField() + title!: string + + @FilterableField({ nullable: true }) + description?: string + + @FilterableField() + completed!: boolean + + @FilterableField(() => GraphQLISODateTime) + created!: Date + + @FilterableField(() => GraphQLISODateTime) + updated!: Date + + @FilterableField() + todoItemId!: number +} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-input.dto.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-input.dto.ts new file mode 100644 index 000000000..b846208b9 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-input.dto.ts @@ -0,0 +1,24 @@ +import { Field, ID, InputType } from '@nestjs/graphql' +import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator' + +@InputType('SubTaskInput') +export class CreateSubTaskDTO { + @Field() + @IsString() + @IsNotEmpty() + title!: string + + @Field({ nullable: true }) + @IsOptional() + @IsString() + @IsNotEmpty() + description?: string + + @Field() + @IsBoolean() + completed!: boolean + + @Field(() => ID) + @IsNotEmpty() + todoItemId!: number +} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-update.dto.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-update.dto.ts new file mode 100644 index 000000000..dd4913f33 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/subtask-update.dto.ts @@ -0,0 +1,27 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator' + +@InputType('SubTaskUpdate') +export class SubTaskUpdateDTO { + @Field() + @IsOptional() + @IsNotEmpty() + @IsString() + title?: string + + @Field({ nullable: true }) + @IsOptional() + @IsNotEmpty() + @IsString() + description?: string + + @Field({ nullable: true }) + @IsOptional() + @IsBoolean() + completed?: boolean + + @Field({ nullable: true }) + @IsOptional() + @IsNotEmpty() + todoItemId?: number +} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/dto/todo-item-reference.dto.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/todo-item-reference.dto.ts new file mode 100644 index 000000000..ab2ac2fc9 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/dto/todo-item-reference.dto.ts @@ -0,0 +1,12 @@ +import { Directive, Field, ID, ObjectType } from '@nestjs/graphql' +import { CursorConnection } from '@ptc-org/nestjs-query-graphql' + +import { SubTaskDTO } from './sub-task.dto' + +@ObjectType('TodoItem') +@Directive('@key(fields: "id")') +@CursorConnection('subTasks', () => SubTaskDTO) +export class TodoItemReferenceDTO { + @Field(() => ID) + id!: number +} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.entity.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.entity.ts new file mode 100644 index 000000000..e5f371ab4 --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.entity.ts @@ -0,0 +1,25 @@ +import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' + +@Entity({ name: 'sub_task' }) +export class SubTaskEntity { + @PrimaryGeneratedColumn() + id!: number + + @Column() + title!: string + + @Column({ nullable: true }) + description?: string + + @Column() + completed!: boolean + + @Column({ nullable: false, name: 'todo_item_id' }) + todoItemId!: number + + @CreateDateColumn() + created!: Date + + @UpdateDateColumn() + updated!: Date +} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.module.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.module.ts new file mode 100644 index 000000000..e14a4e76d --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/sub-task.module.ts @@ -0,0 +1,33 @@ +import { Module } from '@nestjs/common' +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql' +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm' + +import { SubTaskDTO } from './dto/sub-task.dto' +import { CreateSubTaskDTO } from './dto/subtask-input.dto' +import { SubTaskUpdateDTO } from './dto/subtask-update.dto' +import { TodoItemReferenceDTO } from './dto/todo-item-reference.dto' +import { SubTaskEntity } from './sub-task.entity' +import { TodoItemService } from './todo-item.service' + +@Module({ + imports: [ + NestjsQueryGraphQLModule.forFeature({ + imports: [NestjsQueryTypeOrmModule.forFeature([SubTaskEntity])], + services: [TodoItemService], + resolvers: [ + { + DTOClass: SubTaskDTO, + EntityClass: SubTaskEntity, + CreateDTOClass: CreateSubTaskDTO, + UpdateDTOClass: SubTaskUpdateDTO + }, + { + type: 'federated', + DTOClass: TodoItemReferenceDTO, + Service: TodoItemService + } + ] + }) + ] +}) +export class SubTaskModule {} diff --git a/examples/federation-v2/sub-task-graphql/src/sub-task/todo-item.service.ts b/examples/federation-v2/sub-task-graphql/src/sub-task/todo-item.service.ts new file mode 100644 index 000000000..ea98dec3b --- /dev/null +++ b/examples/federation-v2/sub-task-graphql/src/sub-task/todo-item.service.ts @@ -0,0 +1,24 @@ +import { InjectQueryService, QueryService, RelationQueryService } from '@ptc-org/nestjs-query-core' + +import { TodoItemReferenceDTO } from './dto/todo-item-reference.dto' +import { SubTaskEntity } from './sub-task.entity' + +@QueryService(TodoItemReferenceDTO) +export class TodoItemService extends RelationQueryService { + constructor( + @InjectQueryService(SubTaskEntity) + readonly subTaskService: QueryService + ) { + super({ + // the name of the relation + subTasks: { + // the service to delegate to when looking up the relations + service: subTaskService, + // a query factory that will take in the reference to create a query. + query: (todoItemReferenceDTO) => ({ + filter: { todoItemId: { eq: todoItemReferenceDTO.id } } + }) + } + }) + } +} diff --git a/examples/federation-v2/tag-graphql/e2e/fixtures.ts b/examples/federation-v2/tag-graphql/e2e/fixtures.ts new file mode 100644 index 000000000..880c45f5a --- /dev/null +++ b/examples/federation-v2/tag-graphql/e2e/fixtures.ts @@ -0,0 +1,34 @@ +import { Connection } from 'typeorm' + +import { executeTruncate } from '../../../helpers' +import { TagEntity } from '../src/tag/tag.entity' +import { TagTodoItemEntity } from '../src/tag/tag-todo-item.entity' + +const tables = ['tag_todo_item', 'tag'] +export const truncate = async (connection: Connection): Promise => executeTruncate(connection, tables) + +export const refresh = async (connection: Connection): Promise => { + await truncate(connection) + + const tagsRepo = connection.getRepository(TagEntity) + const tagTodoItemRepo = connection.getRepository(TagTodoItemEntity) + + const urgentTag = await tagsRepo.save({ name: 'Urgent' }) + const homeTag = await tagsRepo.save({ name: 'Home' }) + const workTag = await tagsRepo.save({ name: 'Work' }) + const questionTag = await tagsRepo.save({ name: 'Question' }) + const blockedTag = await tagsRepo.save({ name: 'Blocked' }) + + await tagTodoItemRepo.save([ + { tag: urgentTag, todoItemId: 1 }, + { tag: urgentTag, todoItemId: 2 }, + { tag: homeTag, todoItemId: 1 }, + { tag: homeTag, todoItemId: 4 }, + { tag: workTag, todoItemId: 2 }, + { tag: workTag, todoItemId: 3 }, + { tag: questionTag, todoItemId: 5 }, + { tag: blockedTag, todoItemId: 3 }, + { tag: blockedTag, todoItemId: 4 }, + { tag: blockedTag, todoItemId: 5 } + ]) +} diff --git a/examples/federation-v2/tag-graphql/e2e/graphql-fragments.ts b/examples/federation-v2/tag-graphql/e2e/graphql-fragments.ts new file mode 100644 index 000000000..55af75e64 --- /dev/null +++ b/examples/federation-v2/tag-graphql/e2e/graphql-fragments.ts @@ -0,0 +1,26 @@ +export const todoItemFields = ` + id + ` + +export const tagFields = ` +id +name +` + +export const pageInfoField = ` +pageInfo{ + hasNextPage + hasPreviousPage + startCursor + endCursor +} +` + +export const edgeNodes = (fields: string): string => ` + edges { + node{ + ${fields} + } + cursor + } + ` diff --git a/examples/federation-v2/tag-graphql/e2e/tag.resolver.spec.ts b/examples/federation-v2/tag-graphql/e2e/tag.resolver.spec.ts new file mode 100644 index 000000000..b182683a3 --- /dev/null +++ b/examples/federation-v2/tag-graphql/e2e/tag.resolver.spec.ts @@ -0,0 +1,610 @@ +import { INestApplication, ValidationPipe } from '@nestjs/common' +import { Test } from '@nestjs/testing' +import { CursorConnectionType } from '@ptc-org/nestjs-query-graphql' +import request from 'supertest' +import { Connection } from 'typeorm' + +import { AppModule } from '../src/app.module' +import { TagDTO } from '../src/tag/dto/tag.dto' +import { TagTodoItemDTO } from '../src/tag/dto/tag-todo-item.dto' +import { TodoItemReferenceDTO } from '../src/tag/dto/todo-item-reference.dto' +import { refresh } from './fixtures' +import { edgeNodes, pageInfoField, tagFields, todoItemFields } from './graphql-fragments' + +describe('Federated v2 - TagResolver (e2e)', () => { + let app: INestApplication + + beforeAll(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [AppModule] + }).compile() + + app = moduleRef.createNestApplication() + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.init() + await refresh(app.get(Connection)) + }) + + afterAll(() => refresh(app.get(Connection))) + + const tags = [ + { id: '1', name: 'Urgent' }, + { id: '2', name: 'Home' }, + { id: '3', name: 'Work' }, + { id: '4', name: 'Question' }, + { id: '5', name: 'Blocked' } + ] + + describe('find one', () => { + it(`should find a tag by id`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tag(id: 1) { + ${tagFields} + } + }` + }) + .expect(200, { data: { tag: tags[0] } })) + + it(`should throw item not found on non existing tag`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tag(id: 100) { + ${tagFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toContain('Unable to find') + })) + + it(`should return tagTodoItems as a connection`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tag(id: 1) { + tagTodoItems(sorting: [{ field: todoItemId, direction: ASC }]) { + ${pageInfoField} + ${edgeNodes(`todoItem {${todoItemFields}}`)} + } + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = + body.data.tag.tagTodoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node.todoItem.id)).toEqual(['1', '2']) + })) + }) + + describe('query', () => { + it(`should return a connection`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tags { + ${pageInfoField} + ${edgeNodes(tagFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.tags + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjQ=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(5) + expect(edges.map((e) => e.node)).toEqual(tags) + })) + + it(`should allow querying`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tags(filter: { id: { in: [1, 2, 3] } }) { + ${pageInfoField} + ${edgeNodes(tagFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.tags + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(3) + expect(edges.map((e) => e.node)).toEqual(tags.slice(0, 3)) + })) + + it(`should allow sorting`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tags(sorting: [{field: id, direction: DESC}]) { + ${pageInfoField} + ${edgeNodes(tagFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.tags + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjQ=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(5) + expect(edges.map((e) => e.node)).toEqual(tags.slice().reverse()) + })) + + describe('paging', () => { + it(`should allow paging with the 'first' field`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tags(paging: {first: 2}) { + ${pageInfoField} + ${edgeNodes(tagFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.tags + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual(tags.slice(0, 2)) + })) + + it(`should allow paging with the 'first' field and 'after'`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + tags(paging: {first: 2, after: "YXJyYXljb25uZWN0aW9uOjE="}) { + ${pageInfoField} + ${edgeNodes(tagFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.tags + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjM=', + hasNextPage: true, + hasPreviousPage: true, + startCursor: 'YXJyYXljb25uZWN0aW9uOjI=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual(tags.slice(2, 4)) + })) + }) + }) + + describe('create one', () => { + it('should allow creating a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneTag( + input: { + tag: { name: "Test Tag" } + } + ) { + ${tagFields} + } + }` + }) + .expect(200, { + data: { + createOneTag: { + id: '6', + name: 'Test Tag' + } + } + })) + + it('should validate a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneTag( + input: { + tag: { name: "" } + } + ) { + ${tagFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('name should not be empty') + })) + }) + + describe('create many', () => { + it('should allow creating a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyTags( + input: { + tags: [ + { name: "Create Many Tag - 1" }, + { name: "Create Many Tag - 2" } + ] + } + ) { + ${tagFields} + } + }` + }) + .expect(200, { + data: { + createManyTags: [ + { id: '7', name: 'Create Many Tag - 1' }, + { id: '8', name: 'Create Many Tag - 2' } + ] + } + })) + + it('should validate a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyTags( + input: { + tags: [{ name: "" }] + } + ) { + ${tagFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('name should not be empty') + })) + }) + + describe('update one', () => { + it('should allow updating a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTag( + input: { + id: "6", + update: { name: "Update Test Tag" } + } + ) { + ${tagFields} + } + }` + }) + .expect(200, { + data: { + updateOneTag: { + id: '6', + name: 'Update Test Tag' + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTag( + input: { + update: { name: "Update Test Tag" } + } + ) { + ${tagFields} + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "UpdateOneTagInput.id" of required type "ID!" was not provided.') + })) + + it('should validate an update', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTag( + input: { + id: "6", + update: { name: "" } + } + ) { + ${tagFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('name should not be empty') + })) + }) + + describe('update many', () => { + it('should allow updating a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTags( + input: { + filter: {id: { in: ["7", "8"]} }, + update: { name: "Update Many Tag" } + } + ) { + updatedCount + } + }` + }) + .expect(200, { + data: { + updateManyTags: { + updatedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTags( + input: { + update: { name: "Update Many Tag" } + } + ) { + updatedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "UpdateManyTagsInput.filter" of required type "TagUpdateFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTags( + input: { + filter: { }, + update: { name: "Update Many Tag" } + } + ) { + updatedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + describe('delete one', () => { + it('should allow deleting a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneTag( + input: { id: "6" } + ) { + ${tagFields} + } + }` + }) + .expect(200, { + data: { + deleteOneTag: { + id: null, + name: 'Update Test Tag' + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneTag( + input: { } + ) { + ${tagFields} + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "DeleteOneTagInput.id" of required type "ID!" was not provided.') + })) + }) + + describe('delete many', () => { + it('should allow updating a tag', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTags( + input: { + filter: {id: { in: ["7", "8"]} }, + } + ) { + deletedCount + } + }` + }) + .expect(200, { + data: { + deleteManyTags: { + deletedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTags( + input: { } + ) { + deletedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "DeleteManyTagsInput.filter" of required type "TagDeleteFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTags( + input: { + filter: { }, + } + ) { + deletedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + afterAll(async () => { + await app.close() + }) +}) diff --git a/examples/federation-v2/tag-graphql/schema.gql b/examples/federation-v2/tag-graphql/schema.gql new file mode 100644 index 000000000..9e204eff5 --- /dev/null +++ b/examples/federation-v2/tag-graphql/schema.gql @@ -0,0 +1,424 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +type TodoItem { + id: ID! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TodoItemTagTodoItemsConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +input TagTodoItemFilter { + and: [TagTodoItemFilter!] + or: [TagTodoItemFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input TagTodoItemSort { + field: TagTodoItemSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TagTodoItemSortFields { + tagId + todoItemId + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type TagTodoItem { + tagId: ID! + todoItemId: ID! + created: DateTime! + updated: DateTime! + todoItem: TodoItem! + tag: Tag! +} + +type Tag { + id: ID! + name: String! + created: DateTime! + updated: DateTime! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TagTagTodoItemsConnection! +} + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type TagDeleteResponse { + id: ID + name: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type TagEdge { + """The node containing the Tag""" + node: Tag! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type TagConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagEdge!]! +} + +type TagTodoItemEdge { + """The node containing the TagTodoItem""" + node: TagTodoItem! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type TagTagTodoItemsConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type TagTodoItemDeleteResponse { + tagId: ID + todoItemId: ID + created: DateTime + updated: DateTime +} + +type TagTodoItemConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type TodoItemTagTodoItemsConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type Query { + tag( + """The id of the record to find.""" + id: ID! + ): Tag! + tags( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagFilter! = {} + + """Specify to sort results.""" + sorting: [TagSort!]! = [] + ): TagConnection! + tagTodoItem( + """The id of the record to find.""" + id: ID! + ): TagTodoItem! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TagTodoItemConnection! +} + +input TagFilter { + and: [TagFilter!] + or: [TagFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input TagSort { + field: TagSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TagSortFields { + id + name + created + updated +} + +type Mutation { + createOneTag(input: CreateOneTagInput!): Tag! + createManyTags(input: CreateManyTagsInput!): [Tag!]! + updateOneTag(input: UpdateOneTagInput!): Tag! + updateManyTags(input: UpdateManyTagsInput!): UpdateManyResponse! + deleteOneTag(input: DeleteOneTagInput!): TagDeleteResponse! + deleteManyTags(input: DeleteManyTagsInput!): DeleteManyResponse! + createOneTagTodoItem(input: CreateOneTagTodoItemInput!): TagTodoItem! + createManyTagTodoItems(input: CreateManyTagTodoItemsInput!): [TagTodoItem!]! + updateOneTagTodoItem(input: UpdateOneTagTodoItemInput!): TagTodoItem! + updateManyTagTodoItems(input: UpdateManyTagTodoItemsInput!): UpdateManyResponse! + deleteOneTagTodoItem(input: DeleteOneTagTodoItemInput!): TagTodoItemDeleteResponse! + deleteManyTagTodoItems(input: DeleteManyTagTodoItemsInput!): DeleteManyResponse! +} + +input CreateOneTagInput { + """The record to create""" + tag: TagInput! +} + +input TagInput { + name: String! +} + +input CreateManyTagsInput { + """Array of records to create""" + tags: [TagInput!]! +} + +input UpdateOneTagInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TagInput! +} + +input UpdateManyTagsInput { + """Filter used to find fields to update""" + filter: TagUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TagInput! +} + +input TagUpdateFilter { + and: [TagUpdateFilter!] + or: [TagUpdateFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTagInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTagsInput { + """Filter to find records to delete""" + filter: TagDeleteFilter! +} + +input TagDeleteFilter { + and: [TagDeleteFilter!] + or: [TagDeleteFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input CreateOneTagTodoItemInput { + """The record to create""" + tagTodoItem: TagTodoItemInput! +} + +input TagTodoItemInput { + tagId: Float! + todoItemId: Float! +} + +input CreateManyTagTodoItemsInput { + """Array of records to create""" + tagTodoItems: [TagTodoItemInput!]! +} + +input UpdateOneTagTodoItemInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TagTodoItemInput! +} + +input UpdateManyTagTodoItemsInput { + """Filter used to find fields to update""" + filter: TagTodoItemUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TagTodoItemInput! +} + +input TagTodoItemUpdateFilter { + and: [TagTodoItemUpdateFilter!] + or: [TagTodoItemUpdateFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTagTodoItemInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTagTodoItemsInput { + """Filter to find records to delete""" + filter: TagTodoItemDeleteFilter! +} + +input TagTodoItemDeleteFilter { + and: [TagTodoItemDeleteFilter!] + or: [TagTodoItemDeleteFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} \ No newline at end of file diff --git a/examples/federation-v2/tag-graphql/src/app.module.ts b/examples/federation-v2/tag-graphql/src/app.module.ts new file mode 100644 index 000000000..ba566a02f --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/app.module.ts @@ -0,0 +1,22 @@ +import { ApolloFederationDriver } from '@nestjs/apollo' +import { Module } from '@nestjs/common' +import { GraphQLModule } from '@nestjs/graphql' +import { TypeOrmModule } from '@nestjs/typeorm' + +import { typeormOrmConfig } from '../../../helpers' +import { TagModule } from './tag/tag.module' + +@Module({ + imports: [ + TypeOrmModule.forRoot(typeormOrmConfig('federation_tag')), + GraphQLModule.forRoot({ + driver: ApolloFederationDriver, + autoSchemaFile: { + federation: 2, + path: 'examples/federation-v2/tag-graphql/schema.gql' + } + }), + TagModule + ] +}) +export class AppModule {} diff --git a/examples/federation-v2/tag-graphql/src/main.ts b/examples/federation-v2/tag-graphql/src/main.ts new file mode 100644 index 000000000..ae139978f --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/main.ts @@ -0,0 +1,23 @@ +import { ValidationPipe } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' + +import { AppModule } from './app.module' + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.listen(3003) +} + +// eslint-disable-next-line no-void +void bootstrap() diff --git a/examples/federation-v2/tag-graphql/src/tag/dto/tag-input.dto.ts b/examples/federation-v2/tag-graphql/src/tag/dto/tag-input.dto.ts new file mode 100644 index 000000000..8b921af50 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/dto/tag-input.dto.ts @@ -0,0 +1,10 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsNotEmpty, IsString } from 'class-validator' + +@InputType('TagInput') +export class TagInputDTO { + @Field() + @IsString() + @IsNotEmpty() + name!: string +} diff --git a/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.dto.ts b/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.dto.ts new file mode 100644 index 000000000..5d078f154 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.dto.ts @@ -0,0 +1,22 @@ +import { GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql' +import { FilterableField, Reference, Relation } from '@ptc-org/nestjs-query-graphql' + +import { TagDTO } from './tag.dto' +import { TodoItemReferenceDTO } from './todo-item-reference.dto' + +@ObjectType('TagTodoItem') +@Relation('tag', () => TagDTO) +@Reference('todoItem', () => TodoItemReferenceDTO, { id: 'todoItemId' }) +export class TagTodoItemDTO { + @FilterableField(() => ID) + tagId!: number + + @FilterableField(() => ID) + todoItemId!: number + + @FilterableField(() => GraphQLISODateTime) + created!: Date + + @FilterableField(() => GraphQLISODateTime) + updated!: Date +} diff --git a/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.input.ts b/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.input.ts new file mode 100644 index 000000000..b716875b1 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/dto/tag-todo-item.input.ts @@ -0,0 +1,15 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsInt, IsNotEmpty } from 'class-validator' + +@InputType('TagTodoItemInput') +export class TagTodoItemInputDTO { + @Field() + @IsInt() + @IsNotEmpty() + tagId!: number + + @Field() + @IsInt() + @IsNotEmpty() + todoItemId!: number +} diff --git a/examples/federation-v2/tag-graphql/src/tag/dto/tag.dto.ts b/examples/federation-v2/tag-graphql/src/tag/dto/tag.dto.ts new file mode 100644 index 000000000..7982e70c3 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/dto/tag.dto.ts @@ -0,0 +1,20 @@ +import { GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql' +import { CursorConnection, FilterableField } from '@ptc-org/nestjs-query-graphql' + +import { TagTodoItemDTO } from './tag-todo-item.dto' + +@ObjectType('Tag') +@CursorConnection('tagTodoItems', () => TagTodoItemDTO) +export class TagDTO { + @FilterableField(() => ID) + id!: number + + @FilterableField() + name!: string + + @FilterableField(() => GraphQLISODateTime) + created!: Date + + @FilterableField(() => GraphQLISODateTime) + updated!: Date +} diff --git a/examples/federation-v2/tag-graphql/src/tag/dto/todo-item-reference.dto.ts b/examples/federation-v2/tag-graphql/src/tag/dto/todo-item-reference.dto.ts new file mode 100644 index 000000000..d78890f4f --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/dto/todo-item-reference.dto.ts @@ -0,0 +1,12 @@ +import { Directive, Field, ID, ObjectType } from '@nestjs/graphql' +import { CursorConnection } from '@ptc-org/nestjs-query-graphql' + +import { TagTodoItemDTO } from './tag-todo-item.dto' + +@ObjectType('TodoItem') +@Directive('@key(fields: "id")') +@CursorConnection('tagTodoItems', () => TagTodoItemDTO) +export class TodoItemReferenceDTO { + @Field(() => ID) + id!: number +} diff --git a/examples/federation-v2/tag-graphql/src/tag/tag-todo-item.entity.ts b/examples/federation-v2/tag-graphql/src/tag/tag-todo-item.entity.ts new file mode 100644 index 000000000..c421d6e49 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/tag-todo-item.entity.ts @@ -0,0 +1,22 @@ +import { CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm' + +import { TagEntity } from './tag.entity' + +@Entity({ name: 'tag_todo_item' }) +export class TagTodoItemEntity { + @PrimaryColumn() + tagId!: number + + @PrimaryColumn() + todoItemId!: number + + @CreateDateColumn() + created!: Date + + @UpdateDateColumn() + updated!: Date + + @ManyToOne(() => TagEntity, (tag) => tag.tagTodoItems) + @JoinColumn({ name: 'tagId' }) + tag!: TagEntity +} diff --git a/examples/federation-v2/tag-graphql/src/tag/tag.entity.ts b/examples/federation-v2/tag-graphql/src/tag/tag.entity.ts new file mode 100644 index 000000000..39dc92579 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/tag.entity.ts @@ -0,0 +1,21 @@ +import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' + +import { TagTodoItemEntity } from './tag-todo-item.entity' + +@Entity({ name: 'tag' }) +export class TagEntity { + @PrimaryGeneratedColumn() + id!: number + + @Column() + name!: string + + @CreateDateColumn() + created!: Date + + @UpdateDateColumn() + updated!: Date + + @OneToMany(() => TagTodoItemEntity, (tagTodoItem) => tagTodoItem.tag) + tagTodoItems!: TagTodoItemEntity[] +} diff --git a/examples/federation-v2/tag-graphql/src/tag/tag.module.ts b/examples/federation-v2/tag-graphql/src/tag/tag.module.ts new file mode 100644 index 000000000..b801a9900 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/tag.module.ts @@ -0,0 +1,41 @@ +import { Module } from '@nestjs/common' +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql' +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm' + +import { TagDTO } from './dto/tag.dto' +import { TagInputDTO } from './dto/tag-input.dto' +import { TagTodoItemDTO } from './dto/tag-todo-item.dto' +import { TagTodoItemInputDTO } from './dto/tag-todo-item.input' +import { TodoItemReferenceDTO } from './dto/todo-item-reference.dto' +import { TagEntity } from './tag.entity' +import { TagTodoItemEntity } from './tag-todo-item.entity' +import { TodoItemService } from './todo-item.service' + +@Module({ + imports: [ + NestjsQueryGraphQLModule.forFeature({ + imports: [NestjsQueryTypeOrmModule.forFeature([TagEntity, TagTodoItemEntity])], + services: [TodoItemService], + resolvers: [ + { + DTOClass: TagDTO, + EntityClass: TagEntity, + CreateDTOClass: TagInputDTO, + UpdateDTOClass: TagInputDTO + }, + { + DTOClass: TagTodoItemDTO, + EntityClass: TagTodoItemEntity, + CreateDTOClass: TagTodoItemInputDTO, + UpdateDTOClass: TagTodoItemInputDTO + }, + { + type: 'federated', + DTOClass: TodoItemReferenceDTO, + Service: TodoItemService + } + ] + }) + ] +}) +export class TagModule {} diff --git a/examples/federation-v2/tag-graphql/src/tag/todo-item.service.ts b/examples/federation-v2/tag-graphql/src/tag/todo-item.service.ts new file mode 100644 index 000000000..a9482b5a6 --- /dev/null +++ b/examples/federation-v2/tag-graphql/src/tag/todo-item.service.ts @@ -0,0 +1,21 @@ +import { InjectQueryService, QueryService, RelationQueryService } from '@ptc-org/nestjs-query-core' + +import { TodoItemReferenceDTO } from './dto/todo-item-reference.dto' +import { TagTodoItemEntity } from './tag-todo-item.entity' + +@QueryService(TodoItemReferenceDTO) +export class TodoItemService extends RelationQueryService { + constructor( + @InjectQueryService(TagTodoItemEntity) + readonly tagTodoItemService: QueryService + ) { + super({ + tagTodoItems: { + service: tagTodoItemService, + query: (ref: TodoItemReferenceDTO) => ({ + filter: { todoItemId: { eq: ref.id } } + }) + } + }) + } +} diff --git a/examples/federation-v2/todo-item-graphql/e2e/fixtures.ts b/examples/federation-v2/todo-item-graphql/e2e/fixtures.ts new file mode 100644 index 000000000..69855dc09 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/e2e/fixtures.ts @@ -0,0 +1,20 @@ +import { Connection } from 'typeorm' + +import { executeTruncate } from '../../../helpers' +import { TodoItemEntity } from '../src/todo-item/todo-item.entity' + +const tables = ['todo_item'] +export const truncate = async (connection: Connection): Promise => executeTruncate(connection, tables) + +export const refresh = async (connection: Connection): Promise => { + await truncate(connection) + + const todoRepo = connection.getRepository(TodoItemEntity) + await todoRepo.save([ + { title: 'Create Nest App', completed: true, assigneeId: 1 }, + { title: 'Create Entity', completed: false, assigneeId: 2 }, + { title: 'Create Entity Service', completed: false, assigneeId: 3 }, + { title: 'Add Todo Item Resolver', completed: false }, + { title: 'How to create item With Sub Tasks', completed: false } + ]) +} diff --git a/examples/federation-v2/todo-item-graphql/e2e/graphql-fragments.ts b/examples/federation-v2/todo-item-graphql/e2e/graphql-fragments.ts new file mode 100644 index 000000000..330df39ab --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/e2e/graphql-fragments.ts @@ -0,0 +1,24 @@ +export const todoItemFields = ` + id + title + completed + description + ` + +export const pageInfoField = ` +pageInfo{ + hasNextPage + hasPreviousPage + startCursor + endCursor +} +` + +export const edgeNodes = (fields: string): string => ` + edges { + node{ + ${fields} + } + cursor + } + ` diff --git a/examples/federation-v2/todo-item-graphql/e2e/todo-item.resolver.spec.ts b/examples/federation-v2/todo-item-graphql/e2e/todo-item.resolver.spec.ts new file mode 100644 index 000000000..17d7afd4f --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/e2e/todo-item.resolver.spec.ts @@ -0,0 +1,695 @@ +import { INestApplication, ValidationPipe } from '@nestjs/common' +import { Test } from '@nestjs/testing' +import { CursorConnectionType } from '@ptc-org/nestjs-query-graphql' +import request from 'supertest' +import { Connection } from 'typeorm' + +import { AppModule } from '../src/app.module' +import { TodoItemDTO } from '../src/todo-item/dto/todo-item.dto' +import { refresh } from './fixtures' +import { edgeNodes, pageInfoField, todoItemFields } from './graphql-fragments' + +describe('Federated v2 - TodoItemResolver (e2e)', () => { + let app: INestApplication + + beforeAll(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [AppModule] + }).compile() + + app = moduleRef.createNestApplication() + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.init() + await refresh(app.get(Connection)) + }) + + afterAll(() => refresh(app.get(Connection))) + + describe('find one', () => { + it(`should find a todo item by id`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItem(id: 1) { + ${todoItemFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + todoItem: { + id: '1', + title: 'Create Nest App', + completed: true, + description: null + } + } + }) + })) + + it(`should find a todo and assignee`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItem(id: 1) { + ${todoItemFields} + assigneeId + assignee { + id + __typename + } + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + todoItem: { + id: '1', + title: 'Create Nest App', + completed: true, + description: null, + assigneeId: '1', + assignee: { + id: '1', + __typename: 'User' + } + } + } + }) + })) + + it(`should return null if there is no assignee`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItem(id: 5) { + ${todoItemFields} + assigneeId + assignee { + id + __typename + } + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + todoItem: { + id: '5', + title: 'How to create item With Sub Tasks', + completed: false, + description: null, + assigneeId: null, + assignee: null + } + } + }) + })) + + it(`should throw item not found on non existing todo item`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItem(id: 100) { + ${todoItemFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toContain('Unable to find') + })) + }) + + describe('query', () => { + it(`should return a connection`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItems { + ${pageInfoField} + ${edgeNodes(todoItemFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.todoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjQ=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(5) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', title: 'Create Nest App', completed: true, description: null }, + { id: '2', title: 'Create Entity', completed: false, description: null }, + { id: '3', title: 'Create Entity Service', completed: false, description: null }, + { id: '4', title: 'Add Todo Item Resolver', completed: false, description: null }, + { id: '5', title: 'How to create item With Sub Tasks', completed: false, description: null } + ]) + })) + + it(`should allow querying`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItems(filter: { id: { in: [1, 2, 3] } }) { + ${pageInfoField} + ${edgeNodes(todoItemFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.todoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(3) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', title: 'Create Nest App', completed: true, description: null }, + { id: '2', title: 'Create Entity', completed: false, description: null }, + { id: '3', title: 'Create Entity Service', completed: false, description: null } + ]) + })) + + it(`should allow sorting`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItems(sorting: [{field: id, direction: DESC}]) { + ${pageInfoField} + ${edgeNodes(todoItemFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.todoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjQ=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(5) + expect(edges.map((e) => e.node)).toEqual([ + { id: '5', title: 'How to create item With Sub Tasks', completed: false, description: null }, + { id: '4', title: 'Add Todo Item Resolver', completed: false, description: null }, + { id: '3', title: 'Create Entity Service', completed: false, description: null }, + { id: '2', title: 'Create Entity', completed: false, description: null }, + { id: '1', title: 'Create Nest App', completed: true, description: null } + ]) + })) + + describe('paging', () => { + it(`should allow paging with the 'first' field`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItems(paging: {first: 2}) { + ${pageInfoField} + ${edgeNodes(todoItemFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.todoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', title: 'Create Nest App', completed: true, description: null }, + { id: '2', title: 'Create Entity', completed: false, description: null } + ]) + })) + + it(`should allow paging with the 'first' field and 'after'`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + todoItems(paging: {first: 2, after: "YXJyYXljb25uZWN0aW9uOjE="}) { + ${pageInfoField} + ${edgeNodes(todoItemFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.todoItems + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjM=', + hasNextPage: true, + hasPreviousPage: true, + startCursor: 'YXJyYXljb25uZWN0aW9uOjI=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual([ + { id: '3', title: 'Create Entity Service', completed: false, description: null }, + { id: '4', title: 'Add Todo Item Resolver', completed: false, description: null } + ]) + })) + }) + }) + + describe('create one', () => { + it('should allow creating a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneTodoItem( + input: { + todoItem: { title: "Test Todo", completed: false } + } + ) { + id + title + completed + } + }` + }) + .expect(200, { + data: { + createOneTodoItem: { + id: '6', + title: 'Test Todo', + completed: false + } + } + })) + + it('should validate a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneTodoItem( + input: { + todoItem: { title: "Test Todo with a too long title!", completed: false } + } + ) { + id + title + completed + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title must be shorter than or equal to 20 characters') + })) + }) + + describe('create many', () => { + it('should allow creating a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyTodoItems( + input: { + todoItems: [ + { title: "Many Test Todo 1", completed: false }, + { title: "Many Test Todo 2", completed: true } + ] + } + ) { + id + title + completed + } + }` + }) + .expect(200, { + data: { + createManyTodoItems: [ + { id: '7', title: 'Many Test Todo 1', completed: false }, + { id: '8', title: 'Many Test Todo 2', completed: true } + ] + } + })) + + it('should validate a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyTodoItems( + input: { + todoItems: [{ title: "Test Todo With A Really Long Title", completed: false }] + } + ) { + id + title + completed + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title must be shorter than or equal to 20 characters') + })) + }) + + describe('update one', () => { + it('should allow updating a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTodoItem( + input: { + id: "6", + update: { title: "Update Test Todo", completed: true } + } + ) { + id + title + completed + } + }` + }) + .expect(200, { + data: { + updateOneTodoItem: { + id: '6', + title: 'Update Test Todo', + completed: true + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTodoItem( + input: { + update: { title: "Update Test Todo With A Really Long Title" } + } + ) { + id + title + completed + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "UpdateOneTodoItemInput.id" of required type "ID!" was not provided.') + })) + + it('should validate an update', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneTodoItem( + input: { + id: "6", + update: { title: "Update Test Todo With A Really Long Title" } + } + ) { + id + title + completed + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('title must be shorter than or equal to 20 characters') + })) + }) + + describe('update many', () => { + it('should allow updating a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTodoItems( + input: { + filter: {id: { in: ["7", "8"]} }, + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(200, { + data: { + updateManyTodoItems: { + updatedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTodoItems( + input: { + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "UpdateManyTodoItemsInput.filter" of required type "TodoItemUpdateFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyTodoItems( + input: { + filter: { }, + update: { title: "Update Many Test", completed: true } + } + ) { + updatedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + describe('delete one', () => { + it('should allow deleting a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneTodoItem( + input: { id: "6" } + ) { + id + title + completed + } + }` + }) + .expect(200, { + data: { + deleteOneTodoItem: { + id: null, + title: 'Update Test Todo', + completed: true + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneTodoItem( + input: { } + ) { + id + title + completed + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "DeleteOneTodoItemInput.id" of required type "ID!" was not provided.') + })) + }) + + describe('delete many', () => { + it('should allow updating a todoItem', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTodoItems( + input: { + filter: {id: { in: ["7", "8"]} }, + } + ) { + deletedCount + } + }` + }) + .expect(200, { + data: { + deleteManyTodoItems: { + deletedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTodoItems( + input: { } + ) { + deletedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "DeleteManyTodoItemsInput.filter" of required type "TodoItemDeleteFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyTodoItems( + input: { + filter: { }, + } + ) { + deletedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + afterAll(async () => { + await app.close() + }) +}) diff --git a/examples/federation-v2/todo-item-graphql/schema.gql b/examples/federation-v2/todo-item-graphql/schema.gql new file mode 100644 index 000000000..ffc931ad9 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/schema.gql @@ -0,0 +1,287 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +type User { + id: ID! +} + +type TodoItem { + id: ID! + title: String! + description: String + completed: Boolean! + assigneeId: String + created: DateTime! + updated: DateTime! + assignee: User +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type TodoItemDeleteResponse { + id: ID + title: String + description: String + completed: Boolean + assigneeId: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type TodoItemEdge { + """The node containing the TodoItem""" + node: TodoItem! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type TodoItemConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TodoItemEdge!]! +} + +type Query { + todoItem( + """The id of the record to find.""" + id: ID! + ): TodoItem! + todoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TodoItemSort!]! = [] + ): TodoItemConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +input TodoItemFilter { + and: [TodoItemFilter!] + or: [TodoItemFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input BooleanFieldComparison { + is: Boolean + isNot: Boolean +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input TodoItemSort { + field: TodoItemSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TodoItemSortFields { + id + title + description + completed + assigneeId + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type Mutation { + createOneTodoItem(input: CreateOneTodoItemInput!): TodoItem! + createManyTodoItems(input: CreateManyTodoItemsInput!): [TodoItem!]! + updateOneTodoItem(input: UpdateOneTodoItemInput!): TodoItem! + updateManyTodoItems(input: UpdateManyTodoItemsInput!): UpdateManyResponse! + deleteOneTodoItem(input: DeleteOneTodoItemInput!): TodoItemDeleteResponse! + deleteManyTodoItems(input: DeleteManyTodoItemsInput!): DeleteManyResponse! +} + +input CreateOneTodoItemInput { + """The record to create""" + todoItem: TodoItemInput! +} + +input TodoItemInput { + title: String! + completed: Boolean! + assigneeId: ID +} + +input CreateManyTodoItemsInput { + """Array of records to create""" + todoItems: [TodoItemInput!]! +} + +input UpdateOneTodoItemInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TodoItemUpdate! +} + +input TodoItemUpdate { + title: String + completed: Boolean + assigneeId: ID +} + +input UpdateManyTodoItemsInput { + """Filter used to find fields to update""" + filter: TodoItemUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TodoItemUpdate! +} + +input TodoItemUpdateFilter { + and: [TodoItemUpdateFilter!] + or: [TodoItemUpdateFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTodoItemInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTodoItemsInput { + """Filter to find records to delete""" + filter: TodoItemDeleteFilter! +} + +input TodoItemDeleteFilter { + and: [TodoItemDeleteFilter!] + or: [TodoItemDeleteFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} \ No newline at end of file diff --git a/examples/federation-v2/todo-item-graphql/src/app.module.ts b/examples/federation-v2/todo-item-graphql/src/app.module.ts new file mode 100644 index 000000000..cac4442d0 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/app.module.ts @@ -0,0 +1,22 @@ +import { ApolloFederationDriver } from '@nestjs/apollo' +import { Module } from '@nestjs/common' +import { GraphQLModule } from '@nestjs/graphql' +import { TypeOrmModule } from '@nestjs/typeorm' + +import { typeormOrmConfig } from '../../../helpers' +import { TodoItemModule } from './todo-item/todo-item.module' + +@Module({ + imports: [ + TypeOrmModule.forRoot(typeormOrmConfig('federation_todo_item')), + GraphQLModule.forRoot({ + driver: ApolloFederationDriver, + autoSchemaFile: { + federation: 2, + path: 'examples/federation-v2/todo-item-graphql/schema.gql' + } + }), + TodoItemModule + ] +}) +export class AppModule {} diff --git a/examples/federation-v2/todo-item-graphql/src/main.ts b/examples/federation-v2/todo-item-graphql/src/main.ts new file mode 100644 index 000000000..7cf4071d9 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/main.ts @@ -0,0 +1,23 @@ +import { ValidationPipe } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' + +import { AppModule } from './app.module' + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.listen(3001) +} + +// eslint-disable-next-line no-void +void bootstrap() diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-input.dto.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-input.dto.ts new file mode 100644 index 000000000..a0be42030 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-input.dto.ts @@ -0,0 +1,18 @@ +import { Field, ID, InputType } from '@nestjs/graphql' +import { IsBoolean, IsOptional, IsString, MaxLength } from 'class-validator' + +@InputType('TodoItemInput') +export class TodoItemInputDTO { + @IsString() + @MaxLength(20) + @Field() + title!: string + + @IsBoolean() + @Field() + completed!: boolean + + @IsOptional() + @Field(() => ID, { nullable: true }) + assigneeId?: number +} diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-update.dto.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-update.dto.ts new file mode 100644 index 000000000..ebb5699bb --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item-update.dto.ts @@ -0,0 +1,20 @@ +import { Field, ID, InputType } from '@nestjs/graphql' +import { IsBoolean, IsOptional, IsString, MaxLength } from 'class-validator' + +@InputType('TodoItemUpdate') +export class TodoItemUpdateDTO { + @IsOptional() + @IsString() + @MaxLength(20) + @Field({ nullable: true }) + title?: string + + @IsOptional() + @IsBoolean() + @Field({ nullable: true }) + completed?: boolean + + @IsOptional() + @Field(() => ID, { nullable: true }) + assigneeId?: number +} diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item.dto.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item.dto.ts new file mode 100644 index 000000000..603ddf192 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/todo-item.dto.ts @@ -0,0 +1,30 @@ +import { Directive, GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql' +import { FilterableField, Reference } from '@ptc-org/nestjs-query-graphql' + +import { UserReferenceDTO } from './user-reference.dto' + +@ObjectType('TodoItem') +@Directive('@key(fields: "id")') +@Reference('assignee', () => UserReferenceDTO, { id: 'assigneeId' }, { nullable: true }) +export class TodoItemDTO { + @FilterableField(() => ID) + id!: number + + @FilterableField() + title!: string + + @FilterableField({ nullable: true }) + description?: string + + @FilterableField() + completed!: boolean + + @FilterableField({ nullable: true }) + assigneeId?: string + + @FilterableField(() => GraphQLISODateTime) + created!: Date + + @FilterableField(() => GraphQLISODateTime) + updated!: Date +} diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/dto/user-reference.dto.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/user-reference.dto.ts new file mode 100644 index 000000000..a23bdd4a6 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/dto/user-reference.dto.ts @@ -0,0 +1,8 @@ +import { Directive, Field, ID, ObjectType } from '@nestjs/graphql' + +@ObjectType('User') +@Directive('@key(fields: "id")') +export class UserReferenceDTO { + @Field(() => ID) + id!: number +} diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.entity.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.entity.ts new file mode 100644 index 000000000..f92a5ce05 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.entity.ts @@ -0,0 +1,25 @@ +import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' + +@Entity({ name: 'todo_item' }) +export class TodoItemEntity { + @PrimaryGeneratedColumn() + id!: number + + @Column() + title!: string + + @Column({ nullable: true }) + description?: string + + @Column() + completed!: boolean + + @Column({ nullable: true }) + assigneeId?: number + + @CreateDateColumn() + created!: Date + + @UpdateDateColumn() + updated!: Date +} diff --git a/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.module.ts b/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.module.ts new file mode 100644 index 000000000..818704216 --- /dev/null +++ b/examples/federation-v2/todo-item-graphql/src/todo-item/todo-item.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common' +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql' +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm' + +import { TodoItemDTO } from './dto/todo-item.dto' +import { TodoItemInputDTO } from './dto/todo-item-input.dto' +import { TodoItemUpdateDTO } from './dto/todo-item-update.dto' +import { TodoItemEntity } from './todo-item.entity' + +@Module({ + imports: [ + NestjsQueryGraphQLModule.forFeature({ + imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])], + resolvers: [ + { + DTOClass: TodoItemDTO, + EntityClass: TodoItemEntity, + CreateDTOClass: TodoItemInputDTO, + UpdateDTOClass: TodoItemUpdateDTO, + referenceBy: { key: 'id' } + } + ] + }) + ] +}) +export class TodoItemModule {} diff --git a/examples/federation-v2/user-graphql/e2e/fixtures.ts b/examples/federation-v2/user-graphql/e2e/fixtures.ts new file mode 100644 index 000000000..84fd72d24 --- /dev/null +++ b/examples/federation-v2/user-graphql/e2e/fixtures.ts @@ -0,0 +1,18 @@ +import { Connection } from 'typeorm' + +import { executeTruncate } from '../../../helpers' +import { UserEntity } from '../src/user/user.entity' + +const tables = ['user'] +export const truncate = async (connection: Connection): Promise => executeTruncate(connection, tables) + +export const refresh = async (connection: Connection): Promise => { + await truncate(connection) + + const userRepo = connection.getRepository(UserEntity) + await userRepo.save([ + { name: 'User 1', email: 'user1@example.com' }, + { name: 'User 2', email: 'user2@example.com' }, + { name: 'User 3', email: 'user3@example.com' } + ]) +} diff --git a/examples/federation-v2/user-graphql/e2e/graphql-fragments.ts b/examples/federation-v2/user-graphql/e2e/graphql-fragments.ts new file mode 100644 index 000000000..93b58c663 --- /dev/null +++ b/examples/federation-v2/user-graphql/e2e/graphql-fragments.ts @@ -0,0 +1,23 @@ +export const userFields = ` + id + name + email + ` + +export const pageInfoField = ` +pageInfo{ + hasNextPage + hasPreviousPage + startCursor + endCursor +} +` + +export const edgeNodes = (fields: string): string => ` + edges { + node{ + ${fields} + } + cursor + } + ` diff --git a/examples/federation-v2/user-graphql/e2e/user.resolver.spec.ts b/examples/federation-v2/user-graphql/e2e/user.resolver.spec.ts new file mode 100644 index 000000000..6d412e8ed --- /dev/null +++ b/examples/federation-v2/user-graphql/e2e/user.resolver.spec.ts @@ -0,0 +1,620 @@ +import { INestApplication, ValidationPipe } from '@nestjs/common' +import { Test } from '@nestjs/testing' +import { CursorConnectionType } from '@ptc-org/nestjs-query-graphql' +import request from 'supertest' +import { Connection } from 'typeorm' + +import { AppModule } from '../src/app.module' +import { UserDTO } from '../src/user/dto/user.dto' +import { refresh } from './fixtures' +import { edgeNodes, pageInfoField, userFields } from './graphql-fragments' + +describe('Federated v2 - UserResolver (e2e)', () => { + let app: INestApplication + + beforeAll(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [AppModule] + }).compile() + + app = moduleRef.createNestApplication() + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.init() + await refresh(app.get(Connection)) + }) + + afterAll(() => refresh(app.get(Connection))) + + describe('find one', () => { + it(`should find a user by id`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + user(id: 1) { + ${userFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body).toEqual({ + data: { + user: { + id: '1', + name: 'User 1', + email: 'user1@example.com' + } + } + }) + })) + + it(`should throw item not found on non existing user`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + user(id: 100) { + ${userFields} + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toContain('Unable to find') + })) + }) + + describe('query', () => { + it(`should return a connection`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + users { + ${pageInfoField} + ${edgeNodes(userFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.users + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(3) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', name: 'User 1', email: 'user1@example.com' }, + { id: '2', name: 'User 2', email: 'user2@example.com' }, + { id: '3', name: 'User 3', email: 'user3@example.com' } + ]) + })) + + it(`should allow querying`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + users(filter: { id: { in: [1, 2] } }) { + ${pageInfoField} + ${edgeNodes(userFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.users + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', name: 'User 1', email: 'user1@example.com' }, + { id: '2', name: 'User 2', email: 'user2@example.com' } + ]) + })) + + it(`should allow sorting`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + users(sorting: [{field: id, direction: DESC}]) { + ${pageInfoField} + ${edgeNodes(userFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.users + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(3) + expect(edges.map((e) => e.node)).toEqual([ + { id: '3', name: 'User 3', email: 'user3@example.com' }, + { id: '2', name: 'User 2', email: 'user2@example.com' }, + { id: '1', name: 'User 1', email: 'user1@example.com' } + ]) + })) + + describe('paging', () => { + it(`should allow paging with the 'first' field`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + users(paging: {first: 2}) { + ${pageInfoField} + ${edgeNodes(userFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.users + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjE=', + hasNextPage: true, + hasPreviousPage: false, + startCursor: 'YXJyYXljb25uZWN0aW9uOjA=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual([ + { id: '1', name: 'User 1', email: 'user1@example.com' }, + { id: '2', name: 'User 2', email: 'user2@example.com' } + ]) + })) + + it(`should allow paging with the 'first' field and 'after'`, () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `{ + users(paging: {first: 2, after: "YXJyYXljb25uZWN0aW9uOjA="}) { + ${pageInfoField} + ${edgeNodes(userFields)} + } + }` + }) + .expect(200) + .then(({ body }) => { + const { edges, pageInfo }: CursorConnectionType = body.data.users + expect(pageInfo).toEqual({ + endCursor: 'YXJyYXljb25uZWN0aW9uOjI=', + hasNextPage: false, + hasPreviousPage: true, + startCursor: 'YXJyYXljb25uZWN0aW9uOjE=' + }) + expect(edges).toHaveLength(2) + expect(edges.map((e) => e.node)).toEqual([ + { id: '2', name: 'User 2', email: 'user2@example.com' }, + { id: '3', name: 'User 3', email: 'user3@example.com' } + ]) + })) + }) + }) + + describe('create one', () => { + it('should allow creating a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneUser( + input: { + user: { name: "User 4", email: "user4@example.com" } + } + ) { + id + name + email + } + }` + }) + .expect(200, { + data: { + createOneUser: { + id: '4', + name: 'User 4', + email: 'user4@example.com' + } + } + })) + + it('should validate a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createOneUser( + input: { + user: { name: "User 5", email: "This is not a valid email" } + } + ) { + id + name + email + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('email must be an email') + })) + }) + + describe('create many', () => { + it('should allow creating a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyUsers( + input: { + users: [ + { name: "User 5", email: "user5@example.com" }, + { name: "User 6", email: "user6@example.com" } + ] + } + ) { + id + name + email + } + }` + }) + .expect(200, { + data: { + createManyUsers: [ + { id: '5', name: 'User 5', email: 'user5@example.com' }, + { id: '6', name: 'User 6', email: 'user6@example.com' } + ] + } + })) + + it('should validate a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + createManyUsers( + input: { + users: [{ name: "User 7", email: "This is not a valid email" }] + } + ) { + id + name + email + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('email must be an email') + })) + }) + + describe('update one', () => { + it('should allow updating a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneUser( + input: { + id: "6", + update: { name: "User 6a", email: "user6a@example.com" } + } + ) { + id + name + email + } + }` + }) + .expect(200, { + data: { + updateOneUser: { + id: '6', + name: 'User 6a', + email: 'user6a@example.com' + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneUser( + input: { + update: { name: "User X" } + } + ) { + id + name + email + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "UpdateOneUserInput.id" of required type "ID!" was not provided.') + })) + + it('should validate an update', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateOneUser( + input: { + id: "6", + update: { email: "This is not a valid email address" } + } + ) { + id + name + email + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('email must be an email') + })) + }) + + describe('update many', () => { + it('should allow updating a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyUsers( + input: { + filter: {id: { in: ["5", "6"]} }, + update: { name: "New Users" } + } + ) { + updatedCount + } + }` + }) + .expect(200, { + data: { + updateManyUsers: { + updatedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyUsers( + input: { + update: { name: "New users" } + } + ) { + updatedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "UpdateManyUsersInput.filter" of required type "UserUpdateFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + updateManyUsers( + input: { + filter: { }, + update: { name: "New users" } + } + ) { + updatedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + describe('delete one', () => { + it('should allow deleting a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneUser( + input: { id: "6" } + ) { + id + name + email + } + }` + }) + .expect(200, { + data: { + deleteOneUser: { + id: null, + name: 'New Users', + email: 'user6a@example.com' + } + } + })) + + it('should require an id', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteOneUser( + input: { } + ) { + id + name + email + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe('Field "DeleteOneUserInput.id" of required type "ID!" was not provided.') + })) + }) + + describe('delete many', () => { + it('should allow deleting a user', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyUsers( + input: { + filter: {id: { in: ["4", "5"]} }, + } + ) { + deletedCount + } + }` + }) + .expect(200, { + data: { + deleteManyUsers: { + deletedCount: 2 + } + } + })) + + it('should require a filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyUsers( + input: { } + ) { + deletedCount + } + }` + }) + .expect(400) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(body.errors[0].message).toBe( + 'Field "DeleteManyUsersInput.filter" of required type "UserDeleteFilter!" was not provided.' + ) + })) + + it('should require a non-empty filter', () => + request(app.getHttpServer()) + .post('/graphql') + .send({ + operationName: null, + variables: {}, + query: `mutation { + deleteManyUsers( + input: { + filter: { }, + } + ) { + deletedCount + } + }` + }) + .expect(200) + .then(({ body }) => { + expect(body.errors).toHaveLength(1) + expect(JSON.stringify(body.errors[0])).toContain('filter must be a non-empty object') + })) + }) + + afterAll(async () => { + await app.close() + }) +}) diff --git a/examples/federation-v2/user-graphql/schema.gql b/examples/federation-v2/user-graphql/schema.gql new file mode 100644 index 000000000..826de8adb --- /dev/null +++ b/examples/federation-v2/user-graphql/schema.gql @@ -0,0 +1,263 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +type User { + id: ID! + name: String! + email: String! + created: DateTime! + updated: DateTime! +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type UserDeleteResponse { + id: ID + name: String + email: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type UserEdge { + """The node containing the User""" + node: User! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type UserConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [UserEdge!]! +} + +type Query { + user( + """The id of the record to find.""" + id: ID! + ): User! + users( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: UserFilter! = {} + + """Specify to sort results.""" + sorting: [UserSort!]! = [] + ): UserConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +input UserFilter { + and: [UserFilter!] + or: [UserFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input UserSort { + field: UserSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum UserSortFields { + id + name + email + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type Mutation { + createOneUser(input: CreateOneUserInput!): User! + createManyUsers(input: CreateManyUsersInput!): [User!]! + updateOneUser(input: UpdateOneUserInput!): User! + updateManyUsers(input: UpdateManyUsersInput!): UpdateManyResponse! + deleteOneUser(input: DeleteOneUserInput!): UserDeleteResponse! + deleteManyUsers(input: DeleteManyUsersInput!): DeleteManyResponse! +} + +input CreateOneUserInput { + """The record to create""" + user: UserInput! +} + +input UserInput { + name: String! + email: String! +} + +input CreateManyUsersInput { + """Array of records to create""" + users: [UserInput!]! +} + +input UpdateOneUserInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: UserUpdate! +} + +input UserUpdate { + name: String + email: String +} + +input UpdateManyUsersInput { + """Filter used to find fields to update""" + filter: UserUpdateFilter! + + """The update to apply to all records found using the filter""" + update: UserUpdate! +} + +input UserUpdateFilter { + and: [UserUpdateFilter!] + or: [UserUpdateFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneUserInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyUsersInput { + """Filter to find records to delete""" + filter: UserDeleteFilter! +} + +input UserDeleteFilter { + and: [UserDeleteFilter!] + or: [UserDeleteFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} \ No newline at end of file diff --git a/examples/federation-v2/user-graphql/src/app.module.ts b/examples/federation-v2/user-graphql/src/app.module.ts new file mode 100644 index 000000000..371f4356e --- /dev/null +++ b/examples/federation-v2/user-graphql/src/app.module.ts @@ -0,0 +1,22 @@ +import { ApolloFederationDriver } from '@nestjs/apollo' +import { Module } from '@nestjs/common' +import { GraphQLModule } from '@nestjs/graphql' +import { TypeOrmModule } from '@nestjs/typeorm' + +import { typeormOrmConfig } from '../../../helpers' +import { UserModule } from './user/user.module' + +@Module({ + imports: [ + TypeOrmModule.forRoot(typeormOrmConfig('federation_user')), + GraphQLModule.forRoot({ + driver: ApolloFederationDriver, + autoSchemaFile: { + federation: 2, + path: 'examples/federation-v2/user-graphql/schema.gql' + } + }), + UserModule + ] +}) +export class AppModule {} diff --git a/examples/federation-v2/user-graphql/src/main.ts b/examples/federation-v2/user-graphql/src/main.ts new file mode 100644 index 000000000..2c1b20ab3 --- /dev/null +++ b/examples/federation-v2/user-graphql/src/main.ts @@ -0,0 +1,23 @@ +import { ValidationPipe } from '@nestjs/common' +import { NestFactory } from '@nestjs/core' + +import { AppModule } from './app.module' + +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + whitelist: true, + forbidNonWhitelisted: true, + skipMissingProperties: false, + forbidUnknownValues: true + }) + ) + + await app.listen(3004) +} + +// eslint-disable-next-line no-void +void bootstrap() diff --git a/examples/federation-v2/user-graphql/src/user/dto/user-input.dto.ts b/examples/federation-v2/user-graphql/src/user/dto/user-input.dto.ts new file mode 100644 index 000000000..a99f7482e --- /dev/null +++ b/examples/federation-v2/user-graphql/src/user/dto/user-input.dto.ts @@ -0,0 +1,14 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsEmail, IsString, MaxLength } from 'class-validator' + +@InputType('UserInput') +export class UserInputDTO { + @IsString() + @MaxLength(50) + @Field() + name!: string + + @IsEmail() + @Field() + email!: string +} diff --git a/examples/federation-v2/user-graphql/src/user/dto/user-update.dto.ts b/examples/federation-v2/user-graphql/src/user/dto/user-update.dto.ts new file mode 100644 index 000000000..0156120c6 --- /dev/null +++ b/examples/federation-v2/user-graphql/src/user/dto/user-update.dto.ts @@ -0,0 +1,16 @@ +import { Field, InputType } from '@nestjs/graphql' +import { IsEmail, IsOptional, IsString, MaxLength } from 'class-validator' + +@InputType('UserUpdate') +export class UserUpdateDTO { + @IsOptional() + @IsString() + @MaxLength(50) + @Field({ nullable: true }) + name?: string + + @IsOptional() + @IsEmail() + @Field({ nullable: true }) + email?: string +} diff --git a/examples/federation-v2/user-graphql/src/user/dto/user.dto.ts b/examples/federation-v2/user-graphql/src/user/dto/user.dto.ts new file mode 100644 index 000000000..477c406c7 --- /dev/null +++ b/examples/federation-v2/user-graphql/src/user/dto/user.dto.ts @@ -0,0 +1,21 @@ +import { Directive, GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql' +import { FilterableField } from '@ptc-org/nestjs-query-graphql' + +@ObjectType('User') +@Directive('@key(fields: "id")') +export class UserDTO { + @FilterableField(() => ID) + id!: number + + @FilterableField() + name!: string + + @FilterableField() + email!: string + + @FilterableField(() => GraphQLISODateTime) + created!: Date + + @FilterableField(() => GraphQLISODateTime) + updated!: Date +} diff --git a/examples/federation-v2/user-graphql/src/user/user.entity.ts b/examples/federation-v2/user-graphql/src/user/user.entity.ts new file mode 100644 index 000000000..7fde240cd --- /dev/null +++ b/examples/federation-v2/user-graphql/src/user/user.entity.ts @@ -0,0 +1,19 @@ +import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm' + +@Entity({ name: 'user' }) +export class UserEntity { + @PrimaryGeneratedColumn() + id!: number + + @Column() + name!: string + + @Column() + email!: string + + @CreateDateColumn() + created!: Date + + @UpdateDateColumn() + updated!: Date +} diff --git a/examples/federation-v2/user-graphql/src/user/user.module.ts b/examples/federation-v2/user-graphql/src/user/user.module.ts new file mode 100644 index 000000000..32980a360 --- /dev/null +++ b/examples/federation-v2/user-graphql/src/user/user.module.ts @@ -0,0 +1,26 @@ +import { Module } from '@nestjs/common' +import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql' +import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm' + +import { UserDTO } from './dto/user.dto' +import { UserInputDTO } from './dto/user-input.dto' +import { UserUpdateDTO } from './dto/user-update.dto' +import { UserEntity } from './user.entity' + +@Module({ + imports: [ + NestjsQueryGraphQLModule.forFeature({ + imports: [NestjsQueryTypeOrmModule.forFeature([UserEntity])], + resolvers: [ + { + DTOClass: UserDTO, + EntityClass: UserEntity, + CreateDTOClass: UserInputDTO, + UpdateDTOClass: UserUpdateDTO, + referenceBy: { key: 'id' } + } + ] + }) + ] +}) +export class UserModule {} diff --git a/examples/federation/graphql-gateway/src/app.module.ts b/examples/federation/graphql-gateway/src/app.module.ts index d80ff3c5c..8457fc116 100644 --- a/examples/federation/graphql-gateway/src/app.module.ts +++ b/examples/federation/graphql-gateway/src/app.module.ts @@ -6,7 +6,7 @@ import { GraphQLModule } from '@nestjs/graphql' imports: [ GraphQLModule.forRoot({ driver: ApolloFederationDriver, - autoSchemaFile: 'examples/graphql-gateway/schema.gql', + autoSchemaFile: 'examples/federation/graphql-gateway/schema.gql', server: { // ... Apollo server options cors: true diff --git a/examples/federation/sub-task-graphql/schema.gql b/examples/federation/sub-task-graphql/schema.gql new file mode 100644 index 000000000..2ce17cf55 --- /dev/null +++ b/examples/federation/sub-task-graphql/schema.gql @@ -0,0 +1,349 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +directive @key(fields: String!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE + +directive @extends on OBJECT | INTERFACE + +directive @external on OBJECT | FIELD_DEFINITION + +directive @requires(fields: String!) on FIELD_DEFINITION + +directive @provides(fields: String!) on FIELD_DEFINITION + +directive @shareable on FIELD_DEFINITION | OBJECT + +directive @link(url: String!, import: [link__Import]) on SCHEMA + +directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @override(from: String!) on FIELD_DEFINITION + +type TodoItem { + id: ID! + subTasks( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: SubTaskFilter! = {} + + """Specify to sort results.""" + sorting: [SubTaskSort!]! = [] + ): TodoItemSubTasksConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +input SubTaskFilter { + and: [SubTaskFilter!] + or: [SubTaskFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input BooleanFieldComparison { + is: Boolean + isNot: Boolean +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input NumberFieldComparison { + is: Boolean + isNot: Boolean + eq: Float + neq: Float + gt: Float + gte: Float + lt: Float + lte: Float + in: [Float!] + notIn: [Float!] + between: NumberFieldComparisonBetween + notBetween: NumberFieldComparisonBetween +} + +input NumberFieldComparisonBetween { + lower: Float! + upper: Float! +} + +input SubTaskSort { + field: SubTaskSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum SubTaskSortFields { + id + title + description + completed + created + updated + todoItemId +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type SubTask { + id: ID! + title: String! + description: String + completed: Boolean! + created: DateTime! + updated: DateTime! + todoItemId: Float! + todoItem: TodoItem! +} + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type SubTaskDeleteResponse { + id: ID + title: String + description: String + completed: Boolean + created: DateTime + updated: DateTime + todoItemId: Float +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type SubTaskEdge { + """The node containing the SubTask""" + node: SubTask! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type SubTaskConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [SubTaskEdge!]! +} + +type TodoItemSubTasksConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [SubTaskEdge!]! +} + +type Query { + subTask( + """The id of the record to find.""" + id: ID! + ): SubTask! + subTasks( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: SubTaskFilter! = {} + + """Specify to sort results.""" + sorting: [SubTaskSort!]! = [] + ): SubTaskConnection! +} + +type Mutation { + createOneSubTask(input: CreateOneSubTaskInput!): SubTask! + createManySubTasks(input: CreateManySubTasksInput!): [SubTask!]! + updateOneSubTask(input: UpdateOneSubTaskInput!): SubTask! + updateManySubTasks(input: UpdateManySubTasksInput!): UpdateManyResponse! + deleteOneSubTask(input: DeleteOneSubTaskInput!): SubTaskDeleteResponse! + deleteManySubTasks(input: DeleteManySubTasksInput!): DeleteManyResponse! +} + +input CreateOneSubTaskInput { + """The record to create""" + subTask: SubTaskInput! +} + +input SubTaskInput { + title: String! + description: String + completed: Boolean! + todoItemId: ID! +} + +input CreateManySubTasksInput { + """Array of records to create""" + subTasks: [SubTaskInput!]! +} + +input UpdateOneSubTaskInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: SubTaskUpdate! +} + +input SubTaskUpdate { + title: String! + description: String + completed: Boolean + todoItemId: Float +} + +input UpdateManySubTasksInput { + """Filter used to find fields to update""" + filter: SubTaskUpdateFilter! + + """The update to apply to all records found using the filter""" + update: SubTaskUpdate! +} + +input SubTaskUpdateFilter { + and: [SubTaskUpdateFilter!] + or: [SubTaskUpdateFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} + +input DeleteOneSubTaskInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManySubTasksInput { + """Filter to find records to delete""" + filter: SubTaskDeleteFilter! +} + +input SubTaskDeleteFilter { + and: [SubTaskDeleteFilter!] + or: [SubTaskDeleteFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + created: DateFieldComparison + updated: DateFieldComparison + todoItemId: NumberFieldComparison +} + +scalar link__Import \ No newline at end of file diff --git a/examples/federation/sub-task-graphql/src/app.module.ts b/examples/federation/sub-task-graphql/src/app.module.ts index 1f7ebfac3..b6ac0d3a3 100644 --- a/examples/federation/sub-task-graphql/src/app.module.ts +++ b/examples/federation/sub-task-graphql/src/app.module.ts @@ -11,7 +11,7 @@ import { SubTaskModule } from './sub-task/sub-task.module' TypeOrmModule.forRoot(typeormOrmConfig('federation_sub_task')), GraphQLModule.forRoot({ driver: ApolloFederationDriver, - autoSchemaFile: 'examples/sub-task-graphql/schema.gql' + autoSchemaFile: 'examples/federation/sub-task-graphql/schema.gql' }), SubTaskModule ] diff --git a/examples/federation/tag-graphql/schema.gql b/examples/federation/tag-graphql/schema.gql new file mode 100644 index 000000000..97bd69d36 --- /dev/null +++ b/examples/federation/tag-graphql/schema.gql @@ -0,0 +1,446 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +directive @key(fields: String!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE + +directive @extends on OBJECT | INTERFACE + +directive @external on OBJECT | FIELD_DEFINITION + +directive @requires(fields: String!) on FIELD_DEFINITION + +directive @provides(fields: String!) on FIELD_DEFINITION + +directive @shareable on FIELD_DEFINITION | OBJECT + +directive @link(url: String!, import: [link__Import]) on SCHEMA + +directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @override(from: String!) on FIELD_DEFINITION + +type TodoItem { + id: ID! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TodoItemTagTodoItemsConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +input TagTodoItemFilter { + and: [TagTodoItemFilter!] + or: [TagTodoItemFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input TagTodoItemSort { + field: TagTodoItemSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TagTodoItemSortFields { + tagId + todoItemId + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type TagTodoItem { + tagId: ID! + todoItemId: ID! + created: DateTime! + updated: DateTime! + todoItem: TodoItem! + tag: Tag! +} + +type Tag { + id: ID! + name: String! + created: DateTime! + updated: DateTime! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TagTagTodoItemsConnection! +} + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type TagDeleteResponse { + id: ID + name: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type TagEdge { + """The node containing the Tag""" + node: Tag! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type TagConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagEdge!]! +} + +type TagTodoItemEdge { + """The node containing the TagTodoItem""" + node: TagTodoItem! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +type TagTagTodoItemsConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type TagTodoItemDeleteResponse { + tagId: ID + todoItemId: ID + created: DateTime + updated: DateTime +} + +type TagTodoItemConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type TodoItemTagTodoItemsConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TagTodoItemEdge!]! +} + +type Query { + tag( + """The id of the record to find.""" + id: ID! + ): Tag! + tags( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagFilter! = {} + + """Specify to sort results.""" + sorting: [TagSort!]! = [] + ): TagConnection! + tagTodoItem( + """The id of the record to find.""" + id: ID! + ): TagTodoItem! + tagTodoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TagTodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TagTodoItemSort!]! = [] + ): TagTodoItemConnection! +} + +input TagFilter { + and: [TagFilter!] + or: [TagFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input TagSort { + field: TagSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TagSortFields { + id + name + created + updated +} + +type Mutation { + createOneTag(input: CreateOneTagInput!): Tag! + createManyTags(input: CreateManyTagsInput!): [Tag!]! + updateOneTag(input: UpdateOneTagInput!): Tag! + updateManyTags(input: UpdateManyTagsInput!): UpdateManyResponse! + deleteOneTag(input: DeleteOneTagInput!): TagDeleteResponse! + deleteManyTags(input: DeleteManyTagsInput!): DeleteManyResponse! + createOneTagTodoItem(input: CreateOneTagTodoItemInput!): TagTodoItem! + createManyTagTodoItems(input: CreateManyTagTodoItemsInput!): [TagTodoItem!]! + updateOneTagTodoItem(input: UpdateOneTagTodoItemInput!): TagTodoItem! + updateManyTagTodoItems(input: UpdateManyTagTodoItemsInput!): UpdateManyResponse! + deleteOneTagTodoItem(input: DeleteOneTagTodoItemInput!): TagTodoItemDeleteResponse! + deleteManyTagTodoItems(input: DeleteManyTagTodoItemsInput!): DeleteManyResponse! +} + +input CreateOneTagInput { + """The record to create""" + tag: TagInput! +} + +input TagInput { + name: String! +} + +input CreateManyTagsInput { + """Array of records to create""" + tags: [TagInput!]! +} + +input UpdateOneTagInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TagInput! +} + +input UpdateManyTagsInput { + """Filter used to find fields to update""" + filter: TagUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TagInput! +} + +input TagUpdateFilter { + and: [TagUpdateFilter!] + or: [TagUpdateFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTagInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTagsInput { + """Filter to find records to delete""" + filter: TagDeleteFilter! +} + +input TagDeleteFilter { + and: [TagDeleteFilter!] + or: [TagDeleteFilter!] + id: IDFilterComparison + name: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input CreateOneTagTodoItemInput { + """The record to create""" + tagTodoItem: TagTodoItemInput! +} + +input TagTodoItemInput { + tagId: Float! + todoItemId: Float! +} + +input CreateManyTagTodoItemsInput { + """Array of records to create""" + tagTodoItems: [TagTodoItemInput!]! +} + +input UpdateOneTagTodoItemInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TagTodoItemInput! +} + +input UpdateManyTagTodoItemsInput { + """Filter used to find fields to update""" + filter: TagTodoItemUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TagTodoItemInput! +} + +input TagTodoItemUpdateFilter { + and: [TagTodoItemUpdateFilter!] + or: [TagTodoItemUpdateFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTagTodoItemInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTagTodoItemsInput { + """Filter to find records to delete""" + filter: TagTodoItemDeleteFilter! +} + +input TagTodoItemDeleteFilter { + and: [TagTodoItemDeleteFilter!] + or: [TagTodoItemDeleteFilter!] + tagId: IDFilterComparison + todoItemId: IDFilterComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +scalar link__Import \ No newline at end of file diff --git a/examples/federation/tag-graphql/src/app.module.ts b/examples/federation/tag-graphql/src/app.module.ts index a89937bb2..855a8747c 100644 --- a/examples/federation/tag-graphql/src/app.module.ts +++ b/examples/federation/tag-graphql/src/app.module.ts @@ -11,7 +11,7 @@ import { TagModule } from './tag/tag.module' TypeOrmModule.forRoot(typeormOrmConfig('federation_tag')), GraphQLModule.forRoot({ driver: ApolloFederationDriver, - autoSchemaFile: 'examples/tag-graphql/schema.gql' + autoSchemaFile: 'examples/federation/tag-graphql/schema.gql' }), TagModule ] diff --git a/examples/federation/todo-item-graphql/schema.gql b/examples/federation/todo-item-graphql/schema.gql new file mode 100644 index 000000000..6958787b8 --- /dev/null +++ b/examples/federation/todo-item-graphql/schema.gql @@ -0,0 +1,309 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +directive @key(fields: String!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE + +directive @extends on OBJECT | INTERFACE + +directive @external on OBJECT | FIELD_DEFINITION + +directive @requires(fields: String!) on FIELD_DEFINITION + +directive @provides(fields: String!) on FIELD_DEFINITION + +directive @shareable on FIELD_DEFINITION | OBJECT + +directive @link(url: String!, import: [link__Import]) on SCHEMA + +directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @override(from: String!) on FIELD_DEFINITION + +type User { + id: ID! +} + +type TodoItem { + id: ID! + title: String! + description: String + completed: Boolean! + assigneeId: String + created: DateTime! + updated: DateTime! + assignee: User +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type TodoItemDeleteResponse { + id: ID + title: String + description: String + completed: Boolean + assigneeId: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type TodoItemEdge { + """The node containing the TodoItem""" + node: TodoItem! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type TodoItemConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [TodoItemEdge!]! +} + +type Query { + todoItem( + """The id of the record to find.""" + id: ID! + ): TodoItem! + todoItems( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: TodoItemFilter! = {} + + """Specify to sort results.""" + sorting: [TodoItemSort!]! = [] + ): TodoItemConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +input TodoItemFilter { + and: [TodoItemFilter!] + or: [TodoItemFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input BooleanFieldComparison { + is: Boolean + isNot: Boolean +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input TodoItemSort { + field: TodoItemSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum TodoItemSortFields { + id + title + description + completed + assigneeId + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type Mutation { + createOneTodoItem(input: CreateOneTodoItemInput!): TodoItem! + createManyTodoItems(input: CreateManyTodoItemsInput!): [TodoItem!]! + updateOneTodoItem(input: UpdateOneTodoItemInput!): TodoItem! + updateManyTodoItems(input: UpdateManyTodoItemsInput!): UpdateManyResponse! + deleteOneTodoItem(input: DeleteOneTodoItemInput!): TodoItemDeleteResponse! + deleteManyTodoItems(input: DeleteManyTodoItemsInput!): DeleteManyResponse! +} + +input CreateOneTodoItemInput { + """The record to create""" + todoItem: TodoItemInput! +} + +input TodoItemInput { + title: String! + completed: Boolean! + assigneeId: ID +} + +input CreateManyTodoItemsInput { + """Array of records to create""" + todoItems: [TodoItemInput!]! +} + +input UpdateOneTodoItemInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: TodoItemUpdate! +} + +input TodoItemUpdate { + title: String + completed: Boolean + assigneeId: ID +} + +input UpdateManyTodoItemsInput { + """Filter used to find fields to update""" + filter: TodoItemUpdateFilter! + + """The update to apply to all records found using the filter""" + update: TodoItemUpdate! +} + +input TodoItemUpdateFilter { + and: [TodoItemUpdateFilter!] + or: [TodoItemUpdateFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneTodoItemInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyTodoItemsInput { + """Filter to find records to delete""" + filter: TodoItemDeleteFilter! +} + +input TodoItemDeleteFilter { + and: [TodoItemDeleteFilter!] + or: [TodoItemDeleteFilter!] + id: IDFilterComparison + title: StringFieldComparison + description: StringFieldComparison + completed: BooleanFieldComparison + assigneeId: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +scalar link__Import \ No newline at end of file diff --git a/examples/federation/todo-item-graphql/src/app.module.ts b/examples/federation/todo-item-graphql/src/app.module.ts index f48234af9..d515d3d34 100644 --- a/examples/federation/todo-item-graphql/src/app.module.ts +++ b/examples/federation/todo-item-graphql/src/app.module.ts @@ -11,7 +11,7 @@ import { TodoItemModule } from './todo-item/todo-item.module' TypeOrmModule.forRoot(typeormOrmConfig('federation_todo_item')), GraphQLModule.forRoot({ driver: ApolloFederationDriver, - autoSchemaFile: 'examples/todo-item-graphql/schema.gql' + autoSchemaFile: 'examples/federation/todo-item-graphql/schema.gql' }), TodoItemModule ] diff --git a/examples/federation/user-graphql/schema.gql b/examples/federation/user-graphql/schema.gql new file mode 100644 index 000000000..8df7bedaf --- /dev/null +++ b/examples/federation/user-graphql/schema.gql @@ -0,0 +1,285 @@ +# ------------------------------------------------------ +# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) +# ------------------------------------------------------ + +directive @key(fields: String!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE + +directive @extends on OBJECT | INTERFACE + +directive @external on OBJECT | FIELD_DEFINITION + +directive @requires(fields: String!) on FIELD_DEFINITION + +directive @provides(fields: String!) on FIELD_DEFINITION + +directive @shareable on FIELD_DEFINITION | OBJECT + +directive @link(url: String!, import: [link__Import]) on SCHEMA + +directive @tag(name: String!) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @override(from: String!) on FIELD_DEFINITION + +type User { + id: ID! + name: String! + email: String! + created: DateTime! + updated: DateTime! +} + +""" +A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. +""" +scalar DateTime + +type DeleteManyResponse { + """The number of records deleted.""" + deletedCount: Int! +} + +type UserDeleteResponse { + id: ID + name: String + email: String + created: DateTime + updated: DateTime +} + +type UpdateManyResponse { + """The number of records updated.""" + updatedCount: Int! +} + +type UserEdge { + """The node containing the User""" + node: User! + + """Cursor for this node.""" + cursor: ConnectionCursor! +} + +"""Cursor for paging through collections""" +scalar ConnectionCursor + +type PageInfo { + """true if paging forward and there are more records.""" + hasNextPage: Boolean + + """true if paging backwards and there are more records.""" + hasPreviousPage: Boolean + + """The cursor of the first returned record.""" + startCursor: ConnectionCursor + + """The cursor of the last returned record.""" + endCursor: ConnectionCursor +} + +type UserConnection { + """Paging information""" + pageInfo: PageInfo! + + """Array of edges.""" + edges: [UserEdge!]! +} + +type Query { + user( + """The id of the record to find.""" + id: ID! + ): User! + users( + """Limit or page results.""" + paging: CursorPaging! = {first: 10} + + """Specify to filter the records returned.""" + filter: UserFilter! = {} + + """Specify to sort results.""" + sorting: [UserSort!]! = [] + ): UserConnection! +} + +input CursorPaging { + """Paginate before opaque cursor""" + before: ConnectionCursor + + """Paginate after opaque cursor""" + after: ConnectionCursor + + """Paginate first""" + first: Int + + """Paginate last""" + last: Int +} + +input UserFilter { + and: [UserFilter!] + or: [UserFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input IDFilterComparison { + is: Boolean + isNot: Boolean + eq: ID + neq: ID + gt: ID + gte: ID + lt: ID + lte: ID + like: ID + notLike: ID + iLike: ID + notILike: ID + in: [ID!] + notIn: [ID!] +} + +input StringFieldComparison { + is: Boolean + isNot: Boolean + eq: String + neq: String + gt: String + gte: String + lt: String + lte: String + like: String + notLike: String + iLike: String + notILike: String + in: [String!] + notIn: [String!] +} + +input DateFieldComparison { + is: Boolean + isNot: Boolean + eq: DateTime + neq: DateTime + gt: DateTime + gte: DateTime + lt: DateTime + lte: DateTime + in: [DateTime!] + notIn: [DateTime!] + between: DateFieldComparisonBetween + notBetween: DateFieldComparisonBetween +} + +input DateFieldComparisonBetween { + lower: DateTime! + upper: DateTime! +} + +input UserSort { + field: UserSortFields! + direction: SortDirection! + nulls: SortNulls +} + +enum UserSortFields { + id + name + email + created + updated +} + +"""Sort Directions""" +enum SortDirection { + ASC + DESC +} + +"""Sort Nulls Options""" +enum SortNulls { + NULLS_FIRST + NULLS_LAST +} + +type Mutation { + createOneUser(input: CreateOneUserInput!): User! + createManyUsers(input: CreateManyUsersInput!): [User!]! + updateOneUser(input: UpdateOneUserInput!): User! + updateManyUsers(input: UpdateManyUsersInput!): UpdateManyResponse! + deleteOneUser(input: DeleteOneUserInput!): UserDeleteResponse! + deleteManyUsers(input: DeleteManyUsersInput!): DeleteManyResponse! +} + +input CreateOneUserInput { + """The record to create""" + user: UserInput! +} + +input UserInput { + name: String! + email: String! +} + +input CreateManyUsersInput { + """Array of records to create""" + users: [UserInput!]! +} + +input UpdateOneUserInput { + """The id of the record to update""" + id: ID! + + """The update to apply.""" + update: UserUpdate! +} + +input UserUpdate { + name: String + email: String +} + +input UpdateManyUsersInput { + """Filter used to find fields to update""" + filter: UserUpdateFilter! + + """The update to apply to all records found using the filter""" + update: UserUpdate! +} + +input UserUpdateFilter { + and: [UserUpdateFilter!] + or: [UserUpdateFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +input DeleteOneUserInput { + """The id of the record to delete.""" + id: ID! +} + +input DeleteManyUsersInput { + """Filter to find records to delete""" + filter: UserDeleteFilter! +} + +input UserDeleteFilter { + and: [UserDeleteFilter!] + or: [UserDeleteFilter!] + id: IDFilterComparison + name: StringFieldComparison + email: StringFieldComparison + created: DateFieldComparison + updated: DateFieldComparison +} + +scalar link__Import \ No newline at end of file diff --git a/examples/federation/user-graphql/src/app.module.ts b/examples/federation/user-graphql/src/app.module.ts index f4a197165..fac2e84c9 100644 --- a/examples/federation/user-graphql/src/app.module.ts +++ b/examples/federation/user-graphql/src/app.module.ts @@ -11,7 +11,7 @@ import { UserModule } from './user/user.module' TypeOrmModule.forRoot(typeormOrmConfig('federation_user')), GraphQLModule.forRoot({ driver: ApolloFederationDriver, - autoSchemaFile: 'examples/user-graphql/schema.gql' + autoSchemaFile: 'examples/federation/user-graphql/schema.gql' }), UserModule ] diff --git a/package.json b/package.json index 8a0871f99..08ae2ec9c 100644 --- a/package.json +++ b/package.json @@ -11,59 +11,60 @@ "test:e2e": "nx e2e examples" }, "dependencies": { - "@apollo/federation": "0.38.1", - "@apollo/server": "^4.9.3", - "@docusaurus/core": "2.4.1", - "@docusaurus/preset-classic": "2.4.1", + "@docusaurus/core": "2.4.3", + "@docusaurus/preset-classic": "2.4.3", "@m8a/nestjs-typegoose": "11.1.0", - "@nestjs/common": "10.2.3", - "@nestjs/core": "10.2.3", - "@nestjs/graphql": "^12.0.8", - "@nestjs/jwt": "10.1.0", + "@nestjs/common": "10.2.7", + "@nestjs/core": "10.2.7", + "@nestjs/graphql": "^12.0.9", + "@nestjs/jwt": "10.1.1", "@nestjs/mongoose": "10.0.1", - "@nestjs/passport": "10.0.1", - "@nestjs/platform-express": "10.2.3", + "@nestjs/passport": "10.0.2", + "@nestjs/platform-express": "10.2.7", "@nestjs/sequelize": "10.0.0", "@nestjs/typeorm": "^10.0.0", "class-validator": "0.14.0", "clsx": "^2.0.0", - "mongoose": "^7.5.0", - "mysql2": "3.6.0", + "mongoose": "^7.5.4", + "mysql2": "3.6.1", "passport": "0.6.0", "passport-jwt": "4.0.1", "passport-local": "1.0.0", "pg": "8.11.3", - "prism-react-renderer": "^2.0.6", + "prism-react-renderer": "^2.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "reflect-metadata": "^0.1.13", - "rimraf": "5.0.1", + "rimraf": "5.0.5", "rxjs": "7.8.1", - "sequelize": "6.32.1", + "sequelize": "6.33.0", "sequelize-typescript": "2.1.5", "tslib": "^2.6.2", "typeorm": "^0.3.17" }, "devDependencies": { - "@actions/core": "^1.10.0", - "@apollo/gateway": "2.5.3", - "@commitlint/cli": "17.7.1", + "@actions/core": "^1.10.1", + "@apollo/federation": "0.38.1", + "@apollo/gateway": "2.2.3", + "@apollo/server": "^4.9.4", + "@apollo/subgraph": "2.2.3", + "@commitlint/cli": "17.7.2", "@commitlint/config-conventional": "^17.7.0", - "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.3", "@jscutlery/semver": "3.1.0", - "@nestjs/apollo": "^12.0.7", - "@nestjs/cli": "10.1.17", + "@nestjs/apollo": "^12.0.9", + "@nestjs/cli": "10.1.18", "@nestjs/schematics": "10.0.2", - "@nestjs/testing": "^10.2.3", + "@nestjs/testing": "^10.2.7", "@nx-plus/docusaurus": "^15.0.0-rc.0", "@nx/eslint-plugin": "16.8.1", "@nx/jest": "16.8.1", "@nx/js": "16.8.1", "@nx/linter": "16.8.1", "@nx/node": "16.8.1", - "@typegoose/typegoose": "^11.4.1", - "@types/express": "4.17.17", - "@types/jest": "29.5.4", + "@typegoose/typegoose": "^11.5.0", + "@types/express": "4.17.18", + "@types/jest": "29.5.5", "@types/lodash.escaperegexp": "4.1.7", "@types/lodash.filter": "4.6.7", "@types/lodash.keys": "4.2.7", @@ -71,36 +72,36 @@ "@types/lodash.omit": "4.5.7", "@types/lodash.pick": "4.4.7", "@types/lodash.pickby": "4.6.7", - "@types/node": "20.5.7", - "@types/passport-jwt": "3.0.9", - "@types/passport-local": "1.0.35", - "@types/pluralize": "0.0.30", - "@types/supertest": "2.0.12", - "@types/uuid": "9.0.3", - "@types/ws": "8.5.5", - "@typescript-eslint/eslint-plugin": "6.5.0", - "@typescript-eslint/parser": "6.5.0", + "@types/node": "20.8.2", + "@types/passport-jwt": "3.0.10", + "@types/passport-local": "1.0.36", + "@types/pluralize": "0.0.31", + "@types/supertest": "2.0.14", + "@types/uuid": "9.0.4", + "@types/ws": "8.5.6", + "@typescript-eslint/eslint-plugin": "6.7.4", + "@typescript-eslint/parser": "6.7.4", "class-transformer": "0.5.1", "class-validator": "0.14.0", "dataloader": "2.2.2", - "eslint": "8.48.0", + "eslint": "8.50.0", "eslint-config-airbnb": "19.0.4", "eslint-config-airbnb-typescript": "17.1.0", "eslint-config-prettier": "9.0.0", - "eslint-import-resolver-typescript": "3.6.0", + "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-import": "2.28.1", - "eslint-plugin-jest": "27.2.3", + "eslint-plugin-jest": "27.4.2", "eslint-plugin-prettier": "5.0.0", "eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-tsdoc": "0.2.17", - "graphql": "16.8.0", + "graphql": "16.8.1", "graphql-query-complexity": "0.12.0", "graphql-subscriptions": "2.0.0", "graphql-tools": "9.0.0", "husky": "8.0.3", - "jest": "29.6.4", + "jest": "29.7.0", "jest-extended": "4.0.1", - "mongodb-memory-server": "8.15.1", + "mongodb-memory-server": "8.16.0", "nx": "16.8.1", "nx-cloud": "16.4.0", "prettier": "3.0.3", diff --git a/packages/query-typeorm/package.json b/packages/query-typeorm/package.json index 5bf68583c..5c0e6a812 100644 --- a/packages/query-typeorm/package.json +++ b/packages/query-typeorm/package.json @@ -25,7 +25,7 @@ "lodash.omit": "^4.5.0", "lodash.pickby": "^4.6.0", "tslib": "^2.6.2", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "peerDependencies": { "@nestjs/common": "^9.0.0 || ^10.0.0", diff --git a/yarn.lock b/yarn.lock index 71deea9b8..e4fae79b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,13 +12,13 @@ __metadata: languageName: node linkType: hard -"@actions/core@npm:^1.10.0": - version: 1.10.0 - resolution: "@actions/core@npm:1.10.0" +"@actions/core@npm:^1.10.1": + version: 1.10.1 + resolution: "@actions/core@npm:1.10.1" dependencies: "@actions/http-client": ^2.0.1 uuid: ^8.3.2 - checksum: 0a75621e007ab20d887434cdd165f0b9036f14c22252a2faed33543d8b9d04ec95d823e69ca636a25245574e4585d73e1e9e47a845339553c664f9f2c9614669 + checksum: 96524c2725e70e3c3176b4e4d93a1358a86f3c5ca777db9a2f65eadfa672f00877db359bf60fffc416c33838ffb4743db93bcc5bf53e76199dd28bf7f7ff8e80 languageName: node linkType: hard @@ -259,13 +259,14 @@ __metadata: languageName: node linkType: hard -"@angular-devkit/core@npm:16.2.0": - version: 16.2.0 - resolution: "@angular-devkit/core@npm:16.2.0" +"@angular-devkit/core@npm:16.2.3": + version: 16.2.3 + resolution: "@angular-devkit/core@npm:16.2.3" dependencies: ajv: 8.12.0 ajv-formats: 2.1.1 jsonc-parser: 3.2.0 + picomatch: 2.3.1 rxjs: 7.8.1 source-map: 0.7.4 peerDependencies: @@ -273,23 +274,23 @@ __metadata: peerDependenciesMeta: chokidar: optional: true - checksum: 307546a9ad9e6cdecff82f49891a6c2a6c63f7eae37442b40f5d492b95c6bf94b9061ac1855e0aab7132a8e4b05e37c5bb10fb6822a9e950720b7ea20cf3cbe0 + checksum: e040a043f18c140bdcd4f12e1cafd1114d6c8f489d5c5cf6c789157db3f6922a6e546e7ea70af6a9b6956d2f56f5c650ec6dfe4d3f1574745f6e7585f41d3aef languageName: node linkType: hard -"@angular-devkit/schematics-cli@npm:16.2.0": - version: 16.2.0 - resolution: "@angular-devkit/schematics-cli@npm:16.2.0" +"@angular-devkit/schematics-cli@npm:16.2.3": + version: 16.2.3 + resolution: "@angular-devkit/schematics-cli@npm:16.2.3" dependencies: - "@angular-devkit/core": 16.2.0 - "@angular-devkit/schematics": 16.2.0 + "@angular-devkit/core": 16.2.3 + "@angular-devkit/schematics": 16.2.3 ansi-colors: 4.1.3 inquirer: 8.2.4 symbol-observable: 4.0.0 yargs-parser: 21.1.1 bin: schematics: bin/schematics.js - checksum: 04054bf53e1b8ec9b4219efac4357e245c6573fce56d925a59ac30c747bc7b08108896c8d8d22a521eb59e82222ff46c68fbd8e2be09e4e98c45aa0821e08830 + checksum: 2117168b39d9979db8e968d07a9c960d9837e0fb2b5ef5d694e7788bfcc3843a6cd0a0925c426807c9fcc530c0a06b0da0b804739853aa066e863e1905383f73 languageName: node linkType: hard @@ -319,16 +320,16 @@ __metadata: languageName: node linkType: hard -"@angular-devkit/schematics@npm:16.2.0": - version: 16.2.0 - resolution: "@angular-devkit/schematics@npm:16.2.0" +"@angular-devkit/schematics@npm:16.2.3": + version: 16.2.3 + resolution: "@angular-devkit/schematics@npm:16.2.3" dependencies: - "@angular-devkit/core": 16.2.0 + "@angular-devkit/core": 16.2.3 jsonc-parser: 3.2.0 magic-string: 0.30.1 ora: 5.4.1 rxjs: 7.8.1 - checksum: a793e151ae70894e8784f3f79482dfe416722d3232fe454db685efd095b23da541316e8fe7a0cab54995a24cb95a95b2d443bc915b9637b0b31de526d2e4679c + checksum: 1e9189e5427ff30992176d812cc48cb5e51ca3bc84f1bcb55f2eb7fc44e04888bb0d911d687fbec5f5d99084cd47de39e51e5cf5b79b2de298fb62617529b310 languageName: node linkType: hard @@ -377,21 +378,21 @@ __metadata: languageName: node linkType: hard -"@apollo/composition@npm:2.5.3": - version: 2.5.3 - resolution: "@apollo/composition@npm:2.5.3" +"@apollo/composition@npm:^2.2.3": + version: 2.5.5 + resolution: "@apollo/composition@npm:2.5.5" dependencies: - "@apollo/federation-internals": 2.5.3 - "@apollo/query-graphs": 2.5.3 + "@apollo/federation-internals": 2.5.5 + "@apollo/query-graphs": 2.5.5 peerDependencies: graphql: ^16.5.0 - checksum: 8b117c434e4f184df848fbaafb0ae4e4f4d24270d89c74298cef2787cbefd32b9058edbbc5c49af447a758f4bc585d1cdecd620d8bb6c31051df55624f0b22c7 + checksum: 912ddf00d9aa01fc7df1cf82876cf3687711dffd652e3c0712ce00d5679954cae3a5b67be3063c6e1afe48ba1d78e7738354ed6b8973546f66fda2f65a46f03e languageName: node linkType: hard -"@apollo/federation-internals@npm:2.5.3": - version: 2.5.3 - resolution: "@apollo/federation-internals@npm:2.5.3" +"@apollo/federation-internals@npm:2.5.5, @apollo/federation-internals@npm:^2.2.3": + version: 2.5.5 + resolution: "@apollo/federation-internals@npm:2.5.5" dependencies: "@types/uuid": ^9.0.0 chalk: ^4.1.0 @@ -399,7 +400,7 @@ __metadata: uuid: ^9.0.0 peerDependencies: graphql: ^16.5.0 - checksum: bc3b90835f1e0908e515f63e3afd65795efb69a68a333063a522a88948ca52c6a73e339d7673d7d0ad7b43e7f94766872e5abcdb4e89ee6d7c0f167a27e5458c + checksum: 9192404f0a5ef3711e08c57f3ba628420ab2c1ab262ad266311e5e2ac54503040c554aa10a805496fb59c5794cd2239d8b29a25b62bfe9fe0cde7e0c7de822f9 languageName: node linkType: hard @@ -416,31 +417,31 @@ __metadata: languageName: node linkType: hard -"@apollo/gateway@npm:2.5.3": - version: 2.5.3 - resolution: "@apollo/gateway@npm:2.5.3" - dependencies: - "@apollo/composition": 2.5.3 - "@apollo/federation-internals": 2.5.3 - "@apollo/query-planner": 2.5.3 - "@apollo/server-gateway-interface": ^1.1.0 - "@apollo/usage-reporting-protobuf": ^4.1.0 - "@apollo/utils.createhash": ^2.0.0 - "@apollo/utils.fetcher": ^2.0.0 - "@apollo/utils.isnodelike": ^2.0.0 - "@apollo/utils.keyvaluecache": ^2.1.0 - "@apollo/utils.logger": ^2.0.0 +"@apollo/gateway@npm:2.2.3": + version: 2.2.3 + resolution: "@apollo/gateway@npm:2.2.3" + dependencies: + "@apollo/composition": ^2.2.3 + "@apollo/federation-internals": ^2.2.3 + "@apollo/query-planner": ^2.2.3 + "@apollo/server-gateway-interface": ^1.0.2 + "@apollo/usage-reporting-protobuf": ^4.0.0 + "@apollo/utils.createhash": ^1.1.0 + "@apollo/utils.fetcher": ^1.1.0 + "@apollo/utils.isnodelike": ^1.1.0 + "@apollo/utils.logger": ^1.0.0 "@josephg/resolvable": ^1.0.1 "@opentelemetry/api": ^1.0.1 "@types/node-fetch": ^2.6.2 async-retry: ^1.3.3 loglevel: ^1.6.1 + lru-cache: ^7.13.1 make-fetch-happen: ^11.0.0 node-abort-controller: ^3.0.1 node-fetch: ^2.6.7 peerDependencies: graphql: ^16.5.0 - checksum: 45ff8772d9499e73fc9463cf9158a45dea20811730142474257b870c4917f9008b54cd023233cabe711156488cb40893f2f26223cb8ccb93f9870ee6cdcec36b + checksum: ab31538cca91954ee2fe2f44f3efa2775962bc41e11125e6e74e5a0f741f333da33b8ed48faa7a265d019792ef15f96465e844658332ca05d2b0846c9bd6216f languageName: node linkType: hard @@ -491,37 +492,37 @@ __metadata: languageName: node linkType: hard -"@apollo/query-graphs@npm:2.5.3": - version: 2.5.3 - resolution: "@apollo/query-graphs@npm:2.5.3" +"@apollo/query-graphs@npm:2.5.5": + version: 2.5.5 + resolution: "@apollo/query-graphs@npm:2.5.5" dependencies: - "@apollo/federation-internals": 2.5.3 + "@apollo/federation-internals": 2.5.5 deep-equal: ^2.0.5 ts-graphviz: ^1.5.4 uuid: ^9.0.0 peerDependencies: graphql: ^16.5.0 - checksum: 45b2761517805537a64dfae0a9ccddb12b3fdf412e66e9b56128e5eb1c6f347bc7182d490e04913e28ae2be8776ca4f64b038ffab7f0aa50d878ba3f4203d3fc + checksum: bc5f0216ae5e5dcbdc0e9cf8aa2682fe1958c06aaade82161b882a265a2c2c606eedc40c5da54067d59bcf3c95934b468932f8383bad4633036d4d494b1379c9 languageName: node linkType: hard -"@apollo/query-planner@npm:2.5.3": - version: 2.5.3 - resolution: "@apollo/query-planner@npm:2.5.3" +"@apollo/query-planner@npm:^2.2.3": + version: 2.5.5 + resolution: "@apollo/query-planner@npm:2.5.5" dependencies: - "@apollo/federation-internals": 2.5.3 - "@apollo/query-graphs": 2.5.3 + "@apollo/federation-internals": 2.5.5 + "@apollo/query-graphs": 2.5.5 "@apollo/utils.keyvaluecache": ^2.1.0 chalk: ^4.1.0 deep-equal: ^2.0.5 pretty-format: ^29.0.0 peerDependencies: graphql: ^16.5.0 - checksum: 98bb2b1dd302de35b5460b5f92ebe9be90fd2d877fccaaa0902511f45792406676ff117c6871c77f7300e6d290ab67cee0ba83fc8e9f4f95d818bb52258ad11d + checksum: d5a6f20da03ed4a15f2b23e40a4040e6136b96281d323c0b26801a6c346c12873811e81315e0921c31eef3584eb5111bf3e750fee30dcfa54094e23ee9a3134a languageName: node linkType: hard -"@apollo/server-gateway-interface@npm:^1.1.0, @apollo/server-gateway-interface@npm:^1.1.1": +"@apollo/server-gateway-interface@npm:^1.0.2, @apollo/server-gateway-interface@npm:^1.1.1": version: 1.1.1 resolution: "@apollo/server-gateway-interface@npm:1.1.1" dependencies: @@ -546,9 +547,9 @@ __metadata: languageName: node linkType: hard -"@apollo/server@npm:^4.9.3": - version: 4.9.3 - resolution: "@apollo/server@npm:4.9.3" +"@apollo/server@npm:^4.9.4": + version: 4.9.4 + resolution: "@apollo/server@npm:4.9.4" dependencies: "@apollo/cache-control-types": ^1.0.3 "@apollo/server-gateway-interface": ^1.1.1 @@ -578,7 +579,19 @@ __metadata: whatwg-mimetype: ^3.0.0 peerDependencies: graphql: ^16.6.0 - checksum: 28537d7646669a5dc1302cfd75d8a9bf473459ee585c6b778d174628a2cfb3f89a5ac742eca7de2a779b6c9e3f30da509a8787a71227520d009ac190aa7a9207 + checksum: bf7105ffceaed6e3c54f1506513944bb324ae32e92b1aabb3ec7de1b9fee1373bdec6e1a3f5efb7c7f8090671f1ba2d37c01f5b1456c93127ffede1a0b554bac + languageName: node + linkType: hard + +"@apollo/subgraph@npm:2.2.3": + version: 2.2.3 + resolution: "@apollo/subgraph@npm:2.2.3" + dependencies: + "@apollo/cache-control-types": ^1.0.2 + "@apollo/federation-internals": ^2.2.3 + peerDependencies: + graphql: ^16.5.0 + checksum: 38b3566b1250da770fa6c0084cf1ec1bf6b59fc423d4f8ecf6f68bee1f33e2affc6bd04953a0e9fe8dd6eeb3864428709c750099b993a49e8a319af7f538cce9 languageName: node linkType: hard @@ -593,7 +606,7 @@ __metadata: languageName: node linkType: hard -"@apollo/usage-reporting-protobuf@npm:^4.1.0, @apollo/usage-reporting-protobuf@npm:^4.1.1": +"@apollo/usage-reporting-protobuf@npm:^4.0.0, @apollo/usage-reporting-protobuf@npm:^4.1.0, @apollo/usage-reporting-protobuf@npm:^4.1.1": version: 4.1.1 resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1" dependencies: @@ -602,6 +615,16 @@ __metadata: languageName: node linkType: hard +"@apollo/utils.createhash@npm:^1.1.0": + version: 1.1.0 + resolution: "@apollo/utils.createhash@npm:1.1.0" + dependencies: + "@apollo/utils.isnodelike": ^1.1.0 + sha.js: ^2.4.11 + checksum: 46790cb7af2a050f2614c356abb436da2a5fe4b7e55b487460900953a3e9ffb906c2fae2f3a219d7fcc9db795e5dac4fff64feabdc29abe8825266fafda9efd2 + languageName: node + linkType: hard + "@apollo/utils.createhash@npm:^2.0.0": version: 2.0.1 resolution: "@apollo/utils.createhash@npm:2.0.1" @@ -621,6 +644,13 @@ __metadata: languageName: node linkType: hard +"@apollo/utils.fetcher@npm:^1.1.0": + version: 1.1.1 + resolution: "@apollo/utils.fetcher@npm:1.1.1" + checksum: 7f2284cfddeb59775dc471d20d0a447049f32c069df429ac4aa7b733bd341f6cc9b755fd37226a73b00a4c9fa7f598cb2f5ce0a98dc22a2ce9217cc6947f5f09 + languageName: node + linkType: hard + "@apollo/utils.fetcher@npm:^2.0.0": version: 2.0.1 resolution: "@apollo/utils.fetcher@npm:2.0.1" @@ -628,6 +658,13 @@ __metadata: languageName: node linkType: hard +"@apollo/utils.isnodelike@npm:^1.1.0": + version: 1.1.0 + resolution: "@apollo/utils.isnodelike@npm:1.1.0" + checksum: 66d620b9db01a919858138e99e2227a793912aafa5deed3eedbaa3b29e1364b6e82c111562743951dd56f4574c331a34f83d864f0d648f5e32c9555653f121af + languageName: node + linkType: hard + "@apollo/utils.isnodelike@npm:^2.0.0, @apollo/utils.isnodelike@npm:^2.0.1": version: 2.0.1 resolution: "@apollo/utils.isnodelike@npm:2.0.1" @@ -3370,13 +3407,13 @@ __metadata: languageName: node linkType: hard -"@commitlint/cli@npm:17.7.1": - version: 17.7.1 - resolution: "@commitlint/cli@npm:17.7.1" +"@commitlint/cli@npm:17.7.2": + version: 17.7.2 + resolution: "@commitlint/cli@npm:17.7.2" dependencies: "@commitlint/format": ^17.4.4 "@commitlint/lint": ^17.7.0 - "@commitlint/load": ^17.7.1 + "@commitlint/load": ^17.7.2 "@commitlint/read": ^17.5.1 "@commitlint/types": ^17.4.4 execa: ^5.0.0 @@ -3386,7 +3423,7 @@ __metadata: yargs: ^17.0.0 bin: commitlint: cli.js - checksum: 2500a50514ab0629d3661d74e6f759f0b9b56c1992fbc101bb78a67033c6ed02a6dad3ae728f91f1f9b3034ae17e3808835957f885ab7129a421085d31f6cb23 + checksum: 7d5d86b27980135713094e44023ee7a6cc2bb1cd015f92111857e069a3127dab63d4575b507bdac2e16255aaab65da908d1f7667e8aa9de7e032d9c464ef3154 languageName: node linkType: hard @@ -3462,15 +3499,15 @@ __metadata: languageName: node linkType: hard -"@commitlint/load@npm:^17.7.1": - version: 17.7.1 - resolution: "@commitlint/load@npm:17.7.1" +"@commitlint/load@npm:^17.7.2": + version: 17.7.2 + resolution: "@commitlint/load@npm:17.7.2" dependencies: "@commitlint/config-validator": ^17.6.7 "@commitlint/execute-rule": ^17.4.0 "@commitlint/resolve-extends": ^17.6.7 "@commitlint/types": ^17.4.4 - "@types/node": 20.4.7 + "@types/node": 20.5.1 chalk: ^4.1.0 cosmiconfig: ^8.0.0 cosmiconfig-typescript-loader: ^4.0.0 @@ -3480,7 +3517,7 @@ __metadata: resolve-from: ^5.0.0 ts-node: ^10.8.1 typescript: ^4.6.4 || ^5.0.0 - checksum: 8d0e56b49a0e4dec7e8e28a2c6bc7ce985e6b8e10274aa20d0e3f6c2465fc9082d18f91bbe5c336594ebabcc4dc9668fdeaa039ef5bbfaf26ca0be423461ef61 + checksum: dda9f7efd6413309266617a5ee026df65cc8c590b86c312f5905285fcbef5ae3ec983694c145007d89402c9f728882465f016167b156f43f6ed414c3b8ca079a languageName: node linkType: hard @@ -3613,9 +3650,9 @@ __metadata: languageName: node linkType: hard -"@docusaurus/core@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/core@npm:2.4.1" +"@docusaurus/core@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/core@npm:2.4.3" dependencies: "@babel/core": ^7.18.6 "@babel/generator": ^7.18.7 @@ -3627,13 +3664,13 @@ __metadata: "@babel/runtime": ^7.18.6 "@babel/runtime-corejs3": ^7.18.6 "@babel/traverse": ^7.18.8 - "@docusaurus/cssnano-preset": 2.4.1 - "@docusaurus/logger": 2.4.1 - "@docusaurus/mdx-loader": 2.4.1 + "@docusaurus/cssnano-preset": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-common": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 "@slorber/static-site-generator-webpack-plugin": ^4.0.7 "@svgr/webpack": ^6.2.1 autoprefixer: ^10.4.7 @@ -3693,40 +3730,40 @@ __metadata: react-dom: ^16.8.4 || ^17.0.0 bin: docusaurus: bin/docusaurus.mjs - checksum: 40c887ef662f7679d803695d4193268c2c177c6d4e13b43b56cc519322522a1608b4bfc4999f6355be778ca7a0256f0d27ab18a19b352a9da1aed66e2644dc82 + checksum: cce7173ee131364857c16f70f94155ba0e1b044cde54045fb0cf62ad138f8d8ef093f5aba7c7617a9aa0545b3ee3930aec2e09f645daec015696968338963013 languageName: node linkType: hard -"@docusaurus/cssnano-preset@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/cssnano-preset@npm:2.4.1" +"@docusaurus/cssnano-preset@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/cssnano-preset@npm:2.4.3" dependencies: cssnano-preset-advanced: ^5.3.8 postcss: ^8.4.14 postcss-sort-media-queries: ^4.2.1 tslib: ^2.4.0 - checksum: d498345981288af2dcb8650bed3c3361cfe336541a8bda65743fbe8ee5746e81e723ba086e2e6249c3b283f4bc50b5c81cff15b0406969cd610bed345b3804ac + checksum: f4a4c60b075c23541da90e00ae26af2e7eaadf20d783b37b9110a5e34599e4e91947425e33bad58ba71abee81c85cca99f5d7d76575f53fbaf73617b55e39c62 languageName: node linkType: hard -"@docusaurus/logger@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/logger@npm:2.4.1" +"@docusaurus/logger@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/logger@npm:2.4.3" dependencies: chalk: ^4.1.2 tslib: ^2.4.0 - checksum: be81840f2df477ab633d8ced6fd3a512582e764a48d66b1c12bb20b5d4c717f349e254e33b00b9b53381dbdb24a3e3d0ca9b19511366244b3620fa19cc4c69dc + checksum: f026a8233aa317f16ce5b25c6785a431f319c52fc07a1b9e26f4b3df2197974e75830a16b6140314f8f4ef02dc19242106ec2ae1599740b26d516cc34c56102f languageName: node linkType: hard -"@docusaurus/mdx-loader@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/mdx-loader@npm:2.4.1" +"@docusaurus/mdx-loader@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/mdx-loader@npm:2.4.3" dependencies: "@babel/parser": ^7.18.8 "@babel/traverse": ^7.18.8 - "@docusaurus/logger": 2.4.1 - "@docusaurus/utils": 2.4.1 + "@docusaurus/logger": 2.4.3 + "@docusaurus/utils": 2.4.3 "@mdx-js/mdx": ^1.6.22 escape-html: ^1.0.3 file-loader: ^6.2.0 @@ -3743,16 +3780,16 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: cf36bbde228a058869dfd770a85f130035a54e563b957a3cfc3191d06efdcfc272bb51b51e6225a0246b233e5d7d0ca1cb4df4b700b837aa72bbb0c9f6f6f5bd + checksum: 5a774f7ea5f484e888b2bd1bf8b182279e3788afec779eb8920cf468b92ab8d83a1ae8be51925074241a4d1a38d989cfb366d2baf0f67ed6f063342395a7ca8e languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/module-type-aliases@npm:2.4.1" +"@docusaurus/module-type-aliases@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/module-type-aliases@npm:2.4.3" dependencies: "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/types": 2.4.1 + "@docusaurus/types": 2.4.3 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -3762,21 +3799,21 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 9e328c7bc5cd40b399550995edbeeea5ce88be7eb75f4c49499e8fd05a8bbabf180dce4d1cae0185721629fc6e0f2e8fc513e3ce846080f9771f7a9bc1c45ba8 + checksum: 22ce1a6a20acc35cdd2ec57e55f29e65dbe0fb3a46aaa8c033ec78bf04cd3087f0523c816c744ed311095512dd686c83e0a8619cc1a2a937c27cd54527739c38 languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-content-blog@npm:2.4.1" - dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/logger": 2.4.1 - "@docusaurus/mdx-loader": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-common": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 +"@docusaurus/plugin-content-blog@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-content-blog@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 fs-extra: ^10.1.0 @@ -3789,21 +3826,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 9d4e543b70d032d7edf0c986c45f36a088db76dc737a24374dcb877177b889fb0a5ed7b0a9c9ebb912523ef23ba26787d0fff59d9032b3e8075bdde9c072956a + checksum: 9fd41331c609b9488eea363e617e3763a814c75f83eb1b858cef402a0f5b96f67a342e25ff8c333489e550eb4d379eae09a88b986a97c25170fe203662e2f1ae languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-content-docs@npm:2.4.1" - dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/logger": 2.4.1 - "@docusaurus/mdx-loader": 2.4.1 - "@docusaurus/module-type-aliases": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 +"@docusaurus/plugin-content-docs@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-content-docs@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/module-type-aliases": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 "@types/react-router-config": ^5.0.6 combine-promises: ^1.1.0 fs-extra: ^10.1.0 @@ -3816,132 +3853,132 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 028eda178dc81a74c25fd2efddb47e44451af2b268b13d99ef2b60cf13da1443f3bce884fd4a8a7ae92fed8ef747308309074f9524753fd80a40b5252a237e37 + checksum: bc01201f64721131eb84f264e51c7497b8034d2a3d99d762169f5dc456c3d8882acfa01fdbaa8fdc6e2e220479b36e0c9e8e17397bf887884589535bdeaeb4bb languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-content-pages@npm:2.4.1" +"@docusaurus/plugin-content-pages@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-content-pages@npm:2.4.3" dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/mdx-loader": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 fs-extra: ^10.1.0 tslib: ^2.4.0 webpack: ^5.73.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 6af4eb7c064ed90158ad584eb64593473940b1880034a65fbcfde36116d6702b882bb9b0340141a5a48e67b0f84c03b8202b94171f5924d9f0c279cb68959a47 + checksum: 00439c2e1a1f345cd549739db13a3610b6d9f7ffa6cf7507ad6ac1f3c8d24041947acc2a446be7edf1a613cf354a50d1133aa28ddf64a0eff6ed8a31bf1a542f languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-debug@npm:2.4.1" +"@docusaurus/plugin-debug@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-debug@npm:2.4.3" dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 fs-extra: ^10.1.0 react-json-view: ^1.21.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 0be51e9a881383ed76b6e8f369ca6f7754a4f6bd59093c6d28d955b9422a25e868f24b534eb08ba84a5524ae742edd4a052813767b2ea1e8767914dceffc19b8 + checksum: 88955828b72e463e04501cc6bedf802208e377ae0f4d72735625bcbb47918afc4f2588355c6914064cfdbe4945d3da6473ce76319aa1f66dd975b3b43c4c39b0 languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-google-analytics@npm:2.4.1" +"@docusaurus/plugin-google-analytics@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-google-analytics@npm:2.4.3" dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 9e754c0bc7779867af07cd77de36f5b491671a96fba5e3517458803465c24773357eb2f1400c41c80e69524cb2c7e9e353262335051aa54192eeae9d9eb055cb + checksum: 6e30de6b5c479493614a5552a295f07ffb9c83f3740a68c7d4dbac378b8288da7430f26cdc246d763855c6084ad86a6f87286e6c8b40f4817794bb1a04e109ea languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-google-gtag@npm:2.4.1" +"@docusaurus/plugin-google-gtag@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-google-gtag@npm:2.4.3" dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: ed529f2100599401e1c2aa772dca7c60fdb1990e44af3a9e476e1922f1370ef0dd0b5e6442f846bd942b74af63f3163ac85f1eefe1e85660b61ee60f2044c463 + checksum: 4aaac4d262b3bb7fc3f16620c5329b90db92bf28361ced54f2945fc0e4669483e2f36b076332e0ee9d11b6233cd2c81ca35c953119bad42171e62571c1692d6a languageName: node linkType: hard -"@docusaurus/plugin-google-tag-manager@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-google-tag-manager@npm:2.4.1" +"@docusaurus/plugin-google-tag-manager@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-google-tag-manager@npm:2.4.3" dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: c5c6fce9c9eeae7cbeb277b9765a67d5c4403a3e04f634aadac6d4ba9901739a547d4ea023c83a76cfece2fdb2d175851acaa69abb2f190401b612adeab5524d + checksum: c3af89b4d41fab463d853cbfbe8f43d384f702dd09fd914fffcca01fdf94c282d1b98d762c9142fe21f6471f5dd643679e8d11344c95fdf6657aff0618c3c7a5 languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/plugin-sitemap@npm:2.4.1" - dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/logger": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-common": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 +"@docusaurus/plugin-sitemap@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/plugin-sitemap@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 fs-extra: ^10.1.0 sitemap: ^7.1.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: aa6728278017c047b4ed1456e349b1a267d85b4bb0c422bb63e59fc28ccb0e286dc66918f44f6ade660e550b047e2b14796c54c96fde6eb69395770cf39cf306 + checksum: cf96b9f0e32cefa58e37a4bc2f0a112ea657f06faf47b780ec2ba39d5e2daca6486a73f3b376c56ad3bb42f3f0c3f70a783f1ce1964b74e2ba273e6f439e439b languageName: node linkType: hard -"@docusaurus/preset-classic@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/preset-classic@npm:2.4.1" - dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/plugin-content-blog": 2.4.1 - "@docusaurus/plugin-content-docs": 2.4.1 - "@docusaurus/plugin-content-pages": 2.4.1 - "@docusaurus/plugin-debug": 2.4.1 - "@docusaurus/plugin-google-analytics": 2.4.1 - "@docusaurus/plugin-google-gtag": 2.4.1 - "@docusaurus/plugin-google-tag-manager": 2.4.1 - "@docusaurus/plugin-sitemap": 2.4.1 - "@docusaurus/theme-classic": 2.4.1 - "@docusaurus/theme-common": 2.4.1 - "@docusaurus/theme-search-algolia": 2.4.1 - "@docusaurus/types": 2.4.1 +"@docusaurus/preset-classic@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/preset-classic@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/plugin-content-blog": 2.4.3 + "@docusaurus/plugin-content-docs": 2.4.3 + "@docusaurus/plugin-content-pages": 2.4.3 + "@docusaurus/plugin-debug": 2.4.3 + "@docusaurus/plugin-google-analytics": 2.4.3 + "@docusaurus/plugin-google-gtag": 2.4.3 + "@docusaurus/plugin-google-tag-manager": 2.4.3 + "@docusaurus/plugin-sitemap": 2.4.3 + "@docusaurus/theme-classic": 2.4.3 + "@docusaurus/theme-common": 2.4.3 + "@docusaurus/theme-search-algolia": 2.4.3 + "@docusaurus/types": 2.4.3 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: bad7f237ac03a9bc6206cb7a5d077d85d5a6316d34ff089c487ce92b8f6103ef22b04f35d637bdc31dddabd97d5babb1817852b9b97db7c33f3d4c7f33cb149d + checksum: a321badc44696adf4ab2d4a5d6c93f595e8c17988aec9609d325928a1d60f5e0205b23fe849b28ddaed24f7935829e86c402f6b761d6e65db4224270b9dd443c languageName: node linkType: hard @@ -3957,22 +3994,22 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/theme-classic@npm:2.4.1" - dependencies: - "@docusaurus/core": 2.4.1 - "@docusaurus/mdx-loader": 2.4.1 - "@docusaurus/module-type-aliases": 2.4.1 - "@docusaurus/plugin-content-blog": 2.4.1 - "@docusaurus/plugin-content-docs": 2.4.1 - "@docusaurus/plugin-content-pages": 2.4.1 - "@docusaurus/theme-common": 2.4.1 - "@docusaurus/theme-translations": 2.4.1 - "@docusaurus/types": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-common": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 +"@docusaurus/theme-classic@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/theme-classic@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/module-type-aliases": 2.4.3 + "@docusaurus/plugin-content-blog": 2.4.3 + "@docusaurus/plugin-content-docs": 2.4.3 + "@docusaurus/plugin-content-pages": 2.4.3 + "@docusaurus/theme-common": 2.4.3 + "@docusaurus/theme-translations": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 "@mdx-js/react": ^1.6.22 clsx: ^1.2.1 copy-text-to-clipboard: ^3.0.1 @@ -3989,21 +4026,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 058875d4c60f77f86b5d679b1ef99ed06101411f003d2d65fa4fe5ae6fbe5e5e6a291616268a18a29fdd84f0853cc4219a2c1801663b75f27c664b3ace7d009e + checksum: 215b7fa416f40ce68773265a168af47fa770583ebe33ec7b34c7e082dfe7c79252b589a6b26532cb0ab7dd089611a9cd0e20c94df097be320a227b98e3b3fbb8 languageName: node linkType: hard -"@docusaurus/theme-common@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/theme-common@npm:2.4.1" - dependencies: - "@docusaurus/mdx-loader": 2.4.1 - "@docusaurus/module-type-aliases": 2.4.1 - "@docusaurus/plugin-content-blog": 2.4.1 - "@docusaurus/plugin-content-docs": 2.4.1 - "@docusaurus/plugin-content-pages": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-common": 2.4.1 +"@docusaurus/theme-common@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/theme-common@npm:2.4.3" + dependencies: + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/module-type-aliases": 2.4.3 + "@docusaurus/plugin-content-blog": 2.4.3 + "@docusaurus/plugin-content-docs": 2.4.3 + "@docusaurus/plugin-content-pages": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -4016,22 +4053,22 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 206db83caab59eadc5b8e5394d46b64ec8695bd20d4a3defe111c28094faf6de92481c3bb4e54c159a519bc782759031b121e17d7e0175d873a843f36630c539 + checksum: 76817f548705542124d708c804e724674ec9bf996a5cb2a5c9a2919416367567cca4a3fa6055589990c339f6e1fb9d3944e25ed30b79fabe191db00d6ef986ca languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/theme-search-algolia@npm:2.4.1" +"@docusaurus/theme-search-algolia@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/theme-search-algolia@npm:2.4.3" dependencies: "@docsearch/react": ^3.1.1 - "@docusaurus/core": 2.4.1 - "@docusaurus/logger": 2.4.1 - "@docusaurus/plugin-content-docs": 2.4.1 - "@docusaurus/theme-common": 2.4.1 - "@docusaurus/theme-translations": 2.4.1 - "@docusaurus/utils": 2.4.1 - "@docusaurus/utils-validation": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/plugin-content-docs": 2.4.3 + "@docusaurus/theme-common": 2.4.3 + "@docusaurus/theme-translations": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 algoliasearch: ^4.13.1 algoliasearch-helper: ^3.10.0 clsx: ^1.2.1 @@ -4043,23 +4080,23 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 00016804462e3ca961de96f477c397bf68bbfa7c641cfb95e76492ec00f2e0f8f5b19623cd6ad0fda31ad08aa29fa1a74185d9bd34f61437e7f36f711064f3ba + checksum: 665d244c25bff21dd45c983c9b85f9827d2dd58945b802d645370b5e7092820532faf488c0bc0ce88e8fc0088c7f56eb9abb96589cf3857372c1b61bba6cbed7 languageName: node linkType: hard -"@docusaurus/theme-translations@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/theme-translations@npm:2.4.1" +"@docusaurus/theme-translations@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/theme-translations@npm:2.4.3" dependencies: fs-extra: ^10.1.0 tslib: ^2.4.0 - checksum: cf21cd01db6426ccc29360fe9caca39e61ee5efde3796539e8292e212c25727227970f935050f294f0ab475f201720e32a1d09a7e40f2b08f56f69282f660da8 + checksum: 8424583a130b0d32b6adf578dc5daeefaad199019c8a6a23fbd67577209be64923cde59d423ea9d41d6e7cfc2318e7fa6a17a665e8ae1c871ce0880525f9b8fd languageName: node linkType: hard -"@docusaurus/types@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/types@npm:2.4.1" +"@docusaurus/types@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/types@npm:2.4.3" dependencies: "@types/history": ^4.7.11 "@types/react": "*" @@ -4072,13 +4109,13 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: d44e91c9153802a5c63a0bd91e56654f901df837ac7b380dff8f165991728e88d29efa7c64c6522d0afdf8ec845613aff5867badb717d29b691392712f655936 + checksum: c123c45630e885b588f808baa06a97f8408a3381906f65cb92ae75732aedfca6ab2cada94f969c08e043b885b95298616440326259b789010e0986cbcd7a960b languageName: node linkType: hard -"@docusaurus/utils-common@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/utils-common@npm:2.4.1" +"@docusaurus/utils-common@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/utils-common@npm:2.4.3" dependencies: tslib: ^2.4.0 peerDependencies: @@ -4086,28 +4123,28 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 475f05b94a879d9078564dbb081d91a953356f54d0a4384a8711281a62851b58d99df9b45664a30e40ac37733772cedd53a253d34a07fbd5b36bcce46ab200c8 + checksum: 1ae315d8d8ce7a0163a698ffdca55b734d21f336512138c128bc0fa2a8d224edbaad0c8dbd7a3de2e8ef734dc2656c505d09066dee4fc84819d153593abb8984 languageName: node linkType: hard -"@docusaurus/utils-validation@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/utils-validation@npm:2.4.1" +"@docusaurus/utils-validation@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/utils-validation@npm:2.4.3" dependencies: - "@docusaurus/logger": 2.4.1 - "@docusaurus/utils": 2.4.1 + "@docusaurus/logger": 2.4.3 + "@docusaurus/utils": 2.4.3 joi: ^17.6.0 js-yaml: ^4.1.0 tslib: ^2.4.0 - checksum: 44dc482770ea3932e68e58c0bb9503e1b3c73ce28565c438b0d68a7427ee91760ca84a5e150dfc4e04497e072fe4394050dd2af4c4ff43a227b1464e89d705a0 + checksum: d3472b3f7a0a029c2cef1f00bc9db403d5f7e74e2091eccbc45d06f5776a84fd73bd1a18cf3a8a3cc0348ce49f753a1300deac670c2a82c56070cc40ca9df06e languageName: node linkType: hard -"@docusaurus/utils@npm:2.4.1": - version: 2.4.1 - resolution: "@docusaurus/utils@npm:2.4.1" +"@docusaurus/utils@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/utils@npm:2.4.3" dependencies: - "@docusaurus/logger": 2.4.1 + "@docusaurus/logger": 2.4.3 "@svgr/webpack": ^6.2.1 escape-string-regexp: ^4.0.0 file-loader: ^6.2.0 @@ -4128,7 +4165,7 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 4c7e49cabe6650b027c0f698344532fb81c8aaf912f17a287fad986e008ce7c6d34d372b44974488ce160ae43ef6aad4ac7b2790bc3fe2ab05ef5fa7b9506ce9 + checksum: dd1aa7688d1a4b2775e13a91d528608ceab33c57a921404d9a989867c31c8ef17fe3892e4f5680dfb4a783da7b9973e2077e907ff4ac172927433e606e8fa9b9 languageName: node linkType: hard @@ -4174,10 +4211,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.48.0": - version: 8.48.0 - resolution: "@eslint/js@npm:8.48.0" - checksum: b2755f9c0ee810c886eba3c50dcacb184ba5a5cd1cbc01988ee506ad7340653cae0bd55f1d95c64b56dfc6d25c2caa7825335ffd2c50165bae9996fe0f396851 +"@eslint/js@npm:8.50.0": + version: 8.50.0 + resolution: "@eslint/js@npm:8.50.0" + checksum: 302478f2acaaa7228729ec6a04f56641590185e1d8cd1c836a6db8a6b8009f80a57349341be9fbb9aa1721a7a569d1be3ffc598a33300d22816f11832095386c languageName: node linkType: hard @@ -4240,15 +4277,16 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:10.0.1": - version: 10.0.1 - resolution: "@graphql-tools/utils@npm:10.0.1" +"@graphql-tools/utils@npm:10.0.6": + version: 10.0.6 + resolution: "@graphql-tools/utils@npm:10.0.6" dependencies: "@graphql-typed-document-node/core": ^3.1.1 + dset: ^3.1.2 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: fc6412b6914bcae87f825e1cf5998f3c0e54470d00730054b2e079a4e2f19eeb52626294eb62d684f82ff2ae59c6e1c1854664a0e13de9becf40aa857c437e3d + checksum: 1eae5ff2056930edf1b5a6aa38a2b28c2b3da0260d4d6babbd3fb25f8638b04c7ea8a481b3e1d4d965d81f2123b577646afb0fe20da87e76362d6f7f099e4be9 languageName: node linkType: hard @@ -4302,14 +4340,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.10": - version: 0.11.10 - resolution: "@humanwhocodes/config-array@npm:0.11.10" +"@humanwhocodes/config-array@npm:^0.11.11": + version: 0.11.11 + resolution: "@humanwhocodes/config-array@npm:0.11.11" dependencies: "@humanwhocodes/object-schema": ^1.2.1 debug: ^4.1.1 minimatch: ^3.0.5 - checksum: 1b1302e2403d0e35bc43e66d67a2b36b0ad1119efc704b5faff68c41f791a052355b010fb2d27ef022670f550de24cd6d08d5ecf0821c16326b7dcd0ee5d5d8a + checksum: db84507375ab77b8ffdd24f498a5b49ad6b64391d30dd2ac56885501d03964d29637e05b1ed5aefa09d57ac667e28028bc22d2da872bfcd619652fbdb5f4ca19 languageName: node linkType: hard @@ -4382,28 +4420,28 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/console@npm:29.6.4" +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 - jest-message-util: ^29.6.3 - jest-util: ^29.6.3 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 slash: ^3.0.0 - checksum: 1caf061a39266b86e96ca13358401839e4d930742cbaa9e87e79d7ce170a83195e52e5b2d22eb5aa9a949219b61a163a81e337ec98b8323d88d79853051df96c + checksum: 0e3624e32c5a8e7361e889db70b170876401b7d70f509a2538c31d5cd50deb0c1ae4b92dc63fe18a0902e0a48c590c21d53787a0df41a52b34fa7cab96c384d6 languageName: node linkType: hard -"@jest/core@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/core@npm:29.6.4" +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" dependencies: - "@jest/console": ^29.6.4 - "@jest/reporters": ^29.6.4 - "@jest/test-result": ^29.6.4 - "@jest/transform": ^29.6.4 + "@jest/console": ^29.7.0 + "@jest/reporters": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" ansi-escapes: ^4.2.1 @@ -4411,21 +4449,21 @@ __metadata: ci-info: ^3.2.0 exit: ^0.1.2 graceful-fs: ^4.2.9 - jest-changed-files: ^29.6.3 - jest-config: ^29.6.4 - jest-haste-map: ^29.6.4 - jest-message-util: ^29.6.3 + jest-changed-files: ^29.7.0 + jest-config: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-message-util: ^29.7.0 jest-regex-util: ^29.6.3 - jest-resolve: ^29.6.4 - jest-resolve-dependencies: ^29.6.4 - jest-runner: ^29.6.4 - jest-runtime: ^29.6.4 - jest-snapshot: ^29.6.4 - jest-util: ^29.6.3 - jest-validate: ^29.6.3 - jest-watcher: ^29.6.4 + jest-resolve: ^29.7.0 + jest-resolve-dependencies: ^29.7.0 + jest-runner: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + jest-watcher: ^29.7.0 micromatch: ^4.0.4 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 slash: ^3.0.0 strip-ansi: ^6.0.0 peerDependencies: @@ -4433,7 +4471,7 @@ __metadata: peerDependenciesMeta: node-notifier: optional: true - checksum: 0f36532c909775814cb7d4310d61881beaefdec6229ef0b7493c6191dfca20ae5222120846ea5ef8cdeaa8cef265aae9cea8989dcab572d8daea9afd14247c7a + checksum: af759c9781cfc914553320446ce4e47775ae42779e73621c438feb1e4231a5d4862f84b1d8565926f2d1aab29b3ec3dcfdc84db28608bdf5f29867124ebcfc0d languageName: node linkType: hard @@ -4449,15 +4487,15 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/environment@npm:29.6.4" +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" dependencies: - "@jest/fake-timers": ^29.6.4 + "@jest/fake-timers": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" - jest-mock: ^29.6.3 - checksum: 810d8f1fc26d293acfc44927bcb78adc58ed4ea580a64c8d94aa6c67239dcb149186bf25b94ff28b79de15253e0c877ad8d330feac205f185f3517593168510c + jest-mock: ^29.7.0 + checksum: 6fb398143b2543d4b9b8d1c6dbce83fa5247f84f550330604be744e24c2bd2178bb893657d62d1b97cf2f24baf85c450223f8237cccb71192c36a38ea2272934 languageName: node linkType: hard @@ -4470,12 +4508,12 @@ __metadata: languageName: node linkType: hard -"@jest/expect-utils@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/expect-utils@npm:29.6.4" +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" dependencies: jest-get-type: ^29.6.3 - checksum: a17059e02a4c0fca98e2abb7e9e58c70df3cd3d4ebcc6a960cb57c571726f7bd738c6cd008a9bf99770b77e92f7e21c75fe1f9ceec9b7a7710010f9340bb28ad + checksum: 75eb177f3d00b6331bcaa057e07c0ccb0733a1d0a1943e1d8db346779039cb7f103789f16e502f888a3096fb58c2300c38d1f3748b36a7fa762eb6f6d1b160ed languageName: node linkType: hard @@ -4489,13 +4527,13 @@ __metadata: languageName: node linkType: hard -"@jest/expect@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/expect@npm:29.6.4" +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" dependencies: - expect: ^29.6.4 - jest-snapshot: ^29.6.4 - checksum: e9d7306a96e2f9f9f7a0d93d41850cbad987ebda951a5d9a63d3f5fb61da4c1e41adb54af7f7222e4a185454ecb17ddc77845e18001ee28ac114f7a7fe9e671d + expect: ^29.7.0 + jest-snapshot: ^29.7.0 + checksum: a01cb85fd9401bab3370618f4b9013b90c93536562222d920e702a0b575d239d74cecfe98010aaec7ad464f67cf534a353d92d181646a4b792acaa7e912ae55e languageName: node linkType: hard @@ -4513,17 +4551,17 @@ __metadata: languageName: node linkType: hard -"@jest/fake-timers@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/fake-timers@npm:29.6.4" +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@sinonjs/fake-timers": ^10.0.2 "@types/node": "*" - jest-message-util: ^29.6.3 - jest-mock: ^29.6.3 - jest-util: ^29.6.3 - checksum: 3f06d1090cbaaf781920fe59b10509ad86b587c401818a066ee1550101c6203e0718f0f83bbd2afa8bdf7b43eb280f89fb9f8c98886094e53ccabe5e64de9be1 + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: caf2bbd11f71c9241b458d1b5a66cbe95debc5a15d96442444b5d5c7ba774f523c76627c6931cca5e10e76f0d08761f6f1f01a608898f4751a0eee54fc3d8d00 languageName: node linkType: hard @@ -4539,15 +4577,15 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/globals@npm:29.6.4" +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" dependencies: - "@jest/environment": ^29.6.4 - "@jest/expect": ^29.6.4 + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 "@jest/types": ^29.6.3 - jest-mock: ^29.6.3 - checksum: a41b18871a248151264668a38b13cb305f03db112bfd89ec44e858af0e79066e0b03d6b68c8baf1ec6c578be6fdb87519389c83438608b91471d17a5724858e0 + jest-mock: ^29.7.0 + checksum: 97dbb9459135693ad3a422e65ca1c250f03d82b2a77f6207e7fa0edd2c9d2015fbe4346f3dc9ebff1678b9d8da74754d4d440b7837497f8927059c0642a22123 languageName: node linkType: hard @@ -4588,14 +4626,14 @@ __metadata: languageName: node linkType: hard -"@jest/reporters@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/reporters@npm:29.6.4" +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" dependencies: "@bcoe/v8-coverage": ^0.2.3 - "@jest/console": ^29.6.4 - "@jest/test-result": ^29.6.4 - "@jest/transform": ^29.6.4 + "@jest/console": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 "@jest/types": ^29.6.3 "@jridgewell/trace-mapping": ^0.3.18 "@types/node": "*" @@ -4609,9 +4647,9 @@ __metadata: istanbul-lib-report: ^3.0.0 istanbul-lib-source-maps: ^4.0.0 istanbul-reports: ^3.1.3 - jest-message-util: ^29.6.3 - jest-util: ^29.6.3 - jest-worker: ^29.6.4 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 slash: ^3.0.0 string-length: ^4.0.1 strip-ansi: ^6.0.0 @@ -4621,7 +4659,7 @@ __metadata: peerDependenciesMeta: node-notifier: optional: true - checksum: 9ee0db497f3a826f535d3af0575ceb67984f9708bc6386450359517c212c67218ae98b8ea93ab05df2f920aed9c4166ef64209d66a09b7e30fc0077c91347ad0 + checksum: 7eadabd62cc344f629024b8a268ecc8367dba756152b761bdcb7b7e570a3864fc51b2a9810cd310d85e0a0173ef002ba4528d5ea0329fbf66ee2a3ada9c40455 languageName: node linkType: hard @@ -4677,15 +4715,15 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/test-result@npm:29.6.4" +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" dependencies: - "@jest/console": ^29.6.4 + "@jest/console": ^29.7.0 "@jest/types": ^29.6.3 "@types/istanbul-lib-coverage": ^2.0.0 collect-v8-coverage: ^1.0.0 - checksum: a13c82d29038e80059191a1a443240678c6934ea832fdabaec12b3ece397b6303022a064494a6bbd167a024f04e6b4d9ace1001300927ff70405ec9d854f1193 + checksum: 67b6317d526e335212e5da0e768e3b8ab8a53df110361b80761353ad23b6aea4432b7c5665bdeb87658ea373b90fb1afe02ed3611ef6c858c7fba377505057fa languageName: node linkType: hard @@ -4701,15 +4739,15 @@ __metadata: languageName: node linkType: hard -"@jest/test-sequencer@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/test-sequencer@npm:29.6.4" +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" dependencies: - "@jest/test-result": ^29.6.4 + "@jest/test-result": ^29.7.0 graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.4 + jest-haste-map: ^29.7.0 slash: ^3.0.0 - checksum: 517fc66b74a87431a8a1429e4505d85bd09c11f2ba835e46c07c79911fbee23b89c01ec444c7c1d12d1b36f9eba60fcbbccc8e1bc1ae54a1a8b03b5f530ff81b + checksum: 73f43599017946be85c0b6357993b038f875b796e2f0950487a82f4ebcb115fa12131932dd9904026b4ad8be131fe6e28bd8d0aa93b1563705185f9804bff8bd languageName: node linkType: hard @@ -4736,9 +4774,9 @@ __metadata: languageName: node linkType: hard -"@jest/transform@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/transform@npm:29.6.4" +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" dependencies: "@babel/core": ^7.11.6 "@jest/types": ^29.6.3 @@ -4748,14 +4786,14 @@ __metadata: convert-source-map: ^2.0.0 fast-json-stable-stringify: ^2.1.0 graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.4 + jest-haste-map: ^29.7.0 jest-regex-util: ^29.6.3 - jest-util: ^29.6.3 + jest-util: ^29.7.0 micromatch: ^4.0.4 pirates: ^4.0.4 slash: ^3.0.0 write-file-atomic: ^4.0.2 - checksum: 0341a200a0bb926fc67ab9aede91c7b4009458206495e92057e72a115c55da5fed117457e68c6ea821e24c58b55da75c6a7b0f272ed63c2693db583d689a3383 + checksum: 0f8ac9f413903b3cb6d240102db848f2a354f63971ab885833799a9964999dd51c388162106a807f810071f864302cdd8e3f0c241c29ce02d85a36f18f3f40ab languageName: node linkType: hard @@ -5004,14 +5042,14 @@ __metadata: languageName: node linkType: hard -"@nestjs/apollo@npm:^12.0.7": - version: 12.0.7 - resolution: "@nestjs/apollo@npm:12.0.7" +"@nestjs/apollo@npm:^12.0.9": + version: 12.0.9 + resolution: "@nestjs/apollo@npm:12.0.9" dependencies: "@apollo/server-plugin-landing-page-graphql-playground": 4.0.0 iterall: 1.3.0 lodash.omit: 4.5.0 - tslib: 2.6.0 + tslib: 2.6.2 peerDependencies: "@apollo/gateway": ^2.0.0 "@apollo/server": ^4.3.2 @@ -5028,17 +5066,17 @@ __metadata: optional: true "@as-integrations/fastify": optional: true - checksum: fd33cd07673756fc7f9097981ab38a7541a73400effff13f9bce6b8996f3bf3893ad9d101e5b5d4eadbdc8d9a515390bb5c61409a6adf79c82e1ade96259edd6 + checksum: 6c22eb5f3dc3dab0574f142caa9b8dd0592236baf117e6c06d88cfd0f0a2e43bc2df331429516947f16ba75d20931ed1fd0e6677a39d30128692b90827fa153f languageName: node linkType: hard -"@nestjs/cli@npm:10.1.17": - version: 10.1.17 - resolution: "@nestjs/cli@npm:10.1.17" +"@nestjs/cli@npm:10.1.18": + version: 10.1.18 + resolution: "@nestjs/cli@npm:10.1.18" dependencies: - "@angular-devkit/core": 16.2.0 - "@angular-devkit/schematics": 16.2.0 - "@angular-devkit/schematics-cli": 16.2.0 + "@angular-devkit/core": 16.2.3 + "@angular-devkit/schematics": 16.2.3 + "@angular-devkit/schematics-cli": 16.2.3 "@nestjs/schematics": ^10.0.1 chalk: 4.1.2 chokidar: 3.5.3 @@ -5055,7 +5093,7 @@ __metadata: tree-kill: 1.2.2 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.1.0 - typescript: 5.1.6 + typescript: 5.2.2 webpack: 5.88.2 webpack-node-externals: 3.0.0 peerDependencies: @@ -5068,13 +5106,13 @@ __metadata: optional: true bin: nest: bin/nest.js - checksum: c253f5958d8d167fd3298e090912ad025fa9ad80687713e89a7b1b229162ab91e6a923781e2f4c8b4aeeec0ca8ab55dbeccc263b02075be67ea40e830fe268a7 + checksum: 58db21d772fe1a62af789ad571cdbbf073e1d92ef32b869b6685ed294d72e2218e7b5d49a6173d15f13871738eb3ed8b75dce85e82236be23ec96c133ba1668d languageName: node linkType: hard -"@nestjs/common@npm:10.2.3": - version: 10.2.3 - resolution: "@nestjs/common@npm:10.2.3" +"@nestjs/common@npm:10.2.7": + version: 10.2.7 + resolution: "@nestjs/common@npm:10.2.7" dependencies: iterare: 1.2.1 tslib: 2.6.2 @@ -5089,13 +5127,13 @@ __metadata: optional: true class-validator: optional: true - checksum: 047db662763c4cc7bb1c3b4be68d9ac0e0b80ea7bdaabee7d205cb8e48513b3ca63f883b1055c729454432813bfe5cd115a8da4a823ec3f550eb1505c573e7dc + checksum: b0a498eae3bc5c84659064830eab57583caaddef15ed1137768d73e986dabe2e1a04f61d8c0181b1c538e8c5f4ea3342a1f342e7a19a59e46d306ea3b53f3342 languageName: node linkType: hard -"@nestjs/core@npm:10.2.3": - version: 10.2.3 - resolution: "@nestjs/core@npm:10.2.3" +"@nestjs/core@npm:10.2.7": + version: 10.2.7 + resolution: "@nestjs/core@npm:10.2.7" dependencies: "@nuxtjs/opencollective": 0.3.2 fast-safe-stringify: 2.1.1 @@ -5117,26 +5155,26 @@ __metadata: optional: true "@nestjs/websockets": optional: true - checksum: cb4cb817ce4fe13410c02984a6fda81d09f6cfd19107ee13db775229189ab57bba12fcdd2d2325d467e8ac6fd6cf4f7c8f12a86a72798b62a2f767ce9f9065f7 + checksum: 7e180d9eb014bb5867ef9476e414ab497a145f3966871155eac08da6b6a75709cae1bbf43bd74bc855316f565396457ccef224ad173a5c5614e4032c59cb9e3c languageName: node linkType: hard -"@nestjs/graphql@npm:^12.0.8": - version: 12.0.8 - resolution: "@nestjs/graphql@npm:12.0.8" +"@nestjs/graphql@npm:^12.0.9": + version: 12.0.9 + resolution: "@nestjs/graphql@npm:12.0.9" dependencies: "@graphql-tools/merge": 9.0.0 "@graphql-tools/schema": 10.0.0 - "@graphql-tools/utils": 10.0.1 + "@graphql-tools/utils": 10.0.6 "@nestjs/mapped-types": 2.0.2 chokidar: 3.5.3 - fast-glob: 3.2.12 + fast-glob: 3.3.1 graphql-tag: 2.12.6 graphql-ws: 5.14.0 lodash: 4.17.21 normalize-path: 3.0.0 subscriptions-transport-ws: 0.11.0 - tslib: 2.6.0 + tslib: 2.6.2 uuid: 9.0.0 ws: 8.13.0 peerDependencies: @@ -5157,19 +5195,19 @@ __metadata: optional: true ts-morph: optional: true - checksum: 70d21025cba4d936c3b6097467085d8835be8550eeb7fdc586492254a56437b23da836faba3e56b69f7be31b0dc8078706eaa91081a7618e3b7602217a7b9692 + checksum: 617373e36065eaf55d313bed4d24fb10909da3c796d52001e9bc6ed23605805627c0b9260a37d33dd5c4f9d65a2083d0972df3630ebee32d49c665e07c4fac43 languageName: node linkType: hard -"@nestjs/jwt@npm:10.1.0": - version: 10.1.0 - resolution: "@nestjs/jwt@npm:10.1.0" +"@nestjs/jwt@npm:10.1.1": + version: 10.1.1 + resolution: "@nestjs/jwt@npm:10.1.1" dependencies: "@types/jsonwebtoken": 9.0.2 jsonwebtoken: 9.0.0 peerDependencies: "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0 - checksum: c172b11ce154f5f98b27a3b3a70a0dadbcad97624e201ccb487b6cf05a8d42edd9ecb8a442e375b974a7c889889f022ab9f684e4ec1019c91b43a8fe4d2d9ea8 + checksum: d679ce4e0fac61d1e23c698a7687946f065e8d75ae5897c81252500fe1ca91b4b918c7e0272369da1566026fce2128d43da452b94eb6694a79abe8735d25cf24 languageName: node linkType: hard @@ -5203,19 +5241,19 @@ __metadata: languageName: node linkType: hard -"@nestjs/passport@npm:10.0.1": - version: 10.0.1 - resolution: "@nestjs/passport@npm:10.0.1" +"@nestjs/passport@npm:10.0.2": + version: 10.0.2 + resolution: "@nestjs/passport@npm:10.0.2" peerDependencies: "@nestjs/common": ^8.0.0 || ^9.0.0 || ^10.0.0 passport: ^0.4.0 || ^0.5.0 || ^0.6.0 - checksum: bc7ed690ce8bb99839307d626ea8c8cf29d6fa8967f5e42e45fb3e8bc865f3973695646a0a963ef54c609685a0674b52184f1c14af38f147088986eb03d74b9d + checksum: d9d0c2206cc7fc1c88da2e165d901099c971be57732d7b4f28d169ae9e4637a423d992c63660026e16cb2c43d709369496c11c4b760ba98d82ce422a672a6ee9 languageName: node linkType: hard -"@nestjs/platform-express@npm:10.2.3": - version: 10.2.3 - resolution: "@nestjs/platform-express@npm:10.2.3" +"@nestjs/platform-express@npm:10.2.7": + version: 10.2.7 + resolution: "@nestjs/platform-express@npm:10.2.7" dependencies: body-parser: 1.20.2 cors: 2.8.5 @@ -5225,7 +5263,7 @@ __metadata: peerDependencies: "@nestjs/common": ^10.0.0 "@nestjs/core": ^10.0.0 - checksum: 71e98db7b0733050460d1dc45f8ceae10db8f8783404f6f9fd4e1a08d0cbb4dc18c3b1cfaa71ebac8dcaed68284e6ad3fe30d3a0396411975c4768c07890189a + checksum: 34b912591642e86dc666c74c8b3ff10771251d9aa3f3c392525cbdff9b14f770c46e704eb2d9c9e790399a8d2416d25a6bc6fd3577e9ee22caac67acf608a32b languageName: node linkType: hard @@ -5275,9 +5313,9 @@ __metadata: languageName: node linkType: hard -"@nestjs/testing@npm:^10.2.3": - version: 10.2.3 - resolution: "@nestjs/testing@npm:10.2.3" +"@nestjs/testing@npm:^10.2.7": + version: 10.2.7 + resolution: "@nestjs/testing@npm:10.2.7" dependencies: tslib: 2.6.2 peerDependencies: @@ -5290,7 +5328,7 @@ __metadata: optional: true "@nestjs/platform-express": optional: true - checksum: 302c9cc8f4a596663182450519601e0fdc1fb6ef33c81bb885db0f565120dd808752d92457af395e4cff25b41d1549de053f698380196cbfa97ba8b12e697a34 + checksum: 598f6b206d4dad0e03ef78fd5579df07212443983dfa2c7036f56e1f865f5175ee6d44aadca873e9f75c04550b0cb375d03b9f1343db9b55f4765bdb277cf95d languageName: node linkType: hard @@ -5945,7 +5983,7 @@ __metadata: lodash.omit: ^4.5.0 lodash.pickby: ^4.6.0 tslib: ^2.6.2 - uuid: ^9.0.0 + uuid: ^9.0.1 peerDependencies: "@nestjs/common": ^9.0.0 || ^10.0.0 "@nestjs/typeorm": ^9.0.0 || ^10.0.0 @@ -6669,18 +6707,18 @@ __metadata: languageName: node linkType: hard -"@typegoose/typegoose@npm:^11.4.1": - version: 11.4.1 - resolution: "@typegoose/typegoose@npm:11.4.1" +"@typegoose/typegoose@npm:^11.5.0": + version: 11.5.0 + resolution: "@typegoose/typegoose@npm:11.5.0" dependencies: lodash: ^4.17.20 loglevel: ^1.8.1 reflect-metadata: ^0.1.13 semver: ^7.5.4 - tslib: ^2.6.0 + tslib: ^2.6.2 peerDependencies: - mongoose: ~7.4.0 - checksum: 1dee270212ab5ba859321f00098885dcf3908984a25fad2d81b4a3663b9091c6004d06b64ab912db6d651b28fa711b026de8cdce96b59abc4da1a83328085678 + mongoose: ~7.5.0 + checksum: 613c047239a5991b2654bbc9b61da0c8ac7378a044b426adad9404da16518f6c6d75c613c311f5c382c97ab95d2320557ff75ff7e735fb185cfa78a57aacf972 languageName: node linkType: hard @@ -6818,7 +6856,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:4.17.17, @types/express@npm:^4.17.13": +"@types/express@npm:*, @types/express@npm:^4.17.13": version: 4.17.17 resolution: "@types/express@npm:4.17.17" dependencies: @@ -6830,6 +6868,18 @@ __metadata: languageName: node linkType: hard +"@types/express@npm:4.17.18": + version: 4.17.18 + resolution: "@types/express@npm:4.17.18" + dependencies: + "@types/body-parser": "*" + "@types/express-serve-static-core": ^4.17.33 + "@types/qs": "*" + "@types/serve-static": "*" + checksum: 8c178da4f0edff1f006d871fbdc3f849620986ff10bad252f3dfd45b57554e26aaa28c602285df028930d5216e257a06fbaf795070f8bb42f7d87e3b689cba50 + languageName: node + linkType: hard + "@types/graceful-fs@npm:^4.1.3": version: 4.1.6 resolution: "@types/graceful-fs@npm:4.1.6" @@ -6903,13 +6953,13 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:29.5.4": - version: 29.5.4 - resolution: "@types/jest@npm:29.5.4" +"@types/jest@npm:29.5.5": + version: 29.5.5 + resolution: "@types/jest@npm:29.5.5" dependencies: expect: ^29.0.0 pretty-format: ^29.0.0 - checksum: 38ed5942f44336452efd0f071eab60aaa57cd8d46530348d0a3aa5a691dcbf1366c4ca8f6ee8364efb45b4413bfefae443e5d4f469246a472a03b21ac11cd4ed + checksum: 56e55cde9949bcc0ee2fa34ce5b7c32c2bfb20e53424aa4ff3a210859eeaaa3fdf6f42f81a3f655238039cdaaaf108b054b7a8602f394e6c52b903659338d8c6 languageName: node linkType: hard @@ -7076,17 +7126,17 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:20.4.7": - version: 20.4.7 - resolution: "@types/node@npm:20.4.7" - checksum: a40d7003f66b56220a2028179e49f950b46fa6dbf860a4a6ecbd6ba7976f05b2f0b31ced39689ec88a7d9e32d07e088c6a06d270b99d5bc13a28291ac2f30ca7 +"@types/node@npm:20.5.1": + version: 20.5.1 + resolution: "@types/node@npm:20.5.1" + checksum: 3dbe611cd67afa987102c8558ee70f848949c5dcfee5f60abc073e55c0d7b048e391bf06bb1e0dc052cb7210ca97136ac496cbaf6e89123c989de6bd125fde82 languageName: node linkType: hard -"@types/node@npm:20.5.7": - version: 20.5.7 - resolution: "@types/node@npm:20.5.7" - checksum: fc284c8e16ddc04569730d58e87eae349eb1c3dd9020cb79a1862d9d9add6f04e7367a236f3252db8db2572f90278e250f4cd43d27d264972b54394eaba1ed76 +"@types/node@npm:20.8.2": + version: 20.8.2 + resolution: "@types/node@npm:20.8.2" + checksum: 3da73e25d821bfcdb7de98589027e08bb4848e55408671c4a83ec0341e124b5313a0b20e1e4b4eff1168ea17a86f622ad73fcb04b761abd77496b9a27cbd5de5 languageName: node linkType: hard @@ -7125,25 +7175,25 @@ __metadata: languageName: node linkType: hard -"@types/passport-jwt@npm:3.0.9": - version: 3.0.9 - resolution: "@types/passport-jwt@npm:3.0.9" +"@types/passport-jwt@npm:3.0.10": + version: 3.0.10 + resolution: "@types/passport-jwt@npm:3.0.10" dependencies: "@types/express": "*" "@types/jsonwebtoken": "*" "@types/passport-strategy": "*" - checksum: 9db11d4a6cd6b652fc98bfc98463d3d0e349edafb04447178536d0c1a53ecec999be1ae07773e80d40458b6e753ebe5f54130d584ae4e29ccb83a792dc88c075 + checksum: ec1c9ca119a4f85f9c2810581715a11a405b3f536c6ee25871f12b3698a75e56554d4752fc3d8791c291efae4d5481b49c3b1ad52d368718dcd265d7ae5bbc55 languageName: node linkType: hard -"@types/passport-local@npm:1.0.35": - version: 1.0.35 - resolution: "@types/passport-local@npm:1.0.35" +"@types/passport-local@npm:1.0.36": + version: 1.0.36 + resolution: "@types/passport-local@npm:1.0.36" dependencies: "@types/express": "*" "@types/passport": "*" "@types/passport-strategy": "*" - checksum: b4ed4c40d2c7c42370c8a0ca7e18728bf3dbf2a56171d45c4f4d0281af9d91595ef9677a4f47ef10fdd5374a917b0ea64fb02d44ff4c424e48965e92915da294 + checksum: 32c9259053e659088527298c364ba2f05eac202412df89246506ad847d755107c08fe8452e50ebaca079cecedbb25acfd71fbb4565f109acc0557d1bf0db8386 languageName: node linkType: hard @@ -7166,10 +7216,10 @@ __metadata: languageName: node linkType: hard -"@types/pluralize@npm:0.0.30": - version: 0.0.30 - resolution: "@types/pluralize@npm:0.0.30" - checksum: 7a9a4a24aac1f74bd63e592a824ebec114486e0635a94496e92aa37fa388fac585be108d3ccfc7b2c490963679ec4900fbf394d22fa6cbf419f22cc499ab5a29 +"@types/pluralize@npm:0.0.31": + version: 0.0.31 + resolution: "@types/pluralize@npm:0.0.31" + checksum: 950d52d8f6709cdb7001336942fba0a63bf54b45695391fc2244d03db69b0eb6f187f80519d74941f5ce1dfa900d3975f2ed52e98b1f63a79045f5c085832beb languageName: node linkType: hard @@ -7353,12 +7403,12 @@ __metadata: languageName: node linkType: hard -"@types/supertest@npm:2.0.12": - version: 2.0.12 - resolution: "@types/supertest@npm:2.0.12" +"@types/supertest@npm:2.0.14": + version: 2.0.14 + resolution: "@types/supertest@npm:2.0.14" dependencies: "@types/superagent": "*" - checksum: f0e2b44f86bec2f708d6a3d0cb209055b487922040773049b0f8c6b557af52d4b5fa904e17dfaa4ce6e610172206bbec7b62420d158fa57b6ffc2de37b1730d3 + checksum: 9f6850a22b8f0fd4c26a6dfd9b64771a66476b1a4f841a3b84a9da843ce69463efbf37594fe107297dd14a225d199b802464d48d70e9413238c637903d392137 languageName: node linkType: hard @@ -7369,10 +7419,10 @@ __metadata: languageName: node linkType: hard -"@types/uuid@npm:9.0.3": - version: 9.0.3 - resolution: "@types/uuid@npm:9.0.3" - checksum: 3dde198defd71c067dd14b3050a8fe6d1ead5fe94ec318472e2c30a399d13f18941fe66cffabdcac7267177c9de2f975fdee6f0cc87cde610a2578e1ce4cc3af +"@types/uuid@npm:9.0.4": + version: 9.0.4 + resolution: "@types/uuid@npm:9.0.4" + checksum: 356e2504456eaebbc43a5af5ca6c07d71f5ae5520b5767cb1c62cd0ec55475fc4ee3d16a2874f4a5fce78e40e8583025afd3a7d9ba41f82939de310665f53f0e languageName: node linkType: hard @@ -7407,7 +7457,16 @@ __metadata: languageName: node linkType: hard -"@types/ws@npm:8.5.5, @types/ws@npm:^8.5.5": +"@types/ws@npm:8.5.6": + version: 8.5.6 + resolution: "@types/ws@npm:8.5.6" + dependencies: + "@types/node": "*" + checksum: 7addb0c5fa4e7713d5209afb8a90f1852b12c02cb537395adf7a05fbaf21205dc5f7c110fd5ad6f3dbf147112cbff33fb11d8633059cb344f0c14f595b1ea1fb + languageName: node + linkType: hard + +"@types/ws@npm:^8.5.5": version: 8.5.5 resolution: "@types/ws@npm:8.5.5" dependencies: @@ -7432,15 +7491,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.5.0" +"@typescript-eslint/eslint-plugin@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/eslint-plugin@npm:6.7.4" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.5.0 - "@typescript-eslint/type-utils": 6.5.0 - "@typescript-eslint/utils": 6.5.0 - "@typescript-eslint/visitor-keys": 6.5.0 + "@typescript-eslint/scope-manager": 6.7.4 + "@typescript-eslint/type-utils": 6.7.4 + "@typescript-eslint/utils": 6.7.4 + "@typescript-eslint/visitor-keys": 6.7.4 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -7453,25 +7512,25 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: d81525c9a081186ec1ae7d957972065d50bae8fe4b3de111e573adc7267bb830baaec8f1ae47d3b937984ac34324bacc3951868b7986d4f9974bbe480f2261c0 + checksum: 91d5051ae935d8bb61091665ee1e5c456992a0c29b58c86c1bb2b72c935dd831c0d3c7726a8d609455ae4a8b4ba8786ebeeef4bc7eff388b5f77475e7a634dc0 languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/parser@npm:6.5.0" +"@typescript-eslint/parser@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/parser@npm:6.7.4" dependencies: - "@typescript-eslint/scope-manager": 6.5.0 - "@typescript-eslint/types": 6.5.0 - "@typescript-eslint/typescript-estree": 6.5.0 - "@typescript-eslint/visitor-keys": 6.5.0 + "@typescript-eslint/scope-manager": 6.7.4 + "@typescript-eslint/types": 6.7.4 + "@typescript-eslint/typescript-estree": 6.7.4 + "@typescript-eslint/visitor-keys": 6.7.4 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: e9a70886ec2660aee5c77cdff67ba11651eb855b7ecd3ad1e70837fce997d6e6db9dfe1e1eab46a9b2147cbc034ae9c109951f3bc24ce54e78cae669b6bc9c95 + checksum: 60e7c01a69c1a67577f031cd6ef3c7980a9aedf2045b9950e339836acb2fe9d7bf0c8909fa95d713a8270f19dead43d82beb27dcf8705f81fe35b14b737e8fe0 languageName: node linkType: hard @@ -7485,22 +7544,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/scope-manager@npm:6.5.0" +"@typescript-eslint/scope-manager@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/scope-manager@npm:6.7.4" dependencies: - "@typescript-eslint/types": 6.5.0 - "@typescript-eslint/visitor-keys": 6.5.0 - checksum: 30d78143f68e07d6bd15a147f64cc16830f8a8c8409b37aa7c7d205d7585f3648ec1c5365b3f177b7561971b407f773f6dba83b3b78fa63091045f2d6bbc6b9f + "@typescript-eslint/types": 6.7.4 + "@typescript-eslint/visitor-keys": 6.7.4 + checksum: 8475d28f6408c204fb6bf25df45c1f16cad950190e31346c4b1ae15461a96f30b31b6fd1d3d635b41db6aa9a3fd3de25f04823632c74eeea478f34ebd134a1b0 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/type-utils@npm:6.5.0" +"@typescript-eslint/type-utils@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/type-utils@npm:6.7.4" dependencies: - "@typescript-eslint/typescript-estree": 6.5.0 - "@typescript-eslint/utils": 6.5.0 + "@typescript-eslint/typescript-estree": 6.7.4 + "@typescript-eslint/utils": 6.7.4 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -7508,7 +7567,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 80b9e5099f5bdb05348ea8664c0a5084efc851de43ef6c1997041e1f07e9cc34ac874cc9e8afb317c887513d657e2583ad360e3d57feaab775bde0acc1807982 + checksum: 231240a1aa1008a1b1facdd40b931433606947254f6e04705d154791a8b2c15d5ce3355b7d8a29cf7bb53c2e2eca1340c7860dd395389858d442af06c586d1fd languageName: node linkType: hard @@ -7536,10 +7595,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/types@npm:6.5.0" - checksum: 950ec16991d71494d10cb752535bbc4395295e3f03a716d53ec55bbb0aaff487aa774cc5002f775ffcc80b9f0e16ac53ecebf7cac1444ca4f7a847b0859ffbfb +"@typescript-eslint/types@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/types@npm:6.7.4" + checksum: 287ae48a2bb722b866460bcb2ba4ff908348145b3fc0af4ea75679d474e9ba3632bf64689044f181fe8ca3cb5f41238bb31ea428d5e78f1c3982f6dac6b7b149 languageName: node linkType: hard @@ -7561,12 +7620,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.5.0" +"@typescript-eslint/typescript-estree@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/typescript-estree@npm:6.7.4" dependencies: - "@typescript-eslint/types": 6.5.0 - "@typescript-eslint/visitor-keys": 6.5.0 + "@typescript-eslint/types": 6.7.4 + "@typescript-eslint/visitor-keys": 6.7.4 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -7575,7 +7634,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 05717fa1f2609fa5669803191cf309a379c815aaf4fff6850f40560eec8749759c36b288f05cecffd5c1d0be8de1fe414ecfee6ecf99b6ae521baa48c8b58455 + checksum: 2e8f5e972403233522eff09cfe7a0a23549cfd462e82b434aa32ddbdba5b329be5a549514a157f6b79e2d0159c9348d23b202e5d915d4f2c7cbfe72e1a48a429 languageName: node linkType: hard @@ -7597,20 +7656,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/utils@npm:6.5.0" +"@typescript-eslint/utils@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/utils@npm:6.7.4" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.5.0 - "@typescript-eslint/types": 6.5.0 - "@typescript-eslint/typescript-estree": 6.5.0 + "@typescript-eslint/scope-manager": 6.7.4 + "@typescript-eslint/types": 6.7.4 + "@typescript-eslint/typescript-estree": 6.7.4 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 58a82213c8a7bac97a6538b9845c1de5c5692fbf72548f95ed5e044a222608590bcafbb9eacba92a8c4e9eb3e5d0a2fd553eae0d6694ed2d6152aed4dabf9480 + checksum: 75e197dd58b230436ceb51f2050bb3af8796b05a197eaf741251f8e9c4d9ba1a99d654d090da0c49d31b20da79d9cc3746cbb663ffd5ea614d7a960d64676d65 languageName: node linkType: hard @@ -7624,13 +7683,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.5.0": - version: 6.5.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.5.0" +"@typescript-eslint/visitor-keys@npm:6.7.4": + version: 6.7.4 + resolution: "@typescript-eslint/visitor-keys@npm:6.7.4" dependencies: - "@typescript-eslint/types": 6.5.0 + "@typescript-eslint/types": 6.7.4 eslint-visitor-keys: ^3.4.1 - checksum: 768a02dd0d8aae45708646bb0c51e67da09e71dc101bb0a0e55d7e0c8eadfea2f531acd3035d1ec34bf2380b66188f3fc47c6bef0201eae36b2dcc48d1934442 + checksum: 34d09798b6c48dc059e88c6cb3df5f96e859bd65d1dd05d907b8a3c7a5708a737d50607081fb14a4b974b90cfe4169a93db974bf53af8b282420187f73b0afac languageName: node linkType: hard @@ -8496,11 +8555,11 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^29.6.4": - version: 29.6.4 - resolution: "babel-jest@npm:29.6.4" +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" dependencies: - "@jest/transform": ^29.6.4 + "@jest/transform": ^29.7.0 "@types/babel__core": ^7.1.14 babel-plugin-istanbul: ^6.1.1 babel-preset-jest: ^29.6.3 @@ -8509,7 +8568,7 @@ __metadata: slash: ^3.0.0 peerDependencies: "@babel/core": ^7.8.0 - checksum: c574f1805ab6b51a7d0f5a028aad19eec4634be81e66e6f4631b79b34d8ea05dfb53629f3686c77345163872730aa0408c9e5937ed85f846984228f7ab5e5d96 + checksum: ee6f8e0495afee07cac5e4ee167be705c711a8cc8a737e05a587a131fdae2b3c8f9aa55dfd4d9c03009ac2d27f2de63d8ba96d3e8460da4d00e8af19ef9a83f7 languageName: node linkType: hard @@ -10156,6 +10215,23 @@ __metadata: languageName: node linkType: hard +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + prompts: ^2.0.1 + bin: + create-jest: bin/create-jest.js + checksum: 1427d49458adcd88547ef6fa39041e1fe9033a661293aa8d2c3aa1b4967cb5bf4f0c00436c7a61816558f28ba2ba81a94d5c962e8022ea9a883978fc8e1f2945 + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -10941,7 +11017,7 @@ __metadata: languageName: node linkType: hard -"dottie@npm:^2.0.4": +"dottie@npm:^2.0.6": version: 2.0.6 resolution: "dottie@npm:2.0.6" checksum: 4c778df9dc631a1108a32ef390916836814999a7411d10883f4151bd49c9c6934dc329b3f50fc7692849aa75ba87dba880fd54be501a3b39a6b9c23d6f772a09 @@ -11338,9 +11414,9 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-typescript@npm:3.6.0": - version: 3.6.0 - resolution: "eslint-import-resolver-typescript@npm:3.6.0" +"eslint-import-resolver-typescript@npm:3.6.1": + version: 3.6.1 + resolution: "eslint-import-resolver-typescript@npm:3.6.1" dependencies: debug: ^4.3.4 enhanced-resolve: ^5.12.0 @@ -11352,7 +11428,7 @@ __metadata: peerDependencies: eslint: "*" eslint-plugin-import: "*" - checksum: 57b1b3859149f847e0d4174ff979cf35362d60c951df047f01b96f4c3794a7ea0d4e1ec85be25e610d3706902c3acfb964a66b825c1a55e3ce3a124b9a7a13bd + checksum: 454fa0646533050fb57f13d27daf8c71f51b0bb9156d6a461290ccb8576d892209fcc6702a89553f3f5ea8e5b407395ca2e5de169a952c953685f1f7c46b4496 languageName: node linkType: hard @@ -11395,9 +11471,9 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jest@npm:27.2.3": - version: 27.2.3 - resolution: "eslint-plugin-jest@npm:27.2.3" +"eslint-plugin-jest@npm:27.4.2": + version: 27.4.2 + resolution: "eslint-plugin-jest@npm:27.4.2" dependencies: "@typescript-eslint/utils": ^5.10.0 peerDependencies: @@ -11409,7 +11485,7 @@ __metadata: optional: true jest: optional: true - checksum: 4c7e07f52f17749ac6fd0ff5fcd5ce30b88983ba31eeee322e4d48859f55eaa112f06172e586ad2031c00ff28bb2dfdc3d35c83895251b9c0e860fa47dfc5ff4 + checksum: 99a8301ae00c37da97866b8b13c89a077716d2c653b26bc417d242e7300a43237c0017fd488c43966fa38585f19050facdbbc71d03ca36a1ce6f2ba930a9143e languageName: node linkType: hard @@ -11485,15 +11561,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:8.48.0": - version: 8.48.0 - resolution: "eslint@npm:8.48.0" +"eslint@npm:8.50.0": + version: 8.50.0 + resolution: "eslint@npm:8.50.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.2 - "@eslint/js": 8.48.0 - "@humanwhocodes/config-array": ^0.11.10 + "@eslint/js": 8.50.0 + "@humanwhocodes/config-array": ^0.11.11 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 ajv: ^6.12.4 @@ -11528,7 +11604,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: f20b359a4f8123fec5c033577368cc020d42978b1b45303974acd8da7a27063168ee3fe297ab5b35327162f6a93154063e3ce6577102f70f9809aff793db9bd0 + checksum: 9ebfe5615dc84700000d218e32ddfdcfc227ca600f65f18e5541ec34f8902a00356a9a8804d9468fd6c8637a5ef6a3897291dad91ba6579d5b32ffeae5e31768 languageName: node linkType: hard @@ -11709,16 +11785,16 @@ __metadata: languageName: node linkType: hard -"expect@npm:^29.6.4": - version: 29.6.4 - resolution: "expect@npm:29.6.4" +"expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" dependencies: - "@jest/expect-utils": ^29.6.4 + "@jest/expect-utils": ^29.7.0 jest-get-type: ^29.6.3 - jest-matcher-utils: ^29.6.4 - jest-message-util: ^29.6.3 - jest-util: ^29.6.3 - checksum: 019b187d665562e4948b239e011a8791363e916f3076a229298d625e67fdadb06e8c2748798c49b4cf418ea223673eadd1de06537e08ba3c055c6f0efefc2306 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + checksum: 9257f10288e149b81254a0fda8ffe8d54a7061cd61d7515779998b012579d2b8c22354b0eb901daf0145f347403da582f75f359f4810c007182ad3fb318b5c0c languageName: node linkType: hard @@ -11809,19 +11885,6 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.2.12": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 - languageName: node - linkType: hard - "fast-glob@npm:3.2.7": version: 3.2.7 resolution: "fast-glob@npm:3.2.7" @@ -11835,29 +11898,29 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": - version: 3.3.0 - resolution: "fast-glob@npm:3.3.0" +"fast-glob@npm:3.3.1, fast-glob@npm:^3.3.1": + version: 3.3.1 + resolution: "fast-glob@npm:3.3.1" dependencies: "@nodelib/fs.stat": ^2.0.2 "@nodelib/fs.walk": ^1.2.3 glob-parent: ^5.1.2 merge2: ^1.3.0 micromatch: ^4.0.4 - checksum: 20df62be28eb5426fe8e40e0d05601a63b1daceb7c3d87534afcad91bdcf1e4b1743cf2d5247d6e225b120b46df0b9053a032b2691ba34ee121e033acd81f547 + checksum: b6f3add6403e02cf3a798bfbb1183d0f6da2afd368f27456010c0bc1f9640aea308243d4cb2c0ab142f618276e65ecb8be1661d7c62a7b4e5ba774b9ce5432e5 languageName: node linkType: hard -"fast-glob@npm:^3.3.1": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": + version: 3.3.0 + resolution: "fast-glob@npm:3.3.0" dependencies: "@nodelib/fs.stat": ^2.0.2 "@nodelib/fs.walk": ^1.2.3 glob-parent: ^5.1.2 merge2: ^1.3.0 micromatch: ^4.0.4 - checksum: b6f3add6403e02cf3a798bfbb1183d0f6da2afd368f27456010c0bc1f9640aea308243d4cb2c0ab142f618276e65ecb8be1661d7c62a7b4e5ba774b9ce5432e5 + checksum: 20df62be28eb5426fe8e40e0d05601a63b1daceb7c3d87534afcad91bdcf1e4b1743cf2d5247d6e225b120b46df0b9053a032b2691ba34ee121e033acd81f547 languageName: node linkType: hard @@ -12664,7 +12727,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.2.5": +"glob@npm:^10.2.2": version: 10.3.3 resolution: "glob@npm:10.3.3" dependencies: @@ -12679,6 +12742,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.3.7": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + "glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -12915,10 +12993,10 @@ __metadata: languageName: node linkType: hard -"graphql@npm:16.8.0": - version: 16.8.0 - resolution: "graphql@npm:16.8.0" - checksum: d853d4085b0c911a7e2a926c3b0d379934ec61cd4329e70cdf281763102f024fd80a97db7a505b8b04fed9050cb4875f8f518150ea854557a500a0b41dcd7f4e +"graphql@npm:16.8.1": + version: 16.8.1 + resolution: "graphql@npm:16.8.1" + checksum: 8d304b7b6f708c8c5cc164b06e92467dfe36aff6d4f2cf31dd19c4c2905a0e7b89edac4b7e225871131fd24e21460836b369de0c06532644d15b461d55b1ccc0 languageName: node linkType: hard @@ -14368,6 +14446,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.8.7 resolution: "jake@npm:10.8.7" @@ -14382,14 +14473,14 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-changed-files@npm:29.6.3" +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" dependencies: execa: ^5.0.0 - jest-util: ^29.6.3 + jest-util: ^29.7.0 p-limit: ^3.1.0 - checksum: 55bc820a70c220a02fec214d5c48d5e0d829549e5c7b9959776b4ca3f76f5ff20c7c8ff816a847822766f1d712477ab3027f7a66ec61bf65de3f852e878b4dfd + checksum: 963e203893c396c5dfc75e00a49426688efea7361b0f0e040035809cecd2d46b3c01c02be2d9e8d38b1138357d2de7719ea5b5be21f66c10f2e9685a5a73bb99 languageName: node linkType: hard @@ -14421,49 +14512,48 @@ __metadata: languageName: node linkType: hard -"jest-circus@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-circus@npm:29.6.4" +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" dependencies: - "@jest/environment": ^29.6.4 - "@jest/expect": ^29.6.4 - "@jest/test-result": ^29.6.4 + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 + "@jest/test-result": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 co: ^4.6.0 dedent: ^1.0.0 is-generator-fn: ^2.0.0 - jest-each: ^29.6.3 - jest-matcher-utils: ^29.6.4 - jest-message-util: ^29.6.3 - jest-runtime: ^29.6.4 - jest-snapshot: ^29.6.4 - jest-util: ^29.6.3 + jest-each: ^29.7.0 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 p-limit: ^3.1.0 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 pure-rand: ^6.0.0 slash: ^3.0.0 stack-utils: ^2.0.3 - checksum: 31f64ddf6df4aefe30ef5f8de9da137c9cba58ab5e2a25cf749450735088dc88a9974591a4256d481af0fe64608173c921219f9fad9a7dd87cbe47a79e111be8 + checksum: 349437148924a5a109c9b8aad6d393a9591b4dac1918fc97d81b7fc515bc905af9918495055071404af1fab4e48e4b04ac3593477b1d5dcf48c4e71b527c70a7 languageName: node linkType: hard -"jest-cli@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-cli@npm:29.6.4" +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" dependencies: - "@jest/core": ^29.6.4 - "@jest/test-result": ^29.6.4 + "@jest/core": ^29.7.0 + "@jest/test-result": ^29.7.0 "@jest/types": ^29.6.3 chalk: ^4.0.0 + create-jest: ^29.7.0 exit: ^0.1.2 - graceful-fs: ^4.2.9 import-local: ^3.0.2 - jest-config: ^29.6.4 - jest-util: ^29.6.3 - jest-validate: ^29.6.3 - prompts: ^2.0.1 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 yargs: ^17.3.1 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -14472,7 +14562,7 @@ __metadata: optional: true bin: jest: bin/jest.js - checksum: 87a85a27eff0e502717b6ee0ce861d3e50d8c47d7298477f8ca10964b958f06c20241d28f1360ce2a85072763483e4924248106a8ed530ca460a56db3fdfc53e + checksum: 664901277a3f5007ea4870632ed6e7889db9da35b2434e7cb488443e6bf5513889b344b7fddf15112135495b9875892b156faeb2d7391ddb9e2a849dcb7b6c36 languageName: node linkType: hard @@ -14514,30 +14604,30 @@ __metadata: languageName: node linkType: hard -"jest-config@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-config@npm:29.6.4" +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" dependencies: "@babel/core": ^7.11.6 - "@jest/test-sequencer": ^29.6.4 + "@jest/test-sequencer": ^29.7.0 "@jest/types": ^29.6.3 - babel-jest: ^29.6.4 + babel-jest: ^29.7.0 chalk: ^4.0.0 ci-info: ^3.2.0 deepmerge: ^4.2.2 glob: ^7.1.3 graceful-fs: ^4.2.9 - jest-circus: ^29.6.4 - jest-environment-node: ^29.6.4 + jest-circus: ^29.7.0 + jest-environment-node: ^29.7.0 jest-get-type: ^29.6.3 jest-regex-util: ^29.6.3 - jest-resolve: ^29.6.4 - jest-runner: ^29.6.4 - jest-util: ^29.6.3 - jest-validate: ^29.6.3 + jest-resolve: ^29.7.0 + jest-runner: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 micromatch: ^4.0.4 parse-json: ^5.2.0 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 slash: ^3.0.0 strip-json-comments: ^3.1.1 peerDependencies: @@ -14548,7 +14638,7 @@ __metadata: optional: true ts-node: optional: true - checksum: 177352658774344896df3988dbe892e0b117579f45cc43aebc588493665bf19a557e202f097f5b4a987314ec2d84afa0769299ac6e702c5923d1fd3cfa4692b0 + checksum: 4cabf8f894c180cac80b7df1038912a3fc88f96f2622de33832f4b3314f83e22b08fb751da570c0ab2b7988f21604bdabade95e3c0c041068ac578c085cf7dff languageName: node linkType: hard @@ -14564,15 +14654,15 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-diff@npm:29.6.4" +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" dependencies: chalk: ^4.0.0 diff-sequences: ^29.6.3 jest-get-type: ^29.6.3 - pretty-format: ^29.6.3 - checksum: e205c45ab6dbcc660dc2a682cddb20f6a3cbbbdecd2821cce2050619f96dbd7560ee25f7f51d42c302596aeaddbea54390b78be3ab639340d24d67e4d270a8b0 + pretty-format: ^29.7.0 + checksum: 08e24a9dd43bfba1ef07a6374e5af138f53137b79ec3d5cc71a2303515335898888fa5409959172e1e05de966c9e714368d15e8994b0af7441f0721ee8e1bb77 languageName: node linkType: hard @@ -14585,12 +14675,12 @@ __metadata: languageName: node linkType: hard -"jest-docblock@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-docblock@npm:29.6.3" +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" dependencies: detect-newline: ^3.0.0 - checksum: 6f3213a1e79e7eedafeb462acfa9a41303f9c0167893b140f6818fa16d7eb6bf3f9b9cf4669097ca6b7154847793489ecd6b4f6cfb0e416b88cfa3b4b36715b6 + checksum: 66390c3e9451f8d96c5da62f577a1dad701180cfa9b071c5025acab2f94d7a3efc2515cfa1654ebe707213241541ce9c5530232cdc8017c91ed64eea1bd3b192 languageName: node linkType: hard @@ -14607,16 +14697,16 @@ __metadata: languageName: node linkType: hard -"jest-each@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-each@npm:29.6.3" +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 chalk: ^4.0.0 jest-get-type: ^29.6.3 - jest-util: ^29.6.3 - pretty-format: ^29.6.3 - checksum: fe06e80b3554e2a8464f5f5c61943e02db1f8a7177139cb55b3201a1d1513cb089d8800401f102729a31bf8dd6f88229044e6088fea9dd5647ed11e841b6b88c + jest-util: ^29.7.0 + pretty-format: ^29.7.0 + checksum: e88f99f0184000fc8813f2a0aa79e29deeb63700a3b9b7928b8a418d7d93cd24933608591dbbdea732b473eb2021c72991b5cc51a17966842841c6e28e6f691c languageName: node linkType: hard @@ -14634,17 +14724,17 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-environment-node@npm:29.6.4" +"jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" dependencies: - "@jest/environment": ^29.6.4 - "@jest/fake-timers": ^29.6.4 + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" - jest-mock: ^29.6.3 - jest-util: ^29.6.3 - checksum: 518221505af4bd32c84f2af2c03f9d771de2711bd69fe7723b648fcc2e05d95b4e75f493afa9010209e26a4a3309ebee971f9b18c45b540891771d3b68c3a16e + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: 501a9966292cbe0ca3f40057a37587cb6def25e1e0c5e39ac6c650fe78d3c70a2428304341d084ac0cced5041483acef41c477abac47e9a290d5545fd2f15646 languageName: node linkType: hard @@ -14700,9 +14790,9 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-haste-map@npm:29.6.4" +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/graceful-fs": ^4.1.3 @@ -14712,14 +14802,14 @@ __metadata: fsevents: ^2.3.2 graceful-fs: ^4.2.9 jest-regex-util: ^29.6.3 - jest-util: ^29.6.3 - jest-worker: ^29.6.4 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 micromatch: ^4.0.4 walker: ^1.0.8 dependenciesMeta: fsevents: optional: true - checksum: 4f720fd3813bb38400b7a9a094e55664cbddd907ba1769457ed746f6c870c615167647a5b697a788183d832b1dcb1b66143e52990a6f4403283f6686077fa868 + checksum: c2c8f2d3e792a963940fbdfa563ce14ef9e14d4d86da645b96d3cd346b8d35c5ce0b992ee08593939b5f718cf0a1f5a90011a056548a1dbf58397d4356786f01 languageName: node linkType: hard @@ -14733,13 +14823,13 @@ __metadata: languageName: node linkType: hard -"jest-leak-detector@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-leak-detector@npm:29.6.3" +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" dependencies: jest-get-type: ^29.6.3 - pretty-format: ^29.6.3 - checksum: 27548fcfc7602fe1b88f8600185e35ffff71751f3631e52bbfdfc72776f5a13a430185cf02fc632b41320a74f99ae90e40ce101c8887509f0f919608a7175129 + pretty-format: ^29.7.0 + checksum: e3950e3ddd71e1d0c22924c51a300a1c2db6cf69ec1e51f95ccf424bcc070f78664813bef7aed4b16b96dfbdeea53fe358f8aeaaea84346ae15c3735758f1605 languageName: node linkType: hard @@ -14755,15 +14845,15 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-matcher-utils@npm:29.6.4" +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" dependencies: chalk: ^4.0.0 - jest-diff: ^29.6.4 + jest-diff: ^29.7.0 jest-get-type: ^29.6.3 - pretty-format: ^29.6.3 - checksum: 9e17bce282e74bdbba2ce5475c490e0bba4f464cd42132bfc5df0337e0853af4dba925c7f4f61cbb0a4818fa121d28d7ff0196ec8829773a22fce59a822976d2 + pretty-format: ^29.7.0 + checksum: d7259e5f995d915e8a37a8fd494cb7d6af24cd2a287b200f831717ba0d015190375f9f5dc35393b8ba2aae9b2ebd60984635269c7f8cff7d85b077543b7744cd languageName: node linkType: hard @@ -14784,9 +14874,9 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-message-util@npm:29.6.3" +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" dependencies: "@babel/code-frame": ^7.12.13 "@jest/types": ^29.6.3 @@ -14794,10 +14884,10 @@ __metadata: chalk: ^4.0.0 graceful-fs: ^4.2.9 micromatch: ^4.0.4 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 slash: ^3.0.0 stack-utils: ^2.0.3 - checksum: 59f5229a06c073a8877ba4d2e304cc07d63b0062bf5764d4bed14364403889e77f1825d1bd9017c19a840847d17dffd414dc06f1fcb537b5f9e03dbc65b84ada + checksum: a9d025b1c6726a2ff17d54cc694de088b0489456c69106be6b615db7a51b7beb66788bea7a59991a019d924fbf20f67d085a445aedb9a4d6760363f4d7d09930 languageName: node linkType: hard @@ -14812,14 +14902,14 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-mock@npm:29.6.3" +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/node": "*" - jest-util: ^29.6.3 - checksum: 35772968010c0afb1bb1ef78570b9cbea907c6f967d24b4e95e1a596a1000c63d60e225fb9ddfdd5218674da4aa61d92a09927fc26310cecbbfaa8278d919e32 + jest-util: ^29.7.0 + checksum: 81ba9b68689a60be1482212878973700347cb72833c5e5af09895882b9eb5c4e02843a1bbdf23f94c52d42708bab53a30c45a3482952c9eec173d1eaac5b86c5 languageName: node linkType: hard @@ -14849,13 +14939,13 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-resolve-dependencies@npm:29.6.4" +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" dependencies: jest-regex-util: ^29.6.3 - jest-snapshot: ^29.6.4 - checksum: 34f81d22cbd72203130cc14cbb66d5783d9f59fba4d366b9653f8fb4f6feeaac25d89696f2f77c700659843d5440dc92f58ad443ba05da1da46c39234866d916 + jest-snapshot: ^29.7.0 + checksum: aeb75d8150aaae60ca2bb345a0d198f23496494677cd6aefa26fc005faf354061f073982175daaf32b4b9d86b26ca928586344516e3e6969aa614cb13b883984 languageName: node linkType: hard @@ -14876,20 +14966,20 @@ __metadata: languageName: node linkType: hard -"jest-resolve@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-resolve@npm:29.6.4" +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" dependencies: chalk: ^4.0.0 graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.4 + jest-haste-map: ^29.7.0 jest-pnp-resolver: ^1.2.2 - jest-util: ^29.6.3 - jest-validate: ^29.6.3 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 resolve: ^1.20.0 resolve.exports: ^2.0.0 slash: ^3.0.0 - checksum: 5f0ef260aec79ef00e16e0ba7b27d527054e1faed08a144279cd191b5c5b71af67c52b9ddfd24aa2f563d254618ce9bf7519809f23fb2abf6c4fa375503caa28 + checksum: 0ca218e10731aa17920526ec39deaec59ab9b966237905ffc4545444481112cd422f01581230eceb7e82d86f44a543d520a71391ec66e1b4ef1a578bd5c73487 languageName: node linkType: hard @@ -14922,32 +15012,32 @@ __metadata: languageName: node linkType: hard -"jest-runner@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-runner@npm:29.6.4" +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" dependencies: - "@jest/console": ^29.6.4 - "@jest/environment": ^29.6.4 - "@jest/test-result": ^29.6.4 - "@jest/transform": ^29.6.4 + "@jest/console": ^29.7.0 + "@jest/environment": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 emittery: ^0.13.1 graceful-fs: ^4.2.9 - jest-docblock: ^29.6.3 - jest-environment-node: ^29.6.4 - jest-haste-map: ^29.6.4 - jest-leak-detector: ^29.6.3 - jest-message-util: ^29.6.3 - jest-resolve: ^29.6.4 - jest-runtime: ^29.6.4 - jest-util: ^29.6.3 - jest-watcher: ^29.6.4 - jest-worker: ^29.6.4 + jest-docblock: ^29.7.0 + jest-environment-node: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-leak-detector: ^29.7.0 + jest-message-util: ^29.7.0 + jest-resolve: ^29.7.0 + jest-runtime: ^29.7.0 + jest-util: ^29.7.0 + jest-watcher: ^29.7.0 + jest-worker: ^29.7.0 p-limit: ^3.1.0 source-map-support: 0.5.13 - checksum: ca977dd30262171fe000de8407a3187c16e7057ddf690bcc21068155aacd4824ee927b544e0fa9f2885948b47a5123b472da41e095e3bcbdebb79f1fa2f2fc56 + checksum: f0405778ea64812bf9b5c50b598850d94ccf95d7ba21f090c64827b41decd680ee19fcbb494007cdd7f5d0d8906bfc9eceddd8fa583e753e736ecd462d4682fb languageName: node linkType: hard @@ -14981,16 +15071,16 @@ __metadata: languageName: node linkType: hard -"jest-runtime@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-runtime@npm:29.6.4" +"jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" dependencies: - "@jest/environment": ^29.6.4 - "@jest/fake-timers": ^29.6.4 - "@jest/globals": ^29.6.4 + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 + "@jest/globals": ^29.7.0 "@jest/source-map": ^29.6.3 - "@jest/test-result": ^29.6.4 - "@jest/transform": ^29.6.4 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 @@ -14998,16 +15088,16 @@ __metadata: collect-v8-coverage: ^1.0.0 glob: ^7.1.3 graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.4 - jest-message-util: ^29.6.3 - jest-mock: ^29.6.3 + jest-haste-map: ^29.7.0 + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 jest-regex-util: ^29.6.3 - jest-resolve: ^29.6.4 - jest-snapshot: ^29.6.4 - jest-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 slash: ^3.0.0 strip-bom: ^4.0.0 - checksum: 93deacd06f8f2bb808dbfb8acbcbc0b724187b3d3fffafd497a32c939bf385ca21f5a3f03eebd5b958a0e93865d0e68a0db73bd0fe16dafbd5e922558aa7b359 + checksum: d19f113d013e80691e07047f68e1e3448ef024ff2c6b586ce4f90cd7d4c62a2cd1d460110491019719f3c59bfebe16f0e201ed005ef9f80e2cf798c374eed54e languageName: node linkType: hard @@ -15040,31 +15130,31 @@ __metadata: languageName: node linkType: hard -"jest-snapshot@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-snapshot@npm:29.6.4" +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" dependencies: "@babel/core": ^7.11.6 "@babel/generator": ^7.7.2 "@babel/plugin-syntax-jsx": ^7.7.2 "@babel/plugin-syntax-typescript": ^7.7.2 "@babel/types": ^7.3.3 - "@jest/expect-utils": ^29.6.4 - "@jest/transform": ^29.6.4 + "@jest/expect-utils": ^29.7.0 + "@jest/transform": ^29.7.0 "@jest/types": ^29.6.3 babel-preset-current-node-syntax: ^1.0.0 chalk: ^4.0.0 - expect: ^29.6.4 + expect: ^29.7.0 graceful-fs: ^4.2.9 - jest-diff: ^29.6.4 + jest-diff: ^29.7.0 jest-get-type: ^29.6.3 - jest-matcher-utils: ^29.6.4 - jest-message-util: ^29.6.3 - jest-util: ^29.6.3 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 natural-compare: ^1.4.0 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 semver: ^7.5.3 - checksum: 0c9b5ec640457fb780ac6c9b6caa814436e9e16bf744772eee3bfd055ae5f7a3085a6a09b2f30910e31915dafc3955d92357cc98189e4d5dcb417b5fdafda6e3 + checksum: 86821c3ad0b6899521ce75ee1ae7b01b17e6dfeff9166f2cf17f012e0c5d8c798f30f9e4f8f7f5bed01ea7b55a6bc159f5eda778311162cbfa48785447c237ad languageName: node linkType: hard @@ -15082,9 +15172,9 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-util@npm:29.6.3" +"jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/node": "*" @@ -15092,7 +15182,7 @@ __metadata: ci-info: ^3.2.0 graceful-fs: ^4.2.9 picomatch: ^2.2.3 - checksum: 7bf3ba3ac67ac6ceff7d8fdd23a86768e23ddd9133ecd9140ef87cc0c28708effabaf67a6cd45cd9d90a63d645a522ed0825d09ee59ac4c03b9c473b1fef4c7c + checksum: 042ab4980f4ccd4d50226e01e5c7376a8556b472442ca6091a8f102488c0f22e6e8b89ea874111d2328a2080083bf3225c86f3788c52af0bd0345a00eb57a3ca languageName: node linkType: hard @@ -15110,17 +15200,17 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-validate@npm:29.6.3" +"jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 camelcase: ^6.2.0 chalk: ^4.0.0 jest-get-type: ^29.6.3 leven: ^3.1.0 - pretty-format: ^29.6.3 - checksum: caa489ed11080441c636b8035ab71bafbdc0c052b1e452855e4d2dd24ac15e497710a270ea6fc5ef8926b22c1ce4d6e07ec2dc193f0810cff5851d7a2222c045 + pretty-format: ^29.7.0 + checksum: 191fcdc980f8a0de4dbdd879fa276435d00eb157a48683af7b3b1b98b0f7d9de7ffe12689b617779097ff1ed77601b9f7126b0871bba4f776e222c40f62e9dae languageName: node linkType: hard @@ -15140,19 +15230,19 @@ __metadata: languageName: node linkType: hard -"jest-watcher@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-watcher@npm:29.6.4" +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" dependencies: - "@jest/test-result": ^29.6.4 + "@jest/test-result": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" ansi-escapes: ^4.2.1 chalk: ^4.0.0 emittery: ^0.13.1 - jest-util: ^29.6.3 + jest-util: ^29.7.0 string-length: ^4.0.1 - checksum: 13c0f96f7e9212e4f3ef2daf3e787045bdcec414061bf286eca934c7f4083fb04d38df9ced9c0edfbe15f3521ca581eb2ed6108c338a0db1f3e1def65687992f + checksum: 67e6e7fe695416deff96b93a14a561a6db69389a0667e9489f24485bb85e5b54e12f3b2ba511ec0b777eca1e727235b073e3ebcdd473d68888650489f88df92f languageName: node linkType: hard @@ -15179,26 +15269,26 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-worker@npm:29.6.4" +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" dependencies: "@types/node": "*" - jest-util: ^29.6.3 + jest-util: ^29.7.0 merge-stream: ^2.0.0 supports-color: ^8.0.0 - checksum: 05d19a5759ebfeb964036065be55ad8d8e8ddffa85d9b3a4c0b95765695efb1d8226ec824a4d8e660c38cda3389bfeb98d819f47232acf9fb0e79f553b7c0a76 + checksum: 30fff60af49675273644d408b650fc2eb4b5dcafc5a0a455f238322a8f9d8a98d847baca9d51ff197b6747f54c7901daa2287799230b856a0f48287d131f8c13 languageName: node linkType: hard -"jest@npm:29.6.4": - version: 29.6.4 - resolution: "jest@npm:29.6.4" +"jest@npm:29.7.0": + version: 29.7.0 + resolution: "jest@npm:29.7.0" dependencies: - "@jest/core": ^29.6.4 + "@jest/core": ^29.7.0 "@jest/types": ^29.6.3 import-local: ^3.0.2 - jest-cli: ^29.6.4 + jest-cli: ^29.7.0 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: @@ -15206,7 +15296,7 @@ __metadata: optional: true bin: jest: bin/jest.js - checksum: ba28ca7a86d029bcd742bb254c0c8d0119c1e002ddae128ff6409ebabc0b29c36f69dbf3fdd326aff16e7b2500c9a918bbc6a9a5db4d966e035127242239439f + checksum: 17ca8d67504a7dbb1998cf3c3077ec9031ba3eb512da8d71cb91bcabb2b8995c4e4b292b740cb9bf1cbff5ce3e110b3f7c777b0cefb6f41ab05445f248d0ee0b languageName: node linkType: hard @@ -15890,7 +15980,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.10.1, lru-cache@npm:^7.14.1, lru-cache@npm:^7.7.1": +"lru-cache@npm:^7.10.1, lru-cache@npm:^7.13.1, lru-cache@npm:^7.14.1, lru-cache@npm:^7.7.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 @@ -16509,9 +16599,9 @@ __metadata: languageName: node linkType: hard -"mongodb-memory-server-core@npm:8.15.1": - version: 8.15.1 - resolution: "mongodb-memory-server-core@npm:8.15.1" +"mongodb-memory-server-core@npm:8.16.0": + version: 8.16.0 + resolution: "mongodb-memory-server-core@npm:8.16.0" dependencies: async-mutex: ^0.3.2 camelcase: ^6.3.0 @@ -16528,17 +16618,17 @@ __metadata: tslib: ^2.6.1 uuid: ^9.0.0 yauzl: ^2.10.0 - checksum: 2e47663a65575f4d067f8acf47a00aa7f2cfd8040854034f72e2ca35ab3d708fbe45feff556eff9d9d8fce5a9618a57c4d01c8a9c267b810470962fd5e126823 + checksum: 8840323954ecd2974b9c3037e937889ad8315aba02b759fcb04c58457e71714bfcb60c2150b107c60f4e4b9535753f10ebe71c85bbe75a5897ee4e3006b6018c languageName: node linkType: hard -"mongodb-memory-server@npm:8.15.1": - version: 8.15.1 - resolution: "mongodb-memory-server@npm:8.15.1" +"mongodb-memory-server@npm:8.16.0": + version: 8.16.0 + resolution: "mongodb-memory-server@npm:8.16.0" dependencies: - mongodb-memory-server-core: 8.15.1 + mongodb-memory-server-core: 8.16.0 tslib: ^2.6.1 - checksum: ad1f1cba52925556274786414c9267056dac6a7463789a13ebb3722a840fdbe45131a50d964ec5ee215460518dc0966050c8f118b70ea97d8de5d4276da44c6b + checksum: 6dbccf05e29939866867cec17bac268620bf743fdf6f363d633ede982d92391e28cf5c5ff09cd16762c48cd2dcb2d12f8fe0744d43c36ee90e7ae8fcc978fe47 languageName: node linkType: hard @@ -16592,9 +16682,9 @@ __metadata: languageName: node linkType: hard -"mongoose@npm:^7.5.0": - version: 7.5.0 - resolution: "mongoose@npm:7.5.0" +"mongoose@npm:^7.5.4": + version: 7.5.4 + resolution: "mongoose@npm:7.5.4" dependencies: bson: ^5.4.0 kareem: 2.5.1 @@ -16603,7 +16693,7 @@ __metadata: mquery: 5.0.0 ms: 2.1.3 sift: 16.0.1 - checksum: 3e4219fd29a44efe9d1fe41134bdbafca9b44f6da58fc01be3723379954d9ca6bdd8d2bdd352ded932432b9d0e0c5146490add84eb14f4aee3743d94e6cae643 + checksum: e888bc5e47c7c3f0158dd93c18efedc15a7dbaa7c7c599e38aa4fccf00514280af02ae8cb40e91190d5cff8822a78c3cfd15adfd309094a3a7b3ca5ba3c6fb03 languageName: node linkType: hard @@ -16692,9 +16782,9 @@ __metadata: languageName: node linkType: hard -"mysql2@npm:3.6.0": - version: 3.6.0 - resolution: "mysql2@npm:3.6.0" +"mysql2@npm:3.6.1": + version: 3.6.1 + resolution: "mysql2@npm:3.6.1" dependencies: denque: ^2.1.0 generate-function: ^2.3.1 @@ -16704,7 +16794,7 @@ __metadata: named-placeholders: ^1.1.3 seq-queue: ^0.0.5 sqlstring: ^2.3.2 - checksum: 3c0f6102ce76314b3a0789626bf49beccf4e51cba72dc8509e631ccd47f12d23020832468b6e30db513e73bd2ed72b6e0e6b118a7ad808f9e32f2e3dc744ffc8 + checksum: 29892b9810557c4cc1ce8291286aff57ffbe2d832a5ce5de8d9f336497d367a8613662ee5fac1b2144ef898550f66b251f5b8801a6d8fdf89b9018263708e63b languageName: node linkType: hard @@ -16779,29 +16869,30 @@ __metadata: version: 0.0.0-use.local resolution: "nestjs-query@workspace:." dependencies: - "@actions/core": ^1.10.0 + "@actions/core": ^1.10.1 "@apollo/federation": 0.38.1 - "@apollo/gateway": 2.5.3 - "@apollo/server": ^4.9.3 - "@commitlint/cli": 17.7.1 + "@apollo/gateway": 2.2.3 + "@apollo/server": ^4.9.4 + "@apollo/subgraph": 2.2.3 + "@commitlint/cli": 17.7.2 "@commitlint/config-conventional": ^17.7.0 - "@docusaurus/core": 2.4.1 - "@docusaurus/module-type-aliases": 2.4.1 - "@docusaurus/preset-classic": 2.4.1 + "@docusaurus/core": 2.4.3 + "@docusaurus/module-type-aliases": 2.4.3 + "@docusaurus/preset-classic": 2.4.3 "@jscutlery/semver": 3.1.0 "@m8a/nestjs-typegoose": 11.1.0 - "@nestjs/apollo": ^12.0.7 - "@nestjs/cli": 10.1.17 - "@nestjs/common": 10.2.3 - "@nestjs/core": 10.2.3 - "@nestjs/graphql": ^12.0.8 - "@nestjs/jwt": 10.1.0 + "@nestjs/apollo": ^12.0.9 + "@nestjs/cli": 10.1.18 + "@nestjs/common": 10.2.7 + "@nestjs/core": 10.2.7 + "@nestjs/graphql": ^12.0.9 + "@nestjs/jwt": 10.1.1 "@nestjs/mongoose": 10.0.1 - "@nestjs/passport": 10.0.1 - "@nestjs/platform-express": 10.2.3 + "@nestjs/passport": 10.0.2 + "@nestjs/platform-express": 10.2.7 "@nestjs/schematics": 10.0.2 "@nestjs/sequelize": 10.0.0 - "@nestjs/testing": ^10.2.3 + "@nestjs/testing": ^10.2.7 "@nestjs/typeorm": ^10.0.0 "@nx-plus/docusaurus": ^15.0.0-rc.0 "@nx/eslint-plugin": 16.8.1 @@ -16809,9 +16900,9 @@ __metadata: "@nx/js": 16.8.1 "@nx/linter": 16.8.1 "@nx/node": 16.8.1 - "@typegoose/typegoose": ^11.4.1 - "@types/express": 4.17.17 - "@types/jest": 29.5.4 + "@typegoose/typegoose": ^11.5.0 + "@types/express": 4.17.18 + "@types/jest": 29.5.5 "@types/lodash.escaperegexp": 4.1.7 "@types/lodash.filter": 4.6.7 "@types/lodash.keys": 4.2.7 @@ -16819,39 +16910,39 @@ __metadata: "@types/lodash.omit": 4.5.7 "@types/lodash.pick": 4.4.7 "@types/lodash.pickby": 4.6.7 - "@types/node": 20.5.7 - "@types/passport-jwt": 3.0.9 - "@types/passport-local": 1.0.35 - "@types/pluralize": 0.0.30 - "@types/supertest": 2.0.12 - "@types/uuid": 9.0.3 - "@types/ws": 8.5.5 - "@typescript-eslint/eslint-plugin": 6.5.0 - "@typescript-eslint/parser": 6.5.0 + "@types/node": 20.8.2 + "@types/passport-jwt": 3.0.10 + "@types/passport-local": 1.0.36 + "@types/pluralize": 0.0.31 + "@types/supertest": 2.0.14 + "@types/uuid": 9.0.4 + "@types/ws": 8.5.6 + "@typescript-eslint/eslint-plugin": 6.7.4 + "@typescript-eslint/parser": 6.7.4 class-transformer: 0.5.1 class-validator: 0.14.0 clsx: ^2.0.0 dataloader: 2.2.2 - eslint: 8.48.0 + eslint: 8.50.0 eslint-config-airbnb: 19.0.4 eslint-config-airbnb-typescript: 17.1.0 eslint-config-prettier: 9.0.0 - eslint-import-resolver-typescript: 3.6.0 + eslint-import-resolver-typescript: 3.6.1 eslint-plugin-import: 2.28.1 - eslint-plugin-jest: 27.2.3 + eslint-plugin-jest: 27.4.2 eslint-plugin-prettier: 5.0.0 eslint-plugin-simple-import-sort: ^10.0.0 eslint-plugin-tsdoc: 0.2.17 - graphql: 16.8.0 + graphql: 16.8.1 graphql-query-complexity: 0.12.0 graphql-subscriptions: 2.0.0 graphql-tools: 9.0.0 husky: 8.0.3 - jest: 29.6.4 + jest: 29.7.0 jest-extended: 4.0.1 - mongodb-memory-server: 8.15.1 - mongoose: ^7.5.0 - mysql2: 3.6.0 + mongodb-memory-server: 8.16.0 + mongoose: ^7.5.4 + mysql2: 3.6.1 nx: 16.8.1 nx-cloud: 16.4.0 passport: 0.6.0 @@ -16859,13 +16950,13 @@ __metadata: passport-local: 1.0.0 pg: 8.11.3 prettier: 3.0.3 - prism-react-renderer: ^2.0.6 + prism-react-renderer: ^2.1.0 react: ^18.2.0 react-dom: ^18.2.0 reflect-metadata: ^0.1.13 - rimraf: 5.0.1 + rimraf: 5.0.5 rxjs: 7.8.1 - sequelize: 6.32.1 + sequelize: 6.33.0 sequelize-typescript: 2.1.5 sql-formatter: ^12.2.4 sqlite3: ^5.1.6 @@ -17908,14 +17999,7 @@ __metadata: languageName: node linkType: hard -"pg-connection-string@npm:^2.6.0": - version: 2.6.1 - resolution: "pg-connection-string@npm:2.6.1" - checksum: 882344a47e1ecf3a91383e0809bf2ac48facea97fcec0358d6e060e1cbcb8737acde419b4c86f05da4ce4a16634ee50fff1d2bb787d73b52ccbfde697243ad8a - languageName: node - linkType: hard - -"pg-connection-string@npm:^2.6.2": +"pg-connection-string@npm:^2.6.1, pg-connection-string@npm:^2.6.2": version: 2.6.2 resolution: "pg-connection-string@npm:2.6.2" checksum: 22265882c3b6f2320785378d0760b051294a684989163d5a1cde4009e64e84448d7bf67d9a7b9e7f69440c3ee9e2212f9aa10dd17ad6773f6143c6020cebbcb5 @@ -17998,7 +18082,7 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": +"picomatch@npm:2.3.1, picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf @@ -18579,14 +18663,14 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.6.3": - version: 29.6.3 - resolution: "pretty-format@npm:29.6.3" +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" dependencies: "@jest/schemas": ^29.6.3 ansi-styles: ^5.0.0 react-is: ^18.0.0 - checksum: 4e1c0db48e65571c22e80ff92123925ff8b3a2a89b71c3a1683cfde711004d492de32fe60c6bc10eea8bf6c678e5cbe544ac6c56cb8096e1eb7caf856928b1c4 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 languageName: node linkType: hard @@ -18606,15 +18690,15 @@ __metadata: languageName: node linkType: hard -"prism-react-renderer@npm:^2.0.6": - version: 2.0.6 - resolution: "prism-react-renderer@npm:2.0.6" +"prism-react-renderer@npm:^2.1.0": + version: 2.1.0 + resolution: "prism-react-renderer@npm:2.1.0" dependencies: "@types/prismjs": ^1.26.0 clsx: ^1.2.1 peerDependencies: react: ">=16.0.0" - checksum: d2202b79ddf01d308da3ba2f7f31a852fb0fb2e0290575d44e719af4c1d91fa913d04eb480fa3ba03e2d35d745ae806904270ffad00770511ec8bd80db67cb24 + checksum: 61b4eb22bdbf01005a0d7ec2a24a27b69e28f124a1fbbfc2adb4d7d41a7929ea94d5ce506a361dd5a230728402f02595d521d9a5286d74ec9b34be0896c513a5 languageName: node linkType: hard @@ -19598,14 +19682,14 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:5.0.1": - version: 5.0.1 - resolution: "rimraf@npm:5.0.1" +"rimraf@npm:5.0.5": + version: 5.0.5 + resolution: "rimraf@npm:5.0.5" dependencies: - glob: ^10.2.5 + glob: ^10.3.7 bin: - rimraf: dist/cjs/src/bin.js - checksum: bafce85391349a2d960847980bf9b5caa2a8887f481af630f1ea27e08288217293cec72d75e9a2ba35495c212789f66a7f3d23366ba6197026ab71c535126857 + rimraf: dist/esm/bin.mjs + checksum: d66eef829b2e23b16445f34e73d75c7b7cf4cbc8834b04720def1c8f298eb0753c3d76df77325fad79d0a2c60470525d95f89c2475283ad985fd7441c32732d1 languageName: node linkType: hard @@ -19855,7 +19939,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:^7.0.0, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.1, semver@npm:^7.5.3, semver@npm:^7.5.4": +"semver@npm:7.5.4, semver@npm:^7.0.0, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -19924,21 +20008,21 @@ __metadata: languageName: node linkType: hard -"sequelize@npm:6.32.1": - version: 6.32.1 - resolution: "sequelize@npm:6.32.1" +"sequelize@npm:6.33.0": + version: 6.33.0 + resolution: "sequelize@npm:6.33.0" dependencies: "@types/debug": ^4.1.8 "@types/validator": ^13.7.17 debug: ^4.3.4 - dottie: ^2.0.4 + dottie: ^2.0.6 inflection: ^1.13.4 lodash: ^4.17.21 moment: ^2.29.4 moment-timezone: ^0.5.43 - pg-connection-string: ^2.6.0 + pg-connection-string: ^2.6.1 retry-as-promised: ^7.0.4 - semver: ^7.5.1 + semver: ^7.5.4 sequelize-pool: ^7.1.0 toposort-class: ^1.0.1 uuid: ^8.3.2 @@ -19963,7 +20047,7 @@ __metadata: optional: true tedious: optional: true - checksum: 5284fd7a8eb8dfa8340c50c119b31006dda0931714d3e5a72bbfef3a07838018f935cc1b789a46486298043f10d553dbf9cf9cf60c46c6646ecfc9e9623a8b4c + checksum: 16bb4423f749137ce155e4a104332716be8ba529e74c379f9316c9ab53210a3169e464ee46b1b21465a1b9c6c9cc4311a3203980ea8a7d9a3b102b1c63a45159 languageName: node linkType: hard @@ -21348,13 +21432,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.6.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": - version: 2.6.0 - resolution: "tslib@npm:2.6.0" - checksum: c01066038f950016a18106ddeca4649b4d76caa76ec5a31e2a26e10586a59fceb4ee45e96719bf6c715648e7c14085a81fee5c62f7e9ebee68e77a5396e5538f - languageName: node - linkType: hard - "tslib@npm:2.6.2, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -21369,6 +21446,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": + version: 2.6.0 + resolution: "tslib@npm:2.6.0" + checksum: c01066038f950016a18106ddeca4649b4d76caa76ec5a31e2a26e10586a59fceb4ee45e96719bf6c715648e7c14085a81fee5c62f7e9ebee68e77a5396e5538f + languageName: node + linkType: hard + "tslib@npm:^2.6.1": version: 2.6.1 resolution: "tslib@npm:2.6.1" @@ -21605,16 +21689,6 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.1.6, typescript@npm:^4.6.4 || ^5.0.0, typescript@npm:~5.1.3": - version: 5.1.6 - resolution: "typescript@npm:5.1.6" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: b2f2c35096035fe1f5facd1e38922ccb8558996331405eb00a5111cc948b2e733163cc22fab5db46992aba7dd520fff637f2c1df4996ff0e134e77d3249a7350 - languageName: node - linkType: hard - "typescript@npm:5.2.2": version: 5.2.2 resolution: "typescript@npm:5.2.2" @@ -21625,13 +21699,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@5.1.6#~builtin, typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin, typescript@patch:typescript@~5.1.3#~builtin": +"typescript@npm:^4.6.4 || ^5.0.0, typescript@npm:~5.1.3": version: 5.1.6 - resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=7ad353" + resolution: "typescript@npm:5.1.6" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 21e88b0a0c0226f9cb9fd25b9626fb05b4c0f3fddac521844a13e1f30beb8f14e90bd409a9ac43c812c5946d714d6e0dee12d5d02dfc1c562c5aacfa1f49b606 + checksum: b2f2c35096035fe1f5facd1e38922ccb8558996331405eb00a5111cc948b2e733163cc22fab5db46992aba7dd520fff637f2c1df4996ff0e134e77d3249a7350 languageName: node linkType: hard @@ -21645,6 +21719,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin, typescript@patch:typescript@~5.1.3#~builtin": + version: 5.1.6 + resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=7ad353" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 21e88b0a0c0226f9cb9fd25b9626fb05b4c0f3fddac521844a13e1f30beb8f14e90bd409a9ac43c812c5946d714d6e0dee12d5d02dfc1c562c5aacfa1f49b606 + languageName: node + linkType: hard + "ua-parser-js@npm:^1.0.35": version: 1.0.35 resolution: "ua-parser-js@npm:1.0.35" @@ -22063,6 +22147,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^9.0.1": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 39931f6da74e307f51c0fb463dc2462807531dc80760a9bff1e35af4316131b4fc3203d16da60ae33f07fdca5b56f3f1dd662da0c99fea9aaeab2004780cc5f4 + languageName: node + linkType: hard + "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1"