@memberjunction/search-engine 5.32.0 → 5.34.0
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/dist/generic/BaseReRanker.d.ts +164 -0
- package/dist/generic/BaseReRanker.d.ts.map +1 -0
- package/dist/generic/BaseReRanker.js +209 -0
- package/dist/generic/BaseReRanker.js.map +1 -0
- package/dist/generic/EntitySearchProvider.d.ts +51 -3
- package/dist/generic/EntitySearchProvider.d.ts.map +1 -1
- package/dist/generic/EntitySearchProvider.js +130 -17
- package/dist/generic/EntitySearchProvider.js.map +1 -1
- package/dist/generic/FullTextSearchProvider.d.ts +7 -2
- package/dist/generic/FullTextSearchProvider.d.ts.map +1 -1
- package/dist/generic/FullTextSearchProvider.js +25 -4
- package/dist/generic/FullTextSearchProvider.js.map +1 -1
- package/dist/generic/ISearchProvider.d.ts +44 -2
- package/dist/generic/ISearchProvider.d.ts.map +1 -1
- package/dist/generic/ISearchProvider.js +35 -1
- package/dist/generic/ISearchProvider.js.map +1 -1
- package/dist/generic/NoopReRanker.d.ts +28 -0
- package/dist/generic/NoopReRanker.d.ts.map +1 -0
- package/dist/generic/NoopReRanker.js +49 -0
- package/dist/generic/NoopReRanker.js.map +1 -0
- package/dist/generic/ScopeTemplateRenderer.d.ts +36 -0
- package/dist/generic/ScopeTemplateRenderer.d.ts.map +1 -0
- package/dist/generic/ScopeTemplateRenderer.js +110 -0
- package/dist/generic/ScopeTemplateRenderer.js.map +1 -0
- package/dist/generic/SearchEngine.d.ts +180 -12
- package/dist/generic/SearchEngine.d.ts.map +1 -1
- package/dist/generic/SearchEngine.js +737 -35
- package/dist/generic/SearchEngine.js.map +1 -1
- package/dist/generic/SearchFusion.d.ts +40 -6
- package/dist/generic/SearchFusion.d.ts.map +1 -1
- package/dist/generic/SearchFusion.js +139 -18
- package/dist/generic/SearchFusion.js.map +1 -1
- package/dist/generic/StorageSearchProvider.d.ts +9 -2
- package/dist/generic/StorageSearchProvider.d.ts.map +1 -1
- package/dist/generic/StorageSearchProvider.js +44 -12
- package/dist/generic/StorageSearchProvider.js.map +1 -1
- package/dist/generic/VectorSearchProvider.d.ts +9 -2
- package/dist/generic/VectorSearchProvider.d.ts.map +1 -1
- package/dist/generic/VectorSearchProvider.js +83 -13
- package/dist/generic/VectorSearchProvider.js.map +1 -1
- package/dist/generic/search.types.d.ts +206 -0
- package/dist/generic/search.types.d.ts.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions/SearchScopePermissionResolver.d.ts +109 -0
- package/dist/permissions/SearchScopePermissionResolver.d.ts.map +1 -0
- package/dist/permissions/SearchScopePermissionResolver.js +159 -0
- package/dist/permissions/SearchScopePermissionResolver.js.map +1 -0
- package/dist/providers/AzureAISearchProvider.d.ts +37 -0
- package/dist/providers/AzureAISearchProvider.d.ts.map +1 -0
- package/dist/providers/AzureAISearchProvider.js +180 -0
- package/dist/providers/AzureAISearchProvider.js.map +1 -0
- package/dist/providers/ElasticsearchSearchProvider.d.ts +43 -0
- package/dist/providers/ElasticsearchSearchProvider.d.ts.map +1 -0
- package/dist/providers/ElasticsearchSearchProvider.js +200 -0
- package/dist/providers/ElasticsearchSearchProvider.js.map +1 -0
- package/dist/providers/OpenSearchSearchProvider.d.ts +36 -0
- package/dist/providers/OpenSearchSearchProvider.d.ts.map +1 -0
- package/dist/providers/OpenSearchSearchProvider.js +167 -0
- package/dist/providers/OpenSearchSearchProvider.js.map +1 -0
- package/dist/providers/TypesenseSearchProvider.d.ts +36 -0
- package/dist/providers/TypesenseSearchProvider.d.ts.map +1 -0
- package/dist/providers/TypesenseSearchProvider.js +161 -0
- package/dist/providers/TypesenseSearchProvider.js.map +1 -0
- package/dist/rerankers/BGEReRanker.d.ts +57 -0
- package/dist/rerankers/BGEReRanker.d.ts.map +1 -0
- package/dist/rerankers/BGEReRanker.js +193 -0
- package/dist/rerankers/BGEReRanker.js.map +1 -0
- package/dist/rerankers/CohereReRanker.d.ts +65 -0
- package/dist/rerankers/CohereReRanker.d.ts.map +1 -0
- package/dist/rerankers/CohereReRanker.js +155 -0
- package/dist/rerankers/CohereReRanker.js.map +1 -0
- package/dist/rerankers/OpenAIReRanker.d.ts +62 -0
- package/dist/rerankers/OpenAIReRanker.d.ts.map +1 -0
- package/dist/rerankers/OpenAIReRanker.js +197 -0
- package/dist/rerankers/OpenAIReRanker.js.map +1 -0
- package/dist/rerankers/RerankerBudgetGuard.d.ts +54 -0
- package/dist/rerankers/RerankerBudgetGuard.d.ts.map +1 -0
- package/dist/rerankers/RerankerBudgetGuard.js +67 -0
- package/dist/rerankers/RerankerBudgetGuard.js.map +1 -0
- package/dist/rerankers/VoyageReRanker.d.ts +59 -0
- package/dist/rerankers/VoyageReRanker.d.ts.map +1 -0
- package/dist/rerankers/VoyageReRanker.js +184 -0
- package/dist/rerankers/VoyageReRanker.js.map +1 -0
- package/package.json +13 -8
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { UserInfo } from '@memberjunction/core';
|
|
2
|
+
import type { MJSearchScopePermissionEntity, MJAIAgentEntity } from '@memberjunction/core-entities';
|
|
3
|
+
/**
|
|
4
|
+
* Permission level granted on a SearchScope. None is an explicit deny that
|
|
5
|
+
* overrides role grants for that scope/principal pair. The resolver collapses
|
|
6
|
+
* multiple grants into the highest level (Manage > Search > Read > None).
|
|
7
|
+
*/
|
|
8
|
+
export type SearchScopePermissionLevel = 'None' | 'Read' | 'Search' | 'Manage';
|
|
9
|
+
/**
|
|
10
|
+
* Where the resolver picked up the effective permission. Used for audit
|
|
11
|
+
* logging and explanatory error messages.
|
|
12
|
+
*/
|
|
13
|
+
export type SearchScopePermissionSource = 'DirectGrant' | 'RoleGrant' | 'AgentUnscopedAll' | 'AgentNone' | 'AgentAssignedNotListed' | 'NoGrant';
|
|
14
|
+
export interface EffectivePermission {
|
|
15
|
+
/** True when the principal can at least read the scope's metadata. */
|
|
16
|
+
readonly Allowed: boolean;
|
|
17
|
+
/** Highest level granted, or 'None' when no grant applies. */
|
|
18
|
+
readonly Level: SearchScopePermissionLevel;
|
|
19
|
+
/** Where the decision came from. */
|
|
20
|
+
readonly Source: SearchScopePermissionSource;
|
|
21
|
+
/** Human-readable explanation suitable for audit logs and error messages. */
|
|
22
|
+
readonly Reason: string;
|
|
23
|
+
/**
|
|
24
|
+
* Renders the effective permission as a SQL predicate fragment that can
|
|
25
|
+
* be ANDed into a provider's WHERE clause. Returns '1=1' when the
|
|
26
|
+
* permission allows unrestricted access for this scope, '1=0' when it
|
|
27
|
+
* rejects entirely. Providers that translate to non-SQL DSLs should
|
|
28
|
+
* inspect Allowed/Level instead — the predicate is for SQL Server-backed
|
|
29
|
+
* providers and is intentionally trivial today; richer per-scope filters
|
|
30
|
+
* live in the SearchScope.ScopeConfig template.
|
|
31
|
+
*/
|
|
32
|
+
toSqlPredicate(): string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Inputs required to resolve a permission. The resolver is server-side only
|
|
36
|
+
* and never reaches into request context — caller passes the identities it
|
|
37
|
+
* has already established.
|
|
38
|
+
*/
|
|
39
|
+
export interface ResolvePermissionInput {
|
|
40
|
+
/**
|
|
41
|
+
* The acting user. Required even when an agent is invoking the search,
|
|
42
|
+
* because agent-mediated calls still authenticate as a user and any
|
|
43
|
+
* direct/role grants on that user ID still apply.
|
|
44
|
+
*/
|
|
45
|
+
User: UserInfo;
|
|
46
|
+
/** The SearchScope being authorized. */
|
|
47
|
+
SearchScopeID: string;
|
|
48
|
+
/**
|
|
49
|
+
* The agent on whose behalf the search runs, or null for human-driven
|
|
50
|
+
* searches. When set, the agent's SearchScopeAccess column gates the
|
|
51
|
+
* fallback paths.
|
|
52
|
+
*/
|
|
53
|
+
Agent: MJAIAgentEntity | null;
|
|
54
|
+
/**
|
|
55
|
+
* Optional ContextUser for RunView calls. Server-side code must always
|
|
56
|
+
* pass this to enforce data isolation; it is the same UserInfo as `User`
|
|
57
|
+
* unless the caller is impersonating.
|
|
58
|
+
*/
|
|
59
|
+
ContextUser?: UserInfo;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolves the effective SearchScope permission for a (user, scope, agent)
|
|
63
|
+
* triple.
|
|
64
|
+
*
|
|
65
|
+
* Resolution order (later steps only run if the earlier did not produce a
|
|
66
|
+
* definitive answer):
|
|
67
|
+
*
|
|
68
|
+
* 1. Agent.SearchScopeAccess === 'None' → reject (explicit agent-side deny).
|
|
69
|
+
* 2. Direct grant: a SearchScopePermission row with UserID = user.ID and
|
|
70
|
+
* SearchScopeID = scope.ID. PermissionLevel = 'None' is an explicit
|
|
71
|
+
* deny that short-circuits and rejects regardless of role grants.
|
|
72
|
+
* 3. Role grants: SearchScopePermission rows where RoleID is in the
|
|
73
|
+
* user's UserRoles. The highest non-None level wins. None entries are
|
|
74
|
+
* ignored at the role level (see comment below).
|
|
75
|
+
* 4. Agent.SearchScopeAccess === 'All' → allow at Search level (lets
|
|
76
|
+
* trusted agents act across all scopes when no user-side grant exists).
|
|
77
|
+
* 5. No grant → reject.
|
|
78
|
+
*
|
|
79
|
+
* The user-direct-None rule (step 2) is intentional: an admin who explicitly
|
|
80
|
+
* denies a user on a scope should not have that decision overridden by a
|
|
81
|
+
* role membership the user happens to also hold. Role-level None entries
|
|
82
|
+
* are not authoritative because they are usually authored as a placeholder
|
|
83
|
+
* (e.g., to make a row exist before granting it later) and would create
|
|
84
|
+
* surprising lockouts when a user joins a role.
|
|
85
|
+
*/
|
|
86
|
+
export declare class SearchScopePermissionResolver {
|
|
87
|
+
/**
|
|
88
|
+
* Resolves the effective permission. All UUID comparisons go through
|
|
89
|
+
* UUIDsEqual to remain case-insensitive across SQL Server / PostgreSQL.
|
|
90
|
+
*/
|
|
91
|
+
ResolveEffectivePermission(input: ResolvePermissionInput): Promise<EffectivePermission>;
|
|
92
|
+
/**
|
|
93
|
+
* Checks whether the given scope is in the agent's assigned-scope list
|
|
94
|
+
* via __mj.AIAgentSearchScope. Used to enforce the SearchScopeAccess='Assigned'
|
|
95
|
+
* deny-list rule. Returns true when at least one matching row exists with
|
|
96
|
+
* Status='Active'; false otherwise.
|
|
97
|
+
*/
|
|
98
|
+
protected isScopeAssignedToAgent(agentID: string, searchScopeID: string, contextUser: UserInfo): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Loads all SearchScopePermission rows scoped to the given SearchScope.
|
|
101
|
+
* Caller-supplied ContextUser ensures the RunView runs under the same
|
|
102
|
+
* identity the rest of the request is using.
|
|
103
|
+
*/
|
|
104
|
+
protected loadPermissionsForScope(searchScopeID: string, contextUser: UserInfo): Promise<MJSearchScopePermissionEntity[]>;
|
|
105
|
+
/** Bundles the result fields together with a closure-bound toSqlPredicate. */
|
|
106
|
+
private buildResult;
|
|
107
|
+
}
|
|
108
|
+
export declare const DefaultSearchScopePermissionResolver: SearchScopePermissionResolver;
|
|
109
|
+
//# sourceMappingURL=SearchScopePermissionResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchScopePermissionResolver.d.ts","sourceRoot":"","sources":["../../src/permissions/SearchScopePermissionResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEpG;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GACjC,aAAa,GACb,WAAW,GACX,kBAAkB,GAClB,WAAW,GACX,wBAAwB,GACxB,SAAS,CAAC;AAEhB,MAAM,WAAW,mBAAmB;IAChC,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,0BAA0B,CAAC;IAC3C,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,cAAc,IAAI,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACnC;;;;OAIG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,6BAA6B;IACtC;;;OAGG;IACU,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAmEpG;;;;;OAKG;cACa,sBAAsB,CAClC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,OAAO,CAAC;IAmBnB;;;;OAIG;cACa,uBAAuB,CACnC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,6BAA6B,EAAE,CAAC;IAqB3C,8EAA8E;IAC9E,OAAO,CAAC,WAAW;CActB;AAID,eAAO,MAAM,oCAAoC,+BAAsC,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { RunView } from '@memberjunction/core';
|
|
2
|
+
import { UUIDsEqual } from '@memberjunction/global';
|
|
3
|
+
const LEVEL_RANK = {
|
|
4
|
+
None: 0,
|
|
5
|
+
Read: 1,
|
|
6
|
+
Search: 2,
|
|
7
|
+
Manage: 3,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Picks the highest level between two grants. None is treated as the lowest
|
|
11
|
+
* (a None row from a role does not deny when a Read row exists for the user
|
|
12
|
+
* directly — the explicit deny is only authoritative when it is the user's
|
|
13
|
+
* own direct grant; see resolution-order rules below).
|
|
14
|
+
*/
|
|
15
|
+
function highestLevel(a, b) {
|
|
16
|
+
return LEVEL_RANK[a] >= LEVEL_RANK[b] ? a : b;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolves the effective SearchScope permission for a (user, scope, agent)
|
|
20
|
+
* triple.
|
|
21
|
+
*
|
|
22
|
+
* Resolution order (later steps only run if the earlier did not produce a
|
|
23
|
+
* definitive answer):
|
|
24
|
+
*
|
|
25
|
+
* 1. Agent.SearchScopeAccess === 'None' → reject (explicit agent-side deny).
|
|
26
|
+
* 2. Direct grant: a SearchScopePermission row with UserID = user.ID and
|
|
27
|
+
* SearchScopeID = scope.ID. PermissionLevel = 'None' is an explicit
|
|
28
|
+
* deny that short-circuits and rejects regardless of role grants.
|
|
29
|
+
* 3. Role grants: SearchScopePermission rows where RoleID is in the
|
|
30
|
+
* user's UserRoles. The highest non-None level wins. None entries are
|
|
31
|
+
* ignored at the role level (see comment below).
|
|
32
|
+
* 4. Agent.SearchScopeAccess === 'All' → allow at Search level (lets
|
|
33
|
+
* trusted agents act across all scopes when no user-side grant exists).
|
|
34
|
+
* 5. No grant → reject.
|
|
35
|
+
*
|
|
36
|
+
* The user-direct-None rule (step 2) is intentional: an admin who explicitly
|
|
37
|
+
* denies a user on a scope should not have that decision overridden by a
|
|
38
|
+
* role membership the user happens to also hold. Role-level None entries
|
|
39
|
+
* are not authoritative because they are usually authored as a placeholder
|
|
40
|
+
* (e.g., to make a row exist before granting it later) and would create
|
|
41
|
+
* surprising lockouts when a user joins a role.
|
|
42
|
+
*/
|
|
43
|
+
export class SearchScopePermissionResolver {
|
|
44
|
+
/**
|
|
45
|
+
* Resolves the effective permission. All UUID comparisons go through
|
|
46
|
+
* UUIDsEqual to remain case-insensitive across SQL Server / PostgreSQL.
|
|
47
|
+
*/
|
|
48
|
+
async ResolveEffectivePermission(input) {
|
|
49
|
+
const { User, SearchScopeID, Agent } = input;
|
|
50
|
+
const contextUser = input.ContextUser ?? User;
|
|
51
|
+
// Step 1: agent-side explicit deny short-circuits everything.
|
|
52
|
+
if (Agent && Agent.SearchScopeAccess === 'None') {
|
|
53
|
+
return this.buildResult(false, 'None', 'AgentNone', `Agent '${Agent.Name}' has SearchScopeAccess='None'; refused without consulting per-scope grants.`);
|
|
54
|
+
}
|
|
55
|
+
// Step 1b: agent-side Assigned restriction. When SearchScopeAccess='Assigned'
|
|
56
|
+
// the agent can ONLY use scopes listed in __mj.AIAgentSearchScope for
|
|
57
|
+
// this agent. If the scope isn't in that list, deny early before
|
|
58
|
+
// consulting per-user grants — this is a deny-list, not a grant.
|
|
59
|
+
if (Agent && Agent.SearchScopeAccess === 'Assigned') {
|
|
60
|
+
const isListed = await this.isScopeAssignedToAgent(Agent.ID, SearchScopeID, contextUser);
|
|
61
|
+
if (!isListed) {
|
|
62
|
+
return this.buildResult(false, 'None', 'AgentAssignedNotListed', `Agent '${Agent.Name}' has SearchScopeAccess='Assigned' and this scope is not in its assigned scope list; refused with ACCESS_DENIED.`);
|
|
63
|
+
}
|
|
64
|
+
// Falls through to user/role checks; Assigned restricts but does
|
|
65
|
+
// not grant — the user must still have a per-scope grant.
|
|
66
|
+
}
|
|
67
|
+
// Load all SearchScopePermission rows for this scope. We pull the
|
|
68
|
+
// whole set (typically small per scope) and filter in JS so we can
|
|
69
|
+
// apply the user-direct-None short-circuit deterministically.
|
|
70
|
+
const rows = await this.loadPermissionsForScope(SearchScopeID, contextUser);
|
|
71
|
+
// Step 2: direct grant for this user (highest priority).
|
|
72
|
+
const userGrants = rows.filter(r => r.UserID && UUIDsEqual(r.UserID, User.ID));
|
|
73
|
+
if (userGrants.length > 0) {
|
|
74
|
+
// If any user-direct row is None, that is an explicit deny.
|
|
75
|
+
if (userGrants.some(r => r.PermissionLevel === 'None')) {
|
|
76
|
+
return this.buildResult(false, 'None', 'DirectGrant', `User '${User.Name}' has an explicit None grant on this scope; refused.`);
|
|
77
|
+
}
|
|
78
|
+
const level = userGrants.reduce((acc, r) => highestLevel(acc, r.PermissionLevel), 'None');
|
|
79
|
+
return this.buildResult(true, level, 'DirectGrant', `User '${User.Name}' has a direct grant at level '${level}' on this scope.`);
|
|
80
|
+
}
|
|
81
|
+
// Step 3: role grants. Match any of the user's roles to a row's RoleID.
|
|
82
|
+
const userRoleIds = User.UserRoles?.map(ur => ur.RoleID) ?? [];
|
|
83
|
+
const roleGrants = rows.filter(r => r.RoleID
|
|
84
|
+
&& userRoleIds.some(uid => UUIDsEqual(uid, r.RoleID))
|
|
85
|
+
&& r.PermissionLevel !== 'None');
|
|
86
|
+
if (roleGrants.length > 0) {
|
|
87
|
+
const level = roleGrants.reduce((acc, r) => highestLevel(acc, r.PermissionLevel), 'None');
|
|
88
|
+
return this.buildResult(true, level, 'RoleGrant', `User '${User.Name}' inherits level '${level}' on this scope through role membership.`);
|
|
89
|
+
}
|
|
90
|
+
// Step 4: agent fallback. SearchScopeAccess='All' lets trusted agents
|
|
91
|
+
// operate across scopes when the user has no per-scope grant.
|
|
92
|
+
if (Agent && Agent.SearchScopeAccess === 'All') {
|
|
93
|
+
return this.buildResult(true, 'Search', 'AgentUnscopedAll', `Agent '${Agent.Name}' has SearchScopeAccess='All'; granting 'Search' as a fallback for this scope.`);
|
|
94
|
+
}
|
|
95
|
+
// Step 5: no grant.
|
|
96
|
+
return this.buildResult(false, 'None', 'NoGrant', `User '${User.Name}' has no direct grant, no qualifying role grant, and no agent-side fallback for this scope.`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Checks whether the given scope is in the agent's assigned-scope list
|
|
100
|
+
* via __mj.AIAgentSearchScope. Used to enforce the SearchScopeAccess='Assigned'
|
|
101
|
+
* deny-list rule. Returns true when at least one matching row exists with
|
|
102
|
+
* Status='Active'; false otherwise.
|
|
103
|
+
*/
|
|
104
|
+
async isScopeAssignedToAgent(agentID, searchScopeID, contextUser) {
|
|
105
|
+
const rv = new RunView();
|
|
106
|
+
const result = await rv.RunView({
|
|
107
|
+
EntityName: 'MJ: AI Agent Search Scopes',
|
|
108
|
+
ExtraFilter: `AgentID='${agentID}' AND SearchScopeID='${searchScopeID}' AND Status='Active'`,
|
|
109
|
+
Fields: ['ID'],
|
|
110
|
+
ResultType: 'simple',
|
|
111
|
+
// Same fail-closed semantics as loadPermissionsForScope: a stale
|
|
112
|
+
// cache must never let an Assigned-mode agent reach a scope it
|
|
113
|
+
// shouldn't.
|
|
114
|
+
BypassCache: true,
|
|
115
|
+
}, contextUser);
|
|
116
|
+
if (!result.Success) {
|
|
117
|
+
throw new Error(`SearchScopePermissionResolver: failed to load AIAgentSearchScope rows for agent ${agentID}, scope ${searchScopeID}: ${result.ErrorMessage}`);
|
|
118
|
+
}
|
|
119
|
+
return (result.Results?.length ?? 0) > 0;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Loads all SearchScopePermission rows scoped to the given SearchScope.
|
|
123
|
+
* Caller-supplied ContextUser ensures the RunView runs under the same
|
|
124
|
+
* identity the rest of the request is using.
|
|
125
|
+
*/
|
|
126
|
+
async loadPermissionsForScope(searchScopeID, contextUser) {
|
|
127
|
+
const rv = new RunView();
|
|
128
|
+
const result = await rv.RunView({
|
|
129
|
+
EntityName: 'MJ: Search Scope Permissions',
|
|
130
|
+
ExtraFilter: `SearchScopeID='${searchScopeID}'`,
|
|
131
|
+
ResultType: 'simple',
|
|
132
|
+
// Permission decisions must NEVER read stale cache — a freshly-revoked grant
|
|
133
|
+
// or a freshly-granted permission must take effect immediately. Skipping
|
|
134
|
+
// the server-side RunView cache adds one DB query per resolver call but
|
|
135
|
+
// eliminates the security-correctness risk of a delayed permission update.
|
|
136
|
+
BypassCache: true,
|
|
137
|
+
}, contextUser);
|
|
138
|
+
if (!result.Success) {
|
|
139
|
+
// Fail closed: an unreadable permissions table cannot be treated
|
|
140
|
+
// as "no permissions exist".
|
|
141
|
+
throw new Error(`SearchScopePermissionResolver: failed to load permissions for scope ${searchScopeID}: ${result.ErrorMessage}`);
|
|
142
|
+
}
|
|
143
|
+
return result.Results ?? [];
|
|
144
|
+
}
|
|
145
|
+
/** Bundles the result fields together with a closure-bound toSqlPredicate. */
|
|
146
|
+
buildResult(allowed, level, source, reason) {
|
|
147
|
+
return {
|
|
148
|
+
Allowed: allowed,
|
|
149
|
+
Level: level,
|
|
150
|
+
Source: source,
|
|
151
|
+
Reason: reason,
|
|
152
|
+
toSqlPredicate: () => allowed ? '1=1' : '1=0',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Hint to consumers: keep one resolver per request unless you genuinely
|
|
157
|
+
// need a different policy. The class is stateless; instantiation is cheap.
|
|
158
|
+
export const DefaultSearchScopePermissionResolver = new SearchScopePermissionResolver();
|
|
159
|
+
//# sourceMappingURL=SearchScopePermissionResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchScopePermissionResolver.js","sourceRoot":"","sources":["../../src/permissions/SearchScopePermissionResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Azure AI Search provider for the SearchEngine (P5.3).
|
|
3
|
+
*
|
|
4
|
+
* Calls Azure AI Search's `docs/search` REST endpoint directly via fetch.
|
|
5
|
+
* Azure AI Search's filter syntax is OData ($filter), passed through as a
|
|
6
|
+
* pre-rendered string from the scope's `MetadataFilter`. Permission /
|
|
7
|
+
* tenant push-down lives entirely in that filter — no post-fusion filtering.
|
|
8
|
+
*
|
|
9
|
+
* **Connection options** (from `SearchProviderConfig.ProviderConfig`):
|
|
10
|
+
* - `serviceName` — Azure AI Search service short name (combined with
|
|
11
|
+
* `.search.windows.net`); OR
|
|
12
|
+
* - `endpoint` — full HTTPS endpoint URL (e.g. `https://my.search.windows.net`)
|
|
13
|
+
* - `apiKey` — query or admin key (sent via `api-key` header)
|
|
14
|
+
* - `apiVersion` — API version, default `2024-07-01`
|
|
15
|
+
* - `defaultIndex` — fallback index when no scope ExternalIndexes
|
|
16
|
+
* - `defaultSearchFields` — comma-separated `searchFields` (when omitted,
|
|
17
|
+
* Azure searches all searchable fields)
|
|
18
|
+
*
|
|
19
|
+
* @module @memberjunction/search-engine
|
|
20
|
+
*/
|
|
21
|
+
import { UserInfo } from '@memberjunction/core';
|
|
22
|
+
import { BaseSearchProvider, SearchProviderConfig } from '../generic/ISearchProvider.js';
|
|
23
|
+
import { SearchSource, SearchFilters, SearchResultItem, ScopeConstraints } from '../generic/search.types.js';
|
|
24
|
+
export declare class AzureAISearchProvider extends BaseSearchProvider {
|
|
25
|
+
readonly SourceType: SearchSource;
|
|
26
|
+
private parsedConfig;
|
|
27
|
+
private available;
|
|
28
|
+
Initialize(config: SearchProviderConfig, contextUser: UserInfo): Promise<void>;
|
|
29
|
+
CheckAvailability(_contextUser: UserInfo): Promise<void>;
|
|
30
|
+
IsAvailable(): boolean;
|
|
31
|
+
Search(query: string, topK: number, _filters: SearchFilters | undefined, _contextUser: UserInfo, scopeConstraints?: ScopeConstraints): Promise<SearchResultItem[]>;
|
|
32
|
+
/** Resolve the Azure search service base URL from the parsed config. */
|
|
33
|
+
private resolveEndpoint;
|
|
34
|
+
}
|
|
35
|
+
/** Tree-shake prevention helper. */
|
|
36
|
+
export declare function LoadAzureAISearchProvider(): void;
|
|
37
|
+
//# sourceMappingURL=AzureAISearchProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AzureAISearchProvider.d.ts","sourceRoot":"","sources":["../../src/providers/AzureAISearchProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EACH,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EACnB,MAAM,yBAAyB,CAAC;AAoBjC,qBACa,qBAAsB,SAAQ,kBAAkB;IACzD,SAAgB,UAAU,EAAE,YAAY,CAAc;IAEtD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,SAAS,CAAS;IAEJ,UAAU,CAAC,MAAM,EAAE,oBAAoB,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9E,iBAAiB,CAAC,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB9D,WAAW,IAAI,OAAO;IAIzB,MAAM,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,YAAY,EAAE,QAAQ,EACtB,gBAAgB,CAAC,EAAE,gBAAgB,GACpC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAsF9B,wEAAwE;IACxE,OAAO,CAAC,eAAe;CAS1B;AAED,oCAAoC;AACpC,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Azure AI Search provider for the SearchEngine (P5.3).
|
|
3
|
+
*
|
|
4
|
+
* Calls Azure AI Search's `docs/search` REST endpoint directly via fetch.
|
|
5
|
+
* Azure AI Search's filter syntax is OData ($filter), passed through as a
|
|
6
|
+
* pre-rendered string from the scope's `MetadataFilter`. Permission /
|
|
7
|
+
* tenant push-down lives entirely in that filter — no post-fusion filtering.
|
|
8
|
+
*
|
|
9
|
+
* **Connection options** (from `SearchProviderConfig.ProviderConfig`):
|
|
10
|
+
* - `serviceName` — Azure AI Search service short name (combined with
|
|
11
|
+
* `.search.windows.net`); OR
|
|
12
|
+
* - `endpoint` — full HTTPS endpoint URL (e.g. `https://my.search.windows.net`)
|
|
13
|
+
* - `apiKey` — query or admin key (sent via `api-key` header)
|
|
14
|
+
* - `apiVersion` — API version, default `2024-07-01`
|
|
15
|
+
* - `defaultIndex` — fallback index when no scope ExternalIndexes
|
|
16
|
+
* - `defaultSearchFields` — comma-separated `searchFields` (when omitted,
|
|
17
|
+
* Azure searches all searchable fields)
|
|
18
|
+
*
|
|
19
|
+
* @module @memberjunction/search-engine
|
|
20
|
+
*/
|
|
21
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
22
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
24
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
|
+
};
|
|
27
|
+
import { LogError } from '@memberjunction/core';
|
|
28
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
29
|
+
import { BaseSearchProvider } from '../generic/ISearchProvider.js';
|
|
30
|
+
let AzureAISearchProvider = class AzureAISearchProvider extends BaseSearchProvider {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(...arguments);
|
|
33
|
+
this.SourceType = 'fulltext';
|
|
34
|
+
this.parsedConfig = null;
|
|
35
|
+
this.available = false;
|
|
36
|
+
}
|
|
37
|
+
async Initialize(config, contextUser) {
|
|
38
|
+
await super.Initialize(config, contextUser);
|
|
39
|
+
this.parsedConfig = config.ProviderConfig ?? null;
|
|
40
|
+
if (!this.parsedConfig?.apiKey || (!this.parsedConfig.endpoint && !this.parsedConfig.serviceName)) {
|
|
41
|
+
LogError('AzureAISearchProvider: ProviderConfig must include apiKey and either endpoint or serviceName.');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async CheckAvailability(_contextUser) {
|
|
46
|
+
if (!this.parsedConfig?.apiKey) {
|
|
47
|
+
this.available = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const endpoint = this.resolveEndpoint();
|
|
51
|
+
if (!endpoint) {
|
|
52
|
+
this.available = false;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
// Probe the service-level endpoint with the api-version param. A 200/401 both
|
|
57
|
+
// confirm the host is reachable; we treat any HTTP response as "service is up
|
|
58
|
+
// and credential is at least the right shape" — Azure returns 401 if the key
|
|
59
|
+
// is wrong, which IS reachable.
|
|
60
|
+
const url = `${endpoint}/?api-version=${encodeURIComponent(this.parsedConfig.apiVersion ?? '2024-07-01')}`;
|
|
61
|
+
const response = await fetch(url, { method: 'GET', headers: { 'api-key': this.parsedConfig.apiKey } });
|
|
62
|
+
this.available = response.ok || response.status === 401;
|
|
63
|
+
if (!this.available) {
|
|
64
|
+
LogError(`AzureAISearchProvider: probe returned ${response.status}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
69
|
+
LogError(`AzureAISearchProvider: probe failed — ${msg}`);
|
|
70
|
+
this.available = false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
IsAvailable() {
|
|
74
|
+
return this.available;
|
|
75
|
+
}
|
|
76
|
+
async Search(query, topK, _filters, _contextUser, scopeConstraints) {
|
|
77
|
+
if (!this.parsedConfig?.apiKey)
|
|
78
|
+
return [];
|
|
79
|
+
const endpoint = this.resolveEndpoint();
|
|
80
|
+
if (!endpoint)
|
|
81
|
+
return [];
|
|
82
|
+
const effectiveQuery = scopeConstraints?.QueryTransforms?.[this.SourceType] ?? query;
|
|
83
|
+
const apiVersion = this.parsedConfig.apiVersion ?? '2024-07-01';
|
|
84
|
+
const scopedAzureRows = scopeConstraints?.ExternalIndexes
|
|
85
|
+
?.filter(r => r.IndexType === 'AzureAISearch' && r.ExternalIndexName) ?? [];
|
|
86
|
+
const targets = scopedAzureRows.length > 0
|
|
87
|
+
? scopedAzureRows
|
|
88
|
+
: (this.parsedConfig.defaultIndex
|
|
89
|
+
? [{
|
|
90
|
+
IndexType: 'AzureAISearch',
|
|
91
|
+
ExternalIndexName: this.parsedConfig.defaultIndex,
|
|
92
|
+
MetadataFilter: undefined,
|
|
93
|
+
}]
|
|
94
|
+
: []);
|
|
95
|
+
if (targets.length === 0)
|
|
96
|
+
return [];
|
|
97
|
+
const requests = targets.map(async (idx) => {
|
|
98
|
+
const url = `${endpoint}/indexes/${encodeURIComponent(idx.ExternalIndexName)}/docs/search?api-version=${encodeURIComponent(apiVersion)}`;
|
|
99
|
+
const body = {
|
|
100
|
+
search: effectiveQuery,
|
|
101
|
+
top: topK,
|
|
102
|
+
};
|
|
103
|
+
if (this.parsedConfig?.defaultSearchFields) {
|
|
104
|
+
body.searchFields = this.parsedConfig.defaultSearchFields;
|
|
105
|
+
}
|
|
106
|
+
if (idx.MetadataFilter && typeof idx.MetadataFilter === 'string') {
|
|
107
|
+
body.filter = idx.MetadataFilter;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const response = await fetch(url, {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
headers: { 'api-key': this.parsedConfig.apiKey, 'Content-Type': 'application/json' },
|
|
113
|
+
body: JSON.stringify(body),
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
const text = await response.text().catch(() => '');
|
|
117
|
+
LogError(`AzureAISearchProvider: ${idx.ExternalIndexName} returned ${response.status}: ${text || response.statusText}`);
|
|
118
|
+
return { index: idx.ExternalIndexName, hits: [] };
|
|
119
|
+
}
|
|
120
|
+
const json = await response.json();
|
|
121
|
+
return { index: idx.ExternalIndexName, hits: json.value ?? [] };
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
125
|
+
LogError(`AzureAISearchProvider: ${idx.ExternalIndexName} fetch failed — ${msg}`);
|
|
126
|
+
return { index: idx.ExternalIndexName, hits: [] };
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
const results = await Promise.all(requests);
|
|
130
|
+
const merged = results.flatMap(r => r.hits.map(h => ({ index: r.index, hit: h })));
|
|
131
|
+
if (merged.length === 0)
|
|
132
|
+
return [];
|
|
133
|
+
const topScore = Math.max(1, ...merged.map(m => m.hit['@search.score']));
|
|
134
|
+
return merged
|
|
135
|
+
.sort((a, b) => b.hit['@search.score'] - a.hit['@search.score'])
|
|
136
|
+
.slice(0, topK)
|
|
137
|
+
.map((m) => {
|
|
138
|
+
const id = String(m.hit['id'] ?? m.hit['Id'] ?? m.hit['ID'] ?? '');
|
|
139
|
+
const title = String(m.hit['title'] ?? m.hit['name'] ?? m.hit['Name'] ?? id);
|
|
140
|
+
const snippet = String(m.hit['content'] ?? m.hit['description'] ?? '');
|
|
141
|
+
const normalized = m.hit['@search.score'] / topScore;
|
|
142
|
+
return {
|
|
143
|
+
ID: `azs-${m.index}-${id}`,
|
|
144
|
+
EntityName: m.index,
|
|
145
|
+
RecordID: id,
|
|
146
|
+
SourceType: this.SourceType,
|
|
147
|
+
ResultType: 'entity-record',
|
|
148
|
+
Title: title.slice(0, 200),
|
|
149
|
+
Snippet: snippet.slice(0, 500),
|
|
150
|
+
Score: normalized,
|
|
151
|
+
ScoreBreakdown: { FullText: normalized },
|
|
152
|
+
Tags: [],
|
|
153
|
+
MatchedAt: new Date(),
|
|
154
|
+
EntityIcon: 'fa-solid fa-cloud',
|
|
155
|
+
RecordName: title.slice(0, 200),
|
|
156
|
+
RawMetadata: JSON.stringify({ index: m.index, id, _rawScore: m.hit['@search.score'] }),
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/** Resolve the Azure search service base URL from the parsed config. */
|
|
161
|
+
resolveEndpoint() {
|
|
162
|
+
if (this.parsedConfig?.endpoint) {
|
|
163
|
+
return this.parsedConfig.endpoint.replace(/\/$/, '');
|
|
164
|
+
}
|
|
165
|
+
if (this.parsedConfig?.serviceName) {
|
|
166
|
+
return `https://${this.parsedConfig.serviceName}.search.windows.net`;
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
AzureAISearchProvider = __decorate([
|
|
172
|
+
RegisterClass(BaseSearchProvider, 'AzureAISearchProvider')
|
|
173
|
+
], AzureAISearchProvider);
|
|
174
|
+
export { AzureAISearchProvider };
|
|
175
|
+
/** Tree-shake prevention helper. */
|
|
176
|
+
export function LoadAzureAISearchProvider() {
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
178
|
+
const _ref = AzureAISearchProvider;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=AzureAISearchProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AzureAISearchProvider.js","sourceRoot":"","sources":["../../src/providers/AzureAISearchProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Elasticsearch search provider for the SearchEngine (P5.1).
|
|
3
|
+
*
|
|
4
|
+
* Translates a query plus a SearchScope's `ExternalIndexes` constraint into an
|
|
5
|
+
* Elasticsearch search request. Each `MJ: Search Scope External Indexes` row
|
|
6
|
+
* with `IndexType='Elasticsearch'` and a non-empty `ExternalIndexName` becomes
|
|
7
|
+
* a target index in the request. The scope's rendered `MetadataFilter` (a JSON
|
|
8
|
+
* object the scope author authored as ES filter DSL) is composed into the
|
|
9
|
+
* top-level `bool.filter` so permission predicates and tenant-scoping push down
|
|
10
|
+
* to the engine — no post-fusion filtering.
|
|
11
|
+
*
|
|
12
|
+
* **Connection.** Reads from `SearchProviderConfig.ProviderConfig`:
|
|
13
|
+
* - `node` — Elasticsearch node URL (e.g. `https://es.example.internal:9200`)
|
|
14
|
+
* - `apiKey` — base64-encoded API key (preferred)
|
|
15
|
+
* - `username` + `password` — basic auth fallback
|
|
16
|
+
* - `cloudId` — Elastic Cloud deployment ID, when used in place of `node`
|
|
17
|
+
* - `defaultField` — field to match against when the scope/provider doesn't
|
|
18
|
+
* specify one (default: `content`)
|
|
19
|
+
*
|
|
20
|
+
* **Optional peer dep.** `@elastic/elasticsearch` is in `optionalDependencies`
|
|
21
|
+
* and loaded via dynamic import per CLAUDE.md rule #8 case 2 — consumers who
|
|
22
|
+
* don't use Elasticsearch don't pay the bundle cost.
|
|
23
|
+
*
|
|
24
|
+
* @module @memberjunction/search-engine
|
|
25
|
+
*/
|
|
26
|
+
import { UserInfo } from '@memberjunction/core';
|
|
27
|
+
import { BaseSearchProvider, SearchProviderConfig } from '../generic/ISearchProvider.js';
|
|
28
|
+
import { SearchSource, SearchFilters, SearchResultItem, ScopeConstraints } from '../generic/search.types.js';
|
|
29
|
+
export declare class ElasticsearchSearchProvider extends BaseSearchProvider {
|
|
30
|
+
readonly SourceType: SearchSource;
|
|
31
|
+
private client;
|
|
32
|
+
private available;
|
|
33
|
+
private parsedConfig;
|
|
34
|
+
Initialize(config: SearchProviderConfig, contextUser: UserInfo): Promise<void>;
|
|
35
|
+
CheckAvailability(_contextUser: UserInfo): Promise<void>;
|
|
36
|
+
IsAvailable(): boolean;
|
|
37
|
+
Search(query: string, topK: number, _filters: SearchFilters | undefined, _contextUser: UserInfo, scopeConstraints?: ScopeConstraints): Promise<SearchResultItem[]>;
|
|
38
|
+
}
|
|
39
|
+
/** Tree-shake prevention helper. */
|
|
40
|
+
export declare function LoadElasticsearchSearchProvider(): void;
|
|
41
|
+
/** Test-only: clear the memoized SDK loader so each test installs its own mock. */
|
|
42
|
+
export declare function __resetElasticsearchClientLoaderForTests(): void;
|
|
43
|
+
//# sourceMappingURL=ElasticsearchSearchProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElasticsearchSearchProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ElasticsearchSearchProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAuB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EACH,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EACnB,MAAM,yBAAyB,CAAC;AA8DjC,qBACa,2BAA4B,SAAQ,kBAAkB;IAC/D,SAAgB,UAAU,EAAE,YAAY,CAAc;IAEtD,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA4C;IAE1C,UAAU,CAAC,MAAM,EAAE,oBAAoB,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B9E,iBAAiB,CAAC,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9D,WAAW,IAAI,OAAO;IAIzB,MAAM,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,YAAY,EAAE,QAAQ,EACtB,gBAAgB,CAAC,EAAE,gBAAgB,GACpC,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAiFjC;AAED,oCAAoC;AACpC,wBAAgB,+BAA+B,IAAI,IAAI,CAGtD;AAED,mFAAmF;AACnF,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D"}
|