super bug
This commit is contained in:
@@ -1,10 +1,5 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common'
|
import { Inject, Injectable } from '@nestjs/common'
|
||||||
import {
|
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||||
Pothos,
|
|
||||||
PothosRef,
|
|
||||||
PothosSchema,
|
|
||||||
SchemaBuilderToken,
|
|
||||||
} from '@smatch-corp/nestjs-pothos'
|
|
||||||
import { Builder } from '../Graphql/graphql.builder'
|
import { Builder } from '../Graphql/graphql.builder'
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import { PrismaService } from '../Prisma/prisma.service'
|
||||||
import { ChatRoomType } from '@prisma/client'
|
import { ChatRoomType } from '@prisma/client'
|
||||||
@@ -58,6 +53,10 @@ export class ChatroomSchema extends PothosSchema {
|
|||||||
meetingRoom: t.relation('meetingRoom', {
|
meetingRoom: t.relation('meetingRoom', {
|
||||||
description: 'The meeting room.',
|
description: 'The meeting room.',
|
||||||
}),
|
}),
|
||||||
|
lastActivity: t.expose('lastActivity', {
|
||||||
|
type: 'DateTime',
|
||||||
|
description: 'The last activity date and time.',
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -79,8 +78,7 @@ export class ChatroomSchema extends PothosSchema {
|
|||||||
|
|
||||||
chatRooms: t.prismaField({
|
chatRooms: t.prismaField({
|
||||||
type: [this.chatRoom()],
|
type: [this.chatRoom()],
|
||||||
description:
|
description: 'Retrieve a list of chat rooms with optional filtering, ordering, and pagination.',
|
||||||
'Retrieve a list of chat rooms with optional filtering, ordering, and pagination.',
|
|
||||||
args: this.builder.generator.findManyArgs('ChatRoom'),
|
args: this.builder.generator.findManyArgs('ChatRoom'),
|
||||||
resolve: async (query, _root, args, _ctx, _info) => {
|
resolve: async (query, _root, args, _ctx, _info) => {
|
||||||
return await this.prisma.chatRoom.findMany({
|
return await this.prisma.chatRoom.findMany({
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import { JSONObjectResolver } from 'graphql-scalars'
|
import { JSONObjectResolver } from 'graphql-scalars'
|
||||||
import PrismaPlugin, {
|
import PrismaPlugin, { PothosPrismaDatamodel, PrismaClient } from '@pothos/plugin-prisma'
|
||||||
PothosPrismaDatamodel,
|
|
||||||
PrismaClient,
|
|
||||||
} from '@pothos/plugin-prisma'
|
|
||||||
import { Request, Response } from 'express'
|
import { Request, Response } from 'express'
|
||||||
import SmartSubscriptionPlugin, {
|
import SmartSubscriptionPlugin, { subscribeOptionsFromIterator } from '@pothos/plugin-smart-subscriptions'
|
||||||
subscribeOptionsFromIterator,
|
|
||||||
} from '@pothos/plugin-smart-subscriptions'
|
|
||||||
import ZodPlugin from '@pothos/plugin-zod'
|
import ZodPlugin from '@pothos/plugin-zod'
|
||||||
import AuthzPlugin from '@pothos/plugin-authz'
|
import AuthzPlugin from '@pothos/plugin-authz'
|
||||||
import ErrorsPlugin from '@pothos/plugin-errors'
|
import ErrorsPlugin from '@pothos/plugin-errors'
|
||||||
@@ -90,22 +85,11 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
|||||||
|
|
||||||
constructor(private readonly prisma: PrismaClient) {
|
constructor(private readonly prisma: PrismaClient) {
|
||||||
super({
|
super({
|
||||||
plugins: [
|
plugins: [PrismaPlugin, PrismaUtils, SimpleObjectPlugin, SmartSubscriptionPlugin, RelayPlugin, ErrorsPlugin, AuthzPlugin, ZodPlugin],
|
||||||
PrismaPlugin,
|
|
||||||
PrismaUtils,
|
|
||||||
SimpleObjectPlugin,
|
|
||||||
SmartSubscriptionPlugin,
|
|
||||||
RelayPlugin,
|
|
||||||
ErrorsPlugin,
|
|
||||||
AuthzPlugin,
|
|
||||||
ZodPlugin,
|
|
||||||
],
|
|
||||||
smartSubscriptions: {
|
smartSubscriptions: {
|
||||||
debounceDelay: 1000,
|
debounceDelay: 1000,
|
||||||
...subscribeOptionsFromIterator((name, context) => {
|
...subscribeOptionsFromIterator((name, context) => {
|
||||||
return context.isSubscription
|
return context.isSubscription ? context.websocket.pubSub.asyncIterator(name) : context.http.pubSub.asyncIterator(name)
|
||||||
? context.websocket.pubSub.asyncIterator(name)
|
|
||||||
: context.http.pubSub.asyncIterator(name)
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
zod: {
|
zod: {
|
||||||
@@ -174,13 +158,9 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
|||||||
this.globalConnectionField('totalCount', (t) =>
|
this.globalConnectionField('totalCount', (t) =>
|
||||||
t.int({
|
t.int({
|
||||||
nullable: true,
|
nullable: true,
|
||||||
resolve: (parent) =>
|
resolve: (parent) => (typeof parent.totalCount === 'function' ? parent.totalCount() : parent.totalCount),
|
||||||
typeof parent.totalCount === 'function'
|
|
||||||
? parent.totalCount()
|
|
||||||
: parent.totalCount,
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export type BuilderTypes =
|
export type BuilderTypes = PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>
|
||||||
PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>
|
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common'
|
import { Inject, Injectable } from '@nestjs/common'
|
||||||
|
|
||||||
import {
|
import { type BaseEnum, type EnumRef, InputObjectRef, type InputType, type InputTypeParam, type SchemaTypes } from '@pothos/core'
|
||||||
type BaseEnum,
|
|
||||||
type EnumRef,
|
|
||||||
InputObjectRef,
|
|
||||||
type InputType,
|
|
||||||
type InputTypeParam,
|
|
||||||
type SchemaTypes,
|
|
||||||
} from '@pothos/core'
|
|
||||||
import { type PrismaModelTypes, getModel } from '@pothos/plugin-prisma'
|
import { type PrismaModelTypes, getModel } from '@pothos/plugin-prisma'
|
||||||
import type { FilterOps } from '@pothos/plugin-prisma-utils'
|
import type { FilterOps } from '@pothos/plugin-prisma-utils'
|
||||||
import * as Prisma from '@prisma/client'
|
import * as Prisma from '@prisma/client'
|
||||||
@@ -15,31 +8,15 @@ import { SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
|||||||
|
|
||||||
const filterOps = ['equals', 'in', 'notIn', 'not'] as const
|
const filterOps = ['equals', 'in', 'notIn', 'not'] as const
|
||||||
const sortableFilterProps = ['lt', 'lte', 'gt', 'gte'] as const
|
const sortableFilterProps = ['lt', 'lte', 'gt', 'gte'] as const
|
||||||
const stringFilterOps = [
|
const stringFilterOps = [...filterOps, 'contains', 'startsWith', 'endsWith', 'mode', 'search'] as const
|
||||||
...filterOps,
|
|
||||||
'contains',
|
|
||||||
'startsWith',
|
|
||||||
'endsWith',
|
|
||||||
'mode',
|
|
||||||
'search',
|
|
||||||
] as const
|
|
||||||
const sortableTypes = ['String', 'Int', 'Float', 'DateTime', 'BigInt'] as const
|
const sortableTypes = ['String', 'Int', 'Float', 'DateTime', 'BigInt'] as const
|
||||||
const listOps = ['every', 'some', 'none'] as const
|
const listOps = ['every', 'some', 'none'] as const
|
||||||
const scalarListOps = [
|
const scalarListOps = ['has', 'hasSome', 'hasEvery', 'isEmpty', 'equals'] as const
|
||||||
'has',
|
|
||||||
'hasSome',
|
|
||||||
'hasEvery',
|
|
||||||
'isEmpty',
|
|
||||||
'equals',
|
|
||||||
] as const
|
|
||||||
const JsonFilterOps = ['equals', 'in', 'notIn', 'not'] as const
|
const JsonFilterOps = ['equals', 'in', 'notIn', 'not'] as const
|
||||||
const EnumFilterOps = ['equals', 'not'] as const
|
const EnumFilterOps = ['equals', 'not'] as const
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
||||||
private refCache = new Map<
|
private refCache = new Map<InputType<Types> | string, Map<string, InputObjectRef<Types, unknown>>>()
|
||||||
InputType<Types> | string,
|
|
||||||
Map<string, InputObjectRef<Types, unknown>>
|
|
||||||
>()
|
|
||||||
|
|
||||||
private enumRefs = new Map<string, EnumRef<Types, unknown>>()
|
private enumRefs = new Map<string, EnumRef<Types, unknown>>()
|
||||||
|
|
||||||
@@ -49,9 +26,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
private builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
private builder: PothosSchemaTypes.SchemaBuilder<Types>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
findManyArgs<Name extends string & keyof Types['PrismaTypes']>(
|
findManyArgs<Name extends string & keyof Types['PrismaTypes']>(modelName: Name) {
|
||||||
modelName: Name,
|
|
||||||
) {
|
|
||||||
return this.builder.args((t) => ({
|
return this.builder.args((t) => ({
|
||||||
filter: t.field({
|
filter: t.field({
|
||||||
type: this.getWhere(modelName),
|
type: this.getWhere(modelName),
|
||||||
@@ -78,9 +53,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
findUniqueArgs<Name extends string & keyof Types['PrismaTypes']>(
|
findUniqueArgs<Name extends string & keyof Types['PrismaTypes']>(modelName: Name) {
|
||||||
modelName: Name,
|
|
||||||
) {
|
|
||||||
return this.builder.args((t) => ({
|
return this.builder.args((t) => ({
|
||||||
where: t.field({
|
where: t.field({
|
||||||
type: this.getWhereUnique(modelName),
|
type: this.getWhereUnique(modelName),
|
||||||
@@ -89,13 +62,8 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
getWhere<Name extends string & keyof Types['PrismaTypes']>(
|
getWhere<Name extends string & keyof Types['PrismaTypes']>(modelName: Name, without?: string[]) {
|
||||||
modelName: Name,
|
const withoutName = (without ?? []).map((name) => `Without${capitalize(name)}`).join('')
|
||||||
without?: string[],
|
|
||||||
) {
|
|
||||||
const withoutName = (without ?? [])
|
|
||||||
.map((name) => `Without${capitalize(name)}`)
|
|
||||||
.join('')
|
|
||||||
const fullName = `${modelName}${withoutName}Filter`
|
const fullName = `${modelName}${withoutName}Filter`
|
||||||
|
|
||||||
return this.getRef(modelName, fullName, () => {
|
return this.getRef(modelName, fullName, () => {
|
||||||
@@ -105,40 +73,21 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
name: fullName,
|
name: fullName,
|
||||||
fields: (() => {
|
fields: (() => {
|
||||||
const fields: Record<string, InputType<Types>> = {}
|
const fields: Record<string, InputType<Types>> = {}
|
||||||
const withoutFields = model.fields.filter((field) =>
|
const withoutFields = model.fields.filter((field) => without?.includes(field.name))
|
||||||
without?.includes(field.name),
|
|
||||||
)
|
|
||||||
|
|
||||||
model.fields
|
model.fields
|
||||||
.filter(
|
.filter((field) => !withoutFields.some((f) => f.name === field.name || f.relationFromFields?.includes(field.name)))
|
||||||
(field) =>
|
|
||||||
!withoutFields.some(
|
|
||||||
(f) =>
|
|
||||||
f.name === field.name ||
|
|
||||||
f.relationFromFields?.includes(field.name),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.forEach((field) => {
|
.forEach((field) => {
|
||||||
let type
|
let type
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
case 'scalar':
|
case 'scalar':
|
||||||
type = field.isList
|
type = field.isList ? this.getScalarListFilter(this.mapScalarType(field.type) as InputType<Types>) : this.getFilter(this.mapScalarType(field.type) as InputType<Types>)
|
||||||
? this.getScalarListFilter(
|
|
||||||
this.mapScalarType(field.type) as InputType<Types>,
|
|
||||||
)
|
|
||||||
: this.getFilter(
|
|
||||||
this.mapScalarType(field.type) as InputType<Types>,
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
case 'enum':
|
case 'enum':
|
||||||
type = field.isList
|
type = field.isList ? this.getScalarListFilter(this.getEnum(field.type)) : this.getFilter(this.getEnum(field.type))
|
||||||
? this.getScalarListFilter(this.getEnum(field.type))
|
|
||||||
: this.getFilter(this.getEnum(field.type))
|
|
||||||
break
|
break
|
||||||
case 'object':
|
case 'object':
|
||||||
type = field.isList
|
type = field.isList ? this.getListFilter(this.getWhere(field.type as Name)) : this.getWhere(field.type as Name)
|
||||||
? this.getListFilter(this.getWhere(field.type as Name))
|
|
||||||
: this.getWhere(field.type as Name)
|
|
||||||
break
|
break
|
||||||
case 'unsupported':
|
case 'unsupported':
|
||||||
break
|
break
|
||||||
@@ -154,15 +103,10 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
return fields
|
return fields
|
||||||
}) as never,
|
}) as never,
|
||||||
}) as InputObjectRef<
|
}) as InputObjectRef<Types, (PrismaModelTypes & Types['PrismaTypes'][Name])['Where']>
|
||||||
Types,
|
|
||||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Where']
|
|
||||||
>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getWhereUnique<Name extends string & keyof Types['PrismaTypes']>(
|
getWhereUnique<Name extends string & keyof Types['PrismaTypes']>(modelName: Name) {
|
||||||
modelName: Name,
|
|
||||||
) {
|
|
||||||
const name = `${modelName}UniqueFilter`
|
const name = `${modelName}UniqueFilter`
|
||||||
|
|
||||||
return this.getRef(modelName, name, () => {
|
return this.getRef(modelName, name, () => {
|
||||||
@@ -173,15 +117,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
const fields: Record<string, InputType<Types>> = {}
|
const fields: Record<string, InputType<Types>> = {}
|
||||||
|
|
||||||
model.fields
|
model.fields
|
||||||
.filter(
|
.filter((field) => field.isUnique || field.isId || model.uniqueIndexes.some((index) => index.fields.includes(field.name)) || model.primaryKey?.fields.includes(field.name))
|
||||||
(field) =>
|
|
||||||
field.isUnique ||
|
|
||||||
field.isId ||
|
|
||||||
model.uniqueIndexes.some((index) =>
|
|
||||||
index.fields.includes(field.name),
|
|
||||||
) ||
|
|
||||||
model.primaryKey?.fields.includes(field.name),
|
|
||||||
)
|
|
||||||
.forEach((field) => {
|
.forEach((field) => {
|
||||||
let type
|
let type
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
@@ -207,15 +143,10 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
return fields
|
return fields
|
||||||
}) as never,
|
}) as never,
|
||||||
}) as InputObjectRef<
|
}) as InputObjectRef<Types, (PrismaModelTypes & Types['PrismaTypes'][Name])['WhereUnique']>
|
||||||
Types,
|
|
||||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['WhereUnique']
|
|
||||||
>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getOrderBy<Name extends string & keyof Types['PrismaTypes']>(
|
getOrderBy<Name extends string & keyof Types['PrismaTypes']>(modelName: Name) {
|
||||||
modelName: Name,
|
|
||||||
) {
|
|
||||||
const name = `${modelName}OrderBy`
|
const name = `${modelName}OrderBy`
|
||||||
return this.getRef(modelName, name, () => {
|
return this.getRef(modelName, name, () => {
|
||||||
const model = getModel(modelName, this.builder)
|
const model = getModel(modelName, this.builder)
|
||||||
@@ -252,13 +183,8 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getCreateInput<Name extends string & keyof Types['PrismaTypes']>(
|
getCreateInput<Name extends string & keyof Types['PrismaTypes']>(modelName: Name, without?: string[]) {
|
||||||
modelName: Name,
|
const withoutName = (without ?? []).map((name) => `Without${capitalize(name)}`).join('')
|
||||||
without?: string[],
|
|
||||||
) {
|
|
||||||
const withoutName = (without ?? [])
|
|
||||||
.map((name) => `Without${capitalize(name)}`)
|
|
||||||
.join('')
|
|
||||||
const fullName = `${modelName}Create${withoutName}Input`
|
const fullName = `${modelName}Create${withoutName}Input`
|
||||||
|
|
||||||
return this.getRef(modelName, fullName, () => {
|
return this.getRef(modelName, fullName, () => {
|
||||||
@@ -267,22 +193,11 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
name: fullName,
|
name: fullName,
|
||||||
fields: (() => {
|
fields: (() => {
|
||||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||||
const withoutFields = model.fields.filter((field) =>
|
const withoutFields = model.fields.filter((field) => without?.includes(field.name))
|
||||||
without?.includes(field.name),
|
const relationIds = model.fields.flatMap((field) => field.relationFromFields ?? [])
|
||||||
)
|
|
||||||
const relationIds = model.fields.flatMap(
|
|
||||||
(field) => field.relationFromFields ?? [],
|
|
||||||
)
|
|
||||||
|
|
||||||
model.fields
|
model.fields
|
||||||
.filter(
|
.filter((field) => !withoutFields.some((f) => f.name === field.name || f.relationFromFields?.includes(field.name)) && !relationIds.includes(field.name))
|
||||||
(field) =>
|
|
||||||
!withoutFields.some(
|
|
||||||
(f) =>
|
|
||||||
f.name === field.name ||
|
|
||||||
f.relationFromFields?.includes(field.name),
|
|
||||||
) && !relationIds.includes(field.name),
|
|
||||||
)
|
|
||||||
.forEach((field) => {
|
.forEach((field) => {
|
||||||
let type
|
let type
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
@@ -308,58 +223,33 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
return fields
|
return fields
|
||||||
}) as never,
|
}) as never,
|
||||||
}) as InputObjectRef<
|
}) as InputObjectRef<Types, (PrismaModelTypes & Types['PrismaTypes'][Name])['Create']>
|
||||||
Types,
|
|
||||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Create']
|
|
||||||
>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getCreateRelationInput<
|
getCreateRelationInput<Name extends string & keyof Types['PrismaTypes'], Relation extends Model['RelationName'], Model extends PrismaModelTypes = Types['PrismaTypes'][Name] extends PrismaModelTypes ? Types['PrismaTypes'][Name] : never>(
|
||||||
Name extends string & keyof Types['PrismaTypes'],
|
modelName: Name,
|
||||||
Relation extends Model['RelationName'],
|
relation: Relation,
|
||||||
Model extends
|
) {
|
||||||
PrismaModelTypes = Types['PrismaTypes'][Name] extends PrismaModelTypes
|
return this.getRef(`${modelName}${capitalize(relation)}`, 'CreateRelationInput', () => {
|
||||||
? Types['PrismaTypes'][Name]
|
|
||||||
: never,
|
|
||||||
>(modelName: Name, relation: Relation) {
|
|
||||||
return this.getRef(
|
|
||||||
`${modelName}${capitalize(relation)}`,
|
|
||||||
'CreateRelationInput',
|
|
||||||
() => {
|
|
||||||
const model = getModel(modelName, this.builder)
|
const model = getModel(modelName, this.builder)
|
||||||
return this.builder.prismaCreateRelation(modelName, relation, {
|
return this.builder.prismaCreateRelation(modelName, relation, {
|
||||||
fields: () => {
|
fields: () => {
|
||||||
const relationField = model.fields.find(
|
const relationField = model.fields.find((field) => field.name === relation)!
|
||||||
(field) => field.name === relation,
|
|
||||||
)!
|
|
||||||
const relatedModel = getModel(relationField.type, this.builder)
|
const relatedModel = getModel(relationField.type, this.builder)
|
||||||
const relatedFieldName = relatedModel.fields.find(
|
const relatedFieldName = relatedModel.fields.find((field) => field.relationName === relationField.relationName)!
|
||||||
(field) => field.relationName === relationField.relationName,
|
|
||||||
)!
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
create: this.getCreateInput(relationField.type as Name, [
|
create: this.getCreateInput(relationField.type as Name, [relatedFieldName.name]),
|
||||||
relatedFieldName.name,
|
|
||||||
]),
|
|
||||||
connect: this.getWhereUnique(relationField.type as Name),
|
connect: this.getWhereUnique(relationField.type as Name),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} as never) as InputObjectRef<
|
} as never) as InputObjectRef<Types, NonNullable<Model['Create'][Relation & keyof Model['Update']]>>
|
||||||
Types,
|
})
|
||||||
NonNullable<Model['Create'][Relation & keyof Model['Update']]>
|
|
||||||
>
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCreateManyInput<Name extends string & keyof Types['PrismaTypes']>(
|
getCreateManyInput<Name extends string & keyof Types['PrismaTypes']>(modelName: Name, without?: string[]) {
|
||||||
modelName: Name,
|
const withoutName = (without ?? []).map((name) => `Without${capitalize(name)}`).join('')
|
||||||
without?: string[],
|
|
||||||
) {
|
|
||||||
const withoutName = (without ?? [])
|
|
||||||
.map((name) => `Without${capitalize(name)}`)
|
|
||||||
.join('')
|
|
||||||
const fullName = `${modelName}Create${withoutName}Input`
|
const fullName = `${modelName}Create${withoutName}Input`
|
||||||
|
|
||||||
return this.getRef(modelName, fullName, () => {
|
return this.getRef(modelName, fullName, () => {
|
||||||
@@ -369,22 +259,11 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
name: fullName,
|
name: fullName,
|
||||||
fields: (() => {
|
fields: (() => {
|
||||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||||
const withoutFields = model.fields.filter((field) =>
|
const withoutFields = model.fields.filter((field) => without?.includes(field.name))
|
||||||
without?.includes(field.name),
|
const relationIds = model.fields.flatMap((field) => field.relationFromFields ?? [])
|
||||||
)
|
|
||||||
const relationIds = model.fields.flatMap(
|
|
||||||
(field) => field.relationFromFields ?? [],
|
|
||||||
)
|
|
||||||
|
|
||||||
model.fields
|
model.fields
|
||||||
.filter(
|
.filter((field) => !withoutFields.some((f) => f.name === field.name || f.relationFromFields?.includes(field.name)) && !relationIds.includes(field.name))
|
||||||
(field) =>
|
|
||||||
!withoutFields.some(
|
|
||||||
(f) =>
|
|
||||||
f.name === field.name ||
|
|
||||||
f.relationFromFields?.includes(field.name),
|
|
||||||
) && !relationIds.includes(field.name),
|
|
||||||
)
|
|
||||||
.forEach((field) => {
|
.forEach((field) => {
|
||||||
let type
|
let type
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
@@ -407,20 +286,12 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
return fields
|
return fields
|
||||||
}) as never,
|
}) as never,
|
||||||
}) as InputObjectRef<
|
}) as InputObjectRef<Types, (PrismaModelTypes & Types['PrismaTypes'][Name])['Create']>
|
||||||
Types,
|
|
||||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Create']
|
|
||||||
>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getUpdateInput<Name extends string & keyof Types['PrismaTypes']>(
|
getUpdateInput<Name extends string & keyof Types['PrismaTypes']>(modelName: Name, without?: string[]) {
|
||||||
modelName: Name,
|
const withoutName = (without ?? []).map((name) => `Without${capitalize(name)}`).join('')
|
||||||
without?: string[],
|
|
||||||
) {
|
|
||||||
const withoutName = (without ?? [])
|
|
||||||
.map((name) => `Without${capitalize(name)}`)
|
|
||||||
.join('')
|
|
||||||
const fullName = `${modelName}Update${withoutName}Input`
|
const fullName = `${modelName}Update${withoutName}Input`
|
||||||
|
|
||||||
return this.getRef(modelName, fullName, () => {
|
return this.getRef(modelName, fullName, () => {
|
||||||
@@ -429,22 +300,11 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
name: fullName,
|
name: fullName,
|
||||||
fields: (() => {
|
fields: (() => {
|
||||||
const fields: Record<string, InputTypeParam<Types>> = {}
|
const fields: Record<string, InputTypeParam<Types>> = {}
|
||||||
const withoutFields = model.fields.filter((field) =>
|
const withoutFields = model.fields.filter((field) => without?.includes(field.name))
|
||||||
without?.includes(field.name),
|
const relationIds = model.fields.flatMap((field) => field.relationFromFields ?? [])
|
||||||
)
|
|
||||||
const relationIds = model.fields.flatMap(
|
|
||||||
(field) => field.relationFromFields ?? [],
|
|
||||||
)
|
|
||||||
|
|
||||||
model.fields
|
model.fields
|
||||||
.filter(
|
.filter((field) => !withoutFields.some((f) => f.name === field.name || f.relationFromFields?.includes(field.name)) && !relationIds.includes(field.name))
|
||||||
(field) =>
|
|
||||||
!withoutFields.some(
|
|
||||||
(f) =>
|
|
||||||
f.name === field.name ||
|
|
||||||
f.relationFromFields?.includes(field.name),
|
|
||||||
) && !relationIds.includes(field.name),
|
|
||||||
)
|
|
||||||
.forEach((field) => {
|
.forEach((field) => {
|
||||||
let type
|
let type
|
||||||
switch (field.kind) {
|
switch (field.kind) {
|
||||||
@@ -470,45 +330,27 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
return fields
|
return fields
|
||||||
}) as never,
|
}) as never,
|
||||||
}) as InputObjectRef<
|
}) as InputObjectRef<Types, (PrismaModelTypes & Types['PrismaTypes'][Name])['Update']>
|
||||||
Types,
|
|
||||||
(PrismaModelTypes & Types['PrismaTypes'][Name])['Update']
|
|
||||||
>
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getUpdateRelationInput<
|
getUpdateRelationInput<Name extends string & keyof Types['PrismaTypes'], Relation extends Model['RelationName'], Model extends PrismaModelTypes = Types['PrismaTypes'][Name] extends PrismaModelTypes ? Types['PrismaTypes'][Name] : never>(
|
||||||
Name extends string & keyof Types['PrismaTypes'],
|
modelName: Name,
|
||||||
Relation extends Model['RelationName'],
|
relation: Relation,
|
||||||
Model extends
|
) {
|
||||||
PrismaModelTypes = Types['PrismaTypes'][Name] extends PrismaModelTypes
|
return this.getRef(`${modelName}${capitalize(relation)}`, 'UpdateRelationInput', () => {
|
||||||
? Types['PrismaTypes'][Name]
|
|
||||||
: never,
|
|
||||||
>(modelName: Name, relation: Relation) {
|
|
||||||
return this.getRef(
|
|
||||||
`${modelName}${capitalize(relation)}`,
|
|
||||||
'UpdateRelationInput',
|
|
||||||
() => {
|
|
||||||
const model = getModel(modelName, this.builder)
|
const model = getModel(modelName, this.builder)
|
||||||
return this.builder.prismaUpdateRelation(modelName, relation, {
|
return this.builder.prismaUpdateRelation(modelName, relation, {
|
||||||
fields: () => {
|
fields: () => {
|
||||||
const relationField = model.fields.find(
|
const relationField = model.fields.find((field) => field.name === relation)!
|
||||||
(field) => field.name === relation,
|
|
||||||
)!
|
|
||||||
const relatedModel = getModel(relationField.type, this.builder)
|
const relatedModel = getModel(relationField.type, this.builder)
|
||||||
const relatedFieldName = relatedModel.fields.find(
|
const relatedFieldName = relatedModel.fields.find((field) => field.relationName === relationField.relationName)!.name
|
||||||
(field) => field.relationName === relationField.relationName,
|
|
||||||
)!.name
|
|
||||||
|
|
||||||
if (relationField.isList) {
|
if (relationField.isList) {
|
||||||
return {
|
return {
|
||||||
create: this.getCreateInput(relationField.type as Name, [
|
create: this.getCreateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
createMany: {
|
createMany: {
|
||||||
skipDuplicates: 'Boolean',
|
skipDuplicates: 'Boolean',
|
||||||
data: this.getCreateInput(relationField.type as Name, [
|
data: this.getCreateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
set: this.getWhereUnique(relationField.type as Name),
|
set: this.getWhereUnique(relationField.type as Name),
|
||||||
disconnect: this.getWhereUnique(relationField.type as Name),
|
disconnect: this.getWhereUnique(relationField.type as Name),
|
||||||
@@ -516,42 +358,26 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
connect: this.getWhereUnique(relationField.type as Name),
|
connect: this.getWhereUnique(relationField.type as Name),
|
||||||
update: {
|
update: {
|
||||||
where: this.getWhereUnique(relationField.type as Name),
|
where: this.getWhereUnique(relationField.type as Name),
|
||||||
data: this.getUpdateInput(relationField.type as Name, [
|
data: this.getUpdateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
updateMany: {
|
updateMany: {
|
||||||
where: this.getWhere(relationField.type as Name, [
|
where: this.getWhere(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
data: this.getUpdateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
]),
|
|
||||||
data: this.getUpdateInput(relationField.type as Name, [
|
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
deleteMany: this.getWhere(relationField.type as Name, [
|
deleteMany: this.getWhere(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
create: this.getCreateInput(relationField.type as Name, [
|
create: this.getCreateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
relatedFieldName,
|
update: this.getUpdateInput(relationField.type as Name, [relatedFieldName]),
|
||||||
]),
|
|
||||||
update: this.getUpdateInput(relationField.type as Name, [
|
|
||||||
relatedFieldName,
|
|
||||||
]),
|
|
||||||
connect: this.getWhereUnique(relationField.type as Name),
|
connect: this.getWhereUnique(relationField.type as Name),
|
||||||
disconnect: relationField.isRequired ? undefined : 'Boolean',
|
disconnect: relationField.isRequired ? undefined : 'Boolean',
|
||||||
delete: relationField.isRequired ? undefined : 'Boolean',
|
delete: relationField.isRequired ? undefined : 'Boolean',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} as never) as InputObjectRef<
|
} as never) as InputObjectRef<Types, NonNullable<Model['Update'][Relation & keyof Model['Update']]>>
|
||||||
Types,
|
})
|
||||||
NonNullable<Model['Update'][Relation & keyof Model['Update']]>
|
|
||||||
>
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFilter(type: InputType<Types>) {
|
private getFilter(type: InputType<Types>) {
|
||||||
@@ -596,12 +422,9 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
|
|
||||||
private getEnum(name: string) {
|
private getEnum(name: string) {
|
||||||
if (!this.enumRefs.has(name)) {
|
if (!this.enumRefs.has(name)) {
|
||||||
const enumRef = this.builder.enumType(
|
const enumRef = this.builder.enumType((Prisma as unknown as Record<string, BaseEnum>)[name], {
|
||||||
(Prisma as unknown as Record<string, BaseEnum>)[name],
|
|
||||||
{
|
|
||||||
name,
|
name,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
this.enumRefs.set(name, enumRef)
|
this.enumRefs.set(name, enumRef)
|
||||||
}
|
}
|
||||||
@@ -623,11 +446,7 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRef<T extends InputObjectRef<Types, unknown>>(
|
private getRef<T extends InputObjectRef<Types, unknown>>(key: InputType<Types> | string, name: string, create: () => T): T {
|
||||||
key: InputType<Types> | string,
|
|
||||||
name: string,
|
|
||||||
create: () => T,
|
|
||||||
): T {
|
|
||||||
if (!this.refCache.has(key)) {
|
if (!this.refCache.has(key)) {
|
||||||
this.refCache.set(key, new Map())
|
this.refCache.set(key, new Map())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,8 @@
|
|||||||
import { Inject, Injectable, Logger } from '@nestjs/common'
|
import { Inject, Injectable, Logger } from '@nestjs/common'
|
||||||
import {
|
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||||
Pothos,
|
|
||||||
PothosRef,
|
|
||||||
PothosSchema,
|
|
||||||
SchemaBuilderToken,
|
|
||||||
} from '@smatch-corp/nestjs-pothos'
|
|
||||||
import { Builder, SchemaContext } from '../Graphql/graphql.builder'
|
import { Builder, SchemaContext } from '../Graphql/graphql.builder'
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import { PrismaService } from '../Prisma/prisma.service'
|
||||||
import {
|
import { ChatRoomType, Message, MessageContextType, MessageType } from '@prisma/client'
|
||||||
ChatRoomType,
|
|
||||||
Message,
|
|
||||||
MessageContextType,
|
|
||||||
MessageType,
|
|
||||||
} from '@prisma/client'
|
|
||||||
import { DateTimeUtils } from '../common/utils/datetime.utils'
|
import { DateTimeUtils } from '../common/utils/datetime.utils'
|
||||||
import { PubSubEvent } from '../common/pubsub/pubsub-event'
|
import { PubSubEvent } from '../common/pubsub/pubsub-event'
|
||||||
|
|
||||||
@@ -85,8 +75,7 @@ export class MessageSchema extends PothosSchema {
|
|||||||
}),
|
}),
|
||||||
messages: t.prismaField({
|
messages: t.prismaField({
|
||||||
type: [this.message()],
|
type: [this.message()],
|
||||||
description:
|
description: 'Retrieve a list of messages with optional filtering, ordering, and pagination.',
|
||||||
'Retrieve a list of messages with optional filtering, ordering, and pagination.',
|
|
||||||
args: this.builder.generator.findManyArgs('Message'),
|
args: this.builder.generator.findManyArgs('Message'),
|
||||||
resolve: async (query, _root, args) => {
|
resolve: async (query, _root, args) => {
|
||||||
return await this.prisma.message.findMany({
|
return await this.prisma.message.findMany({
|
||||||
@@ -118,15 +107,7 @@ export class MessageSchema extends PothosSchema {
|
|||||||
description: 'Send a message to a chat room.',
|
description: 'Send a message to a chat room.',
|
||||||
args: {
|
args: {
|
||||||
input: t.arg({
|
input: t.arg({
|
||||||
type: this.builder.generator.getCreateInput('Message', [
|
type: this.builder.generator.getCreateInput('Message', ['id', 'senderId', 'sender', 'sentAt', 'context', 'recipient', 'recipientId']),
|
||||||
'id',
|
|
||||||
'senderId',
|
|
||||||
'sender',
|
|
||||||
'sentAt',
|
|
||||||
'context',
|
|
||||||
'recipient',
|
|
||||||
'recipientId',
|
|
||||||
]),
|
|
||||||
description: 'The message to send.',
|
description: 'The message to send.',
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
@@ -174,20 +155,26 @@ export class MessageSchema extends PothosSchema {
|
|||||||
throw new Error('Content cannot be longer than 1024 characters')
|
throw new Error('Content cannot be longer than 1024 characters')
|
||||||
}
|
}
|
||||||
args.input.context = messageContext
|
args.input.context = messageContext
|
||||||
const message = await this.prisma.message.create({
|
const lastActivity = DateTimeUtils.now()
|
||||||
|
const message = await this.prisma.$transaction(async (tx) => {
|
||||||
|
const message = await tx.message.create({
|
||||||
...query,
|
...query,
|
||||||
data: args.input,
|
data: args.input,
|
||||||
})
|
})
|
||||||
ctx.http.pubSub.publish(
|
await tx.chatRoom.update({
|
||||||
`${PubSubEvent.MESSAGE_SENT}.${message.chatRoomId}`,
|
where: {
|
||||||
message,
|
id: message.chatRoomId!,
|
||||||
)
|
},
|
||||||
|
data: {
|
||||||
|
lastActivity: lastActivity.toJSDate(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return message
|
||||||
|
})
|
||||||
|
ctx.http.pubSub.publish(`${PubSubEvent.MESSAGE_SENT}.${message.chatRoomId}`, message)
|
||||||
// publish to new message subscribers
|
// publish to new message subscribers
|
||||||
userIds.forEach((userId: string) => {
|
userIds.forEach((userId: string) => {
|
||||||
ctx.http.pubSub.publish(
|
ctx.http.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${userId}`, message)
|
||||||
`${PubSubEvent.NEW_MESSAGE}.${userId}`,
|
|
||||||
message,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
return message
|
return message
|
||||||
},
|
},
|
||||||
@@ -209,9 +196,7 @@ export class MessageSchema extends PothosSchema {
|
|||||||
const {
|
const {
|
||||||
websocket: { pubSub },
|
websocket: { pubSub },
|
||||||
} = ctx
|
} = ctx
|
||||||
return pubSub.asyncIterator([
|
return pubSub.asyncIterator([`${PubSubEvent.MESSAGE_SENT}.${args.chatRoomId}`]) as unknown as AsyncIterable<Message>
|
||||||
`${PubSubEvent.MESSAGE_SENT}.${args.chatRoomId}`,
|
|
||||||
]) as unknown as AsyncIterable<Message>
|
|
||||||
},
|
},
|
||||||
resolve: (payload: Message) => payload,
|
resolve: (payload: Message) => payload,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
import { Inject, Injectable, Logger } from '@nestjs/common'
|
import { Inject, Injectable, Logger } from '@nestjs/common'
|
||||||
import {
|
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||||
Pothos,
|
|
||||||
PothosRef,
|
|
||||||
PothosSchema,
|
|
||||||
SchemaBuilderToken,
|
|
||||||
} from '@smatch-corp/nestjs-pothos'
|
|
||||||
import { Builder, SchemaContext } from '../Graphql/graphql.builder'
|
import { Builder, SchemaContext } from '../Graphql/graphql.builder'
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import { PrismaService } from '../Prisma/prisma.service'
|
||||||
import { clerkClient } from '@clerk/express'
|
import { clerkClient } from '@clerk/express'
|
||||||
import { UnauthorizedException } from '@nestjs/common'
|
import { UnauthorizedException } from '@nestjs/common'
|
||||||
import { MailService } from '../Mail/mail.service'
|
import { MailService } from '../Mail/mail.service'
|
||||||
import { MessageSchema } from 'src/Message/message.schema'
|
import { MessageSchema } from 'src/Message/message.schema'
|
||||||
import { Message, MessageContextType, MessageType } from '@prisma/client'
|
import { ChatRoom, Message, MessageContextType, MessageType, Role } from '@prisma/client'
|
||||||
import { PubSubEvent } from 'src/common/pubsub/pubsub-event'
|
import { PubSubEvent } from 'src/common/pubsub/pubsub-event'
|
||||||
import { DateTimeUtils } from 'src/common/utils/datetime.utils'
|
import { DateTimeUtils } from 'src/common/utils/datetime.utils'
|
||||||
import { JsonValue } from '@prisma/client/runtime/library'
|
import { JsonValue } from '@prisma/client/runtime/library'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
type UserWithChatRooms = {
|
||||||
|
name: string
|
||||||
|
id: string
|
||||||
|
email: string
|
||||||
|
phoneNumber: string | null
|
||||||
|
bankBin: string | null
|
||||||
|
bankAccountNumber: string | null
|
||||||
|
packageValue: number
|
||||||
|
role: Role
|
||||||
|
avatarUrl: string | null
|
||||||
|
createdAt: Date
|
||||||
|
updatedAt: Date
|
||||||
|
customerChatRoom?: ChatRoom[]
|
||||||
|
mentorChatRoom?: ChatRoom[]
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserSchema extends PothosSchema {
|
export class UserSchema extends PothosSchema {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -148,18 +160,39 @@ export class UserSchema extends PothosSchema {
|
|||||||
}),
|
}),
|
||||||
me: t.prismaField({
|
me: t.prismaField({
|
||||||
description: 'Retrieve the current user in context.',
|
description: 'Retrieve the current user in context.',
|
||||||
type: this.user(),
|
type: this.user() || 'Json',
|
||||||
|
args: {
|
||||||
|
includeChatRoom: t.arg({ type: 'Boolean', required: false }),
|
||||||
|
},
|
||||||
resolve: async (_query, _root, _args, ctx) => {
|
resolve: async (_query, _root, _args, ctx) => {
|
||||||
if (ctx.isSubscription) {
|
if (ctx.isSubscription) {
|
||||||
throw new Error('Not allowed')
|
throw new Error('Not allowed')
|
||||||
}
|
}
|
||||||
return ctx.http.me
|
let user = ctx.http.me as UserWithChatRooms
|
||||||
|
if (!user?.name) {
|
||||||
|
throw new Error('User not found')
|
||||||
|
}
|
||||||
|
if (_args.includeChatRoom) {
|
||||||
|
const customerChatRoom = await this.prisma.chatRoom.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [{ customerId: ctx.http.me?.id }, { mentorId: ctx.http.me?.id }],
|
||||||
|
},
|
||||||
|
distinct: ['id'],
|
||||||
|
orderBy: {
|
||||||
|
lastActivity: 'desc',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
user = {
|
||||||
|
...user,
|
||||||
|
customerChatRoom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
users: t.prismaField({
|
users: t.prismaField({
|
||||||
description:
|
description: 'Retrieve a list of users with optional filtering, ordering, and pagination.',
|
||||||
'Retrieve a list of users with optional filtering, ordering, and pagination.',
|
|
||||||
type: [this.user()],
|
type: [this.user()],
|
||||||
args: this.builder.generator.findManyArgs('User'),
|
args: this.builder.generator.findManyArgs('User'),
|
||||||
resolve: async (query, _root, args) => {
|
resolve: async (query, _root, args) => {
|
||||||
@@ -291,8 +324,7 @@ export class UserSchema extends PothosSchema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buffer = Buffer.concat(chunks)
|
const buffer = Buffer.concat(chunks)
|
||||||
const { id: userId, imageUrl } =
|
const { id: userId, imageUrl } = await clerkClient.users.updateUserProfileImage(id, {
|
||||||
await clerkClient.users.updateUserProfileImage(id, {
|
|
||||||
file: new Blob([buffer]),
|
file: new Blob([buffer]),
|
||||||
})
|
})
|
||||||
await this.prisma.user.update({
|
await this.prisma.user.update({
|
||||||
@@ -371,14 +403,9 @@ export class UserSchema extends PothosSchema {
|
|||||||
throw new Error(`User ${args.email} not found`)
|
throw new Error(`User ${args.email} not found`)
|
||||||
}
|
}
|
||||||
// send email
|
// send email
|
||||||
await this.mailService.sendTemplateEmail(
|
await this.mailService.sendTemplateEmail([args.email], 'Thông báo chọn lựa quản trị viên cho người điều hành', 'ModeratorInvitation', {
|
||||||
[args.email],
|
|
||||||
'Thông báo chọn lựa quản trị viên cho người điều hành',
|
|
||||||
'ModeratorInvitation',
|
|
||||||
{
|
|
||||||
USER_NAME: user.name,
|
USER_NAME: user.name,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
return 'Invited'
|
return 'Invited'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -415,10 +442,7 @@ export class UserSchema extends PothosSchema {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
// publish message
|
// publish message
|
||||||
await ctx.http.pubSub.publish(
|
await ctx.http.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`, message)
|
||||||
`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`,
|
|
||||||
message,
|
|
||||||
)
|
|
||||||
return message
|
return message
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -433,9 +457,7 @@ export class UserSchema extends PothosSchema {
|
|||||||
const {
|
const {
|
||||||
websocket: { pubSub },
|
websocket: { pubSub },
|
||||||
} = ctx
|
} = ctx
|
||||||
return pubSub.asyncIterator([
|
return pubSub.asyncIterator([`${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`]) as unknown as AsyncIterable<Message>
|
||||||
`${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`,
|
|
||||||
]) as unknown as AsyncIterable<Message>
|
|
||||||
},
|
},
|
||||||
resolve: async (payload: Message) => payload,
|
resolve: async (payload: Message) => payload,
|
||||||
}),
|
}),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user