Refactor backend and add exception handlers (#189)

This commit is contained in:
Charles Bochet 2023-06-04 00:21:36 +02:00 committed by GitHub
parent a2fe159c2c
commit bbc80cd543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 459 additions and 899 deletions

View File

@ -22,10 +22,6 @@ export type AffectedRows = {
count: Scalars['Int'];
};
export type BoolFieldUpdateOperationsInput = {
set?: InputMaybe<Scalars['Boolean']>;
};
export type BoolFilter = {
equals?: InputMaybe<Scalars['Boolean']>;
not?: InputMaybe<NestedBoolFilter>;
@ -54,20 +50,6 @@ export type CommentCreateInput = {
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CommentCreateManyAuthorInput = {
body: Scalars['String'];
commentThreadId: Scalars['String'];
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
id: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CommentCreateManyAuthorInputEnvelope = {
data: Array<CommentCreateManyAuthorInput>;
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
};
export type CommentCreateManyCommentThreadInput = {
authorId: Scalars['String'];
body: Scalars['String'];
@ -82,31 +64,10 @@ export type CommentCreateManyCommentThreadInputEnvelope = {
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
};
export type CommentCreateNestedManyWithoutAuthorInput = {
connect?: InputMaybe<Array<CommentWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<CommentCreateOrConnectWithoutAuthorInput>>;
create?: InputMaybe<Array<CommentCreateWithoutAuthorInput>>;
createMany?: InputMaybe<CommentCreateManyAuthorInputEnvelope>;
};
export type CommentCreateNestedManyWithoutCommentThreadInput = {
createMany?: InputMaybe<CommentCreateManyCommentThreadInputEnvelope>;
};
export type CommentCreateOrConnectWithoutAuthorInput = {
create: CommentCreateWithoutAuthorInput;
where: CommentWhereUniqueInput;
};
export type CommentCreateWithoutAuthorInput = {
body: Scalars['String'];
commentThread: CommentThreadCreateNestedOneWithoutCommentsInput;
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
id: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CommentListRelationFilter = {
every?: InputMaybe<CommentWhereInput>;
none?: InputMaybe<CommentWhereInput>;
@ -117,19 +78,6 @@ export type CommentOrderByRelationAggregateInput = {
_count?: InputMaybe<SortOrder>;
};
export type CommentScalarWhereInput = {
AND?: InputMaybe<Array<CommentScalarWhereInput>>;
NOT?: InputMaybe<Array<CommentScalarWhereInput>>;
OR?: InputMaybe<Array<CommentScalarWhereInput>>;
authorId?: InputMaybe<StringFilter>;
body?: InputMaybe<StringFilter>;
commentThreadId?: InputMaybe<StringFilter>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
id?: InputMaybe<StringFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type CommentThread = {
__typename?: 'CommentThread';
commentThreadTargets?: Maybe<Array<CommentThreadTarget>>;
@ -153,19 +101,6 @@ export type CommentThreadCreateNestedOneWithoutCommentsInput = {
connect?: InputMaybe<CommentThreadWhereUniqueInput>;
};
export type CommentThreadCreateOrConnectWithoutCommentsInput = {
create: CommentThreadCreateWithoutCommentsInput;
where: CommentThreadWhereUniqueInput;
};
export type CommentThreadCreateWithoutCommentsInput = {
commentThreadTargets?: InputMaybe<CommentThreadTargetCreateNestedManyWithoutCommentThreadInput>;
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
id: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CommentThreadRelationFilter = {
is?: InputMaybe<CommentThreadWhereInput>;
isNot?: InputMaybe<CommentThreadWhereInput>;
@ -201,87 +136,12 @@ export type CommentThreadTargetCreateNestedManyWithoutCommentThreadInput = {
createMany?: InputMaybe<CommentThreadTargetCreateManyCommentThreadInputEnvelope>;
};
export type CommentThreadTargetCreateOrConnectWithoutCommentThreadInput = {
create: CommentThreadTargetCreateWithoutCommentThreadInput;
where: CommentThreadTargetWhereUniqueInput;
};
export type CommentThreadTargetCreateWithoutCommentThreadInput = {
commentableId: Scalars['String'];
commentableType: CommentableType;
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
id: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CommentThreadTargetListRelationFilter = {
every?: InputMaybe<CommentThreadTargetWhereInput>;
none?: InputMaybe<CommentThreadTargetWhereInput>;
some?: InputMaybe<CommentThreadTargetWhereInput>;
};
export type CommentThreadTargetScalarWhereInput = {
AND?: InputMaybe<Array<CommentThreadTargetScalarWhereInput>>;
NOT?: InputMaybe<Array<CommentThreadTargetScalarWhereInput>>;
OR?: InputMaybe<Array<CommentThreadTargetScalarWhereInput>>;
commentThreadId?: InputMaybe<StringFilter>;
commentableId?: InputMaybe<StringFilter>;
commentableType?: InputMaybe<EnumCommentableTypeFilter>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
id?: InputMaybe<StringFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type CommentThreadTargetUpdateManyMutationInput = {
commentableId?: InputMaybe<StringFieldUpdateOperationsInput>;
commentableType?: InputMaybe<EnumCommentableTypeFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CommentThreadTargetUpdateManyWithWhereWithoutCommentThreadInput = {
data: CommentThreadTargetUpdateManyMutationInput;
where: CommentThreadTargetScalarWhereInput;
};
export type CommentThreadTargetUpdateManyWithoutCommentThreadNestedInput = {
connect?: InputMaybe<Array<CommentThreadTargetWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<CommentThreadTargetCreateOrConnectWithoutCommentThreadInput>>;
create?: InputMaybe<Array<CommentThreadTargetCreateWithoutCommentThreadInput>>;
createMany?: InputMaybe<CommentThreadTargetCreateManyCommentThreadInputEnvelope>;
delete?: InputMaybe<Array<CommentThreadTargetWhereUniqueInput>>;
deleteMany?: InputMaybe<Array<CommentThreadTargetScalarWhereInput>>;
disconnect?: InputMaybe<Array<CommentThreadTargetWhereUniqueInput>>;
set?: InputMaybe<Array<CommentThreadTargetWhereUniqueInput>>;
update?: InputMaybe<Array<CommentThreadTargetUpdateWithWhereUniqueWithoutCommentThreadInput>>;
updateMany?: InputMaybe<Array<CommentThreadTargetUpdateManyWithWhereWithoutCommentThreadInput>>;
upsert?: InputMaybe<Array<CommentThreadTargetUpsertWithWhereUniqueWithoutCommentThreadInput>>;
};
export type CommentThreadTargetUpdateWithWhereUniqueWithoutCommentThreadInput = {
data: CommentThreadTargetUpdateWithoutCommentThreadInput;
where: CommentThreadTargetWhereUniqueInput;
};
export type CommentThreadTargetUpdateWithoutCommentThreadInput = {
commentableId?: InputMaybe<StringFieldUpdateOperationsInput>;
commentableType?: InputMaybe<EnumCommentableTypeFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CommentThreadTargetUpsertWithWhereUniqueWithoutCommentThreadInput = {
create: CommentThreadTargetCreateWithoutCommentThreadInput;
update: CommentThreadTargetUpdateWithoutCommentThreadInput;
where: CommentThreadTargetWhereUniqueInput;
};
export type CommentThreadTargetWhereInput = {
AND?: InputMaybe<Array<CommentThreadTargetWhereInput>>;
NOT?: InputMaybe<Array<CommentThreadTargetWhereInput>>;
@ -296,31 +156,6 @@ export type CommentThreadTargetWhereInput = {
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type CommentThreadTargetWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
};
export type CommentThreadUpdateOneRequiredWithoutCommentsNestedInput = {
connect?: InputMaybe<CommentThreadWhereUniqueInput>;
connectOrCreate?: InputMaybe<CommentThreadCreateOrConnectWithoutCommentsInput>;
create?: InputMaybe<CommentThreadCreateWithoutCommentsInput>;
update?: InputMaybe<CommentThreadUpdateWithoutCommentsInput>;
upsert?: InputMaybe<CommentThreadUpsertWithoutCommentsInput>;
};
export type CommentThreadUpdateWithoutCommentsInput = {
commentThreadTargets?: InputMaybe<CommentThreadTargetUpdateManyWithoutCommentThreadNestedInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CommentThreadUpsertWithoutCommentsInput = {
create: CommentThreadCreateWithoutCommentsInput;
update: CommentThreadUpdateWithoutCommentsInput;
};
export type CommentThreadWhereInput = {
AND?: InputMaybe<Array<CommentThreadWhereInput>>;
NOT?: InputMaybe<Array<CommentThreadWhereInput>>;
@ -337,53 +172,6 @@ export type CommentThreadWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
};
export type CommentUpdateManyMutationInput = {
body?: InputMaybe<StringFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CommentUpdateManyWithWhereWithoutAuthorInput = {
data: CommentUpdateManyMutationInput;
where: CommentScalarWhereInput;
};
export type CommentUpdateManyWithoutAuthorNestedInput = {
connect?: InputMaybe<Array<CommentWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<CommentCreateOrConnectWithoutAuthorInput>>;
create?: InputMaybe<Array<CommentCreateWithoutAuthorInput>>;
createMany?: InputMaybe<CommentCreateManyAuthorInputEnvelope>;
delete?: InputMaybe<Array<CommentWhereUniqueInput>>;
deleteMany?: InputMaybe<Array<CommentScalarWhereInput>>;
disconnect?: InputMaybe<Array<CommentWhereUniqueInput>>;
set?: InputMaybe<Array<CommentWhereUniqueInput>>;
update?: InputMaybe<Array<CommentUpdateWithWhereUniqueWithoutAuthorInput>>;
updateMany?: InputMaybe<Array<CommentUpdateManyWithWhereWithoutAuthorInput>>;
upsert?: InputMaybe<Array<CommentUpsertWithWhereUniqueWithoutAuthorInput>>;
};
export type CommentUpdateWithWhereUniqueWithoutAuthorInput = {
data: CommentUpdateWithoutAuthorInput;
where: CommentWhereUniqueInput;
};
export type CommentUpdateWithoutAuthorInput = {
body?: InputMaybe<StringFieldUpdateOperationsInput>;
commentThread?: InputMaybe<CommentThreadUpdateOneRequiredWithoutCommentsNestedInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CommentUpsertWithWhereUniqueWithoutAuthorInput = {
create: CommentCreateWithoutAuthorInput;
update: CommentUpdateWithoutAuthorInput;
where: CommentWhereUniqueInput;
};
export type CommentWhereInput = {
AND?: InputMaybe<Array<CommentWhereInput>>;
NOT?: InputMaybe<Array<CommentWhereInput>>;
@ -399,10 +187,6 @@ export type CommentWhereInput = {
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type CommentWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
};
export enum CommentableType {
Company = 'Company',
Person = 'Person'
@ -441,25 +225,6 @@ export type CompanyCreateInput = {
export type CompanyCreateNestedOneWithoutPeopleInput = {
connect?: InputMaybe<CompanyWhereUniqueInput>;
connectOrCreate?: InputMaybe<CompanyCreateOrConnectWithoutPeopleInput>;
create?: InputMaybe<CompanyCreateWithoutPeopleInput>;
};
export type CompanyCreateOrConnectWithoutPeopleInput = {
create: CompanyCreateWithoutPeopleInput;
where: CompanyWhereUniqueInput;
};
export type CompanyCreateWithoutPeopleInput = {
accountOwner?: InputMaybe<UserCreateNestedOneWithoutCompaniesInput>;
address: Scalars['String'];
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
domainName: Scalars['String'];
employees?: InputMaybe<Scalars['Int']>;
id: Scalars['String'];
name: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type CompanyListRelationFilter = {
@ -519,29 +284,6 @@ export type CompanyUpdateInput = {
export type CompanyUpdateOneWithoutPeopleNestedInput = {
connect?: InputMaybe<CompanyWhereUniqueInput>;
connectOrCreate?: InputMaybe<CompanyCreateOrConnectWithoutPeopleInput>;
create?: InputMaybe<CompanyCreateWithoutPeopleInput>;
delete?: InputMaybe<Scalars['Boolean']>;
disconnect?: InputMaybe<Scalars['Boolean']>;
update?: InputMaybe<CompanyUpdateWithoutPeopleInput>;
upsert?: InputMaybe<CompanyUpsertWithoutPeopleInput>;
};
export type CompanyUpdateWithoutPeopleInput = {
accountOwner?: InputMaybe<UserUpdateOneWithoutCompaniesNestedInput>;
address?: InputMaybe<StringFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
domainName?: InputMaybe<StringFieldUpdateOperationsInput>;
employees?: InputMaybe<NullableIntFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
name?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type CompanyUpsertWithoutPeopleInput = {
create: CompanyCreateWithoutPeopleInput;
update: CompanyUpdateWithoutPeopleInput;
};
export type CompanyWhereInput = {
@ -591,10 +333,6 @@ export type DateTimeNullableFilter = {
notIn?: InputMaybe<Array<Scalars['DateTime']>>;
};
export type EnumCommentableTypeFieldUpdateOperationsInput = {
set?: InputMaybe<CommentableType>;
};
export type EnumCommentableTypeFilter = {
equals?: InputMaybe<CommentableType>;
in?: InputMaybe<Array<CommentableType>>;
@ -602,6 +340,13 @@ export type EnumCommentableTypeFilter = {
notIn?: InputMaybe<Array<CommentableType>>;
};
export type EnumPipelineProgressableTypeFilter = {
equals?: InputMaybe<PipelineProgressableType>;
in?: InputMaybe<Array<PipelineProgressableType>>;
not?: InputMaybe<NestedEnumPipelineProgressableTypeFilter>;
notIn?: InputMaybe<Array<PipelineProgressableType>>;
};
export type IntNullableFilter = {
equals?: InputMaybe<Scalars['Int']>;
gt?: InputMaybe<Scalars['Int']>;
@ -717,6 +462,13 @@ export type NestedEnumCommentableTypeFilter = {
notIn?: InputMaybe<Array<CommentableType>>;
};
export type NestedEnumPipelineProgressableTypeFilter = {
equals?: InputMaybe<PipelineProgressableType>;
in?: InputMaybe<Array<PipelineProgressableType>>;
not?: InputMaybe<NestedEnumPipelineProgressableTypeFilter>;
notIn?: InputMaybe<Array<PipelineProgressableType>>;
};
export type NestedIntNullableFilter = {
equals?: InputMaybe<Scalars['Int']>;
gt?: InputMaybe<Scalars['Int']>;
@ -768,10 +520,6 @@ export type NullableIntFieldUpdateOperationsInput = {
set?: InputMaybe<Scalars['Int']>;
};
export type NullableStringFieldUpdateOperationsInput = {
set?: InputMaybe<Scalars['String']>;
};
export type Person = {
__typename?: 'Person';
_commentCount: Scalars['Int'];
@ -803,45 +551,8 @@ export type PersonCreateInput = {
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type PersonCreateManyCompanyInput = {
city: Scalars['String'];
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
email: Scalars['String'];
firstname: Scalars['String'];
id: Scalars['String'];
lastname: Scalars['String'];
phone: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type PersonCreateManyCompanyInputEnvelope = {
data: Array<PersonCreateManyCompanyInput>;
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
};
export type PersonCreateNestedManyWithoutCompanyInput = {
connect?: InputMaybe<Array<PersonWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<PersonCreateOrConnectWithoutCompanyInput>>;
create?: InputMaybe<Array<PersonCreateWithoutCompanyInput>>;
createMany?: InputMaybe<PersonCreateManyCompanyInputEnvelope>;
};
export type PersonCreateOrConnectWithoutCompanyInput = {
create: PersonCreateWithoutCompanyInput;
where: PersonWhereUniqueInput;
};
export type PersonCreateWithoutCompanyInput = {
city: Scalars['String'];
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
email: Scalars['String'];
firstname: Scalars['String'];
id: Scalars['String'];
lastname: Scalars['String'];
phone: Scalars['String'];
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type PersonListRelationFilter = {
@ -882,22 +593,6 @@ export enum PersonScalarFieldEnum {
WorkspaceId = 'workspaceId'
}
export type PersonScalarWhereInput = {
AND?: InputMaybe<Array<PersonScalarWhereInput>>;
NOT?: InputMaybe<Array<PersonScalarWhereInput>>;
OR?: InputMaybe<Array<PersonScalarWhereInput>>;
city?: InputMaybe<StringFilter>;
companyId?: InputMaybe<StringNullableFilter>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
email?: InputMaybe<StringFilter>;
firstname?: InputMaybe<StringFilter>;
id?: InputMaybe<StringFilter>;
lastname?: InputMaybe<StringFilter>;
phone?: InputMaybe<StringFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type PersonUpdateInput = {
city?: InputMaybe<StringFieldUpdateOperationsInput>;
company?: InputMaybe<CompanyUpdateOneWithoutPeopleNestedInput>;
@ -911,58 +606,8 @@ export type PersonUpdateInput = {
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type PersonUpdateManyMutationInput = {
city?: InputMaybe<StringFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
email?: InputMaybe<StringFieldUpdateOperationsInput>;
firstname?: InputMaybe<StringFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
lastname?: InputMaybe<StringFieldUpdateOperationsInput>;
phone?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type PersonUpdateManyWithWhereWithoutCompanyInput = {
data: PersonUpdateManyMutationInput;
where: PersonScalarWhereInput;
};
export type PersonUpdateManyWithoutCompanyNestedInput = {
connect?: InputMaybe<Array<PersonWhereUniqueInput>>;
connectOrCreate?: InputMaybe<Array<PersonCreateOrConnectWithoutCompanyInput>>;
create?: InputMaybe<Array<PersonCreateWithoutCompanyInput>>;
createMany?: InputMaybe<PersonCreateManyCompanyInputEnvelope>;
delete?: InputMaybe<Array<PersonWhereUniqueInput>>;
deleteMany?: InputMaybe<Array<PersonScalarWhereInput>>;
disconnect?: InputMaybe<Array<PersonWhereUniqueInput>>;
set?: InputMaybe<Array<PersonWhereUniqueInput>>;
update?: InputMaybe<Array<PersonUpdateWithWhereUniqueWithoutCompanyInput>>;
updateMany?: InputMaybe<Array<PersonUpdateManyWithWhereWithoutCompanyInput>>;
upsert?: InputMaybe<Array<PersonUpsertWithWhereUniqueWithoutCompanyInput>>;
};
export type PersonUpdateWithWhereUniqueWithoutCompanyInput = {
data: PersonUpdateWithoutCompanyInput;
where: PersonWhereUniqueInput;
};
export type PersonUpdateWithoutCompanyInput = {
city?: InputMaybe<StringFieldUpdateOperationsInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
email?: InputMaybe<StringFieldUpdateOperationsInput>;
firstname?: InputMaybe<StringFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
lastname?: InputMaybe<StringFieldUpdateOperationsInput>;
phone?: InputMaybe<StringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type PersonUpsertWithWhereUniqueWithoutCompanyInput = {
create: PersonCreateWithoutCompanyInput;
update: PersonUpdateWithoutCompanyInput;
where: PersonWhereUniqueInput;
};
export type PersonWhereInput = {
@ -998,6 +643,17 @@ export type Pipeline = {
updatedAt: Scalars['DateTime'];
};
export type PipelineOrderByWithRelationInput = {
createdAt?: InputMaybe<SortOrder>;
deletedAt?: InputMaybe<SortOrder>;
icon?: InputMaybe<SortOrder>;
id?: InputMaybe<SortOrder>;
name?: InputMaybe<SortOrder>;
pipelineProgresses?: InputMaybe<PipelineProgressOrderByRelationAggregateInput>;
pipelineStages?: InputMaybe<PipelineStageOrderByRelationAggregateInput>;
updatedAt?: InputMaybe<SortOrder>;
};
export type PipelineProgress = {
__typename?: 'PipelineProgress';
associableId: Scalars['String'];
@ -1012,11 +668,52 @@ export type PipelineProgress = {
updatedAt: Scalars['DateTime'];
};
export type PipelineProgressListRelationFilter = {
every?: InputMaybe<PipelineProgressWhereInput>;
none?: InputMaybe<PipelineProgressWhereInput>;
some?: InputMaybe<PipelineProgressWhereInput>;
};
export type PipelineProgressOrderByRelationAggregateInput = {
_count?: InputMaybe<SortOrder>;
};
export type PipelineProgressWhereInput = {
AND?: InputMaybe<Array<PipelineProgressWhereInput>>;
NOT?: InputMaybe<Array<PipelineProgressWhereInput>>;
OR?: InputMaybe<Array<PipelineProgressWhereInput>>;
associableId?: InputMaybe<StringFilter>;
associableType?: InputMaybe<EnumPipelineProgressableTypeFilter>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
id?: InputMaybe<StringFilter>;
pipeline?: InputMaybe<PipelineRelationFilter>;
pipelineId?: InputMaybe<StringFilter>;
pipelineStage?: InputMaybe<PipelineStageRelationFilter>;
pipelineStageId?: InputMaybe<StringFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export enum PipelineProgressableType {
Company = 'Company',
Person = 'Person'
}
export type PipelineRelationFilter = {
is?: InputMaybe<PipelineWhereInput>;
isNot?: InputMaybe<PipelineWhereInput>;
};
export enum PipelineScalarFieldEnum {
CreatedAt = 'createdAt',
DeletedAt = 'deletedAt',
Icon = 'icon',
Id = 'id',
Name = 'name',
UpdatedAt = 'updatedAt',
WorkspaceId = 'workspaceId'
}
export type PipelineStage = {
__typename?: 'PipelineStage';
color: Scalars['String'];
@ -1031,10 +728,90 @@ export type PipelineStage = {
updatedAt: Scalars['DateTime'];
};
export type PipelineStageListRelationFilter = {
every?: InputMaybe<PipelineStageWhereInput>;
none?: InputMaybe<PipelineStageWhereInput>;
some?: InputMaybe<PipelineStageWhereInput>;
};
export type PipelineStageOrderByRelationAggregateInput = {
_count?: InputMaybe<SortOrder>;
};
export type PipelineStageOrderByWithRelationInput = {
color?: InputMaybe<SortOrder>;
createdAt?: InputMaybe<SortOrder>;
deletedAt?: InputMaybe<SortOrder>;
id?: InputMaybe<SortOrder>;
name?: InputMaybe<SortOrder>;
pipeline?: InputMaybe<PipelineOrderByWithRelationInput>;
pipelineId?: InputMaybe<SortOrder>;
pipelineProgresses?: InputMaybe<PipelineProgressOrderByRelationAggregateInput>;
type?: InputMaybe<SortOrder>;
updatedAt?: InputMaybe<SortOrder>;
};
export type PipelineStageRelationFilter = {
is?: InputMaybe<PipelineStageWhereInput>;
isNot?: InputMaybe<PipelineStageWhereInput>;
};
export enum PipelineStageScalarFieldEnum {
Color = 'color',
CreatedAt = 'createdAt',
DeletedAt = 'deletedAt',
Id = 'id',
Name = 'name',
PipelineId = 'pipelineId',
Type = 'type',
UpdatedAt = 'updatedAt',
WorkspaceId = 'workspaceId'
}
export type PipelineStageWhereInput = {
AND?: InputMaybe<Array<PipelineStageWhereInput>>;
NOT?: InputMaybe<Array<PipelineStageWhereInput>>;
OR?: InputMaybe<Array<PipelineStageWhereInput>>;
color?: InputMaybe<StringFilter>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
id?: InputMaybe<StringFilter>;
name?: InputMaybe<StringFilter>;
pipeline?: InputMaybe<PipelineRelationFilter>;
pipelineId?: InputMaybe<StringFilter>;
pipelineProgresses?: InputMaybe<PipelineProgressListRelationFilter>;
type?: InputMaybe<StringFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type PipelineStageWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
};
export type PipelineWhereInput = {
AND?: InputMaybe<Array<PipelineWhereInput>>;
NOT?: InputMaybe<Array<PipelineWhereInput>>;
OR?: InputMaybe<Array<PipelineWhereInput>>;
createdAt?: InputMaybe<DateTimeFilter>;
deletedAt?: InputMaybe<DateTimeNullableFilter>;
icon?: InputMaybe<StringFilter>;
id?: InputMaybe<StringFilter>;
name?: InputMaybe<StringFilter>;
pipelineProgresses?: InputMaybe<PipelineProgressListRelationFilter>;
pipelineStages?: InputMaybe<PipelineStageListRelationFilter>;
updatedAt?: InputMaybe<DateTimeFilter>;
};
export type PipelineWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
};
export type Query = {
__typename?: 'Query';
findManyCompany: Array<Company>;
findManyPerson: Array<Person>;
findManyPipeline: Array<Pipeline>;
findManyPipelineStage: Array<PipelineStage>;
findManyUser: Array<User>;
};
@ -1059,6 +836,26 @@ export type QueryFindManyPersonArgs = {
};
export type QueryFindManyPipelineArgs = {
cursor?: InputMaybe<PipelineWhereUniqueInput>;
distinct?: InputMaybe<Array<PipelineScalarFieldEnum>>;
orderBy?: InputMaybe<Array<PipelineOrderByWithRelationInput>>;
skip?: InputMaybe<Scalars['Int']>;
take?: InputMaybe<Scalars['Int']>;
where?: InputMaybe<PipelineWhereInput>;
};
export type QueryFindManyPipelineStageArgs = {
cursor?: InputMaybe<PipelineStageWhereUniqueInput>;
distinct?: InputMaybe<Array<PipelineStageScalarFieldEnum>>;
orderBy?: InputMaybe<Array<PipelineStageOrderByWithRelationInput>>;
skip?: InputMaybe<Scalars['Int']>;
take?: InputMaybe<Scalars['Int']>;
where?: InputMaybe<PipelineStageWhereInput>;
};
export type QueryFindManyUserArgs = {
cursor?: InputMaybe<UserWhereUniqueInput>;
distinct?: InputMaybe<Array<UserScalarFieldEnum>>;
@ -1149,31 +946,6 @@ export type UserCreateNestedOneWithoutCommentsInput = {
export type UserCreateNestedOneWithoutCompaniesInput = {
connect?: InputMaybe<UserWhereUniqueInput>;
connectOrCreate?: InputMaybe<UserCreateOrConnectWithoutCompaniesInput>;
create?: InputMaybe<UserCreateWithoutCompaniesInput>;
};
export type UserCreateOrConnectWithoutCompaniesInput = {
create: UserCreateWithoutCompaniesInput;
where: UserWhereUniqueInput;
};
export type UserCreateWithoutCompaniesInput = {
avatarUrl?: InputMaybe<Scalars['String']>;
comments?: InputMaybe<CommentCreateNestedManyWithoutAuthorInput>;
createdAt?: InputMaybe<Scalars['DateTime']>;
deletedAt?: InputMaybe<Scalars['DateTime']>;
disabled?: InputMaybe<Scalars['Boolean']>;
displayName: Scalars['String'];
email: Scalars['String'];
emailVerified?: InputMaybe<Scalars['Boolean']>;
id: Scalars['String'];
lastSeen?: InputMaybe<Scalars['DateTime']>;
locale: Scalars['String'];
metadata?: InputMaybe<Scalars['JSON']>;
passwordHash?: InputMaybe<Scalars['String']>;
phoneNumber?: InputMaybe<Scalars['String']>;
updatedAt?: InputMaybe<Scalars['DateTime']>;
};
export type UserOrderByWithRelationInput = {
@ -1219,35 +991,6 @@ export enum UserScalarFieldEnum {
export type UserUpdateOneWithoutCompaniesNestedInput = {
connect?: InputMaybe<UserWhereUniqueInput>;
connectOrCreate?: InputMaybe<UserCreateOrConnectWithoutCompaniesInput>;
create?: InputMaybe<UserCreateWithoutCompaniesInput>;
delete?: InputMaybe<Scalars['Boolean']>;
disconnect?: InputMaybe<Scalars['Boolean']>;
update?: InputMaybe<UserUpdateWithoutCompaniesInput>;
upsert?: InputMaybe<UserUpsertWithoutCompaniesInput>;
};
export type UserUpdateWithoutCompaniesInput = {
avatarUrl?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
comments?: InputMaybe<CommentUpdateManyWithoutAuthorNestedInput>;
createdAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
deletedAt?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
disabled?: InputMaybe<BoolFieldUpdateOperationsInput>;
displayName?: InputMaybe<StringFieldUpdateOperationsInput>;
email?: InputMaybe<StringFieldUpdateOperationsInput>;
emailVerified?: InputMaybe<BoolFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
lastSeen?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
locale?: InputMaybe<StringFieldUpdateOperationsInput>;
metadata?: InputMaybe<Scalars['JSON']>;
passwordHash?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
phoneNumber?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
updatedAt?: InputMaybe<DateTimeFieldUpdateOperationsInput>;
};
export type UserUpsertWithoutCompaniesInput = {
create: UserCreateWithoutCompaniesInput;
update: UserUpdateWithoutCompaniesInput;
};
export type UserWhereInput = {

View File

@ -1,18 +1,17 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { CompanyCreateWithoutPeopleInput } from './company-create-without-people.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { CompanyCreateOrConnectWithoutPeopleInput } from './company-create-or-connect-without-people.input';
import { CompanyWhereUniqueInput } from './company-where-unique.input';
import { Type } from 'class-transformer';
@InputType()
export class CompanyCreateNestedOneWithoutPeopleInput {
@Field(() => CompanyCreateWithoutPeopleInput, { nullable: true })
@Type(() => CompanyCreateWithoutPeopleInput)
@HideField()
create?: CompanyCreateWithoutPeopleInput;
@Field(() => CompanyCreateOrConnectWithoutPeopleInput, { nullable: true })
@Type(() => CompanyCreateOrConnectWithoutPeopleInput)
@HideField()
connectOrCreate?: CompanyCreateOrConnectWithoutPeopleInput;
@Field(() => CompanyWhereUniqueInput, { nullable: true })

View File

@ -1,37 +1,34 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { CompanyCreateWithoutPeopleInput } from './company-create-without-people.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { CompanyCreateOrConnectWithoutPeopleInput } from './company-create-or-connect-without-people.input';
import { CompanyUpsertWithoutPeopleInput } from './company-upsert-without-people.input';
import { CompanyWhereUniqueInput } from './company-where-unique.input';
import { Type } from 'class-transformer';
import { CompanyUpdateWithoutPeopleInput } from './company-update-without-people.input';
@InputType()
export class CompanyUpdateOneWithoutPeopleNestedInput {
@Field(() => CompanyCreateWithoutPeopleInput, { nullable: true })
@Type(() => CompanyCreateWithoutPeopleInput)
@HideField()
create?: CompanyCreateWithoutPeopleInput;
@Field(() => CompanyCreateOrConnectWithoutPeopleInput, { nullable: true })
@Type(() => CompanyCreateOrConnectWithoutPeopleInput)
@HideField()
connectOrCreate?: CompanyCreateOrConnectWithoutPeopleInput;
@Field(() => CompanyUpsertWithoutPeopleInput, { nullable: true })
@Type(() => CompanyUpsertWithoutPeopleInput)
@HideField()
upsert?: CompanyUpsertWithoutPeopleInput;
@Field(() => Boolean, { nullable: true })
@HideField()
disconnect?: boolean;
@Field(() => Boolean, { nullable: true })
@HideField()
delete?: boolean;
@Field(() => CompanyWhereUniqueInput, { nullable: true })
@Type(() => CompanyWhereUniqueInput)
connect?: CompanyWhereUniqueInput;
@Field(() => CompanyUpdateWithoutPeopleInput, { nullable: true })
@Type(() => CompanyUpdateWithoutPeopleInput)
@HideField()
update?: CompanyUpdateWithoutPeopleInput;
}

View File

@ -1,23 +1,21 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { PersonCreateWithoutCompanyInput } from './person-create-without-company.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { PersonCreateOrConnectWithoutCompanyInput } from './person-create-or-connect-without-company.input';
import { PersonCreateManyCompanyInputEnvelope } from './person-create-many-company-input-envelope.input';
import { PersonWhereUniqueInput } from './person-where-unique.input';
import { Type } from 'class-transformer';
@InputType()
export class PersonCreateNestedManyWithoutCompanyInput {
@Field(() => [PersonCreateWithoutCompanyInput], { nullable: true })
@Type(() => PersonCreateWithoutCompanyInput)
@HideField()
create?: Array<PersonCreateWithoutCompanyInput>;
@Field(() => [PersonCreateOrConnectWithoutCompanyInput], { nullable: true })
@Type(() => PersonCreateOrConnectWithoutCompanyInput)
@HideField()
connectOrCreate?: Array<PersonCreateOrConnectWithoutCompanyInput>;
@Field(() => PersonCreateManyCompanyInputEnvelope, { nullable: true })
@Type(() => PersonCreateManyCompanyInputEnvelope)
@HideField()
createMany?: PersonCreateManyCompanyInputEnvelope;
@Field(() => [PersonWhereUniqueInput], { nullable: true })

View File

@ -1,64 +1,49 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { PersonCreateWithoutCompanyInput } from './person-create-without-company.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { PersonCreateOrConnectWithoutCompanyInput } from './person-create-or-connect-without-company.input';
import { PersonUpsertWithWhereUniqueWithoutCompanyInput } from './person-upsert-with-where-unique-without-company.input';
import { PersonCreateManyCompanyInputEnvelope } from './person-create-many-company-input-envelope.input';
import { PersonWhereUniqueInput } from './person-where-unique.input';
import { Type } from 'class-transformer';
import { PersonUpdateWithWhereUniqueWithoutCompanyInput } from './person-update-with-where-unique-without-company.input';
import { PersonUpdateManyWithWhereWithoutCompanyInput } from './person-update-many-with-where-without-company.input';
import { PersonScalarWhereInput } from './person-scalar-where.input';
@InputType()
export class PersonUpdateManyWithoutCompanyNestedInput {
@Field(() => [PersonCreateWithoutCompanyInput], { nullable: true })
@Type(() => PersonCreateWithoutCompanyInput)
@HideField()
create?: Array<PersonCreateWithoutCompanyInput>;
@Field(() => [PersonCreateOrConnectWithoutCompanyInput], { nullable: true })
@Type(() => PersonCreateOrConnectWithoutCompanyInput)
@HideField()
connectOrCreate?: Array<PersonCreateOrConnectWithoutCompanyInput>;
@Field(() => [PersonUpsertWithWhereUniqueWithoutCompanyInput], {
nullable: true,
})
@Type(() => PersonUpsertWithWhereUniqueWithoutCompanyInput)
@HideField()
upsert?: Array<PersonUpsertWithWhereUniqueWithoutCompanyInput>;
@Field(() => PersonCreateManyCompanyInputEnvelope, { nullable: true })
@Type(() => PersonCreateManyCompanyInputEnvelope)
@HideField()
createMany?: PersonCreateManyCompanyInputEnvelope;
@Field(() => [PersonWhereUniqueInput], { nullable: true })
@Type(() => PersonWhereUniqueInput)
@HideField()
set?: Array<PersonWhereUniqueInput>;
@Field(() => [PersonWhereUniqueInput], { nullable: true })
@Type(() => PersonWhereUniqueInput)
@HideField()
disconnect?: Array<PersonWhereUniqueInput>;
@Field(() => [PersonWhereUniqueInput], { nullable: true })
@Type(() => PersonWhereUniqueInput)
@HideField()
delete?: Array<PersonWhereUniqueInput>;
@Field(() => [PersonWhereUniqueInput], { nullable: true })
@Type(() => PersonWhereUniqueInput)
connect?: Array<PersonWhereUniqueInput>;
@Field(() => [PersonUpdateWithWhereUniqueWithoutCompanyInput], {
nullable: true,
})
@Type(() => PersonUpdateWithWhereUniqueWithoutCompanyInput)
@HideField()
update?: Array<PersonUpdateWithWhereUniqueWithoutCompanyInput>;
@Field(() => [PersonUpdateManyWithWhereWithoutCompanyInput], {
nullable: true,
})
@Type(() => PersonUpdateManyWithWhereWithoutCompanyInput)
@HideField()
updateMany?: Array<PersonUpdateManyWithWhereWithoutCompanyInput>;
@Field(() => [PersonScalarWhereInput], { nullable: true })
@Type(() => PersonScalarWhereInput)
@HideField()
deleteMany?: Array<PersonScalarWhereInput>;
}

View File

@ -1,18 +1,17 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { UserCreateWithoutCompaniesInput } from './user-create-without-companies.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { UserCreateOrConnectWithoutCompaniesInput } from './user-create-or-connect-without-companies.input';
import { UserWhereUniqueInput } from './user-where-unique.input';
import { Type } from 'class-transformer';
@InputType()
export class UserCreateNestedOneWithoutCompaniesInput {
@Field(() => UserCreateWithoutCompaniesInput, { nullable: true })
@Type(() => UserCreateWithoutCompaniesInput)
@HideField()
create?: UserCreateWithoutCompaniesInput;
@Field(() => UserCreateOrConnectWithoutCompaniesInput, { nullable: true })
@Type(() => UserCreateOrConnectWithoutCompaniesInput)
@HideField()
connectOrCreate?: UserCreateOrConnectWithoutCompaniesInput;
@Field(() => UserWhereUniqueInput, { nullable: true })

View File

@ -1,37 +1,34 @@
import { Field } from '@nestjs/graphql';
import { InputType } from '@nestjs/graphql';
import { UserCreateWithoutCompaniesInput } from './user-create-without-companies.input';
import { Type } from 'class-transformer';
import { HideField } from '@nestjs/graphql';
import { UserCreateOrConnectWithoutCompaniesInput } from './user-create-or-connect-without-companies.input';
import { UserUpsertWithoutCompaniesInput } from './user-upsert-without-companies.input';
import { UserWhereUniqueInput } from './user-where-unique.input';
import { Type } from 'class-transformer';
import { UserUpdateWithoutCompaniesInput } from './user-update-without-companies.input';
@InputType()
export class UserUpdateOneWithoutCompaniesNestedInput {
@Field(() => UserCreateWithoutCompaniesInput, { nullable: true })
@Type(() => UserCreateWithoutCompaniesInput)
@HideField()
create?: UserCreateWithoutCompaniesInput;
@Field(() => UserCreateOrConnectWithoutCompaniesInput, { nullable: true })
@Type(() => UserCreateOrConnectWithoutCompaniesInput)
@HideField()
connectOrCreate?: UserCreateOrConnectWithoutCompaniesInput;
@Field(() => UserUpsertWithoutCompaniesInput, { nullable: true })
@Type(() => UserUpsertWithoutCompaniesInput)
@HideField()
upsert?: UserUpsertWithoutCompaniesInput;
@Field(() => Boolean, { nullable: true })
@HideField()
disconnect?: boolean;
@Field(() => Boolean, { nullable: true })
@HideField()
delete?: boolean;
@Field(() => UserWhereUniqueInput, { nullable: true })
@Type(() => UserWhereUniqueInput)
connect?: UserWhereUniqueInput;
@Field(() => UserUpdateWithoutCompaniesInput, { nullable: true })
@Type(() => UserUpdateWithoutCompaniesInput)
@HideField()
update?: UserUpdateWithoutCompaniesInput;
}

View File

@ -22,6 +22,7 @@ import { CompanyRelationsResolver } from './resolvers/relations/company-relation
import { CommentThreadRelationsResolver } from './resolvers/relations/comment-thread-relations.resolver';
import { PipelineRelationsResolver } from './resolvers/relations/pipeline-relations.resolver';
import { PipelineStageRelationsResolver } from './resolvers/relations/pipeline-stage-relations.resolver';
import { GraphQLError } from 'graphql';
@Module({
imports: [
@ -29,6 +30,10 @@ import { PipelineStageRelationsResolver } from './resolvers/relations/pipeline-s
context: ({ req }) => ({ req }),
driver: ApolloDriver,
autoSchemaFile: true,
formatError: (error: GraphQLError) => {
error.extensions.stacktrace = undefined;
return error;
},
}),
AuthModule,
PrismaModule,

View File

@ -11,10 +11,12 @@ import { AffectedRows } from '../@generated/prisma/affected-rows.output';
import { DeleteManyCompanyArgs } from '../@generated/company/delete-many-company.args';
import { Workspace } from '@prisma/client';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { Prisma } from '@prisma/client';
import { UpdateOneGuard } from './guards/update-one.guard';
import { DeleteManyGuard } from './guards/delete-many.guard';
import { CreateOneGuard } from './guards/create-one.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => Company)
export class CompanyResolver {
constructor(
@ -35,6 +37,7 @@ export class CompanyResolver {
return this.prismaService.company.findMany(preparedArgs);
}
@UseGuards(UpdateOneGuard)
@Mutation(() => Company, {
nullable: true,
})
@ -50,6 +53,7 @@ export class CompanyResolver {
} satisfies UpdateOneCompanyArgs as Prisma.CompanyUpdateArgs);
}
@UseGuards(DeleteManyGuard)
@Mutation(() => AffectedRows, {
nullable: false,
})
@ -61,6 +65,7 @@ export class CompanyResolver {
});
}
@UseGuards(CreateOneGuard)
@Mutation(() => Company, {
nullable: false,
})

View File

@ -0,0 +1,18 @@
import { Catch, HttpException } from '@nestjs/common';
import { GqlExceptionFilter } from '@nestjs/graphql';
import { Prisma } from '@prisma/client';
import { GraphQLError } from 'graphql';
@Catch()
export class ExceptionFilter implements GqlExceptionFilter {
catch(exception: HttpException) {
if (exception instanceof Prisma.PrismaClientValidationError) {
throw new GraphQLError('Invalid request', {
extensions: {
code: 'INVALID_REQUEST',
},
});
}
return exception;
}
}

View File

@ -0,0 +1,12 @@
import { CanActivate, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class CreateOneGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(): Promise<boolean> {
// TODO
return true;
}
}

View File

@ -0,0 +1,12 @@
import { CanActivate, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class DeleteManyGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(): Promise<boolean> {
// TODO
return true;
}
}

View File

@ -0,0 +1,50 @@
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class UpdateOneGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const gqlContext = GqlExecutionContext.create(context);
const request = gqlContext.getContext().req;
const entity = gqlContext.getArgByIndex(3).returnType?.name;
const args = gqlContext.getArgs();
console.log(args.data);
if (!entity || !args.where?.id) {
throw new HttpException(
{ reason: 'Invalid Request' },
HttpStatus.BAD_REQUEST,
);
}
const object = await this.prismaService[entity].findUniqueOrThrow({
where: { id: args.where.id },
});
if (!object) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
const workspace = await request.workspace;
if (object.workspaceId !== workspace.id) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
return true;
}
}

View File

@ -11,10 +11,12 @@ import { DeleteManyPersonArgs } from '../@generated/person/delete-many-person.ar
import { Workspace } from '../@generated/workspace/workspace.model';
import { AuthWorkspace } from './decorators/auth-workspace.decorator';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { Prisma } from '@prisma/client';
import { UpdateOneGuard } from './guards/update-one.guard';
import { DeleteManyGuard } from './guards/delete-many.guard';
import { CreateOneGuard } from './guards/create-one.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => Person)
export class PersonResolver {
constructor(
@ -39,6 +41,7 @@ export class PersonResolver {
});
}
@UseGuards(UpdateOneGuard)
@Mutation(() => Person, {
nullable: true,
})
@ -54,6 +57,7 @@ export class PersonResolver {
} satisfies UpdateOnePersonArgs as Prisma.PersonUpdateArgs);
}
@UseGuards(DeleteManyGuard)
@Mutation(() => AffectedRows, {
nullable: false,
})
@ -65,6 +69,7 @@ export class PersonResolver {
});
}
@UseGuards(CreateOneGuard)
@Mutation(() => Person, {
nullable: false,
})

View File

@ -1,23 +1,20 @@
import { Resolver, Query, Args } from '@nestjs/graphql';
import { PrismaService } from 'src/database/prisma.service';
import { UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard';
import { UseFilters, UseGuards } from '@nestjs/common';
import { User } from '../@generated/user/user.model';
import { FindManyUserArgs } from '../@generated/user/find-many-user.args';
import { Workspace } from '@prisma/client';
import { AuthWorkspace } from './decorators/auth-workspace.decorator';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { ExceptionFilter } from './exception-filters/exception.filter';
import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => User)
export class UserResolver {
constructor(
private readonly prismaService: PrismaService,
private readonly argsService: ArgsService,
) {}
constructor(private readonly prismaService: PrismaService) {}
@UseFilters(ExceptionFilter)
@Query(() => [User], {
nullable: false,
})

View File

@ -1,20 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
appController = app.get<AppController>(AppController);
});
it('should be defined', () => {
expect(appController).toBeDefined();
});
});

View File

@ -1,7 +0,0 @@
import { Controller } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
}

View File

@ -1,5 +1,4 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HealthController } from './health.controller';
import { TerminusModule } from '@nestjs/terminus';
@ -9,7 +8,7 @@ import { ConfigModule } from '@nestjs/config';
import { ApiModule } from './api/api.module';
@Module({
imports: [ConfigModule.forRoot({}), TerminusModule, AuthModule, ApiModule],
controllers: [AppController, HealthController],
controllers: [HealthController],
providers: [AppService],
})
export class AppModule {}

View File

@ -5,10 +5,7 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy';
import { AuthService } from './services/auth.service';
import { GoogleAuthController } from './google.auth.controller';
import { GoogleStrategy } from './strategies/google.auth.strategy';
import { AuthController } from './auth.controller';
import { UserRepository } from 'src/entities/user/user.repository';
import { WorkspaceRepository } from 'src/entities/workspace/workspace.repository';
import { RefreshTokenRepository } from 'src/entities/refresh-token/refresh-token.repository';
import { TokenController } from './token.controller';
import { PrismaService } from 'src/database/prisma.service';
const jwtModule = JwtModule.registerAsync({
@ -26,16 +23,8 @@ const jwtModule = JwtModule.registerAsync({
@Module({
imports: [jwtModule, ConfigModule.forRoot({})],
controllers: [GoogleAuthController, AuthController],
providers: [
AuthService,
JwtAuthStrategy,
GoogleStrategy,
UserRepository,
WorkspaceRepository,
RefreshTokenRepository,
PrismaService,
],
controllers: [GoogleAuthController, TokenController],
providers: [AuthService, JwtAuthStrategy, GoogleStrategy, PrismaService],
exports: [jwtModule],
})
export class AuthModule {}

View File

@ -26,7 +26,7 @@ export class GoogleAuthController {
@Get('redirect')
@UseGuards(AuthGuard('google'))
async googleAuthRedirect(@Req() req: GoogleRequest, @Res() res: Response) {
const user = await this.authService.upsertUser(req.user);
const user = await this.authService.createUser(req.user);
if (!user) {
throw new HttpException(

View File

@ -1,85 +0,0 @@
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { Request } from 'express';
import { PrismaService } from 'src/database/prisma.service';
type OperationEntity = {
operation?: string;
entity?: string;
};
@Injectable()
export class CheckWorkspaceOwnership implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const gqlContext = GqlExecutionContext.create(context);
const request = gqlContext.getContext().req;
const { operation, entity } = this.fetchOperationAndEntity(request);
const variables = request.body.variables;
const workspace = await request.workspace;
if (!entity || !operation) {
return false;
}
if (operation === 'updateOne') {
const object = await this.prismaService[entity].findUniqueOrThrow({
where: { id: variables.id },
});
if (!object) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
if (object.workspaceId !== workspace.id) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
return true;
}
if (operation === 'deleteMany') {
// TODO: write this logic
return true;
}
if (operation === 'findMany') {
return true;
}
if (operation === 'createOne') {
return true;
}
return false;
}
private fetchOperationAndEntity(request: Request): OperationEntity {
if (!request.body.operationName) {
return { operation: undefined, entity: undefined };
}
const regex =
/(updateOne|deleteMany|createOne|findMany)(Person|Company|User)/i;
const match = request.body.query.match(regex);
if (match) {
return {
operation: match[1],
entity: match[2].toLowerCase(),
};
}
return { operation: undefined, entity: undefined };
}
}

View File

@ -2,11 +2,9 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { JwtPayload } from '../strategies/jwt.auth.strategy';
import { ConfigService } from '@nestjs/config';
import { UserRepository } from 'src/entities/user/user.repository';
import { WorkspaceRepository } from 'src/entities/workspace/workspace.repository';
import { RefreshTokenRepository } from 'src/entities/refresh-token/refresh-token.repository';
import { v4 } from 'uuid';
import { RefreshToken, User } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
export type UserPayload = {
firstName: string;
@ -19,12 +17,10 @@ export class AuthService {
constructor(
private jwtService: JwtService,
private configService: ConfigService,
private userRepository: UserRepository,
private workspaceRepository: WorkspaceRepository,
private refreshTokenRepository: RefreshTokenRepository,
private prismaService: PrismaService,
) {}
async upsertUser(rawUser: UserPayload) {
async createUser(rawUser: UserPayload) {
if (!rawUser.email) {
throw new HttpException(
{ reason: 'Email is missing' },
@ -48,7 +44,7 @@ export class AuthService {
);
}
const workspace = await this.workspaceRepository.findUnique({
const workspace = await this.prismaService.workspace.findUnique({
where: { domainName: emailDomain },
});
@ -59,50 +55,66 @@ export class AuthService {
);
}
const user = await this.userRepository.upsertUser({
data: {
id: v4(),
const user = await this.prismaService.user.upsert({
where: {
email: rawUser.email,
},
create: {
id: v4(),
displayName: rawUser.firstName + ' ' + rawUser.lastName,
email: rawUser.email,
locale: 'en',
},
workspaceId: workspace.id,
update: {},
});
await this.userRepository.upsertWorkspaceMember({
data: {
await this.prismaService.workspaceMember.upsert({
where: {
userId: user.id,
},
create: {
id: v4(),
userId: user.id,
workspaceId: workspace.id,
},
update: {},
});
return user;
}
async generateAccessToken(refreshToken: string): Promise<string | undefined> {
const refreshTokenObject = await this.refreshTokenRepository.findFirst({
const refreshTokenObject = await this.prismaService.refreshToken.findFirst({
where: { refreshToken: refreshToken },
});
if (!refreshTokenObject) {
return;
throw new HttpException(
{ reason: 'Invalid Refresh token' },
HttpStatus.FORBIDDEN,
);
}
const user = await this.userRepository.findUnique({
const user = await this.prismaService.user.findUnique({
where: { id: refreshTokenObject.userId },
});
if (!user) {
return;
throw new HttpException(
{ reason: 'Refresh token is not associated to a valid user' },
HttpStatus.FORBIDDEN,
);
}
const workspace = await this.workspaceRepository.findFirst({
const workspace = await this.prismaService.workspace.findFirst({
where: { workspaceMember: { some: { userId: user.id } } },
});
if (!workspace) {
return;
throw new HttpException(
{ reason: 'Refresh token is not associated to a valid workspace' },
HttpStatus.FORBIDDEN,
);
}
const payload: JwtPayload = {
@ -113,12 +125,16 @@ export class AuthService {
}
async registerRefreshToken(user: User): Promise<RefreshToken> {
const refreshToken = await this.refreshTokenRepository.upsertRefreshToken({
data: {
const refreshToken = await this.prismaService.refreshToken.upsert({
where: {
id: user.id,
},
create: {
id: v4(),
userId: user.id,
refreshToken: v4(),
},
update: {},
});
return refreshToken;

View File

@ -3,7 +3,7 @@ import { Request, Response } from 'express';
import { AuthService } from './services/auth.service';
@Controller('auth/token')
export class AuthController {
export class TokenController {
constructor(private authService: AuthService) {}
@Post()

View File

@ -12,35 +12,78 @@ generator nestgraphql {
provider = "node node_modules/prisma-nestjs-graphql"
output = "../../src/api/@generated"
decorate_1_type = "*CommentThreadTargetCreateNestedManyWithoutCommentThreadInput"
decorate_1_field = "!(createMany)"
decorate_1_name = "HideField"
decorate_1_from = "@nestjs/graphql"
decorate_1_arguments = "[]"
// CommentThread create: Only Allow targets createMany and comments createMany
decorate_createCommentThreadTargets_type = "*CommentThreadTargetCreateNestedManyWithoutCommentThreadInput"
decorate_createCommentThreadTargets_field = "!(createMany)"
decorate_createCommentThreadTargets_name = "HideField"
decorate_createCommentThreadTargets_from = "@nestjs/graphql"
decorate_createCommentThreadTargets_arguments = "[]"
decorate_2_type = "*CommentCreateNestedManyWithoutCommentThreadInput"
decorate_2_field = "!(createMany)"
decorate_2_name = "HideField"
decorate_2_from = "@nestjs/graphql"
decorate_2_arguments = "[]"
decorate_createCommentThreadComments_type = "*CommentCreateNestedManyWithoutCommentThreadInput"
decorate_createCommentThreadComments_field = "!(createMany)"
decorate_createCommentThreadComments_name = "HideField"
decorate_createCommentThreadComments_from = "@nestjs/graphql"
decorate_createCommentThreadComments_arguments = "[]"
decorate_3_type = "*UserCreateNestedOneWithoutCommentsInput"
decorate_3_field = "!(connect)"
decorate_3_name = "HideField"
decorate_3_from = "@nestjs/graphql"
decorate_3_arguments = "[]"
// Comment create: Only Allow author connect and commentThread connect
decorate_createCommentUser_type = "*UserCreateNestedOneWithoutCommentsInput"
decorate_createCommentUser_field = "!(connect)"
decorate_createCommentUser_name = "HideField"
decorate_createCommentUser_from = "@nestjs/graphql"
decorate_createCommentUser_arguments = "[]"
decorate_4_type = "*CommentThreadCreateNestedOneWithoutCommentsInput"
decorate_4_field = "!(connect)"
decorate_4_name = "HideField"
decorate_4_from = "@nestjs/graphql"
decorate_4_arguments = "[]"
decorate_createCommentCommentThread_type = "*CommentThreadCreateNestedOneWithoutCommentsInput"
decorate_createCommentCommentThread_field = "!(connect)"
decorate_createCommentCommentThread_name = "HideField"
decorate_createCommentCommentThread_from = "@nestjs/graphql"
decorate_createCommentCommentThread_arguments = "[]"
decorate_5_type = "!(*Aggregate*|*GroupBy*|*OrderBy*)"
decorate_5_field = "_count"
decorate_5_name = "HideField"
decorate_5_from = "@nestjs/graphql"
decorate_5_arguments = "[]"
// Person create: Only Allow company connect
decorate_createPersonCompany_type = "*CompanyCreateNestedOneWithoutPeopleInput"
decorate_createPersonCompany_field = "!(connect)"
decorate_createPersonCompany_name = "HideField"
decorate_createPersonCompany_from = "@nestjs/graphql"
decorate_createPersonCompany_arguments = "[]"
// Person update: Only Allow company connect
decorate_updatePersonCompany_type = "*CompanyUpdateOneWithoutPeopleNestedInput"
decorate_updatePersonCompany_field = "!(connect)"
decorate_updatePersonCompany_name = "HideField"
decorate_updatePersonCompany_from = "@nestjs/graphql"
decorate_updatePersonCompany_arguments = "[]"
// Company create: Only Allow people and accountOwner connect
decorate_createCompanyUser_type = "*UserCreateNestedOneWithoutCompaniesInput"
decorate_createCompanyUser_field = "!(connect)"
decorate_createCompanyUser_name = "HideField"
decorate_createCompanyUser_from = "@nestjs/graphql"
decorate_createCompanyUser_arguments = "[]"
decorate_createCompanyPerson_type = "*PersonCreateNestedManyWithoutCompanyInput"
decorate_createCompanyPerson_field = "!(connect)"
decorate_createCompanyPerson_name = "HideField"
decorate_createCompanyPerson_from = "@nestjs/graphql"
decorate_createCompanyPerson_arguments = "[]"
// Company update: Only Allow action on people and accountOwner
decorate_updateCompanyUser_type = "*UserUpdateOneWithoutCompaniesNestedInput"
decorate_updateCompanyUser_field = "!(connect)"
decorate_updateCompanyUser_name = "HideField"
decorate_updateCompanyUser_from = "@nestjs/graphql"
decorate_updateCompanyUser_arguments = "[]"
decorate_updateCompanyPerson_type = "*PersonUpdateManyWithoutCompanyNestedInput"
decorate_updateCompanyPerson_field = "!(connect)"
decorate_updateCompanyPerson_name = "HideField"
decorate_updateCompanyPerson_from = "@nestjs/graphql"
decorate_updateCompanyPerson_arguments = "[]"
// Disable _count on all models except Aggregation use case
decorate_count_type = "!(*Aggregate*|*GroupBy*|*OrderBy*)"
decorate_count_field = "_count"
decorate_count_name = "HideField"
decorate_count_from = "@nestjs/graphql"
decorate_count_arguments = "[]"
}
model User {

View File

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { CompanyRepository } from './company.repository';
import { PrismaModule } from 'src/database/prisma.module';
@Module({
imports: [PrismaModule],
providers: [CompanyRepository],
exports: [CompanyRepository],
})
export class CompanyModule {}

View File

@ -1,25 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Company, Prisma } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class CompanyRepository {
constructor(private prisma: PrismaService) {}
async findMany(params: {
skip?: number;
take?: number;
cursor?: Prisma.CompanyWhereUniqueInput;
where?: Prisma.CompanyWhereInput;
orderBy?: Prisma.CompanyOrderByWithRelationInput;
}): Promise<Company[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.company.findMany({ skip, take, cursor, where, orderBy });
}
async findOne(id: string | null) {
if (id === null) return null;
const company = await this.prisma.company.findUnique({ where: { id } });
return company;
}
}

View File

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { PersonRepository } from './person.repository';
import { PrismaModule } from 'src/database/prisma.module';
@Module({
imports: [PrismaModule],
providers: [PersonRepository],
exports: [PersonRepository],
})
export class PersonModule {}

View File

@ -1,19 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Person, Prisma } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class PersonRepository {
constructor(private prisma: PrismaService) {}
async findMany(params: {
skip?: number;
take?: number;
cursor?: Prisma.PersonWhereUniqueInput;
where?: Prisma.PersonWhereInput;
orderBy?: Prisma.PersonOrderByWithRelationInput;
}): Promise<Person[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.person.findMany({ skip, take, cursor, where, orderBy });
}
}

View File

@ -1,32 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Prisma, RefreshToken } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class RefreshTokenRepository {
constructor(private prisma: PrismaService) {}
async upsertRefreshToken(params: {
data: Prisma.RefreshTokenUncheckedCreateInput;
}): Promise<RefreshToken> {
const { data } = params;
return await this.prisma.refreshToken.upsert({
where: {
id: data.id,
},
create: {
id: data.id,
userId: data.userId,
refreshToken: data.refreshToken,
},
update: {},
});
}
async findFirst(
data: Prisma.RefreshTokenFindFirstArgs,
): Promise<RefreshToken | null> {
return await this.prisma.refreshToken.findFirst(data);
}
}

View File

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { UserRepository } from './user.repository';
import { PrismaModule } from 'src/database/prisma.module';
@Module({
imports: [PrismaModule],
providers: [UserRepository],
exports: [UserRepository],
})
export class UserModule {}

View File

@ -1,67 +0,0 @@
import { Injectable } from '@nestjs/common';
import { User, Prisma, WorkspaceMember } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class UserRepository {
constructor(private prisma: PrismaService) {}
async findMany(params: {
skip?: number;
take?: number;
cursor?: Prisma.UserWhereUniqueInput;
where?: Prisma.UserWhereInput;
orderBy?: Prisma.UserOrderByWithRelationInput;
}): Promise<User[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.user.findMany({ skip, take, cursor, where, orderBy });
}
async findUnique(params: {
where?: Prisma.UserWhereInput;
}): Promise<User | null> {
const { where } = params;
return this.prisma.user.findFirst({
where,
});
}
async upsertUser(params: {
data: Prisma.UserCreateInput;
workspaceId: string;
}): Promise<User> {
const { data } = params;
return await this.prisma.user.upsert({
where: {
email: data.email,
},
create: {
id: data.id,
displayName: data.displayName,
email: data.email,
locale: data.locale,
},
update: {},
});
}
async upsertWorkspaceMember(params: {
data: Prisma.WorkspaceMemberUncheckedCreateInput;
}): Promise<WorkspaceMember> {
const { data } = params;
return await this.prisma.workspaceMember.upsert({
where: {
userId: data.userId,
},
create: {
id: data.id,
userId: data.userId,
workspaceId: data.workspaceId,
},
update: {},
});
}
}

View File

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { WorkspaceRepository } from './workspace.repository';
import { PrismaModule } from 'src/database/prisma.module';
@Module({
imports: [PrismaModule],
providers: [WorkspaceRepository],
exports: [WorkspaceRepository],
})
export class WorkspaceModule {}

View File

@ -1,37 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Workspace, Prisma } from '@prisma/client';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class WorkspaceRepository {
constructor(private prisma: PrismaService) {}
async findMany(params: {
skip?: number;
take?: number;
cursor?: Prisma.WorkspaceWhereUniqueInput;
where?: Prisma.WorkspaceWhereInput;
orderBy?: Prisma.WorkspaceOrderByWithRelationInput;
}): Promise<Workspace[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.workspace.findMany({
skip,
take,
cursor,
where,
orderBy,
});
}
async findUnique(
params: Prisma.WorkspaceFindUniqueArgs,
): Promise<Workspace | null> {
return await this.prisma.workspace.findUnique(params);
}
async findFirst(
params: Prisma.WorkspaceFindFirstArgs,
): Promise<Workspace | null> {
return await this.prisma.workspace.findFirst(params);
}
}

View File

@ -0,0 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HealthController } from './health.controller';
import { AppService } from './app.service';
import { TerminusModule } from '@nestjs/terminus';
describe('HealthController', () => {
let healthController: HealthController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [HealthController],
imports: [TerminusModule],
providers: [AppService],
}).compile();
healthController = app.get<HealthController>(HealthController);
});
it('should be defined', () => {
expect(healthController).toBeDefined();
});
});

View File

@ -5,4 +5,5 @@ async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
}
bootstrap();