@infrab4a/connect-nestjs 2.0.0-alpha.9 → 3.0.0-alpha.0

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 (98) hide show
  1. package/eslint.config.js +17 -0
  2. package/package.json +4 -15
  3. package/project.json +49 -0
  4. package/rollup.config.js +17 -0
  5. package/src/consts/es-config.const.ts +1 -0
  6. package/src/consts/hasura-options.const.ts +1 -0
  7. package/src/consts/index.ts +4 -0
  8. package/src/consts/storage.const.ts +1 -0
  9. package/src/consts/vertex-config.const.ts +1 -0
  10. package/src/index.ts +7 -0
  11. package/src/infra/elasticsearch/adapters/index.ts +1 -0
  12. package/src/infra/elasticsearch/adapters/native-elasticsearch-adapter.ts +137 -0
  13. package/src/infra/elasticsearch/index.ts +1 -0
  14. package/src/infra/firebase/firestore/index.ts +2 -0
  15. package/src/infra/firebase/firestore/services/connect-collection-reference.ts +27 -0
  16. package/src/infra/firebase/firestore/services/connect-collection.service.ts +137 -0
  17. package/src/infra/firebase/firestore/services/connect-document-reference.ts +12 -0
  18. package/src/infra/firebase/firestore/services/connect-document.service.ts +51 -0
  19. package/src/infra/firebase/firestore/services/connect-firestore.service.ts +24 -0
  20. package/src/infra/firebase/firestore/services/connect-firestore.ts +9 -0
  21. package/src/infra/firebase/firestore/services/index.ts +6 -0
  22. package/src/infra/firebase/firestore/types/connect-query-snapshot.type.ts +6 -0
  23. package/src/infra/firebase/firestore/types/index.ts +1 -0
  24. package/src/infra/firebase/firestore/vo/connect-base-document-snapshot.vo.ts +27 -0
  25. package/src/infra/firebase/firestore/vo/index.ts +1 -0
  26. package/src/infra/firebase/index.ts +1 -0
  27. package/src/infra/index.ts +4 -0
  28. package/src/infra/pagarme/adapters/index.ts +3 -0
  29. package/src/infra/pagarme/adapters/pagarme-bank-slip-api.adapter.ts +96 -0
  30. package/src/infra/pagarme/adapters/pagarme-card-api.adapter.ts +226 -0
  31. package/src/infra/pagarme/adapters/pagarme-pix-api.adapter.ts +69 -0
  32. package/src/infra/pagarme/index.ts +1 -0
  33. package/src/infra/vertex-ai/adapters/discovery-engine-adapter.ts +148 -0
  34. package/src/infra/vertex-ai/adapters/index.ts +1 -0
  35. package/src/infra/vertex-ai/helpers/index.ts +1 -0
  36. package/src/infra/vertex-ai/helpers/product-vertex-ai.helper.ts +52 -0
  37. package/src/infra/vertex-ai/index.ts +3 -0
  38. package/src/infra/vertex-ai/types/index.ts +2 -0
  39. package/src/infra/vertex-ai/types/vertex-config.ts +23 -0
  40. package/src/infra/vertex-ai/types/vertex-search-result.ts +17 -0
  41. package/src/nest-connect.module.ts +36 -0
  42. package/src/nest-elastic-search.module.ts +26 -0
  43. package/src/nest-firestore.module.ts +363 -0
  44. package/src/nest-hasura-graphql.module.ts +227 -0
  45. package/src/nest-storage.module.ts +16 -0
  46. package/src/nest-vertex-ai-search.module.ts +26 -0
  47. package/src/types/pagarme.d.ts +25 -0
  48. package/tsconfig.json +15 -0
  49. package/tsconfig.lib.json +7 -0
  50. package/tsconfig.lib.prod.json +10 -0
  51. package/tsconfig.spec.json +17 -0
  52. package/index.cjs.d.ts +0 -1
  53. package/index.cjs.default.js +0 -1
  54. package/index.cjs.js +0 -1334
  55. package/index.cjs.mjs +0 -2
  56. package/index.esm.js +0 -1317
  57. package/src/consts/es-config.const.d.ts +0 -1
  58. package/src/consts/hasura-options.const.d.ts +0 -1
  59. package/src/consts/index.d.ts +0 -4
  60. package/src/consts/storage.const.d.ts +0 -1
  61. package/src/consts/vertex-config.const.d.ts +0 -1
  62. package/src/index.d.ts +0 -7
  63. package/src/infra/elasticsearch/adapters/index.d.ts +0 -1
  64. package/src/infra/elasticsearch/adapters/native-elasticsearch-adapter.d.ts +0 -19
  65. package/src/infra/elasticsearch/index.d.ts +0 -1
  66. package/src/infra/firebase/firestore/index.d.ts +0 -2
  67. package/src/infra/firebase/firestore/services/connect-collection-reference.d.ts +0 -19
  68. package/src/infra/firebase/firestore/services/connect-collection.service.d.ts +0 -32
  69. package/src/infra/firebase/firestore/services/connect-document-reference.d.ts +0 -11
  70. package/src/infra/firebase/firestore/services/connect-document.service.d.ts +0 -17
  71. package/src/infra/firebase/firestore/services/connect-firestore.d.ts +0 -7
  72. package/src/infra/firebase/firestore/services/connect-firestore.service.d.ts +0 -8
  73. package/src/infra/firebase/firestore/services/index.d.ts +0 -6
  74. package/src/infra/firebase/firestore/types/connect-query-snapshot.type.d.ts +0 -4
  75. package/src/infra/firebase/firestore/types/index.d.ts +0 -1
  76. package/src/infra/firebase/firestore/vo/connect-base-document-snapshot.vo.d.ts +0 -12
  77. package/src/infra/firebase/firestore/vo/index.d.ts +0 -1
  78. package/src/infra/firebase/index.d.ts +0 -1
  79. package/src/infra/index.d.ts +0 -4
  80. package/src/infra/pagarme/adapters/index.d.ts +0 -3
  81. package/src/infra/pagarme/adapters/pagarme-bank-slip-api.adapter.d.ts +0 -9
  82. package/src/infra/pagarme/adapters/pagarme-card-api.adapter.d.ts +0 -21
  83. package/src/infra/pagarme/adapters/pagarme-pix-api.adapter.d.ts +0 -8
  84. package/src/infra/pagarme/index.d.ts +0 -1
  85. package/src/infra/vertex-ai/adapters/discovery-engine-adapter.d.ts +0 -17
  86. package/src/infra/vertex-ai/adapters/index.d.ts +0 -1
  87. package/src/infra/vertex-ai/helpers/index.d.ts +0 -1
  88. package/src/infra/vertex-ai/helpers/product-vertex-ai.helper.d.ts +0 -7
  89. package/src/infra/vertex-ai/index.d.ts +0 -3
  90. package/src/infra/vertex-ai/types/index.d.ts +0 -2
  91. package/src/infra/vertex-ai/types/vertex-config.d.ts +0 -23
  92. package/src/infra/vertex-ai/types/vertex-search-result.d.ts +0 -18
  93. package/src/nest-connect.module.d.ts +0 -13
  94. package/src/nest-elastic-search.module.d.ts +0 -5
  95. package/src/nest-firestore.module.d.ts +0 -10
  96. package/src/nest-hasura-graphql.module.d.ts +0 -13
  97. package/src/nest-storage.module.d.ts +0 -2
  98. package/src/nest-vertex-ai-search.module.d.ts +0 -5
@@ -0,0 +1,96 @@
1
+ import {
2
+ addDays,
3
+ BusinessError,
4
+ Checkout,
5
+ format,
6
+ PagarmeCredentials,
7
+ PagarmePaymentStatus,
8
+ Payment,
9
+ PaymentError,
10
+ PaymentProviderBankSlip,
11
+ PaymentRepository,
12
+ PaymentTransaction,
13
+ } from '@infrab4a/connect'
14
+ import pagarme from 'pagarme'
15
+
16
+ export class PagarmeBankSlipAPIAdapter implements PaymentProviderBankSlip {
17
+ constructor(private credentials: PagarmeCredentials, private paymentRepository: PaymentRepository) {}
18
+
19
+ public async pay(checkout: Checkout): Promise<Payment> {
20
+ try {
21
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
22
+ const payload = this.createBoletoPayment(checkout)
23
+ const result = await client.transactions.create(payload)
24
+
25
+ console.warn('[PAGARME BOLETO DATA TO SEND]', payload)
26
+ console.warn('result PagarmeBankSlipAPIAdapter', JSON.stringify(result))
27
+
28
+ if (result.status !== PagarmePaymentStatus['Em processamento']) {
29
+ return Promise.reject(
30
+ new PaymentError('Houve uma falha ao gerar o boleto. Tente novamente', {
31
+ checkoutId: checkout.id,
32
+ userEmail: checkout.user.email,
33
+ info: result,
34
+ }),
35
+ )
36
+ }
37
+
38
+ const payment = await this.paymentRepository.create({
39
+ createdAt: new Date(),
40
+ updatedAt: new Date(),
41
+ userId: checkout.user.id,
42
+ checkoutId: checkout.id,
43
+ totalPrice: checkout.totalPrice,
44
+ paymentProvider: 'pagarMe',
45
+ transaction: result,
46
+ })
47
+
48
+ return payment
49
+ } catch (error) {
50
+ console.error('Error PagarmeBankSlipAPIAdapter', JSON.stringify(error))
51
+ throw new PaymentError('Houve uma falha ao gerar o boleto. Tente novamente', {
52
+ checkoutId: checkout.id,
53
+ userEmail: checkout.user.email,
54
+ info: error,
55
+ })
56
+ }
57
+ }
58
+
59
+ public async getBoletoTransaction(paymentId: number): Promise<PaymentTransaction> {
60
+ try {
61
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
62
+ const result = await client.transactions.find({ id: paymentId })
63
+
64
+ return result as PaymentTransaction
65
+ } catch (error) {
66
+ throw new BusinessError('Houve uma falha buscar o boleto com paymentId: ' + paymentId, {
67
+ paymentId,
68
+ info: error,
69
+ })
70
+ }
71
+ }
72
+
73
+ private createBoletoPayment(checkout: Checkout) {
74
+ return {
75
+ api_key: this.credentials.API_KEY,
76
+ amount: Math.floor(checkout.totalPrice * 100),
77
+ boleto_rules: ['strict_expiration_date'],
78
+ boleto_instructions: 'Sr. Caixa, NÃO aceitar o pagamento após o vencimento.',
79
+ boleto_expiration_date: format(addDays(new Date(), 3), 'yyyy-MM-dd'),
80
+ payment_method: 'boleto',
81
+ postback_url: this.credentials.URL_POSTBACK,
82
+ customer: {
83
+ external_id: checkout.user.id,
84
+ type: 'individual',
85
+ country: 'br',
86
+ name: checkout.user.displayName,
87
+ documents: [
88
+ {
89
+ type: 'cpf',
90
+ number: checkout.user.cpf,
91
+ },
92
+ ],
93
+ },
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,226 @@
1
+ import {
2
+ BusinessError,
3
+ BusinessUnitEnum,
4
+ CardInfo,
5
+ Checkout,
6
+ LineItem,
7
+ OrderBlockedRepository,
8
+ PagarMeCard,
9
+ PagarmeCredentials,
10
+ PagarmePaymentStatus,
11
+ Payment,
12
+ PaymentCardInfo,
13
+ PaymentError,
14
+ PaymentProviderCard,
15
+ PaymentProviders,
16
+ PaymentRepository,
17
+ PaymentTransaction,
18
+ Shops,
19
+ } from '@infrab4a/connect'
20
+ import pagarme from 'pagarme'
21
+
22
+ export class PagarmeCardAPIAdapter implements PaymentProviderCard<PagarMeCard> {
23
+ constructor(
24
+ private credentials: PagarmeCredentials,
25
+ private paymentRepository: PaymentRepository,
26
+ private orderBlockedRepository: OrderBlockedRepository,
27
+ ) {}
28
+
29
+ public async pay(checkout: Checkout, card: PaymentCardInfo): Promise<Payment> {
30
+ try {
31
+ const client = await this.createPagarmeClient()
32
+ const transactionResult = await this.executeCardTransaction(client, checkout, card)
33
+
34
+ await this.validateTransactionResult(transactionResult, checkout, card)
35
+
36
+ return await this.createPaymentRecord(checkout, transactionResult)
37
+ } catch (error) {
38
+ this.handlePaymentError(error, checkout)
39
+ }
40
+ }
41
+
42
+ private async createPagarmeClient() {
43
+ return await pagarme.client.connect({ api_key: this.credentials.API_KEY })
44
+ }
45
+
46
+ private async executeCardTransaction(client: any, checkout: Checkout, card: PaymentCardInfo) {
47
+ const payload = this.createCardPayment(checkout, card)
48
+ const result = await client.transactions.create(payload)
49
+
50
+ this.logTransactionDetails(payload, result)
51
+
52
+ return result
53
+ }
54
+
55
+ private logTransactionDetails(payload: any, result: any): void {
56
+ console.warn('[PAGARME CARD DATA TO SEND]', payload)
57
+ console.warn('result PagarmeCardAPIAdapter', JSON.stringify(result))
58
+ }
59
+
60
+ private async validateTransactionResult(result: any, checkout: Checkout, card: PaymentCardInfo): Promise<void> {
61
+ if (result.status !== PagarmePaymentStatus.Pago) {
62
+ await this.handleUnauthorizedPayment(checkout, card, result)
63
+ }
64
+ }
65
+
66
+ private async handleUnauthorizedPayment(checkout: Checkout, card: PaymentCardInfo, result: any): Promise<never> {
67
+ await this.createBlockedOrderRecord(checkout, card)
68
+
69
+ throw new PaymentError(
70
+ 'Seu pagamento com cartão não foi autorizado. Para não perder seus produtos, pague com PIX ou outro cartão de crédito',
71
+ {
72
+ checkoutId: checkout.id,
73
+ userEmail: checkout.user.email,
74
+ info: result,
75
+ },
76
+ )
77
+ }
78
+
79
+ private async createBlockedOrderRecord(checkout: Checkout, card: PaymentCardInfo): Promise<void> {
80
+ await this.orderBlockedRepository.createBlockedOrderOrPayment({
81
+ checkout,
82
+ blockType: 'Card not authorized',
83
+ type: 'Card',
84
+ limiteRange: 'day',
85
+ card,
86
+ })
87
+ }
88
+
89
+ private async createPaymentRecord(checkout: Checkout, transactionResult: any): Promise<Payment> {
90
+ return await this.paymentRepository.create({
91
+ createdAt: new Date(),
92
+ updatedAt: new Date(),
93
+ userId: checkout.user.id,
94
+ checkoutId: checkout.id,
95
+ totalPrice: checkout.totalPrice,
96
+ paymentProvider: PaymentProviders.PAGARME,
97
+ transaction: { ...transactionResult, paidAt: new Date() },
98
+ })
99
+ }
100
+
101
+ private handlePaymentError(error: any, checkout: Checkout): never {
102
+ console.error('Error PagarmeCardAPIAdapter', JSON.stringify(error))
103
+
104
+ throw new PaymentError(
105
+ 'Seu pagamento com cartão não foi autorizado. Para não perder seus produtos, pague com PIX ou outro cartão de crédito',
106
+ {
107
+ checkoutId: checkout.id,
108
+ userEmail: checkout.user.email,
109
+ info: error,
110
+ },
111
+ )
112
+ }
113
+
114
+ public async addCard(card: CardInfo): Promise<PagarMeCard> {
115
+ try {
116
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
117
+ const result = await client.cards.create({
118
+ card_number: card.number,
119
+ card_expiration_date: card.expirationDate.replace('/', ''),
120
+ card_holder_name: card.name,
121
+ card_cvv: card.cvv,
122
+ })
123
+
124
+ return result as PagarMeCard
125
+ } catch (error) {
126
+ throw new BusinessError('Houve uma falha adicionar o cartão', {
127
+ info: error,
128
+ })
129
+ }
130
+ }
131
+
132
+ public async createCardHash(bu: BusinessUnitEnum, card: CardInfo): Promise<string> {
133
+ try {
134
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
135
+ const result = await client.security.encrypt({
136
+ card_number: card.number,
137
+ card_expiration_date: card.expirationDate.replace('/', ''),
138
+ card_holder_name: card.name,
139
+ card_cvv: card.cvv,
140
+ })
141
+
142
+ return result as string
143
+ } catch (error) {
144
+ throw new BusinessError('Houve uma falha ao gerar o hash do cartão', {
145
+ info: error,
146
+ })
147
+ }
148
+ }
149
+
150
+ public async getCardByToken(id: string): Promise<PagarMeCard> {
151
+ try {
152
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
153
+ const result = await client.cards.find({
154
+ id,
155
+ })
156
+
157
+ return result as PagarMeCard
158
+ } catch (error) {
159
+ throw new BusinessError('Houve uma falha buscar o cartão com id: ' + id, {
160
+ info: error,
161
+ })
162
+ }
163
+ }
164
+
165
+ public async createTransaction(data: any): Promise<PaymentTransaction> {
166
+ try {
167
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
168
+ const result = await client.transactions.create(data)
169
+
170
+ return result as PaymentTransaction
171
+ } catch (error) {
172
+ throw new BusinessError('Houve uma falha ao criar a transação', {
173
+ info: error,
174
+ })
175
+ }
176
+ }
177
+
178
+ private createCardPayment(checkout: Checkout, card: PaymentCardInfo) {
179
+ return {
180
+ api_key: this.credentials.API_KEY,
181
+ amount: Math.floor(checkout.totalPrice * 100),
182
+ card_id: card.cardId,
183
+ card_cvv: card.cardCvv,
184
+ payment_method: 'credit_card',
185
+ installments: card.installments,
186
+ soft_descriptor: checkout.shop === Shops.GLAMSHOP ? 'Glam' : "Men's Market",
187
+ customer: {
188
+ external_id: checkout.user.id,
189
+ name: checkout.user.displayName,
190
+ type: 'individual',
191
+ country: 'br',
192
+ email: checkout.user.email,
193
+ phone_numbers: checkout.user.phone ? ['+55' + checkout.user.phone] : '',
194
+ documents: [
195
+ {
196
+ type: 'cpf',
197
+ number: checkout.user.cpf,
198
+ },
199
+ ],
200
+ },
201
+ billing: {
202
+ name: checkout.user.displayName,
203
+ address: {
204
+ country: 'br',
205
+ state: checkout.billingAddress ? checkout.billingAddress.state : checkout.shippingAddress?.state,
206
+ city: checkout.billingAddress ? checkout.billingAddress.city : checkout.shippingAddress?.city,
207
+ neighborhood: checkout.billingAddress ? checkout.billingAddress.district : checkout.shippingAddress?.district,
208
+ street: checkout.billingAddress ? checkout.billingAddress.street : checkout.shippingAddress?.street,
209
+ street_number: checkout.billingAddress ? checkout.billingAddress.number : checkout.shippingAddress?.number,
210
+ zipcode: checkout.billingAddress
211
+ ? checkout.billingAddress.zip.replace('-', '')
212
+ : checkout.shippingAddress?.zip.replace('-', ''),
213
+ },
214
+ },
215
+ items: checkout.lineItems.map((item: LineItem) => {
216
+ return {
217
+ id: item.id,
218
+ title: checkout.user.isSubscriber ? `${item.name} - ASSINANTE` : item.name,
219
+ unit_price: Math.floor(item.pricePaid * 100),
220
+ quantity: item.quantity,
221
+ tangible: true,
222
+ }
223
+ }),
224
+ }
225
+ }
226
+ }
@@ -0,0 +1,69 @@
1
+ import {
2
+ addDays,
3
+ Checkout,
4
+ format,
5
+ PagarmeCredentials,
6
+ Payment,
7
+ PaymentError,
8
+ PaymentProviderPix,
9
+ PaymentRepository,
10
+ } from '@infrab4a/connect'
11
+ import pagarme from 'pagarme'
12
+
13
+ export class PagarmePixAPIAdapter implements PaymentProviderPix {
14
+ constructor(private credentials: PagarmeCredentials, private paymentRepository: PaymentRepository) {}
15
+
16
+ public async pay(checkout: Checkout): Promise<Payment> {
17
+ try {
18
+ const client = await pagarme.client.connect({ api_key: this.credentials.API_KEY })
19
+ const payload = this.createPixPayment(checkout)
20
+ const result = await client.transactions.create(payload)
21
+
22
+ console.warn('[PAGARME PIX DATA TO SEND]', payload)
23
+ console.warn('result PagarmePixAPIAdapter', JSON.stringify(result))
24
+
25
+ const payment = await this.paymentRepository.create({
26
+ createdAt: new Date(),
27
+ updatedAt: new Date(),
28
+ userId: checkout.user.id,
29
+ checkoutId: checkout.id,
30
+ totalPrice: checkout.totalPrice,
31
+ paymentProvider: 'pagarMe',
32
+ transaction: result,
33
+ })
34
+
35
+ return payment
36
+ } catch (error) {
37
+ console.error('Error PagarmePixAPIAdapter', JSON.stringify(error))
38
+ throw new PaymentError('Houve uma falha ao processar pagamento com pix', {
39
+ checkoutId: checkout.id,
40
+ userEmail: checkout.user.email,
41
+ info: error,
42
+ })
43
+ }
44
+ }
45
+
46
+ private createPixPayment(checkout: Checkout) {
47
+ return {
48
+ payment_method: 'pix',
49
+ amount: Math.floor(checkout.totalPrice * 100),
50
+ api_key: this.credentials.API_KEY,
51
+ postback_url: this.credentials.URL_POSTBACK,
52
+ pix_expiration_date: format(addDays(new Date(), 1), 'yyyy-MM-dd'),
53
+ customer: {
54
+ external_id: checkout.user.id,
55
+ type: 'individual',
56
+ country: 'br',
57
+ name: checkout.user.displayName,
58
+ email: checkout.user.email.trim(),
59
+ phone_numbers: checkout.user.phone ? ['+55' + checkout.user.phone] : '',
60
+ documents: [
61
+ {
62
+ type: 'cpf',
63
+ number: checkout.user.cpf,
64
+ },
65
+ ],
66
+ },
67
+ }
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+ export * from './adapters'
@@ -0,0 +1,148 @@
1
+ import { DocumentServiceClient } from '@google-cloud/discoveryengine'
2
+ import { SearchServiceClient } from '@google-cloud/discoveryengine/build/src/v1beta'
3
+ import { ProductBulk, ProductHasuraGraphQL, ProductSearch, VertexSearchAdapter } from '@infrab4a/connect'
4
+ import { Inject, Injectable } from '@nestjs/common'
5
+
6
+ import { VERTEX_CONFIG } from '../../../consts'
7
+ import { ProductVertexHelper } from '../helpers/product-vertex-ai.helper'
8
+ import { VertexConfig, VertexSearchResult } from '../types'
9
+
10
+ @Injectable()
11
+ export class DiscoveryEngineVertexAdapter implements VertexSearchAdapter<ProductSearch> {
12
+ private config: VertexConfig
13
+ private parentEngine: string
14
+ private parentDataStore: string
15
+ private servingConfig: string
16
+ private searchClient
17
+ private documentClient
18
+
19
+ constructor(@Inject(VERTEX_CONFIG) configuration: VertexConfig) {
20
+ this.config = configuration
21
+ this.parentEngine =
22
+ `projects/${this.config.projectId}/locations/${this.config.location}/` +
23
+ `collections/default_collection/engines/${this.config.dataStoreId}`
24
+ this.parentDataStore =
25
+ `projects/${this.config.projectId}/locations/${this.config.location}/` +
26
+ `collections/default_collection/dataStores/${this.config.dataStoreId}/branches/default_branch/documents`
27
+ this.searchClient = new SearchServiceClient({
28
+ apiEndpoint: configuration.apiEndpoint,
29
+ credentials: configuration.credentials,
30
+ })
31
+ this.documentClient = new DocumentServiceClient({
32
+ apiEndpoint: configuration.apiEndpoint,
33
+ credentials: configuration.credentials,
34
+ })
35
+ this.servingConfig = this.searchClient.projectLocationCollectionDataStoreServingConfigPath(
36
+ configuration.projectId,
37
+ configuration.location,
38
+ configuration.collectionId,
39
+ configuration.dataStoreId,
40
+ configuration.servingConfigId,
41
+ )
42
+ }
43
+
44
+ public async save(product: ProductHasuraGraphQL) {
45
+ const productSearch = ProductVertexHelper.productMapper(product)
46
+
47
+ const request = {
48
+ parent: this.parentEngine,
49
+ allowMissing: true,
50
+ document: {
51
+ name: this.parentDataStore + `/${product.id}`,
52
+ jsonData: JSON.stringify(productSearch),
53
+ data: 'jsonData',
54
+ },
55
+ }
56
+
57
+ const response = await this.documentClient.updateDocument(request)
58
+
59
+ return response
60
+ }
61
+
62
+ public async update(id: string, data: ProductHasuraGraphQL) {
63
+ const productSearch = ProductVertexHelper.productMapper(data)
64
+
65
+ const request = {
66
+ parent: this.parentEngine,
67
+ allowMissing: true,
68
+ document: {
69
+ name: this.parentDataStore + `/${id}`,
70
+ jsonData: JSON.stringify(productSearch),
71
+ data: 'jsonData',
72
+ },
73
+ }
74
+
75
+ const response = await this.documentClient.updateDocument(request)
76
+
77
+ return response
78
+ }
79
+
80
+ public async query(term: string, total: number) {
81
+ const response = (await this.searchClient.search(
82
+ {
83
+ pageSize: total,
84
+ query: term,
85
+ filter: '',
86
+ languageCode: 'pt-BR',
87
+ servingConfig: this.servingConfig,
88
+ relevanceThreshold: 'MEDIUM',
89
+ },
90
+ {
91
+ autoPaginate: false,
92
+ },
93
+ )) as VertexSearchResult<ProductSearch>
94
+
95
+ return ProductVertexHelper.resultProductMapper(response)
96
+ }
97
+
98
+ public async get(id: string) {
99
+ const request = {
100
+ name: this.parentDataStore + `/${id}`,
101
+ }
102
+
103
+ const response = await this.documentClient.getDocument(request)
104
+ const document = JSON.parse(response[0].jsonData)
105
+
106
+ return document
107
+ }
108
+
109
+ public async delete(id: string) {
110
+ const request = {
111
+ name: this.parentDataStore + `/${id}`,
112
+ }
113
+
114
+ await this.documentClient.deleteDocument(request)
115
+ }
116
+
117
+ public async bulkProducts(products: ProductBulk[]): Promise<void> {
118
+ try {
119
+ const batchSize = 100
120
+ let total = 0
121
+
122
+ for (let index = 0; index < products.length; index += batchSize) {
123
+ const bulkProducts = products.slice(index, index + batchSize)
124
+
125
+ const [operation] = await this.documentClient.importDocuments({
126
+ parent:
127
+ `projects/${this.config.projectId}/locations/${this.config.location}/` +
128
+ `collections/default_collection/dataStores/${this.config.dataStoreId}/branches/default_branch`,
129
+ inlineSource: {
130
+ documents: bulkProducts,
131
+ },
132
+ })
133
+
134
+ total += bulkProducts.length
135
+ const [response] = await operation.promise()
136
+
137
+ console.warn(
138
+ `Imported: ${total} documents`,
139
+ ((total / products.length) * 100).toFixed(2) + '%',
140
+ 'Erros: ',
141
+ response.errorSamples ? response.errorSamples : [],
142
+ )
143
+ }
144
+ } catch (error) {
145
+ console.error(error)
146
+ }
147
+ }
148
+ }
@@ -0,0 +1 @@
1
+ export * from './discovery-engine-adapter'
@@ -0,0 +1 @@
1
+ export * from './product-vertex-ai.helper'
@@ -0,0 +1,52 @@
1
+ import { ProductHasuraGraphQL, ProductSearch } from '@infrab4a/connect'
2
+
3
+ import { VertexSearchResult } from '../types'
4
+
5
+ export class ProductVertexHelper {
6
+ constructor() {}
7
+
8
+ public static productMapper(product: ProductHasuraGraphQL): ProductSearch {
9
+ const image = product.miniatures && (product.miniatures as string[]).length ? product.miniatures[0] : null
10
+
11
+ return {
12
+ id: product.id.toString(),
13
+ miniatures: image,
14
+ icon: image,
15
+ name: product.name,
16
+ brand: product.brand?.toString().trim() ? product.brand?.toString().trim() : null,
17
+ ean: product.EAN,
18
+ sku: product.sku,
19
+ slug: product.slug,
20
+ published: product.published,
21
+ gender: product.gender,
22
+ stock: product.stock.quantity,
23
+ rating: product.rate,
24
+ shoppingCount: product.shoppingCount,
25
+ description: product.description.description,
26
+ fullPrice: product.fullPrice,
27
+ price: product.price.price,
28
+ subscriberPrice: product.subscriberPrice,
29
+ outlet: product.outlet,
30
+ createdAt: product.createdAt,
31
+ }
32
+ }
33
+
34
+ public static resultProductMapper(result: VertexSearchResult<ProductSearch>): ProductSearch[] {
35
+ return result[0].length
36
+ ? result[0].map((result) => {
37
+ return {
38
+ id: result.document?.structData.fields.id.stringValue,
39
+ name: result.document?.structData.fields.name.stringValue,
40
+ brand: result.document?.structData.fields.brand?.stringValue,
41
+ stock: result.document?.structData.fields.stock?.numberValue,
42
+ rating: result.document?.structData.fields.rating?.stringValue,
43
+ gender: result.document?.structData.fields.gender?.stringValue,
44
+ slug: result.document?.structData.fields.slug?.stringValue,
45
+ sku: result.document?.structData.fields.sku?.stringValue,
46
+ ean: result.document?.structData.fields.ean?.stringValue,
47
+ description: result.document?.structData.fields.description?.stringValue,
48
+ } as any
49
+ })
50
+ : []
51
+ }
52
+ }
@@ -0,0 +1,3 @@
1
+ export * from './adapters'
2
+ export * from './helpers'
3
+ export * from './types'
@@ -0,0 +1,2 @@
1
+ export * from './vertex-config'
2
+ export * from './vertex-search-result'
@@ -0,0 +1,23 @@
1
+ export type VertexConfig = {
2
+ credentials: {
3
+ type: string
4
+ project_id: string
5
+ private_key_id: string
6
+ private_key: string
7
+ client_email: string
8
+ client_id: string
9
+ auth_uri?: string
10
+ token_uri?: string
11
+ auth_provider_x509_cert_url?: string
12
+ client_x509_cert_url?: string
13
+ apiKey?: string
14
+ authDomain?: string
15
+ }
16
+ apiEndpoint: string
17
+ projectId: string
18
+ location: string
19
+ dataStoreId: string
20
+ collectionId: string
21
+ engine: string
22
+ servingConfigId: string
23
+ }
@@ -0,0 +1,17 @@
1
+ import { protos } from '@google-cloud/discoveryengine'
2
+
3
+ export type VertexSearchResult<T> = [
4
+ VertexResult<T>[],
5
+ protos.google.cloud.discoveryengine.v1.ISearchRequest | null,
6
+ protos.google.cloud.discoveryengine.v1.ISearchResponse,
7
+ ]
8
+
9
+ type VertexResult<T> = {
10
+ id?: string | null
11
+ document?: {
12
+ structData: {
13
+ fields: { [P in keyof T]: any }
14
+ }
15
+ }
16
+ chunk?: protos.google.cloud.discoveryengine.v1.IChunk
17
+ }
@@ -0,0 +1,36 @@
1
+ import { isNil } from '@infrab4a/connect'
2
+ import { DynamicModule, Module } from '@nestjs/common'
3
+
4
+ import { ESClientOptions, VertexConfig } from './infra'
5
+ import { NestElasticSeachModule } from './nest-elastic-search.module'
6
+ import { NestFirestoreModule } from './nest-firestore.module'
7
+ import { HasuraGraphQLOptions, NestHasuraGraphQLModule } from './nest-hasura-graphql.module'
8
+ import { NestVertexSeachModule } from './nest-vertex-ai-search.module'
9
+
10
+ @Module({})
11
+ export class NestConnectModule {
12
+ public static initializeApp(options: {
13
+ firebase?: {
14
+ googleApplicationCredential: string
15
+ }
16
+ elasticSearch?: ESClientOptions
17
+ hasura: HasuraGraphQLOptions
18
+ vertex?: VertexConfig
19
+ }): DynamicModule {
20
+ return {
21
+ module: NestConnectModule,
22
+ imports: [
23
+ ...(options.firebase ? [NestFirestoreModule.initializeApp({ firebase: options.firebase })] : []),
24
+ ...(isNil(options?.hasura) ? [] : [NestHasuraGraphQLModule.initializeApp(options.hasura)]),
25
+ ...(isNil(options?.elasticSearch) ? [] : [NestElasticSeachModule.initializeApp(options.elasticSearch)]),
26
+ ...(isNil(options?.vertex) ? [] : [NestVertexSeachModule.initializeApp(options.vertex)]),
27
+ ],
28
+ exports: [
29
+ ...(options.firebase ? [NestFirestoreModule] : []),
30
+ ...(isNil(options?.hasura) ? [] : [NestHasuraGraphQLModule]),
31
+ ...(isNil(options?.elasticSearch) ? [] : [NestElasticSeachModule]),
32
+ ...(isNil(options?.vertex) ? [] : [NestVertexSeachModule]),
33
+ ],
34
+ }
35
+ }
36
+ }