diff --git a/server/src/core/@generated/comment-thread-target/create-many-comment-thread-target.args.ts b/server/src/core/@generated/comment-thread-target/create-many-comment-thread-target.args.ts index 409492ba5..c2b72c0f2 100644 --- a/server/src/core/@generated/comment-thread-target/create-many-comment-thread-target.args.ts +++ b/server/src/core/@generated/comment-thread-target/create-many-comment-thread-target.args.ts @@ -9,8 +9,8 @@ export class CreateManyCommentThreadTargetArgs { @Field(() => [CommentThreadTargetCreateManyInput], {nullable:false}) @Type(() => CommentThreadTargetCreateManyInput) - @Type(() => CommentThreadTargetCreateManyInput) @ValidateNested({each: true}) + @Type(() => CommentThreadTargetCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/comment-thread-target/create-one-comment-thread-target.args.ts b/server/src/core/@generated/comment-thread-target/create-one-comment-thread-target.args.ts index d029ed70b..0e5ebee05 100644 --- a/server/src/core/@generated/comment-thread-target/create-one-comment-thread-target.args.ts +++ b/server/src/core/@generated/comment-thread-target/create-one-comment-thread-target.args.ts @@ -9,7 +9,7 @@ export class CreateOneCommentThreadTargetArgs { @Field(() => CommentThreadTargetCreateInput, {nullable:false}) @Type(() => CommentThreadTargetCreateInput) - @Type(() => CommentThreadTargetCreateInput) @ValidateNested({each: true}) + @Type(() => CommentThreadTargetCreateInput) data!: CommentThreadTargetCreateInput; } diff --git a/server/src/core/@generated/comment-thread-target/update-many-comment-thread-target.args.ts b/server/src/core/@generated/comment-thread-target/update-many-comment-thread-target.args.ts index 1865abdba..f2ac96498 100644 --- a/server/src/core/@generated/comment-thread-target/update-many-comment-thread-target.args.ts +++ b/server/src/core/@generated/comment-thread-target/update-many-comment-thread-target.args.ts @@ -10,8 +10,8 @@ export class UpdateManyCommentThreadTargetArgs { @Field(() => CommentThreadTargetUpdateManyMutationInput, {nullable:false}) @Type(() => CommentThreadTargetUpdateManyMutationInput) - @Type(() => CommentThreadTargetUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => CommentThreadTargetUpdateManyMutationInput) data!: CommentThreadTargetUpdateManyMutationInput; @Field(() => CommentThreadTargetWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/comment-thread-target/update-one-comment-thread-target.args.ts b/server/src/core/@generated/comment-thread-target/update-one-comment-thread-target.args.ts index 3d08745b3..7f083a66a 100644 --- a/server/src/core/@generated/comment-thread-target/update-one-comment-thread-target.args.ts +++ b/server/src/core/@generated/comment-thread-target/update-one-comment-thread-target.args.ts @@ -10,8 +10,8 @@ export class UpdateOneCommentThreadTargetArgs { @Field(() => CommentThreadTargetUpdateInput, {nullable:false}) @Type(() => CommentThreadTargetUpdateInput) - @Type(() => CommentThreadTargetUpdateInput) @ValidateNested({each: true}) + @Type(() => CommentThreadTargetUpdateInput) data!: CommentThreadTargetUpdateInput; @Field(() => CommentThreadTargetWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/comment-thread/create-many-comment-thread.args.ts b/server/src/core/@generated/comment-thread/create-many-comment-thread.args.ts index 3400a43fb..eb14acb1b 100644 --- a/server/src/core/@generated/comment-thread/create-many-comment-thread.args.ts +++ b/server/src/core/@generated/comment-thread/create-many-comment-thread.args.ts @@ -9,8 +9,8 @@ export class CreateManyCommentThreadArgs { @Field(() => [CommentThreadCreateManyInput], {nullable:false}) @Type(() => CommentThreadCreateManyInput) - @Type(() => CommentThreadCreateManyInput) @ValidateNested({each: true}) + @Type(() => CommentThreadCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/comment-thread/create-one-comment-thread.args.ts b/server/src/core/@generated/comment-thread/create-one-comment-thread.args.ts index 08d3bb108..20ed8d3e5 100644 --- a/server/src/core/@generated/comment-thread/create-one-comment-thread.args.ts +++ b/server/src/core/@generated/comment-thread/create-one-comment-thread.args.ts @@ -9,7 +9,7 @@ export class CreateOneCommentThreadArgs { @Field(() => CommentThreadCreateInput, {nullable:false}) @Type(() => CommentThreadCreateInput) - @Type(() => CommentThreadCreateInput) @ValidateNested({each: true}) + @Type(() => CommentThreadCreateInput) data!: CommentThreadCreateInput; } diff --git a/server/src/core/@generated/comment-thread/update-many-comment-thread.args.ts b/server/src/core/@generated/comment-thread/update-many-comment-thread.args.ts index b8a35f9bc..ccf3aeaf4 100644 --- a/server/src/core/@generated/comment-thread/update-many-comment-thread.args.ts +++ b/server/src/core/@generated/comment-thread/update-many-comment-thread.args.ts @@ -10,8 +10,8 @@ export class UpdateManyCommentThreadArgs { @Field(() => CommentThreadUpdateManyMutationInput, {nullable:false}) @Type(() => CommentThreadUpdateManyMutationInput) - @Type(() => CommentThreadUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => CommentThreadUpdateManyMutationInput) data!: CommentThreadUpdateManyMutationInput; @Field(() => CommentThreadWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/comment-thread/update-one-comment-thread.args.ts b/server/src/core/@generated/comment-thread/update-one-comment-thread.args.ts index 276840fa4..0c7ba7277 100644 --- a/server/src/core/@generated/comment-thread/update-one-comment-thread.args.ts +++ b/server/src/core/@generated/comment-thread/update-one-comment-thread.args.ts @@ -10,8 +10,8 @@ export class UpdateOneCommentThreadArgs { @Field(() => CommentThreadUpdateInput, {nullable:false}) @Type(() => CommentThreadUpdateInput) - @Type(() => CommentThreadUpdateInput) @ValidateNested({each: true}) + @Type(() => CommentThreadUpdateInput) data!: CommentThreadUpdateInput; @Field(() => CommentThreadWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/comment/create-many-comment.args.ts b/server/src/core/@generated/comment/create-many-comment.args.ts index bf0446052..fc752ae2b 100644 --- a/server/src/core/@generated/comment/create-many-comment.args.ts +++ b/server/src/core/@generated/comment/create-many-comment.args.ts @@ -9,8 +9,8 @@ export class CreateManyCommentArgs { @Field(() => [CommentCreateManyInput], {nullable:false}) @Type(() => CommentCreateManyInput) - @Type(() => CommentCreateManyInput) @ValidateNested({each: true}) + @Type(() => CommentCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/comment/create-one-comment.args.ts b/server/src/core/@generated/comment/create-one-comment.args.ts index 7733d478d..573b1a2e6 100644 --- a/server/src/core/@generated/comment/create-one-comment.args.ts +++ b/server/src/core/@generated/comment/create-one-comment.args.ts @@ -9,7 +9,7 @@ export class CreateOneCommentArgs { @Field(() => CommentCreateInput, {nullable:false}) @Type(() => CommentCreateInput) - @Type(() => CommentCreateInput) @ValidateNested({each: true}) + @Type(() => CommentCreateInput) data!: CommentCreateInput; } diff --git a/server/src/core/@generated/comment/update-many-comment.args.ts b/server/src/core/@generated/comment/update-many-comment.args.ts index 18e51d135..2ed02c08d 100644 --- a/server/src/core/@generated/comment/update-many-comment.args.ts +++ b/server/src/core/@generated/comment/update-many-comment.args.ts @@ -10,8 +10,8 @@ export class UpdateManyCommentArgs { @Field(() => CommentUpdateManyMutationInput, {nullable:false}) @Type(() => CommentUpdateManyMutationInput) - @Type(() => CommentUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => CommentUpdateManyMutationInput) data!: CommentUpdateManyMutationInput; @Field(() => CommentWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/comment/update-one-comment.args.ts b/server/src/core/@generated/comment/update-one-comment.args.ts index 67e763831..efeb6180f 100644 --- a/server/src/core/@generated/comment/update-one-comment.args.ts +++ b/server/src/core/@generated/comment/update-one-comment.args.ts @@ -10,8 +10,8 @@ export class UpdateOneCommentArgs { @Field(() => CommentUpdateInput, {nullable:false}) @Type(() => CommentUpdateInput) - @Type(() => CommentUpdateInput) @ValidateNested({each: true}) + @Type(() => CommentUpdateInput) data!: CommentUpdateInput; @Field(() => CommentWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/company/create-many-company.args.ts b/server/src/core/@generated/company/create-many-company.args.ts index 7cf83a514..08e78f224 100644 --- a/server/src/core/@generated/company/create-many-company.args.ts +++ b/server/src/core/@generated/company/create-many-company.args.ts @@ -9,8 +9,8 @@ export class CreateManyCompanyArgs { @Field(() => [CompanyCreateManyInput], {nullable:false}) @Type(() => CompanyCreateManyInput) - @Type(() => CompanyCreateManyInput) @ValidateNested({each: true}) + @Type(() => CompanyCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/company/create-one-company.args.ts b/server/src/core/@generated/company/create-one-company.args.ts index dbef92eae..c8dd6a033 100644 --- a/server/src/core/@generated/company/create-one-company.args.ts +++ b/server/src/core/@generated/company/create-one-company.args.ts @@ -9,7 +9,7 @@ export class CreateOneCompanyArgs { @Field(() => CompanyCreateInput, {nullable:false}) @Type(() => CompanyCreateInput) - @Type(() => CompanyCreateInput) @ValidateNested({each: true}) + @Type(() => CompanyCreateInput) data!: CompanyCreateInput; } diff --git a/server/src/core/@generated/company/update-many-company.args.ts b/server/src/core/@generated/company/update-many-company.args.ts index f722b5c4e..6672abe31 100644 --- a/server/src/core/@generated/company/update-many-company.args.ts +++ b/server/src/core/@generated/company/update-many-company.args.ts @@ -10,8 +10,8 @@ export class UpdateManyCompanyArgs { @Field(() => CompanyUpdateManyMutationInput, {nullable:false}) @Type(() => CompanyUpdateManyMutationInput) - @Type(() => CompanyUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => CompanyUpdateManyMutationInput) data!: CompanyUpdateManyMutationInput; @Field(() => CompanyWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/company/update-one-company.args.ts b/server/src/core/@generated/company/update-one-company.args.ts index 5b6fcb30c..ca5a67049 100644 --- a/server/src/core/@generated/company/update-one-company.args.ts +++ b/server/src/core/@generated/company/update-one-company.args.ts @@ -10,8 +10,8 @@ export class UpdateOneCompanyArgs { @Field(() => CompanyUpdateInput, {nullable:false}) @Type(() => CompanyUpdateInput) - @Type(() => CompanyUpdateInput) @ValidateNested({each: true}) + @Type(() => CompanyUpdateInput) data!: CompanyUpdateInput; @Field(() => CompanyWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/person/create-many-person.args.ts b/server/src/core/@generated/person/create-many-person.args.ts index afa8386df..d78b614a4 100644 --- a/server/src/core/@generated/person/create-many-person.args.ts +++ b/server/src/core/@generated/person/create-many-person.args.ts @@ -9,8 +9,8 @@ export class CreateManyPersonArgs { @Field(() => [PersonCreateManyInput], {nullable:false}) @Type(() => PersonCreateManyInput) - @Type(() => PersonCreateManyInput) @ValidateNested({each: true}) + @Type(() => PersonCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/person/create-one-person.args.ts b/server/src/core/@generated/person/create-one-person.args.ts index 84db827ae..8651efd2c 100644 --- a/server/src/core/@generated/person/create-one-person.args.ts +++ b/server/src/core/@generated/person/create-one-person.args.ts @@ -9,7 +9,7 @@ export class CreateOnePersonArgs { @Field(() => PersonCreateInput, {nullable:false}) @Type(() => PersonCreateInput) - @Type(() => PersonCreateInput) @ValidateNested({each: true}) + @Type(() => PersonCreateInput) data!: PersonCreateInput; } diff --git a/server/src/core/@generated/person/update-many-person.args.ts b/server/src/core/@generated/person/update-many-person.args.ts index 801368ed8..ba742bafd 100644 --- a/server/src/core/@generated/person/update-many-person.args.ts +++ b/server/src/core/@generated/person/update-many-person.args.ts @@ -10,8 +10,8 @@ export class UpdateManyPersonArgs { @Field(() => PersonUpdateManyMutationInput, {nullable:false}) @Type(() => PersonUpdateManyMutationInput) - @Type(() => PersonUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => PersonUpdateManyMutationInput) data!: PersonUpdateManyMutationInput; @Field(() => PersonWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/person/update-one-person.args.ts b/server/src/core/@generated/person/update-one-person.args.ts index 2501e66cc..c70516db7 100644 --- a/server/src/core/@generated/person/update-one-person.args.ts +++ b/server/src/core/@generated/person/update-one-person.args.ts @@ -10,8 +10,8 @@ export class UpdateOnePersonArgs { @Field(() => PersonUpdateInput, {nullable:false}) @Type(() => PersonUpdateInput) - @Type(() => PersonUpdateInput) @ValidateNested({each: true}) + @Type(() => PersonUpdateInput) data!: PersonUpdateInput; @Field(() => PersonWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/pipeline-progress/create-many-pipeline-progress.args.ts b/server/src/core/@generated/pipeline-progress/create-many-pipeline-progress.args.ts index c0f92417a..447f7bf6f 100644 --- a/server/src/core/@generated/pipeline-progress/create-many-pipeline-progress.args.ts +++ b/server/src/core/@generated/pipeline-progress/create-many-pipeline-progress.args.ts @@ -9,8 +9,8 @@ export class CreateManyPipelineProgressArgs { @Field(() => [PipelineProgressCreateManyInput], {nullable:false}) @Type(() => PipelineProgressCreateManyInput) - @Type(() => PipelineProgressCreateManyInput) @ValidateNested({each: true}) + @Type(() => PipelineProgressCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/pipeline-progress/create-one-pipeline-progress.args.ts b/server/src/core/@generated/pipeline-progress/create-one-pipeline-progress.args.ts index 252b38dab..3455dda8d 100644 --- a/server/src/core/@generated/pipeline-progress/create-one-pipeline-progress.args.ts +++ b/server/src/core/@generated/pipeline-progress/create-one-pipeline-progress.args.ts @@ -9,7 +9,7 @@ export class CreateOnePipelineProgressArgs { @Field(() => PipelineProgressCreateInput, {nullable:false}) @Type(() => PipelineProgressCreateInput) - @Type(() => PipelineProgressCreateInput) @ValidateNested({each: true}) + @Type(() => PipelineProgressCreateInput) data!: PipelineProgressCreateInput; } diff --git a/server/src/core/@generated/pipeline-progress/update-many-pipeline-progress.args.ts b/server/src/core/@generated/pipeline-progress/update-many-pipeline-progress.args.ts index 532d3f5c2..6e2ecd02b 100644 --- a/server/src/core/@generated/pipeline-progress/update-many-pipeline-progress.args.ts +++ b/server/src/core/@generated/pipeline-progress/update-many-pipeline-progress.args.ts @@ -10,8 +10,8 @@ export class UpdateManyPipelineProgressArgs { @Field(() => PipelineProgressUpdateManyMutationInput, {nullable:false}) @Type(() => PipelineProgressUpdateManyMutationInput) - @Type(() => PipelineProgressUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => PipelineProgressUpdateManyMutationInput) data!: PipelineProgressUpdateManyMutationInput; @Field(() => PipelineProgressWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/pipeline-progress/update-one-pipeline-progress.args.ts b/server/src/core/@generated/pipeline-progress/update-one-pipeline-progress.args.ts index 9d18d04c5..b7fbafe4b 100644 --- a/server/src/core/@generated/pipeline-progress/update-one-pipeline-progress.args.ts +++ b/server/src/core/@generated/pipeline-progress/update-one-pipeline-progress.args.ts @@ -10,8 +10,8 @@ export class UpdateOnePipelineProgressArgs { @Field(() => PipelineProgressUpdateInput, {nullable:false}) @Type(() => PipelineProgressUpdateInput) - @Type(() => PipelineProgressUpdateInput) @ValidateNested({each: true}) + @Type(() => PipelineProgressUpdateInput) data!: PipelineProgressUpdateInput; @Field(() => PipelineProgressWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/pipeline-stage/create-many-pipeline-stage.args.ts b/server/src/core/@generated/pipeline-stage/create-many-pipeline-stage.args.ts index 606acc20f..92168e92b 100644 --- a/server/src/core/@generated/pipeline-stage/create-many-pipeline-stage.args.ts +++ b/server/src/core/@generated/pipeline-stage/create-many-pipeline-stage.args.ts @@ -9,8 +9,8 @@ export class CreateManyPipelineStageArgs { @Field(() => [PipelineStageCreateManyInput], {nullable:false}) @Type(() => PipelineStageCreateManyInput) - @Type(() => PipelineStageCreateManyInput) @ValidateNested({each: true}) + @Type(() => PipelineStageCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/pipeline-stage/create-one-pipeline-stage.args.ts b/server/src/core/@generated/pipeline-stage/create-one-pipeline-stage.args.ts index 0418d91cf..5821b7a43 100644 --- a/server/src/core/@generated/pipeline-stage/create-one-pipeline-stage.args.ts +++ b/server/src/core/@generated/pipeline-stage/create-one-pipeline-stage.args.ts @@ -9,7 +9,7 @@ export class CreateOnePipelineStageArgs { @Field(() => PipelineStageCreateInput, {nullable:false}) @Type(() => PipelineStageCreateInput) - @Type(() => PipelineStageCreateInput) @ValidateNested({each: true}) + @Type(() => PipelineStageCreateInput) data!: PipelineStageCreateInput; } diff --git a/server/src/core/@generated/pipeline-stage/update-many-pipeline-stage.args.ts b/server/src/core/@generated/pipeline-stage/update-many-pipeline-stage.args.ts index a45ce9de4..ce2c3fc9a 100644 --- a/server/src/core/@generated/pipeline-stage/update-many-pipeline-stage.args.ts +++ b/server/src/core/@generated/pipeline-stage/update-many-pipeline-stage.args.ts @@ -10,8 +10,8 @@ export class UpdateManyPipelineStageArgs { @Field(() => PipelineStageUpdateManyMutationInput, {nullable:false}) @Type(() => PipelineStageUpdateManyMutationInput) - @Type(() => PipelineStageUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => PipelineStageUpdateManyMutationInput) data!: PipelineStageUpdateManyMutationInput; @Field(() => PipelineStageWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/pipeline-stage/update-one-pipeline-stage.args.ts b/server/src/core/@generated/pipeline-stage/update-one-pipeline-stage.args.ts index fe59b6317..2a8995dc5 100644 --- a/server/src/core/@generated/pipeline-stage/update-one-pipeline-stage.args.ts +++ b/server/src/core/@generated/pipeline-stage/update-one-pipeline-stage.args.ts @@ -10,8 +10,8 @@ export class UpdateOnePipelineStageArgs { @Field(() => PipelineStageUpdateInput, {nullable:false}) @Type(() => PipelineStageUpdateInput) - @Type(() => PipelineStageUpdateInput) @ValidateNested({each: true}) + @Type(() => PipelineStageUpdateInput) data!: PipelineStageUpdateInput; @Field(() => PipelineStageWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/pipeline/create-many-pipeline.args.ts b/server/src/core/@generated/pipeline/create-many-pipeline.args.ts index 9f0c2cba5..58d1a1ce7 100644 --- a/server/src/core/@generated/pipeline/create-many-pipeline.args.ts +++ b/server/src/core/@generated/pipeline/create-many-pipeline.args.ts @@ -9,8 +9,8 @@ export class CreateManyPipelineArgs { @Field(() => [PipelineCreateManyInput], {nullable:false}) @Type(() => PipelineCreateManyInput) - @Type(() => PipelineCreateManyInput) @ValidateNested({each: true}) + @Type(() => PipelineCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/pipeline/create-one-pipeline.args.ts b/server/src/core/@generated/pipeline/create-one-pipeline.args.ts index 143dea427..d27b30083 100644 --- a/server/src/core/@generated/pipeline/create-one-pipeline.args.ts +++ b/server/src/core/@generated/pipeline/create-one-pipeline.args.ts @@ -9,7 +9,7 @@ export class CreateOnePipelineArgs { @Field(() => PipelineCreateInput, {nullable:false}) @Type(() => PipelineCreateInput) - @Type(() => PipelineCreateInput) @ValidateNested({each: true}) + @Type(() => PipelineCreateInput) data!: PipelineCreateInput; } diff --git a/server/src/core/@generated/pipeline/update-many-pipeline.args.ts b/server/src/core/@generated/pipeline/update-many-pipeline.args.ts index 338e0fedc..33a24fce2 100644 --- a/server/src/core/@generated/pipeline/update-many-pipeline.args.ts +++ b/server/src/core/@generated/pipeline/update-many-pipeline.args.ts @@ -10,8 +10,8 @@ export class UpdateManyPipelineArgs { @Field(() => PipelineUpdateManyMutationInput, {nullable:false}) @Type(() => PipelineUpdateManyMutationInput) - @Type(() => PipelineUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => PipelineUpdateManyMutationInput) data!: PipelineUpdateManyMutationInput; @Field(() => PipelineWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/pipeline/update-one-pipeline.args.ts b/server/src/core/@generated/pipeline/update-one-pipeline.args.ts index 460599fba..fea3d76f5 100644 --- a/server/src/core/@generated/pipeline/update-one-pipeline.args.ts +++ b/server/src/core/@generated/pipeline/update-one-pipeline.args.ts @@ -10,8 +10,8 @@ export class UpdateOnePipelineArgs { @Field(() => PipelineUpdateInput, {nullable:false}) @Type(() => PipelineUpdateInput) - @Type(() => PipelineUpdateInput) @ValidateNested({each: true}) + @Type(() => PipelineUpdateInput) data!: PipelineUpdateInput; @Field(() => PipelineWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/refresh-token/create-many-refresh-token.args.ts b/server/src/core/@generated/refresh-token/create-many-refresh-token.args.ts index 0a8510995..abd1265fb 100644 --- a/server/src/core/@generated/refresh-token/create-many-refresh-token.args.ts +++ b/server/src/core/@generated/refresh-token/create-many-refresh-token.args.ts @@ -9,8 +9,8 @@ export class CreateManyRefreshTokenArgs { @Field(() => [RefreshTokenCreateManyInput], {nullable:false}) @Type(() => RefreshTokenCreateManyInput) - @Type(() => RefreshTokenCreateManyInput) @ValidateNested({each: true}) + @Type(() => RefreshTokenCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/refresh-token/create-one-refresh-token.args.ts b/server/src/core/@generated/refresh-token/create-one-refresh-token.args.ts index fd6f04cef..cd6d099e4 100644 --- a/server/src/core/@generated/refresh-token/create-one-refresh-token.args.ts +++ b/server/src/core/@generated/refresh-token/create-one-refresh-token.args.ts @@ -9,7 +9,7 @@ export class CreateOneRefreshTokenArgs { @Field(() => RefreshTokenCreateInput, {nullable:false}) @Type(() => RefreshTokenCreateInput) - @Type(() => RefreshTokenCreateInput) @ValidateNested({each: true}) + @Type(() => RefreshTokenCreateInput) data!: RefreshTokenCreateInput; } diff --git a/server/src/core/@generated/refresh-token/update-many-refresh-token.args.ts b/server/src/core/@generated/refresh-token/update-many-refresh-token.args.ts index 4670c0f53..51c0f7807 100644 --- a/server/src/core/@generated/refresh-token/update-many-refresh-token.args.ts +++ b/server/src/core/@generated/refresh-token/update-many-refresh-token.args.ts @@ -10,8 +10,8 @@ export class UpdateManyRefreshTokenArgs { @Field(() => RefreshTokenUpdateManyMutationInput, {nullable:false}) @Type(() => RefreshTokenUpdateManyMutationInput) - @Type(() => RefreshTokenUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => RefreshTokenUpdateManyMutationInput) data!: RefreshTokenUpdateManyMutationInput; @Field(() => RefreshTokenWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/refresh-token/update-one-refresh-token.args.ts b/server/src/core/@generated/refresh-token/update-one-refresh-token.args.ts index 53f7031d0..c878ef06b 100644 --- a/server/src/core/@generated/refresh-token/update-one-refresh-token.args.ts +++ b/server/src/core/@generated/refresh-token/update-one-refresh-token.args.ts @@ -10,8 +10,8 @@ export class UpdateOneRefreshTokenArgs { @Field(() => RefreshTokenUpdateInput, {nullable:false}) @Type(() => RefreshTokenUpdateInput) - @Type(() => RefreshTokenUpdateInput) @ValidateNested({each: true}) + @Type(() => RefreshTokenUpdateInput) data!: RefreshTokenUpdateInput; @Field(() => RefreshTokenWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/user/create-many-user.args.ts b/server/src/core/@generated/user/create-many-user.args.ts index c4911579e..e57cc3d60 100644 --- a/server/src/core/@generated/user/create-many-user.args.ts +++ b/server/src/core/@generated/user/create-many-user.args.ts @@ -9,8 +9,8 @@ export class CreateManyUserArgs { @Field(() => [UserCreateManyInput], {nullable:false}) @Type(() => UserCreateManyInput) - @Type(() => UserCreateManyInput) @ValidateNested({each: true}) + @Type(() => UserCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/user/create-one-user.args.ts b/server/src/core/@generated/user/create-one-user.args.ts index 0ae7729b1..017efd836 100644 --- a/server/src/core/@generated/user/create-one-user.args.ts +++ b/server/src/core/@generated/user/create-one-user.args.ts @@ -9,7 +9,7 @@ export class CreateOneUserArgs { @Field(() => UserCreateInput, {nullable:false}) @Type(() => UserCreateInput) - @Type(() => UserCreateInput) @ValidateNested({each: true}) + @Type(() => UserCreateInput) data!: UserCreateInput; } diff --git a/server/src/core/@generated/user/update-many-user.args.ts b/server/src/core/@generated/user/update-many-user.args.ts index 0b492226d..7b964a700 100644 --- a/server/src/core/@generated/user/update-many-user.args.ts +++ b/server/src/core/@generated/user/update-many-user.args.ts @@ -10,8 +10,8 @@ export class UpdateManyUserArgs { @Field(() => UserUpdateManyMutationInput, {nullable:false}) @Type(() => UserUpdateManyMutationInput) - @Type(() => UserUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => UserUpdateManyMutationInput) data!: UserUpdateManyMutationInput; @Field(() => UserWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/user/update-one-user.args.ts b/server/src/core/@generated/user/update-one-user.args.ts index 025f33e68..819930ca9 100644 --- a/server/src/core/@generated/user/update-one-user.args.ts +++ b/server/src/core/@generated/user/update-one-user.args.ts @@ -10,8 +10,8 @@ export class UpdateOneUserArgs { @Field(() => UserUpdateInput, {nullable:false}) @Type(() => UserUpdateInput) - @Type(() => UserUpdateInput) @ValidateNested({each: true}) + @Type(() => UserUpdateInput) data!: UserUpdateInput; @Field(() => UserWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/workspace-member/create-many-workspace-member.args.ts b/server/src/core/@generated/workspace-member/create-many-workspace-member.args.ts index 62dd8da7c..6200d2a3c 100644 --- a/server/src/core/@generated/workspace-member/create-many-workspace-member.args.ts +++ b/server/src/core/@generated/workspace-member/create-many-workspace-member.args.ts @@ -9,8 +9,8 @@ export class CreateManyWorkspaceMemberArgs { @Field(() => [WorkspaceMemberCreateManyInput], {nullable:false}) @Type(() => WorkspaceMemberCreateManyInput) - @Type(() => WorkspaceMemberCreateManyInput) @ValidateNested({each: true}) + @Type(() => WorkspaceMemberCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/workspace-member/create-one-workspace-member.args.ts b/server/src/core/@generated/workspace-member/create-one-workspace-member.args.ts index 17614ef69..81c65ffab 100644 --- a/server/src/core/@generated/workspace-member/create-one-workspace-member.args.ts +++ b/server/src/core/@generated/workspace-member/create-one-workspace-member.args.ts @@ -9,7 +9,7 @@ export class CreateOneWorkspaceMemberArgs { @Field(() => WorkspaceMemberCreateInput, {nullable:false}) @Type(() => WorkspaceMemberCreateInput) - @Type(() => WorkspaceMemberCreateInput) @ValidateNested({each: true}) + @Type(() => WorkspaceMemberCreateInput) data!: WorkspaceMemberCreateInput; } diff --git a/server/src/core/@generated/workspace-member/update-many-workspace-member.args.ts b/server/src/core/@generated/workspace-member/update-many-workspace-member.args.ts index d850a6eb0..3b90fb76a 100644 --- a/server/src/core/@generated/workspace-member/update-many-workspace-member.args.ts +++ b/server/src/core/@generated/workspace-member/update-many-workspace-member.args.ts @@ -10,8 +10,8 @@ export class UpdateManyWorkspaceMemberArgs { @Field(() => WorkspaceMemberUpdateManyMutationInput, {nullable:false}) @Type(() => WorkspaceMemberUpdateManyMutationInput) - @Type(() => WorkspaceMemberUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => WorkspaceMemberUpdateManyMutationInput) data!: WorkspaceMemberUpdateManyMutationInput; @Field(() => WorkspaceMemberWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/workspace-member/update-one-workspace-member.args.ts b/server/src/core/@generated/workspace-member/update-one-workspace-member.args.ts index 4f5f2b2d4..06e17b917 100644 --- a/server/src/core/@generated/workspace-member/update-one-workspace-member.args.ts +++ b/server/src/core/@generated/workspace-member/update-one-workspace-member.args.ts @@ -10,8 +10,8 @@ export class UpdateOneWorkspaceMemberArgs { @Field(() => WorkspaceMemberUpdateInput, {nullable:false}) @Type(() => WorkspaceMemberUpdateInput) - @Type(() => WorkspaceMemberUpdateInput) @ValidateNested({each: true}) + @Type(() => WorkspaceMemberUpdateInput) data!: WorkspaceMemberUpdateInput; @Field(() => WorkspaceMemberWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/@generated/workspace/create-many-workspace.args.ts b/server/src/core/@generated/workspace/create-many-workspace.args.ts index 11636c24d..9dc7e7e9e 100644 --- a/server/src/core/@generated/workspace/create-many-workspace.args.ts +++ b/server/src/core/@generated/workspace/create-many-workspace.args.ts @@ -9,8 +9,8 @@ export class CreateManyWorkspaceArgs { @Field(() => [WorkspaceCreateManyInput], {nullable:false}) @Type(() => WorkspaceCreateManyInput) - @Type(() => WorkspaceCreateManyInput) @ValidateNested({each: true}) + @Type(() => WorkspaceCreateManyInput) data!: Array; @Field(() => Boolean, {nullable:true}) diff --git a/server/src/core/@generated/workspace/create-one-workspace.args.ts b/server/src/core/@generated/workspace/create-one-workspace.args.ts index 22b1f766f..ce2dec159 100644 --- a/server/src/core/@generated/workspace/create-one-workspace.args.ts +++ b/server/src/core/@generated/workspace/create-one-workspace.args.ts @@ -9,7 +9,7 @@ export class CreateOneWorkspaceArgs { @Field(() => WorkspaceCreateInput, {nullable:false}) @Type(() => WorkspaceCreateInput) - @Type(() => WorkspaceCreateInput) @ValidateNested({each: true}) + @Type(() => WorkspaceCreateInput) data!: WorkspaceCreateInput; } diff --git a/server/src/core/@generated/workspace/update-many-workspace.args.ts b/server/src/core/@generated/workspace/update-many-workspace.args.ts index ee0c3f95f..7772c4a69 100644 --- a/server/src/core/@generated/workspace/update-many-workspace.args.ts +++ b/server/src/core/@generated/workspace/update-many-workspace.args.ts @@ -10,8 +10,8 @@ export class UpdateManyWorkspaceArgs { @Field(() => WorkspaceUpdateManyMutationInput, {nullable:false}) @Type(() => WorkspaceUpdateManyMutationInput) - @Type(() => WorkspaceUpdateManyMutationInput) @ValidateNested({each: true}) + @Type(() => WorkspaceUpdateManyMutationInput) data!: WorkspaceUpdateManyMutationInput; @Field(() => WorkspaceWhereInput, {nullable:true}) diff --git a/server/src/core/@generated/workspace/update-one-workspace.args.ts b/server/src/core/@generated/workspace/update-one-workspace.args.ts index 151ae42a1..d28d7161b 100644 --- a/server/src/core/@generated/workspace/update-one-workspace.args.ts +++ b/server/src/core/@generated/workspace/update-one-workspace.args.ts @@ -10,8 +10,8 @@ export class UpdateOneWorkspaceArgs { @Field(() => WorkspaceUpdateInput, {nullable:false}) @Type(() => WorkspaceUpdateInput) - @Type(() => WorkspaceUpdateInput) @ValidateNested({each: true}) + @Type(() => WorkspaceUpdateInput) data!: WorkspaceUpdateInput; @Field(() => WorkspaceWhereUniqueInput, {nullable:false}) diff --git a/server/src/core/file/controllers/file.controller.ts b/server/src/core/file/controllers/file.controller.ts index b50004af7..7b7761aee 100644 --- a/server/src/core/file/controllers/file.controller.ts +++ b/server/src/core/file/controllers/file.controller.ts @@ -1,10 +1,9 @@ -import { Controller, Get, Param, Res, UseGuards } from '@nestjs/common'; +import { Controller, Get, Param, Res } from '@nestjs/common'; import { Response } from 'express'; import { checkFilePath, checkFilename } from '../file.utils'; import { FileService } from '../services/file.service'; -import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; -@UseGuards(JwtAuthGuard) +// TODO: Add cookie authentication @Controller('files') export class FileController { constructor(private readonly fileService: FileService) {} diff --git a/server/src/core/file/services/file-upload.service.spec.ts b/server/src/core/file/services/file-upload.service.spec.ts index ab092c1e8..ae39c8df5 100644 --- a/server/src/core/file/services/file-upload.service.spec.ts +++ b/server/src/core/file/services/file-upload.service.spec.ts @@ -1,8 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { FileUploadService } from './file-upload.service'; -import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service'; -import { LocalStorageService } from 'src/integrations/local-storage/local-storage.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { FileStorageService } from 'src/integrations/file-storage/file-storage.service'; describe('FileUploadService', () => { let service: FileUploadService; @@ -12,11 +11,7 @@ describe('FileUploadService', () => { providers: [ FileUploadService, { - provide: S3StorageService, - useValue: {}, - }, - { - provide: LocalStorageService, + provide: FileStorageService, useValue: {}, }, { diff --git a/server/src/core/file/services/file-upload.service.ts b/server/src/core/file/services/file-upload.service.ts index 779113d5e..f17ad5d49 100644 --- a/server/src/core/file/services/file-upload.service.ts +++ b/server/src/core/file/services/file-upload.service.ts @@ -1,20 +1,13 @@ import { Injectable } from '@nestjs/common'; import sharp from 'sharp'; -import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service'; -import { kebabCase } from 'src/utils/kebab-case'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { LocalStorageService } from 'src/integrations/local-storage/local-storage.service'; import { getCropSize } from 'src/utils/image'; import { settings } from 'src/constants/settings'; import { FileFolder } from '../interfaces/file-folder.interface'; +import { FileStorageService } from 'src/integrations/file-storage/file-storage.service'; @Injectable() export class FileUploadService { - constructor( - private readonly s3Storage: S3StorageService, - private readonly localStorage: LocalStorageService, - private readonly environmentService: EnvironmentService, - ) {} + constructor(private readonly fileStorage: FileStorageService) {} async uploadFile({ file, @@ -27,23 +20,16 @@ export class FileUploadService { mimeType: string | undefined; fileFolder: FileFolder; }) { - const storageType = this.environmentService.getStorageType(); + await this.fileStorage.write({ + file, + name, + mimeType, + folder: fileFolder, + }); - switch (storageType) { - case 's3': { - await this.uploadFileToS3(file, name, mimeType, fileFolder); - return { - name: `/${name}`, - }; - } - case 'local': - default: { - await this.uploadToLocal(file, name, fileFolder); - return { - name: `/${name}`, - }; - } - } + return { + name: `/${name}`, + }; } async uploadImage({ @@ -88,48 +74,4 @@ export class FileUploadService { name: `/${name}`, }; } - - private async uploadToLocal( - file: Buffer | Uint8Array | string, - name: string, - fileFolder: FileFolder, - ): Promise { - const folderName = kebabCase(fileFolder.toString()); - - try { - const result = await this.localStorage.uploadFile({ - file, - name, - folder: folderName, - }); - - return result; - } catch (err) { - console.log('uploadFile error: ', err); - throw err; - } - } - - private async uploadFileToS3( - file: Buffer | Uint8Array | string, - name: string, - mimeType: string | undefined, - fileFolder: FileFolder, - ) { - // Aws only accept bucket with kebab-case name - const bucketFolderName = kebabCase(fileFolder.toString()); - - try { - const result = await this.s3Storage.uploadFile({ - Key: `${bucketFolderName}/${name}`, - Body: file, - ContentType: mimeType, - }); - - return result; - } catch (err) { - console.log('uploadFile error: ', err); - throw err; - } - } } diff --git a/server/src/core/file/services/file.service.spec.ts b/server/src/core/file/services/file.service.spec.ts index 9f425584e..69ebbf7d7 100644 --- a/server/src/core/file/services/file.service.spec.ts +++ b/server/src/core/file/services/file.service.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { FileService } from './file.service'; -import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; +import { FileStorageService } from 'src/integrations/file-storage/file-storage.service'; describe('FileService', () => { let service: FileService; @@ -11,7 +11,7 @@ describe('FileService', () => { providers: [ FileService, { - provide: S3StorageService, + provide: FileStorageService, useValue: {}, }, { diff --git a/server/src/core/file/services/file.service.ts b/server/src/core/file/services/file.service.ts index 51d3b993f..23e584d6c 100644 --- a/server/src/core/file/services/file.service.ts +++ b/server/src/core/file/services/file.service.ts @@ -1,55 +1,14 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service'; -import { EnvironmentService } from 'src/integrations/environment/environment.service'; -import { createReadStream } from 'fs'; -import { join } from 'path'; -import { Readable } from 'stream'; +import { Injectable } from '@nestjs/common'; +import { FileStorageService } from 'src/integrations/file-storage/file-storage.service'; @Injectable() export class FileService { - constructor( - private readonly s3Storage: S3StorageService, - private readonly environmentService: EnvironmentService, - ) {} + constructor(private readonly fileStorageService: FileStorageService) {} async getFileStream(folderPath: string, filename: string) { - const storageType = this.environmentService.getStorageType(); - - switch (storageType) { - case 's3': - return this.getS3FileStream(folderPath, filename); - case 'local': - default: - return this.getLocalFileStream(folderPath, filename); - } - } - - private async getLocalFileStream(folderPath: string, filename: string) { - const storageLocation = this.environmentService.getStorageLocalPath(); - - const filePath = join( - process.cwd(), - `${storageLocation}/`, + return this.fileStorageService.read({ folderPath, filename, - ); - - return createReadStream(filePath); - } - - private async getS3FileStream(folderPath: string, filename: string) { - try { - const file = await this.s3Storage.getFile({ - Key: `${folderPath}/${filename}`, - }); - - if (!file || !file.Body || !(file.Body instanceof Readable)) { - throw new Error('Unable to get file stream'); - } - - return Readable.from(file.Body); - } catch (error) { - throw new NotFoundException('File not found'); - } + }); } } diff --git a/server/src/integrations/file-storage/drivers/interfaces/storage-driver.interface.ts b/server/src/integrations/file-storage/drivers/interfaces/storage-driver.interface.ts new file mode 100644 index 000000000..6f1280cd7 --- /dev/null +++ b/server/src/integrations/file-storage/drivers/interfaces/storage-driver.interface.ts @@ -0,0 +1,11 @@ +import { Readable } from 'stream'; + +export interface StorageDriver { + read(params: { folderPath: string; filename: string }): Promise; + write(params: { + file: Buffer | Uint8Array | string; + name: string; + folder: string; + mimeType: string | undefined; + }): Promise; +} diff --git a/server/src/integrations/file-storage/drivers/local.driver.ts b/server/src/integrations/file-storage/drivers/local.driver.ts new file mode 100644 index 000000000..72746d704 --- /dev/null +++ b/server/src/integrations/file-storage/drivers/local.driver.ts @@ -0,0 +1,57 @@ +import * as fs from 'fs/promises'; +import { createReadStream, existsSync } from 'fs'; +import { join, dirname } from 'path'; +import { StorageDriver } from './interfaces/storage-driver.interface'; +import { Readable } from 'stream'; +import { kebabCase } from 'src/utils/kebab-case'; + +export interface LocalDriverOptions { + storagePath: string; +} + +export class LocalDriver implements StorageDriver { + private options: LocalDriverOptions; + + constructor(options: LocalDriverOptions) { + this.options = options; + } + + async createFolder(path: string) { + if (existsSync(path)) { + return; + } + + return fs.mkdir(path, { recursive: true }); + } + + async write(params: { + file: Buffer | Uint8Array | string; + name: string; + folder: string; + mimeType: string | undefined; + }): Promise { + const filePath = join( + `${this.options.storagePath}/`, + kebabCase(params.folder), + params.name, + ); + const folderPath = dirname(filePath); + + await this.createFolder(folderPath); + + await fs.writeFile(filePath, params.file); + } + + async read(params: { + folderPath: string; + filename: string; + }): Promise { + const filePath = join( + `${this.options.storagePath}/`, + params.folderPath, + params.filename, + ); + + return createReadStream(filePath); + } +} diff --git a/server/src/integrations/s3-storage/s3-storage.service.ts b/server/src/integrations/file-storage/drivers/s3.driver.ts similarity index 53% rename from server/src/integrations/s3-storage/s3-storage.service.ts rename to server/src/integrations/file-storage/drivers/s3.driver.ts index b4d82a807..5bf6170b7 100644 --- a/server/src/integrations/s3-storage/s3-storage.service.ts +++ b/server/src/integrations/file-storage/drivers/s3.driver.ts @@ -1,28 +1,26 @@ -import { Injectable, Inject } from '@nestjs/common'; -import { MODULE_OPTIONS_TOKEN } from './s3-storage.module-definition'; -import { S3StorageModuleOptions } from './interfaces'; import { CreateBucketCommandInput, GetObjectCommand, - GetObjectCommandInput, - GetObjectCommandOutput, HeadBucketCommandInput, NotFound, PutObjectCommand, - PutObjectCommandInput, - PutObjectCommandOutput, S3, + S3ClientConfig, } from '@aws-sdk/client-s3'; +import { StorageDriver } from './interfaces/storage-driver.interface'; +import { Readable } from 'stream'; +import { kebabCase } from 'src/utils/kebab-case'; -@Injectable() -export class S3StorageService { +export interface S3DriverOptions extends S3ClientConfig { + bucketName: string; + region: string; +} + +export class S3Driver implements StorageDriver { private s3Client: S3; private bucketName: string; - constructor( - @Inject(MODULE_OPTIONS_TOKEN) - private readonly options: S3StorageModuleOptions, - ) { + constructor(options: S3DriverOptions) { const { bucketName, region, ...s3Options } = options; if (!bucketName || !region) { @@ -37,28 +35,39 @@ export class S3StorageService { return this.s3Client; } - async uploadFile( - params: Omit, - ): Promise { + async write(params: { + file: Buffer | Uint8Array | string; + name: string; + folder: string; + mimeType: string | undefined; + }): Promise { const command = new PutObjectCommand({ - ...params, + Key: `${kebabCase(params.folder)}/${params.name}`, + Body: params.file, + ContentType: params.mimeType, Bucket: this.bucketName, }); await this.createBucket({ Bucket: this.bucketName }); - return this.s3Client.send(command); + await this.s3Client.send(command); } - async getFile( - params: Omit, - ): Promise { + async read(params: { + folderPath: string; + filename: string; + }): Promise { const command = new GetObjectCommand({ - ...params, + Key: `${params.folderPath}/${params.filename}`, Bucket: this.bucketName, }); + const file = await this.s3Client.send(command); - return this.s3Client.send(command); + if (!file || !file.Body || !(file.Body instanceof Readable)) { + throw new Error('Unable to get file stream'); + } + + return Readable.from(file.Body); } async checkBucketExists(args: HeadBucketCommandInput) { diff --git a/server/src/integrations/file-storage/file-storage.constants.ts b/server/src/integrations/file-storage/file-storage.constants.ts new file mode 100644 index 000000000..1c726adbc --- /dev/null +++ b/server/src/integrations/file-storage/file-storage.constants.ts @@ -0,0 +1 @@ +export const STORAGE_DRIVER = Symbol('STORAGE_DRIVER'); diff --git a/server/src/integrations/file-storage/file-storage.module-definition.ts b/server/src/integrations/file-storage/file-storage.module-definition.ts new file mode 100644 index 000000000..e3b6bc298 --- /dev/null +++ b/server/src/integrations/file-storage/file-storage.module-definition.ts @@ -0,0 +1,13 @@ +import { ConfigurableModuleBuilder } from '@nestjs/common'; +import { FileStorageModuleOptions } from './interfaces'; + +export const { + ConfigurableModuleClass, + MODULE_OPTIONS_TOKEN, + OPTIONS_TYPE, + ASYNC_OPTIONS_TYPE, +} = new ConfigurableModuleBuilder({ + moduleName: 'FileStorage', +}) + .setClassMethodName('forRoot') + .build(); diff --git a/server/src/integrations/file-storage/file-storage.module.ts b/server/src/integrations/file-storage/file-storage.module.ts new file mode 100644 index 000000000..c6e1b75dc --- /dev/null +++ b/server/src/integrations/file-storage/file-storage.module.ts @@ -0,0 +1,48 @@ +import { DynamicModule, Global } from '@nestjs/common'; +import { FileStorageService } from './file-storage.service'; +import { LocalDriver } from './drivers/local.driver'; +import { S3Driver } from './drivers/s3.driver'; +import { + FileStorageModuleAsyncOptions, + FileStorageModuleOptions, +} from './interfaces'; +import { STORAGE_DRIVER } from './file-storage.constants'; + +@Global() +export class FileStorageModule { + static forRoot(options: FileStorageModuleOptions): DynamicModule { + const provider = { + provide: STORAGE_DRIVER, + useValue: + options.type === 's3' + ? new S3Driver(options.options) + : new LocalDriver(options.options), + }; + + return { + module: FileStorageModule, + providers: [FileStorageService, provider], + exports: [FileStorageService], + }; + } + + static forRootAsync(options: FileStorageModuleAsyncOptions): DynamicModule { + const provider = { + provide: STORAGE_DRIVER, + useFactory: async (...args: any[]) => { + const config = await options.useFactory(...args); + return config?.type === 's3' + ? new S3Driver(config.options) + : new LocalDriver(config.options); + }, + inject: options.inject || [], + }; + + return { + module: FileStorageModule, + imports: options.imports || [], + providers: [FileStorageService, provider], + exports: [FileStorageService], + }; + } +} diff --git a/server/src/integrations/s3-storage/s3-storage.service.spec.ts b/server/src/integrations/file-storage/file-storage.service.spec.ts similarity index 50% rename from server/src/integrations/s3-storage/s3-storage.service.spec.ts rename to server/src/integrations/file-storage/file-storage.service.spec.ts index 231dbb659..26af91020 100644 --- a/server/src/integrations/s3-storage/s3-storage.service.spec.ts +++ b/server/src/integrations/file-storage/file-storage.service.spec.ts @@ -1,22 +1,22 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { S3StorageService } from './s3-storage.service'; -import { MODULE_OPTIONS_TOKEN } from './s3-storage.module-definition'; +import { FileStorageService } from './file-storage.service'; +import { STORAGE_DRIVER } from './file-storage.constants'; -describe('S3StorageService', () => { - let service: S3StorageService; +describe('FileStorageService', () => { + let service: FileStorageService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - S3StorageService, + FileStorageService, { - provide: MODULE_OPTIONS_TOKEN, + provide: STORAGE_DRIVER, useValue: {}, }, ], }).compile(); - service = module.get(S3StorageService); + service = module.get(FileStorageService); }); it('should be defined', () => { diff --git a/server/src/integrations/file-storage/file-storage.service.ts b/server/src/integrations/file-storage/file-storage.service.ts new file mode 100644 index 000000000..c55d8f5f5 --- /dev/null +++ b/server/src/integrations/file-storage/file-storage.service.ts @@ -0,0 +1,22 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { STORAGE_DRIVER } from './file-storage.constants'; +import { StorageDriver } from './drivers/interfaces/storage-driver.interface'; +import { Readable } from 'stream'; + +@Injectable() +export class FileStorageService implements StorageDriver { + constructor(@Inject(STORAGE_DRIVER) private driver: StorageDriver) {} + + write(params: { + file: string | Buffer | Uint8Array; + name: string; + folder: string; + mimeType: string | undefined; + }): Promise { + return this.driver.write(params); + } + + read(params: { folderPath: string; filename: string }): Promise { + return this.driver.read(params); + } +} diff --git a/server/src/integrations/file-storage/interfaces/file-storage.interface.ts b/server/src/integrations/file-storage/interfaces/file-storage.interface.ts new file mode 100644 index 000000000..bfc1070c2 --- /dev/null +++ b/server/src/integrations/file-storage/interfaces/file-storage.interface.ts @@ -0,0 +1,25 @@ +import { StorageType } from 'src/integrations/environment/interfaces/storage.interface'; +import { S3DriverOptions } from '../drivers/s3.driver'; +import { LocalDriverOptions } from '../drivers/local.driver'; +import { FactoryProvider, ModuleMetadata } from '@nestjs/common'; + +export interface S3DriverFactoryOptions { + type: StorageType.S3; + options: S3DriverOptions; +} + +export interface LocalDriverFactoryOptions { + type: StorageType.Local; + options: LocalDriverOptions; +} + +export type FileStorageModuleOptions = + | S3DriverFactoryOptions + | LocalDriverFactoryOptions; + +export type FileStorageModuleAsyncOptions = { + useFactory: ( + ...args: any[] + ) => FileStorageModuleOptions | Promise; +} & Pick & + Pick; diff --git a/server/src/integrations/file-storage/interfaces/index.ts b/server/src/integrations/file-storage/interfaces/index.ts new file mode 100644 index 000000000..6abeadb10 --- /dev/null +++ b/server/src/integrations/file-storage/interfaces/index.ts @@ -0,0 +1 @@ +export * from './file-storage.interface'; diff --git a/server/src/integrations/integrations.module.ts b/server/src/integrations/integrations.module.ts index c8d868e66..d6b260435 100644 --- a/server/src/integrations/integrations.module.ts +++ b/server/src/integrations/integrations.module.ts @@ -1,59 +1,61 @@ import { Module } from '@nestjs/common'; import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; -import { S3StorageModule } from './s3-storage/s3-storage.module'; -import { S3StorageModuleOptions } from './s3-storage/interfaces'; -import { LocalStorageModule } from './local-storage/local-storage.module'; -import { LocalStorageModuleOptions } from './local-storage/interfaces'; import { EnvironmentModule } from './environment/environment.module'; import { EnvironmentService } from './environment/environment.service'; +import { FileStorageModule } from './file-storage/file-storage.module'; +import { FileStorageModuleOptions } from './file-storage/interfaces'; +import { StorageType } from './environment/interfaces/storage.interface'; /** - * S3 Storage Module factory - * @param config - * @returns S3ModuleOptions - */ -const S3StorageModuleFactory = async ( - environmentService: EnvironmentService, -): Promise => { - const bucketName = environmentService.getStorageS3Name(); - const region = environmentService.getStorageS3Region(); - - return { - bucketName: bucketName ?? '', - credentials: fromNodeProviderChain({ - clientConfig: { region }, - }), - forcePathStyle: true, - region: region ?? '', - }; -}; - -/** - * LocalStorage Module factory + * FileStorage Module factory * @param environment - * @returns LocalStorageModuleOptions + * @returns FileStorageModuleOptions */ -const localStorageModuleFactory = async ( +const fileStorageModuleFactory = async ( environmentService: EnvironmentService, -): Promise => { - const storagePath = environmentService.getStorageLocalPath(); +): Promise => { + const type = environmentService.getStorageType(); - return { - storagePath: process.cwd() + '/' + storagePath, - }; + switch (type) { + case undefined: + case StorageType.Local: { + const storagePath = environmentService.getStorageLocalPath(); + + return { + type: StorageType.Local, + options: { + storagePath: process.cwd() + '/' + storagePath, + }, + }; + } + case StorageType.S3: { + const bucketName = environmentService.getStorageS3Name(); + const region = environmentService.getStorageS3Region(); + + return { + type: StorageType.S3, + options: { + bucketName: bucketName ?? '', + credentials: fromNodeProviderChain({ + clientConfig: { region }, + }), + forcePathStyle: true, + region: region ?? '', + }, + }; + } + default: + throw new Error(`Invalid storage type (${type}), check your .env file`); + } }; @Module({ imports: [ - S3StorageModule.forRootAsync({ - useFactory: S3StorageModuleFactory, - inject: [EnvironmentService], - }), - LocalStorageModule.forRootAsync({ - useFactory: localStorageModuleFactory, - inject: [EnvironmentService], - }), EnvironmentModule.forRoot({}), + FileStorageModule.forRootAsync({ + useFactory: fileStorageModuleFactory, + inject: [EnvironmentService], + }), ], exports: [], providers: [], diff --git a/server/src/integrations/local-storage/interfaces/index.ts b/server/src/integrations/local-storage/interfaces/index.ts deleted file mode 100644 index eeafd32c3..000000000 --- a/server/src/integrations/local-storage/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './local-storage.interface'; diff --git a/server/src/integrations/local-storage/interfaces/local-storage.interface.ts b/server/src/integrations/local-storage/interfaces/local-storage.interface.ts deleted file mode 100644 index b5ac7f6bd..000000000 --- a/server/src/integrations/local-storage/interfaces/local-storage.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface LocalStorageModuleOptions { - storagePath: string; -} diff --git a/server/src/integrations/local-storage/local-storage.module-definition.ts b/server/src/integrations/local-storage/local-storage.module-definition.ts deleted file mode 100644 index 9fe25f7ee..000000000 --- a/server/src/integrations/local-storage/local-storage.module-definition.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { LocalStorageModuleOptions } from './interfaces'; - -export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = - new ConfigurableModuleBuilder({ - moduleName: 'LocalStorage', - }) - .setClassMethodName('forRoot') - .build(); diff --git a/server/src/integrations/local-storage/local-storage.module.ts b/server/src/integrations/local-storage/local-storage.module.ts deleted file mode 100644 index bb4f0d430..000000000 --- a/server/src/integrations/local-storage/local-storage.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Global, Module } from '@nestjs/common'; -import { LocalStorageService } from './local-storage.service'; -import { ConfigurableModuleClass } from './local-storage.module-definition'; - -@Global() -@Module({ - providers: [LocalStorageService], - exports: [LocalStorageService], -}) -export class LocalStorageModule extends ConfigurableModuleClass {} diff --git a/server/src/integrations/local-storage/local-storage.service.spec.ts b/server/src/integrations/local-storage/local-storage.service.spec.ts deleted file mode 100644 index 754462a63..000000000 --- a/server/src/integrations/local-storage/local-storage.service.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { LocalStorageService } from './local-storage.service'; -import { MODULE_OPTIONS_TOKEN } from './local-storage.module-definition'; - -describe('LocalStorageService', () => { - let service: LocalStorageService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - LocalStorageService, - { - provide: MODULE_OPTIONS_TOKEN, - useValue: {}, - }, - ], - }).compile(); - - service = module.get(LocalStorageService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/server/src/integrations/local-storage/local-storage.service.ts b/server/src/integrations/local-storage/local-storage.service.ts deleted file mode 100644 index bb8dcffea..000000000 --- a/server/src/integrations/local-storage/local-storage.service.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Injectable, Inject } from '@nestjs/common'; -import * as fs from 'fs/promises'; -import { existsSync } from 'fs'; -import * as path from 'path'; -import { MODULE_OPTIONS_TOKEN } from './local-storage.module-definition'; -import { LocalStorageModuleOptions } from './interfaces'; - -@Injectable() -export class LocalStorageService { - constructor( - @Inject(MODULE_OPTIONS_TOKEN) - private readonly options: LocalStorageModuleOptions, - ) {} - - async createFolder(path: string) { - if (existsSync(path)) { - return; - } - - return fs.mkdir(path, { recursive: true }); - } - - async uploadFile(params: { - file: Buffer | Uint8Array | string; - name: string; - folder: string; - }) { - const filePath = `${this.options.storagePath}/${params.folder}/${params.name}`; - const folderPath = path.dirname(filePath); - - await this.createFolder(folderPath); - - return fs.writeFile(filePath, params.file); - } -} diff --git a/server/src/integrations/s3-storage/interfaces/index.ts b/server/src/integrations/s3-storage/interfaces/index.ts deleted file mode 100644 index 52408298f..000000000 --- a/server/src/integrations/s3-storage/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './s3-storage-module.interface'; diff --git a/server/src/integrations/s3-storage/interfaces/s3-storage-module.interface.ts b/server/src/integrations/s3-storage/interfaces/s3-storage-module.interface.ts deleted file mode 100644 index 426ba7615..000000000 --- a/server/src/integrations/s3-storage/interfaces/s3-storage-module.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { S3ClientConfig } from '@aws-sdk/client-s3'; - -export interface S3StorageModuleOptions extends S3ClientConfig { - bucketName: string; - region: string; -} diff --git a/server/src/integrations/s3-storage/s3-storage.module-definition.ts b/server/src/integrations/s3-storage/s3-storage.module-definition.ts deleted file mode 100644 index ccb3fef88..000000000 --- a/server/src/integrations/s3-storage/s3-storage.module-definition.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ConfigurableModuleBuilder } from '@nestjs/common'; -import { S3StorageModuleOptions } from './interfaces'; - -export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = - new ConfigurableModuleBuilder({ - moduleName: 'S3Storage', - }) - .setClassMethodName('forRoot') - .build(); diff --git a/server/src/integrations/s3-storage/s3-storage.module.ts b/server/src/integrations/s3-storage/s3-storage.module.ts deleted file mode 100644 index e17d27f1c..000000000 --- a/server/src/integrations/s3-storage/s3-storage.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Global, Module } from '@nestjs/common'; -import { S3StorageService } from './s3-storage.service'; -import { ConfigurableModuleClass } from './s3-storage.module-definition'; - -@Global() -@Module({ - providers: [S3StorageService], - exports: [S3StorageService], -}) -export class S3StorageModule extends ConfigurableModuleClass {}