@open-mercato/core 0.6.6-develop.6413.1.ae875fb682 → 0.6.6-develop.6419.1.a632f417c4

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 (32) hide show
  1. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +5 -1
  2. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +2 -2
  3. package/dist/modules/messages/api/[id]/route.js +25 -2
  4. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  5. package/dist/modules/messages/api/openapi.js +1 -0
  6. package/dist/modules/messages/api/openapi.js.map +2 -2
  7. package/dist/modules/messages/commands/actions.js +8 -0
  8. package/dist/modules/messages/commands/actions.js.map +2 -2
  9. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +50 -24
  10. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +2 -2
  11. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js +1 -0
  12. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js.map +2 -2
  13. package/dist/modules/messages/lib/constants.js +3 -1
  14. package/dist/modules/messages/lib/constants.js.map +2 -2
  15. package/dist/modules/query_index/lib/batch.js +11 -2
  16. package/dist/modules/query_index/lib/batch.js.map +2 -2
  17. package/dist/modules/query_index/lib/search-tokens.js +2 -31
  18. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  19. package/dist/modules/sync_excel/lib/adapters/customers.js +6 -6
  20. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  21. package/package.json +7 -7
  22. package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +5 -1
  23. package/src/modules/messages/api/[id]/route.ts +30 -1
  24. package/src/modules/messages/api/openapi.ts +1 -0
  25. package/src/modules/messages/commands/actions.ts +14 -0
  26. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +53 -28
  27. package/src/modules/messages/components/message-detail/panels/composer-dialogs.tsx +1 -0
  28. package/src/modules/messages/components/message-detail/types.ts +1 -0
  29. package/src/modules/messages/lib/constants.ts +4 -0
  30. package/src/modules/query_index/lib/batch.ts +15 -2
  31. package/src/modules/query_index/lib/search-tokens.ts +5 -32
  32. package/src/modules/sync_excel/lib/adapters/customers.ts +6 -6
@@ -1,4 +1,5 @@
1
1
  import { type Kysely, sql } from 'kysely'
2
+ import { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'
2
3
  import { buildIndexDocument, type IndexCustomFieldValue } from './document'
3
4
  import { replaceSearchTokensForBatch, isSearchDebugEnabled } from './search-tokens'
4
5
 
@@ -245,7 +246,13 @@ export async function upsertIndexBatch(
245
246
  .execute()
246
247
  try {
247
248
  await replaceSearchTokensForBatch(db, tokenPayloads)
248
- } catch {}
249
+ } catch (searchTokenError) {
250
+ // Record instead of swallowing: a failed token write leaves fulltext search stale.
251
+ await recordIndexerError(
252
+ { db },
253
+ { source: 'fulltext', handler: 'query_index:reindex-batch', error: searchTokenError, entityType, tenantId: scope.tenantId ?? null, organizationId: scope.orgId ?? null },
254
+ ).catch(() => undefined)
255
+ }
249
256
  if (debugEnabled) {
250
257
  console.info('[reindex:batch:tokens]', {
251
258
  entityType,
@@ -298,5 +305,11 @@ export async function upsertIndexBatch(
298
305
  }
299
306
  try {
300
307
  await replaceSearchTokensForBatch(db, tokenPayloads)
301
- } catch {}
308
+ } catch (searchTokenError) {
309
+ // Record instead of swallowing: a failed token write leaves fulltext search stale.
310
+ await recordIndexerError(
311
+ { db },
312
+ { source: 'fulltext', handler: 'query_index:reindex-batch', error: searchTokenError, entityType, tenantId: scope.tenantId ?? null, organizationId: scope.orgId ?? null },
313
+ ).catch(() => undefined)
314
+ }
302
315
  }
@@ -212,8 +212,6 @@ export async function replaceSearchTokensForBatch(
212
212
 
213
213
  const scopeKey = (org: string | null, tenant: string | null) => `${org ?? '__null__'}|${tenant ?? '__null__'}`
214
214
  const scopeBuckets = new Map<string, { organizationId: string | null; tenantId: string | null; ids: Set<string> }>()
215
- const fieldPairsByScope = new Map<string, EntityFieldPair[]>()
216
- const seenPairsByScope = new Map<string, Set<string>>()
217
215
 
218
216
  for (const payload of payloads) {
219
217
  const org = payload.organizationId ?? null
@@ -224,41 +222,16 @@ export async function replaceSearchTokensForBatch(
224
222
  scopeBuckets.set(key, bucket)
225
223
  }
226
224
 
227
- for (const payload of payloads) {
228
- const org = payload.organizationId ?? null
229
- const tenant = payload.tenantId ?? null
230
- const key = scopeKey(org, tenant)
231
- const pairs = fieldPairsByScope.get(key) ?? []
232
- const seen = seenPairsByScope.get(key) ?? new Set<string>()
233
- const fieldPairs = buildFieldPairs(String(payload.recordId), payload.doc)
234
- for (const pair of fieldPairs) {
235
- const dedupeKey = `${pair[0]}|${pair[1]}`
236
- if (seen.has(dedupeKey)) continue
237
- seen.add(dedupeKey)
238
- pairs.push(pair)
239
- }
240
- fieldPairsByScope.set(key, pairs)
241
- seenPairsByScope.set(key, seen)
242
- }
243
-
244
225
  await db.transaction().execute(async (trx) => {
245
- for (const [key, bucket] of scopeBuckets.entries()) {
246
- const pairs = fieldPairsByScope.get(key) ?? []
247
- let deleteQuery = trx
226
+ for (const [, bucket] of scopeBuckets.entries()) {
227
+ // Delete by entity_id: a batch replaces all of a record's tokens, and a per-field OR over the
228
+ // whole batch overflows the query compiler's call stack on large batches.
229
+ const deleteQuery = trx
248
230
  .deleteFrom('search_tokens' as any)
249
231
  .where('entity_type' as any, '=', payloads[0].entityType)
250
232
  .where(sql<boolean>`organization_id is not distinct from ${bucket.organizationId}`)
251
233
  .where(sql<boolean>`tenant_id is not distinct from ${bucket.tenantId}`)
252
- if (pairs.length) {
253
- deleteQuery = deleteQuery.where((eb: any) => eb.or(
254
- pairs.map(([rid, field]) => eb.and([
255
- eb('entity_id' as any, '=', rid),
256
- eb('field' as any, '=', field),
257
- ])),
258
- ))
259
- } else {
260
- deleteQuery = deleteQuery.where('entity_id' as any, 'in', Array.from(bucket.ids))
261
- }
234
+ .where('entity_id' as any, 'in', Array.from(bucket.ids))
262
235
  await deleteQuery.execute()
263
236
  }
264
237
  const payloadWithTimestamps = rows.map((row) => ({ ...row, created_at: sql`now()` }))
@@ -1048,15 +1048,15 @@ export const syncExcelCustomersAdapter: DataSyncAdapter = {
1048
1048
  const startOffset = cursor?.uploadId === upload.id ? cursor.offset : 0
1049
1049
  const commandContext = buildCommandContext(container, input.scope)
1050
1050
  const customFieldDefinitions = await loadImportCustomFieldDefinitions(em, input.scope)
1051
+ const emailDedupeIndex = await buildEmailDedupeIndex({
1052
+ em,
1053
+ rows: document.rows.slice(startOffset),
1054
+ mapping: input.mapping,
1055
+ scope: input.scope,
1056
+ })
1051
1057
 
1052
1058
  for (let offset = startOffset, batchIndex = 0; offset < document.rows.length; offset += input.batchSize, batchIndex += 1) {
1053
1059
  const batchRows = document.rows.slice(offset, offset + input.batchSize)
1054
- const emailDedupeIndex = await buildEmailDedupeIndex({
1055
- em,
1056
- rows: batchRows,
1057
- mapping: input.mapping,
1058
- scope: input.scope,
1059
- })
1060
1060
  const items: ImportItem[] = []
1061
1061
 
1062
1062
  for (let index = 0; index < batchRows.length; index += 1) {