@open-mercato/core 0.4.6-develop-e321a4e2a1 → 0.4.6-main-24e64eef39

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 (180) hide show
  1. package/AGENTS.md +0 -22
  2. package/dist/modules/api_docs/frontend/docs/api/page.js +1 -1
  3. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  4. package/dist/modules/attachments/api/library/[id]/route.js +1 -0
  5. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  6. package/dist/modules/attachments/components/AttachmentLibrary.js +1 -1
  7. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  8. package/dist/modules/attachments/lib/partitionEnv.js +1 -1
  9. package/dist/modules/attachments/lib/partitionEnv.js.map +2 -2
  10. package/dist/modules/auth/backend/users/page.js +1 -1
  11. package/dist/modules/auth/backend/users/page.js.map +2 -2
  12. package/dist/modules/auth/cli.js +1 -1
  13. package/dist/modules/auth/cli.js.map +2 -2
  14. package/dist/modules/auth/commands/users.js +1 -1
  15. package/dist/modules/auth/commands/users.js.map +2 -2
  16. package/dist/modules/business_rules/components/utils/formHelpers.js +1 -1
  17. package/dist/modules/business_rules/components/utils/formHelpers.js.map +2 -2
  18. package/dist/modules/catalog/backend/catalog/products/create/page.js +1 -1
  19. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  20. package/dist/modules/catalog/commands/products.js +1 -1
  21. package/dist/modules/catalog/commands/products.js.map +2 -2
  22. package/dist/modules/catalog/commands/shared.js +1 -1
  23. package/dist/modules/catalog/commands/shared.js.map +2 -2
  24. package/dist/modules/catalog/components/PriceKindSettings.js +1 -1
  25. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  26. package/dist/modules/catalog/components/products/productForm.js +1 -1
  27. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  28. package/dist/modules/configs/lib/upgrade-actions.js.map +1 -1
  29. package/dist/modules/currencies/services/providers/raiffeisen.js +1 -1
  30. package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
  31. package/dist/modules/customers/backend/customers/companies/page.js +3 -3
  32. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  33. package/dist/modules/customers/backend/customers/deals/page.js +3 -3
  34. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  35. package/dist/modules/customers/backend/customers/people/page.js +3 -3
  36. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  37. package/dist/modules/customers/cli.js +2 -2
  38. package/dist/modules/customers/cli.js.map +2 -2
  39. package/dist/modules/customers/lib/detailHelpers.js +1 -1
  40. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  41. package/dist/modules/entities/cli.js +1 -1
  42. package/dist/modules/entities/cli.js.map +2 -2
  43. package/dist/modules/entities/lib/field-definitions.js +1 -1
  44. package/dist/modules/entities/lib/field-definitions.js.map +2 -2
  45. package/dist/modules/entities/lib/install-from-ce.js +1 -1
  46. package/dist/modules/entities/lib/install-from-ce.js.map +2 -2
  47. package/dist/modules/inbox_ops/lib/emailParser.js +1 -1
  48. package/dist/modules/inbox_ops/lib/emailParser.js.map +2 -2
  49. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js +0 -8
  50. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js.map +2 -2
  51. package/dist/modules/perspectives/services/perspectiveService.js +1 -1
  52. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  53. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -3
  54. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  55. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -7
  56. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  57. package/dist/modules/query_index/lib/engine.js +1 -1
  58. package/dist/modules/query_index/lib/engine.js.map +2 -2
  59. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  60. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  61. package/dist/modules/resources/backend/resources/resources/page.js +3 -3
  62. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  63. package/dist/modules/resources/commands/resources.js +1 -1
  64. package/dist/modules/resources/commands/resources.js.map +2 -2
  65. package/dist/modules/resources/lib/seeds.js +1 -1
  66. package/dist/modules/resources/lib/seeds.js.map +2 -2
  67. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js +1 -1
  68. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js.map +2 -2
  69. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js +1 -1
  70. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js.map +2 -2
  71. package/dist/modules/sales/backend/sales/channels/page.js +3 -3
  72. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  73. package/dist/modules/sales/commands/documents.js +2 -2
  74. package/dist/modules/sales/commands/documents.js.map +2 -2
  75. package/dist/modules/sales/components/channels/offerTableUtils.js +2 -3
  76. package/dist/modules/sales/components/channels/offerTableUtils.js.map +2 -2
  77. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -4
  78. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  79. package/dist/modules/sales/components/documents/ShipmentDialog.js +1 -1
  80. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  81. package/dist/modules/sales/lib/shipments/snapshots.js.map +1 -1
  82. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -8
  83. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
  84. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -8
  85. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +2 -2
  86. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -3
  87. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  88. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -3
  89. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  90. package/dist/modules/staff/backend/staff/team-members/page.js +3 -3
  91. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  92. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  93. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  94. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -3
  95. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  96. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  97. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  98. package/dist/modules/workflows/backend/instances/page.js +2 -2
  99. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  100. package/dist/modules/workflows/backend/tasks/page.js +1 -1
  101. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  102. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
  103. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  104. package/dist/modules/workflows/lib/graph-utils.js +1 -1
  105. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  106. package/package.json +2 -2
  107. package/src/modules/api_docs/frontend/docs/api/page.tsx +1 -1
  108. package/src/modules/attachments/api/library/[id]/route.ts +1 -0
  109. package/src/modules/attachments/components/AttachmentLibrary.tsx +1 -1
  110. package/src/modules/attachments/lib/partitionEnv.ts +1 -1
  111. package/src/modules/auth/backend/users/page.tsx +1 -1
  112. package/src/modules/auth/cli.ts +1 -1
  113. package/src/modules/auth/commands/users.ts +1 -1
  114. package/src/modules/business_rules/components/utils/formHelpers.ts +1 -1
  115. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1 -1
  116. package/src/modules/catalog/commands/products.ts +1 -1
  117. package/src/modules/catalog/commands/shared.ts +1 -1
  118. package/src/modules/catalog/components/PriceKindSettings.tsx +1 -1
  119. package/src/modules/catalog/components/products/productForm.ts +1 -1
  120. package/src/modules/configs/lib/upgrade-actions.ts +1 -1
  121. package/src/modules/currencies/services/providers/raiffeisen.ts +1 -1
  122. package/src/modules/customers/backend/customers/companies/page.tsx +3 -3
  123. package/src/modules/customers/backend/customers/deals/page.tsx +3 -3
  124. package/src/modules/customers/backend/customers/people/page.tsx +3 -3
  125. package/src/modules/customers/cli.ts +2 -2
  126. package/src/modules/customers/lib/detailHelpers.ts +1 -1
  127. package/src/modules/entities/cli.ts +1 -1
  128. package/src/modules/entities/lib/field-definitions.ts +1 -1
  129. package/src/modules/entities/lib/install-from-ce.ts +1 -1
  130. package/src/modules/inbox_ops/lib/emailParser.ts +1 -1
  131. package/src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx +0 -8
  132. package/src/modules/perspectives/services/perspectiveService.ts +1 -1
  133. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -3
  134. package/src/modules/query_index/components/QueryIndexesTable.tsx +7 -7
  135. package/src/modules/query_index/lib/engine.ts +1 -1
  136. package/src/modules/resources/backend/resources/resource-types/page.tsx +3 -2
  137. package/src/modules/resources/backend/resources/resources/page.tsx +3 -3
  138. package/src/modules/resources/commands/resources.ts +1 -1
  139. package/src/modules/resources/lib/seeds.ts +1 -1
  140. package/src/modules/sales/api/dashboard/widgets/new-orders/route.ts +1 -1
  141. package/src/modules/sales/api/dashboard/widgets/new-quotes/route.ts +1 -1
  142. package/src/modules/sales/backend/sales/channels/page.tsx +3 -3
  143. package/src/modules/sales/commands/documents.ts +2 -2
  144. package/src/modules/sales/components/channels/offerTableUtils.tsx +2 -3
  145. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +4 -4
  146. package/src/modules/sales/components/documents/ShipmentDialog.tsx +1 -1
  147. package/src/modules/sales/lib/shipments/snapshots.ts +1 -1
  148. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -8
  149. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -8
  150. package/src/modules/staff/backend/staff/leave-requests/page.tsx +3 -3
  151. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +3 -3
  152. package/src/modules/staff/backend/staff/team-members/page.tsx +3 -3
  153. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  154. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -3
  155. package/src/modules/staff/backend/staff/teams/page.tsx +3 -2
  156. package/src/modules/workflows/backend/instances/page.tsx +2 -2
  157. package/src/modules/workflows/backend/tasks/page.tsx +1 -1
  158. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
  159. package/src/modules/workflows/lib/graph-utils.ts +1 -1
  160. package/dist/modules/integrations/acl.js +0 -8
  161. package/dist/modules/integrations/acl.js.map +0 -7
  162. package/dist/modules/integrations/data/enrichers.js +0 -72
  163. package/dist/modules/integrations/data/enrichers.js.map +0 -7
  164. package/dist/modules/integrations/data/entities.js +0 -63
  165. package/dist/modules/integrations/data/entities.js.map +0 -7
  166. package/dist/modules/integrations/index.js +0 -9
  167. package/dist/modules/integrations/index.js.map +0 -7
  168. package/dist/modules/integrations/setup.js +0 -13
  169. package/dist/modules/integrations/setup.js.map +0 -7
  170. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +0 -69
  171. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +0 -7
  172. package/dist/modules/integrations/widgets/injection-table.js +0 -13
  173. package/dist/modules/integrations/widgets/injection-table.js.map +0 -7
  174. package/src/modules/integrations/acl.ts +0 -4
  175. package/src/modules/integrations/data/enrichers.ts +0 -98
  176. package/src/modules/integrations/data/entities.ts +0 -46
  177. package/src/modules/integrations/index.ts +0 -5
  178. package/src/modules/integrations/setup.ts +0 -11
  179. package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +0 -94
  180. package/src/modules/integrations/widgets/injection-table.ts +0 -17
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/query_index/lib/engine.ts"],
4
- "sourcesContent": ["import type { QueryEngine, QueryOptions, QueryResult, FilterOp, Filter, QueryCustomFieldSource, PartialIndexWarning } from '@open-mercato/shared/lib/query/types'\nimport { SortDir } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { BasicQueryEngine, resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport type { Knex } from 'knex'\nimport type { EventBus } from '@open-mercato/events'\nimport { readCoverageSnapshot, refreshCoverageSnapshot } from './coverage'\nimport { createProfiler, shouldEnableProfiler, type Profiler } from '@open-mercato/shared/lib/profiler'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\nimport { decryptIndexDocCustomFields } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken, parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport {\n applyJoinFilters,\n normalizeFilters,\n partitionFilters,\n resolveJoins,\n type BaseFilter,\n type ResolvedJoin,\n} from '@open-mercato/shared/lib/query/join-utils'\nimport { resolveSearchConfig, type SearchConfig } from '@open-mercato/shared/lib/search/config'\nimport { tokenizeText } from '@open-mercato/shared/lib/search/tokenize'\n\nfunction resolveBooleanEnv(names: readonly string[], defaultValue: boolean): boolean {\n for (const name of names) {\n const raw = process.env[name]\n if (raw !== undefined) return parseBooleanWithDefault(raw, defaultValue)\n }\n return defaultValue\n}\n\nfunction resolveDebugVerbosity(): boolean {\n // Check explicit OM_QUERY_INDEX_DEBUG flag first\n const queryIndexDebug = process.env.OM_QUERY_INDEX_DEBUG\n if (queryIndexDebug !== undefined) {\n return parseBooleanToken(queryIndexDebug) ?? false\n }\n // Fall back to log level or NODE_ENV\n const level = (process.env.LOG_VERBOSITY ?? process.env.LOG_LEVEL ?? '').toLowerCase()\n if (['debug', 'trace', 'silly'].includes(level)) return true\n // Default to false (don't spam logs in development)\n return false\n}\n\ntype ResultRow = Record<string, unknown>\ntype ResultBuilder<TResult = ResultRow[]> = Knex.QueryBuilder<ResultRow, TResult>\ntype NormalizedFilter = { field: string; op: FilterOp; value?: unknown }\ntype IndexDocSource = { alias: string; entityId: EntityId; recordIdColumn: string }\ntype PreparedCustomFieldSource = {\n alias: string\n indexAlias: string\n entityId: EntityId\n recordIdColumn: string\n organizationField?: string\n tenantField?: string\n table: string\n}\ntype SearchRuntime = {\n enabled: boolean\n config: SearchConfig\n organizationScope?: { ids: string[]; includeNull: boolean } | null\n tenantId?: string | null\n searchSources?: SearchTokenSource[]\n}\n\ntype EncryptionResolver = () => {\n decryptEntityPayload?: (entityId: EntityId, payload: Record<string, unknown>, tenantId?: string | null, organizationId?: string | null) => Promise<Record<string, unknown>>\n isEnabled?: () => boolean\n} | null\n\ntype SearchTokenSource = { entity: string; recordIdColumn: string }\n\nfunction createQueryProfiler(entity: string): Profiler {\n const enabled = shouldEnableProfiler(entity)\n return createProfiler({\n scope: 'query_engine',\n target: entity,\n label: `query_engine:${entity}`,\n loggerLabel: '[qe:profile]',\n enabled,\n })\n}\n\nexport class HybridQueryEngine implements QueryEngine {\n private coverageStatsTtlMs: number\n private customFieldKeysCache = new Map<string, { expiresAt: number; value: string[] }>()\n private customFieldKeysTtlMs: number\n private columnCache = new Map<string, boolean>()\n private debugVerbosity: boolean | null = null\n private sqlDebugEnabled: boolean | null = null\n private forcePartialIndexEnabled: boolean | null = null\n private autoReindexEnabled: boolean | null = null\n private coverageOptimizationEnabled: boolean | null = null\n private pendingCoverageRefreshKeys = new Set<string>()\n private searchAliasSeq = 0\n\n constructor(\n private em: EntityManager,\n private fallback: BasicQueryEngine,\n private eventBusResolver?: () => Pick<EventBus, 'emitEvent'> | null | undefined,\n private vectorServiceResolver?: () => VectorIndexService | null | undefined,\n private encryptionResolver?: EncryptionResolver,\n ) {\n const coverageTtl = Number.parseInt(process.env.QUERY_INDEX_COVERAGE_CACHE_MS ?? '', 10)\n this.coverageStatsTtlMs = Number.isFinite(coverageTtl) && coverageTtl >= 0 ? coverageTtl : 5 * 60 * 1000\n const cfTtl = Number.parseInt(process.env.QUERY_INDEX_CF_KEYS_CACHE_MS ?? '', 10)\n this.customFieldKeysTtlMs = Number.isFinite(cfTtl) && cfTtl >= 0 ? cfTtl : 5 * 60 * 1000\n }\n\n private getEncryptionService() {\n try {\n return this.encryptionResolver?.() ?? null\n } catch {\n return null\n }\n }\n\n async query<T = unknown>(entity: EntityId, opts: QueryOptions = {}): Promise<QueryResult<T>> {\n const providedProfiler = opts.profiler\n const profiler = providedProfiler && providedProfiler.enabled\n ? providedProfiler\n : createQueryProfiler(String(entity))\n profiler.mark('query:init')\n let profileClosed = false\n const finishProfile = (meta?: Record<string, unknown>) => {\n if (!profiler.enabled || profileClosed) return\n profileClosed = true\n profiler.end(meta)\n }\n\n try {\n const debugEnabled = this.isDebugVerbosity()\n if (debugEnabled) this.debug('query:start', { entity })\n this.searchAliasSeq = 0\n\n const isCustom = await this.isCustomEntity(entity)\n if (isCustom) {\n if (debugEnabled) this.debug('query:custom-entity', { entity })\n const section = profiler.section('custom_entity')\n try {\n const result = await this.queryCustomEntity<T>(entity, opts)\n section.end({ mode: 'custom_entity' })\n finishProfile({\n result: 'custom_entity',\n total: Array.isArray(result.items) ? result.items.length : undefined,\n })\n return result\n } catch (err) {\n section.end({ error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }\n\n const knex = this.getKnex()\n profiler.mark('query:knex_ready')\n const baseTable = resolveEntityTableName(this.em, entity)\n profiler.mark('query:base_table_resolved')\n const searchConfig = resolveSearchConfig()\n const orgScope = this.resolveOrganizationScope(opts)\n const searchEnabled = searchConfig.enabled && await this.tableExists('search_tokens')\n\n const baseExists = await profiler.measure('base_table_exists', () => this.tableExists(baseTable))\n if (!baseExists) {\n if (debugEnabled) this.debug('query:fallback:missing-base', { entity, baseTable })\n const fallbackResult = await this.fallback.query(entity, opts)\n finishProfile({ result: 'fallback', reason: 'missing_base' })\n return fallbackResult\n }\n\n const normalizedFilters = normalizeFilters(opts.filters)\n const cfFilters = normalizedFilters.filter((filter) => filter.field.startsWith('cf:') || filter.field.startsWith('l10n:'))\n const coverageScope = this.resolveCoverageSnapshotScope(opts)\n const wantsCf = (\n (opts.fields || []).some((field) => typeof field === 'string' && (field.startsWith('cf:') || field.startsWith('l10n:'))) ||\n cfFilters.length > 0 ||\n opts.includeCustomFields === true ||\n (Array.isArray(opts.includeCustomFields) && opts.includeCustomFields.length > 0)\n )\n\n if (debugEnabled) {\n this.debug('query:config', {\n entity,\n wantsCustomFields: wantsCf,\n customFieldSources: Array.isArray(opts.customFieldSources) ? opts.customFieldSources.map((src) => src?.entityId) : undefined,\n fields: opts.fields,\n })\n }\n\n let partialIndexWarning: PartialIndexWarning | null = null\n let entityHasActiveCustomFields = true\n\n if (wantsCf) {\n entityHasActiveCustomFields = await this.entityHasActiveCustomFields(entity, opts.tenantId ?? null)\n const hasIndexRows = await profiler.measure(\n 'index_any_rows',\n () => this.indexAnyRows(entity),\n (value) => ({ hasIndexRows: value })\n )\n if (!hasIndexRows) {\n if (debugEnabled) this.debug('query:fallback:no-index', { entity })\n const fallbackResult = await this.fallback.query(entity, opts)\n finishProfile({ result: 'fallback', reason: 'no_index_rows' })\n return fallbackResult\n }\n if (entityHasActiveCustomFields) {\n const gap = await profiler.measure(\n 'resolve_coverage_gap',\n () => this.resolveCoverageGap(entity, opts, coverageScope),\n (value) => (value\n ? {\n scope: value.scope,\n baseCount: value.stats?.baseCount ?? null,\n indexedCount: value.stats?.indexedCount ?? null,\n }\n : { scope: null })\n )\n if (gap) {\n if (!opts.skipAutoReindex) {\n this.scheduleAutoReindex(entity, opts, gap.stats, coverageScope?.organizationId ?? null)\n }\n const force = this.isForcePartialIndexEnabled()\n if (!force) {\n if (gap.stats) {\n console.warn('[HybridQueryEngine] Partial index coverage detected; falling back to basic engine:', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n if (debugEnabled) this.debug('query:fallback:partial-coverage', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n } else {\n console.warn('[HybridQueryEngine] Partial index coverage detected; falling back to basic engine:', { entity })\n if (debugEnabled) this.debug('query:fallback:partial-coverage', { entity })\n }\n const fallbackResult = await this.fallback.query(entity, opts)\n const resultWithWarning: QueryResult<T> = {\n ...fallbackResult,\n meta: {\n ...(fallbackResult.meta ?? {}),\n partialIndexWarning: {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n },\n },\n }\n finishProfile({\n result: 'fallback',\n reason: 'partial_index',\n scope: gap.scope,\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n })\n return resultWithWarning\n }\n if (gap.stats) {\n console.warn('[HybridQueryEngine] Partial index coverage detected; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n if (debugEnabled) this.debug('query:partial-coverage:forced', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n } else {\n console.warn('[HybridQueryEngine] Partial index coverage detected; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity })\n if (debugEnabled) this.debug('query:partial-coverage:forced', { entity })\n }\n partialIndexWarning = {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n }\n }\n } else if (debugEnabled) {\n this.debug('query:coverage:skip-no-custom-fields', { entity })\n }\n }\n\n const qualify = (col: string) => `b.${col}`\n let builder: ResultBuilder = knex({ b: baseTable })\n const hasCustomFieldFilters = cfFilters.length > 0\n const canOptimizeCount = !hasCustomFieldFilters\n let optimizedCountBuilder: ResultBuilder | null = canOptimizeCount ? knex({ b: baseTable }) : null\n\n const resolvedJoinsConfig = resolveJoins(baseTable, opts.joins, (entityId) => resolveEntityTableName(this.em, entityId as any))\n const joinMap = new Map<string, ResolvedJoin>()\n const aliasTables = new Map<string, string>()\n aliasTables.set('b', baseTable)\n aliasTables.set('base', baseTable)\n aliasTables.set(baseTable, baseTable)\n for (const join of resolvedJoinsConfig) {\n joinMap.set(join.alias, join)\n aliasTables.set(join.alias, join.table)\n }\n const { baseFilters, joinFilters } = partitionFilters(baseTable, normalizedFilters, joinMap)\n\n if (!opts.tenantId) throw new Error('QueryEngine: tenantId is required')\n\n const hasOrganizationColumn = await this.columnExists(baseTable, 'organization_id')\n const hasTenantColumn = await this.columnExists(baseTable, 'tenant_id')\n const hasDeletedColumn = await this.columnExists(baseTable, 'deleted_at')\n const searchRuntimeBase = {\n enabled: false,\n config: searchConfig,\n organizationScope: orgScope,\n tenantId: opts.tenantId ?? null,\n }\n\n if (orgScope && hasOrganizationColumn) {\n builder = this.applyOrganizationScope(builder, qualify('organization_id'), orgScope)\n if (optimizedCountBuilder) optimizedCountBuilder = this.applyOrganizationScope(optimizedCountBuilder, qualify('organization_id'), orgScope)\n }\n if (hasTenantColumn) {\n builder = builder.where(qualify('tenant_id'), opts.tenantId)\n if (optimizedCountBuilder) optimizedCountBuilder = optimizedCountBuilder.where(qualify('tenant_id'), opts.tenantId)\n }\n if (!opts.withDeleted && hasDeletedColumn) {\n builder = builder.whereNull(qualify('deleted_at'))\n if (optimizedCountBuilder) optimizedCountBuilder = optimizedCountBuilder.whereNull(qualify('deleted_at'))\n }\n\n const baseJoinParts: string[] = []\n baseJoinParts.push(`ei.entity_type = ${knex.raw('?', [entity]).toString()}`)\n baseJoinParts.push(`ei.entity_id = (${qualify('id')}::text)`)\n if (hasOrganizationColumn) {\n baseJoinParts.push(`ei.organization_id = ${qualify('organization_id')}`)\n baseJoinParts.push('ei.organization_id is not null')\n }\n if (hasTenantColumn) {\n baseJoinParts.push(`ei.tenant_id = ${qualify('tenant_id')}`)\n baseJoinParts.push('ei.tenant_id is not null')\n }\n if (!opts.withDeleted) baseJoinParts.push(`ei.deleted_at is null`)\n builder = builder.leftJoin({ ei: 'entity_indexes' }, knex.raw(baseJoinParts.join(' AND ')))\n\n const columns = await this.getBaseColumnsForEntity(entity)\n const indexSources: IndexDocSource[] = [{ alias: 'ei', entityId: entity, recordIdColumn: 'b.id' }]\n\n const shouldAttachCustomSources = Array.isArray(opts.customFieldSources) && opts.customFieldSources.length > 0 && (wantsCf || searchEnabled)\n if (shouldAttachCustomSources) {\n const prepared = this.prepareCustomFieldSources(knex, builder, opts.customFieldSources ?? [], qualify)\n builder = prepared.builder\n for (const source of prepared.sources) {\n const fragments: string[] = []\n fragments.push(`${source.indexAlias}.entity_type = ${knex.raw('?', [source.entityId]).toString()}`)\n fragments.push(`${source.indexAlias}.entity_id = (${knex.raw('??::text', [`${source.alias}.${source.recordIdColumn}`]).toString()})`)\n const orgExpr = source.organizationField\n ? knex.raw('??', [`${source.alias}.${source.organizationField}`]).toString()\n : (columns.has('organization_id') ? qualify('organization_id') : null)\n if (orgExpr) {\n fragments.push(`${source.indexAlias}.organization_id = ${orgExpr}`)\n fragments.push(`${source.indexAlias}.organization_id is not null`)\n }\n const tenantExpr = source.tenantField\n ? knex.raw('??', [`${source.alias}.${source.tenantField}`]).toString()\n : (columns.has('tenant_id') ? qualify('tenant_id') : null)\n if (tenantExpr) {\n fragments.push(`${source.indexAlias}.tenant_id = ${tenantExpr}`)\n fragments.push(`${source.indexAlias}.tenant_id is not null`)\n }\n if (!opts.withDeleted) fragments.push(`${source.indexAlias}.deleted_at is null`)\n builder = builder.leftJoin({ [source.indexAlias]: 'entity_indexes' }, knex.raw(fragments.join(' AND ')))\n indexSources.push({ alias: source.indexAlias, entityId: source.entityId, recordIdColumn: `${source.alias}.${source.recordIdColumn}` })\n }\n }\n\n if (debugEnabled) {\n this.debug('query:index-sources', {\n entity,\n sources: indexSources.map((src) => ({ alias: src.alias, entity: src.entityId })),\n })\n }\n\n const searchSources: SearchTokenSource[] = indexSources\n .map((src) => ({\n entity: String(src.entityId),\n recordIdColumn: src.recordIdColumn,\n }))\n .filter((src) => src.recordIdColumn && src.entity)\n const hasSearchTokens = searchEnabled && searchSources.length\n ? await this.searchSourcesHaveTokens(searchSources, opts.tenantId ?? null, orgScope)\n : false\n const searchRuntime: SearchRuntime = { ...searchRuntimeBase, searchSources, enabled: searchEnabled && hasSearchTokens }\n const searchFilters = normalizeFilters(opts.filters).filter((filter) => filter.op === 'like' || filter.op === 'ilike')\n if (searchFilters.length) {\n this.logSearchDebug('search:init', {\n entity,\n baseTable,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\n fields: searchFilters.map((filter) => String(filter.field)),\n searchEnabled,\n hasSearchTokens,\n searchSources,\n searchConfig: {\n enabled: searchConfig.enabled,\n minTokenLength: searchConfig.minTokenLength,\n enablePartials: searchConfig.enablePartials,\n hashAlgorithm: searchConfig.hashAlgorithm,\n blocklistedFields: searchConfig.blocklistedFields,\n },\n })\n if (!searchEnabled) {\n this.logSearchDebug('search:disabled', { entity, baseTable })\n } else if (!hasSearchTokens) {\n this.logSearchDebug('search:no-search-tokens', {\n entity,\n baseTable,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\n searchSources,\n })\n }\n }\n const hasNonBaseSearchSource = searchSources.some(\n (src) => src.entity !== String(entity) || src.recordIdColumn !== 'b.id'\n )\n if (hasNonBaseSearchSource) {\n optimizedCountBuilder = null\n }\n\n if (!partialIndexWarning && Array.isArray(opts.customFieldSources) && opts.customFieldSources.length > 0 && this.isForcePartialIndexEnabled()) {\n const seen = new Set<string>([entity])\n for (const source of opts.customFieldSources) {\n const targetEntity = source?.entityId ? String(source.entityId) : null\n if (!targetEntity || seen.has(targetEntity)) continue\n seen.add(targetEntity)\n const sourceHasCustomFields = await this.entityHasActiveCustomFields(targetEntity, opts.tenantId ?? null)\n if (!sourceHasCustomFields) {\n if (debugEnabled) this.debug('query:coverage:skip-no-custom-fields', { entity: targetEntity })\n continue\n }\n const sourceTable = source.table ?? resolveEntityTableName(this.em, targetEntity)\n try {\n const gap = await profiler.measure(\n 'resolve_coverage_gap',\n () => this.resolveCoverageGap(targetEntity, opts, coverageScope, sourceTable),\n (value) => (value\n ? {\n entity: targetEntity,\n scope: value.scope,\n baseCount: value.stats?.baseCount ?? null,\n indexedCount: value.stats?.indexedCount ?? null,\n }\n : { entity: targetEntity, scope: null })\n )\n if (!gap) continue\n if (!opts.skipAutoReindex) {\n this.scheduleAutoReindex(targetEntity, opts, gap.stats, coverageScope?.organizationId ?? null)\n }\n partialIndexWarning = {\n entity: targetEntity,\n entityLabel: this.resolveEntityLabel(targetEntity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n }\n if (debugEnabled) {\n if (gap.stats) this.debug('query:partial-coverage:forced', { entity: targetEntity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n else this.debug('query:partial-coverage:forced', { entity: targetEntity })\n }\n break\n } catch (err) {\n if (debugEnabled) this.debug('query:partial-coverage:check-failed', { entity: targetEntity, error: err instanceof Error ? err.message : err })\n }\n }\n }\n\n if (\n !partialIndexWarning &&\n wantsCf &&\n entityHasActiveCustomFields &&\n this.isForcePartialIndexEnabled() &&\n opts.tenantId\n ) {\n try {\n await this.indexCoverageStats(entity, opts, coverageScope)\n const globalStats = await this.indexCoverageStats(entity, opts, coverageScope)\n if (globalStats) {\n const globalBase = globalStats.baseCount\n const globalIndexed = globalStats.indexedCount\n const globalGap = (globalBase > 0 && globalIndexed < globalBase) || globalIndexed > globalBase\n if (globalGap) {\n console.warn('[HybridQueryEngine] Partial index coverage detected at global scope; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity, baseCount: globalBase, indexedCount: globalIndexed, scope: 'global' })\n if (debugEnabled) {\n this.debug('query:partial-coverage:forced', {\n entity,\n baseCount: globalBase,\n indexedCount: globalIndexed,\n scope: 'global',\n })\n }\n partialIndexWarning = {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: globalBase,\n indexedCount: globalIndexed,\n scope: 'global',\n }\n }\n }\n } catch (err) {\n if (debugEnabled) {\n this.debug('query:partial-coverage:global-check-failed', {\n entity,\n error: err instanceof Error ? err.message : err,\n })\n }\n }\n }\n\n const resolveBaseColumn = (field: string): string | null => {\n if (columns.has(field)) return field\n if (field === 'organization_id' && columns.has('id')) return 'id'\n return null\n }\n\n for (const filter of cfFilters) {\n builder = this.applyCfFilterAcrossSources(\n knex,\n builder,\n filter.field,\n filter.op,\n filter.value,\n indexSources,\n searchRuntime\n )\n }\n\n for (const filter of baseFilters) {\n const baseField = resolveBaseColumn(String(filter.field))\n if (!baseField) continue\n const column = qualify(baseField)\n builder = this.applyColumnFilter(builder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: 'b.id',\n })\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyColumnFilter(optimizedCountBuilder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: 'b.id',\n })\n }\n }\n\n const applyAliasScopes = async (target: ResultBuilder, aliasName: string) => {\n const tableName = aliasTables.get(aliasName)\n if (!tableName) return\n if (orgScope && await this.columnExists(tableName, 'organization_id')) {\n this.applyOrganizationScope(target, `${aliasName}.organization_id`, orgScope)\n }\n if (opts.tenantId && await this.columnExists(tableName, 'tenant_id')) {\n target.where(`${aliasName}.tenant_id`, opts.tenantId)\n }\n if (!opts.withDeleted && await this.columnExists(tableName, 'deleted_at')) {\n target.whereNull(`${aliasName}.deleted_at`)\n }\n }\n\n const applyJoinFilterOp = (target: ResultBuilder, column: string, op: FilterOp, value?: unknown) => {\n switch (op) {\n case 'eq':\n target.where(column, value as Knex.Value)\n break\n case 'ne':\n target.whereNot(column, value as Knex.Value)\n break\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n target.where(column, operator, value as Knex.Value)\n break\n }\n case 'in':\n target.whereIn(column, this.toArray(value) as readonly Knex.Value[])\n break\n case 'nin':\n target.whereNotIn(column, this.toArray(value) as readonly Knex.Value[])\n break\n case 'like':\n target.where(column, 'like', value as Knex.Value)\n break\n case 'ilike':\n target.where(column, 'ilike', value as Knex.Value)\n break\n case 'exists':\n value ? target.whereNotNull(column) : target.whereNull(column)\n break\n }\n }\n\n await applyJoinFilters({\n knex,\n baseTable,\n builder,\n joinMap,\n joinFilters,\n aliasTables,\n qualifyBase: (column) => qualify(column),\n applyAliasScope: (target, alias) => applyAliasScopes(target, alias),\n applyFilterOp: (target, column, op, value) => applyJoinFilterOp(target as ResultBuilder, column, op, value),\n columnExists: (tbl, column) => this.columnExists(tbl, column),\n }) as ResultBuilder\n\n if (optimizedCountBuilder) {\n await applyJoinFilters({\n knex,\n baseTable,\n builder: optimizedCountBuilder,\n joinMap,\n joinFilters,\n aliasTables,\n qualifyBase: (column) => qualify(column),\n applyAliasScope: (target, alias) => applyAliasScopes(target, alias),\n applyFilterOp: (target, column, op, value) => applyJoinFilterOp(target as ResultBuilder, column, op, value),\n columnExists: (tbl, column) => this.columnExists(tbl, column),\n })\n }\n\n // When no fields specified, select all base table columns (like BasicQueryEngine does)\n const selectFieldSet = new Set<string>((opts.fields && opts.fields.length) ? opts.fields.map(String) : Array.from(columns.keys()))\n if (opts.includeCustomFields === true) {\n const entityIds = Array.from(new Set(indexSources.map((src) => String(src.entityId))))\n try {\n const resolvedKeys = await this.resolveAvailableCustomFieldKeys(entityIds, opts.tenantId ?? null)\n resolvedKeys.forEach((key) => selectFieldSet.add(`cf:${key}`))\n if (this.isDebugVerbosity()) {\n this.debug('query:cf:resolved-keys', { entity, keys: resolvedKeys })\n }\n } catch (err) {\n console.warn('[HybridQueryEngine] Failed to resolve custom field keys for', entity, err)\n }\n } else if (Array.isArray(opts.includeCustomFields)) {\n opts.includeCustomFields\n .map((key) => String(key))\n .forEach((key) => selectFieldSet.add(`cf:${key}`))\n }\n const selectFields = Array.from(selectFieldSet)\n for (const field of selectFields) {\n const fieldName = String(field)\n if (fieldName.startsWith('cf:')) {\n const alias = this.sanitize(fieldName)\n const { jsonSql } = this.buildCfExpressions(knex, fieldName, indexSources)\n const exprSql = jsonSql === 'NULL' ? 'NULL::jsonb' : jsonSql\n builder = builder.select(knex.raw(`${exprSql} as ??`, [alias]))\n } else if (columns.has(fieldName)) {\n builder = builder.select(knex.raw('?? as ??', [qualify(fieldName), fieldName]))\n }\n }\n\n for (const sort of opts.sort || []) {\n const fieldName = String(sort.field)\n if (fieldName.startsWith('cf:')) {\n const { textSql } = this.buildCfExpressions(knex, fieldName, indexSources)\n if (textSql !== 'NULL') {\n const direction = sort.dir ?? SortDir.Asc\n builder = builder.orderByRaw(`${textSql} ${direction}`)\n }\n } else {\n const baseField = resolveBaseColumn(fieldName)\n if (!baseField) continue\n builder = builder.orderBy(qualify(baseField), sort.dir ?? SortDir.Asc)\n }\n }\n\n const page = opts.page?.page ?? 1\n const pageSize = opts.page?.pageSize ?? 20\n\n const sqlDebugEnabled = this.isSqlDebugEnabled()\n let total: number\n\n if (optimizedCountBuilder) {\n const countSource = optimizedCountBuilder.clone().clearSelect().clearOrder().select(knex.raw(`${qualify('id')} as id`)).groupBy(qualify('id'))\n const countQuery = knex.from(countSource.as('sq')).count({ count: knex.raw('*') })\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = countQuery.clone().toSQL()\n this.debug('query:sql:count', { entity, sql, bindings })\n }\n const countRow = await this.captureSqlTiming(\n 'query:sql:count',\n entity,\n () => countQuery.first(),\n { optimized: true },\n profiler\n )\n total = this.parseCount(countRow)\n } else {\n const countBuilder = builder.clone().clearSelect().clearOrder().countDistinct(`${qualify('id')} as count`)\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = countBuilder.clone().toSQL()\n this.debug('query:sql:count', { entity, sql, bindings })\n }\n const countRow = await this.captureSqlTiming(\n 'query:sql:count',\n entity,\n () => countBuilder.first(),\n { optimized: false },\n profiler\n )\n total = this.parseCount(countRow)\n }\n\n const dataBuilder = builder.clone().limit(pageSize).offset((page - 1) * pageSize)\n\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = dataBuilder.clone().toSQL()\n this.debug('query:sql:data', { entity, sql, bindings, page, pageSize })\n }\n const itemsRaw = await this.captureSqlTiming(\n 'query:sql:data',\n entity,\n () => dataBuilder,\n { page, pageSize },\n profiler\n )\n if (debugEnabled) this.debug('query:complete', { entity, total, items: Array.isArray(itemsRaw) ? itemsRaw.length : 0 })\n\n let items = itemsRaw as any[]\n const encSvc = this.getEncryptionService()\n const dekKeyCache = new Map<string | null, string | null>()\n if (encSvc?.decryptEntityPayload) {\n const decrypt = encSvc.decryptEntityPayload.bind(encSvc) as (\n entityId: EntityId,\n payload: Record<string, unknown>,\n tenantId: string | null,\n organizationId: string | null,\n ) => Promise<Record<string, unknown>>\n items = await Promise.all(\n items.map(async (item) => {\n try {\n const decrypted = await decrypt(\n entity,\n item,\n item?.tenant_id ?? item?.tenantId ?? opts.tenantId ?? null,\n item?.organization_id ?? item?.organizationId ?? null,\n )\n return { ...item, ...decrypted }\n } catch (err) {\n console.error('Error decrypting entity payload', err);\n return item\n }\n })\n )\n }\n if (encSvc) {\n items = await Promise.all(\n items.map(async (item) => {\n try {\n return await decryptIndexDocCustomFields(\n item,\n {\n tenantId: item?.tenant_id ?? item?.tenantId ?? opts.tenantId ?? null,\n organizationId: item?.organization_id ?? item?.organizationId ?? null,\n },\n encSvc as any,\n dekKeyCache,\n )\n } catch {\n return item\n }\n }),\n )\n }\n\n const typedItems = items as unknown as T[]\n const result: QueryResult<T> = { items: typedItems, page, pageSize, total }\n if (partialIndexWarning) {\n result.meta = { partialIndexWarning }\n }\n finishProfile({\n result: 'ok',\n total,\n page,\n pageSize,\n itemCount: Array.isArray(items) ? items.length : undefined,\n partialIndexWarning: partialIndexWarning ? true : false,\n })\n return result\n } catch (err) {\n finishProfile({ result: 'error', error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }\n\n private getKnex(): Knex {\n const connection = this.em.getConnection()\n const withKnex = connection as { getKnex?: () => Knex }\n if (typeof withKnex.getKnex === 'function') {\n return withKnex.getKnex()\n }\n throw new Error('HybridQueryEngine requires a SQL connection that exposes getKnex()')\n }\n\n private prepareCustomFieldSources(\n knex: Knex,\n builder: ResultBuilder,\n sources: QueryCustomFieldSource[],\n qualify: (column: string) => string\n ): { builder: ResultBuilder; sources: PreparedCustomFieldSource[] } {\n let current = builder\n const prepared: PreparedCustomFieldSource[] = []\n sources.forEach((source, index) => {\n if (!source) return\n const joinTable = source.table ?? resolveEntityTableName(this.em, source.entityId)\n const alias = source.alias ?? `cfs_${index}`\n const join = source.join\n if (!join) {\n throw new Error(`QueryEngine: customFieldSources entry for ${String(source.entityId)} requires a join configuration`)\n }\n const joinArgs = { [alias]: joinTable }\n const joinCallback = function (this: Knex.JoinClause) {\n this.on(`${alias}.${join.toField}`, '=', qualify(join.fromField))\n }\n current = (join.type ?? 'left') === 'inner'\n ? current.join(joinArgs, joinCallback)\n : current.leftJoin(joinArgs, joinCallback)\n prepared.push({\n alias,\n indexAlias: `ei_${alias}`,\n entityId: source.entityId,\n recordIdColumn: source.recordIdColumn ?? 'id',\n organizationField: source.organizationField,\n tenantField: source.tenantField,\n table: joinTable,\n })\n })\n return { builder: current, sources: prepared }\n }\n\n private async isCustomEntity(entity: string): Promise<boolean> {\n try {\n const knex = this.getKnex()\n const row = await knex('custom_entities').where({ entity_id: entity, is_active: true }).first()\n return !!row\n } catch {\n return false\n }\n }\n\n private applySearchTokens<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n opts: {\n knex: Knex\n entity: string\n field: string\n hashes: string[]\n recordIdColumn: string\n tenantId?: string | null\n organizationScope?: { ids: string[]; includeNull: boolean } | null\n combineWith?: 'and' | 'or'\n }\n ): boolean {\n if (!opts.hashes.length) {\n this.logSearchDebug('search:skip-no-hashes', {\n entity: opts.entity,\n field: opts.field,\n tenantId: opts.tenantId ?? null,\n organizationScope: opts.organizationScope,\n })\n return false\n }\n const alias = `st_${this.searchAliasSeq++}`\n const combineWith = opts.combineWith === 'or' ? 'orWhereExists' : 'whereExists'\n const engine = this\n this.logSearchDebug('search:apply-search-tokens', {\n entity: opts.entity,\n field: opts.field,\n alias,\n tokenCount: opts.hashes.length,\n tenantId: opts.tenantId ?? null,\n organizationScope: opts.organizationScope,\n combineWith: opts.combineWith ?? 'and',\n })\n ;(q as any)[combineWith](function (this: Knex.QueryBuilder) {\n this.select(1)\n .from({ [alias]: 'search_tokens' })\n .where(`${alias}.entity_type`, opts.entity)\n .andWhere(`${alias}.field`, opts.field)\n .andWhereRaw('?? = ??::text', [`${alias}.entity_id`, opts.recordIdColumn])\n .whereIn(`${alias}.token_hash`, opts.hashes)\n .groupBy(`${alias}.entity_id`, `${alias}.field`)\n .havingRaw(`count(distinct ${alias}.token_hash) >= ?`, [opts.hashes.length])\n if (opts.tenantId !== undefined) {\n this.andWhereRaw(`${alias}.tenant_id is not distinct from ?`, [opts.tenantId ?? null])\n }\n if (opts.organizationScope) {\n engine.applyOrganizationScope(this as any, `${alias}.organization_id`, opts.organizationScope)\n }\n })\n return true\n }\n\n private jsonbRawAlias(knex: Knex, alias: string, key: string): Knex.Raw {\n // Prefer cf:<key> but fall back to bare <key> for legacy docs\n if (key.startsWith('cf:')) {\n const bare = key.slice(3)\n return knex.raw(`coalesce(${alias}.doc -> ?, ${alias}.doc -> ?)`, [key, bare])\n }\n return knex.raw(`${alias}.doc -> ?`, [key])\n }\n private cfTextExprAlias(knex: Knex, alias: string, key: string): Knex.Raw {\n if (key.startsWith('cf:')) {\n const bare = key.slice(3)\n return knex.raw(`coalesce((${alias}.doc ->> ?), (${alias}.doc ->> ?))`, [key, bare])\n }\n return knex.raw(`(${alias}.doc ->> ?)`, [key])\n }\n private buildCfExpressions(knex: Knex, key: string, sources: IndexDocSource[]): { jsonSql: string; textSql: string } {\n if (!sources.length) return { jsonSql: 'NULL', textSql: 'NULL' }\n const jsonFragments = sources.map((source) => this.jsonbRawAlias(knex, source.alias, key).toString())\n const textFragments = sources.map((source) => this.cfTextExprAlias(knex, source.alias, key).toString())\n const jsonSql = jsonFragments.length === 1 ? jsonFragments[0] : `coalesce(${jsonFragments.join(', ')})`\n const textSql = textFragments.length === 1 ? textFragments[0] : `coalesce(${textFragments.join(', ')})`\n return { jsonSql, textSql }\n }\n\n private applyCfFilterAcrossSources(\n knex: Knex,\n builder: ResultBuilder,\n key: string,\n op: FilterOp,\n value: unknown,\n sources: IndexDocSource[],\n search?: SearchRuntime\n ): ResultBuilder {\n if (!sources.length) return builder\n if ((op === 'like' || op === 'ilike') && search?.enabled && typeof value === 'string') {\n const tokens = tokenizeText(String(value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n let applied = false\n if (sources.length) {\n builder = builder.where((qb) => {\n sources.forEach((source, idx) => {\n const ok = this.applySearchTokens(qb as any, {\n knex,\n entity: source.entityId,\n field: key,\n hashes,\n recordIdColumn: `${source.alias}.entity_id`,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n combineWith: idx === 0 ? 'and' : 'or',\n })\n if (ok) applied = true\n })\n })\n }\n this.logSearchDebug('search:cf-filter-across', {\n entity: sources.map((src) => src.entityId),\n field: key,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n })\n if (applied) return builder\n } else {\n this.logSearchDebug('search:cf-skip-empty-hashes', {\n entity: sources.map((src) => src.entityId),\n field: key,\n value,\n })\n }\n return builder\n }\n const { jsonSql, textSql } = this.buildCfExpressions(knex, key, sources)\n if (jsonSql === 'NULL' || textSql === 'NULL') return builder\n const textExpr = knex.raw(textSql)\n const arrContains = (val: unknown) => knex.raw(`${jsonSql} @> ?::jsonb`, [JSON.stringify([val])])\n switch (op) {\n case 'eq':\n return builder.where((qb) => {\n qb.orWhere(textExpr, '=', value as Knex.Value)\n qb.orWhere(arrContains(value))\n })\n case 'ne':\n return builder.whereNot(textExpr, '=', value as Knex.Value)\n case 'in': {\n const values = this.toArray(value)\n return builder.where((qb) => {\n values.forEach((val) => {\n qb.orWhere(textExpr, '=', val as Knex.Value)\n qb.orWhere(arrContains(val))\n })\n })\n }\n case 'nin': {\n const values = this.toArray(value) as readonly Knex.Value[]\n return builder.whereNotIn(textExpr as any, values as any)\n }\n case 'like':\n return builder.where(textExpr, 'like', value as Knex.Value)\n case 'ilike':\n return builder.where(textExpr, 'ilike', value as Knex.Value)\n case 'exists':\n return value\n ? builder.whereRaw(`${textExpr.toString()} is not null`)\n : builder.whereRaw(`${textExpr.toString()} is null`)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n return builder.where(textExpr, operator, value as Knex.Value)\n }\n default:\n return builder\n }\n }\n\n private applyCfFilterFromAlias(\n knex: Knex,\n q: ResultBuilder,\n alias: string,\n entityType: string,\n key: string,\n op: FilterOp,\n value: unknown,\n search?: SearchRuntime\n ): ResultBuilder {\n const text = this.cfTextExprAlias(knex, alias, key)\n const arrExpr = knex.raw(`(${alias}.doc -> ?)`, [key])\n const arrContains = (val: unknown) => knex.raw(`${arrExpr.toString()} @> ?::jsonb`, [JSON.stringify([val])])\n if ((op === 'like' || op === 'ilike') && search?.enabled && typeof value === 'string') {\n const tokens = tokenizeText(String(value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n const applied = this.applySearchTokens(q, {\n knex,\n entity: entityType,\n field: key,\n hashes,\n recordIdColumn: `${alias}.entity_id`,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n })\n this.logSearchDebug('search:cf-filter', {\n entity: entityType,\n field: key,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n })\n if (applied) return q\n } else {\n this.logSearchDebug('search:cf-skip-empty-hashes', {\n entity: entityType,\n field: key,\n value,\n })\n }\n return q\n }\n switch (op) {\n case 'eq':\n return q.where((builder) => {\n builder.orWhere(text, '=', value as Knex.Value)\n builder.orWhere(arrContains(value))\n })\n case 'ne':\n return q.whereNot(text, '=', value as Knex.Value)\n case 'in': {\n const vals = this.toArray(value)\n return q.where((builder) => {\n vals.forEach((val) => {\n builder.orWhere(text, '=', val as Knex.Value)\n builder.orWhere(arrContains(val))\n })\n })\n }\n case 'nin': {\n const vals = this.toArray(value) as readonly Knex.Value[]\n return q.whereNotIn(text as any, vals as any)\n }\n case 'like':\n return q.where(text, 'like', value as Knex.Value)\n case 'ilike':\n return q.where(text, 'ilike', value as Knex.Value)\n case 'exists':\n return value\n ? q.whereRaw(`${text.toString()} is not null`)\n : q.whereRaw(`${text.toString()} is null`)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n return q.where(text, operator, value as Knex.Value)\n }\n default:\n return q\n }\n }\n\n private async queryCustomEntity<T = unknown>(entity: string, opts: QueryOptions = {}): Promise<QueryResult<T>> {\n const knex = this.getKnex()\n const alias = 'ce'\n let q = knex({ [alias]: 'custom_entities_storage' }).where(`${alias}.entity_type`, entity)\n\n const orgScope = this.resolveOrganizationScope(opts)\n\n // Require tenant scope; custom entities are tenant-scoped only\n if (!opts.tenantId) throw new Error('QueryEngine: tenantId is required')\n q = q.andWhere(`${alias}.tenant_id`, opts.tenantId)\n if (orgScope) {\n q = this.applyOrganizationScope(q, `${alias}.organization_id`, orgScope)\n }\n if (!opts.withDeleted) q = q.whereNull(`${alias}.deleted_at`)\n const searchConfig = resolveSearchConfig()\n const searchEnabled = searchConfig.enabled && await this.tableExists('search_tokens')\n const hasSearchTokens = searchEnabled\n ? await this.hasSearchTokens(entity, opts.tenantId ?? null, orgScope)\n : false\n const searchRuntime: SearchRuntime = {\n enabled: searchEnabled && hasSearchTokens,\n config: searchConfig,\n organizationScope: orgScope,\n tenantId: opts.tenantId ?? null,\n }\n\n const normalizedFilters = normalizeFilters(opts.filters)\n\n // Apply filters: cf:* via JSONB; other keys: special-case id/created_at/updated_at/deleted_at, otherwise from doc\n for (const filter of normalizedFilters) {\n if (filter.field.startsWith('cf:')) {\n q = this.applyCfFilterFromAlias(knex, q, alias, entity, filter.field, filter.op, filter.value, searchRuntime)\n continue\n }\n const column = this.resolveCustomEntityColumn(alias, String(filter.field))\n if (column) {\n q = this.applyColumnFilter(q, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: `${alias}.entity_id`,\n })\n continue\n }\n const docExpr = knex.raw(`(${alias}.doc ->> ?)`, [String(filter.field)])\n q = this.applyColumnFilter(q, docExpr, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: `${alias}.entity_id`,\n })\n }\n\n // Determine CFs and l10n keys to include\n const cfKeys = new Set<string>()\n for (const f of (opts.fields || [])) {\n if (typeof f === 'string' && f.startsWith('cf:')) cfKeys.add(f.slice(3))\n else if (typeof f === 'string' && f.startsWith('l10n:')) cfKeys.add(f)\n }\n for (const filter of normalizedFilters) {\n if (typeof filter.field === 'string' && filter.field.startsWith('cf:')) cfKeys.add(filter.field.slice(3))\n else if (typeof filter.field === 'string' && filter.field.startsWith('l10n:')) cfKeys.add(filter.field)\n }\n if (opts.includeCustomFields === true) {\n try {\n const rows = await knex('custom_field_defs')\n .select('key')\n .where({ entity_id: entity, is_active: true })\n .modify((qb) => {\n qb.andWhere({ tenant_id: opts.tenantId })\n // NOTE: organization-level scoping intentionally disabled for custom fields\n // if (opts.organizationId != null) qb.andWhere((b: any) => b.where({ organization_id: opts.organizationId }).orWhereNull('organization_id'))\n // else qb.whereNull('organization_id')\n })\n for (const row of rows) {\n const key = (row as Record<string, unknown>).key\n if (typeof key === 'string') {\n cfKeys.add(key)\n } else if (key != null) {\n cfKeys.add(String(key))\n }\n }\n } catch {\n // ignore and fall back to whatever keys we already have\n }\n } else if (Array.isArray(opts.includeCustomFields)) {\n for (const k of opts.includeCustomFields) cfKeys.add(k)\n }\n\n // Selection\n const requested = (opts.fields && opts.fields.length) ? opts.fields : ['id']\n for (const field of requested) {\n const f = String(field)\n if (f.startsWith('cf:')) {\n const aliasName = this.sanitize(f)\n const expr = this.jsonbRawAlias(knex, alias, f)\n q = q.select({ [aliasName]: expr })\n } else if (f === 'id') {\n q = q.select(knex.raw(`${alias}.entity_id as ??`, ['id']))\n } else if (f === 'created_at' || f === 'updated_at' || f === 'deleted_at') {\n q = q.select(knex.raw(`${alias}.?? as ??`, [f, f]))\n } else {\n // Non-cf from doc\n const expr = knex.raw(`(${alias}.doc ->> ?)`, [f])\n q = q.select({ [f]: expr })\n }\n }\n // Ensure CFs necessary for sort are selected\n const cfSelectedAliases: string[] = []\n for (const key of cfKeys) {\n const aliasName = this.sanitize(`cf:${key}`)\n const expr = this.jsonbRawAlias(knex, alias, `cf:${key}`)\n q = q.select({ [aliasName]: expr })\n cfSelectedAliases.push(aliasName)\n }\n\n // Sorting\n for (const s of opts.sort || []) {\n if (s.field.startsWith('cf:')) {\n const key = s.field.slice(3)\n const aliasName = this.sanitize(`cf:${key}`)\n if (!cfSelectedAliases.includes(aliasName)) {\n const expr = this.jsonbRawAlias(knex, alias, `cf:${key}`)\n q = q.select({ [aliasName]: expr })\n cfSelectedAliases.push(aliasName)\n }\n q = q.orderBy(aliasName, s.dir ?? SortDir.Asc)\n } else if (s.field === 'id') {\n q = q.orderBy(`${alias}.entity_id`, s.dir ?? SortDir.Asc)\n } else if (s.field === 'created_at' || s.field === 'updated_at' || s.field === 'deleted_at') {\n q = q.orderBy(`${alias}.${s.field}`, s.dir ?? SortDir.Asc)\n } else {\n const direction = s.dir ?? SortDir.Asc\n q = q.orderByRaw(`(${alias}.doc ->> ?) ${direction}`, [s.field])\n }\n }\n\n // Pagination + totals\n const page = opts.page?.page ?? 1\n const pageSize = opts.page?.pageSize ?? 20\n const countClone = q.clone()\n if (typeof countClone.clearSelect === 'function') countClone.clearSelect()\n if (typeof countClone.clearOrder === 'function') countClone.clearOrder()\n const countRow = await countClone.countDistinct(`${alias}.entity_id as count`).first()\n const total = this.parseCount(countRow)\n const items = await q.limit(pageSize).offset((page - 1) * pageSize)\n return { items, page, pageSize, total }\n }\n\n private async tableExists(table: string): Promise<boolean> {\n const knex = this.getKnex()\n const exists = await knex('information_schema.tables').where({ table_name: table }).first()\n return !!exists\n }\n\n private async hasSearchTokens(\n entity: string,\n tenantId: string | null,\n orgScope?: { ids: string[]; includeNull: boolean } | null\n ): Promise<boolean> {\n try {\n const knex = this.getKnex()\n const query = knex('search_tokens').select(1).where('entity_type', entity).limit(1)\n if (tenantId !== undefined) {\n query.andWhereRaw('tenant_id is not distinct from ?', [tenantId])\n }\n if (orgScope) {\n this.applyOrganizationScope(query as any, 'search_tokens.organization_id', orgScope)\n }\n const row = await query.first()\n return !!row\n } catch (err) {\n this.logSearchDebug('search:has-tokens-error', {\n entity,\n tenantId,\n organizationScope: orgScope,\n error: err instanceof Error ? err.message : String(err),\n })\n return false\n }\n }\n\n private async searchSourcesHaveTokens(\n sources: SearchTokenSource[],\n tenantId: string | null,\n orgScope?: { ids: string[]; includeNull: boolean } | null\n ): Promise<boolean> {\n for (const source of sources) {\n const ok = await this.hasSearchTokens(source.entity, tenantId, orgScope)\n this.logSearchDebug('search:source-has-tokens', {\n entity: source.entity,\n recordIdColumn: source.recordIdColumn,\n tenantId,\n organizationScope: orgScope,\n hasTokens: ok,\n })\n if (ok) return true\n }\n return false\n }\n\n private async resolveAvailableCustomFieldKeys(entityIds: string[], tenantId: string | null): Promise<string[]> {\n if (!entityIds.length) return []\n const cacheKey = this.customFieldKeysCacheKey(entityIds, tenantId)\n const now = Date.now()\n const cached = this.customFieldKeysCache.get(cacheKey)\n if (cached && cached.expiresAt > now) {\n return cached.value.slice()\n }\n\n const knex = this.getKnex()\n const rows = await knex('custom_field_defs')\n .select('key')\n .whereIn('entity_id', entityIds)\n .andWhere('is_active', true)\n .modify((qb: any) => {\n qb.andWhere((inner: any) => {\n inner.where({ tenant_id: tenantId }).orWhereNull('tenant_id')\n })\n })\n const keys = new Set<string>()\n for (const row of rows || []) {\n const key = (row as Record<string, unknown>).key\n if (typeof key === 'string' && key.trim().length) keys.add(key.trim())\n else if (key != null) keys.add(String(key))\n }\n const result = Array.from(keys)\n if (this.customFieldKeysTtlMs > 0) {\n this.customFieldKeysCache.set(cacheKey, { expiresAt: now + this.customFieldKeysTtlMs, value: result })\n }\n return result.slice()\n }\n\n private async entityHasActiveCustomFields(entityId: string, tenantId: string | null): Promise<boolean> {\n try {\n const keys = await this.resolveAvailableCustomFieldKeys([entityId], tenantId)\n return keys.length > 0\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('query:cf:check-error', {\n entity: entityId,\n tenantId: tenantId ?? null,\n error: err instanceof Error ? err.message : err,\n })\n }\n return true\n }\n }\n\n private customFieldKeysCacheKey(entityIds: string[], tenantId: string | null): string {\n const sorted = entityIds.slice().sort((a, b) => a.localeCompare(b)).join(',')\n return `${tenantId ?? '__none__'}|${sorted}`\n }\n\n private resolveVectorService(): VectorIndexService | null {\n if (!this.vectorServiceResolver) return null\n try {\n return this.vectorServiceResolver() ?? null\n } catch {\n return null\n }\n }\n\n private resolveEntityLabel(entity: string): string {\n return entity\n }\n\n private async indexAnyRows(entity: string): Promise<boolean> {\n const knex = this.getKnex()\n // Prefer coverage snapshots \u2013 cheap and already scoped by maintenance jobs.\n const coverage = await knex('entity_index_coverage')\n .select(1)\n .where('entity_type', entity)\n .where('indexed_count', '>', 0)\n .first()\n if (coverage) return true\n const exists = await knex('entity_indexes').select('entity_id').where({ entity_type: entity }).first()\n return !!exists\n }\n private async getStoredCoverageSnapshot(\n entity: string,\n tenantId: string | null,\n organizationId: string | null,\n withDeleted: boolean\n ): Promise<{ baseCount: number; indexedCount: number } | null> {\n try {\n if (!this.isCoverageOptimizationEnabled()) {\n await refreshCoverageSnapshot(\n this.em,\n {\n entityType: entity,\n tenantId,\n organizationId,\n withDeleted,\n },\n )\n }\n const knex = this.getKnex()\n const row = await readCoverageSnapshot(knex, {\n entityType: entity,\n tenantId,\n organizationId,\n withDeleted,\n })\n if (!row) return null\n return { baseCount: row.baseCount, indexedCount: row.indexedCount }\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('coverage:snapshot:read-error', {\n entity,\n tenantId,\n organizationId,\n withDeleted,\n error: err instanceof Error ? err.message : err,\n })\n }\n return null\n }\n }\n\n private scheduleAutoReindex(\n entity: string,\n opts: QueryOptions,\n stats?: { baseCount: number; indexedCount: number },\n organizationIdOverride?: string | null\n ) {\n if (!this.isAutoReindexEnabled()) return\n\n const bus = this.resolveEventBus()\n if (!bus) return\n const payload = {\n entityType: entity,\n tenantId: opts.tenantId ?? null,\n organizationId: organizationIdOverride ?? opts.organizationId ?? null,\n force: false,\n }\n const context = stats\n ? {\n entity,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n baseCount: stats.baseCount,\n indexedCount: stats.indexedCount,\n }\n : { entity, tenantId: payload.tenantId, organizationId: payload.organizationId }\n\n void Promise.resolve()\n .then(async () => {\n try {\n await bus.emitEvent('query_index.reindex', payload, { persistent: true })\n if (this.isDebugVerbosity()) this.debug('query:auto-reindex:scheduled', context)\n } catch (err) {\n console.warn('[HybridQueryEngine] Failed to schedule auto reindex:', {\n ...context,\n error: err instanceof Error ? err.message : err,\n })\n }\n })\n }\n\n private scheduleCoverageRefresh(\n entity: string,\n tenantId: string | null | undefined,\n organizationId: string | null | undefined,\n withDeleted: boolean\n ): void {\n const bus = this.resolveEventBus()\n if (!bus) return\n const key = [\n entity,\n tenantId ?? '__tenant__',\n organizationId ?? '__org__',\n withDeleted ? '1' : '0',\n ].join('|')\n if (this.pendingCoverageRefreshKeys.has(key)) return\n this.pendingCoverageRefreshKeys.add(key)\n void Promise.resolve()\n .then(async () => {\n try {\n await bus.emitEvent('query_index.coverage.refresh', {\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n delayMs: 0,\n })\n if (this.isDebugVerbosity()) {\n this.debug('coverage:refresh:scheduled', {\n entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n })\n }\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('coverage:refresh:failed', {\n entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n error: err instanceof Error ? err.message : err,\n })\n }\n }\n })\n .finally(() => {\n this.pendingCoverageRefreshKeys.delete(key)\n })\n }\n\n private resolveEventBus(): Pick<EventBus, 'emitEvent'> | null {\n if (!this.eventBusResolver) return null\n try {\n const bus = this.eventBusResolver()\n return bus ?? null\n } catch {\n return null\n }\n }\n\n private isAutoReindexEnabled(): boolean {\n if (this.autoReindexEnabled != null) return this.autoReindexEnabled\n const raw = (\n process.env.SCHEDULE_AUTO_REINDEX ??\n process.env.QUERY_INDEX_AUTO_REINDEX ??\n ''\n )\n .trim()\n .toLowerCase()\n if (!raw) {\n this.autoReindexEnabled = true\n return true\n }\n const parsed = parseBooleanToken(raw)\n this.autoReindexEnabled = parsed === null ? true : parsed\n return this.autoReindexEnabled\n }\n\n private isCoverageOptimizationEnabled(): boolean {\n if (this.coverageOptimizationEnabled != null) return this.coverageOptimizationEnabled\n const raw = (process.env.OPTIMIZE_INDEX_COVERAGE_STATS ?? '').trim().toLowerCase()\n if (!raw) {\n this.coverageOptimizationEnabled = false\n return false\n }\n this.coverageOptimizationEnabled = parseBooleanToken(raw) === true\n return this.coverageOptimizationEnabled\n }\n\n private async columnExists(table: string, column: string): Promise<boolean> {\n const key = `${table}.${column}`\n if (this.columnCache.has(key)) {\n const cached = this.columnCache.get(key)\n if (cached === true) return true\n this.columnCache.delete(key)\n }\n const knex = this.getKnex()\n const exists = await knex('information_schema.columns')\n .where({ table_name: table, column_name: column })\n .first()\n const present = !!exists\n if (present) this.columnCache.set(key, true)\n else this.columnCache.delete(key)\n return present\n }\n\n private async getBaseColumnsForEntity(entity: string): Promise<Map<string, string>> {\n const knex = this.getKnex()\n const table = resolveEntityTableName(this.em, entity)\n const rows = await knex('information_schema.columns')\n .select('column_name', 'data_type')\n .where({ table_name: table })\n const map = new Map<string, string>()\n for (const r of rows) map.set(r.column_name, r.data_type)\n return map\n }\n\n private resolveOrganizationScope(opts: QueryOptions): { ids: string[]; includeNull: boolean } | null {\n if (opts.organizationIds !== undefined) {\n const raw = (opts.organizationIds ?? []).map((id) => (typeof id === 'string' ? id.trim() : id))\n const includeNull = raw.some((id) => id == null || id === '')\n const ids = raw.filter((id): id is string => typeof id === 'string' && id.length > 0)\n const unique = Array.from(new Set(ids))\n return { ids: unique, includeNull }\n }\n if (typeof opts.organizationId === 'string' && opts.organizationId.trim().length > 0) {\n return { ids: [opts.organizationId], includeNull: false }\n }\n return null\n }\n\n private resolveCoverageSnapshotScope(\n opts: QueryOptions\n ): { tenantId: string | null; organizationId: string | null } | null {\n const tenantId = opts.tenantId ?? null\n const orgScope = this.resolveOrganizationScope(opts)\n if (!orgScope) return { tenantId, organizationId: null }\n if (orgScope.includeNull) {\n if (orgScope.ids.length === 0) return { tenantId, organizationId: null }\n return null\n }\n if (orgScope.ids.length === 1) return { tenantId, organizationId: orgScope.ids[0] }\n if (orgScope.ids.length === 0) return { tenantId, organizationId: null }\n return null\n }\n\n private applyOrganizationScope<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n column: string,\n scope: { ids: string[]; includeNull: boolean }\n ): Knex.QueryBuilder<TRecord, TResult> {\n if (scope.ids.length === 0 && !scope.includeNull) {\n return q.whereRaw('1 = 0')\n }\n return q.where((builder) => {\n let applied = false\n if (scope.ids.length > 0) {\n builder.whereIn(column, scope.ids as readonly string[])\n applied = true\n }\n if (scope.includeNull) {\n if (applied) builder.orWhereNull(column)\n else builder.whereNull(column)\n } else if (!applied) {\n builder.whereRaw('1 = 0')\n }\n })\n }\n\n private normalizeFilters(filters?: QueryOptions['filters']): NormalizedFilter[] {\n if (!filters) return []\n const normalizeField = (k: string) => k.startsWith('cf_') ? `cf:${k.slice(3)}` : k\n if (Array.isArray(filters)) {\n return (filters as Filter[]).map((filter) => ({\n field: normalizeField(String(filter.field)),\n op: filter.op,\n value: filter.value,\n }))\n }\n const out: NormalizedFilter[] = []\n const obj = filters as Record<string, unknown>\n const add = (field: string, op: FilterOp, value?: unknown) => out.push({ field, op, value })\n for (const [rawKey, rawVal] of Object.entries(obj)) {\n const field = normalizeField(rawKey)\n if (rawVal !== null && typeof rawVal === 'object' && !Array.isArray(rawVal)) {\n for (const [opKey, opVal] of Object.entries(rawVal as Record<string, unknown>)) {\n switch (opKey) {\n case '$eq': add(field, 'eq', opVal); break\n case '$ne': add(field, 'ne', opVal); break\n case '$gt': add(field, 'gt', opVal); break\n case '$gte': add(field, 'gte', opVal); break\n case '$lt': add(field, 'lt', opVal); break\n case '$lte': add(field, 'lte', opVal); break\n case '$in': add(field, 'in', opVal); break\n case '$nin': add(field, 'nin', opVal); break\n case '$like': add(field, 'like', opVal); break\n case '$ilike': add(field, 'ilike', opVal); break\n case '$exists': add(field, 'exists', opVal); break\n }\n }\n } else {\n add(field, 'eq', rawVal)\n }\n }\n return out\n }\n\n private sanitize(s: string): string {\n return s.replace(/[^a-zA-Z0-9_]/g, '_')\n }\n\n private toArray(value: unknown): readonly unknown[] {\n if (Array.isArray(value)) {\n return value\n }\n if (value === undefined) {\n return []\n }\n return [value]\n }\n\n private parseCount(row: unknown): number {\n if (row && typeof row === 'object' && 'count' in row) {\n const value = (row as { count: unknown }).count\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? 0 : parsed\n }\n }\n return 0\n }\n\n private logSearchDebug(event: string, payload: Record<string, unknown>) {\n if (!this.isDebugVerbosity()) return\n try {\n console.info('[query-index:search]', event, JSON.stringify(payload))\n } catch {\n console.info('[query-index:search]', event, payload)\n }\n }\n\n private applyColumnFilter<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n column: string | Knex.Raw,\n filter: NormalizedFilter,\n search?: SearchRuntime & { knex: Knex; entity: string; field: string; recordIdColumn?: string }\n ): Knex.QueryBuilder<TRecord, TResult> {\n if (\n (filter.op === 'like' || filter.op === 'ilike') &&\n search?.enabled &&\n typeof filter.value === 'string'\n ) {\n const tokens = tokenizeText(String(filter.value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n const sources: SearchTokenSource[] = (search.searchSources && search.searchSources.length\n ? search.searchSources\n : [{ entity: search.entity, recordIdColumn: search.recordIdColumn ?? '' }]\n ).filter((src) => src.recordIdColumn && src.entity)\n let applied = false\n if (sources.length) {\n q = q.where((qb) => {\n sources.forEach((src, idx) => {\n const ok = this.applySearchTokens(qb as any, {\n knex: search.knex,\n entity: src.entity,\n field: search.field,\n hashes,\n recordIdColumn: src.recordIdColumn,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n combineWith: idx === 0 ? 'and' : 'or',\n })\n if (ok) applied = true\n })\n })\n }\n this.logSearchDebug('search:filter', {\n entity: search.entity,\n field: search.field,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n sources: sources.map((src) => ({ entity: src.entity, recordIdColumn: src.recordIdColumn })),\n })\n if (applied) return q\n } else {\n this.logSearchDebug('search:skip-empty-hashes', {\n entity: search.entity,\n field: search.field,\n value: filter.value,\n })\n }\n return q\n }\n const col = column as any\n switch (filter.op) {\n case 'eq':\n return q.where(col, filter.value as Knex.Value)\n case 'ne':\n return q.whereNot(col, filter.value as Knex.Value)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = filter.op === 'gt' ? '>' : filter.op === 'gte' ? '>=' : filter.op === 'lt' ? '<' : '<='\n return q.where(col, operator, filter.value as Knex.Value)\n }\n case 'in': {\n const values = this.toArray(filter.value) as readonly Knex.Value[]\n return q.whereIn(col, values)\n }\n case 'nin': {\n const values = this.toArray(filter.value) as readonly Knex.Value[]\n return q.whereNotIn(col, values)\n }\n case 'like':\n return q.where(col, 'like', filter.value as Knex.Value)\n case 'ilike':\n return q.where(col, 'ilike', filter.value as Knex.Value)\n case 'exists':\n return filter.value ? q.whereNotNull(col) : q.whereNull(col)\n default:\n return q\n }\n }\n\n private resolveCustomEntityColumn(alias: string, field: string): string | null {\n if (field === 'id') return `${alias}.entity_id`\n if (field === 'organization_id' || field === 'organizationId') return `${alias}.organization_id`\n if (field === 'tenant_id' || field === 'tenantId') return `${alias}.tenant_id`\n if (field === 'created_at' || field === 'updated_at' || field === 'deleted_at') return `${alias}.${field}`\n return null\n }\n\n private isDebugVerbosity(): boolean {\n if (this.debugVerbosity != null) return this.debugVerbosity\n this.debugVerbosity = resolveDebugVerbosity()\n return this.debugVerbosity\n }\n\n private isSqlDebugEnabled(): boolean {\n if (this.sqlDebugEnabled != null) return this.sqlDebugEnabled\n this.sqlDebugEnabled = resolveBooleanEnv(['QUERY_ENGINE_DEBUG_SQL'], false)\n return this.sqlDebugEnabled\n }\n\n private isForcePartialIndexEnabled(): boolean {\n if (this.forcePartialIndexEnabled != null) return this.forcePartialIndexEnabled\n this.forcePartialIndexEnabled = resolveBooleanEnv(['FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES'], true)\n return this.forcePartialIndexEnabled\n }\n\n private async resolveCoverageGap(\n entity: string,\n opts: QueryOptions,\n coverageScope?: { tenantId: string | null; organizationId: string | null } | null,\n _sourceTable?: string\n ): Promise<{ stats?: { baseCount: number; indexedCount: number }; scope: 'scoped' | 'global' } | null> {\n const scope = coverageScope ?? this.resolveCoverageSnapshotScope(opts)\n if (!scope) return null\n const tenantId = scope.tenantId\n const organizationId = scope.organizationId\n const withDeleted = !!opts.withDeleted\n\n const snapshot = await this.getStoredCoverageSnapshot(entity, tenantId, organizationId, withDeleted)\n if (!snapshot) {\n this.scheduleCoverageRefresh(entity, tenantId, organizationId, withDeleted)\n return { stats: undefined, scope: 'scoped' }\n }\n\n const baseCount = snapshot.baseCount\n const indexCount = snapshot.indexedCount\n const hasGap = baseCount > 0 && indexCount < baseCount\n if (hasGap || indexCount > baseCount) {\n return { stats: snapshot, scope: 'scoped' }\n }\n\n return null\n }\n\n // Backward-compatible hook for tests that mock coverage stats\n private async indexCoverageStats(\n entity: string,\n opts: QueryOptions,\n coverageScope?: { tenantId: string | null; organizationId: string | null } | null,\n ): Promise<{ baseCount: number; indexedCount: number } | null> {\n const gap = await this.resolveCoverageGap(entity, opts, coverageScope)\n return gap?.stats ?? null\n }\n\n private async captureSqlTiming<TResult>(\n label: string,\n entity: EntityId,\n execute: () => Promise<TResult> | TResult,\n extra?: Record<string, unknown>,\n profiler?: Profiler\n ): Promise<TResult> {\n const shouldDebug = this.isSqlDebugEnabled() && this.isDebugVerbosity()\n const shouldProfile = profiler?.enabled === true\n if (!shouldDebug && !shouldProfile) {\n return Promise.resolve(execute())\n }\n const startedAt = process.hrtime.bigint()\n try {\n return await Promise.resolve(execute())\n } finally {\n const elapsedMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000\n const context: Record<string, unknown> = {\n entity,\n durationMs: Math.round(elapsedMs * 1000) / 1000,\n }\n if (extra) Object.assign(context, extra)\n if (shouldProfile) profiler!.record(label, context.durationMs as number, extra)\n if (shouldDebug) this.debug(`${label}:timing`, context)\n }\n }\n\n private debug(message: string, context?: Record<string, unknown>): void {\n if (!this.isDebugVerbosity()) return\n if (!this.isSqlDebugEnabled()) return\n if (context) console.debug('[HybridQueryEngine]', message, context)\n else console.debug('[HybridQueryEngine]', message)\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { QueryEngine, QueryOptions, QueryResult, FilterOp, Filter, QueryCustomFieldSource, PartialIndexWarning } from '@open-mercato/shared/lib/query/types'\nimport { SortDir } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { BasicQueryEngine, resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport type { Knex } from 'knex'\nimport type { EventBus } from '@open-mercato/events'\nimport { readCoverageSnapshot, refreshCoverageSnapshot } from './coverage'\nimport { createProfiler, shouldEnableProfiler, type Profiler } from '@open-mercato/shared/lib/profiler'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\nimport { decryptIndexDocCustomFields } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken, parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport {\n applyJoinFilters,\n normalizeFilters,\n partitionFilters,\n resolveJoins,\n type BaseFilter,\n type ResolvedJoin,\n} from '@open-mercato/shared/lib/query/join-utils'\nimport { resolveSearchConfig, type SearchConfig } from '@open-mercato/shared/lib/search/config'\nimport { tokenizeText } from '@open-mercato/shared/lib/search/tokenize'\n\nfunction resolveBooleanEnv(names: readonly string[], defaultValue: boolean): boolean {\n for (const name of names) {\n const raw = process.env[name]\n if (raw !== undefined) return parseBooleanWithDefault(raw, defaultValue)\n }\n return defaultValue\n}\n\nfunction resolveDebugVerbosity(): boolean {\n // Check explicit OM_QUERY_INDEX_DEBUG flag first\n const queryIndexDebug = process.env.OM_QUERY_INDEX_DEBUG\n if (queryIndexDebug !== undefined) {\n return parseBooleanToken(queryIndexDebug) ?? false\n }\n // Fall back to log level or NODE_ENV\n const level = (process.env.LOG_VERBOSITY ?? process.env.LOG_LEVEL ?? '').toLowerCase()\n if (['debug', 'trace', 'silly'].includes(level)) return true\n // Default to false (don't spam logs in development)\n return false\n}\n\ntype ResultRow = Record<string, unknown>\ntype ResultBuilder<TResult = ResultRow[]> = Knex.QueryBuilder<ResultRow, TResult>\ntype NormalizedFilter = { field: string; op: FilterOp; value?: unknown }\ntype IndexDocSource = { alias: string; entityId: EntityId; recordIdColumn: string }\ntype PreparedCustomFieldSource = {\n alias: string\n indexAlias: string\n entityId: EntityId\n recordIdColumn: string\n organizationField?: string\n tenantField?: string\n table: string\n}\ntype SearchRuntime = {\n enabled: boolean\n config: SearchConfig\n organizationScope?: { ids: string[]; includeNull: boolean } | null\n tenantId?: string | null\n searchSources?: SearchTokenSource[]\n}\n\ntype EncryptionResolver = () => {\n decryptEntityPayload?: (entityId: EntityId, payload: Record<string, unknown>, tenantId?: string | null, organizationId?: string | null) => Promise<Record<string, unknown>>\n isEnabled?: () => boolean\n} | null\n\ntype SearchTokenSource = { entity: string; recordIdColumn: string }\n\nfunction createQueryProfiler(entity: string): Profiler {\n const enabled = shouldEnableProfiler(entity)\n return createProfiler({\n scope: 'query_engine',\n target: entity,\n label: `query_engine:${entity}`,\n loggerLabel: '[qe:profile]',\n enabled,\n })\n}\n\nexport class HybridQueryEngine implements QueryEngine {\n private coverageStatsTtlMs: number\n private customFieldKeysCache = new Map<string, { expiresAt: number; value: string[] }>()\n private customFieldKeysTtlMs: number\n private columnCache = new Map<string, boolean>()\n private debugVerbosity: boolean | null = null\n private sqlDebugEnabled: boolean | null = null\n private forcePartialIndexEnabled: boolean | null = null\n private autoReindexEnabled: boolean | null = null\n private coverageOptimizationEnabled: boolean | null = null\n private pendingCoverageRefreshKeys = new Set<string>()\n private searchAliasSeq = 0\n\n constructor(\n private em: EntityManager,\n private fallback: BasicQueryEngine,\n private eventBusResolver?: () => Pick<EventBus, 'emitEvent'> | null | undefined,\n private vectorServiceResolver?: () => VectorIndexService | null | undefined,\n private encryptionResolver?: EncryptionResolver,\n ) {\n const coverageTtl = Number.parseInt(process.env.QUERY_INDEX_COVERAGE_CACHE_MS ?? '', 10)\n this.coverageStatsTtlMs = Number.isFinite(coverageTtl) && coverageTtl >= 0 ? coverageTtl : 5 * 60 * 1000\n const cfTtl = Number.parseInt(process.env.QUERY_INDEX_CF_KEYS_CACHE_MS ?? '', 10)\n this.customFieldKeysTtlMs = Number.isFinite(cfTtl) && cfTtl >= 0 ? cfTtl : 5 * 60 * 1000\n }\n\n private getEncryptionService() {\n try {\n return this.encryptionResolver?.() ?? null\n } catch {\n return null\n }\n }\n\n async query<T = unknown>(entity: EntityId, opts: QueryOptions = {}): Promise<QueryResult<T>> {\n const providedProfiler = opts.profiler\n const profiler = providedProfiler && providedProfiler.enabled\n ? providedProfiler\n : createQueryProfiler(String(entity))\n profiler.mark('query:init')\n let profileClosed = false\n const finishProfile = (meta?: Record<string, unknown>) => {\n if (!profiler.enabled || profileClosed) return\n profileClosed = true\n profiler.end(meta)\n }\n\n try {\n const debugEnabled = this.isDebugVerbosity()\n if (debugEnabled) this.debug('query:start', { entity })\n this.searchAliasSeq = 0\n\n const isCustom = await this.isCustomEntity(entity)\n if (isCustom) {\n if (debugEnabled) this.debug('query:custom-entity', { entity })\n const section = profiler.section('custom_entity')\n try {\n const result = await this.queryCustomEntity<T>(entity, opts)\n section.end({ mode: 'custom_entity' })\n finishProfile({\n result: 'custom_entity',\n total: Array.isArray(result.items) ? result.items.length : undefined,\n })\n return result\n } catch (err) {\n section.end({ error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }\n\n const knex = this.getKnex()\n profiler.mark('query:knex_ready')\n const baseTable = resolveEntityTableName(this.em, entity)\n profiler.mark('query:base_table_resolved')\n const searchConfig = resolveSearchConfig()\n const orgScope = this.resolveOrganizationScope(opts)\n const searchEnabled = searchConfig.enabled && await this.tableExists('search_tokens')\n\n const baseExists = await profiler.measure('base_table_exists', () => this.tableExists(baseTable))\n if (!baseExists) {\n if (debugEnabled) this.debug('query:fallback:missing-base', { entity, baseTable })\n const fallbackResult = await this.fallback.query(entity, opts)\n finishProfile({ result: 'fallback', reason: 'missing_base' })\n return fallbackResult\n }\n\n const normalizedFilters = normalizeFilters(opts.filters)\n const cfFilters = normalizedFilters.filter((filter) => filter.field.startsWith('cf:') || filter.field.startsWith('l10n:'))\n const coverageScope = this.resolveCoverageSnapshotScope(opts)\n const wantsCf = (\n (opts.fields || []).some((field) => typeof field === 'string' && (field.startsWith('cf:') || field.startsWith('l10n:'))) ||\n cfFilters.length > 0 ||\n opts.includeCustomFields === true ||\n (Array.isArray(opts.includeCustomFields) && opts.includeCustomFields.length > 0)\n )\n\n if (debugEnabled) {\n this.debug('query:config', {\n entity,\n wantsCustomFields: wantsCf,\n customFieldSources: Array.isArray(opts.customFieldSources) ? opts.customFieldSources.map((src) => src?.entityId) : undefined,\n fields: opts.fields,\n })\n }\n\n let partialIndexWarning: PartialIndexWarning | null = null\n let entityHasActiveCustomFields = true\n\n if (wantsCf) {\n entityHasActiveCustomFields = await this.entityHasActiveCustomFields(entity, opts.tenantId ?? null)\n const hasIndexRows = await profiler.measure(\n 'index_any_rows',\n () => this.indexAnyRows(entity),\n (value) => ({ hasIndexRows: value })\n )\n if (!hasIndexRows) {\n if (debugEnabled) this.debug('query:fallback:no-index', { entity })\n const fallbackResult = await this.fallback.query(entity, opts)\n finishProfile({ result: 'fallback', reason: 'no_index_rows' })\n return fallbackResult\n }\n if (entityHasActiveCustomFields) {\n const gap = await profiler.measure(\n 'resolve_coverage_gap',\n () => this.resolveCoverageGap(entity, opts, coverageScope),\n (value) => (value\n ? {\n scope: value.scope,\n baseCount: value.stats?.baseCount ?? null,\n indexedCount: value.stats?.indexedCount ?? null,\n }\n : { scope: null })\n )\n if (gap) {\n if (!opts.skipAutoReindex) {\n this.scheduleAutoReindex(entity, opts, gap.stats, coverageScope?.organizationId ?? null)\n }\n const force = this.isForcePartialIndexEnabled()\n if (!force) {\n if (gap.stats) {\n console.warn('[HybridQueryEngine] Partial index coverage detected; falling back to basic engine:', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n if (debugEnabled) this.debug('query:fallback:partial-coverage', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n } else {\n console.warn('[HybridQueryEngine] Partial index coverage detected; falling back to basic engine:', { entity })\n if (debugEnabled) this.debug('query:fallback:partial-coverage', { entity })\n }\n const fallbackResult = await this.fallback.query(entity, opts)\n const resultWithWarning: QueryResult<T> = {\n ...fallbackResult,\n meta: {\n ...(fallbackResult.meta ?? {}),\n partialIndexWarning: {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n },\n },\n }\n finishProfile({\n result: 'fallback',\n reason: 'partial_index',\n scope: gap.scope,\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n })\n return resultWithWarning\n }\n if (gap.stats) {\n console.warn('[HybridQueryEngine] Partial index coverage detected; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n if (debugEnabled) this.debug('query:partial-coverage:forced', { entity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n } else {\n console.warn('[HybridQueryEngine] Partial index coverage detected; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity })\n if (debugEnabled) this.debug('query:partial-coverage:forced', { entity })\n }\n partialIndexWarning = {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n }\n }\n } else if (debugEnabled) {\n this.debug('query:coverage:skip-no-custom-fields', { entity })\n }\n }\n\n const qualify = (col: string) => `b.${col}`\n let builder: ResultBuilder = knex({ b: baseTable })\n const hasCustomFieldFilters = cfFilters.length > 0\n const canOptimizeCount = !hasCustomFieldFilters\n let optimizedCountBuilder: ResultBuilder | null = canOptimizeCount ? knex({ b: baseTable }) : null\n\n const resolvedJoinsConfig = resolveJoins(baseTable, opts.joins, (entityId) => resolveEntityTableName(this.em, entityId as any))\n const joinMap = new Map<string, ResolvedJoin>()\n const aliasTables = new Map<string, string>()\n aliasTables.set('b', baseTable)\n aliasTables.set('base', baseTable)\n aliasTables.set(baseTable, baseTable)\n for (const join of resolvedJoinsConfig) {\n joinMap.set(join.alias, join)\n aliasTables.set(join.alias, join.table)\n }\n const { baseFilters, joinFilters } = partitionFilters(baseTable, normalizedFilters, joinMap)\n\n if (!opts.tenantId) throw new Error('QueryEngine: tenantId is required')\n\n const hasOrganizationColumn = await this.columnExists(baseTable, 'organization_id')\n const hasTenantColumn = await this.columnExists(baseTable, 'tenant_id')\n const hasDeletedColumn = await this.columnExists(baseTable, 'deleted_at')\n const searchRuntimeBase = {\n enabled: false,\n config: searchConfig,\n organizationScope: orgScope,\n tenantId: opts.tenantId ?? null,\n }\n\n if (orgScope && hasOrganizationColumn) {\n builder = this.applyOrganizationScope(builder, qualify('organization_id'), orgScope)\n if (optimizedCountBuilder) optimizedCountBuilder = this.applyOrganizationScope(optimizedCountBuilder, qualify('organization_id'), orgScope)\n }\n if (hasTenantColumn) {\n builder = builder.where(qualify('tenant_id'), opts.tenantId)\n if (optimizedCountBuilder) optimizedCountBuilder = optimizedCountBuilder.where(qualify('tenant_id'), opts.tenantId)\n }\n if (!opts.withDeleted && hasDeletedColumn) {\n builder = builder.whereNull(qualify('deleted_at'))\n if (optimizedCountBuilder) optimizedCountBuilder = optimizedCountBuilder.whereNull(qualify('deleted_at'))\n }\n\n const baseJoinParts: string[] = []\n baseJoinParts.push(`ei.entity_type = ${knex.raw('?', [entity]).toString()}`)\n baseJoinParts.push(`ei.entity_id = (${qualify('id')}::text)`)\n if (hasOrganizationColumn) {\n baseJoinParts.push(`ei.organization_id = ${qualify('organization_id')}`)\n baseJoinParts.push('ei.organization_id is not null')\n }\n if (hasTenantColumn) {\n baseJoinParts.push(`ei.tenant_id = ${qualify('tenant_id')}`)\n baseJoinParts.push('ei.tenant_id is not null')\n }\n if (!opts.withDeleted) baseJoinParts.push(`ei.deleted_at is null`)\n builder = builder.leftJoin({ ei: 'entity_indexes' }, knex.raw(baseJoinParts.join(' AND ')))\n\n const columns = await this.getBaseColumnsForEntity(entity)\n const indexSources: IndexDocSource[] = [{ alias: 'ei', entityId: entity, recordIdColumn: 'b.id' }]\n\n const shouldAttachCustomSources = Array.isArray(opts.customFieldSources) && opts.customFieldSources.length > 0 && (wantsCf || searchEnabled)\n if (shouldAttachCustomSources) {\n const prepared = this.prepareCustomFieldSources(knex, builder, opts.customFieldSources ?? [], qualify)\n builder = prepared.builder\n for (const source of prepared.sources) {\n const fragments: string[] = []\n fragments.push(`${source.indexAlias}.entity_type = ${knex.raw('?', [source.entityId]).toString()}`)\n fragments.push(`${source.indexAlias}.entity_id = (${knex.raw('??::text', [`${source.alias}.${source.recordIdColumn}`]).toString()})`)\n const orgExpr = source.organizationField\n ? knex.raw('??', [`${source.alias}.${source.organizationField}`]).toString()\n : (columns.has('organization_id') ? qualify('organization_id') : null)\n if (orgExpr) {\n fragments.push(`${source.indexAlias}.organization_id = ${orgExpr}`)\n fragments.push(`${source.indexAlias}.organization_id is not null`)\n }\n const tenantExpr = source.tenantField\n ? knex.raw('??', [`${source.alias}.${source.tenantField}`]).toString()\n : (columns.has('tenant_id') ? qualify('tenant_id') : null)\n if (tenantExpr) {\n fragments.push(`${source.indexAlias}.tenant_id = ${tenantExpr}`)\n fragments.push(`${source.indexAlias}.tenant_id is not null`)\n }\n if (!opts.withDeleted) fragments.push(`${source.indexAlias}.deleted_at is null`)\n builder = builder.leftJoin({ [source.indexAlias]: 'entity_indexes' }, knex.raw(fragments.join(' AND ')))\n indexSources.push({ alias: source.indexAlias, entityId: source.entityId, recordIdColumn: `${source.alias}.${source.recordIdColumn}` })\n }\n }\n\n if (debugEnabled) {\n this.debug('query:index-sources', {\n entity,\n sources: indexSources.map((src) => ({ alias: src.alias, entity: src.entityId })),\n })\n }\n\n const searchSources: SearchTokenSource[] = indexSources\n .map((src) => ({\n entity: String(src.entityId),\n recordIdColumn: src.recordIdColumn,\n }))\n .filter((src) => src.recordIdColumn && src.entity)\n const hasSearchTokens = searchEnabled && searchSources.length\n ? await this.searchSourcesHaveTokens(searchSources, opts.tenantId ?? null, orgScope)\n : false\n const searchRuntime: SearchRuntime = { ...searchRuntimeBase, searchSources, enabled: searchEnabled && hasSearchTokens }\n const searchFilters = normalizeFilters(opts.filters).filter((filter) => filter.op === 'like' || filter.op === 'ilike')\n if (searchFilters.length) {\n this.logSearchDebug('search:init', {\n entity,\n baseTable,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\n fields: searchFilters.map((filter) => String(filter.field)),\n searchEnabled,\n hasSearchTokens,\n searchSources,\n searchConfig: {\n enabled: searchConfig.enabled,\n minTokenLength: searchConfig.minTokenLength,\n enablePartials: searchConfig.enablePartials,\n hashAlgorithm: searchConfig.hashAlgorithm,\n blocklistedFields: searchConfig.blocklistedFields,\n },\n })\n if (!searchEnabled) {\n this.logSearchDebug('search:disabled', { entity, baseTable })\n } else if (!hasSearchTokens) {\n this.logSearchDebug('search:no-search-tokens', {\n entity,\n baseTable,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\n searchSources,\n })\n }\n }\n const hasNonBaseSearchSource = searchSources.some(\n (src) => src.entity !== String(entity) || src.recordIdColumn !== 'b.id'\n )\n if (hasNonBaseSearchSource) {\n optimizedCountBuilder = null\n }\n\n if (!partialIndexWarning && Array.isArray(opts.customFieldSources) && opts.customFieldSources.length > 0 && this.isForcePartialIndexEnabled()) {\n const seen = new Set<string>([entity])\n for (const source of opts.customFieldSources) {\n const targetEntity = source?.entityId ? String(source.entityId) : null\n if (!targetEntity || seen.has(targetEntity)) continue\n seen.add(targetEntity)\n const sourceHasCustomFields = await this.entityHasActiveCustomFields(targetEntity, opts.tenantId ?? null)\n if (!sourceHasCustomFields) {\n if (debugEnabled) this.debug('query:coverage:skip-no-custom-fields', { entity: targetEntity })\n continue\n }\n const sourceTable = source.table ?? resolveEntityTableName(this.em, targetEntity)\n try {\n const gap = await profiler.measure(\n 'resolve_coverage_gap',\n () => this.resolveCoverageGap(targetEntity, opts, coverageScope, sourceTable),\n (value) => (value\n ? {\n entity: targetEntity,\n scope: value.scope,\n baseCount: value.stats?.baseCount ?? null,\n indexedCount: value.stats?.indexedCount ?? null,\n }\n : { entity: targetEntity, scope: null })\n )\n if (!gap) continue\n if (!opts.skipAutoReindex) {\n this.scheduleAutoReindex(targetEntity, opts, gap.stats, coverageScope?.organizationId ?? null)\n }\n partialIndexWarning = {\n entity: targetEntity,\n entityLabel: this.resolveEntityLabel(targetEntity),\n baseCount: gap.stats?.baseCount ?? null,\n indexedCount: gap.stats?.indexedCount ?? null,\n scope: gap.stats ? gap.scope : undefined,\n }\n if (debugEnabled) {\n if (gap.stats) this.debug('query:partial-coverage:forced', { entity: targetEntity, baseCount: gap.stats.baseCount, indexedCount: gap.stats.indexedCount, scope: gap.scope })\n else this.debug('query:partial-coverage:forced', { entity: targetEntity })\n }\n break\n } catch (err) {\n if (debugEnabled) this.debug('query:partial-coverage:check-failed', { entity: targetEntity, error: err instanceof Error ? err.message : err })\n }\n }\n }\n\n if (\n !partialIndexWarning &&\n wantsCf &&\n entityHasActiveCustomFields &&\n this.isForcePartialIndexEnabled() &&\n opts.tenantId\n ) {\n try {\n await this.indexCoverageStats(entity, opts, coverageScope)\n const globalStats = await this.indexCoverageStats(entity, opts, coverageScope)\n if (globalStats) {\n const globalBase = globalStats.baseCount\n const globalIndexed = globalStats.indexedCount\n const globalGap = (globalBase > 0 && globalIndexed < globalBase) || globalIndexed > globalBase\n if (globalGap) {\n console.warn('[HybridQueryEngine] Partial index coverage detected at global scope; forcing query index usage due to FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES:', { entity, baseCount: globalBase, indexedCount: globalIndexed, scope: 'global' })\n if (debugEnabled) {\n this.debug('query:partial-coverage:forced', {\n entity,\n baseCount: globalBase,\n indexedCount: globalIndexed,\n scope: 'global',\n })\n }\n partialIndexWarning = {\n entity,\n entityLabel: this.resolveEntityLabel(entity),\n baseCount: globalBase,\n indexedCount: globalIndexed,\n scope: 'global',\n }\n }\n }\n } catch (err) {\n if (debugEnabled) {\n this.debug('query:partial-coverage:global-check-failed', {\n entity,\n error: err instanceof Error ? err.message : err,\n })\n }\n }\n }\n\n const resolveBaseColumn = (field: string): string | null => {\n if (columns.has(field)) return field\n if (field === 'organization_id' && columns.has('id')) return 'id'\n return null\n }\n\n for (const filter of cfFilters) {\n builder = this.applyCfFilterAcrossSources(\n knex,\n builder,\n filter.field,\n filter.op,\n filter.value,\n indexSources,\n searchRuntime\n )\n }\n\n for (const filter of baseFilters) {\n const baseField = resolveBaseColumn(String(filter.field))\n if (!baseField) continue\n const column = qualify(baseField)\n builder = this.applyColumnFilter(builder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: 'b.id',\n })\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyColumnFilter(optimizedCountBuilder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: 'b.id',\n })\n }\n }\n\n const applyAliasScopes = async (target: ResultBuilder, aliasName: string) => {\n const tableName = aliasTables.get(aliasName)\n if (!tableName) return\n if (orgScope && await this.columnExists(tableName, 'organization_id')) {\n this.applyOrganizationScope(target, `${aliasName}.organization_id`, orgScope)\n }\n if (opts.tenantId && await this.columnExists(tableName, 'tenant_id')) {\n target.where(`${aliasName}.tenant_id`, opts.tenantId)\n }\n if (!opts.withDeleted && await this.columnExists(tableName, 'deleted_at')) {\n target.whereNull(`${aliasName}.deleted_at`)\n }\n }\n\n const applyJoinFilterOp = (target: ResultBuilder, column: string, op: FilterOp, value?: unknown) => {\n switch (op) {\n case 'eq':\n target.where(column, value as Knex.Value)\n break\n case 'ne':\n target.whereNot(column, value as Knex.Value)\n break\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n target.where(column, operator, value as Knex.Value)\n break\n }\n case 'in':\n target.whereIn(column, this.toArray(value) as readonly Knex.Value[])\n break\n case 'nin':\n target.whereNotIn(column, this.toArray(value) as readonly Knex.Value[])\n break\n case 'like':\n target.where(column, 'like', value as Knex.Value)\n break\n case 'ilike':\n target.where(column, 'ilike', value as Knex.Value)\n break\n case 'exists':\n value ? target.whereNotNull(column) : target.whereNull(column)\n break\n }\n }\n\n await applyJoinFilters({\n knex,\n baseTable,\n builder,\n joinMap,\n joinFilters,\n aliasTables,\n qualifyBase: (column) => qualify(column),\n applyAliasScope: (target, alias) => applyAliasScopes(target, alias),\n applyFilterOp: (target, column, op, value) => applyJoinFilterOp(target as ResultBuilder, column, op, value),\n columnExists: (tbl, column) => this.columnExists(tbl, column),\n }) as ResultBuilder\n\n if (optimizedCountBuilder) {\n await applyJoinFilters({\n knex,\n baseTable,\n builder: optimizedCountBuilder,\n joinMap,\n joinFilters,\n aliasTables,\n qualifyBase: (column) => qualify(column),\n applyAliasScope: (target, alias) => applyAliasScopes(target, alias),\n applyFilterOp: (target, column, op, value) => applyJoinFilterOp(target as ResultBuilder, column, op, value),\n columnExists: (tbl, column) => this.columnExists(tbl, column),\n })\n }\n\n // When no fields specified, select all base table columns (like BasicQueryEngine does)\n const selectFieldSet = new Set<string>((opts.fields && opts.fields.length) ? opts.fields.map(String) : Array.from(columns.keys()))\n if (opts.includeCustomFields === true) {\n const entityIds = Array.from(new Set(indexSources.map((src) => String(src.entityId))))\n try {\n const resolvedKeys = await this.resolveAvailableCustomFieldKeys(entityIds, opts.tenantId ?? null)\n resolvedKeys.forEach((key) => selectFieldSet.add(`cf:${key}`))\n if (this.isDebugVerbosity()) {\n this.debug('query:cf:resolved-keys', { entity, keys: resolvedKeys })\n }\n } catch (err) {\n console.warn('[HybridQueryEngine] Failed to resolve custom field keys for', entity, err)\n }\n } else if (Array.isArray(opts.includeCustomFields)) {\n opts.includeCustomFields\n .map((key) => String(key))\n .forEach((key) => selectFieldSet.add(`cf:${key}`))\n }\n const selectFields = Array.from(selectFieldSet)\n for (const field of selectFields) {\n const fieldName = String(field)\n if (fieldName.startsWith('cf:')) {\n const alias = this.sanitize(fieldName)\n const { jsonSql } = this.buildCfExpressions(knex, fieldName, indexSources)\n const exprSql = jsonSql === 'NULL' ? 'NULL::jsonb' : jsonSql\n builder = builder.select(knex.raw(`${exprSql} as ??`, [alias]))\n } else if (columns.has(fieldName)) {\n builder = builder.select(knex.raw('?? as ??', [qualify(fieldName), fieldName]))\n }\n }\n\n for (const sort of opts.sort || []) {\n const fieldName = String(sort.field)\n if (fieldName.startsWith('cf:')) {\n const { textSql } = this.buildCfExpressions(knex, fieldName, indexSources)\n if (textSql !== 'NULL') {\n const direction = sort.dir ?? SortDir.Asc\n builder = builder.orderByRaw(`${textSql} ${direction}`)\n }\n } else {\n const baseField = resolveBaseColumn(fieldName)\n if (!baseField) continue\n builder = builder.orderBy(qualify(baseField), sort.dir ?? SortDir.Asc)\n }\n }\n\n const page = opts.page?.page ?? 1\n const pageSize = opts.page?.pageSize ?? 20\n\n const sqlDebugEnabled = this.isSqlDebugEnabled()\n let total: number\n\n if (optimizedCountBuilder) {\n const countSource = optimizedCountBuilder.clone().clearSelect().clearOrder().select(knex.raw(`${qualify('id')} as id`)).groupBy(qualify('id'))\n const countQuery = knex.from(countSource.as('sq')).count({ count: knex.raw('*') })\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = countQuery.clone().toSQL()\n this.debug('query:sql:count', { entity, sql, bindings })\n }\n const countRow = await this.captureSqlTiming(\n 'query:sql:count',\n entity,\n () => countQuery.first(),\n { optimized: true },\n profiler\n )\n total = this.parseCount(countRow)\n } else {\n const countBuilder = builder.clone().clearSelect().clearOrder().countDistinct(`${qualify('id')} as count`)\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = countBuilder.clone().toSQL()\n this.debug('query:sql:count', { entity, sql, bindings })\n }\n const countRow = await this.captureSqlTiming(\n 'query:sql:count',\n entity,\n () => countBuilder.first(),\n { optimized: false },\n profiler\n )\n total = this.parseCount(countRow)\n }\n\n const dataBuilder = builder.clone().limit(pageSize).offset((page - 1) * pageSize)\n\n if (debugEnabled && sqlDebugEnabled) {\n const { sql, bindings } = dataBuilder.clone().toSQL()\n this.debug('query:sql:data', { entity, sql, bindings, page, pageSize })\n }\n const itemsRaw = await this.captureSqlTiming(\n 'query:sql:data',\n entity,\n () => dataBuilder,\n { page, pageSize },\n profiler\n )\n if (debugEnabled) this.debug('query:complete', { entity, total, items: Array.isArray(itemsRaw) ? itemsRaw.length : 0 })\n\n let items = itemsRaw as any[]\n const encSvc = this.getEncryptionService()\n const dekKeyCache = new Map<string | null, string | null>()\n if (encSvc?.decryptEntityPayload) {\n const decrypt = encSvc.decryptEntityPayload.bind(encSvc) as (\n entityId: EntityId,\n payload: Record<string, unknown>,\n tenantId: string | null,\n organizationId: string | null,\n ) => Promise<Record<string, unknown>>\n items = await Promise.all(\n items.map(async (item) => {\n try {\n const decrypted = await decrypt(\n entity,\n item,\n item?.tenant_id ?? item?.tenantId ?? opts.tenantId ?? null,\n item?.organization_id ?? item?.organizationId ?? null,\n )\n return { ...item, ...decrypted }\n } catch (err) {\n console.error('Error decrypting entity payload', err);\n return item\n }\n })\n )\n }\n if (encSvc) {\n items = await Promise.all(\n items.map(async (item) => {\n try {\n return await decryptIndexDocCustomFields(\n item,\n {\n tenantId: item?.tenant_id ?? item?.tenantId ?? opts.tenantId ?? null,\n organizationId: item?.organization_id ?? item?.organizationId ?? null,\n },\n encSvc as any,\n dekKeyCache,\n )\n } catch {\n return item\n }\n }),\n )\n }\n\n const typedItems = items as unknown as T[]\n const result: QueryResult<T> = { items: typedItems, page, pageSize, total }\n if (partialIndexWarning) {\n result.meta = { partialIndexWarning }\n }\n finishProfile({\n result: 'ok',\n total,\n page,\n pageSize,\n itemCount: Array.isArray(items) ? items.length : undefined,\n partialIndexWarning: partialIndexWarning ? true : false,\n })\n return result\n } catch (err) {\n finishProfile({ result: 'error', error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }\n\n private getKnex(): Knex {\n const connection = this.em.getConnection()\n const withKnex = connection as { getKnex?: () => Knex }\n if (typeof withKnex.getKnex === 'function') {\n return withKnex.getKnex()\n }\n throw new Error('HybridQueryEngine requires a SQL connection that exposes getKnex()')\n }\n\n private prepareCustomFieldSources(\n knex: Knex,\n builder: ResultBuilder,\n sources: QueryCustomFieldSource[],\n qualify: (column: string) => string\n ): { builder: ResultBuilder; sources: PreparedCustomFieldSource[] } {\n let current = builder\n const prepared: PreparedCustomFieldSource[] = []\n sources.forEach((source, index) => {\n if (!source) return\n const joinTable = source.table ?? resolveEntityTableName(this.em, source.entityId)\n const alias = source.alias ?? `cfs_${index}`\n const join = source.join\n if (!join) {\n throw new Error(`QueryEngine: customFieldSources entry for ${String(source.entityId)} requires a join configuration`)\n }\n const joinArgs = { [alias]: joinTable }\n const joinCallback = function (this: Knex.JoinClause) {\n this.on(`${alias}.${join.toField}`, '=', qualify(join.fromField))\n }\n current = (join.type ?? 'left') === 'inner'\n ? current.join(joinArgs, joinCallback)\n : current.leftJoin(joinArgs, joinCallback)\n prepared.push({\n alias,\n indexAlias: `ei_${alias}`,\n entityId: source.entityId,\n recordIdColumn: source.recordIdColumn ?? 'id',\n organizationField: source.organizationField,\n tenantField: source.tenantField,\n table: joinTable,\n })\n })\n return { builder: current, sources: prepared }\n }\n\n private async isCustomEntity(entity: string): Promise<boolean> {\n try {\n const knex = this.getKnex()\n const row = await knex('custom_entities').where({ entity_id: entity, is_active: true }).first()\n return !!row\n } catch {\n return false\n }\n }\n\n private applySearchTokens<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n opts: {\n knex: Knex\n entity: string\n field: string\n hashes: string[]\n recordIdColumn: string\n tenantId?: string | null\n organizationScope?: { ids: string[]; includeNull: boolean } | null\n combineWith?: 'and' | 'or'\n }\n ): boolean {\n if (!opts.hashes.length) {\n this.logSearchDebug('search:skip-no-hashes', {\n entity: opts.entity,\n field: opts.field,\n tenantId: opts.tenantId ?? null,\n organizationScope: opts.organizationScope,\n })\n return false\n }\n const alias = `st_${this.searchAliasSeq++}`\n const combineWith = opts.combineWith === 'or' ? 'orWhereExists' : 'whereExists'\n const engine = this\n this.logSearchDebug('search:apply-search-tokens', {\n entity: opts.entity,\n field: opts.field,\n alias,\n tokenCount: opts.hashes.length,\n tenantId: opts.tenantId ?? null,\n organizationScope: opts.organizationScope,\n combineWith: opts.combineWith ?? 'and',\n })\n ;(q as any)[combineWith](function (this: Knex.QueryBuilder) {\n this.select(1)\n .from({ [alias]: 'search_tokens' })\n .where(`${alias}.entity_type`, opts.entity)\n .andWhere(`${alias}.field`, opts.field)\n .andWhereRaw('?? = ??::text', [`${alias}.entity_id`, opts.recordIdColumn])\n .whereIn(`${alias}.token_hash`, opts.hashes)\n .groupBy(`${alias}.entity_id`, `${alias}.field`)\n .havingRaw(`count(distinct ${alias}.token_hash) >= ?`, [opts.hashes.length])\n if (opts.tenantId !== undefined) {\n this.andWhereRaw(`${alias}.tenant_id is not distinct from ?`, [opts.tenantId ?? null])\n }\n if (opts.organizationScope) {\n engine.applyOrganizationScope(this as any, `${alias}.organization_id`, opts.organizationScope)\n }\n })\n return true\n }\n\n private jsonbRawAlias(knex: Knex, alias: string, key: string): Knex.Raw {\n // Prefer cf:<key> but fall back to bare <key> for legacy docs\n if (key.startsWith('cf:')) {\n const bare = key.slice(3)\n return knex.raw(`coalesce(${alias}.doc -> ?, ${alias}.doc -> ?)`, [key, bare])\n }\n return knex.raw(`${alias}.doc -> ?`, [key])\n }\n private cfTextExprAlias(knex: Knex, alias: string, key: string): Knex.Raw {\n if (key.startsWith('cf:')) {\n const bare = key.slice(3)\n return knex.raw(`coalesce((${alias}.doc ->> ?), (${alias}.doc ->> ?))`, [key, bare])\n }\n return knex.raw(`(${alias}.doc ->> ?)`, [key])\n }\n private buildCfExpressions(knex: Knex, key: string, sources: IndexDocSource[]): { jsonSql: string; textSql: string } {\n if (!sources.length) return { jsonSql: 'NULL', textSql: 'NULL' }\n const jsonFragments = sources.map((source) => this.jsonbRawAlias(knex, source.alias, key).toString())\n const textFragments = sources.map((source) => this.cfTextExprAlias(knex, source.alias, key).toString())\n const jsonSql = jsonFragments.length === 1 ? jsonFragments[0] : `coalesce(${jsonFragments.join(', ')})`\n const textSql = textFragments.length === 1 ? textFragments[0] : `coalesce(${textFragments.join(', ')})`\n return { jsonSql, textSql }\n }\n\n private applyCfFilterAcrossSources(\n knex: Knex,\n builder: ResultBuilder,\n key: string,\n op: FilterOp,\n value: unknown,\n sources: IndexDocSource[],\n search?: SearchRuntime\n ): ResultBuilder {\n if (!sources.length) return builder\n if ((op === 'like' || op === 'ilike') && search?.enabled && typeof value === 'string') {\n const tokens = tokenizeText(String(value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n let applied = false\n if (sources.length) {\n builder = builder.where((qb) => {\n sources.forEach((source, idx) => {\n const ok = this.applySearchTokens(qb as any, {\n knex,\n entity: source.entityId,\n field: key,\n hashes,\n recordIdColumn: `${source.alias}.entity_id`,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n combineWith: idx === 0 ? 'and' : 'or',\n })\n if (ok) applied = true\n })\n })\n }\n this.logSearchDebug('search:cf-filter-across', {\n entity: sources.map((src) => src.entityId),\n field: key,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n })\n if (applied) return builder\n } else {\n this.logSearchDebug('search:cf-skip-empty-hashes', {\n entity: sources.map((src) => src.entityId),\n field: key,\n value,\n })\n }\n return builder\n }\n const { jsonSql, textSql } = this.buildCfExpressions(knex, key, sources)\n if (jsonSql === 'NULL' || textSql === 'NULL') return builder\n const textExpr = knex.raw(textSql)\n const arrContains = (val: unknown) => knex.raw(`${jsonSql} @> ?::jsonb`, [JSON.stringify([val])])\n switch (op) {\n case 'eq':\n return builder.where((qb) => {\n qb.orWhere(textExpr, '=', value as Knex.Value)\n qb.orWhere(arrContains(value))\n })\n case 'ne':\n return builder.whereNot(textExpr, '=', value as Knex.Value)\n case 'in': {\n const values = this.toArray(value)\n return builder.where((qb) => {\n values.forEach((val) => {\n qb.orWhere(textExpr, '=', val as Knex.Value)\n qb.orWhere(arrContains(val))\n })\n })\n }\n case 'nin': {\n const values = this.toArray(value) as readonly Knex.Value[]\n return builder.whereNotIn(textExpr as any, values as any)\n }\n case 'like':\n return builder.where(textExpr, 'like', value as Knex.Value)\n case 'ilike':\n return builder.where(textExpr, 'ilike', value as Knex.Value)\n case 'exists':\n return value\n ? builder.whereRaw(`${textExpr.toString()} is not null`)\n : builder.whereRaw(`${textExpr.toString()} is null`)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n return builder.where(textExpr, operator, value as Knex.Value)\n }\n default:\n return builder\n }\n }\n\n private applyCfFilterFromAlias(\n knex: Knex,\n q: ResultBuilder,\n alias: string,\n entityType: string,\n key: string,\n op: FilterOp,\n value: unknown,\n search?: SearchRuntime\n ): ResultBuilder {\n const text = this.cfTextExprAlias(knex, alias, key)\n const arrExpr = knex.raw(`(${alias}.doc -> ?)`, [key])\n const arrContains = (val: unknown) => knex.raw(`${arrExpr.toString()} @> ?::jsonb`, [JSON.stringify([val])])\n if ((op === 'like' || op === 'ilike') && search?.enabled && typeof value === 'string') {\n const tokens = tokenizeText(String(value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n const applied = this.applySearchTokens(q, {\n knex,\n entity: entityType,\n field: key,\n hashes,\n recordIdColumn: `${alias}.entity_id`,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n })\n this.logSearchDebug('search:cf-filter', {\n entity: entityType,\n field: key,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n })\n if (applied) return q\n } else {\n this.logSearchDebug('search:cf-skip-empty-hashes', {\n entity: entityType,\n field: key,\n value,\n })\n }\n return q\n }\n switch (op) {\n case 'eq':\n return q.where((builder) => {\n builder.orWhere(text, '=', value as Knex.Value)\n builder.orWhere(arrContains(value))\n })\n case 'ne':\n return q.whereNot(text, '=', value as Knex.Value)\n case 'in': {\n const vals = this.toArray(value)\n return q.where((builder) => {\n vals.forEach((val) => {\n builder.orWhere(text, '=', val as Knex.Value)\n builder.orWhere(arrContains(val))\n })\n })\n }\n case 'nin': {\n const vals = this.toArray(value) as readonly Knex.Value[]\n return q.whereNotIn(text as any, vals as any)\n }\n case 'like':\n return q.where(text, 'like', value as Knex.Value)\n case 'ilike':\n return q.where(text, 'ilike', value as Knex.Value)\n case 'exists':\n return value\n ? q.whereRaw(`${text.toString()} is not null`)\n : q.whereRaw(`${text.toString()} is null`)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = op === 'gt' ? '>' : op === 'gte' ? '>=' : op === 'lt' ? '<' : '<='\n return q.where(text, operator, value as Knex.Value)\n }\n default:\n return q\n }\n }\n\n private async queryCustomEntity<T = unknown>(entity: string, opts: QueryOptions = {}): Promise<QueryResult<T>> {\n const knex = this.getKnex()\n const alias = 'ce'\n let q = knex({ [alias]: 'custom_entities_storage' }).where(`${alias}.entity_type`, entity)\n\n const orgScope = this.resolveOrganizationScope(opts)\n\n // Require tenant scope; custom entities are tenant-scoped only\n if (!opts.tenantId) throw new Error('QueryEngine: tenantId is required')\n q = q.andWhere(`${alias}.tenant_id`, opts.tenantId)\n if (orgScope) {\n q = this.applyOrganizationScope(q, `${alias}.organization_id`, orgScope)\n }\n if (!opts.withDeleted) q = q.whereNull(`${alias}.deleted_at`)\n const searchConfig = resolveSearchConfig()\n const searchEnabled = searchConfig.enabled && await this.tableExists('search_tokens')\n const hasSearchTokens = searchEnabled\n ? await this.hasSearchTokens(entity, opts.tenantId ?? null, orgScope)\n : false\n const searchRuntime: SearchRuntime = {\n enabled: searchEnabled && hasSearchTokens,\n config: searchConfig,\n organizationScope: orgScope,\n tenantId: opts.tenantId ?? null,\n }\n\n const normalizedFilters = normalizeFilters(opts.filters)\n\n // Apply filters: cf:* via JSONB; other keys: special-case id/created_at/updated_at/deleted_at, otherwise from doc\n for (const filter of normalizedFilters) {\n if (filter.field.startsWith('cf:')) {\n q = this.applyCfFilterFromAlias(knex, q, alias, entity, filter.field, filter.op, filter.value, searchRuntime)\n continue\n }\n const column = this.resolveCustomEntityColumn(alias, String(filter.field))\n if (column) {\n q = this.applyColumnFilter(q, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: `${alias}.entity_id`,\n })\n continue\n }\n const docExpr = knex.raw(`(${alias}.doc ->> ?)`, [String(filter.field)])\n q = this.applyColumnFilter(q, docExpr, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: String(filter.field),\n recordIdColumn: `${alias}.entity_id`,\n })\n }\n\n // Determine CFs and l10n keys to include\n const cfKeys = new Set<string>()\n for (const f of (opts.fields || [])) {\n if (typeof f === 'string' && f.startsWith('cf:')) cfKeys.add(f.slice(3))\n else if (typeof f === 'string' && f.startsWith('l10n:')) cfKeys.add(f)\n }\n for (const filter of normalizedFilters) {\n if (typeof filter.field === 'string' && filter.field.startsWith('cf:')) cfKeys.add(filter.field.slice(3))\n else if (typeof filter.field === 'string' && filter.field.startsWith('l10n:')) cfKeys.add(filter.field)\n }\n if (opts.includeCustomFields === true) {\n try {\n const rows = await knex('custom_field_defs')\n .select('key')\n .where({ entity_id: entity, is_active: true })\n .modify((qb) => {\n qb.andWhere({ tenant_id: opts.tenantId })\n // NOTE: organization-level scoping intentionally disabled for custom fields\n // if (opts.organizationId != null) qb.andWhere((b: any) => b.where({ organization_id: opts.organizationId }).orWhereNull('organization_id'))\n // else qb.whereNull('organization_id')\n })\n for (const row of rows) {\n const key = (row as Record<string, unknown>).key\n if (typeof key === 'string') {\n cfKeys.add(key)\n } else if (key != null) {\n cfKeys.add(String(key))\n }\n }\n } catch {\n // ignore and fall back to whatever keys we already have\n }\n } else if (Array.isArray(opts.includeCustomFields)) {\n for (const k of opts.includeCustomFields) cfKeys.add(k)\n }\n\n // Selection\n const requested = (opts.fields && opts.fields.length) ? opts.fields : ['id']\n for (const field of requested) {\n const f = String(field)\n if (f.startsWith('cf:')) {\n const aliasName = this.sanitize(f)\n const expr = this.jsonbRawAlias(knex, alias, f)\n q = q.select({ [aliasName]: expr })\n } else if (f === 'id') {\n q = q.select(knex.raw(`${alias}.entity_id as ??`, ['id']))\n } else if (f === 'created_at' || f === 'updated_at' || f === 'deleted_at') {\n q = q.select(knex.raw(`${alias}.?? as ??`, [f, f]))\n } else {\n // Non-cf from doc\n const expr = knex.raw(`(${alias}.doc ->> ?)`, [f])\n q = q.select({ [f]: expr })\n }\n }\n // Ensure CFs necessary for sort are selected\n const cfSelectedAliases: string[] = []\n for (const key of cfKeys) {\n const aliasName = this.sanitize(`cf:${key}`)\n const expr = this.jsonbRawAlias(knex, alias, `cf:${key}`)\n q = q.select({ [aliasName]: expr })\n cfSelectedAliases.push(aliasName)\n }\n\n // Sorting\n for (const s of opts.sort || []) {\n if (s.field.startsWith('cf:')) {\n const key = s.field.slice(3)\n const aliasName = this.sanitize(`cf:${key}`)\n if (!cfSelectedAliases.includes(aliasName)) {\n const expr = this.jsonbRawAlias(knex, alias, `cf:${key}`)\n q = q.select({ [aliasName]: expr })\n cfSelectedAliases.push(aliasName)\n }\n q = q.orderBy(aliasName, s.dir ?? SortDir.Asc)\n } else if (s.field === 'id') {\n q = q.orderBy(`${alias}.entity_id`, s.dir ?? SortDir.Asc)\n } else if (s.field === 'created_at' || s.field === 'updated_at' || s.field === 'deleted_at') {\n q = q.orderBy(`${alias}.${s.field}`, s.dir ?? SortDir.Asc)\n } else {\n const direction = s.dir ?? SortDir.Asc\n q = q.orderByRaw(`(${alias}.doc ->> ?) ${direction}`, [s.field])\n }\n }\n\n // Pagination + totals\n const page = opts.page?.page ?? 1\n const pageSize = opts.page?.pageSize ?? 20\n const countClone = q.clone()\n if (typeof countClone.clearSelect === 'function') countClone.clearSelect()\n if (typeof countClone.clearOrder === 'function') countClone.clearOrder()\n const countRow = await countClone.countDistinct(`${alias}.entity_id as count`).first()\n const total = this.parseCount(countRow)\n const items = await q.limit(pageSize).offset((page - 1) * pageSize)\n return { items, page, pageSize, total }\n }\n\n private async tableExists(table: string): Promise<boolean> {\n const knex = this.getKnex()\n const exists = await knex('information_schema.tables').where({ table_name: table }).first()\n return !!exists\n }\n\n private async hasSearchTokens(\n entity: string,\n tenantId: string | null,\n orgScope?: { ids: string[]; includeNull: boolean } | null\n ): Promise<boolean> {\n try {\n const knex = this.getKnex()\n const query = knex('search_tokens').select(1).where('entity_type', entity).limit(1)\n if (tenantId !== undefined) {\n query.andWhereRaw('tenant_id is not distinct from ?', [tenantId])\n }\n if (orgScope) {\n this.applyOrganizationScope(query as any, 'search_tokens.organization_id', orgScope)\n }\n const row = await query.first()\n return !!row\n } catch (err) {\n this.logSearchDebug('search:has-tokens-error', {\n entity,\n tenantId,\n organizationScope: orgScope,\n error: err instanceof Error ? err.message : String(err),\n })\n return false\n }\n }\n\n private async searchSourcesHaveTokens(\n sources: SearchTokenSource[],\n tenantId: string | null,\n orgScope?: { ids: string[]; includeNull: boolean } | null\n ): Promise<boolean> {\n for (const source of sources) {\n const ok = await this.hasSearchTokens(source.entity, tenantId, orgScope)\n this.logSearchDebug('search:source-has-tokens', {\n entity: source.entity,\n recordIdColumn: source.recordIdColumn,\n tenantId,\n organizationScope: orgScope,\n hasTokens: ok,\n })\n if (ok) return true\n }\n return false\n }\n\n private async resolveAvailableCustomFieldKeys(entityIds: string[], tenantId: string | null): Promise<string[]> {\n if (!entityIds.length) return []\n const cacheKey = this.customFieldKeysCacheKey(entityIds, tenantId)\n const now = Date.now()\n const cached = this.customFieldKeysCache.get(cacheKey)\n if (cached && cached.expiresAt > now) {\n return cached.value.slice()\n }\n\n const knex = this.getKnex()\n const rows = await knex('custom_field_defs')\n .select('key')\n .whereIn('entity_id', entityIds)\n .andWhere('is_active', true)\n .modify((qb: any) => {\n qb.andWhere((inner: any) => {\n inner.where({ tenant_id: tenantId }).orWhereNull('tenant_id')\n })\n })\n const keys = new Set<string>()\n for (const row of rows || []) {\n const key = (row as Record<string, unknown>).key\n if (typeof key === 'string' && key.trim().length) keys.add(key.trim())\n else if (key != null) keys.add(String(key))\n }\n const result = Array.from(keys)\n if (this.customFieldKeysTtlMs > 0) {\n this.customFieldKeysCache.set(cacheKey, { expiresAt: now + this.customFieldKeysTtlMs, value: result })\n }\n return result.slice()\n }\n\n private async entityHasActiveCustomFields(entityId: string, tenantId: string | null): Promise<boolean> {\n try {\n const keys = await this.resolveAvailableCustomFieldKeys([entityId], tenantId)\n return keys.length > 0\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('query:cf:check-error', {\n entity: entityId,\n tenantId: tenantId ?? null,\n error: err instanceof Error ? err.message : err,\n })\n }\n return true\n }\n }\n\n private customFieldKeysCacheKey(entityIds: string[], tenantId: string | null): string {\n const sorted = entityIds.slice().sort().join(',')\n return `${tenantId ?? '__none__'}|${sorted}`\n }\n\n private resolveVectorService(): VectorIndexService | null {\n if (!this.vectorServiceResolver) return null\n try {\n return this.vectorServiceResolver() ?? null\n } catch {\n return null\n }\n }\n\n private resolveEntityLabel(entity: string): string {\n return entity\n }\n\n private async indexAnyRows(entity: string): Promise<boolean> {\n const knex = this.getKnex()\n // Prefer coverage snapshots \u2013 cheap and already scoped by maintenance jobs.\n const coverage = await knex('entity_index_coverage')\n .select(1)\n .where('entity_type', entity)\n .where('indexed_count', '>', 0)\n .first()\n if (coverage) return true\n const exists = await knex('entity_indexes').select('entity_id').where({ entity_type: entity }).first()\n return !!exists\n }\n private async getStoredCoverageSnapshot(\n entity: string,\n tenantId: string | null,\n organizationId: string | null,\n withDeleted: boolean\n ): Promise<{ baseCount: number; indexedCount: number } | null> {\n try {\n if (!this.isCoverageOptimizationEnabled()) {\n await refreshCoverageSnapshot(\n this.em,\n {\n entityType: entity,\n tenantId,\n organizationId,\n withDeleted,\n },\n )\n }\n const knex = this.getKnex()\n const row = await readCoverageSnapshot(knex, {\n entityType: entity,\n tenantId,\n organizationId,\n withDeleted,\n })\n if (!row) return null\n return { baseCount: row.baseCount, indexedCount: row.indexedCount }\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('coverage:snapshot:read-error', {\n entity,\n tenantId,\n organizationId,\n withDeleted,\n error: err instanceof Error ? err.message : err,\n })\n }\n return null\n }\n }\n\n private scheduleAutoReindex(\n entity: string,\n opts: QueryOptions,\n stats?: { baseCount: number; indexedCount: number },\n organizationIdOverride?: string | null\n ) {\n if (!this.isAutoReindexEnabled()) return\n\n const bus = this.resolveEventBus()\n if (!bus) return\n const payload = {\n entityType: entity,\n tenantId: opts.tenantId ?? null,\n organizationId: organizationIdOverride ?? opts.organizationId ?? null,\n force: false,\n }\n const context = stats\n ? {\n entity,\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n baseCount: stats.baseCount,\n indexedCount: stats.indexedCount,\n }\n : { entity, tenantId: payload.tenantId, organizationId: payload.organizationId }\n\n void Promise.resolve()\n .then(async () => {\n try {\n await bus.emitEvent('query_index.reindex', payload, { persistent: true })\n if (this.isDebugVerbosity()) this.debug('query:auto-reindex:scheduled', context)\n } catch (err) {\n console.warn('[HybridQueryEngine] Failed to schedule auto reindex:', {\n ...context,\n error: err instanceof Error ? err.message : err,\n })\n }\n })\n }\n\n private scheduleCoverageRefresh(\n entity: string,\n tenantId: string | null | undefined,\n organizationId: string | null | undefined,\n withDeleted: boolean\n ): void {\n const bus = this.resolveEventBus()\n if (!bus) return\n const key = [\n entity,\n tenantId ?? '__tenant__',\n organizationId ?? '__org__',\n withDeleted ? '1' : '0',\n ].join('|')\n if (this.pendingCoverageRefreshKeys.has(key)) return\n this.pendingCoverageRefreshKeys.add(key)\n void Promise.resolve()\n .then(async () => {\n try {\n await bus.emitEvent('query_index.coverage.refresh', {\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n delayMs: 0,\n })\n if (this.isDebugVerbosity()) {\n this.debug('coverage:refresh:scheduled', {\n entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n })\n }\n } catch (err) {\n if (this.isDebugVerbosity()) {\n this.debug('coverage:refresh:failed', {\n entity,\n tenantId: tenantId ?? null,\n organizationId: organizationId ?? null,\n withDeleted,\n error: err instanceof Error ? err.message : err,\n })\n }\n }\n })\n .finally(() => {\n this.pendingCoverageRefreshKeys.delete(key)\n })\n }\n\n private resolveEventBus(): Pick<EventBus, 'emitEvent'> | null {\n if (!this.eventBusResolver) return null\n try {\n const bus = this.eventBusResolver()\n return bus ?? null\n } catch {\n return null\n }\n }\n\n private isAutoReindexEnabled(): boolean {\n if (this.autoReindexEnabled != null) return this.autoReindexEnabled\n const raw = (\n process.env.SCHEDULE_AUTO_REINDEX ??\n process.env.QUERY_INDEX_AUTO_REINDEX ??\n ''\n )\n .trim()\n .toLowerCase()\n if (!raw) {\n this.autoReindexEnabled = true\n return true\n }\n const parsed = parseBooleanToken(raw)\n this.autoReindexEnabled = parsed === null ? true : parsed\n return this.autoReindexEnabled\n }\n\n private isCoverageOptimizationEnabled(): boolean {\n if (this.coverageOptimizationEnabled != null) return this.coverageOptimizationEnabled\n const raw = (process.env.OPTIMIZE_INDEX_COVERAGE_STATS ?? '').trim().toLowerCase()\n if (!raw) {\n this.coverageOptimizationEnabled = false\n return false\n }\n this.coverageOptimizationEnabled = parseBooleanToken(raw) === true\n return this.coverageOptimizationEnabled\n }\n\n private async columnExists(table: string, column: string): Promise<boolean> {\n const key = `${table}.${column}`\n if (this.columnCache.has(key)) {\n const cached = this.columnCache.get(key)\n if (cached === true) return true\n this.columnCache.delete(key)\n }\n const knex = this.getKnex()\n const exists = await knex('information_schema.columns')\n .where({ table_name: table, column_name: column })\n .first()\n const present = !!exists\n if (present) this.columnCache.set(key, true)\n else this.columnCache.delete(key)\n return present\n }\n\n private async getBaseColumnsForEntity(entity: string): Promise<Map<string, string>> {\n const knex = this.getKnex()\n const table = resolveEntityTableName(this.em, entity)\n const rows = await knex('information_schema.columns')\n .select('column_name', 'data_type')\n .where({ table_name: table })\n const map = new Map<string, string>()\n for (const r of rows) map.set(r.column_name, r.data_type)\n return map\n }\n\n private resolveOrganizationScope(opts: QueryOptions): { ids: string[]; includeNull: boolean } | null {\n if (opts.organizationIds !== undefined) {\n const raw = (opts.organizationIds ?? []).map((id) => (typeof id === 'string' ? id.trim() : id))\n const includeNull = raw.some((id) => id == null || id === '')\n const ids = raw.filter((id): id is string => typeof id === 'string' && id.length > 0)\n const unique = Array.from(new Set(ids))\n return { ids: unique, includeNull }\n }\n if (typeof opts.organizationId === 'string' && opts.organizationId.trim().length > 0) {\n return { ids: [opts.organizationId], includeNull: false }\n }\n return null\n }\n\n private resolveCoverageSnapshotScope(\n opts: QueryOptions\n ): { tenantId: string | null; organizationId: string | null } | null {\n const tenantId = opts.tenantId ?? null\n const orgScope = this.resolveOrganizationScope(opts)\n if (!orgScope) return { tenantId, organizationId: null }\n if (orgScope.includeNull) {\n if (orgScope.ids.length === 0) return { tenantId, organizationId: null }\n return null\n }\n if (orgScope.ids.length === 1) return { tenantId, organizationId: orgScope.ids[0] }\n if (orgScope.ids.length === 0) return { tenantId, organizationId: null }\n return null\n }\n\n private applyOrganizationScope<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n column: string,\n scope: { ids: string[]; includeNull: boolean }\n ): Knex.QueryBuilder<TRecord, TResult> {\n if (scope.ids.length === 0 && !scope.includeNull) {\n return q.whereRaw('1 = 0')\n }\n return q.where((builder) => {\n let applied = false\n if (scope.ids.length > 0) {\n builder.whereIn(column, scope.ids as readonly string[])\n applied = true\n }\n if (scope.includeNull) {\n if (applied) builder.orWhereNull(column)\n else builder.whereNull(column)\n } else if (!applied) {\n builder.whereRaw('1 = 0')\n }\n })\n }\n\n private normalizeFilters(filters?: QueryOptions['filters']): NormalizedFilter[] {\n if (!filters) return []\n const normalizeField = (k: string) => k.startsWith('cf_') ? `cf:${k.slice(3)}` : k\n if (Array.isArray(filters)) {\n return (filters as Filter[]).map((filter) => ({\n field: normalizeField(String(filter.field)),\n op: filter.op,\n value: filter.value,\n }))\n }\n const out: NormalizedFilter[] = []\n const obj = filters as Record<string, unknown>\n const add = (field: string, op: FilterOp, value?: unknown) => out.push({ field, op, value })\n for (const [rawKey, rawVal] of Object.entries(obj)) {\n const field = normalizeField(rawKey)\n if (rawVal !== null && typeof rawVal === 'object' && !Array.isArray(rawVal)) {\n for (const [opKey, opVal] of Object.entries(rawVal as Record<string, unknown>)) {\n switch (opKey) {\n case '$eq': add(field, 'eq', opVal); break\n case '$ne': add(field, 'ne', opVal); break\n case '$gt': add(field, 'gt', opVal); break\n case '$gte': add(field, 'gte', opVal); break\n case '$lt': add(field, 'lt', opVal); break\n case '$lte': add(field, 'lte', opVal); break\n case '$in': add(field, 'in', opVal); break\n case '$nin': add(field, 'nin', opVal); break\n case '$like': add(field, 'like', opVal); break\n case '$ilike': add(field, 'ilike', opVal); break\n case '$exists': add(field, 'exists', opVal); break\n }\n }\n } else {\n add(field, 'eq', rawVal)\n }\n }\n return out\n }\n\n private sanitize(s: string): string {\n return s.replace(/[^a-zA-Z0-9_]/g, '_')\n }\n\n private toArray(value: unknown): readonly unknown[] {\n if (Array.isArray(value)) {\n return value\n }\n if (value === undefined) {\n return []\n }\n return [value]\n }\n\n private parseCount(row: unknown): number {\n if (row && typeof row === 'object' && 'count' in row) {\n const value = (row as { count: unknown }).count\n if (typeof value === 'number') return value\n if (typeof value === 'string') {\n const parsed = Number(value)\n return Number.isNaN(parsed) ? 0 : parsed\n }\n }\n return 0\n }\n\n private logSearchDebug(event: string, payload: Record<string, unknown>) {\n if (!this.isDebugVerbosity()) return\n try {\n console.info('[query-index:search]', event, JSON.stringify(payload))\n } catch {\n console.info('[query-index:search]', event, payload)\n }\n }\n\n private applyColumnFilter<TRecord extends ResultRow, TResult>(\n q: Knex.QueryBuilder<TRecord, TResult>,\n column: string | Knex.Raw,\n filter: NormalizedFilter,\n search?: SearchRuntime & { knex: Knex; entity: string; field: string; recordIdColumn?: string }\n ): Knex.QueryBuilder<TRecord, TResult> {\n if (\n (filter.op === 'like' || filter.op === 'ilike') &&\n search?.enabled &&\n typeof filter.value === 'string'\n ) {\n const tokens = tokenizeText(String(filter.value), search.config)\n const hashes = tokens.hashes\n if (hashes.length) {\n const sources: SearchTokenSource[] = (search.searchSources && search.searchSources.length\n ? search.searchSources\n : [{ entity: search.entity, recordIdColumn: search.recordIdColumn ?? '' }]\n ).filter((src) => src.recordIdColumn && src.entity)\n let applied = false\n if (sources.length) {\n q = q.where((qb) => {\n sources.forEach((src, idx) => {\n const ok = this.applySearchTokens(qb as any, {\n knex: search.knex,\n entity: src.entity,\n field: search.field,\n hashes,\n recordIdColumn: src.recordIdColumn,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n combineWith: idx === 0 ? 'and' : 'or',\n })\n if (ok) applied = true\n })\n })\n }\n this.logSearchDebug('search:filter', {\n entity: search.entity,\n field: search.field,\n tokens: tokens.tokens,\n hashes,\n applied,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope,\n sources: sources.map((src) => ({ entity: src.entity, recordIdColumn: src.recordIdColumn })),\n })\n if (applied) return q\n } else {\n this.logSearchDebug('search:skip-empty-hashes', {\n entity: search.entity,\n field: search.field,\n value: filter.value,\n })\n }\n return q\n }\n const col = column as any\n switch (filter.op) {\n case 'eq':\n return q.where(col, filter.value as Knex.Value)\n case 'ne':\n return q.whereNot(col, filter.value as Knex.Value)\n case 'gt':\n case 'gte':\n case 'lt':\n case 'lte': {\n const operator = filter.op === 'gt' ? '>' : filter.op === 'gte' ? '>=' : filter.op === 'lt' ? '<' : '<='\n return q.where(col, operator, filter.value as Knex.Value)\n }\n case 'in': {\n const values = this.toArray(filter.value) as readonly Knex.Value[]\n return q.whereIn(col, values)\n }\n case 'nin': {\n const values = this.toArray(filter.value) as readonly Knex.Value[]\n return q.whereNotIn(col, values)\n }\n case 'like':\n return q.where(col, 'like', filter.value as Knex.Value)\n case 'ilike':\n return q.where(col, 'ilike', filter.value as Knex.Value)\n case 'exists':\n return filter.value ? q.whereNotNull(col) : q.whereNull(col)\n default:\n return q\n }\n }\n\n private resolveCustomEntityColumn(alias: string, field: string): string | null {\n if (field === 'id') return `${alias}.entity_id`\n if (field === 'organization_id' || field === 'organizationId') return `${alias}.organization_id`\n if (field === 'tenant_id' || field === 'tenantId') return `${alias}.tenant_id`\n if (field === 'created_at' || field === 'updated_at' || field === 'deleted_at') return `${alias}.${field}`\n return null\n }\n\n private isDebugVerbosity(): boolean {\n if (this.debugVerbosity != null) return this.debugVerbosity\n this.debugVerbosity = resolveDebugVerbosity()\n return this.debugVerbosity\n }\n\n private isSqlDebugEnabled(): boolean {\n if (this.sqlDebugEnabled != null) return this.sqlDebugEnabled\n this.sqlDebugEnabled = resolveBooleanEnv(['QUERY_ENGINE_DEBUG_SQL'], false)\n return this.sqlDebugEnabled\n }\n\n private isForcePartialIndexEnabled(): boolean {\n if (this.forcePartialIndexEnabled != null) return this.forcePartialIndexEnabled\n this.forcePartialIndexEnabled = resolveBooleanEnv(['FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES'], true)\n return this.forcePartialIndexEnabled\n }\n\n private async resolveCoverageGap(\n entity: string,\n opts: QueryOptions,\n coverageScope?: { tenantId: string | null; organizationId: string | null } | null,\n _sourceTable?: string\n ): Promise<{ stats?: { baseCount: number; indexedCount: number }; scope: 'scoped' | 'global' } | null> {\n const scope = coverageScope ?? this.resolveCoverageSnapshotScope(opts)\n if (!scope) return null\n const tenantId = scope.tenantId\n const organizationId = scope.organizationId\n const withDeleted = !!opts.withDeleted\n\n const snapshot = await this.getStoredCoverageSnapshot(entity, tenantId, organizationId, withDeleted)\n if (!snapshot) {\n this.scheduleCoverageRefresh(entity, tenantId, organizationId, withDeleted)\n return { stats: undefined, scope: 'scoped' }\n }\n\n const baseCount = snapshot.baseCount\n const indexCount = snapshot.indexedCount\n const hasGap = baseCount > 0 && indexCount < baseCount\n if (hasGap || indexCount > baseCount) {\n return { stats: snapshot, scope: 'scoped' }\n }\n\n return null\n }\n\n // Backward-compatible hook for tests that mock coverage stats\n private async indexCoverageStats(\n entity: string,\n opts: QueryOptions,\n coverageScope?: { tenantId: string | null; organizationId: string | null } | null,\n ): Promise<{ baseCount: number; indexedCount: number } | null> {\n const gap = await this.resolveCoverageGap(entity, opts, coverageScope)\n return gap?.stats ?? null\n }\n\n private async captureSqlTiming<TResult>(\n label: string,\n entity: EntityId,\n execute: () => Promise<TResult> | TResult,\n extra?: Record<string, unknown>,\n profiler?: Profiler\n ): Promise<TResult> {\n const shouldDebug = this.isSqlDebugEnabled() && this.isDebugVerbosity()\n const shouldProfile = profiler?.enabled === true\n if (!shouldDebug && !shouldProfile) {\n return Promise.resolve(execute())\n }\n const startedAt = process.hrtime.bigint()\n try {\n return await Promise.resolve(execute())\n } finally {\n const elapsedMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000\n const context: Record<string, unknown> = {\n entity,\n durationMs: Math.round(elapsedMs * 1000) / 1000,\n }\n if (extra) Object.assign(context, extra)\n if (shouldProfile) profiler!.record(label, context.durationMs as number, extra)\n if (shouldDebug) this.debug(`${label}:timing`, context)\n }\n }\n\n private debug(message: string, context?: Record<string, unknown>): void {\n if (!this.isDebugVerbosity()) return\n if (!this.isSqlDebugEnabled()) return\n if (context) console.debug('[HybridQueryEngine]', message, context)\n else console.debug('[HybridQueryEngine]', message)\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["result"]
7
7
  }
@@ -6,7 +6,7 @@ import Link from "next/link";
6
6
  import ReactMarkdown from "react-markdown";
7
7
  import remarkGfm from "remark-gfm";
8
8
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
9
- import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
9
+ import { DataTable } from "@open-mercato/ui/backend/DataTable";
10
10
  import { Button } from "@open-mercato/ui/primitives/button";
11
11
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
12
12
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
@@ -244,7 +244,7 @@ function mapApiResourceType(item) {
244
244
  const appearanceColor = typeof item.appearanceColor === "string" ? item.appearanceColor : typeof item.appearance_color === "string" ? item.appearance_color : null;
245
245
  const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : typeof item.updated_at === "string" ? item.updated_at : null;
246
246
  const resourceCount = typeof item.resourceCount === "number" ? item.resourceCount : typeof item.resource_count === "number" ? item.resource_count : 0;
247
- return withDataTableNamespaces({ id, name, description, appearanceIcon, appearanceColor, updatedAt, resourceCount }, item);
247
+ return { id, name, description, appearanceIcon, appearanceColor, updatedAt, resourceCount };
248
248
  }
249
249
  export {
250
250
  ResourcesResourceTypesPage as default