vendure-plugin.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { Module } from '@nestjs/common';
  2. import { METADATA } from '@nestjs/common/constants';
  3. import { ModuleMetadata } from '@nestjs/common/interfaces';
  4. import { pick } from '@vendure/common/lib/pick';
  5. import { Type } from '@vendure/common/lib/shared-types';
  6. import { DocumentNode } from 'graphql';
  7. import { RuntimeVendureConfig } from '../config/vendure-config';
  8. import { PLUGIN_METADATA } from './plugin-metadata';
  9. /**
  10. * @description
  11. * Defines the metadata of a Vendure plugin. This interface is an superset of the [Nestjs ModuleMetadata](https://docs.nestjs.com/modules)
  12. * (which allows the definition of `imports`, `exports`, `providers` and `controllers`), which means
  13. * that any Nestjs Module is a valid Vendure plugin. In addition, the VendurePluginMetadata allows the definition of
  14. * extra properties specific to Vendure.
  15. *
  16. * @docsCategory plugin
  17. * @docsPage VendurePluginMetadata
  18. */
  19. export interface VendurePluginMetadata extends ModuleMetadata {
  20. /**
  21. * @description
  22. * A function which can modify the {@link VendureConfig} object before the server bootstraps.
  23. */
  24. configuration?: PluginConfigurationFn;
  25. /**
  26. * @description
  27. * The plugin may extend the default Vendure GraphQL shop api by providing extended
  28. * schema definitions and any required resolvers.
  29. */
  30. shopApiExtensions?: APIExtensionDefinition;
  31. /**
  32. * @description
  33. * The plugin may extend the default Vendure GraphQL admin api by providing extended
  34. * schema definitions and any required resolvers.
  35. */
  36. adminApiExtensions?: APIExtensionDefinition;
  37. /**
  38. * @description
  39. * The plugin may define [Nestjs microservice controllers](https://docs.nestjs.com/microservices/basics#request-response)
  40. * which are run in the Worker context.
  41. */
  42. workers?: Array<Type<any>>;
  43. /**
  44. * @description
  45. * The plugin may define custom [TypeORM database entities](https://typeorm.io/#/entities).
  46. */
  47. entities?: Array<Type<any>>;
  48. }
  49. /**
  50. * @description
  51. * An object which allows a plugin to extend the Vendure GraphQL API.
  52. *
  53. * @docsCategory plugin
  54. * @docsPage VendurePluginMetadata
  55. * */
  56. export interface APIExtensionDefinition {
  57. /**
  58. * @description
  59. * Extensions to the schema.
  60. *
  61. * @example
  62. * ```TypeScript
  63. * const schema = gql`extend type SearchReindexResponse {
  64. * timeTaken: Int!
  65. * indexedItemCount: Int!
  66. * }`;
  67. * ```
  68. */
  69. schema?: DocumentNode | (() => DocumentNode);
  70. /**
  71. * @description
  72. * An array of resolvers for the schema extensions. Should be defined as [Nestjs GraphQL resolver](https://docs.nestjs.com/graphql/resolvers-map)
  73. * classes, i.e. using the Nest `\@Resolver()` decorator etc.
  74. */
  75. resolvers: Array<Type<any>> | (() => Array<Type<any>>);
  76. }
  77. /**
  78. * @description
  79. * This method is called before the app bootstraps and should be used to perform any needed modifications to the {@link VendureConfig}.
  80. *
  81. * @docsCategory plugin
  82. * @docsPage VendurePluginMetadata
  83. */
  84. export type PluginConfigurationFn = (
  85. config: RuntimeVendureConfig,
  86. ) => RuntimeVendureConfig | Promise<RuntimeVendureConfig>;
  87. /**
  88. * @description
  89. * The VendurePlugin decorator is a means of configuring and/or extending the functionality of the Vendure server. A Vendure plugin is
  90. * a [Nestjs Module](https://docs.nestjs.com/modules), with optional additional metadata defining things like extensions to the GraphQL API, custom
  91. * configuration or new database entities.
  92. *
  93. * As well as configuring the app, a plugin may also extend the GraphQL schema by extending existing types or adding
  94. * entirely new types. Database entities and resolvers can also be defined to handle the extended GraphQL types.
  95. *
  96. * @example
  97. * ```TypeScript
  98. * import { Controller, Get } from '\@nestjs/common';
  99. * import { Ctx, PluginCommonModule, ProductService, RequestContext, VendurePlugin } from '\@vendure/core';
  100. *
  101. * \@Controller('products')
  102. * export class ProductsController {
  103. * constructor(private productService: ProductService) {}
  104. *
  105. * \@Get()
  106. * findAll(\@Ctx() ctx: RequestContext) {
  107. * return this.productService.findAll(ctx);
  108. * }
  109. * }
  110. *
  111. *
  112. * //A simple plugin which adds a REST endpoint for querying products.
  113. * \@VendurePlugin({
  114. * imports: [PluginCommonModule],
  115. * controllers: [ProductsController],
  116. * })
  117. * export class RestPlugin {}
  118. * ```
  119. *
  120. * @docsCategory plugin
  121. */
  122. export function VendurePlugin(pluginMetadata: VendurePluginMetadata): ClassDecorator {
  123. // tslint:disable-next-line:ban-types
  124. return (target: Function) => {
  125. for (const metadataProperty of Object.values(PLUGIN_METADATA)) {
  126. const property = metadataProperty as keyof VendurePluginMetadata;
  127. if (pluginMetadata[property] != null) {
  128. Reflect.defineMetadata(property, pluginMetadata[property], target);
  129. }
  130. }
  131. const nestModuleMetadata = pick(pluginMetadata, Object.values(METADATA) as any);
  132. Module(nestModuleMetadata)(target);
  133. };
  134. }
  135. /**
  136. * @description
  137. * A plugin which implements this interface can define logic to run when the Vendure server is initialized.
  138. *
  139. * For example, this could be used to call out to an external API or to set up {@link EventBus} listeners.
  140. *
  141. * @docsCategory plugin
  142. * @docsPage Plugin Lifecycle Methods
  143. */
  144. export interface OnVendureBootstrap {
  145. onVendureBootstrap(): void | Promise<void>;
  146. }
  147. /**
  148. * @description
  149. * A plugin which implements this interface can define logic to run when the Vendure worker is initialized.
  150. *
  151. * For example, this could be used to start or connect to a server or databased used by the worker.
  152. *
  153. * @docsCategory plugin
  154. * @docsPage Plugin Lifecycle Methods
  155. */
  156. export interface OnVendureWorkerBootstrap {
  157. onVendureWorkerBootstrap(): void | Promise<void>;
  158. }
  159. /**
  160. * @description
  161. * A plugin which implements this interface can define logic to run before Vendure server is closed.
  162. *
  163. * For example, this could be used to clean up any processes started by the {@link OnVendureBootstrap} method.
  164. *
  165. * @docsCategory plugin
  166. * @docsPage Plugin Lifecycle Methods
  167. */
  168. export interface OnVendureClose {
  169. onVendureClose(): void | Promise<void>;
  170. }
  171. /**
  172. * @description
  173. * A plugin which implements this interface can define logic to run before Vendure worker is closed.
  174. *
  175. * For example, this could be used to close any open connections to external services.
  176. *
  177. * @docsCategory plugin
  178. * @docsPage Plugin Lifecycle Methods
  179. */
  180. export interface OnVendureWorkerClose {
  181. onVendureWorkerClose(): void | Promise<void>;
  182. }
  183. export type PluginLifecycleMethods = OnVendureBootstrap &
  184. OnVendureWorkerBootstrap &
  185. OnVendureClose &
  186. OnVendureWorkerClose;