hydration-test-plugin.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* eslint-disable @typescript-eslint/no-non-null-assertion */
  2. import { Args, Query, Resolver } from '@nestjs/graphql';
  3. import {
  4. Asset,
  5. ChannelService,
  6. Ctx,
  7. DeepPartial,
  8. EntityHydrator,
  9. ID,
  10. LanguageCode,
  11. OrderService,
  12. PluginCommonModule,
  13. Product,
  14. ProductService,
  15. ProductVariantService,
  16. RequestContext,
  17. TransactionalConnection,
  18. VendureEntity,
  19. VendurePlugin,
  20. } from '@vendure/core';
  21. import gql from 'graphql-tag';
  22. import { Entity, ManyToOne } from 'typeorm';
  23. @Resolver()
  24. export class TestAdminPluginResolver {
  25. constructor(
  26. private connection: TransactionalConnection,
  27. private orderService: OrderService,
  28. private channelService: ChannelService,
  29. private productVariantService: ProductVariantService,
  30. private productService: ProductService,
  31. private entityHydrator: EntityHydrator,
  32. ) {}
  33. @Query()
  34. async hydrateProduct(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  35. const product = await this.connection.getRepository(ctx, Product).findOne({
  36. where: { id: args.id },
  37. relations: ['facetValues'],
  38. });
  39. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  40. await this.entityHydrator.hydrate(ctx, product!, {
  41. relations: [
  42. 'variants.options',
  43. 'variants.product',
  44. 'assets.product',
  45. 'facetValues.facet',
  46. 'featuredAsset',
  47. 'variants.stockMovements',
  48. ],
  49. applyProductVariantPrices: true,
  50. });
  51. return product;
  52. }
  53. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1153
  54. @Query()
  55. async hydrateProductAsset(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  56. const product = await this.connection.getRepository(ctx, Product).findOne({ where: { id: args.id } });
  57. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  58. await this.entityHydrator.hydrate(ctx, product!, {
  59. relations: ['assets'],
  60. });
  61. return product;
  62. }
  63. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1161
  64. @Query()
  65. async hydrateProductVariant(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  66. const [variant] = await this.productVariantService.findByIds(ctx, [args.id]);
  67. await this.entityHydrator.hydrate(ctx, variant, {
  68. relations: ['product.facetValues.facet'],
  69. });
  70. return variant;
  71. }
  72. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1324
  73. @Query()
  74. async hydrateProductWithNoFacets(@Ctx() ctx: RequestContext) {
  75. const product = await this.productService.create(ctx, {
  76. enabled: true,
  77. translations: [
  78. {
  79. languageCode: LanguageCode.en,
  80. name: 'test',
  81. slug: 'test',
  82. description: 'test',
  83. },
  84. ],
  85. });
  86. await this.entityHydrator.hydrate(ctx, product, {
  87. relations: ['facetValues', 'facetValues.facet'],
  88. });
  89. return product;
  90. }
  91. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1172
  92. @Query()
  93. async hydrateOrder(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  94. const order = await this.orderService.findOne(ctx, args.id);
  95. await this.entityHydrator.hydrate(ctx, order!, {
  96. relations: ['payments'],
  97. });
  98. return order;
  99. }
  100. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1229
  101. @Query()
  102. async hydrateOrderReturnQuantities(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  103. const order = await this.orderService.findOne(ctx, args.id);
  104. await this.entityHydrator.hydrate(ctx, order!, {
  105. relations: [
  106. 'lines',
  107. 'lines.productVariant',
  108. 'lines.productVariant.product',
  109. 'lines.productVariant.product.assets',
  110. ],
  111. });
  112. return order?.lines.map(line => line.quantity);
  113. }
  114. // Test case for https://github.com/vendure-ecommerce/vendure/issues/1284
  115. @Query()
  116. async hydrateChannel(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  117. const channel = await this.channelService.findOne(ctx, args.id);
  118. await this.entityHydrator.hydrate(ctx, channel!, {
  119. relations: ['customFields.thumb'],
  120. });
  121. return channel;
  122. }
  123. @Query()
  124. async hydrateChannelWithNestedRelation(@Ctx() ctx: RequestContext, @Args() args: { id: ID }) {
  125. const channel = await this.channelService.findOne(ctx, args.id);
  126. await this.entityHydrator.hydrate(ctx, channel!, {
  127. relations: [
  128. 'customFields.thumb',
  129. 'customFields.additionalConfig',
  130. 'customFields.additionalConfig.backgroundImage',
  131. ],
  132. });
  133. return channel;
  134. }
  135. }
  136. @Entity()
  137. export class AdditionalConfig extends VendureEntity {
  138. constructor(input?: DeepPartial<AdditionalConfig>) {
  139. super(input);
  140. }
  141. @ManyToOne(() => Asset, { onDelete: 'SET NULL', nullable: true })
  142. backgroundImage: Asset;
  143. }
  144. @VendurePlugin({
  145. imports: [PluginCommonModule],
  146. entities: [AdditionalConfig],
  147. adminApiExtensions: {
  148. resolvers: [TestAdminPluginResolver],
  149. schema: gql`
  150. extend type Query {
  151. hydrateProduct(id: ID!): JSON
  152. hydrateProductWithNoFacets: JSON
  153. hydrateProductAsset(id: ID!): JSON
  154. hydrateProductVariant(id: ID!): JSON
  155. hydrateOrder(id: ID!): JSON
  156. hydrateOrderReturnQuantities(id: ID!): JSON
  157. hydrateChannel(id: ID!): JSON
  158. hydrateChannelWithNestedRelation(id: ID!): JSON
  159. }
  160. `,
  161. },
  162. configuration: config => {
  163. config.customFields.Channel.push({ name: 'thumb', type: 'relation', entity: Asset, nullable: true });
  164. config.customFields.Channel.push({
  165. name: 'additionalConfig',
  166. type: 'relation',
  167. entity: AdditionalConfig,
  168. graphQLType: 'JSON',
  169. nullable: true,
  170. });
  171. return config;
  172. },
  173. })
  174. export class HydrationTestPlugin {}