@open-mercato/core 0.6.7-develop.6706.1.b3a4c759bb → 0.6.7-develop.6726.1.983ae8a07e
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/modules/auth/api/admin/nav.js +14 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +8 -19
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/lib/backendChrome.js +31 -14
- package/dist/modules/auth/lib/backendChrome.js.map +2 -2
- package/dist/modules/customers/api/utils.js +12 -18
- package/dist/modules/customers/api/utils.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +17 -3
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +7 -1
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/cli.js +11 -4
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +4 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +14 -10
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/batch/route.js +4 -2
- package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +20 -2
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/dashboards/lib/aggregations.js +76 -40
- package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
- package/dist/modules/dashboards/lib/exactDecimal.js +69 -0
- package/dist/modules/dashboards/lib/exactDecimal.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +228 -5
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureGuard.js +3 -2
- package/dist/modules/feature_toggles/components/FeatureGuard.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/staleTime.js +5 -0
- package/dist/modules/feature_toggles/components/hooks/staleTime.js.map +7 -0
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagJson.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagNumber.js.map +2 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js +5 -2
- package/dist/modules/feature_toggles/components/hooks/useFeatureFlagString.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/route.js +16 -1
- package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/search-reindex-proposal-created.js +32 -0
- package/dist/modules/inbox_ops/subscribers/search-reindex-proposal-created.js.map +7 -0
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +0 -5
- package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +2 -2
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js +14 -0
- package/dist/modules/integrations/widgets/injection/external-ids/widget.js.map +7 -0
- package/dist/modules/messages/lib/searchLookup.js +8 -16
- package/dist/modules/messages/lib/searchLookup.js.map +2 -2
- package/dist/modules/query_index/api/openapi.js +13 -1
- package/dist/modules/query_index/api/openapi.js.map +2 -2
- package/dist/modules/query_index/api/status.js +165 -105
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +128 -41
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/query_index/lib/batch.js +11 -4
- package/dist/modules/query_index/lib/batch.js.map +2 -2
- package/dist/modules/query_index/lib/document.js +12 -5
- package/dist/modules/query_index/lib/document.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +36 -4
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/indexer.js +1 -1
- package/dist/modules/query_index/lib/indexer.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +7 -4
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +14 -3
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +22 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +2 -35
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +2 -2
- package/dist/modules/sales/data/validators.js +25 -4
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/api/admin/nav.ts +24 -4
- package/src/modules/auth/api/users/route.ts +8 -28
- package/src/modules/auth/lib/backendChrome.tsx +51 -13
- package/src/modules/customers/api/utils.ts +12 -31
- package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +35 -3
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +10 -1
- package/src/modules/customers/cli.ts +11 -4
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +4 -0
- package/src/modules/customers/components/formConfig.tsx +12 -8
- package/src/modules/dashboards/api/widgets/data/batch/route.ts +4 -0
- package/src/modules/dashboards/api/widgets/data/route.ts +21 -0
- package/src/modules/dashboards/lib/aggregations.ts +122 -43
- package/src/modules/dashboards/lib/exactDecimal.ts +96 -0
- package/src/modules/dashboards/services/widgetDataService.ts +342 -4
- package/src/modules/feature_toggles/components/FeatureGuard.tsx +9 -2
- package/src/modules/feature_toggles/components/hooks/staleTime.ts +5 -0
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagBoolean.ts +13 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagJson.ts +12 -3
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagNumber.ts +10 -1
- package/src/modules/feature_toggles/components/hooks/useFeatureFlagString.ts +10 -1
- package/src/modules/inbox_ops/api/proposals/route.ts +20 -1
- package/src/modules/inbox_ops/subscribers/search-reindex-proposal-created.ts +39 -0
- package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +0 -5
- package/src/modules/integrations/widgets/injection/external-ids/widget.ts +13 -0
- package/src/modules/messages/lib/searchLookup.ts +11 -34
- package/src/modules/query_index/api/openapi.ts +12 -0
- package/src/modules/query_index/api/status.ts +238 -136
- package/src/modules/query_index/components/QueryIndexesTable.tsx +192 -46
- package/src/modules/query_index/i18n/de.json +5 -3
- package/src/modules/query_index/i18n/en.json +5 -3
- package/src/modules/query_index/i18n/es.json +5 -3
- package/src/modules/query_index/i18n/pl.json +5 -3
- package/src/modules/query_index/lib/batch.ts +11 -4
- package/src/modules/query_index/lib/document.ts +35 -4
- package/src/modules/query_index/lib/engine.ts +53 -5
- package/src/modules/query_index/lib/indexer.ts +1 -1
- package/src/modules/query_index/lib/search-tokens.ts +13 -4
- package/src/modules/sales/api/documents/factory.ts +28 -3
- package/src/modules/sales/commands/documents.ts +26 -2
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +2 -48
- package/src/modules/sales/data/validators.ts +50 -5
|
@@ -8,23 +8,30 @@ export type FeatureGuardProps = {
|
|
|
8
8
|
children: React.ReactNode
|
|
9
9
|
fallback?: React.ReactNode
|
|
10
10
|
loadingFallback?: React.ReactNode
|
|
11
|
+
defaultValue?: boolean
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* FeatureGuard component that conditionally renders children based on feature toggle state.
|
|
15
|
-
*
|
|
16
|
+
*
|
|
16
17
|
* @param id - The feature toggle identifier
|
|
17
18
|
* @param children - Content to render when the feature is enabled
|
|
18
19
|
* @param fallback - Optional content to render when the feature is disabled
|
|
19
20
|
* @param loadingFallback - Optional content to render while loading the feature state
|
|
21
|
+
* @param defaultValue - Toggle value assumed when the check cannot be resolved
|
|
22
|
+
* (undefined toggle, type mismatch, network or permission failure). Defaults
|
|
23
|
+
* to `false`; pass `true` to keep guarded UI visible when the check fails.
|
|
24
|
+
* Distinct from `fallback`, which is what gets rendered once the feature is
|
|
25
|
+
* known to be disabled.
|
|
20
26
|
*/
|
|
21
27
|
export function FeatureGuard({
|
|
22
28
|
id,
|
|
23
29
|
children,
|
|
24
30
|
fallback = null,
|
|
25
31
|
loadingFallback = null,
|
|
32
|
+
defaultValue = false,
|
|
26
33
|
}: FeatureGuardProps) {
|
|
27
|
-
const { enabled, isLoading } = useFeatureFlagBoolean({ id })
|
|
34
|
+
const { enabled, isLoading } = useFeatureFlagBoolean({ id, defaultValue })
|
|
28
35
|
|
|
29
36
|
if (isLoading) {
|
|
30
37
|
return <>{loadingFallback}</>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Mirrors the server-side toggle resolution cache TTL in
|
|
2
|
+
// `lib/feature-flag-check.ts`, so several components reading the same toggle
|
|
3
|
+
// share one request instead of refetching a value the server would not have
|
|
4
|
+
// re-resolved anyway.
|
|
5
|
+
export const FEATURE_FLAG_STALE_TIME_MS = 60_000
|
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
import { useQuery } from '@tanstack/react-query'
|
|
4
4
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
5
|
+
import { FEATURE_FLAG_STALE_TIME_MS } from './staleTime'
|
|
5
6
|
|
|
6
7
|
export type UseFeatureFlagOptions = {
|
|
7
8
|
id: string
|
|
9
|
+
/**
|
|
10
|
+
* Value used while the check is in flight and whenever the toggle cannot be
|
|
11
|
+
* resolved (undefined toggle, type mismatch, network or permission failure).
|
|
12
|
+
*
|
|
13
|
+
* Defaults to `false` so an unresolved toggle keeps a feature switched off.
|
|
14
|
+
* Pass `true` for toggles that hide existing UI — there a failed check must
|
|
15
|
+
* not make the feature disappear.
|
|
16
|
+
*/
|
|
17
|
+
defaultValue?: boolean
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
export type UseFeatureFlagResult = {
|
|
@@ -21,6 +31,7 @@ type Result<T> = {
|
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
export function useFeatureFlagBoolean(options: UseFeatureFlagOptions): UseFeatureFlagResult {
|
|
34
|
+
const defaultValue = options.defaultValue ?? false
|
|
24
35
|
const query = useQuery({
|
|
25
36
|
queryKey: ['featureToggles', 'check', options?.id],
|
|
26
37
|
queryFn: async () => {
|
|
@@ -37,9 +48,10 @@ export function useFeatureFlagBoolean(options: UseFeatureFlagOptions): UseFeatur
|
|
|
37
48
|
return result
|
|
38
49
|
},
|
|
39
50
|
enabled: !!options.id,
|
|
51
|
+
staleTime: FEATURE_FLAG_STALE_TIME_MS,
|
|
40
52
|
})
|
|
41
53
|
|
|
42
|
-
const enabled = query.data?.ok ? query.data.value :
|
|
54
|
+
const enabled = query.data?.ok ? query.data.value : defaultValue
|
|
43
55
|
const isLoading = query.isLoading
|
|
44
56
|
|
|
45
57
|
return {
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { useQuery } from '@tanstack/react-query'
|
|
4
4
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
5
|
+
import { FEATURE_FLAG_STALE_TIME_MS } from './staleTime'
|
|
5
6
|
|
|
6
|
-
export type UseFeatureFlagJsonOptions = {
|
|
7
|
+
export type UseFeatureFlagJsonOptions<T = unknown> = {
|
|
7
8
|
id: string
|
|
9
|
+
/**
|
|
10
|
+
* Value used while the check is in flight and whenever the toggle cannot be
|
|
11
|
+
* resolved (undefined toggle, type mismatch, network or permission failure).
|
|
12
|
+
* Defaults to `null`.
|
|
13
|
+
*/
|
|
14
|
+
defaultValue?: T | null
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
export type UseFeatureFlagJsonResult<T = unknown> = {
|
|
@@ -20,7 +27,8 @@ type Result<T> = {
|
|
|
20
27
|
error: unknown
|
|
21
28
|
}
|
|
22
29
|
|
|
23
|
-
export function useFeatureFlagJson<T = unknown>(options: UseFeatureFlagJsonOptions): UseFeatureFlagJsonResult<T> {
|
|
30
|
+
export function useFeatureFlagJson<T = unknown>(options: UseFeatureFlagJsonOptions<T>): UseFeatureFlagJsonResult<T> {
|
|
31
|
+
const defaultValue = options.defaultValue ?? null
|
|
24
32
|
const query = useQuery({
|
|
25
33
|
queryKey: ['featureToggles', 'check', 'json', options?.id],
|
|
26
34
|
queryFn: async () => {
|
|
@@ -37,9 +45,10 @@ export function useFeatureFlagJson<T = unknown>(options: UseFeatureFlagJsonOptio
|
|
|
37
45
|
return result
|
|
38
46
|
},
|
|
39
47
|
enabled: !!options.id,
|
|
48
|
+
staleTime: FEATURE_FLAG_STALE_TIME_MS,
|
|
40
49
|
})
|
|
41
50
|
|
|
42
|
-
const value = query.data?.ok ? query.data.value :
|
|
51
|
+
const value = query.data?.ok ? query.data.value : defaultValue
|
|
43
52
|
const isLoading = query.isLoading
|
|
44
53
|
|
|
45
54
|
return {
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { useQuery } from '@tanstack/react-query'
|
|
4
4
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
5
|
+
import { FEATURE_FLAG_STALE_TIME_MS } from './staleTime'
|
|
5
6
|
|
|
6
7
|
export type UseFeatureFlagNumberOptions = {
|
|
7
8
|
id: string
|
|
9
|
+
/**
|
|
10
|
+
* Value used while the check is in flight and whenever the toggle cannot be
|
|
11
|
+
* resolved (undefined toggle, type mismatch, network or permission failure).
|
|
12
|
+
* Defaults to `null`.
|
|
13
|
+
*/
|
|
14
|
+
defaultValue?: number | null
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
export type UseFeatureFlagNumberResult = {
|
|
@@ -21,6 +28,7 @@ type Result<T> = {
|
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
export function useFeatureFlagNumber(options: UseFeatureFlagNumberOptions): UseFeatureFlagNumberResult {
|
|
31
|
+
const defaultValue = options.defaultValue ?? null
|
|
24
32
|
const query = useQuery({
|
|
25
33
|
queryKey: ['featureToggles', 'check', 'number', options?.id],
|
|
26
34
|
queryFn: async () => {
|
|
@@ -37,9 +45,10 @@ export function useFeatureFlagNumber(options: UseFeatureFlagNumberOptions): UseF
|
|
|
37
45
|
return result
|
|
38
46
|
},
|
|
39
47
|
enabled: !!options.id,
|
|
48
|
+
staleTime: FEATURE_FLAG_STALE_TIME_MS,
|
|
40
49
|
})
|
|
41
50
|
|
|
42
|
-
const value = query.data?.ok ? query.data.value :
|
|
51
|
+
const value = query.data?.ok ? query.data.value : defaultValue
|
|
43
52
|
const isLoading = query.isLoading
|
|
44
53
|
|
|
45
54
|
return {
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { useQuery } from '@tanstack/react-query'
|
|
4
4
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
5
|
+
import { FEATURE_FLAG_STALE_TIME_MS } from './staleTime'
|
|
5
6
|
|
|
6
7
|
export type UseFeatureFlagStringOptions = {
|
|
7
8
|
id: string
|
|
9
|
+
/**
|
|
10
|
+
* Value used while the check is in flight and whenever the toggle cannot be
|
|
11
|
+
* resolved (undefined toggle, type mismatch, network or permission failure).
|
|
12
|
+
* Defaults to `null`.
|
|
13
|
+
*/
|
|
14
|
+
defaultValue?: string | null
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
export type UseFeatureFlagStringResult = {
|
|
@@ -21,6 +28,7 @@ type Result<T> = {
|
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
export function useFeatureFlagString(options: UseFeatureFlagStringOptions): UseFeatureFlagStringResult {
|
|
31
|
+
const defaultValue = options.defaultValue ?? null
|
|
24
32
|
const query = useQuery({
|
|
25
33
|
queryKey: ['featureToggles', 'check', 'string', options?.id],
|
|
26
34
|
queryFn: async () => {
|
|
@@ -37,9 +45,10 @@ export function useFeatureFlagString(options: UseFeatureFlagStringOptions): UseF
|
|
|
37
45
|
return result
|
|
38
46
|
},
|
|
39
47
|
enabled: !!options.id,
|
|
48
|
+
staleTime: FEATURE_FLAG_STALE_TIME_MS,
|
|
40
49
|
})
|
|
41
50
|
|
|
42
|
-
const value = query.data?.ok ? query.data.value :
|
|
51
|
+
const value = query.data?.ok ? query.data.value : defaultValue
|
|
43
52
|
const isLoading = query.isLoading
|
|
44
53
|
|
|
45
54
|
return {
|
|
@@ -4,6 +4,8 @@ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
|
4
4
|
import type { FilterQuery } from '@mikro-orm/postgresql'
|
|
5
5
|
import { findAndCountWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
6
6
|
import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
|
|
7
|
+
import { findEntityIdsBySearchTokens, type SearchTokenDatabase } from '@open-mercato/shared/lib/search/tokenLookup'
|
|
8
|
+
import { E } from '#generated/entities.ids.generated'
|
|
7
9
|
import { InboxProposal, InboxEmail, InboxProposalAction, InboxDiscrepancy, type InboxProposalCategory } from '../../data/entities'
|
|
8
10
|
import { proposalListQuerySchema } from '../../data/validators'
|
|
9
11
|
import { resolveRequestContext, UnauthorizedError } from '../routeHelpers'
|
|
@@ -47,7 +49,24 @@ export async function GET(req: Request) {
|
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
if (query.search) {
|
|
50
|
-
|
|
52
|
+
// `summary` is covered by the inbox_ops encryption map, so an ILIKE alone
|
|
53
|
+
// compares the pattern against ciphertext and matches nothing once
|
|
54
|
+
// encryption is on. Union it with the token index, which stores hashes of
|
|
55
|
+
// the plaintext. Issue #2990.
|
|
56
|
+
const searchOr: FilterQuery<InboxProposal>[] = [
|
|
57
|
+
{ summary: { $ilike: `%${escapeLikePattern(query.search)}%` } },
|
|
58
|
+
]
|
|
59
|
+
const tokenMatch = await findEntityIdsBySearchTokens({
|
|
60
|
+
db: ctx.em.getKysely<SearchTokenDatabase>(),
|
|
61
|
+
entityType: E.inbox_ops.inbox_proposal,
|
|
62
|
+
query: query.search,
|
|
63
|
+
fields: ['summary'],
|
|
64
|
+
scope: { tenantId: ctx.tenantId, organizationId: ctx.organizationId },
|
|
65
|
+
})
|
|
66
|
+
if (tokenMatch.matched && tokenMatch.ids.length) {
|
|
67
|
+
searchOr.push({ id: { $in: tokenMatch.ids } })
|
|
68
|
+
}
|
|
69
|
+
where.$or = searchOr
|
|
51
70
|
}
|
|
52
71
|
|
|
53
72
|
const offset = (query.page - 1) * query.pageSize
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const metadata = {
|
|
2
|
+
event: 'inbox_ops.proposal.created',
|
|
3
|
+
persistent: false,
|
|
4
|
+
id: 'inbox_ops:query-index-reindex-proposal-created',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type Payload = {
|
|
8
|
+
proposalId?: string
|
|
9
|
+
tenantId?: string | null
|
|
10
|
+
organizationId?: string | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type EventBus = { emitEvent: (name: string, body: unknown, options?: unknown) => Promise<void> }
|
|
14
|
+
type HandlerContext = { resolve: <T = unknown>(name: string) => T }
|
|
15
|
+
|
|
16
|
+
export default async function handle(payload: Payload, ctx: HandlerContext): Promise<void> {
|
|
17
|
+
const recordId = typeof payload.proposalId === 'string' ? payload.proposalId : null
|
|
18
|
+
const tenantId = typeof payload.tenantId === 'string' ? payload.tenantId : null
|
|
19
|
+
if (!recordId || !tenantId) return
|
|
20
|
+
|
|
21
|
+
let eventBus: EventBus | null = null
|
|
22
|
+
try {
|
|
23
|
+
eventBus = ctx.resolve<EventBus>('eventBus')
|
|
24
|
+
} catch {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await eventBus.emitEvent('query_index.upsert_one', {
|
|
29
|
+
entityType: 'inbox_ops:inbox_proposal',
|
|
30
|
+
recordId,
|
|
31
|
+
organizationId: payload.organizationId ?? null,
|
|
32
|
+
tenantId,
|
|
33
|
+
crudAction: 'created',
|
|
34
|
+
coverageBaseDelta: 1,
|
|
35
|
+
}, {
|
|
36
|
+
tenantId,
|
|
37
|
+
organizationId: payload.organizationId ?? null,
|
|
38
|
+
}).catch(() => undefined)
|
|
39
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InjectionWidgetModule } from '@open-mercato/shared/modules/widgets/injection'
|
|
2
|
+
import ExternalIdsWidget from './widget.client'
|
|
3
|
+
|
|
4
|
+
const widget: InjectionWidgetModule = {
|
|
5
|
+
metadata: {
|
|
6
|
+
id: 'integrations.injection.external-ids',
|
|
7
|
+
title: 'External IDs',
|
|
8
|
+
features: ['integrations.view'],
|
|
9
|
+
},
|
|
10
|
+
Widget: ExternalIdsWidget,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default widget
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { tokenizeText } from '@open-mercato/shared/lib/search/tokenize'
|
|
2
|
+
import type { Kysely } from 'kysely'
|
|
3
|
+
import { findEntityIdsBySearchTokensCompat, type SearchTokenDatabase } from '@open-mercato/shared/lib/search/tokenLookup'
|
|
5
4
|
|
|
6
|
-
function getDb(em: EntityManager): Kysely<
|
|
7
|
-
return em.getKysely<
|
|
5
|
+
function getDb(em: EntityManager): Kysely<SearchTokenDatabase> {
|
|
6
|
+
return em.getKysely<SearchTokenDatabase>()
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
export async function findMessageIdsBySearchTokens({
|
|
@@ -20,33 +19,11 @@ export async function findMessageIdsBySearchTokens({
|
|
|
20
19
|
organizationId: string | null
|
|
21
20
|
fields?: string[]
|
|
22
21
|
}): Promise<string[] | null> {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
let searchQuery = db
|
|
31
|
-
.selectFrom('search_tokens')
|
|
32
|
-
.select('entity_id')
|
|
33
|
-
.where('entity_type', '=', 'messages:message')
|
|
34
|
-
.where('field', 'in', fields)
|
|
35
|
-
.where('token_hash', 'in', tokens.hashes)
|
|
36
|
-
.where(sql<boolean>`tenant_id is not distinct from ${tenantId}`)
|
|
37
|
-
|
|
38
|
-
if (organizationId) {
|
|
39
|
-
searchQuery = searchQuery.where('organization_id', '=', organizationId)
|
|
40
|
-
} else {
|
|
41
|
-
searchQuery = searchQuery.where(sql<boolean>`organization_id is not distinct from ${null}`)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const rows = await searchQuery
|
|
45
|
-
.groupBy('entity_id')
|
|
46
|
-
.having(sql<boolean>`count(distinct token_hash) >= ${tokens.hashes.length}`)
|
|
47
|
-
.execute()
|
|
48
|
-
|
|
49
|
-
return rows
|
|
50
|
-
.map((row: { entity_id?: unknown }) => (typeof row.entity_id === 'string' ? row.entity_id : null))
|
|
51
|
-
.filter((id: string | null): id is string => typeof id === 'string' && id.length > 0)
|
|
22
|
+
return findEntityIdsBySearchTokensCompat({
|
|
23
|
+
db: getDb(em),
|
|
24
|
+
entityType: 'messages:message',
|
|
25
|
+
query,
|
|
26
|
+
fields,
|
|
27
|
+
scope: { tenantId, organizationId },
|
|
28
|
+
})
|
|
52
29
|
}
|
|
@@ -37,13 +37,25 @@ export const queryIndexJobSchema = z.object({
|
|
|
37
37
|
|
|
38
38
|
export const queryIndexStatusItemSchema = z.object({
|
|
39
39
|
entityId: z.string(),
|
|
40
|
+
/** Human label. Code-defined entities have no label registry, so this mirrors `entityId`. */
|
|
40
41
|
label: z.string(),
|
|
41
42
|
baseCount: z.number().int().nonnegative().nullable(),
|
|
42
43
|
indexCount: z.number().int().nonnegative().nullable(),
|
|
43
44
|
vectorCount: z.number().int().nonnegative().nullable().optional(),
|
|
45
|
+
/** The entity declares `buildSource`, i.e. it is configured for vector search. */
|
|
44
46
|
vectorEnabled: z.boolean().optional(),
|
|
47
|
+
/** Additive: vector indexing can actually run (auto-indexing on, provider reachable, tenant opted in). */
|
|
48
|
+
vectorIndexingActive: z.boolean().optional(),
|
|
49
|
+
fulltextCount: z.number().int().nonnegative().nullable().optional(),
|
|
50
|
+
fulltextEnabled: z.boolean().optional(),
|
|
51
|
+
/** Additive: the entity has active custom field definitions in the current scope. */
|
|
52
|
+
hasCustomFields: z.boolean().optional(),
|
|
53
|
+
/** Aggregate health: query index in sync AND, when vector-configured, vector coverage complete. */
|
|
45
54
|
ok: z.boolean(),
|
|
55
|
+
/** Additive: query index alone is in sync with the base table, independent of vector/fulltext. */
|
|
56
|
+
queryIndexOk: z.boolean().optional(),
|
|
46
57
|
job: queryIndexJobSchema,
|
|
58
|
+
refreshedAt: z.string().datetime().nullable().optional(),
|
|
47
59
|
})
|
|
48
60
|
|
|
49
61
|
export const queryIndexErrorLogSchema = z.object({
|