token-active-order-plugin.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { Args, Mutation, Parent, ResolveField, Resolver } from '@nestjs/graphql';
  2. import { ID } from '@vendure/common/lib/shared-types';
  3. import {
  4. ActiveOrderStrategy,
  5. Ctx,
  6. CustomerService,
  7. idsAreEqual,
  8. Injector,
  9. Order,
  10. OrderService,
  11. PluginCommonModule,
  12. RequestContext,
  13. Transaction,
  14. TransactionalConnection,
  15. UserInputError,
  16. VendurePlugin,
  17. } from '@vendure/core';
  18. import gql from 'graphql-tag';
  19. declare module '@vendure/core/dist/entity/custom-entity-fields' {
  20. interface CustomOrderFields {
  21. orderToken: string;
  22. }
  23. }
  24. class TokenActiveOrderStrategy implements ActiveOrderStrategy<{ token: string }> {
  25. readonly name = 'orderToken';
  26. private connection: TransactionalConnection;
  27. private orderService: OrderService;
  28. init(injector: Injector) {
  29. this.connection = injector.get(TransactionalConnection);
  30. this.orderService = injector.get(OrderService);
  31. }
  32. defineInputType = () => gql`
  33. input OrderTokenActiveOrderInput {
  34. token: String
  35. }
  36. `;
  37. async determineActiveOrder(ctx: RequestContext, input: { token: string }) {
  38. const qb = this.connection
  39. .getRepository(ctx, Order)
  40. .createQueryBuilder('order')
  41. .leftJoinAndSelect('order.customer', 'customer')
  42. .leftJoinAndSelect('customer.user', 'user')
  43. .where('order.customFields.orderToken = :orderToken', { orderToken: input.token });
  44. const order = await qb.getOne();
  45. if (!order) {
  46. return;
  47. }
  48. const orderUserId = order.customer && order.customer.user && order.customer.user.id;
  49. if (order.customer && idsAreEqual(orderUserId, ctx.activeUserId)) {
  50. return order;
  51. }
  52. }
  53. }
  54. @Resolver('Order')
  55. export class OrderTokenResolver {
  56. @ResolveField()
  57. orderToken(@Parent() order: Order) {
  58. return order.customFields.orderToken;
  59. }
  60. }
  61. @Resolver()
  62. export class CreateOrderResolver {
  63. constructor(private orderService: OrderService, private customerService: CustomerService) {}
  64. @Mutation()
  65. @Transaction()
  66. async createOrder(@Ctx() ctx: RequestContext, @Args() args: { customerId: ID }) {
  67. const customer = await this.customerService.findOne(ctx, args.customerId);
  68. if (!customer) {
  69. throw new UserInputError('No customer found');
  70. }
  71. const order = await this.orderService.create(ctx, customer.user?.id);
  72. return this.orderService.updateCustomFields(ctx, order.id, {
  73. orderToken: `token-${args.customerId}`,
  74. });
  75. }
  76. }
  77. @VendurePlugin({
  78. imports: [PluginCommonModule],
  79. configuration: config => {
  80. config.customFields.Order.push({
  81. name: 'orderToken',
  82. type: 'string',
  83. internal: true,
  84. });
  85. config.orderOptions.activeOrderStrategy = new TokenActiveOrderStrategy();
  86. return config;
  87. },
  88. shopApiExtensions: {
  89. schema: gql`
  90. extend type Mutation {
  91. createOrder(customerId: ID!): Order!
  92. }
  93. extend type Order {
  94. orderToken: String!
  95. }
  96. `,
  97. resolvers: [OrderTokenResolver, CreateOrderResolver],
  98. },
  99. })
  100. export class TokenActiveOrderPlugin {}