@vendure/core 2.2.3 → 2.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/api/api-internal-modules.d.ts +2 -2
  2. package/dist/api/config/configure-graphql-module.js.map +1 -1
  3. package/dist/api/config/generate-resolvers.d.ts +4 -4
  4. package/dist/api/config/graphql-custom-fields.js +5 -0
  5. package/dist/api/config/graphql-custom-fields.js.map +1 -1
  6. package/dist/api/resolvers/admin/order.resolver.d.ts +1 -1
  7. package/dist/api/resolvers/entity/order-entity.resolver.d.ts +1 -0
  8. package/dist/api/resolvers/entity/order-entity.resolver.js +15 -0
  9. package/dist/api/resolvers/entity/order-entity.resolver.js.map +1 -1
  10. package/dist/bootstrap.d.ts +1 -1
  11. package/dist/bootstrap.js +7 -3
  12. package/dist/bootstrap.js.map +1 -1
  13. package/dist/config/config.service.d.ts +2 -0
  14. package/dist/config/config.service.js +30 -1
  15. package/dist/config/config.service.js.map +1 -1
  16. package/dist/config/entity/entity-duplicators/index.d.ts +4 -4
  17. package/dist/config/fulfillment/default-fulfillment-process.js +0 -1
  18. package/dist/config/fulfillment/default-fulfillment-process.js.map +1 -1
  19. package/dist/config/promotion/index.d.ts +53 -53
  20. package/dist/connection/connection.module.d.ts +1 -1
  21. package/dist/i18n/i18n.service.js +1 -1
  22. package/dist/i18n/i18n.service.js.map +1 -1
  23. package/dist/i18n/messages/fr.json +138 -0
  24. package/dist/plugin/default-search-plugin/indexer/indexer.controller.d.ts +6 -1
  25. package/dist/plugin/default-search-plugin/indexer/indexer.controller.js +135 -75
  26. package/dist/plugin/default-search-plugin/indexer/indexer.controller.js.map +1 -1
  27. package/dist/plugin/plugin.module.js.map +1 -1
  28. package/dist/service/helpers/custom-field-relation/custom-field-relation.service.js +6 -2
  29. package/dist/service/helpers/custom-field-relation/custom-field-relation.service.js.map +1 -1
  30. package/dist/service/helpers/entity-hydrator/entity-hydrator.service.d.ts +0 -7
  31. package/dist/service/helpers/entity-hydrator/entity-hydrator.service.js +5 -52
  32. package/dist/service/helpers/entity-hydrator/entity-hydrator.service.js.map +1 -1
  33. package/dist/service/helpers/entity-hydrator/merge-deep.d.ts +9 -0
  34. package/dist/service/helpers/entity-hydrator/merge-deep.js +50 -0
  35. package/dist/service/helpers/entity-hydrator/merge-deep.js.map +1 -0
  36. package/dist/service/helpers/list-query-builder/parse-filter-params.js +1 -1
  37. package/dist/service/helpers/list-query-builder/parse-filter-params.js.map +1 -1
  38. package/dist/service/helpers/order-modifier/order-modifier.d.ts +1 -1
  39. package/dist/service/helpers/order-modifier/order-modifier.js +7 -0
  40. package/dist/service/helpers/order-modifier/order-modifier.js.map +1 -1
  41. package/dist/service/helpers/order-splitter/order-splitter.js +3 -2
  42. package/dist/service/helpers/order-splitter/order-splitter.js.map +1 -1
  43. package/dist/service/services/order.service.js +1 -1
  44. package/dist/service/services/order.service.js.map +1 -1
  45. package/dist/service/services/shipping-method.service.js +1 -1
  46. package/dist/service/services/shipping-method.service.js.map +1 -1
  47. package/package.json +3 -3
@@ -3,5 +3,5 @@ import { DataSourceOptions } from 'typeorm';
3
3
  export declare class ConnectionModule {
4
4
  static forRoot(): DynamicModule;
5
5
  static forPlugin(): DynamicModule;
6
- static getTypeOrmLogger(dbConnectionOptions: DataSourceOptions): import("typeorm").Logger | "debug" | "advanced-console" | "simple-console" | "file";
6
+ static getTypeOrmLogger(dbConnectionOptions: DataSourceOptions): "debug" | "advanced-console" | "simple-console" | "file" | import("typeorm").Logger;
7
7
  }
@@ -74,7 +74,7 @@ let I18nService = class I18nService {
74
74
  .use(i18next_icu_1.default)
75
75
  .init({
76
76
  nsSeparator: false,
77
- preload: ['en', 'de', 'ru', 'uk'],
77
+ preload: ['en', 'de', 'ru', 'uk', 'fr'],
78
78
  fallbackLng: 'en',
79
79
  detection: {
80
80
  lookupQuerystring: 'languageCode',
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.service.js","sourceRoot":"","sources":["../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"i18n.service.js","sourceRoot":"","sources":["../../src/i18n/i18n.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ {
2
+ "error": {
3
+ "active-user-does-not-have-sufficient-permissions": "L'utilisateur actif ne dispose pas des permissions suffisantes",
4
+ "available-currency-codes-must-include-default": "availableCurrencyCodes doit inclure defaultCurrencyCode ({ defaultCurrencyCode })",
5
+ "cannot-delete-role": "Le rôle \"{ roleCode }\" ne peut pas être supprimé",
6
+ "cannot-delete-sole-superadmin": "Le seul SuperAdmin ne peut pas être supprimé",
7
+ "cannot-locate-customer-for-user": "Impossible de localiser un Client pour l'utilisateur",
8
+ "cannot-modify-role": "Le rôle \"{ roleCode }\" ne peut pas être modifié",
9
+ "cannot-move-collection-into-self": "Impossible de déplacer une Collection dans elle-même",
10
+ "cannot-transition-payment-from-to": "Impossible de changer l'état du Paiement de \"{ fromState }\" à \"{ toState }\"",
11
+ "cannot-transition-refund-from-to": "Impossible de changer l'état du Remboursement de \"{ fromState }\" à \"{ toState }\"",
12
+ "cannot-transition-fulfillment-from-to": "Impossible de changer l'état de l'Exécution de \"{ fromState }\" à \"{ toState }\"",
13
+ "channel-not-found": "Aucun Canal avec le token \"{ token }\" n'a été trouvé",
14
+ "collection-id-or-slug-must-be-provided": "L'id de la Collection ou le slug doit être fourni",
15
+ "collection-id-slug-mismatch": "L'id et le slug fournis font référence à des Collections différentes",
16
+ "conditions-required-for-action": "L'action de Promotion \"{ action }\" requiert les conditions suivantes : { conditions }",
17
+ "configurable-argument-is-required": "L'argument \"{ name }\" est requis",
18
+ "country-code-not-valid": "Le code pays \"{ countryCode }\" n'a pas été reconnu",
19
+ "currency-not-available-in-channel": "La devise \"{ currencyCode }\" n'est pas disponible dans le Canal actuel",
20
+ "customer-does-not-belong-to-customer-group": "Le client n'appartient pas à ce groupe de clients",
21
+ "default-channel-not-found": "Canal par défaut non trouvé",
22
+ "entity-has-no-translation-in-language": "L'entité traduisible \"{ entityName }\" n'a pas été traduite dans la langue demandée ({ languageCode })",
23
+ "entity-with-id-not-found": "Aucun(e) { entityName } avec l'id \"{ id }\" n'a été trouvé(e)",
24
+ "items-cannot-be-removed-from-default-channel": "Les articles ne peuvent pas être retirés du Canal par défaut",
25
+ "facetfilterinput-invalid-input": "Un objet FacetValueFilterInput ne peut pas spécifier les champs 'and' et 'or' simultanément",
26
+ "field-invalid-datetime-range-max": "La valeur du champ personnalisé \"{ name }\" [{ value }] est supérieure au maximum [{ max }]",
27
+ "field-invalid-datetime-range-min": "La valeur du champ personnalisé \"{ name }\" [{ value }] est inférieure au minimum [{ min }]",
28
+ "field-invalid-non-nullable": "La valeur du champ personnalisé \"{ name }\" ne peut pas être définie à null",
29
+ "field-invalid-no-permission": "Vous n'avez pas les permissions nécessaires pour mettre à jour le champ \"{ name }\"",
30
+ "field-invalid-number-range-max": "La valeur du champ personnalisé \"{ name }\" [{ value }] dépasse le maximum [{ max }]",
31
+ "field-invalid-number-range-min": "La valeur du champ personnalisé \"{ name }\" [{ value }] est inférieure au minimum [{ min }]",
32
+ "field-invalid-readonly": "Le champ personnalisé \"{ name }\" est en lecture seule",
33
+ "field-invalid-string-option": "La valeur du champ personnalisé \"{ name }\" [\"{ value }\"] est invalide. Les options valides sont : [{ validOptions }]",
34
+ "field-invalid-string-pattern": "La valeur du champ personnalisé \"{ name }\" [\"{ value }\"] ne correspond pas au motif [{ pattern }]",
35
+ "forbidden": "Vous n'êtes actuellement pas autorisé à effectuer cette action",
36
+ "invalid-sort-field": "Le champ de tri \"{ fieldName }\" est invalide. Les champs valides sont : { validFields }",
37
+ "list-query-limit-exceeded": "Impossible de prendre plus de { limit } résultats dans une requête de liste",
38
+ "no-active-tax-zone": "La zone fiscale active n'a pas pu être déterminée. Assurez-vous qu'une zone fiscale par défaut est définie pour le canal actuel.",
39
+ "no-configurable-operation-def-with-code-found": "Aucun { type } avec le code \"{ code }\" n'a été trouvé",
40
+ "no-price-found-for-channel": "Aucune information de prix n'a été trouvée pour l'ID de la Variante de Produit \"{ variantId}\" dans le Canal \"{ channel }\".",
41
+ "no-search-plugin-configured": "Aucun plugin de recherche n'a été configuré",
42
+ "order-could-not-be-determined-or-created": "Aucune Commande active n'a pu être déterminée ni créée",
43
+ "order-does-not-contain-line-with-id": "Cette commande ne contient pas de Ligne de Commande avec l'id { id }",
44
+ "pending-identifier-missing": "L'adresse e-mail en attente de mise à jour n'a pas pu être trouvée",
45
+ "permission-invalid": "La permission \"{ permission }\" ne peut pas être attribuée",
46
+ "product-id-or-slug-must-be-provided": "L'id du Produit ou le slug doit être fourni",
47
+ "product-id-slug-mismatch": "L'id et le slug fournis font référence à des Produits différents",
48
+ "product-option-group-already-assigned": "Le groupe d'options de produit \"{ groupCode }\" est déjà attribué au produit \"{ productName }\"",
49
+ "product-variant-option-ids-not-compatible": "Les optionIds de la Variante de Produit doivent inclure un optionId de chaque groupe : {groupNames}",
50
+ "product-variant-options-combination-already-exists": "Une Variante de Produit avec les options sélectionnées existe déjà : {variantName}",
51
+ "promotion-channels-can-only-be-changed-from-default-channel": "Les canaux de promotion peuvent uniquement être modifiés à partir du Canal par défaut",
52
+ "stockonhand-cannot-be-negative": "stockOnHand ne peut pas être une valeur négative",
53
+ "superadmin-must-have-superadmin-role": "Il n'est pas possible de retirer le rôle de SuperAdmin au seul SuperAdmin",
54
+ "target-customer-not-assigned-to-order-channels": "Le Client ciblé n'est pas assigné aux mêmes Canaux que la Commande. IDs de canaux manquants : { missingChannelIds }",
55
+ "unauthorized": "Les informations d'identification ne correspondent pas. Veuillez vérifier et réessayer"
56
+ },
57
+ "errorResult": {
58
+ "ALREADY_LOGGED_IN_ERROR": "Impossible d'attribuer un Client à la Commande lorsqu'on est déjà connecté",
59
+ "ALREADY_REFUNDED_ERROR": "Impossible de rembourser un Article de la Commande qui a déjà été remboursé",
60
+ "CANCEL_ACTIVE_ORDER_ERROR": "Impossible d'annuler des Lignes de Commande d'une Commande dans l'état \"{ orderState }\"",
61
+ "CANCEL_PAYMENT_ERROR": "L'annulation du paiement a échoué",
62
+ "CHANNEL_DEFAULT_LANGUAGE_ERROR": "Impossible de rendre la langue \"{ language }\" indisponible car elle est utilisée comme langue par défaut par le canal \"{ channelCode }\"",
63
+ "COUPON_CODE_EXPIRED_ERROR": "Le code coupon \"{ couponCode }\" a expiré",
64
+ "COUPON_CODE_INVALID_ERROR": "Le code coupon \"{ couponCode }\" n'est pas valide",
65
+ "COUPON_CODE_LIMIT_ERROR": "Le code coupon ne peut pas être utilisé plus de {limit, plural, one {une fois} other {# fois}} par client",
66
+ "CREATE_FULFILLMENT_ERROR": "Une erreur s'est produite lors de la tentative de création de l'Exécution",
67
+ "DUPLICATE_ENTITY_ERROR": "L'entité n'a pas pu être dupliquée",
68
+ "EMAIL_ADDRESS_CONFLICT_ERROR": "L'adresse e-mail n'est pas disponible",
69
+ "EMPTY_ORDER_LINE_SELECTION_ERROR": "Au moins une Ligne de Commande doit être spécifiée",
70
+ "FACET_IN_USE_ERROR": "Le Facet \"{ facetCode }\" inclut des FacetValues qui sont attribués à {productCount, plural, =0 {} one {1 Produit} other {# Produits}} {variantCount, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
71
+ "IDENTIFIER_CHANGE_TOKEN_INVALID_ERROR": "Le jeton de changement d'identifiant n'est pas reconnu",
72
+ "INELIGIBLE_SHIPPING_METHOD_ERROR": "Cette Commande n'est pas éligible pour la Méthode d'Expédition sélectionnée",
73
+ "INSUFFICIENT_STOCK_ERROR": "{quantityAvailable, plural, =0 {Aucun article n'a été} one {Seul un article a été} other {Seulement # articles ont été}} ajouté(s) à la commande en raison d'un stock insuffisant",
74
+ "INSUFFICIENT_STOCK_ON_HAND_ERROR": "Impossible de créer une Exécution car \"{productVariantName}\" a un stockOnHand insuffisant ({stockOnHand})",
75
+ "INVALID_CREDENTIALS_ERROR": "Les informations d'identification fournies sont invalides",
76
+ "ITEMS_ALREADY_FULFILLED_ERROR": "Un ou plusieurs Articles de la Commande font déjà partie d'une Exécution",
77
+ "LANGUAGE_NOT_AVAILABLE_ERROR": "La langue \"{languageCode}\" n'est pas disponible. Activez-la d'abord via les Paramètres Globaux et réessayez",
78
+ "MANUAL_PAYMENT_STATE_ERROR": "Un paiement manuel ne peut être ajouté que dans l'état \"ArrangingPayment\" ou \"ArrangingAdditionalPayment\"",
79
+ "MIME_TYPE_ERROR": "Le type MIME \"{ mimeType }\" n'est pas autorisé.",
80
+ "MISSING_CONDITIONS_ERROR": "Une Promotion doit avoir au moins une condition ou un code coupon défini",
81
+ "MISSING_PASSWORD_ERROR": "Un mot de passe doit être fourni",
82
+ "NEGATIVE_QUANTITY_ERROR": "La quantité pour un Article de la Commande ne peut pas être négative",
83
+ "NO_ACTIVE_ORDER_ERROR": "Il n'y a aucune Commande active associée à la session en cours",
84
+ "NOTHING_TO_REFUND_ERROR": "Rien à rembourser",
85
+ "NOT_VERIFIED_ERROR": "Veuillez vérifier cette adresse e-mail avant de vous connecter",
86
+ "ORDER_LIMIT_ERROR": "Impossible d'ajouter des articles. Une commande peut comprendre un maximum de { maxItems } articles",
87
+ "ORDER_MODIFICATION_ERROR": "Le contenu de la Commande peut uniquement être modifié dans l'état \"AddingItems\"",
88
+ "ORDER_PAYMENT_STATE_ERROR": "Un Paiement ne peut être ajouté que lorsque la Commande est dans l'état \"ArrangingPayment\"",
89
+ "ORDER_STATE_TRANSITION_ERROR": "Impossible de changer l'état de la Commande de \"{ fromState }\" à \"{ toState }\"",
90
+ "PASSWORD_ALREADY_SET_ERROR": "Un mot de passe a déjà été défini lors de l'inscription",
91
+ "PASSWORD_RESET_TOKEN_EXPIRED_ERROR": "Le jeton de réinitialisation du mot de passe a expiré",
92
+ "PASSWORD_RESET_TOKEN_INVALID_ERROR": "Le jeton de réinitialisation du mot de passe n'est pas reconnu",
93
+ "PASSWORD_VALIDATION_ERROR": "Le mot de passe est invalide",
94
+ "PAYMENT_DECLINED_ERROR": "Le paiement a été refusé",
95
+ "PAYMENT_FAILED_ERROR": "Le paiement a échoué",
96
+ "PAYMENT_ORDER_MISMATCH_ERROR": "Le Paiement et les Lignes de Commande n'appartiennent pas à la même Commande",
97
+ "PAYMENT_STATE_TRANSITION_ERROR": "Impossible de changer l'état du Paiement de \"{ fromState }\" à \"{ toState }\"",
98
+ "PRODUCT_OPTION_IN_USE_ERROR": "Impossible de retirer le groupe d'options de produit \"{ optionGroupCode }\" car il est utilisé par {productVariantCount, plural, one {une Variante de Produit} other {# Variantes de Produit}}. Utilisez l'argument `force` pour le retirer malgré tout",
99
+ "QUANTITY_TOO_GREAT_ERROR": "La quantité spécifiée est supérieure aux Articles de la Commande disponibles",
100
+ "REFUND_AMOUNT_ERROR": "Le montant spécifié dépasse le montant remboursable pour ce paiement",
101
+ "REFUND_ORDER_STATE_ERROR": "Impossible de rembourser une Commande dans l'état \"{ orderState }\"",
102
+ "SETTLE_PAYMENT_ERROR": "L'établissement du paiement a échoué",
103
+ "VERIFICATION_TOKEN_EXPIRED_ERROR": "Le jeton de vérification a expiré. Utilisez refreshCustomerVerification pour envoyer un nouveau jeton.",
104
+ "VERIFICATION_TOKEN_INVALID_ERROR": "Le jeton de vérification n'est pas reconnu"
105
+ },
106
+ "message": {
107
+ "asset-to-be-deleted-is-featured": "L'{assetCount, plural, one {Asset est} other {Assets sont}} présenté(s) par {products, plural, =0 {} one {1 Produit} other {# Produits}} {variants, plural, =0 {} one { 1 Variante de Produit} other { # Variantes de Produit}} {collections, plural, =0 {} one { 1 Collection} other { # Collections}}",
108
+ "cannot-delete-last-stock-location": "L'emplacement de stockage restant ne peut pas être supprimé",
109
+ "cannot-remove-tax-category-due-to-tax-rates": "Impossible de retirer la Catégorie Fiscale \"{ name }\" car elle est référencée par {count, plural, one {1 Taux Fiscal} other {# Taux Fiscaux}}",
110
+ "cannot-transition-order-contains-products-which-are-unavailable": "Impossible de passer à \"{ toState }\" car la Commande contient des Variantes de Produit qui ne sont plus disponibles",
111
+ "cannot-transition-from-arranging-additional-payment": "Impossible de passer de \"ArrangingAdditionalPayment\" à moins que le total de la Commande ne soit couvert par des Paiements",
112
+ "cannot-transition-order-from-to": "Impossible de changer l'état de la Commande de \"{ fromState }\" à \"{ toState }\"",
113
+ "cannot-transition-no-additional-payments-needed": "Impossible de passer la Commande à l'état \"ArrangingAdditionalPayment\" car aucun paiement supplémentaire n'est nécessaire",
114
+ "cannot-transition-to-shipping-when-order-is-empty": "Impossible de passer la Commande à l'état \"ArrangingShipping\" lorsque celle-ci est vide",
115
+ "cannot-transition-to-payment-due-to-insufficient-stock": "Impossible de passer la Commande à l'état \"ArrangingPayment\" en raison d'un stock insuffisant de { productVariantNames }",
116
+ "cannot-transition-to-payment-without-customer": "Impossible de passer la Commande à l'état \"ArrangingPayment\" sans les détails du Client",
117
+ "cannot-transition-to-payment-without-shipping-method": "Impossible de passer la Commande à l'état \"ArrangingPayment\" sans Méthode d'Expédition",
118
+ "cannot-transition-unless-all-cancelled": "Impossible de passer la Commande à l'état \"Cancelled\" à moins que tous les Articles de la Commande ne soient annulés",
119
+ "cannot-transition-unless-all-order-items-delivered": "Impossible de passer la Commande à l'état \"Delivered\" à moins que tous les Articles de la Commande ne soient livrés",
120
+ "cannot-transition-unless-some-order-items-delivered": "Impossible de passer la Commande à l'état \"PartiallyDelivered\" à moins que certains Articles de la Commande ne soient livrés",
121
+ "cannot-transition-unless-some-order-items-shipped": "Impossible de passer la Commande à l'état \"PartiallyShipped\" à moins que certains Articles de la Commande ne soient expédiés",
122
+ "cannot-transition-unless-all-order-items-shipped": "Impossible de passer la Commande à l'état \"Shipped\" à moins que tous les Articles de la Commande ne soient expédiés",
123
+ "cannot-transition-without-authorized-payments": "Impossible de passer la Commande à l'état \"PaymentAuthorized\" lorsque le total n'est pas couvert par des Paiements autorisés",
124
+ "cannot-transition-without-modification-payment": "Peut seulement passer à l'état \"ArrangingAdditionalPayment\"",
125
+ "cannot-transition-without-settled-payments": "Impossible de passer la Commande à l'état \"PaymentSettled\" lorsque le total n'est pas couvert par des Paiements réglés",
126
+ "country-used-in-addresses": "Le Pays sélectionné ne peut pas être supprimé car il est utilisé dans {count, plural, one {1 Adresse} other {# Adresses}}",
127
+ "entity-duplication-no-permission": "Vous n'avez pas les permissions nécessaires pour dupliquer cette entité",
128
+ "entity-duplication-no-strategy-found": "Aucune stratégie de duplication avec le code \"{ code }\" n'a été trouvée pour le type d'entité \"{ entityName }\"",
129
+ "facet-force-deleted": "Le Facet a été supprimé et ses FacetValues ont été retirés de {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
130
+ "facet-used": "Le Facet \"{ facetCode }\" inclut des FacetValues qui sont attribués à {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
131
+ "facet-value-force-deleted": "La FacetValue sélectionnée a été retirée de {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}} et supprimée",
132
+ "facet-value-used": "La FacetValue \"{ facetValueCode }\" est attribuée à {products, plural, =0 {} one {1 Produit} other {# Produits}}{both, select, both {, } single {} other {}}{variants, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
133
+ "payment-method-used-in-channels": "La méthode de paiement sélectionnée est assignée aux Canaux suivants : { channelCodes }. Définissez \"force: true\" pour la supprimer de tous les Canaux.",
134
+ "product-option-used": "Impossible de supprimer l'option \"{code}\" car elle est utilisée par {count, plural, =0 {} one {1 Variante de Produit} other {# Variantes de Produit}}",
135
+ "zone-used-in-channels": "La Zone sélectionnée ne peut pas être supprimée car elle est utilisée comme défaut dans les Canaux suivants : { channelCodes }",
136
+ "zone-used-in-tax-rates": "La Zone sélectionnée ne peut pas être supprimée car elle est utilisée dans les Taux Fiscaux suivants : { taxRateNames }"
137
+ }
138
+ }
@@ -3,6 +3,7 @@ import { RequestContextCacheService } from '../../../cache/request-context-cache
3
3
  import { ConfigService } from '../../../config/config.service';
4
4
  import { TransactionalConnection } from '../../../connection/transactional-connection';
5
5
  import { Job } from '../../../job-queue/job';
6
+ import { EntityHydrator } from '../../../service/helpers/entity-hydrator/entity-hydrator.service';
6
7
  import { ProductPriceApplicator } from '../../../service/helpers/product-price-applicator/product-price-applicator';
7
8
  import { ProductVariantService } from '../../../service/services/product-variant.service';
8
9
  import { DefaultSearchPluginInitOptions, ProductChannelMessageData, ReindexMessageResponse, UpdateAssetMessageData, UpdateIndexQueueJobData, UpdateProductMessageData, UpdateVariantMessageData, UpdateVariantsByIdJobData, VariantChannelMessageData } from '../types';
@@ -12,13 +13,14 @@ export declare const variantRelations: string[];
12
13
  export declare const workerLoggerCtx = "DefaultSearchPlugin Worker";
13
14
  export declare class IndexerController {
14
15
  private connection;
16
+ private entityHydrator;
15
17
  private productPriceApplicator;
16
18
  private configService;
17
19
  private requestContextCache;
18
20
  private productVariantService;
19
21
  private options;
20
22
  private queue;
21
- constructor(connection: TransactionalConnection, productPriceApplicator: ProductPriceApplicator, configService: ConfigService, requestContextCache: RequestContextCacheService, productVariantService: ProductVariantService, options: DefaultSearchPluginInitOptions);
23
+ constructor(connection: TransactionalConnection, entityHydrator: EntityHydrator, productPriceApplicator: ProductPriceApplicator, configService: ConfigService, requestContextCache: RequestContextCacheService, productVariantService: ProductVariantService, options: DefaultSearchPluginInitOptions);
22
24
  reindex(job: Job<UpdateIndexQueueJobData>): Observable<ReindexMessageResponse>;
23
25
  updateVariantsById(job: Job<UpdateVariantsByIdJobData>): Observable<ReindexMessageResponse>;
24
26
  updateProduct(data: UpdateProductMessageData): Promise<boolean>;
@@ -34,7 +36,10 @@ export declare class IndexerController {
34
36
  private updateProductInChannel;
35
37
  private updateVariantsInChannel;
36
38
  private deleteProductInChannel;
39
+ private loadChannel;
40
+ private getAllChannels;
37
41
  private getSearchIndexQueryBuilder;
42
+ private getProductInChannelQueryBuilder;
38
43
  private saveVariants;
39
44
  /**
40
45
  * If a Product has no variants, we create a synthetic variant for the purposes
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.IndexerController = exports.workerLoggerCtx = exports.variantRelations = exports.productRelations = exports.BATCH_SIZE = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
17
  const generated_types_1 = require("@vendure/common/lib/generated-types");
18
+ const shared_utils_1 = require("@vendure/common/lib/shared-utils");
18
19
  const unique_1 = require("@vendure/common/lib/unique");
19
20
  const typeorm_1 = require("typeorm");
20
21
  const request_context_cache_service_1 = require("../../../cache/request-context-cache.service");
@@ -23,8 +24,10 @@ const utils_1 = require("../../../common/utils");
23
24
  const config_service_1 = require("../../../config/config.service");
24
25
  const vendure_logger_1 = require("../../../config/logger/vendure-logger");
25
26
  const transactional_connection_1 = require("../../../connection/transactional-connection");
27
+ const channel_entity_1 = require("../../../entity/channel/channel.entity");
26
28
  const product_entity_1 = require("../../../entity/product/product.entity");
27
29
  const product_variant_entity_1 = require("../../../entity/product-variant/product-variant.entity");
30
+ const entity_hydrator_service_1 = require("../../../service/helpers/entity-hydrator/entity-hydrator.service");
28
31
  const product_price_applicator_1 = require("../../../service/helpers/product-price-applicator/product-price-applicator");
29
32
  const product_variant_service_1 = require("../../../service/services/product-variant.service");
30
33
  const constants_1 = require("../constants");
@@ -43,8 +46,9 @@ exports.variantRelations = [
43
46
  ];
44
47
  exports.workerLoggerCtx = 'DefaultSearchPlugin Worker';
45
48
  let IndexerController = class IndexerController {
46
- constructor(connection, productPriceApplicator, configService, requestContextCache, productVariantService, options) {
49
+ constructor(connection, entityHydrator, productPriceApplicator, configService, requestContextCache, productVariantService, options) {
47
50
  this.connection = connection;
51
+ this.entityHydrator = entityHydrator;
48
52
  this.productPriceApplicator = productPriceApplicator;
49
53
  this.configService = configService;
50
54
  this.requestContextCache = requestContextCache;
@@ -56,14 +60,14 @@ let IndexerController = class IndexerController {
56
60
  const { ctx: rawContext } = job.data;
57
61
  const ctx = mutable_request_context_1.MutableRequestContext.deserialize(rawContext);
58
62
  return (0, utils_1.asyncObservable)(async (observer) => {
63
+ var _a;
59
64
  const timeStart = Date.now();
60
- const qb = this.getSearchIndexQueryBuilder(ctx, ctx.channelId);
65
+ const channel = (_a = ctx.channel) !== null && _a !== void 0 ? _a : (await this.loadChannel(ctx, ctx.channelId));
66
+ const qb = this.getSearchIndexQueryBuilder(ctx, channel);
61
67
  const count = await qb.getCount();
62
68
  vendure_logger_1.Logger.verbose(`Reindexing ${count} variants for channel ${ctx.channel.code}`, exports.workerLoggerCtx);
63
69
  const batches = Math.ceil(count / exports.BATCH_SIZE);
64
- await this.connection
65
- .getRepository(ctx, search_index_item_entity_1.SearchIndexItem)
66
- .delete({ languageCode: ctx.languageCode, channelId: ctx.channelId });
70
+ await this.connection.getRepository(ctx, search_index_item_entity_1.SearchIndexItem).delete({ channelId: ctx.channelId });
67
71
  vendure_logger_1.Logger.verbose('Deleted existing index items', exports.workerLoggerCtx);
68
72
  for (let i = 0; i < batches; i++) {
69
73
  if (job.state === generated_types_1.JobState.CANCELLED) {
@@ -105,13 +109,9 @@ let IndexerController = class IndexerController {
105
109
  const end = begin + exports.BATCH_SIZE;
106
110
  vendure_logger_1.Logger.verbose(`Updating ids from index ${begin} to ${end}`);
107
111
  const batchIds = ids.slice(begin, end);
108
- const batch = await this.connection.getRepository(ctx, product_variant_entity_1.ProductVariant).find({
109
- relations: exports.variantRelations,
110
- where: {
111
- id: (0, typeorm_1.In)(batchIds),
112
- deletedAt: (0, typeorm_1.IsNull)(),
113
- },
114
- });
112
+ const batch = await this.getSearchIndexQueryBuilder(ctx, ...(await this.getAllChannels(ctx)))
113
+ .where('variants.deletedAt IS NULL AND variants.id IN (:...ids)', { ids: batchIds })
114
+ .getMany();
115
115
  await this.saveVariants(ctx, batch);
116
116
  observer.next({
117
117
  total: ids.length,
@@ -138,7 +138,7 @@ let IndexerController = class IndexerController {
138
138
  }
139
139
  async deleteProduct(data) {
140
140
  const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
141
- return this.deleteProductInChannel(ctx, data.productId, ctx.channelId);
141
+ return this.deleteProductInChannel(ctx, data.productId, (await this.getAllChannels(ctx)).map(x => x.id));
142
142
  }
143
143
  async deleteVariant(data) {
144
144
  const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
@@ -146,12 +146,7 @@ let IndexerController = class IndexerController {
146
146
  where: { id: (0, typeorm_1.In)(data.variantIds) },
147
147
  });
148
148
  if (variants.length) {
149
- const languageVariants = (0, unique_1.unique)([
150
- ...variants
151
- .reduce((vt, v) => [...vt, ...v.translations], [])
152
- .map(t => t.languageCode),
153
- ]);
154
- await this.removeSearchIndexItems(ctx, ctx.channelId, variants.map(v => v.id), languageVariants);
149
+ await this.removeSearchIndexItems(ctx, variants.map(v => v.id), (await this.getAllChannels(ctx)).map(c => c.id));
155
150
  }
156
151
  return true;
157
152
  }
@@ -161,7 +156,7 @@ let IndexerController = class IndexerController {
161
156
  }
162
157
  async removeProductFromChannel(data) {
163
158
  const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
164
- return this.deleteProductInChannel(ctx, data.productId, data.channelId);
159
+ return this.deleteProductInChannel(ctx, data.productId, [data.channelId]);
165
160
  }
166
161
  async assignVariantToChannel(data) {
167
162
  const ctx = mutable_request_context_1.MutableRequestContext.deserialize(data.ctx);
@@ -174,7 +169,7 @@ let IndexerController = class IndexerController {
174
169
  .getRepository(ctx, product_variant_entity_1.ProductVariant)
175
170
  .findOne({ where: { id: data.productVariantId } });
176
171
  const languageVariants = (_a = variant === null || variant === void 0 ? void 0 : variant.translations.map(t => t.languageCode)) !== null && _a !== void 0 ? _a : [];
177
- await this.removeSearchIndexItems(ctx, data.channelId, [data.productVariantId], languageVariants);
172
+ await this.removeSearchIndexItems(ctx, [data.productVariantId], [data.channelId]);
178
173
  return true;
179
174
  }
180
175
  async updateAsset(data) {
@@ -204,19 +199,22 @@ let IndexerController = class IndexerController {
204
199
  return true;
205
200
  }
206
201
  async updateProductInChannel(ctx, productId, channelId) {
207
- const product = await this.connection.getRepository(ctx, product_entity_1.Product).findOne({
208
- where: { id: productId },
209
- relations: ['variants'],
210
- });
202
+ const channel = await this.loadChannel(ctx, channelId);
203
+ ctx.setChannel(channel);
204
+ const product = await this.getProductInChannelQueryBuilder(ctx, productId, channel).getOneOrFail();
211
205
  if (product) {
212
- const updatedVariants = await this.connection.getRepository(ctx, product_variant_entity_1.ProductVariant).find({
213
- relations: exports.variantRelations,
206
+ const affectedChannels = await this.getAllChannels(ctx, {
214
207
  where: {
215
- id: (0, typeorm_1.In)(product.variants.map(v => v.id)),
216
- deletedAt: (0, typeorm_1.IsNull)(),
208
+ availableLanguageCodes: (0, typeorm_1.In)(product.translations.map(t => t.languageCode)),
217
209
  },
218
210
  });
211
+ const updatedVariants = await this.getSearchIndexQueryBuilder(ctx, ...(0, unique_1.unique)(affectedChannels.concat(channel)))
212
+ .andWhere('variants.productId = :productId', { productId })
213
+ .getMany();
219
214
  if (updatedVariants.length === 0) {
215
+ const clone = new product_entity_1.Product({ id: product.id });
216
+ await this.entityHydrator.hydrate(ctx, clone, { relations: ['translations'] });
217
+ product.translations = clone.translations;
220
218
  await this.saveSyntheticVariant(ctx, product);
221
219
  }
222
220
  else {
@@ -233,89 +231,140 @@ let IndexerController = class IndexerController {
233
231
  return true;
234
232
  }
235
233
  async updateVariantsInChannel(ctx, variantIds, channelId) {
236
- const variants = await this.connection.getRepository(ctx, product_variant_entity_1.ProductVariant).find({
237
- relations: exports.variantRelations,
238
- where: {
239
- id: (0, typeorm_1.In)(variantIds),
240
- deletedAt: (0, typeorm_1.IsNull)(),
241
- },
242
- });
234
+ const channel = await this.loadChannel(ctx, channelId);
235
+ ctx.setChannel(channel);
236
+ const variants = await this.getSearchIndexQueryBuilder(ctx, channel)
237
+ .andWhere('variants.deletedAt IS NULL AND variants.id IN (:...variantIds)', { variantIds })
238
+ .getMany();
243
239
  if (variants) {
244
240
  vendure_logger_1.Logger.verbose(`Updating ${variants.length} variants`, exports.workerLoggerCtx);
245
241
  await this.saveVariants(ctx, variants);
246
242
  }
247
243
  return true;
248
244
  }
249
- async deleteProductInChannel(ctx, productId, channelId) {
250
- const product = await this.connection.getRepository(ctx, product_entity_1.Product).findOne({
251
- where: { id: productId },
252
- relations: ['variants'],
253
- });
245
+ async deleteProductInChannel(ctx, productId, channelIds) {
246
+ const channels = await Promise.all(channelIds.map(channelId => this.loadChannel(ctx, channelId)));
247
+ const product = await this.getProductInChannelQueryBuilder(ctx, productId, ...channels)
248
+ .leftJoinAndSelect('product.variants', 'variants')
249
+ .leftJoinAndSelect('variants.translations', 'variants_translations')
250
+ .getOne();
254
251
  if (product) {
255
- const languageVariants = (0, unique_1.unique)([
256
- ...product.translations.map(t => t.languageCode),
257
- ...product.variants
258
- .reduce((vt, v) => [...vt, ...v.translations], [])
259
- .map(t => t.languageCode),
260
- ]);
261
252
  const removedVariantIds = product.variants.map(v => v.id);
262
253
  if (removedVariantIds.length) {
263
- await this.removeSearchIndexItems(ctx, channelId, removedVariantIds, languageVariants);
254
+ await this.removeSearchIndexItems(ctx, removedVariantIds, channelIds);
264
255
  }
265
256
  }
266
257
  return true;
267
258
  }
268
- getSearchIndexQueryBuilder(ctx, channelId) {
259
+ async loadChannel(ctx, channelId) {
260
+ return await this.connection.getRepository(ctx, channel_entity_1.Channel).findOneOrFail({ where: { id: channelId } });
261
+ }
262
+ async getAllChannels(ctx, options) {
263
+ return await this.connection.getRepository(ctx, channel_entity_1.Channel).find(options);
264
+ }
265
+ getSearchIndexQueryBuilder(ctx, ...channels) {
266
+ const channelLanguages = (0, unique_1.unique)(channels.flatMap(c => c.availableLanguageCodes).concat(this.configService.defaultLanguageCode));
269
267
  const qb = this.connection
270
268
  .getRepository(ctx, product_variant_entity_1.ProductVariant)
271
269
  .createQueryBuilder('variants')
272
270
  .setFindOptions({
273
- relations: exports.variantRelations,
274
- loadEagerRelations: true,
271
+ loadEagerRelations: false,
272
+ })
273
+ .leftJoinAndSelect('variants.channels', 'variant_channels', 'variant_channels.id IN (:...channelId)', {
274
+ channelId: channels.map(x => x.id),
275
+ })
276
+ .leftJoinAndSelect('variant_channels.defaultTaxZone', 'variant_channel_tax_zone')
277
+ .leftJoinAndSelect('variants.taxCategory', 'variant_tax_category')
278
+ .leftJoinAndSelect('variants.productVariantPrices', 'product_variant_prices', 'product_variant_prices.channelId IN (:...channelId)', { channelId: channels.map(x => x.id) })
279
+ .leftJoinAndSelect('variants.translations', 'product_variant_translation', 'product_variant_translation.baseId = variants.id AND product_variant_translation.languageCode IN (:...channelLanguages)', {
280
+ channelLanguages,
275
281
  })
276
282
  .leftJoin('variants.product', 'product')
283
+ .leftJoinAndSelect('variants.facetValues', 'variant_facet_values')
284
+ .leftJoinAndSelect('variant_facet_values.translations', 'variant_facet_value_translations', 'variant_facet_value_translations.languageCode IN (:...channelLanguages)', {
285
+ channelLanguages,
286
+ })
287
+ .leftJoinAndSelect('variant_facet_values.facet', 'facet_values_facet')
288
+ .leftJoinAndSelect('facet_values_facet.translations', 'facet_values_facet_translations', 'facet_values_facet_translations.languageCode IN (:...channelLanguages)', {
289
+ channelLanguages,
290
+ })
291
+ .leftJoinAndSelect('variants.collections', 'collections')
292
+ .leftJoinAndSelect('collections.channels', 'collection_channels', 'collection_channels.id IN (:...channelId)', { channelId: channels.map(x => x.id) })
293
+ .leftJoinAndSelect('collections.translations', 'collection_translations', 'collection_translations.languageCode IN (:...channelLanguages)', {
294
+ channelLanguages,
295
+ })
277
296
  .leftJoin('product.channels', 'channel')
278
- .where('channel.id = :channelId', { channelId })
297
+ .where('channel.id IN (:...channelId)', { channelId: channels.map(x => x.id) })
279
298
  .andWhere('product.deletedAt IS NULL')
280
299
  .andWhere('variants.deletedAt IS NULL');
281
300
  return qb;
282
301
  }
302
+ getProductInChannelQueryBuilder(ctx, productId, ...channels) {
303
+ const channelLanguages = (0, unique_1.unique)(channels.flatMap(c => c.availableLanguageCodes).concat(this.configService.defaultLanguageCode));
304
+ return this.connection
305
+ .getRepository(ctx, product_entity_1.Product)
306
+ .createQueryBuilder('product')
307
+ .setFindOptions({
308
+ loadEagerRelations: false,
309
+ })
310
+ .leftJoinAndSelect('product.translations', 'translations', 'translations.languageCode IN (:...channelLanguages)', {
311
+ channelLanguages,
312
+ })
313
+ .leftJoinAndSelect('product.featuredAsset', 'product_featured_asset')
314
+ .leftJoinAndSelect('product.facetValues', 'product_facet_values')
315
+ .leftJoinAndSelect('product_facet_values.translations', 'product_facet_value_translations', 'product_facet_value_translations.languageCode IN (:...channelLanguages)', {
316
+ channelLanguages,
317
+ })
318
+ .leftJoinAndSelect('product_facet_values.facet', 'product_facet')
319
+ .leftJoinAndSelect('product_facet.translations', 'product_facet_translations', 'product_facet_translations.languageCode IN (:...channelLanguages)', {
320
+ channelLanguages,
321
+ })
322
+ .leftJoinAndSelect('product.channels', 'channel', 'channel.id IN (:...channelId)', {
323
+ channelId: channels.map(x => x.id),
324
+ })
325
+ .where('product.id = :productId', { productId });
326
+ }
283
327
  async saveVariants(ctx, variants) {
328
+ var _a, _b, _c, _d, _e;
284
329
  const items = [];
285
330
  await this.removeSyntheticVariants(ctx, variants);
286
331
  const productMap = new Map();
287
332
  for (const variant of variants) {
288
333
  let product = productMap.get(variant.productId);
289
334
  if (!product) {
290
- product = await this.connection.getEntityOrThrow(ctx, product_entity_1.Product, variant.productId, {
291
- relations: exports.productRelations,
292
- });
335
+ product = await this.getProductInChannelQueryBuilder(ctx, variant.productId, ctx.channel).getOneOrFail();
293
336
  productMap.set(variant.productId, product);
294
337
  }
295
- const languageVariants = (0, unique_1.unique)([
296
- ...variant.translations.map(t => t.languageCode),
297
- ...product.translations.map(t => t.languageCode),
298
- ]);
299
- for (const languageCode of languageVariants) {
338
+ const availableLanguageCodes = (0, unique_1.unique)(ctx.channel.availableLanguageCodes);
339
+ for (const languageCode of availableLanguageCodes) {
300
340
  const productTranslation = this.getTranslation(product, languageCode);
301
341
  const variantTranslation = this.getTranslation(variant, languageCode);
302
342
  const collectionTranslations = variant.collections.map(c => this.getTranslation(c, languageCode));
343
+ let channelIds = variant.channels.map(x => x.id);
344
+ const clone = new product_variant_entity_1.ProductVariant({ id: variant.id });
345
+ await this.entityHydrator.hydrate(ctx, clone, {
346
+ relations: ['channels', 'channels.defaultTaxZone'],
347
+ });
348
+ channelIds.push(...clone.channels
349
+ .filter(x => x.availableLanguageCodes.includes(languageCode))
350
+ .map(x => x.id));
351
+ channelIds = (0, unique_1.unique)(channelIds);
303
352
  for (const channel of variant.channels) {
304
353
  ctx.setChannel(channel);
305
354
  await this.productPriceApplicator.applyChannelPriceAndTax(variant, ctx);
306
355
  const item = new search_index_item_entity_1.SearchIndexItem({
307
- channelId: channel.id,
356
+ channelId: ctx.channelId,
308
357
  languageCode,
309
358
  productVariantId: variant.id,
310
359
  price: variant.price,
311
360
  priceWithTax: variant.priceWithTax,
312
361
  sku: variant.sku,
313
362
  enabled: product.enabled === false ? false : variant.enabled,
314
- slug: productTranslation.slug,
363
+ slug: (_a = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.slug) !== null && _a !== void 0 ? _a : '',
315
364
  productId: product.id,
316
- productName: productTranslation.name,
317
- description: this.constrainDescription(productTranslation.description),
318
- productVariantName: variantTranslation.name,
365
+ productName: (_b = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.name) !== null && _b !== void 0 ? _b : '',
366
+ description: this.constrainDescription((_c = productTranslation === null || productTranslation === void 0 ? void 0 : productTranslation.description) !== null && _c !== void 0 ? _c : ''),
367
+ productVariantName: (_d = variantTranslation === null || variantTranslation === void 0 ? void 0 : variantTranslation.name) !== null && _d !== void 0 ? _d : '',
319
368
  productAssetId: product.featuredAsset ? product.featuredAsset.id : null,
320
369
  productPreviewFocalPoint: product.featuredAsset
321
370
  ? product.featuredAsset.focalPoint
@@ -326,11 +375,11 @@ let IndexerController = class IndexerController {
326
375
  productVariantAssetId: variant.featuredAsset ? variant.featuredAsset.id : null,
327
376
  productPreview: product.featuredAsset ? product.featuredAsset.preview : '',
328
377
  productVariantPreview: variant.featuredAsset ? variant.featuredAsset.preview : '',
329
- channelIds: variant.channels.map(c => c.id),
378
+ channelIds: channelIds.map(x => x.toString()),
330
379
  facetIds: this.getFacetIds(variant, product),
331
380
  facetValueIds: this.getFacetValueIds(variant, product),
332
381
  collectionIds: variant.collections.map(c => c.id.toString()),
333
- collectionSlugs: collectionTranslations.map(c => c.slug),
382
+ collectionSlugs: (_e = collectionTranslations.map(c => c === null || c === void 0 ? void 0 : c.slug).filter(shared_utils_1.notNullOrUndefined)) !== null && _e !== void 0 ? _e : [],
334
383
  });
335
384
  if (this.options.indexStockStatus) {
336
385
  item.inStock =
@@ -420,15 +469,25 @@ let IndexerController = class IndexerController {
420
469
  /**
421
470
  * Remove items from the search index
422
471
  */
423
- async removeSearchIndexItems(ctx, channelId, variantIds, languageCodes) {
472
+ async removeSearchIndexItems(ctx, variantIds, channelIds, ...languageCodes) {
424
473
  const keys = [];
425
474
  for (const productVariantId of variantIds) {
426
- for (const languageCode of languageCodes) {
427
- keys.push({
428
- productVariantId,
429
- channelId,
430
- languageCode,
431
- });
475
+ for (const channelId of channelIds) {
476
+ if (languageCodes.length > 0) {
477
+ for (const languageCode of languageCodes) {
478
+ keys.push({
479
+ productVariantId,
480
+ channelId,
481
+ languageCode,
482
+ });
483
+ }
484
+ }
485
+ else {
486
+ keys.push({
487
+ productVariantId,
488
+ channelId,
489
+ });
490
+ }
432
491
  }
433
492
  }
434
493
  await this.queue.push(() => this.connection.getRepository(ctx, search_index_item_entity_1.SearchIndexItem).delete(keys));
@@ -449,8 +508,9 @@ let IndexerController = class IndexerController {
449
508
  exports.IndexerController = IndexerController;
450
509
  exports.IndexerController = IndexerController = __decorate([
451
510
  (0, common_1.Injectable)(),
452
- __param(5, (0, common_1.Inject)(constants_1.PLUGIN_INIT_OPTIONS)),
511
+ __param(6, (0, common_1.Inject)(constants_1.PLUGIN_INIT_OPTIONS)),
453
512
  __metadata("design:paramtypes", [transactional_connection_1.TransactionalConnection,
513
+ entity_hydrator_service_1.EntityHydrator,
454
514
  product_price_applicator_1.ProductPriceApplicator,
455
515
  config_service_1.ConfigService,
456
516
  request_context_cache_service_1.RequestContextCacheService,