@open-mercato/core 0.4.11-develop.1418.27a299bdaf → 0.4.11-develop.1436.ff2df4355a

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.
@@ -631,7 +631,7 @@ class HybridQueryEngine {
631
631
  };
632
632
  const applyJoinSearchFilterOp = async (target, filter, _qualified, join) => {
633
633
  if (!searchEnabled || !join.entityId) return false;
634
- if (!["eq", "like", "ilike"].includes(filter.op)) return false;
634
+ if (!["like", "ilike"].includes(filter.op)) return false;
635
635
  if (typeof filter.value !== "string" || filter.value.trim().length === 0) return false;
636
636
  let searchAvailable = joinSearchAvailability.get(join.entityId);
637
637
  if (searchAvailable === void 0) {
@@ -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, QueryExtensionsConfig } 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'\nimport { runBeforeQueryPipeline, runAfterQueryPipeline, type QueryExtensionContext } from '@open-mercato/shared/lib/query/query-extension-runner'\n\nfunction buildFilterableCustomFieldJoins(\n sources: QueryCustomFieldSource[] | undefined,\n): Array<{\n alias: string\n table?: string\n entityId: EntityId\n from: { field: string }\n to: { field: string }\n type: 'left' | 'inner'\n}> {\n if (!sources || sources.length === 0) return []\n return sources.flatMap((source, index) => {\n if (!source.join) return []\n const alias = typeof source.alias === 'string' && source.alias.trim().length > 0\n ? source.alias.trim()\n : `cfs_${index}`\n return [{\n alias,\n table: source.table,\n entityId: source.entityId,\n from: { field: source.join.fromField },\n to: { field: source.join.toField },\n type: source.join.type === 'inner' ? 'inner' : 'left',\n }]\n })\n}\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 // --- UMES query extension: before-query pipeline ---\n const ext: QueryExtensionsConfig | undefined = opts.extensions\n let hybridExtCtx: QueryExtensionContext | null = null\n const noopDi = { resolve: <R = unknown>(_name: string): R => { throw new Error('No DI context') } }\n\n if (ext) {\n hybridExtCtx = {\n entity: String(entity),\n engine: 'hybrid',\n tenantId: opts.tenantId ?? '',\n organizationId: opts.organizationId,\n userId: ext.userId,\n em: this.em,\n container: ext.container,\n userFeatures: ext.userFeatures,\n }\n const diCtx = ext.resolve ? { resolve: ext.resolve } : noopDi\n const beforeResult = await runBeforeQueryPipeline(opts, hybridExtCtx, diCtx)\n if (beforeResult.blocked) {\n throw new Error(beforeResult.errorMessage ?? 'Query blocked by extension subscriber')\n }\n opts = beforeResult.query\n }\n // Strip extensions so fallback to BasicQueryEngine doesn't double-execute\n const { extensions: _stripExt, ...coreOpts } = opts\n opts = coreOpts\n\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 const applyAfterExtensions = async <R>(queryResult: QueryResult<R>): Promise<QueryResult<R>> => {\n if (!ext || !hybridExtCtx) return queryResult\n const diCtx = ext.resolve ? { resolve: ext.resolve } : noopDi\n return await runAfterQueryPipeline(\n queryResult as QueryResult<Record<string, unknown>>,\n opts,\n hybridExtCtx,\n diCtx,\n ) as QueryResult<R>\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 await applyAfterExtensions(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 await applyAfterExtensions(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 (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 await applyAfterExtensions(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 await applyAfterExtensions(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(\n baseTable,\n [...(opts.joins ?? []), ...buildFilterableCustomFieldJoins(opts.customFieldSources)],\n (entityId) => resolveEntityTableName(this.em, entityId as any),\n )\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 joinSearchAvailability = new Map<string, boolean>()\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 const regularBaseFilters = baseFilters.filter((filter) => !filter.orGroup)\n const orGroupFilters = baseFilters.filter((filter) => filter.orGroup)\n\n for (const filter of regularBaseFilters) {\n const fieldName = String(filter.field)\n const baseField = resolveBaseColumn(fieldName)\n if (!baseField) {\n builder = this.applyIndexDocFilterFromAlias(\n knex,\n builder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyIndexDocFilterFromAlias(\n knex,\n optimizedCountBuilder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n }\n continue\n }\n const column = qualify(baseField)\n builder = this.applyColumnFilter(builder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyColumnFilter(optimizedCountBuilder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n }\n }\n\n const applyOrGroupedBaseFilters = (target: ResultBuilder | null): ResultBuilder | null => {\n if (!target || orGroupFilters.length === 0) return target\n const groups = new Map<string, BaseFilter[]>()\n for (const filter of orGroupFilters) {\n if (!filter.orGroup) continue\n const existing = groups.get(filter.orGroup) ?? []\n existing.push(filter)\n groups.set(filter.orGroup, existing)\n }\n let next = target\n for (const [, groupFilters] of groups) {\n if (!groupFilters.length) continue\n next = next.where((groupBuilder) => {\n groupFilters.forEach((filter, index) => {\n const fieldName = String(filter.field)\n const baseField = resolveBaseColumn(fieldName)\n const applyCondition = (conditionBuilder: ResultBuilder) => {\n if (!baseField) {\n this.applyIndexDocFilterFromAlias(\n knex,\n conditionBuilder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n return\n }\n this.applyColumnFilter(conditionBuilder, qualify(baseField), filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n }\n if (index === 0) {\n applyCondition(groupBuilder as ResultBuilder)\n return\n }\n groupBuilder.orWhere((conditionBuilder) => {\n applyCondition(conditionBuilder as ResultBuilder)\n })\n })\n })\n }\n return next\n }\n\n builder = applyOrGroupedBaseFilters(builder) ?? builder\n optimizedCountBuilder = applyOrGroupedBaseFilters(optimizedCountBuilder)\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 const applyJoinSearchFilterOp = async (\n target: ResultBuilder,\n filter: { column: string; op: FilterOp; value?: unknown },\n _qualified: string,\n join: ResolvedJoin,\n ): Promise<boolean> => {\n if (!searchEnabled || !join.entityId) return false\n if (!['eq', 'like', 'ilike'].includes(filter.op)) return false\n if (typeof filter.value !== 'string' || filter.value.trim().length === 0) return false\n\n let searchAvailable = joinSearchAvailability.get(join.entityId)\n if (searchAvailable === undefined) {\n searchAvailable = await this.hasSearchTokens(String(join.entityId), opts.tenantId ?? null, orgScope)\n joinSearchAvailability.set(join.entityId, searchAvailable)\n }\n if (!searchAvailable) return false\n\n const tokens = tokenizeText(String(filter.value), searchConfig)\n if (!tokens.hashes.length) return false\n\n return this.applySearchTokens(target, {\n knex,\n entity: String(join.entityId),\n field: filter.column,\n hashes: tokens.hashes,\n recordIdColumn: `${join.alias}.id`,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\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 applyJoinFilterOp: (target, filter, qualified, join) =>\n applyJoinSearchFilterOp(target as ResultBuilder, filter, qualified, join),\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 applyJoinFilterOp: (target, filter, qualified, join) =>\n applyJoinSearchFilterOp(target as ResultBuilder, filter, qualified, join),\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 let result: QueryResult<T> = { items: typedItems, page, pageSize, total }\n if (partialIndexWarning) {\n result.meta = { partialIndexWarning }\n }\n\n // --- UMES query extension: after-query pipeline ---\n result = await applyAfterExtensions(result)\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 applyIndexDocFilterFromAlias(\n knex: Knex,\n q: ResultBuilder,\n alias: string,\n entityType: string,\n key: string,\n op: FilterOp,\n value: unknown,\n recordIdColumn: string,\n search?: SearchRuntime,\n ): ResultBuilder {\n const text = knex.raw(`(${alias}.doc ->> ?)`, [key])\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,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n })\n this.logSearchDebug('search:index-doc-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:index-doc-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(text, '=', value as Knex.Value)\n case 'ne':\n return q.where(text, '!=', value as Knex.Value)\n case 'in':\n return q.whereIn(text as any, this.toArray(value) as readonly Knex.Value[])\n case 'nin':\n return q.whereNotIn(text as any, this.toArray(value) as readonly Knex.Value[])\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'], false)\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, QueryExtensionsConfig } 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'\nimport { runBeforeQueryPipeline, runAfterQueryPipeline, type QueryExtensionContext } from '@open-mercato/shared/lib/query/query-extension-runner'\n\nfunction buildFilterableCustomFieldJoins(\n sources: QueryCustomFieldSource[] | undefined,\n): Array<{\n alias: string\n table?: string\n entityId: EntityId\n from: { field: string }\n to: { field: string }\n type: 'left' | 'inner'\n}> {\n if (!sources || sources.length === 0) return []\n return sources.flatMap((source, index) => {\n if (!source.join) return []\n const alias = typeof source.alias === 'string' && source.alias.trim().length > 0\n ? source.alias.trim()\n : `cfs_${index}`\n return [{\n alias,\n table: source.table,\n entityId: source.entityId,\n from: { field: source.join.fromField },\n to: { field: source.join.toField },\n type: source.join.type === 'inner' ? 'inner' : 'left',\n }]\n })\n}\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 // --- UMES query extension: before-query pipeline ---\n const ext: QueryExtensionsConfig | undefined = opts.extensions\n let hybridExtCtx: QueryExtensionContext | null = null\n const noopDi = { resolve: <R = unknown>(_name: string): R => { throw new Error('No DI context') } }\n\n if (ext) {\n hybridExtCtx = {\n entity: String(entity),\n engine: 'hybrid',\n tenantId: opts.tenantId ?? '',\n organizationId: opts.organizationId,\n userId: ext.userId,\n em: this.em,\n container: ext.container,\n userFeatures: ext.userFeatures,\n }\n const diCtx = ext.resolve ? { resolve: ext.resolve } : noopDi\n const beforeResult = await runBeforeQueryPipeline(opts, hybridExtCtx, diCtx)\n if (beforeResult.blocked) {\n throw new Error(beforeResult.errorMessage ?? 'Query blocked by extension subscriber')\n }\n opts = beforeResult.query\n }\n // Strip extensions so fallback to BasicQueryEngine doesn't double-execute\n const { extensions: _stripExt, ...coreOpts } = opts\n opts = coreOpts\n\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 const applyAfterExtensions = async <R>(queryResult: QueryResult<R>): Promise<QueryResult<R>> => {\n if (!ext || !hybridExtCtx) return queryResult\n const diCtx = ext.resolve ? { resolve: ext.resolve } : noopDi\n return await runAfterQueryPipeline(\n queryResult as QueryResult<Record<string, unknown>>,\n opts,\n hybridExtCtx,\n diCtx,\n ) as QueryResult<R>\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 await applyAfterExtensions(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 await applyAfterExtensions(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 (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 await applyAfterExtensions(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 await applyAfterExtensions(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(\n baseTable,\n [...(opts.joins ?? []), ...buildFilterableCustomFieldJoins(opts.customFieldSources)],\n (entityId) => resolveEntityTableName(this.em, entityId as any),\n )\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 joinSearchAvailability = new Map<string, boolean>()\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 const regularBaseFilters = baseFilters.filter((filter) => !filter.orGroup)\n const orGroupFilters = baseFilters.filter((filter) => filter.orGroup)\n\n for (const filter of regularBaseFilters) {\n const fieldName = String(filter.field)\n const baseField = resolveBaseColumn(fieldName)\n if (!baseField) {\n builder = this.applyIndexDocFilterFromAlias(\n knex,\n builder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyIndexDocFilterFromAlias(\n knex,\n optimizedCountBuilder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n }\n continue\n }\n const column = qualify(baseField)\n builder = this.applyColumnFilter(builder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n if (optimizedCountBuilder) {\n optimizedCountBuilder = this.applyColumnFilter(optimizedCountBuilder, column, filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n }\n }\n\n const applyOrGroupedBaseFilters = (target: ResultBuilder | null): ResultBuilder | null => {\n if (!target || orGroupFilters.length === 0) return target\n const groups = new Map<string, BaseFilter[]>()\n for (const filter of orGroupFilters) {\n if (!filter.orGroup) continue\n const existing = groups.get(filter.orGroup) ?? []\n existing.push(filter)\n groups.set(filter.orGroup, existing)\n }\n let next = target\n for (const [, groupFilters] of groups) {\n if (!groupFilters.length) continue\n next = next.where((groupBuilder) => {\n groupFilters.forEach((filter, index) => {\n const fieldName = String(filter.field)\n const baseField = resolveBaseColumn(fieldName)\n const applyCondition = (conditionBuilder: ResultBuilder) => {\n if (!baseField) {\n this.applyIndexDocFilterFromAlias(\n knex,\n conditionBuilder,\n 'ei',\n entity,\n fieldName,\n filter.op,\n filter.value,\n 'b.id',\n searchRuntime,\n )\n return\n }\n this.applyColumnFilter(conditionBuilder, qualify(baseField), filter, {\n ...searchRuntime,\n knex,\n entity,\n field: fieldName,\n recordIdColumn: 'b.id',\n })\n }\n if (index === 0) {\n applyCondition(groupBuilder as ResultBuilder)\n return\n }\n groupBuilder.orWhere((conditionBuilder) => {\n applyCondition(conditionBuilder as ResultBuilder)\n })\n })\n })\n }\n return next\n }\n\n builder = applyOrGroupedBaseFilters(builder) ?? builder\n optimizedCountBuilder = applyOrGroupedBaseFilters(optimizedCountBuilder)\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 const applyJoinSearchFilterOp = async (\n target: ResultBuilder,\n filter: { column: string; op: FilterOp; value?: unknown },\n _qualified: string,\n join: ResolvedJoin,\n ): Promise<boolean> => {\n if (!searchEnabled || !join.entityId) return false\n if (!['like', 'ilike'].includes(filter.op)) return false\n if (typeof filter.value !== 'string' || filter.value.trim().length === 0) return false\n\n let searchAvailable = joinSearchAvailability.get(join.entityId)\n if (searchAvailable === undefined) {\n searchAvailable = await this.hasSearchTokens(String(join.entityId), opts.tenantId ?? null, orgScope)\n joinSearchAvailability.set(join.entityId, searchAvailable)\n }\n if (!searchAvailable) return false\n\n const tokens = tokenizeText(String(filter.value), searchConfig)\n if (!tokens.hashes.length) return false\n\n return this.applySearchTokens(target, {\n knex,\n entity: String(join.entityId),\n field: filter.column,\n hashes: tokens.hashes,\n recordIdColumn: `${join.alias}.id`,\n tenantId: opts.tenantId ?? null,\n organizationScope: orgScope,\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 applyJoinFilterOp: (target, filter, qualified, join) =>\n applyJoinSearchFilterOp(target as ResultBuilder, filter, qualified, join),\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 applyJoinFilterOp: (target, filter, qualified, join) =>\n applyJoinSearchFilterOp(target as ResultBuilder, filter, qualified, join),\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 let result: QueryResult<T> = { items: typedItems, page, pageSize, total }\n if (partialIndexWarning) {\n result.meta = { partialIndexWarning }\n }\n\n // --- UMES query extension: after-query pipeline ---\n result = await applyAfterExtensions(result)\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 applyIndexDocFilterFromAlias(\n knex: Knex,\n q: ResultBuilder,\n alias: string,\n entityType: string,\n key: string,\n op: FilterOp,\n value: unknown,\n recordIdColumn: string,\n search?: SearchRuntime,\n ): ResultBuilder {\n const text = knex.raw(`(${alias}.doc ->> ?)`, [key])\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,\n tenantId: search.tenantId ?? null,\n organizationScope: search.organizationScope ?? null,\n })\n this.logSearchDebug('search:index-doc-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:index-doc-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(text, '=', value as Knex.Value)\n case 'ne':\n return q.where(text, '!=', value as Knex.Value)\n case 'in':\n return q.whereIn(text as any, this.toArray(value) as readonly Knex.Value[])\n case 'nin':\n return q.whereNotIn(text as any, this.toArray(value) as readonly Knex.Value[])\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'], false)\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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.4.11-develop.1418.27a299bdaf",
3
+ "version": "0.4.11-develop.1436.ff2df4355a",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -230,10 +230,10 @@
230
230
  "ts-pattern": "^5.0.0"
231
231
  },
232
232
  "peerDependencies": {
233
- "@open-mercato/shared": "0.4.11-develop.1418.27a299bdaf"
233
+ "@open-mercato/shared": "0.4.11-develop.1436.ff2df4355a"
234
234
  },
235
235
  "devDependencies": {
236
- "@open-mercato/shared": "0.4.11-develop.1418.27a299bdaf",
236
+ "@open-mercato/shared": "0.4.11-develop.1436.ff2df4355a",
237
237
  "@testing-library/dom": "^10.4.1",
238
238
  "@testing-library/jest-dom": "^6.9.1",
239
239
  "@testing-library/react": "^16.3.1",
@@ -753,7 +753,7 @@ export class HybridQueryEngine implements QueryEngine {
753
753
  join: ResolvedJoin,
754
754
  ): Promise<boolean> => {
755
755
  if (!searchEnabled || !join.entityId) return false
756
- if (!['eq', 'like', 'ilike'].includes(filter.op)) return false
756
+ if (!['like', 'ilike'].includes(filter.op)) return false
757
757
  if (typeof filter.value !== 'string' || filter.value.trim().length === 0) return false
758
758
 
759
759
  let searchAvailable = joinSearchAvailability.get(join.entityId)