@open-mercato/core 0.10.1-develop.7776.1.3032ea0741 → 0.10.1-develop.7781.1.079f42c863

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/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/catalog/components/products/ProductsDataTable.js +6 -5
  3. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  4. package/dist/modules/customers/backend/customers/companies/page.js +5 -4
  5. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  6. package/dist/modules/customers/backend/customers/deals/page.js +6 -5
  7. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  8. package/dist/modules/customers/backend/customers/people/page.js +5 -4
  9. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  10. package/dist/modules/query_index/cli.js +9 -1
  11. package/dist/modules/query_index/cli.js.map +2 -2
  12. package/dist/modules/query_index/lib/coverage.js +13 -2
  13. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  14. package/dist/modules/query_index/lib/engine.js +28 -9
  15. package/dist/modules/query_index/lib/engine.js.map +2 -2
  16. package/dist/modules/query_index/lib/indexer.js +5 -1
  17. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  18. package/dist/modules/query_index/lib/reindexer.js +95 -32
  19. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  20. package/dist/modules/query_index/lib/search-scope.js +101 -0
  21. package/dist/modules/query_index/lib/search-scope.js.map +7 -0
  22. package/dist/modules/query_index/lib/stale.js +41 -1
  23. package/dist/modules/query_index/lib/stale.js.map +2 -2
  24. package/dist/modules/query_index/lib/subscriber-scope.js +30 -7
  25. package/dist/modules/query_index/lib/subscriber-scope.js.map +3 -3
  26. package/dist/modules/query_index/lib/tenant-global.js +41 -0
  27. package/dist/modules/query_index/lib/tenant-global.js.map +7 -0
  28. package/dist/modules/query_index/subscribers/reindex.js +9 -2
  29. package/dist/modules/query_index/subscribers/reindex.js.map +2 -2
  30. package/dist/modules/sales/components/documents/ItemsSection.js +4 -3
  31. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  32. package/package.json +7 -7
  33. package/src/modules/catalog/components/products/ProductsDataTable.tsx +6 -5
  34. package/src/modules/customers/backend/customers/companies/page.tsx +5 -4
  35. package/src/modules/customers/backend/customers/deals/page.tsx +6 -5
  36. package/src/modules/customers/backend/customers/people/page.tsx +5 -4
  37. package/src/modules/query_index/cli.ts +19 -1
  38. package/src/modules/query_index/lib/coverage.ts +29 -3
  39. package/src/modules/query_index/lib/engine.ts +34 -9
  40. package/src/modules/query_index/lib/indexer.ts +6 -1
  41. package/src/modules/query_index/lib/reindexer.ts +205 -36
  42. package/src/modules/query_index/lib/search-scope.ts +144 -0
  43. package/src/modules/query_index/lib/stale.ts +73 -0
  44. package/src/modules/query_index/lib/subscriber-scope.ts +38 -8
  45. package/src/modules/query_index/lib/tenant-global.ts +93 -0
  46. package/src/modules/query_index/subscribers/reindex.ts +24 -1
  47. package/src/modules/sales/components/documents/ItemsSection.tsx +6 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/query_index/cli.ts"],
4
- "sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName, resolveRegisteredEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport {\n upsertIndexBatch,\n assertIndexBatchWritesLanded,\n createEmptyUpsertIndexBatchResult,\n mergeUpsertIndexBatchResults,\n type AnyRow,\n} from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport { purgeIndexScope } from './lib/purge'\nimport { refreshCoverageSnapshot } from './lib/coverage'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\ntype PartitionProgressInfo = { processed: number; total: number }\n\nfunction isIndexerVerbose(): boolean {\n const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')\n return parsed === true\n}\n\nfunction createGroupedProgress(label: string, partitionTargets: number[]) {\n const totals = new Map<number, number>()\n const processed = new Map<number, number>()\n let bar: ProgressBarHandle | null = null\n\n const getTotals = () => {\n let total = 0\n let done = 0\n for (const value of totals.values()) total += value\n for (const value of processed.values()) done += value\n return { total, done }\n }\n\n const tryInitBar = () => {\n if (bar) return\n if (totals.size < partitionTargets.length) return\n const { total } = getTotals()\n if (total <= 0) return\n bar = createProgressBar(label, total) as ProgressBarHandle\n }\n\n return {\n onProgress(partition: number, info: PartitionProgressInfo) {\n processed.set(partition, info.processed)\n if (!totals.has(partition)) totals.set(partition, info.total)\n tryInitBar()\n if (!bar) return\n const { done } = getTotals()\n bar.update(done)\n },\n complete() {\n if (bar) bar.complete()\n },\n getTotals,\n }\n}\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n db: Kysely<any>\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n db,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n // Neither helper swallows failures: upsertIndexBatch treats a failed encrypt as a\n // failed row (writing the plaintext document instead would break encryption at rest)\n // and records a failed decrypt against fulltext.\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n }\n\n const applyFilters = <QB extends { where: (...args: any[]) => QB }>(q: QB): QB => {\n let chain = q\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) {\n chain = chain.where('organization_id' as any, '=', orgOverride)\n }\n if (tenantOverride !== undefined && supportsTenantFilter) {\n chain = chain.where('tenant_id' as any, '=', tenantOverride)\n }\n }\n if (!includeDeleted && supportsDeletedFilter) {\n chain = chain.where('deleted_at' as any, 'is', null as any)\n }\n return chain\n }\n\n if (recordId) {\n const row = await applyFilters(\n db.selectFrom(tableName as any).selectAll() as any,\n )\n .where('id' as any, '=', recordId)\n .executeTakeFirst() as AnyRow | undefined\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n const singleResult = await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(singleResult.written)\n bar.complete()\n assertIndexBatchWritesLanded(entityType, singleResult)\n return { processed: singleResult.written, matched: 1 }\n }\n\n const countRow = await applyFilters(\n db.selectFrom(tableName as any).select(sql<string>`count(*)`.as('count')) as any,\n ).executeTakeFirst() as { count: string | number } | undefined\n const totalRaw = countRow?.count\n const total = totalRaw != null ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let fetched = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n const writeTotals = createEmptyUpsertIndexBatchResult()\n\n while (fetched < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await applyFilters(\n db\n .selectFrom(tableName as any)\n .selectAll()\n .orderBy('id' as any)\n .limit(chunkLimit)\n .offset(cursorOffset) as any,\n ).execute() as AnyRow[]\n if (!chunk.length) break\n\n const chunkResult = await upsertIndexBatch(db, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n mergeUpsertIndexBatchResults(writeTotals, chunkResult)\n\n processed += chunkResult.written\n fetched += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n // After bar.complete() so the terminal is left in a sane state before we throw.\n assertIndexBatchWritesLanded(entityType, writeTotals)\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(db: Kysely<any>, tableName: string): Promise<Set<string>> {\n try {\n const rows = await db\n .selectFrom('information_schema.columns' as any)\n .select(['column_name' as any])\n .where(sql<boolean>`table_schema = current_schema()`)\n .where('table_name' as any, '=', tableName)\n .execute() as Array<{ column_name: string }>\n return new Set(rows.map((row) => String(row.column_name).toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\n/**\n * Above this many missing records the anti-join stops being the cheaper option and the\n * repair falls back to a full single-partition rebuild of the entity.\n */\nconst MAX_TARGETED_REPAIR_RECORDS = 5000\n\n/**\n * List the base records in scope that have no live index row, so a repair rebuilds only\n * what is actually missing instead of re-upserting the whole entity for a one-row gap.\n */\nasync function findUnindexedRecordIds(\n db: Kysely<any>,\n options: {\n entityType: string\n tableName: string\n tenantId?: string | null\n organizationId?: string | null\n limit: number\n },\n): Promise<string[]> {\n const columns = await getColumnSet(db, options.tableName)\n let query = db\n .selectFrom(`${options.tableName} as b` as any)\n .select('b.id' as any)\n .where(({ not, exists, selectFrom }: any) =>\n not(exists(\n selectFrom('entity_indexes as ei' as any)\n .select(sql`1`.as('one'))\n .whereRef('ei.entity_id' as any, '=', sql`b.id::text`)\n .where('ei.entity_type' as any, '=', options.entityType)\n .where('ei.deleted_at' as any, 'is', null as any),\n )),\n )\n .limit(options.limit)\n if (columns.has('deleted_at')) query = query.where('b.deleted_at' as any, 'is', null as any)\n if (options.tenantId != null && columns.has('tenant_id')) {\n query = query.where('b.tenant_id' as any, '=', options.tenantId)\n }\n if (options.organizationId != null && columns.has('organization_id')) {\n query = query.where('b.organization_id' as any, '=', options.organizationId)\n }\n const rows = await query.execute() as Array<{ id: unknown }>\n return rows.map((row) => String(row.id))\n}\n\n/**\n * Recount the scope from the database after a reindex and rebuild whatever is still\n * missing. Runs unconditionally so `mercato init` (and any scripted reindex) cannot finish\n * leaving a gap that a human has to notice and repair by hand from the Query Indexes\n * screen. When counts already agree this is two COUNT queries; when they do not, the\n * repair is scoped to the records the anti-join says are actually missing.\n */\nasync function verifyAndRepairIndexCoverage(\n em: EntityManager,\n options: {\n entityType: string\n tenantId?: string | null\n organizationId?: string | null\n batchSize?: number\n },\n): Promise<void> {\n const scope = {\n entityType: options.entityType,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n withDeleted: false,\n }\n\n let counts: { baseCount: number; indexedCount: number } | null = null\n try {\n counts = await refreshCoverageSnapshot(em, scope)\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: coverage verification skipped (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n if (!counts) return\n if (counts.indexedCount > counts.baseCount) {\n // Legitimate for entities whose base table cannot express the scope, since a per-tenant\n // reindex stamps its own scope onto every row. Surfaced rather than repaired: a rebuild\n // cannot remove the surplus, and the over-count would otherwise mask a real shortfall.\n console.warn(\n ` -> ${options.entityType}: ${counts.indexedCount} index rows for ${counts.baseCount} records \u2014 not repairable by reindexing`,\n )\n return\n }\n if (counts.indexedCount === counts.baseCount) return\n\n const db = (em as any).getKysely() as Kysely<any>\n let tableName: string | null = null\n try {\n tableName = resolveRegisteredEntityTableName(em as any, options.entityType)\n } catch {\n tableName = null\n }\n\n const missingIds = tableName\n ? await findUnindexedRecordIds(db, {\n entityType: options.entityType,\n tableName,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n limit: MAX_TARGETED_REPAIR_RECORDS + 1,\n }).catch(() => null)\n : null\n\n const targeted = missingIds && missingIds.length > 0 && missingIds.length <= MAX_TARGETED_REPAIR_RECORDS\n console.log(\n ` -> ${options.entityType}: ${counts.indexedCount}/${counts.baseCount} indexed after reindex \u2014 repairing`\n + `${targeted ? ` ${missingIds!.length} missing record(s)` : ' the whole entity'}...`,\n )\n\n try {\n if (targeted) {\n const columns = await getColumnSet(db, tableName!)\n for (const recordId of missingIds!) {\n await rebuildEntityIndexes({\n em,\n db,\n entityType: options.entityType,\n tableName: tableName!,\n orgOverride: options.organizationId ?? undefined,\n tenantOverride: options.tenantId ?? undefined,\n global: false,\n includeDeleted: false,\n offset: 0,\n recordId,\n batchSize: 1,\n supportsOrgFilter: columns.has('organization_id'),\n supportsTenantFilter: columns.has('tenant_id'),\n supportsDeletedFilter: columns.has('deleted_at'),\n })\n }\n } else {\n await reindexEntity(em, {\n entityType: options.entityType,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n force: false,\n batchSize: options.batchSize,\n emitVectorizeEvents: false,\n resetCoverage: false,\n })\n }\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: repair pass failed (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n\n const after = await refreshCoverageSnapshot(em, scope).catch(() => null)\n if (after && after.indexedCount < after.baseCount) {\n console.warn(\n ` -> ${options.entityType}: still ${after.indexedCount}/${after.baseCount} indexed after repair`,\n )\n } else {\n console.log(` -> ${options.entityType}: coverage repaired`)\n }\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(\n `Reindexing ${entity}${label}`,\n info.total,\n ) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })\n } else if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: result.processed, total: result.total })\n } else if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName, resolveRegisteredEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport {\n upsertIndexBatch,\n assertIndexBatchWritesLanded,\n createEmptyUpsertIndexBatchResult,\n mergeUpsertIndexBatchResults,\n type AnyRow,\n} from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport type { ReindexJobResult } from './lib/reindexer'\n\n/**\n * A refused sweep returns processed 0 / total 0, which the progress reporting below prints\n * as `0 / 0 (0.00%)` - indistinguishable from a run that found nothing. Say why instead.\n */\nfunction warnIfReindexRefused(entityType: string, result: ReindexJobResult): void {\n if (!result.refused) return\n const detail = result.refused === 'no-tenant-column'\n ? 'the source table has no tenant_id column and the entity type is not declared tenant-global'\n : result.refused === 'declared-global-but-org-scoped'\n ? 'the entity type is declared tenant-global but its table carries an organization_id column'\n : \"the source table's columns could not be read, so no scope could be proven (usually transient)\"\n console.warn(` -> ${entityType}: reindex REFUSED, nothing was indexed - ${detail}`)\n}\nimport { purgeIndexScope } from './lib/purge'\nimport { refreshCoverageSnapshot } from './lib/coverage'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\ntype PartitionProgressInfo = { processed: number; total: number }\n\nfunction isIndexerVerbose(): boolean {\n const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')\n return parsed === true\n}\n\nfunction createGroupedProgress(label: string, partitionTargets: number[]) {\n const totals = new Map<number, number>()\n const processed = new Map<number, number>()\n let bar: ProgressBarHandle | null = null\n\n const getTotals = () => {\n let total = 0\n let done = 0\n for (const value of totals.values()) total += value\n for (const value of processed.values()) done += value\n return { total, done }\n }\n\n const tryInitBar = () => {\n if (bar) return\n if (totals.size < partitionTargets.length) return\n const { total } = getTotals()\n if (total <= 0) return\n bar = createProgressBar(label, total) as ProgressBarHandle\n }\n\n return {\n onProgress(partition: number, info: PartitionProgressInfo) {\n processed.set(partition, info.processed)\n if (!totals.has(partition)) totals.set(partition, info.total)\n tryInitBar()\n if (!bar) return\n const { done } = getTotals()\n bar.update(done)\n },\n complete() {\n if (bar) bar.complete()\n },\n getTotals,\n }\n}\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n db: Kysely<any>\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n db,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n // Neither helper swallows failures: upsertIndexBatch treats a failed encrypt as a\n // failed row (writing the plaintext document instead would break encryption at rest)\n // and records a failed decrypt against fulltext.\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n }\n\n const applyFilters = <QB extends { where: (...args: any[]) => QB }>(q: QB): QB => {\n let chain = q\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) {\n chain = chain.where('organization_id' as any, '=', orgOverride)\n }\n if (tenantOverride !== undefined && supportsTenantFilter) {\n chain = chain.where('tenant_id' as any, '=', tenantOverride)\n }\n }\n if (!includeDeleted && supportsDeletedFilter) {\n chain = chain.where('deleted_at' as any, 'is', null as any)\n }\n return chain\n }\n\n if (recordId) {\n const row = await applyFilters(\n db.selectFrom(tableName as any).selectAll() as any,\n )\n .where('id' as any, '=', recordId)\n .executeTakeFirst() as AnyRow | undefined\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n const singleResult = await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(singleResult.written)\n bar.complete()\n assertIndexBatchWritesLanded(entityType, singleResult)\n return { processed: singleResult.written, matched: 1 }\n }\n\n const countRow = await applyFilters(\n db.selectFrom(tableName as any).select(sql<string>`count(*)`.as('count')) as any,\n ).executeTakeFirst() as { count: string | number } | undefined\n const totalRaw = countRow?.count\n const total = totalRaw != null ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let fetched = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n const writeTotals = createEmptyUpsertIndexBatchResult()\n\n while (fetched < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await applyFilters(\n db\n .selectFrom(tableName as any)\n .selectAll()\n .orderBy('id' as any)\n .limit(chunkLimit)\n .offset(cursorOffset) as any,\n ).execute() as AnyRow[]\n if (!chunk.length) break\n\n const chunkResult = await upsertIndexBatch(db, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n mergeUpsertIndexBatchResults(writeTotals, chunkResult)\n\n processed += chunkResult.written\n fetched += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n // After bar.complete() so the terminal is left in a sane state before we throw.\n assertIndexBatchWritesLanded(entityType, writeTotals)\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(db: Kysely<any>, tableName: string): Promise<Set<string>> {\n try {\n const rows = await db\n .selectFrom('information_schema.columns' as any)\n .select(['column_name' as any])\n .where(sql<boolean>`table_schema = current_schema()`)\n .where('table_name' as any, '=', tableName)\n .execute() as Array<{ column_name: string }>\n return new Set(rows.map((row) => String(row.column_name).toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\n/**\n * Above this many missing records the anti-join stops being the cheaper option and the\n * repair falls back to a full single-partition rebuild of the entity.\n */\nconst MAX_TARGETED_REPAIR_RECORDS = 5000\n\n/**\n * List the base records in scope that have no live index row, so a repair rebuilds only\n * what is actually missing instead of re-upserting the whole entity for a one-row gap.\n */\nasync function findUnindexedRecordIds(\n db: Kysely<any>,\n options: {\n entityType: string\n tableName: string\n tenantId?: string | null\n organizationId?: string | null\n limit: number\n },\n): Promise<string[]> {\n const columns = await getColumnSet(db, options.tableName)\n let query = db\n .selectFrom(`${options.tableName} as b` as any)\n .select('b.id' as any)\n .where(({ not, exists, selectFrom }: any) =>\n not(exists(\n selectFrom('entity_indexes as ei' as any)\n .select(sql`1`.as('one'))\n .whereRef('ei.entity_id' as any, '=', sql`b.id::text`)\n .where('ei.entity_type' as any, '=', options.entityType)\n .where('ei.deleted_at' as any, 'is', null as any),\n )),\n )\n .limit(options.limit)\n if (columns.has('deleted_at')) query = query.where('b.deleted_at' as any, 'is', null as any)\n if (options.tenantId != null && columns.has('tenant_id')) {\n query = query.where('b.tenant_id' as any, '=', options.tenantId)\n }\n if (options.organizationId != null && columns.has('organization_id')) {\n query = query.where('b.organization_id' as any, '=', options.organizationId)\n }\n const rows = await query.execute() as Array<{ id: unknown }>\n return rows.map((row) => String(row.id))\n}\n\n/**\n * Recount the scope from the database after a reindex and rebuild whatever is still\n * missing. Runs unconditionally so `mercato init` (and any scripted reindex) cannot finish\n * leaving a gap that a human has to notice and repair by hand from the Query Indexes\n * screen. When counts already agree this is two COUNT queries; when they do not, the\n * repair is scoped to the records the anti-join says are actually missing.\n */\nasync function verifyAndRepairIndexCoverage(\n em: EntityManager,\n options: {\n entityType: string\n tenantId?: string | null\n organizationId?: string | null\n batchSize?: number\n },\n): Promise<void> {\n const scope = {\n entityType: options.entityType,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n withDeleted: false,\n }\n\n let counts: { baseCount: number; indexedCount: number } | null = null\n try {\n counts = await refreshCoverageSnapshot(em, scope)\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: coverage verification skipped (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n if (!counts) return\n if (counts.indexedCount > counts.baseCount) {\n // Legitimate for entities whose base table cannot express the scope, since a per-tenant\n // reindex stamps its own scope onto every row. Surfaced rather than repaired: a rebuild\n // cannot remove the surplus, and the over-count would otherwise mask a real shortfall.\n console.warn(\n ` -> ${options.entityType}: ${counts.indexedCount} index rows for ${counts.baseCount} records \u2014 not repairable by reindexing`,\n )\n return\n }\n if (counts.indexedCount === counts.baseCount) return\n\n const db = (em as any).getKysely() as Kysely<any>\n let tableName: string | null = null\n try {\n tableName = resolveRegisteredEntityTableName(em as any, options.entityType)\n } catch {\n tableName = null\n }\n\n const missingIds = tableName\n ? await findUnindexedRecordIds(db, {\n entityType: options.entityType,\n tableName,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n limit: MAX_TARGETED_REPAIR_RECORDS + 1,\n }).catch(() => null)\n : null\n\n const targeted = missingIds && missingIds.length > 0 && missingIds.length <= MAX_TARGETED_REPAIR_RECORDS\n console.log(\n ` -> ${options.entityType}: ${counts.indexedCount}/${counts.baseCount} indexed after reindex \u2014 repairing`\n + `${targeted ? ` ${missingIds!.length} missing record(s)` : ' the whole entity'}...`,\n )\n\n try {\n if (targeted) {\n const columns = await getColumnSet(db, tableName!)\n for (const recordId of missingIds!) {\n await rebuildEntityIndexes({\n em,\n db,\n entityType: options.entityType,\n tableName: tableName!,\n orgOverride: options.organizationId ?? undefined,\n tenantOverride: options.tenantId ?? undefined,\n global: false,\n includeDeleted: false,\n offset: 0,\n recordId,\n batchSize: 1,\n supportsOrgFilter: columns.has('organization_id'),\n supportsTenantFilter: columns.has('tenant_id'),\n supportsDeletedFilter: columns.has('deleted_at'),\n })\n }\n } else {\n const repairResult = await reindexEntity(em, {\n entityType: options.entityType,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n force: false,\n batchSize: options.batchSize,\n emitVectorizeEvents: false,\n resetCoverage: false,\n })\n warnIfReindexRefused(options.entityType, repairResult)\n }\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: repair pass failed (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n\n const after = await refreshCoverageSnapshot(em, scope).catch(() => null)\n if (after && after.indexedCount < after.baseCount) {\n console.warn(\n ` -> ${options.entityType}: still ${after.indexedCount}/${after.baseCount} indexed after repair`,\n )\n } else {\n console.log(` -> ${options.entityType}: coverage repaired`)\n }\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(\n `Reindexing ${entity}${label}`,\n info.total,\n ) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(entity, partitionStats)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })\n } else if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(id, result)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: result.processed, total: result.total })\n } else if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
5
+ "mappings": "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",
6
6
  "names": ["bar"]
7
7
  }
@@ -1,6 +1,10 @@
1
+ import { resolveQueryIndexSourceTableMetadata } from "./subscriber-scope.js";
1
2
  import { sql } from "kysely";
2
- import { resolveEntityTableName } from "@open-mercato/shared/lib/query/engine";
3
+ import { resolveEntityTableName as resolveFallbackEntityTableName } from "@open-mercato/shared/lib/query/engine";
3
4
  import { createLogger } from "@open-mercato/shared/lib/logger";
5
+ function resolveEntityTableName(em, entity) {
6
+ return resolveQueryIndexSourceTableMetadata(em, entity)?.table ?? resolveFallbackEntityTableName(em, entity);
7
+ }
4
8
  const logger = createLogger("query_index").child({ component: "coverage" });
5
9
  const COLUMN_CACHE = /* @__PURE__ */ new Map();
6
10
  const COLUMN_CACHE_PENDING = /* @__PURE__ */ new Map();
@@ -227,6 +231,10 @@ async function deleteCoverageForEntity(db, entityType) {
227
231
  if (!entityType) return;
228
232
  await db.deleteFrom("entity_index_coverage").where("entity_type", "=", entityType).execute();
229
233
  }
234
+ async function deleteScopedCoverageForEntity(db, entityType) {
235
+ if (!entityType) return;
236
+ await db.deleteFrom("entity_index_coverage").where("entity_type", "=", entityType).where(sql`(tenant_id is not null or (organization_id is not null and organization_id <> ${GLOBAL_ORGANIZATION_PLACEHOLDER}))`).execute();
237
+ }
230
238
  async function deleteCoverageScope(db, scope) {
231
239
  const { entityType, tenantId, organizationId, withDeleted } = scope;
232
240
  if (!entityType) return;
@@ -240,7 +248,7 @@ async function tableHasColumn(db, table, column) {
240
248
  const pending = COLUMN_CACHE_PENDING.get(key);
241
249
  if (pending) return pending;
242
250
  const promise = (async () => {
243
- const exists = await db.selectFrom("information_schema.columns").select(sql`1`.as("present")).where(sql`table_schema = current_schema()`).where("table_name", "=", table).where("column_name", "=", column).executeTakeFirst();
251
+ const exists = await db.selectFrom("information_schema.columns").select(sql`1`.as("present")).where(table.includes(".") ? sql`table_schema = ${table.split(".")[0]}` : sql`table_schema = current_schema()`).where("table_name", "=", table.split(".").pop()).where("column_name", "=", column).executeTakeFirst();
244
252
  const present = !!exists;
245
253
  COLUMN_CACHE.set(key, present);
246
254
  return present;
@@ -253,6 +261,8 @@ async function tableHasColumn(db, table, column) {
253
261
  }
254
262
  }
255
263
  async function primeColumnCache(db, checks) {
264
+ for (const check of checks.filter((entry) => typeof entry?.table === "string" && entry.table.includes("."))) await tableHasColumn(db, check.table, check.column);
265
+ checks = checks.filter((entry) => !(typeof entry?.table === "string" && entry.table.includes(".")));
256
266
  const missing = [];
257
267
  const seen = /* @__PURE__ */ new Set();
258
268
  for (const check of checks) {
@@ -427,6 +437,7 @@ export {
427
437
  applyCoverageAdjustments,
428
438
  createCoverageAdjustments,
429
439
  deleteCoverageForEntity,
440
+ deleteScopedCoverageForEntity,
430
441
  primeColumnCache,
431
442
  readCoverageSnapshot,
432
443
  readCoverageSnapshots,