video.resolver.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import {
  2. Arg,
  3. Args,
  4. Mutation,
  5. Query,
  6. Root,
  7. Resolver,
  8. FieldResolver,
  9. ObjectType,
  10. Field,
  11. Int,
  12. ArgsType,
  13. Info,
  14. } from 'type-graphql';
  15. import graphqlFields from 'graphql-fields';
  16. import { Inject } from 'typedi';
  17. import { Min } from 'class-validator';
  18. import { Fields, StandardDeleteResponse, UserId, PageInfo, RawFields } from 'warthog';
  19. import {
  20. VideoCreateInput,
  21. VideoCreateManyArgs,
  22. VideoUpdateArgs,
  23. VideoWhereArgs,
  24. VideoWhereInput,
  25. VideoWhereUniqueInput,
  26. VideoOrderByEnum,
  27. } from '../../../generated';
  28. import { Video } from './video.model';
  29. import { VideoService } from './video.service';
  30. import { Channel } from '../channel/channel.model';
  31. import { VideoCategory } from '../video-category/video-category.model';
  32. import { DataObject } from '../data-object/data-object.model';
  33. import { Language } from '../language/language.model';
  34. import { License } from '../license/license.model';
  35. import { VideoMediaMetadata } from '../video-media-metadata/video-media-metadata.model';
  36. import { FeaturedVideo } from '../featured-video/featured-video.model';
  37. import { getConnection } from 'typeorm';
  38. @ObjectType()
  39. export class VideoEdge {
  40. @Field(() => Video, { nullable: false })
  41. node!: Video;
  42. @Field(() => String, { nullable: false })
  43. cursor!: string;
  44. }
  45. @ObjectType()
  46. export class VideoConnection {
  47. @Field(() => Int, { nullable: false })
  48. totalCount!: number;
  49. @Field(() => [VideoEdge], { nullable: false })
  50. edges!: VideoEdge[];
  51. @Field(() => PageInfo, { nullable: false })
  52. pageInfo!: PageInfo;
  53. }
  54. @ArgsType()
  55. export class ConnectionPageInputOptions {
  56. @Field(() => Int, { nullable: true })
  57. @Min(0)
  58. first?: number;
  59. @Field(() => String, { nullable: true })
  60. after?: string; // V3: TODO: should we make a RelayCursor scalar?
  61. @Field(() => Int, { nullable: true })
  62. @Min(0)
  63. last?: number;
  64. @Field(() => String, { nullable: true })
  65. before?: string;
  66. }
  67. @ArgsType()
  68. export class VideoConnectionWhereArgs extends ConnectionPageInputOptions {
  69. @Field(() => VideoWhereInput, { nullable: true })
  70. where?: VideoWhereInput;
  71. @Field(() => VideoOrderByEnum, { nullable: true })
  72. orderBy?: VideoOrderByEnum;
  73. }
  74. @Resolver(Video)
  75. export class VideoResolver {
  76. constructor(@Inject('VideoService') public readonly service: VideoService) {}
  77. @Query(() => [Video])
  78. async videos(
  79. @Args() { where, orderBy, limit, offset }: VideoWhereArgs,
  80. @Fields() fields: string[]
  81. ): Promise<Video[]> {
  82. return this.service.find<VideoWhereInput>(where, orderBy, limit, offset, fields);
  83. }
  84. @Query(() => Video, { nullable: true })
  85. async videoByUniqueInput(
  86. @Arg('where') where: VideoWhereUniqueInput,
  87. @Fields() fields: string[]
  88. ): Promise<Video | null> {
  89. const result = await this.service.find(where, undefined, 1, 0, fields);
  90. return result && result.length >= 1 ? result[0] : null;
  91. }
  92. @Query(() => VideoConnection)
  93. async videosConnection(
  94. @Args() { where, orderBy, ...pageOptions }: VideoConnectionWhereArgs,
  95. @Info() info: any
  96. ): Promise<VideoConnection> {
  97. const rawFields = graphqlFields(info, {}, { excludedFields: ['__typename'] });
  98. let result: any = {
  99. totalCount: 0,
  100. edges: [],
  101. pageInfo: {
  102. hasNextPage: false,
  103. hasPreviousPage: false,
  104. },
  105. };
  106. // If the related database table does not have any records then an error is thrown to the client
  107. // by warthog
  108. try {
  109. result = await this.service.findConnection<VideoWhereInput>(where, orderBy, pageOptions, rawFields);
  110. } catch (err) {
  111. console.log(err);
  112. // TODO: should continue to return this on `Error: Items is empty` or throw the error
  113. if (!(err.message as string).includes('Items is empty')) throw err;
  114. }
  115. return result as Promise<VideoConnection>;
  116. }
  117. @FieldResolver(() => Channel)
  118. async channel(@Root() r: Video): Promise<Channel | null> {
  119. const result = await getConnection()
  120. .getRepository(Video)
  121. .findOne(r.id, { relations: ['channel'] });
  122. if (result && result.channel !== undefined) {
  123. return result.channel;
  124. }
  125. return null;
  126. }
  127. @FieldResolver(() => VideoCategory)
  128. async category(@Root() r: Video): Promise<VideoCategory | null> {
  129. const result = await getConnection()
  130. .getRepository(Video)
  131. .findOne(r.id, { relations: ['category'] });
  132. if (result && result.category !== undefined) {
  133. return result.category;
  134. }
  135. return null;
  136. }
  137. @FieldResolver(() => DataObject)
  138. async thumbnailPhotoDataObject(@Root() r: Video): Promise<DataObject | null> {
  139. const result = await getConnection()
  140. .getRepository(Video)
  141. .findOne(r.id, { relations: ['thumbnailPhotoDataObject'] });
  142. if (result && result.thumbnailPhotoDataObject !== undefined) {
  143. return result.thumbnailPhotoDataObject;
  144. }
  145. return null;
  146. }
  147. @FieldResolver(() => Language)
  148. async language(@Root() r: Video): Promise<Language | null> {
  149. const result = await getConnection()
  150. .getRepository(Video)
  151. .findOne(r.id, { relations: ['language'] });
  152. if (result && result.language !== undefined) {
  153. return result.language;
  154. }
  155. return null;
  156. }
  157. @FieldResolver(() => License)
  158. async license(@Root() r: Video): Promise<License | null> {
  159. const result = await getConnection()
  160. .getRepository(Video)
  161. .findOne(r.id, { relations: ['license'] });
  162. if (result && result.license !== undefined) {
  163. return result.license;
  164. }
  165. return null;
  166. }
  167. @FieldResolver(() => DataObject)
  168. async mediaDataObject(@Root() r: Video): Promise<DataObject | null> {
  169. const result = await getConnection()
  170. .getRepository(Video)
  171. .findOne(r.id, { relations: ['mediaDataObject'] });
  172. if (result && result.mediaDataObject !== undefined) {
  173. return result.mediaDataObject;
  174. }
  175. return null;
  176. }
  177. @FieldResolver(() => VideoMediaMetadata)
  178. async mediaMetadata(@Root() r: Video): Promise<VideoMediaMetadata | null> {
  179. const result = await getConnection()
  180. .getRepository(Video)
  181. .findOne(r.id, { relations: ['mediaMetadata'] });
  182. if (result && result.mediaMetadata !== undefined) {
  183. return result.mediaMetadata;
  184. }
  185. return null;
  186. }
  187. @FieldResolver(() => FeaturedVideo)
  188. async featured(@Root() r: Video): Promise<FeaturedVideo | null> {
  189. const result = await getConnection()
  190. .getRepository(Video)
  191. .findOne(r.id, { relations: ['featured'] });
  192. if (result && result.featured !== undefined) {
  193. return result.featured;
  194. }
  195. return null;
  196. }
  197. }