@stacksjs/ts-cloud-core 0.1.7 → 0.1.9

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 (225) hide show
  1. package/package.json +7 -6
  2. package/src/advanced-features.test.ts +465 -0
  3. package/src/aws/cloudformation.ts +421 -0
  4. package/src/aws/cloudfront.ts +158 -0
  5. package/src/aws/credentials.test.ts +132 -0
  6. package/src/aws/credentials.ts +545 -0
  7. package/src/aws/index.ts +87 -0
  8. package/src/aws/s3.test.ts +188 -0
  9. package/src/aws/s3.ts +1088 -0
  10. package/src/aws/signature.test.ts +670 -0
  11. package/src/aws/signature.ts +1155 -0
  12. package/src/backup/disaster-recovery.test.ts +726 -0
  13. package/src/backup/disaster-recovery.ts +500 -0
  14. package/src/backup/index.ts +34 -0
  15. package/src/backup/manager.test.ts +498 -0
  16. package/src/backup/manager.ts +432 -0
  17. package/src/cicd/circleci.ts +430 -0
  18. package/src/cicd/github-actions.ts +424 -0
  19. package/src/cicd/gitlab-ci.ts +255 -0
  20. package/src/cicd/index.ts +8 -0
  21. package/src/cli/history.ts +396 -0
  22. package/src/cli/index.ts +10 -0
  23. package/src/cli/progress.ts +458 -0
  24. package/src/cli/repl.ts +454 -0
  25. package/src/cli/suggestions.ts +327 -0
  26. package/src/cli/table.test.ts +319 -0
  27. package/src/cli/table.ts +332 -0
  28. package/src/cloudformation/builder.test.ts +327 -0
  29. package/src/cloudformation/builder.ts +378 -0
  30. package/src/cloudformation/builders/api-gateway.ts +449 -0
  31. package/src/cloudformation/builders/cache.ts +334 -0
  32. package/src/cloudformation/builders/cdn.ts +278 -0
  33. package/src/cloudformation/builders/compute.ts +485 -0
  34. package/src/cloudformation/builders/database.ts +392 -0
  35. package/src/cloudformation/builders/functions.ts +343 -0
  36. package/src/cloudformation/builders/messaging.ts +140 -0
  37. package/src/cloudformation/builders/monitoring.ts +300 -0
  38. package/src/cloudformation/builders/network.ts +264 -0
  39. package/src/cloudformation/builders/queue.ts +147 -0
  40. package/src/cloudformation/builders/security.ts +399 -0
  41. package/src/cloudformation/builders/storage.ts +285 -0
  42. package/src/cloudformation/index.ts +30 -0
  43. package/src/cloudformation/types.ts +173 -0
  44. package/src/compliance/aws-config.ts +543 -0
  45. package/src/compliance/cloudtrail.ts +376 -0
  46. package/src/compliance/compliance.test.ts +423 -0
  47. package/src/compliance/guardduty.ts +446 -0
  48. package/src/compliance/index.ts +66 -0
  49. package/src/compliance/security-hub.ts +456 -0
  50. package/src/containers/build-optimization.ts +416 -0
  51. package/src/containers/containers.test.ts +508 -0
  52. package/src/containers/image-scanning.ts +360 -0
  53. package/src/containers/index.ts +9 -0
  54. package/src/containers/registry.ts +293 -0
  55. package/src/containers/service-mesh.ts +520 -0
  56. package/src/database/database.test.ts +762 -0
  57. package/src/database/index.ts +9 -0
  58. package/src/database/migrations.ts +444 -0
  59. package/src/database/performance.ts +528 -0
  60. package/src/database/replicas.ts +534 -0
  61. package/src/database/users.ts +494 -0
  62. package/src/dependency-graph.ts +143 -0
  63. package/src/deployment/ab-testing.ts +582 -0
  64. package/src/deployment/blue-green.ts +452 -0
  65. package/src/deployment/canary.ts +500 -0
  66. package/src/deployment/deployment.test.ts +526 -0
  67. package/src/deployment/index.ts +61 -0
  68. package/src/deployment/progressive.ts +62 -0
  69. package/src/dns/dns.test.ts +641 -0
  70. package/src/dns/dnssec.ts +315 -0
  71. package/src/dns/index.ts +8 -0
  72. package/src/dns/resolver.ts +496 -0
  73. package/src/dns/routing.ts +593 -0
  74. package/src/email/advanced/analytics.ts +445 -0
  75. package/src/email/advanced/index.ts +11 -0
  76. package/src/email/advanced/rules.ts +465 -0
  77. package/src/email/advanced/scheduling.ts +352 -0
  78. package/src/email/advanced/search.ts +412 -0
  79. package/src/email/advanced/shared-mailboxes.ts +404 -0
  80. package/src/email/advanced/templates.ts +455 -0
  81. package/src/email/advanced/threading.ts +281 -0
  82. package/src/email/analytics.ts +467 -0
  83. package/src/email/bounce-handling.ts +425 -0
  84. package/src/email/email.test.ts +431 -0
  85. package/src/email/handlers/__tests__/inbound.test.ts +38 -0
  86. package/src/email/handlers/__tests__/outbound.test.ts +37 -0
  87. package/src/email/handlers/converter.ts +227 -0
  88. package/src/email/handlers/feedback.ts +228 -0
  89. package/src/email/handlers/inbound.ts +169 -0
  90. package/src/email/handlers/outbound.ts +178 -0
  91. package/src/email/index.ts +15 -0
  92. package/src/email/reputation.ts +303 -0
  93. package/src/email/templates.ts +352 -0
  94. package/src/errors/index.test.ts +434 -0
  95. package/src/errors/index.ts +416 -0
  96. package/src/health-checks/index.ts +40 -0
  97. package/src/index.ts +360 -0
  98. package/src/intrinsic-functions.ts +118 -0
  99. package/src/lambda/concurrency.ts +330 -0
  100. package/src/lambda/destinations.ts +345 -0
  101. package/src/lambda/dlq.ts +425 -0
  102. package/src/lambda/index.ts +11 -0
  103. package/src/lambda/lambda.test.ts +840 -0
  104. package/src/lambda/layers.ts +263 -0
  105. package/src/lambda/versions.ts +376 -0
  106. package/src/lambda/vpc.ts +399 -0
  107. package/src/local/config.ts +114 -0
  108. package/src/local/index.ts +6 -0
  109. package/src/local/mock-aws.ts +351 -0
  110. package/src/modules/ai.ts +340 -0
  111. package/src/modules/api.ts +478 -0
  112. package/src/modules/auth.ts +805 -0
  113. package/src/modules/cache.ts +417 -0
  114. package/src/modules/cdn.ts +1062 -0
  115. package/src/modules/communication.ts +1094 -0
  116. package/src/modules/compute.ts +3348 -0
  117. package/src/modules/database.ts +554 -0
  118. package/src/modules/deployment.ts +1079 -0
  119. package/src/modules/dns.ts +337 -0
  120. package/src/modules/email.ts +1538 -0
  121. package/src/modules/filesystem.ts +515 -0
  122. package/src/modules/index.ts +32 -0
  123. package/src/modules/messaging.ts +486 -0
  124. package/src/modules/monitoring.ts +2086 -0
  125. package/src/modules/network.ts +664 -0
  126. package/src/modules/parameter-store.ts +325 -0
  127. package/src/modules/permissions.ts +1081 -0
  128. package/src/modules/phone.ts +494 -0
  129. package/src/modules/queue.ts +1260 -0
  130. package/src/modules/redirects.ts +464 -0
  131. package/src/modules/registry.ts +699 -0
  132. package/src/modules/search.ts +401 -0
  133. package/src/modules/secrets.ts +416 -0
  134. package/src/modules/security.ts +731 -0
  135. package/src/modules/sms.ts +389 -0
  136. package/src/modules/storage.ts +1120 -0
  137. package/src/modules/workflow.ts +680 -0
  138. package/src/multi-account/config.ts +521 -0
  139. package/src/multi-account/index.ts +7 -0
  140. package/src/multi-account/manager.ts +427 -0
  141. package/src/multi-region/cross-region.ts +410 -0
  142. package/src/multi-region/index.ts +8 -0
  143. package/src/multi-region/manager.ts +483 -0
  144. package/src/multi-region/regions.ts +435 -0
  145. package/src/network-security/index.ts +48 -0
  146. package/src/observability/index.ts +9 -0
  147. package/src/observability/logs.ts +522 -0
  148. package/src/observability/metrics.ts +460 -0
  149. package/src/observability/observability.test.ts +782 -0
  150. package/src/observability/synthetics.ts +568 -0
  151. package/src/observability/xray.ts +358 -0
  152. package/src/phone/advanced/analytics.ts +349 -0
  153. package/src/phone/advanced/callbacks.ts +428 -0
  154. package/src/phone/advanced/index.ts +8 -0
  155. package/src/phone/advanced/ivr-builder.ts +504 -0
  156. package/src/phone/advanced/recording.ts +310 -0
  157. package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
  158. package/src/phone/handlers/incoming-call.ts +117 -0
  159. package/src/phone/handlers/missed-call.ts +116 -0
  160. package/src/phone/handlers/voicemail.ts +179 -0
  161. package/src/phone/index.ts +9 -0
  162. package/src/presets/api-backend.ts +134 -0
  163. package/src/presets/data-pipeline.ts +204 -0
  164. package/src/presets/extend.test.ts +295 -0
  165. package/src/presets/extend.ts +297 -0
  166. package/src/presets/fullstack-app.ts +144 -0
  167. package/src/presets/index.ts +27 -0
  168. package/src/presets/jamstack.ts +135 -0
  169. package/src/presets/microservices.ts +167 -0
  170. package/src/presets/ml-api.ts +208 -0
  171. package/src/presets/nodejs-server.ts +104 -0
  172. package/src/presets/nodejs-serverless.ts +114 -0
  173. package/src/presets/realtime-app.ts +184 -0
  174. package/src/presets/static-site.ts +64 -0
  175. package/src/presets/traditional-web-app.ts +339 -0
  176. package/src/presets/wordpress.ts +138 -0
  177. package/src/preview/github.test.ts +249 -0
  178. package/src/preview/github.ts +297 -0
  179. package/src/preview/index.ts +37 -0
  180. package/src/preview/manager.test.ts +440 -0
  181. package/src/preview/manager.ts +326 -0
  182. package/src/preview/notifications.test.ts +582 -0
  183. package/src/preview/notifications.ts +341 -0
  184. package/src/queue/batch-processing.ts +402 -0
  185. package/src/queue/dlq-monitoring.ts +402 -0
  186. package/src/queue/fifo.ts +342 -0
  187. package/src/queue/index.ts +9 -0
  188. package/src/queue/management.ts +428 -0
  189. package/src/queue/queue.test.ts +429 -0
  190. package/src/resource-mgmt/index.ts +39 -0
  191. package/src/resource-naming.ts +62 -0
  192. package/src/s3/index.ts +523 -0
  193. package/src/schema/cloud-config.schema.json +554 -0
  194. package/src/schema/index.ts +68 -0
  195. package/src/security/certificate-manager.ts +492 -0
  196. package/src/security/index.ts +9 -0
  197. package/src/security/scanning.ts +545 -0
  198. package/src/security/secrets-manager.ts +476 -0
  199. package/src/security/secrets-rotation.ts +456 -0
  200. package/src/security/security.test.ts +738 -0
  201. package/src/sms/advanced/ab-testing.ts +389 -0
  202. package/src/sms/advanced/analytics.ts +336 -0
  203. package/src/sms/advanced/campaigns.ts +523 -0
  204. package/src/sms/advanced/chatbot.ts +224 -0
  205. package/src/sms/advanced/index.ts +10 -0
  206. package/src/sms/advanced/link-tracking.ts +248 -0
  207. package/src/sms/advanced/mms.ts +308 -0
  208. package/src/sms/handlers/__tests__/send.test.ts +40 -0
  209. package/src/sms/handlers/delivery-status.ts +133 -0
  210. package/src/sms/handlers/receive.ts +162 -0
  211. package/src/sms/handlers/send.ts +174 -0
  212. package/src/sms/index.ts +9 -0
  213. package/src/stack-diff.ts +389 -0
  214. package/src/static-site/index.ts +85 -0
  215. package/src/template-builder.ts +110 -0
  216. package/src/template-validator.ts +574 -0
  217. package/src/utils/cache.ts +291 -0
  218. package/src/utils/diff.ts +269 -0
  219. package/src/utils/hash.ts +227 -0
  220. package/src/utils/index.ts +8 -0
  221. package/src/utils/parallel.ts +294 -0
  222. package/src/validators/credentials.test.ts +274 -0
  223. package/src/validators/credentials.ts +233 -0
  224. package/src/validators/quotas.test.ts +434 -0
  225. package/src/validators/quotas.ts +217 -0
@@ -0,0 +1,412 @@
1
+ /**
2
+ * Email Search and Indexing
3
+ *
4
+ * Provides OpenSearch integration for email search functionality
5
+ */
6
+
7
+ export interface EmailSearchConfig {
8
+ slug: string
9
+ environment: string
10
+ domainName?: string
11
+ instanceType?: string
12
+ instanceCount?: number
13
+ ebsVolumeSize?: number
14
+ masterUserName?: string
15
+ masterUserPassword?: string
16
+ }
17
+
18
+ export interface EmailSearchDocument {
19
+ messageId: string
20
+ from: string
21
+ fromName?: string
22
+ to: string
23
+ toName?: string
24
+ cc?: string[]
25
+ subject: string
26
+ body: string
27
+ bodyPreview: string
28
+ date: string
29
+ receivedAt: string
30
+ hasAttachments: boolean
31
+ attachmentNames?: string[]
32
+ labels?: string[]
33
+ folder: string
34
+ threadId?: string
35
+ isRead: boolean
36
+ isStarred?: boolean
37
+ mailbox: string
38
+ }
39
+
40
+ export interface SearchQuery {
41
+ query: string
42
+ from?: string
43
+ to?: string
44
+ subject?: string
45
+ hasAttachments?: boolean
46
+ dateFrom?: string
47
+ dateTo?: string
48
+ folder?: string
49
+ labels?: string[]
50
+ isRead?: boolean
51
+ limit?: number
52
+ offset?: number
53
+ sort?: 'date' | 'relevance'
54
+ sortOrder?: 'asc' | 'desc'
55
+ }
56
+
57
+ export interface SearchResult {
58
+ total: number
59
+ hits: Array<{
60
+ score: number
61
+ document: EmailSearchDocument
62
+ highlights?: Record<string, string[]>
63
+ }>
64
+ }
65
+
66
+ /**
67
+ * Email Search Module
68
+ */
69
+ export class EmailSearch {
70
+ /**
71
+ * Create OpenSearch domain for email indexing
72
+ */
73
+ static createSearchDomain(config: EmailSearchConfig): Record<string, any> {
74
+ const {
75
+ slug,
76
+ environment,
77
+ domainName,
78
+ instanceType = 't3.small.search',
79
+ instanceCount = 1,
80
+ ebsVolumeSize = 10,
81
+ masterUserName = 'admin',
82
+ masterUserPassword,
83
+ } = config
84
+
85
+ const domain = domainName || `${slug}-${environment}-email-search`
86
+
87
+ return {
88
+ [`${slug}EmailSearchDomain`]: {
89
+ Type: 'AWS::OpenSearchService::Domain',
90
+ Properties: {
91
+ DomainName: domain,
92
+ EngineVersion: 'OpenSearch_2.11',
93
+ ClusterConfig: {
94
+ InstanceType: instanceType,
95
+ InstanceCount: instanceCount,
96
+ DedicatedMasterEnabled: false,
97
+ ZoneAwarenessEnabled: false,
98
+ },
99
+ EBSOptions: {
100
+ EBSEnabled: true,
101
+ VolumeType: 'gp3',
102
+ VolumeSize: ebsVolumeSize,
103
+ },
104
+ NodeToNodeEncryptionOptions: {
105
+ Enabled: true,
106
+ },
107
+ EncryptionAtRestOptions: {
108
+ Enabled: true,
109
+ },
110
+ DomainEndpointOptions: {
111
+ EnforceHTTPS: true,
112
+ },
113
+ AdvancedSecurityOptions: {
114
+ Enabled: true,
115
+ InternalUserDatabaseEnabled: true,
116
+ MasterUserOptions: {
117
+ MasterUserName: masterUserName,
118
+ MasterUserPassword: masterUserPassword || `${slug}-search-${Date.now()}`,
119
+ },
120
+ },
121
+ AccessPolicies: {
122
+ Version: '2012-10-17',
123
+ Statement: [
124
+ {
125
+ Effect: 'Allow',
126
+ Principal: { AWS: '*' },
127
+ Action: 'es:*',
128
+ Resource: `arn:aws:es:*:*:domain/${domain}/*`,
129
+ },
130
+ ],
131
+ },
132
+ },
133
+ },
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Create Lambda for indexing emails
139
+ */
140
+ static createIndexerLambda(config: {
141
+ slug: string
142
+ roleArn: string
143
+ searchDomainEndpoint: string
144
+ emailBucket: string
145
+ }): Record<string, any> {
146
+ return {
147
+ [`${config.slug}EmailIndexerLambda`]: {
148
+ Type: 'AWS::Lambda::Function',
149
+ Properties: {
150
+ FunctionName: `${config.slug}-email-indexer`,
151
+ Runtime: 'nodejs20.x',
152
+ Handler: 'index.handler',
153
+ Role: config.roleArn,
154
+ Timeout: 60,
155
+ MemorySize: 512,
156
+ Code: {
157
+ ZipFile: EmailSearch.IndexerLambdaCode,
158
+ },
159
+ Environment: {
160
+ Variables: {
161
+ OPENSEARCH_ENDPOINT: config.searchDomainEndpoint,
162
+ EMAIL_BUCKET: config.emailBucket,
163
+ },
164
+ },
165
+ },
166
+ },
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Lambda code for email indexing
172
+ */
173
+ static IndexerLambdaCode = `
174
+ const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
175
+ const https = require('https');
176
+
177
+ const s3 = new S3Client({});
178
+ const OPENSEARCH_ENDPOINT = process.env.OPENSEARCH_ENDPOINT;
179
+
180
+ exports.handler = async (event) => {
181
+ console.log('Email indexer event:', JSON.stringify(event, null, 2));
182
+
183
+ for (const record of event.Records) {
184
+ try {
185
+ const bucket = record.s3.bucket.name;
186
+ const key = decodeURIComponent(record.s3.object.key.replace(/\\+/g, ' '));
187
+
188
+ // Only index metadata.json files
189
+ if (!key.endsWith('/metadata.json')) continue;
190
+
191
+ // Get metadata
192
+ const result = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
193
+ const metadata = JSON.parse(await result.Body.transformToString());
194
+
195
+ // Get body preview
196
+ let bodyPreview = '';
197
+ try {
198
+ const previewKey = key.replace('/metadata.json', '/preview.txt');
199
+ const previewResult = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: previewKey }));
200
+ bodyPreview = await previewResult.Body.transformToString();
201
+ } catch {}
202
+
203
+ // Get full body for indexing
204
+ let body = '';
205
+ try {
206
+ const textKey = key.replace('/metadata.json', '/body.txt');
207
+ const textResult = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: textKey }));
208
+ body = await textResult.Body.transformToString();
209
+ } catch {}
210
+
211
+ // Extract mailbox from path
212
+ const pathParts = key.split('/');
213
+ const mailbox = pathParts[1] + '@' + pathParts[2];
214
+
215
+ // Build search document
216
+ const doc = {
217
+ messageId: metadata.messageId,
218
+ from: metadata.from,
219
+ fromName: metadata.fromName,
220
+ to: metadata.to,
221
+ toName: metadata.toName,
222
+ subject: metadata.subject,
223
+ body: body.substring(0, 50000), // Limit body size
224
+ bodyPreview,
225
+ date: metadata.date,
226
+ receivedAt: metadata.receivedAt,
227
+ hasAttachments: metadata.hasAttachments || false,
228
+ attachmentNames: metadata.attachments?.map(a => a.filename) || [],
229
+ folder: 'inbox',
230
+ mailbox,
231
+ isRead: false,
232
+ };
233
+
234
+ // Index to OpenSearch
235
+ await indexDocument(doc);
236
+
237
+ console.log('Indexed email:', metadata.messageId);
238
+ } catch (error) {
239
+ console.error('Error indexing email:', error);
240
+ }
241
+ }
242
+
243
+ return { statusCode: 200 };
244
+ };
245
+
246
+ async function indexDocument(doc) {
247
+ return new Promise((resolve, reject) => {
248
+ const url = new URL(OPENSEARCH_ENDPOINT);
249
+ const options = {
250
+ hostname: url.hostname,
251
+ port: 443,
252
+ path: '/emails/_doc/' + doc.messageId,
253
+ method: 'PUT',
254
+ headers: {
255
+ 'Content-Type': 'application/json',
256
+ },
257
+ };
258
+
259
+ const req = https.request(options, (res) => {
260
+ let data = '';
261
+ res.on('data', chunk => data += chunk);
262
+ res.on('end', () => resolve(JSON.parse(data)));
263
+ });
264
+
265
+ req.on('error', reject);
266
+ req.write(JSON.stringify(doc));
267
+ req.end();
268
+ });
269
+ }
270
+ `
271
+
272
+ /**
273
+ * Create email index mapping
274
+ */
275
+ static getIndexMapping(): Record<string, any> {
276
+ return {
277
+ mappings: {
278
+ properties: {
279
+ messageId: { type: 'keyword' },
280
+ from: { type: 'keyword' },
281
+ fromName: { type: 'text' },
282
+ to: { type: 'keyword' },
283
+ toName: { type: 'text' },
284
+ cc: { type: 'keyword' },
285
+ subject: {
286
+ type: 'text',
287
+ analyzer: 'standard',
288
+ fields: {
289
+ keyword: { type: 'keyword' },
290
+ },
291
+ },
292
+ body: {
293
+ type: 'text',
294
+ analyzer: 'standard',
295
+ },
296
+ bodyPreview: { type: 'text' },
297
+ date: { type: 'date' },
298
+ receivedAt: { type: 'date' },
299
+ hasAttachments: { type: 'boolean' },
300
+ attachmentNames: { type: 'keyword' },
301
+ labels: { type: 'keyword' },
302
+ folder: { type: 'keyword' },
303
+ threadId: { type: 'keyword' },
304
+ isRead: { type: 'boolean' },
305
+ isStarred: { type: 'boolean' },
306
+ mailbox: { type: 'keyword' },
307
+ },
308
+ },
309
+ settings: {
310
+ number_of_shards: 1,
311
+ number_of_replicas: 0,
312
+ },
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Build OpenSearch query from search parameters
318
+ */
319
+ static buildSearchQuery(params: SearchQuery): Record<string, any> {
320
+ const must: any[] = []
321
+ const filter: any[] = []
322
+
323
+ // Full-text search
324
+ if (params.query) {
325
+ must.push({
326
+ multi_match: {
327
+ query: params.query,
328
+ fields: ['subject^3', 'body', 'fromName', 'toName'],
329
+ type: 'best_fields',
330
+ fuzziness: 'AUTO',
331
+ },
332
+ })
333
+ }
334
+
335
+ // Filters
336
+ if (params.from) {
337
+ filter.push({ term: { from: params.from } })
338
+ }
339
+
340
+ if (params.to) {
341
+ filter.push({ term: { to: params.to } })
342
+ }
343
+
344
+ if (params.subject) {
345
+ must.push({ match_phrase: { subject: params.subject } })
346
+ }
347
+
348
+ if (params.hasAttachments !== undefined) {
349
+ filter.push({ term: { hasAttachments: params.hasAttachments } })
350
+ }
351
+
352
+ if (params.folder) {
353
+ filter.push({ term: { folder: params.folder } })
354
+ }
355
+
356
+ if (params.labels && params.labels.length > 0) {
357
+ filter.push({ terms: { labels: params.labels } })
358
+ }
359
+
360
+ if (params.isRead !== undefined) {
361
+ filter.push({ term: { isRead: params.isRead } })
362
+ }
363
+
364
+ // Date range
365
+ if (params.dateFrom || params.dateTo) {
366
+ const range: any = { date: {} }
367
+ if (params.dateFrom) range.date.gte = params.dateFrom
368
+ if (params.dateTo) range.date.lte = params.dateTo
369
+ filter.push({ range })
370
+ }
371
+
372
+ // Build query
373
+ const query: any = {
374
+ bool: {},
375
+ }
376
+
377
+ if (must.length > 0) {
378
+ query.bool.must = must
379
+ }
380
+
381
+ if (filter.length > 0) {
382
+ query.bool.filter = filter
383
+ }
384
+
385
+ // If no conditions, match all
386
+ if (must.length === 0 && filter.length === 0) {
387
+ query.bool.must = [{ match_all: {} }]
388
+ }
389
+
390
+ // Sort
391
+ const sort: any[] = []
392
+ if (params.sort === 'relevance' && params.query) {
393
+ sort.push({ _score: params.sortOrder || 'desc' })
394
+ }
395
+ sort.push({ date: params.sortOrder || 'desc' })
396
+
397
+ return {
398
+ query,
399
+ sort,
400
+ from: params.offset || 0,
401
+ size: params.limit || 20,
402
+ highlight: {
403
+ fields: {
404
+ subject: {},
405
+ body: { fragment_size: 150, number_of_fragments: 3 },
406
+ },
407
+ },
408
+ }
409
+ }
410
+ }
411
+
412
+ export default EmailSearch