@open-mercato/core 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c
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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/modules/auth/backend/settings/page.js +14 -9
- package/dist/modules/auth/backend/settings/page.js.map +2 -2
- package/dist/modules/customers/cli.js +17 -7
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +229 -216
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/search.js +50 -29
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +13 -4
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +7 -2
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +7 -2
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/runs.js +7 -2
- package/dist/modules/data_sync/api/runs.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +13 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/api/validate.js +9 -4
- package/dist/modules/data_sync/api/validate.js.map +2 -2
- package/dist/modules/design_system/acl.js +9 -0
- package/dist/modules/design_system/acl.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.js +11 -0
- package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +186 -0
- package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
- package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/charts.js +457 -0
- package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/dates.js +306 -0
- package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/detail.js +358 -0
- package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/display.js +785 -0
- package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
- package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/filters.js +505 -0
- package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
- package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/icons.js +140 -0
- package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
- package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +334 -0
- package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
- package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
- package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
- package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
- package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +139 -0
- package/dist/modules/design_system/gallery/registry.js.map +7 -0
- package/dist/modules/design_system/gallery/types.js +1 -0
- package/dist/modules/design_system/gallery/types.js.map +7 -0
- package/dist/modules/design_system/index.js +9 -0
- package/dist/modules/design_system/index.js.map +7 -0
- package/dist/modules/design_system/setup.js +14 -0
- package/dist/modules/design_system/setup.js.map +7 -0
- package/dist/modules/inbox_ops/search.js +15 -4
- package/dist/modules/inbox_ops/search.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/health/route.js +6 -3
- package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +6 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +6 -3
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +6 -3
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +6 -3
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +6 -3
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +2 -2
- package/dist/modules/integrations/api/umes-read.js.map +2 -2
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/query_index/data/entities.js +2 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +32 -50
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/package.json +16 -16
- package/src/modules/auth/backend/settings/page.tsx +17 -8
- package/src/modules/customers/cli.ts +17 -7
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +24 -13
- package/src/modules/customers/i18n/de.json +17 -0
- package/src/modules/customers/i18n/en.json +17 -0
- package/src/modules/customers/i18n/es.json +17 -0
- package/src/modules/customers/i18n/pl.json +17 -0
- package/src/modules/customers/search.ts +59 -27
- package/src/modules/data_sync/AGENTS.md +1 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
- package/src/modules/data_sync/api/mappings/route.ts +13 -4
- package/src/modules/data_sync/api/options.ts +7 -2
- package/src/modules/data_sync/api/run.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
- package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
- package/src/modules/data_sync/api/runs.ts +7 -2
- package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
- package/src/modules/data_sync/api/schedules/route.ts +13 -4
- package/src/modules/data_sync/api/validate.ts +9 -4
- package/src/modules/design_system/AGENTS.md +34 -0
- package/src/modules/design_system/acl.ts +5 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
- package/src/modules/design_system/backend/design-system/page.tsx +14 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
- package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
- package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
- package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
- package/src/modules/design_system/gallery/entries/display.tsx +893 -0
- package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
- package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
- package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
- package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
- package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
- package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
- package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
- package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
- package/src/modules/design_system/gallery/registry.ts +152 -0
- package/src/modules/design_system/gallery/types.ts +32 -0
- package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
- package/src/modules/design_system/i18n/de.json +46 -0
- package/src/modules/design_system/i18n/en.json +46 -0
- package/src/modules/design_system/i18n/es.json +46 -0
- package/src/modules/design_system/i18n/pl.json +46 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/inbox_ops/i18n/de.json +3 -0
- package/src/modules/inbox_ops/i18n/en.json +3 -0
- package/src/modules/inbox_ops/i18n/es.json +3 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
- package/src/modules/integrations/api/[id]/health/route.ts +6 -3
- package/src/modules/integrations/api/[id]/route.ts +6 -3
- package/src/modules/integrations/api/[id]/state/route.ts +6 -3
- package/src/modules/integrations/api/[id]/version/route.ts +6 -3
- package/src/modules/integrations/api/logs/route.ts +6 -3
- package/src/modules/integrations/api/route.ts +6 -3
- package/src/modules/integrations/api/umes-read.ts +2 -2
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/messages/i18n/de.json +2 -0
- package/src/modules/messages/i18n/en.json +2 -0
- package/src/modules/messages/i18n/es.json +2 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/lib/engine.ts +40 -63
- package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
- package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/api/umes-read.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport {
|
|
5
|
-
"mappings": "AACA,SAAS,oBAAoB;AAE7B,SAAS,yBAAyB,gCAAkE;AACpG,SAAS,wBAAwB,qCAAqC;AAEtE,SAAS,
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport { resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n\nexport const integrationApiRoutePaths = {\n list: 'integrations',\n detail: 'integrations/detail',\n logs: 'integrations/logs',\n} as const\n\ntype ReadRouteFieldConfig = {\n targetEntity: string\n recordKeys?: string[]\n listKeys?: string[]\n}\n\ntype ReadRouteContext = {\n routePath: string\n request: Request\n auth: {\n tenantId: string | null\n orgId: string | null\n sub?: string | null\n features?: unknown\n }\n container: AwilixContainer\n}\n\nfunction headersToObject(headers: Headers): Record<string, string> {\n return Object.fromEntries(headers.entries())\n}\n\nfunction searchParamsToObject(url: URL): Record<string, string> {\n const entries: Record<string, string> = {}\n url.searchParams.forEach((value, key) => {\n entries[key] = value\n })\n return entries\n}\n\nfunction toUserFeatures(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n return features.filter((value): value is string => typeof value === 'string')\n}\n\nfunction mergeAdditiveRecord<T extends Record<string, unknown>>(base: T, candidate: T): T {\n const additions = Object.fromEntries(\n Object.entries(candidate).filter(([key]) => !(key in base)),\n ) as Partial<T>\n\n return {\n ...base,\n ...additions,\n }\n}\n\nfunction mergeAdditiveBody(\n baseBody: Record<string, unknown>,\n candidateBody: Record<string, unknown>,\n): Record<string, unknown> {\n return mergeAdditiveRecord(baseBody, candidateBody)\n}\n\nfunction getEnricherContext(input: ReadRouteContext) {\n return {\n organizationId: resolveActiveOrganizationId(input.auth) as string,\n tenantId: input.auth.tenantId as string,\n userId: input.auth.sub ?? '',\n em: input.container.resolve('em') as EntityManager,\n container: input.container,\n userFeatures: toUserFeatures(input.auth.features),\n }\n}\n\nexport async function runIntegrationsReadBeforeInterceptors(\n input: ReadRouteContext,\n): Promise<RunInterceptorsBeforeResult> {\n const url = new URL(input.request.url)\n\n return runApiInterceptorsBefore({\n routePath: input.routePath,\n method: 'GET',\n request: {\n method: 'GET',\n url: input.request.url,\n headers: headersToObject(input.request.headers),\n query: searchParamsToObject(url),\n },\n context: getEnricherContext(input),\n })\n}\n\nasync function applySafeRecordEnrichment(\n record: Record<string, unknown>,\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>> {\n const enriched = await applyResponseEnricherToRecord(record, targetEntity, context)\n return mergeAdditiveRecord(record, enriched.record)\n}\n\nasync function applySafeListEnrichment(\n items: Record<string, unknown>[],\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>[]> {\n const enriched = await applyResponseEnrichers(items, targetEntity, context)\n return items.map((item, index) => {\n const enrichedItem = enriched.items[index]\n if (!enrichedItem) return item\n return mergeAdditiveRecord(item, enrichedItem)\n })\n}\n\nexport async function finalizeIntegrationsReadResponse(\n input: ReadRouteContext & {\n interceptorRequest: InterceptorRequest\n body: Record<string, unknown>\n enrich?: ReadRouteFieldConfig\n method?: ApiInterceptorMethod\n beforeMetadata?: Record<string, Record<string, unknown> | undefined>\n },\n): Promise<NextResponse> {\n const method = input.method ?? 'GET'\n const baseBody = input.body\n const context = getEnricherContext(input)\n\n const intercepted = await runApiInterceptorsAfter({\n routePath: input.routePath,\n method,\n request: input.interceptorRequest,\n response: {\n statusCode: 200,\n body: baseBody,\n headers: {},\n },\n context,\n metadataByInterceptor: input.beforeMetadata,\n })\n\n if (!intercepted.ok) {\n return NextResponse.json(intercepted.body, { status: intercepted.statusCode, headers: intercepted.headers })\n }\n\n let responseBody = mergeAdditiveBody(baseBody, intercepted.body)\n\n if (input.enrich) {\n const { targetEntity, recordKeys = [], listKeys = [] } = input.enrich\n\n for (const key of recordKeys) {\n const current = responseBody[key]\n if (!current || typeof current !== 'object' || Array.isArray(current)) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeRecordEnrichment(current as Record<string, unknown>, targetEntity, context),\n }\n }\n\n for (const key of listKeys) {\n const current = responseBody[key]\n if (!Array.isArray(current)) continue\n const records = current.filter(\n (item): item is Record<string, unknown> => typeof item === 'object' && item !== null && !Array.isArray(item),\n )\n if (records.length !== current.length) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeListEnrichment(records, targetEntity, context),\n }\n }\n }\n\n return NextResponse.json(responseBody, { headers: intercepted.headers })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
if (!auth) return null;
|
|
3
|
-
const selected = auth.orgId;
|
|
4
|
-
if (typeof selected === "string" && selected.trim().length > 0) return selected;
|
|
5
|
-
const actorOrgId = auth.actorOrgId;
|
|
6
|
-
if (typeof actorOrgId === "string" && actorOrgId.trim().length > 0) return actorOrgId;
|
|
7
|
-
return null;
|
|
8
|
-
}
|
|
1
|
+
import { resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
|
|
9
2
|
export {
|
|
10
|
-
resolveIntegrationsOrganizationId
|
|
3
|
+
resolveActiveOrganizationId as resolveIntegrationsOrganizationId
|
|
11
4
|
};
|
|
12
5
|
//# sourceMappingURL=organization-scope.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/lib/organization-scope.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * @deprecated Moved to `@open-mercato/shared/lib/auth/organizationScope` as\n * `resolveActiveOrganizationId`, because `data_sync` needs the same resolution and\n * `integrations` is not the right owner for it. This alias stays for third-party\n * modules that already import from here.\n */\nexport { resolveActiveOrganizationId as resolveIntegrationsOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n"],
|
|
5
|
+
"mappings": "AAMA,SAAwC,mCAAyC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
1
2
|
function appendLine(lines, label, value) {
|
|
2
3
|
if (value === null || value === void 0) return;
|
|
3
4
|
const text = Array.isArray(value) ? value.map((item) => item === null || item === void 0 ? "" : String(item)).filter(Boolean).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
@@ -19,8 +20,8 @@ function snippet(value, max = 140) {
|
|
|
19
20
|
if (trimmed.length <= max) return trimmed;
|
|
20
21
|
return `${trimmed.slice(0, max - 3)}...`;
|
|
21
22
|
}
|
|
22
|
-
function buildMessagePresenter(record) {
|
|
23
|
-
const title = pickString(record.subject) ?? "Message";
|
|
23
|
+
function buildMessagePresenter(translate, record) {
|
|
24
|
+
const title = pickString(record.subject) ?? translate("messages.search.fallback.title", "Message");
|
|
24
25
|
const body = snippet(record.body);
|
|
25
26
|
const externalName = pickString(record.external_name, record.externalName);
|
|
26
27
|
const subtitle = [externalName, body].filter(Boolean).join(" \xB7 ") || void 0;
|
|
@@ -28,7 +29,7 @@ function buildMessagePresenter(record) {
|
|
|
28
29
|
title: String(title),
|
|
29
30
|
subtitle,
|
|
30
31
|
icon: "mail",
|
|
31
|
-
badge: "Message"
|
|
32
|
+
badge: translate("messages.search.badge.message", "Message")
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
const searchConfig = {
|
|
@@ -38,6 +39,7 @@ const searchConfig = {
|
|
|
38
39
|
enabled: true,
|
|
39
40
|
priority: 5,
|
|
40
41
|
buildSource: async (ctx) => {
|
|
42
|
+
const { t } = await resolveTranslations();
|
|
41
43
|
const record = ctx.record;
|
|
42
44
|
const lines = [];
|
|
43
45
|
appendLine(lines, "Subject", record.subject);
|
|
@@ -46,7 +48,7 @@ const searchConfig = {
|
|
|
46
48
|
if (!lines.length) return null;
|
|
47
49
|
return {
|
|
48
50
|
text: lines,
|
|
49
|
-
presenter: buildMessagePresenter(record),
|
|
51
|
+
presenter: buildMessagePresenter(t, record),
|
|
50
52
|
checksumSource: {
|
|
51
53
|
record: {
|
|
52
54
|
subject: record.subject,
|
|
@@ -57,7 +59,10 @@ const searchConfig = {
|
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
},
|
|
60
|
-
formatResult: async (ctx) =>
|
|
62
|
+
formatResult: async (ctx) => {
|
|
63
|
+
const { t } = await resolveTranslations();
|
|
64
|
+
return buildMessagePresenter(t, ctx.record);
|
|
65
|
+
},
|
|
61
66
|
resolveUrl: async (ctx) => {
|
|
62
67
|
const id = pickString(ctx.record.id);
|
|
63
68
|
return id ? `/backend/messages/${encodeURIComponent(id)}` : null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/messages/search.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? 'Message'\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: 'Message',\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => buildMessagePresenter(ctx.record),\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
-
"mappings": "AAOA,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,QAAwD;
|
|
4
|
+
"sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(translate: TranslateFn, record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? translate('messages.search.fallback.title', 'Message')\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: translate('messages.search.badge.message', 'Message'),\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(t, record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildMessagePresenter(t, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,2BAA2B;AAEpC,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,WAAwB,QAAwD;AAC7G,QAAM,QAAQ,WAAW,OAAO,OAAO,KAAK,UAAU,kCAAkC,SAAS;AACjG,QAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,QAAM,eAAe,WAAW,OAAO,eAAe,OAAO,YAAY;AACzE,QAAM,WAAW,CAAC,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK;AACrE,SAAO;AAAA,IACL,OAAO,OAAO,KAAK;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,IACN,OAAO,UAAU,iCAAiC,SAAS;AAAA,EAC7D;AACF;AAEO,MAAM,eAAmC;AAAA,EAC9C,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAA+D;AACjF,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,WAAW,OAAO,OAAO;AAC3C,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,aAAa,OAAO,iBAAiB,OAAO,YAAY;AAC1E,YAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,sBAAsB,GAAG,MAAM;AAAA,UAC1C,gBAAgB;AAAA,YACd,QAAQ;AAAA,cACN,SAAS,OAAO;AAAA,cAChB,MAAM,OAAO;AAAA,cACb,eAAe,OAAO,iBAAiB,OAAO;AAAA,cAC9C,qBAAqB,OAAO,uBAAuB,OAAO;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,eAAO,sBAAsB,GAAG,IAAI,MAAM;AAAA,MAC5C;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,KAAK,WAAW,IAAI,OAAO,EAAE;AACnC,eAAO,KAAK,qBAAqB,mBAAmB,EAAE,CAAC,KAAK;AAAA,MAC9D;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,WAAW,QAAQ,eAAe;AAAA,QAC/C,UAAU,CAAC,gBAAgB;AAAA,QAC3B,UAAU,CAAC,eAAe,eAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;AACR,MAAM,SAAS;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -308,7 +308,8 @@ SearchToken = __decorateClass([
|
|
|
308
308
|
Entity({ tableName: "search_tokens" }),
|
|
309
309
|
Index({ name: "search_tokens_lookup_idx", properties: ["entityType", "field", "tokenHash", "tenantId", "organizationId"] }),
|
|
310
310
|
Index({ name: "search_tokens_entity_idx", properties: ["entityType", "entityId"] }),
|
|
311
|
-
Index({ name: "search_tokens_tenant_token_hash_idx", properties: ["tenantId", "tokenHash"] })
|
|
311
|
+
Index({ name: "search_tokens_tenant_token_hash_idx", properties: ["tenantId", "tokenHash"] }),
|
|
312
|
+
Index({ name: "search_tokens_presence_idx", properties: ["entityType", "tenantId", "organizationId"] })
|
|
312
313
|
], SearchToken);
|
|
313
314
|
export {
|
|
314
315
|
EntityIndexCoverage,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/query_index/data/entities.ts"],
|
|
4
|
-
"sourcesContent": ["import { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n// Generic JSONB-backed index rows for any entity ('<module>:<entity>')\n@Entity({ tableName: 'entity_indexes' })\n@Index({\n name: 'entity_indexes_customer_entity_doc_idx',\n expression:\n `create index \"entity_indexes_customer_entity_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_entity' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_person_profile_doc_idx',\n expression:\n `create index \"entity_indexes_customer_person_profile_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_person_profile' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_company_profile_doc_idx',\n expression:\n `create index \"entity_indexes_customer_company_profile_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_company_profile' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_entity_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_entity_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_entity' and organization_id is null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_person_profile_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_person_profile_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_person_profile' and organization_id is null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_company_profile_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_company_profile_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_company_profile' and organization_id is null and tenant_id is not null`,\n})\n@Index({ name: 'entity_indexes_type_tenant_idx', properties: ['entityType', 'tenantId'] })\n@Unique({\n name: 'entity_indexes_type_entity_org_coalesced_unique',\n properties: ['entityType', 'entityId', 'organizationIdCoalesced'],\n})\nexport class EntityIndexRow {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n // Entity identifier: '<module>:<entity>'\n @Property({ name: 'entity_type', type: 'text' })\n @Index({ name: 'entity_indexes_type_idx' })\n entityType!: string\n\n // Record id as text for compatibility with uuid/int\n @Property({ name: 'entity_id', type: 'text' })\n @Index({ name: 'entity_indexes_entity_idx' })\n entityId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n @Index({ name: 'entity_indexes_org_idx' })\n organizationId?: string | null\n\n @Property({\n name: 'organization_id_coalesced',\n type: 'uuid',\n generated: (cols) => `(coalesce(${cols.organizationId}, '00000000-0000-0000-0000-000000000000'::uuid)) stored`,\n hidden: true,\n })\n organizationIdCoalesced!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n // Flattened document of base fields and custom fields\n @Property({ name: 'doc', type: 'json' })\n doc!: any\n\n // Optional embedding vector or metadata produced by secondary indexers\n @Property({ name: 'embedding', type: 'json', nullable: true })\n embedding?: any | null\n\n @Property({ name: 'index_version', type: 'int', default: 1 })\n indexVersion: number = 1\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// Track long-running index jobs (reindex/purge) per entity and org scope\n@Entity({ tableName: 'entity_index_jobs' })\n// Coalesced-scope unique index so prepareJob can upsert atomically and two\n// concurrent schedulers cannot insert duplicate rows for the same scope (#2739).\n// Declared via @Unique with a raw expression (not properties) because the scope\n// columns are nullable and NULLs must collapse to one bucket via coalesce; mirrors\n// the entity_indexes coalesced uniqueness and the domain_mappings expression unique.\n@Unique({\n name: 'entity_index_jobs_scope_unique',\n expression:\n `create unique index \"entity_index_jobs_scope_unique\" on \"entity_index_jobs\" (\"entity_type\", coalesce(\"organization_id\", '00000000-0000-0000-0000-000000000000'::uuid), coalesce(\"tenant_id\", '00000000-0000-0000-0000-000000000000'::uuid), coalesce(\"partition_index\", -1), coalesce(\"partition_count\", -1))`,\n})\nexport class EntityIndexJob {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n @Index({ name: 'entity_index_jobs_type_idx' })\n entityType!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n @Index({ name: 'entity_index_jobs_org_idx' })\n organizationId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'partition_index', type: 'int', nullable: true })\n partitionIndex?: number | null\n\n @Property({ name: 'partition_count', type: 'int', nullable: true })\n partitionCount?: number | null\n\n @Property({ name: 'processed_count', type: 'int', nullable: true })\n processedCount?: number | null\n\n @Property({ name: 'total_count', type: 'int', nullable: true })\n totalCount?: number | null\n\n @Property({ name: 'heartbeat_at', type: Date, nullable: true })\n heartbeatAt?: Date | null\n\n // 'reindexing' | 'purging'\n @Property({ name: 'status', type: 'text' })\n status!: string\n\n @Property({ name: 'started_at', type: Date, onCreate: () => new Date() })\n startedAt: Date = new Date()\n\n @Property({ name: 'finished_at', type: Date, nullable: true })\n finishedAt?: Date | null\n}\n\n// Snapshot counts for coverage checks (per entity / tenant / org / withDeleted scope)\n@Entity({ tableName: 'entity_index_coverage' })\n@Unique({\n name: 'entity_index_coverage_scope_idx',\n properties: ['entityType', 'tenantId', 'organizationId', 'withDeleted'],\n})\nexport class EntityIndexCoverage {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n entityType!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'with_deleted', type: 'boolean', default: false })\n withDeleted: boolean = false\n\n @Property({ name: 'base_count', type: 'int', unsigned: true, default: 0 })\n baseCount: number = 0\n\n @Property({ name: 'indexed_count', type: 'int', unsigned: true, default: 0 })\n indexedCount: number = 0\n\n @Property({ name: 'vector_indexed_count', type: 'int', unsigned: true, default: 0 })\n vectorIndexedCount: number = 0\n\n @Property({ name: 'refreshed_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n refreshedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'indexer_error_logs' })\n@Index({ name: 'indexer_error_logs_source_idx', properties: ['source'] })\n@Index({ name: 'indexer_error_logs_occurred_idx', properties: ['occurredAt'] })\nexport class IndexerErrorLog {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'source', type: 'text' })\n source!: string\n\n @Property({ name: 'handler', type: 'text' })\n handler!: string\n\n @Property({ name: 'entity_type', type: 'text', nullable: true })\n entityType?: string | null\n\n @Property({ name: 'record_id', type: 'text', nullable: true })\n recordId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'payload', type: 'json', nullable: true })\n payload?: any | null\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'stack', type: 'text', nullable: true })\n stack?: string | null\n\n@Property({ name: 'occurred_at', type: Date, onCreate: () => new Date() })\n occurredAt: Date = new Date()\n}\n\n@Entity({ tableName: 'indexer_status_logs' })\n@Index({ name: 'indexer_status_logs_source_idx', properties: ['source'] })\n@Index({ name: 'indexer_status_logs_occurred_idx', properties: ['occurredAt'] })\nexport class IndexerStatusLog {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'source', type: 'text' })\n source!: string\n\n @Property({ name: 'handler', type: 'text' })\n handler!: string\n\n @Property({ name: 'level', type: 'text' })\n level: string = 'info'\n\n @Property({ name: 'entity_type', type: 'text', nullable: true })\n entityType?: string | null\n\n @Property({ name: 'record_id', type: 'text', nullable: true })\n recordId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'details', type: 'json', nullable: true })\n details?: any | null\n\n @Property({ name: 'occurred_at', type: Date, onCreate: () => new Date() })\n occurredAt: Date = new Date()\n}\n\n@Entity({ tableName: 'search_tokens' })\n@Index({ name: 'search_tokens_lookup_idx', properties: ['entityType', 'field', 'tokenHash', 'tenantId', 'organizationId'] })\n@Index({ name: 'search_tokens_entity_idx', properties: ['entityType', 'entityId'] })\n@Index({ name: 'search_tokens_tenant_token_hash_idx', properties: ['tenantId', 'tokenHash'] })\nexport class SearchToken {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n entityType!: string\n\n @Property({ name: 'entity_id', type: 'text' })\n entityId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'field', type: 'text' })\n field!: string\n\n @Property({ name: 'token_hash', type: 'text' })\n tokenHash!: string\n\n @Property({ name: 'token', type: 'text', nullable: true })\n token?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n// Generic JSONB-backed index rows for any entity ('<module>:<entity>')\n@Entity({ tableName: 'entity_indexes' })\n@Index({\n name: 'entity_indexes_customer_entity_doc_idx',\n expression:\n `create index \"entity_indexes_customer_entity_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_entity' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_person_profile_doc_idx',\n expression:\n `create index \"entity_indexes_customer_person_profile_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_person_profile' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_company_profile_doc_idx',\n expression:\n `create index \"entity_indexes_customer_company_profile_doc_idx\" on \"entity_indexes\" (\"entity_id\", \"organization_id\", \"tenant_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_company_profile' and organization_id is not null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_entity_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_entity_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_entity' and organization_id is null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_person_profile_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_person_profile_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_person_profile' and organization_id is null and tenant_id is not null`,\n})\n@Index({\n name: 'entity_indexes_customer_company_profile_tenant_doc_idx',\n expression:\n `create index \"entity_indexes_customer_company_profile_tenant_doc_idx\" on \"entity_indexes\" (\"tenant_id\", \"entity_id\") include (\"doc\") where deleted_at is null and entity_type = 'customers:customer_company_profile' and organization_id is null and tenant_id is not null`,\n})\n@Index({ name: 'entity_indexes_type_tenant_idx', properties: ['entityType', 'tenantId'] })\n@Unique({\n name: 'entity_indexes_type_entity_org_coalesced_unique',\n properties: ['entityType', 'entityId', 'organizationIdCoalesced'],\n})\nexport class EntityIndexRow {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n // Entity identifier: '<module>:<entity>'\n @Property({ name: 'entity_type', type: 'text' })\n @Index({ name: 'entity_indexes_type_idx' })\n entityType!: string\n\n // Record id as text for compatibility with uuid/int\n @Property({ name: 'entity_id', type: 'text' })\n @Index({ name: 'entity_indexes_entity_idx' })\n entityId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n @Index({ name: 'entity_indexes_org_idx' })\n organizationId?: string | null\n\n @Property({\n name: 'organization_id_coalesced',\n type: 'uuid',\n generated: (cols) => `(coalesce(${cols.organizationId}, '00000000-0000-0000-0000-000000000000'::uuid)) stored`,\n hidden: true,\n })\n organizationIdCoalesced!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n // Flattened document of base fields and custom fields\n @Property({ name: 'doc', type: 'json' })\n doc!: any\n\n // Optional embedding vector or metadata produced by secondary indexers\n @Property({ name: 'embedding', type: 'json', nullable: true })\n embedding?: any | null\n\n @Property({ name: 'index_version', type: 'int', default: 1 })\n indexVersion: number = 1\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// Track long-running index jobs (reindex/purge) per entity and org scope\n@Entity({ tableName: 'entity_index_jobs' })\n// Coalesced-scope unique index so prepareJob can upsert atomically and two\n// concurrent schedulers cannot insert duplicate rows for the same scope (#2739).\n// Declared via @Unique with a raw expression (not properties) because the scope\n// columns are nullable and NULLs must collapse to one bucket via coalesce; mirrors\n// the entity_indexes coalesced uniqueness and the domain_mappings expression unique.\n@Unique({\n name: 'entity_index_jobs_scope_unique',\n expression:\n `create unique index \"entity_index_jobs_scope_unique\" on \"entity_index_jobs\" (\"entity_type\", coalesce(\"organization_id\", '00000000-0000-0000-0000-000000000000'::uuid), coalesce(\"tenant_id\", '00000000-0000-0000-0000-000000000000'::uuid), coalesce(\"partition_index\", -1), coalesce(\"partition_count\", -1))`,\n})\nexport class EntityIndexJob {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n @Index({ name: 'entity_index_jobs_type_idx' })\n entityType!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n @Index({ name: 'entity_index_jobs_org_idx' })\n organizationId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'partition_index', type: 'int', nullable: true })\n partitionIndex?: number | null\n\n @Property({ name: 'partition_count', type: 'int', nullable: true })\n partitionCount?: number | null\n\n @Property({ name: 'processed_count', type: 'int', nullable: true })\n processedCount?: number | null\n\n @Property({ name: 'total_count', type: 'int', nullable: true })\n totalCount?: number | null\n\n @Property({ name: 'heartbeat_at', type: Date, nullable: true })\n heartbeatAt?: Date | null\n\n // 'reindexing' | 'purging'\n @Property({ name: 'status', type: 'text' })\n status!: string\n\n @Property({ name: 'started_at', type: Date, onCreate: () => new Date() })\n startedAt: Date = new Date()\n\n @Property({ name: 'finished_at', type: Date, nullable: true })\n finishedAt?: Date | null\n}\n\n// Snapshot counts for coverage checks (per entity / tenant / org / withDeleted scope)\n@Entity({ tableName: 'entity_index_coverage' })\n@Unique({\n name: 'entity_index_coverage_scope_idx',\n properties: ['entityType', 'tenantId', 'organizationId', 'withDeleted'],\n})\nexport class EntityIndexCoverage {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n entityType!: string\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'with_deleted', type: 'boolean', default: false })\n withDeleted: boolean = false\n\n @Property({ name: 'base_count', type: 'int', unsigned: true, default: 0 })\n baseCount: number = 0\n\n @Property({ name: 'indexed_count', type: 'int', unsigned: true, default: 0 })\n indexedCount: number = 0\n\n @Property({ name: 'vector_indexed_count', type: 'int', unsigned: true, default: 0 })\n vectorIndexedCount: number = 0\n\n @Property({ name: 'refreshed_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n refreshedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'indexer_error_logs' })\n@Index({ name: 'indexer_error_logs_source_idx', properties: ['source'] })\n@Index({ name: 'indexer_error_logs_occurred_idx', properties: ['occurredAt'] })\nexport class IndexerErrorLog {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'source', type: 'text' })\n source!: string\n\n @Property({ name: 'handler', type: 'text' })\n handler!: string\n\n @Property({ name: 'entity_type', type: 'text', nullable: true })\n entityType?: string | null\n\n @Property({ name: 'record_id', type: 'text', nullable: true })\n recordId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'payload', type: 'json', nullable: true })\n payload?: any | null\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'stack', type: 'text', nullable: true })\n stack?: string | null\n\n@Property({ name: 'occurred_at', type: Date, onCreate: () => new Date() })\n occurredAt: Date = new Date()\n}\n\n@Entity({ tableName: 'indexer_status_logs' })\n@Index({ name: 'indexer_status_logs_source_idx', properties: ['source'] })\n@Index({ name: 'indexer_status_logs_occurred_idx', properties: ['occurredAt'] })\nexport class IndexerStatusLog {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'source', type: 'text' })\n source!: string\n\n @Property({ name: 'handler', type: 'text' })\n handler!: string\n\n @Property({ name: 'level', type: 'text' })\n level: string = 'info'\n\n @Property({ name: 'entity_type', type: 'text', nullable: true })\n entityType?: string | null\n\n @Property({ name: 'record_id', type: 'text', nullable: true })\n recordId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'details', type: 'json', nullable: true })\n details?: any | null\n\n @Property({ name: 'occurred_at', type: Date, onCreate: () => new Date() })\n occurredAt: Date = new Date()\n}\n\n@Entity({ tableName: 'search_tokens' })\n@Index({ name: 'search_tokens_lookup_idx', properties: ['entityType', 'field', 'tokenHash', 'tenantId', 'organizationId'] })\n@Index({ name: 'search_tokens_entity_idx', properties: ['entityType', 'entityId'] })\n@Index({ name: 'search_tokens_tenant_token_hash_idx', properties: ['tenantId', 'tokenHash'] })\n// Serves the availability probe (\"does this scope have any tokens?\") as a pure\n// B-tree prefix seek, making the MISS as cheap as the hit \u2014 neither existing\n// index can (lookup_idx buries tenant_id behind field/token_hash), which is how\n// the probe degraded to a seq scan on large tables (#4723). Requires the\n// index-usable `= / IS NULL` predicates the availability resolver emits; see\n// .ai/specs/2026-07-31-search-token-probe-index.md.\n@Index({ name: 'search_tokens_presence_idx', properties: ['entityType', 'tenantId', 'organizationId'] })\nexport class SearchToken {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'entity_type', type: 'text' })\n entityType!: string\n\n @Property({ name: 'entity_id', type: 'text' })\n entityId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'tenant_id', type: 'uuid', nullable: true })\n tenantId?: string | null\n\n @Property({ name: 'field', type: 'text' })\n field!: string\n\n @Property({ name: 'token_hash', type: 'text' })\n tokenHash!: string\n\n @Property({ name: 'token', type: 'text', nullable: true })\n token?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
resolveJoins
|
|
14
14
|
} from "@open-mercato/shared/lib/query/join-utils";
|
|
15
15
|
import { resolveSearchConfig } from "@open-mercato/shared/lib/search/config";
|
|
16
|
+
import {
|
|
17
|
+
createSearchTokenAvailability,
|
|
18
|
+
isSearchFilterOp,
|
|
19
|
+
hasSearchFilter
|
|
20
|
+
} from "@open-mercato/shared/lib/search/availability";
|
|
16
21
|
import { tokenizeText } from "@open-mercato/shared/lib/search/tokenize";
|
|
17
22
|
import { runBeforeQueryPipeline, runAfterQueryPipeline } from "@open-mercato/shared/lib/query/query-extension-runner";
|
|
18
23
|
import { warnOnCiphertextLikeFallback } from "@open-mercato/shared/lib/query/ciphertext-search-warning";
|
|
@@ -85,6 +90,7 @@ class HybridQueryEngine {
|
|
|
85
90
|
this.autoReindexEnabled = null;
|
|
86
91
|
this.coverageOptimizationEnabled = null;
|
|
87
92
|
this.pendingCoverageRefreshKeys = /* @__PURE__ */ new Set();
|
|
93
|
+
this.searchAvailabilityInstance = null;
|
|
88
94
|
const coverageTtl = Number.parseInt(process.env.QUERY_INDEX_COVERAGE_CACHE_MS ?? "", 10);
|
|
89
95
|
this.coverageStatsTtlMs = Number.isFinite(coverageTtl) && coverageTtl >= 0 ? coverageTtl : 5 * 60 * 1e3;
|
|
90
96
|
const cfTtl = Number.parseInt(process.env.QUERY_INDEX_CF_KEYS_CACHE_MS ?? "", 10);
|
|
@@ -102,6 +108,21 @@ class HybridQueryEngine {
|
|
|
102
108
|
if (typeof emAny.getKysely === "function") return emAny.getKysely();
|
|
103
109
|
throw new Error("HybridQueryEngine requires an EntityManager exposing getKysely() (MikroORM v7)");
|
|
104
110
|
}
|
|
111
|
+
searchAvailability() {
|
|
112
|
+
if (!this.searchAvailabilityInstance) {
|
|
113
|
+
this.searchAvailabilityInstance = createSearchTokenAvailability({
|
|
114
|
+
getDb: () => this.getDb(),
|
|
115
|
+
getConfig: resolveSearchConfig,
|
|
116
|
+
applyOrganizationScope: (query, column, scope) => this.applyOrganizationScope(
|
|
117
|
+
query,
|
|
118
|
+
column,
|
|
119
|
+
scope
|
|
120
|
+
),
|
|
121
|
+
logDebug: (event, payload) => this.logSearchDebug(event, payload)
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return this.searchAvailabilityInstance;
|
|
125
|
+
}
|
|
105
126
|
async query(entity, opts = {}) {
|
|
106
127
|
const ext = opts.extensions;
|
|
107
128
|
let hybridExtCtx = null;
|
|
@@ -173,7 +194,7 @@ class HybridQueryEngine {
|
|
|
173
194
|
profiler.mark("query:base_table_resolved");
|
|
174
195
|
const searchConfig = resolveSearchConfig();
|
|
175
196
|
const orgScope = this.resolveOrganizationScope(opts);
|
|
176
|
-
const searchEnabled =
|
|
197
|
+
const searchEnabled = await this.searchAvailability().staticEnabled();
|
|
177
198
|
const baseExists = await profiler.measure("base_table_exists", () => this.tableExists(baseTable));
|
|
178
199
|
if (!baseExists) {
|
|
179
200
|
if (debugEnabled) this.debug("query:fallback:missing-base", { entity, baseTable });
|
|
@@ -317,10 +338,13 @@ class HybridQueryEngine {
|
|
|
317
338
|
}
|
|
318
339
|
}
|
|
319
340
|
const searchSources = indexSources.map((src) => ({ entity: String(src.entityId), recordIdColumn: src.recordIdColumn })).filter((src) => src.recordIdColumn && src.entity);
|
|
320
|
-
const searchFilters = normalizedFilters.filter((filter) => filter.op
|
|
321
|
-
const
|
|
341
|
+
const searchFilters = normalizedFilters.filter((filter) => isSearchFilterOp(filter.op));
|
|
342
|
+
const sourceSearchFilters = [
|
|
343
|
+
...baseFilters,
|
|
344
|
+
...normalizedFilters.filter((filter) => String(filter.field).startsWith("cf:"))
|
|
345
|
+
].filter((filter) => isSearchFilterOp(filter.op));
|
|
346
|
+
const hasSearchTokens = searchEnabled && searchSources.length && sourceSearchFilters.length ? await this.searchAvailability().anySourceHasTokens(searchSources, opts.tenantId ?? null, orgScope) : false;
|
|
322
347
|
const searchRuntime = { ...searchRuntimeBase, searchSources, enabled: searchEnabled && hasSearchTokens };
|
|
323
|
-
const joinSearchAvailability = /* @__PURE__ */ new Map();
|
|
324
348
|
if (searchFilters.length) {
|
|
325
349
|
this.logSearchDebug("search:init", {
|
|
326
350
|
entity,
|
|
@@ -366,8 +390,7 @@ class HybridQueryEngine {
|
|
|
366
390
|
if (!filters.length) continue;
|
|
367
391
|
const join = joinMap.get(alias);
|
|
368
392
|
if (!join?.entityId) continue;
|
|
369
|
-
const hasJoinedTokens = searchEnabled ? await this.
|
|
370
|
-
joinSearchAvailability.set(String(join.entityId), hasJoinedTokens);
|
|
393
|
+
const hasJoinedTokens = searchEnabled ? await this.searchAvailability().hasTokens(String(join.entityId), opts.tenantId ?? null, orgScope) : false;
|
|
371
394
|
const fallbackFields = filters.filter((filter) => !hasJoinedTokens || typeof filter.value !== "string" || tokenizeText(filter.value, searchConfig).hashes.length === 0).map((filter) => filter.column);
|
|
372
395
|
if (!fallbackFields.length) continue;
|
|
373
396
|
await warnOnCiphertextLikeFallback({
|
|
@@ -636,11 +659,7 @@ class HybridQueryEngine {
|
|
|
636
659
|
if (!searchEnabled || !join.entityId) return false;
|
|
637
660
|
if (!["like", "ilike"].includes(filter.op)) return false;
|
|
638
661
|
if (typeof filter.value !== "string" || filter.value.trim().length === 0) return false;
|
|
639
|
-
|
|
640
|
-
if (searchAvailable === void 0) {
|
|
641
|
-
searchAvailable = await this.hasSearchTokens(String(join.entityId), opts.tenantId ?? null, orgScope);
|
|
642
|
-
joinSearchAvailability.set(join.entityId, searchAvailable);
|
|
643
|
-
}
|
|
662
|
+
const searchAvailable = await this.searchAvailability().hasTokens(String(join.entityId), opts.tenantId ?? null, orgScope);
|
|
644
663
|
if (!searchAvailable) return false;
|
|
645
664
|
const tokens = tokenizeText(String(filter.value), searchConfig);
|
|
646
665
|
if (!tokens.hashes.length) return false;
|
|
@@ -1388,10 +1407,9 @@ class HybridQueryEngine {
|
|
|
1388
1407
|
const orgScope = this.resolveOrganizationScope(opts);
|
|
1389
1408
|
if (!opts.tenantId) throw new Error("QueryEngine: tenantId is required");
|
|
1390
1409
|
const normalizedFilters = normalizeFilters(opts.filters);
|
|
1391
|
-
const hasSearchFilter = normalizedFilters.some((filter) => filter.op === "like" || filter.op === "ilike");
|
|
1392
1410
|
const searchConfig = resolveSearchConfig();
|
|
1393
|
-
const searchEnabled =
|
|
1394
|
-
const hasSearchTokens = searchEnabled && hasSearchFilter ? await this.
|
|
1411
|
+
const searchEnabled = await this.searchAvailability().staticEnabled();
|
|
1412
|
+
const hasSearchTokens = searchEnabled && hasSearchFilter(normalizedFilters) ? await this.searchAvailability().hasTokens(entity, opts.tenantId ?? null, orgScope) : false;
|
|
1395
1413
|
const searchRuntime = {
|
|
1396
1414
|
enabled: searchEnabled && hasSearchTokens,
|
|
1397
1415
|
config: searchConfig,
|
|
@@ -1511,42 +1529,6 @@ class HybridQueryEngine {
|
|
|
1511
1529
|
const exists = await db.selectFrom("information_schema.tables").select(sql`1`.as("one")).where("table_name", "=", table).executeTakeFirst();
|
|
1512
1530
|
return !!exists;
|
|
1513
1531
|
}
|
|
1514
|
-
async hasSearchTokens(entity, tenantId, orgScope) {
|
|
1515
|
-
try {
|
|
1516
|
-
const db = this.getDb();
|
|
1517
|
-
let query = db.selectFrom("search_tokens").select(sql`1`.as("one")).where("entity_type", "=", entity);
|
|
1518
|
-
if (tenantId !== void 0) {
|
|
1519
|
-
query = query.where(sql`tenant_id is not distinct from ${tenantId}`);
|
|
1520
|
-
}
|
|
1521
|
-
if (orgScope) {
|
|
1522
|
-
query = this.applyOrganizationScope(query, "search_tokens.organization_id", orgScope);
|
|
1523
|
-
}
|
|
1524
|
-
const row = await query.limit(1).executeTakeFirst();
|
|
1525
|
-
return !!row;
|
|
1526
|
-
} catch (err) {
|
|
1527
|
-
this.logSearchDebug("search:has-tokens-error", {
|
|
1528
|
-
entity,
|
|
1529
|
-
tenantId,
|
|
1530
|
-
organizationScope: orgScope,
|
|
1531
|
-
error: err instanceof Error ? err.message : String(err)
|
|
1532
|
-
});
|
|
1533
|
-
return false;
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
async searchSourcesHaveTokens(sources, tenantId, orgScope) {
|
|
1537
|
-
for (const source of sources) {
|
|
1538
|
-
const ok = await this.hasSearchTokens(source.entity, tenantId, orgScope);
|
|
1539
|
-
this.logSearchDebug("search:source-has-tokens", {
|
|
1540
|
-
entity: source.entity,
|
|
1541
|
-
recordIdColumn: source.recordIdColumn,
|
|
1542
|
-
tenantId,
|
|
1543
|
-
organizationScope: orgScope,
|
|
1544
|
-
hasTokens: ok
|
|
1545
|
-
});
|
|
1546
|
-
if (ok) return true;
|
|
1547
|
-
}
|
|
1548
|
-
return false;
|
|
1549
|
-
}
|
|
1550
1532
|
async resolveAvailableCustomFieldKeys(entityIds, tenantId) {
|
|
1551
1533
|
if (!entityIds.length) return [];
|
|
1552
1534
|
const cacheKey = this.customFieldKeysCacheKey(entityIds, tenantId);
|