@memberjunction/core-entities 5.24.0 → 5.25.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/engines/FileStorageEngine.d.ts +21 -5
- package/dist/engines/FileStorageEngine.d.ts.map +1 -1
- package/dist/engines/FileStorageEngine.js +24 -4
- package/dist/engines/FileStorageEngine.js.map +1 -1
- package/dist/engines/GeoDataEngine.d.ts +141 -0
- package/dist/engines/GeoDataEngine.d.ts.map +1 -0
- package/dist/engines/GeoDataEngine.js +425 -0
- package/dist/engines/GeoDataEngine.js.map +1 -0
- package/dist/engines/InstanceConfigEngine.d.ts +105 -0
- package/dist/engines/InstanceConfigEngine.d.ts.map +1 -0
- package/dist/engines/InstanceConfigEngine.js +198 -0
- package/dist/engines/InstanceConfigEngine.js.map +1 -0
- package/dist/engines/SearchEngineBase.d.ts +76 -0
- package/dist/engines/SearchEngineBase.d.ts.map +1 -0
- package/dist/engines/SearchEngineBase.js +141 -0
- package/dist/engines/SearchEngineBase.js.map +1 -0
- package/dist/engines/UserInfoEngine.d.ts +15 -1
- package/dist/engines/UserInfoEngine.d.ts.map +1 -1
- package/dist/engines/UserInfoEngine.js +45 -0
- package/dist/engines/UserInfoEngine.js.map +1 -1
- package/dist/engines/artifacts.d.ts +13 -0
- package/dist/engines/artifacts.d.ts.map +1 -1
- package/dist/engines/artifacts.js +25 -0
- package/dist/engines/artifacts.js.map +1 -1
- package/dist/generated/entity_subclasses.d.ts +1629 -71
- package/dist/generated/entity_subclasses.d.ts.map +1 -1
- package/dist/generated/entity_subclasses.js +2438 -123
- package/dist/generated/entity_subclasses.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { BaseEngine } from "@memberjunction/core";
|
|
2
|
+
/**
|
|
3
|
+
* InstanceConfigEngine provides centralized, cached access to instance-level feature configuration.
|
|
4
|
+
* It loads all MJ: Instance Configurations records into memory and provides typed getters
|
|
5
|
+
* for boolean, number, string, and JSON values by FeatureKey.
|
|
6
|
+
*
|
|
7
|
+
* Uses BaseEngine for automatic caching and entity-event-based auto-refresh so that
|
|
8
|
+
* configuration changes are reflected without requiring a manual reload.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const engine = InstanceConfigEngine.Instance;
|
|
13
|
+
* await engine.Config(false, contextUser);
|
|
14
|
+
*
|
|
15
|
+
* // Read a boolean flag
|
|
16
|
+
* const searchEnabled = engine.GetBoolean('Shell.SearchBar.Enabled');
|
|
17
|
+
*
|
|
18
|
+
* // Read a number with a custom default
|
|
19
|
+
* const maxResults = engine.GetNumber('Search.MaxResults', 50);
|
|
20
|
+
*
|
|
21
|
+
* // Read a JSON object
|
|
22
|
+
* const uiConfig = engine.GetJSON<{ theme: string }>('UI.DefaultConfig');
|
|
23
|
+
*
|
|
24
|
+
* // Admin: update a setting
|
|
25
|
+
* await engine.Set('Shell.SearchBar.Enabled', 'true', contextUser);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class InstanceConfigEngine extends BaseEngine {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(...arguments);
|
|
31
|
+
this._configs = [];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns the global instance of the class. This is a singleton class, so there
|
|
35
|
+
* is only one instance of it in the application. Do not directly create new instances
|
|
36
|
+
* of it, always use this method to get the instance.
|
|
37
|
+
*/
|
|
38
|
+
static get Instance() {
|
|
39
|
+
return super.getInstance();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Configures the engine by loading all instance configuration records from the database.
|
|
43
|
+
* @param forceRefresh - If true, forces a refresh from the database even if data is cached
|
|
44
|
+
* @param contextUser - Optional user context for server-side operations
|
|
45
|
+
* @param provider - Optional metadata provider
|
|
46
|
+
*/
|
|
47
|
+
async Config(forceRefresh, contextUser, provider) {
|
|
48
|
+
const configs = [
|
|
49
|
+
{
|
|
50
|
+
Type: 'entity',
|
|
51
|
+
EntityName: 'MJ: Instance Configurations',
|
|
52
|
+
PropertyName: '_configs',
|
|
53
|
+
CacheLocal: true
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
await this.Load(configs, provider, forceRefresh, contextUser);
|
|
57
|
+
}
|
|
58
|
+
// ================================================================
|
|
59
|
+
// Cached data getter
|
|
60
|
+
// ================================================================
|
|
61
|
+
/** All instance configuration records */
|
|
62
|
+
get InstanceConfigs() {
|
|
63
|
+
return this._configs || [];
|
|
64
|
+
}
|
|
65
|
+
// ================================================================
|
|
66
|
+
// Lookup helpers
|
|
67
|
+
// ================================================================
|
|
68
|
+
/**
|
|
69
|
+
* Find a configuration record by its FeatureKey.
|
|
70
|
+
* @param featureKey - The dot-notation feature key (e.g. 'Shell.SearchBar.Enabled')
|
|
71
|
+
* @returns The configuration entity, or undefined if not found
|
|
72
|
+
*/
|
|
73
|
+
GetConfigByKey(featureKey) {
|
|
74
|
+
if (!featureKey)
|
|
75
|
+
return undefined;
|
|
76
|
+
return this._configs.find(c => c.FeatureKey === featureKey);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get all configuration records for a given category.
|
|
80
|
+
* @param category - The category to filter by (e.g. 'General', 'Search')
|
|
81
|
+
* @returns Array of matching configuration entities
|
|
82
|
+
*/
|
|
83
|
+
GetConfigsByCategory(category) {
|
|
84
|
+
if (!category)
|
|
85
|
+
return [];
|
|
86
|
+
const lower = category.trim().toLowerCase();
|
|
87
|
+
return this._configs.filter(c => c.Category?.trim().toLowerCase() === lower);
|
|
88
|
+
}
|
|
89
|
+
// ================================================================
|
|
90
|
+
// Typed value getters
|
|
91
|
+
// ================================================================
|
|
92
|
+
/**
|
|
93
|
+
* Get the raw string value for a feature key. Returns the record's Value if non-empty,
|
|
94
|
+
* otherwise falls back to DefaultValue, then to undefined.
|
|
95
|
+
* @param featureKey - The dot-notation feature key
|
|
96
|
+
* @returns The value string, or undefined if the key is not found
|
|
97
|
+
*/
|
|
98
|
+
Get(featureKey) {
|
|
99
|
+
const config = this.GetConfigByKey(featureKey);
|
|
100
|
+
if (!config)
|
|
101
|
+
return undefined;
|
|
102
|
+
return this.ResolveValue(config);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get a boolean value for a feature key. Interprets 'true' (case-insensitive) as true,
|
|
106
|
+
* everything else as false. Returns the provided default if the key is not found.
|
|
107
|
+
* @param featureKey - The dot-notation feature key
|
|
108
|
+
* @param defaultValue - Value to return if the key is not found (defaults to true)
|
|
109
|
+
*/
|
|
110
|
+
GetBoolean(featureKey, defaultValue = true) {
|
|
111
|
+
const raw = this.Get(featureKey);
|
|
112
|
+
if (raw === undefined)
|
|
113
|
+
return defaultValue;
|
|
114
|
+
return raw.trim().toLowerCase() === 'true';
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get a numeric value for a feature key. Returns the provided default if the key
|
|
118
|
+
* is not found or the value cannot be parsed as a number.
|
|
119
|
+
* @param featureKey - The dot-notation feature key
|
|
120
|
+
* @param defaultValue - Value to return if the key is not found or unparseable (defaults to 0)
|
|
121
|
+
*/
|
|
122
|
+
GetNumber(featureKey, defaultValue = 0) {
|
|
123
|
+
const raw = this.Get(featureKey);
|
|
124
|
+
if (raw === undefined)
|
|
125
|
+
return defaultValue;
|
|
126
|
+
const parsed = Number(raw);
|
|
127
|
+
return Number.isNaN(parsed) ? defaultValue : parsed;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get a JSON-parsed value for a feature key. Returns the provided default if the key
|
|
131
|
+
* is not found or the value cannot be parsed as JSON.
|
|
132
|
+
* @param featureKey - The dot-notation feature key
|
|
133
|
+
* @param defaultValue - Value to return if the key is not found or unparseable
|
|
134
|
+
*/
|
|
135
|
+
GetJSON(featureKey, defaultValue) {
|
|
136
|
+
const raw = this.Get(featureKey);
|
|
137
|
+
if (raw === undefined)
|
|
138
|
+
return defaultValue;
|
|
139
|
+
try {
|
|
140
|
+
return JSON.parse(raw);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return defaultValue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ================================================================
|
|
147
|
+
// Admin setter
|
|
148
|
+
// ================================================================
|
|
149
|
+
/**
|
|
150
|
+
* Update the Value of an existing configuration record. This method updates the
|
|
151
|
+
* record in the database and refreshes the local cache entry.
|
|
152
|
+
*
|
|
153
|
+
* Note: This only updates existing records. To create new configuration entries,
|
|
154
|
+
* use the standard entity creation workflow.
|
|
155
|
+
*
|
|
156
|
+
* @param featureKey - The dot-notation feature key to update
|
|
157
|
+
* @param value - The new value string
|
|
158
|
+
* @param contextUser - Optional user context (required on server-side)
|
|
159
|
+
* @returns true if the save succeeded, false otherwise
|
|
160
|
+
*/
|
|
161
|
+
async Set(featureKey, value, contextUser) {
|
|
162
|
+
const config = this.GetConfigByKey(featureKey);
|
|
163
|
+
if (!config) {
|
|
164
|
+
console.error(`InstanceConfigEngine.Set: FeatureKey '${featureKey}' not found`);
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
config.Value = value;
|
|
169
|
+
const saved = await config.Save();
|
|
170
|
+
if (saved) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.error('InstanceConfigEngine.Set: Failed to save:', config.LatestResult?.Message);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
console.error('InstanceConfigEngine.Set: Error:', error instanceof Error ? error.message : String(error));
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ================================================================
|
|
184
|
+
// Private helpers
|
|
185
|
+
// ================================================================
|
|
186
|
+
/**
|
|
187
|
+
* Resolve the effective value for a configuration record. Returns Value if
|
|
188
|
+
* it is non-empty, otherwise falls back to DefaultValue.
|
|
189
|
+
*/
|
|
190
|
+
ResolveValue(config) {
|
|
191
|
+
const val = config.Value;
|
|
192
|
+
if (val != null && val.trim().length > 0) {
|
|
193
|
+
return val;
|
|
194
|
+
}
|
|
195
|
+
return config.DefaultValue;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=InstanceConfigEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstanceConfigEngine.js","sourceRoot":"","sources":["../../src/engines/InstanceConfigEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { BaseEngine, IMetadataProvider, UserInfo } from "@memberjunction/core";
|
|
2
|
+
import { MJSearchProviderEntity } from "../generated/entity_subclasses.js";
|
|
3
|
+
/**
|
|
4
|
+
* SearchEngineBase provides cached access to SearchProvider metadata.
|
|
5
|
+
* Loads all MJ: Search Providers records via BaseEngine and provides
|
|
6
|
+
* typed getters and lookups for use anywhere (client or server).
|
|
7
|
+
*
|
|
8
|
+
* The server-side SearchEngine class uses SearchEngineBase.Instance to
|
|
9
|
+
* access cached provider metadata instead of loading directly via RunView.
|
|
10
|
+
*
|
|
11
|
+
* Uses BaseEngine for automatic caching and entity-event-based auto-refresh
|
|
12
|
+
* so that provider configuration changes are reflected without manual reload.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const base = SearchEngineBase.Instance;
|
|
17
|
+
* await base.Config(false, contextUser);
|
|
18
|
+
*
|
|
19
|
+
* // Get all active providers
|
|
20
|
+
* const activeProviders = base.ActiveProviders;
|
|
21
|
+
*
|
|
22
|
+
* // Find a provider by driver class
|
|
23
|
+
* const vectorProvider = base.GetProviderByDriverClass('VectorSearchProvider');
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class SearchEngineBase extends BaseEngine<SearchEngineBase> {
|
|
27
|
+
/**
|
|
28
|
+
* Returns the global singleton instance.
|
|
29
|
+
*/
|
|
30
|
+
static get Instance(): SearchEngineBase;
|
|
31
|
+
private _providers;
|
|
32
|
+
/**
|
|
33
|
+
* Configures the engine by loading all search provider records from the database.
|
|
34
|
+
* @param forceRefresh - If true, forces a refresh from the database even if data is cached
|
|
35
|
+
* @param contextUser - Optional user context for server-side operations
|
|
36
|
+
* @param provider - Optional metadata provider
|
|
37
|
+
*/
|
|
38
|
+
Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
|
|
39
|
+
/** All search provider records (any status) */
|
|
40
|
+
get Providers(): MJSearchProviderEntity[];
|
|
41
|
+
/** Only active search providers, sorted by Priority ascending */
|
|
42
|
+
get ActiveProviders(): MJSearchProviderEntity[];
|
|
43
|
+
/** Active providers that support preview/autocomplete searches */
|
|
44
|
+
get PreviewProviders(): MJSearchProviderEntity[];
|
|
45
|
+
/**
|
|
46
|
+
* Find a provider by its DriverClass key.
|
|
47
|
+
* @param driverClass - The DriverClass value (e.g., 'VectorSearchProvider')
|
|
48
|
+
* @returns The provider entity, or undefined if not found
|
|
49
|
+
*/
|
|
50
|
+
GetProviderByDriverClass(driverClass: string): MJSearchProviderEntity | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Find a provider by its Name.
|
|
53
|
+
* @param name - The provider name (e.g., 'Semantic')
|
|
54
|
+
* @returns The provider entity, or undefined if not found
|
|
55
|
+
*/
|
|
56
|
+
GetProviderByName(name: string): MJSearchProviderEntity | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Find a provider by its ID.
|
|
59
|
+
* @param id - The provider record ID
|
|
60
|
+
* @returns The provider entity, or undefined if not found
|
|
61
|
+
*/
|
|
62
|
+
GetProviderById(id: string): MJSearchProviderEntity | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Get the display label for a source type, resolving from provider metadata.
|
|
65
|
+
* Falls back to the source type string if no provider matches.
|
|
66
|
+
* @param sourceType - The source type key (e.g., 'vector', 'entity')
|
|
67
|
+
*/
|
|
68
|
+
GetDisplayNameForSourceType(sourceType: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Get the icon for a source type, resolving from provider metadata.
|
|
71
|
+
* Falls back to a generic icon if no provider matches.
|
|
72
|
+
* @param sourceType - The source type key (e.g., 'vector', 'entity')
|
|
73
|
+
*/
|
|
74
|
+
GetIconForSourceType(sourceType: string): string;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=SearchEngineBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchEngineBase.d.ts","sourceRoot":"","sources":["../../src/engines/SearchEngineBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGzG,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,gBAAiB,SAAQ,UAAU,CAAC,gBAAgB,CAAC;IAC9D;;OAEG;IACH,WAAkB,QAAQ,IAAI,gBAAgB,CAE7C;IAED,OAAO,CAAC,UAAU,CAAgC;IAElD;;;;;OAKG;IACU,MAAM,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBhH,+CAA+C;IAC/C,IAAW,SAAS,IAAI,sBAAsB,EAAE,CAE/C;IAED,iEAAiE;IACjE,IAAW,eAAe,IAAI,sBAAsB,EAAE,CAIrD;IAED,kEAAkE;IAClE,IAAW,gBAAgB,IAAI,sBAAsB,EAAE,CAEtD;IAMD;;;;OAIG;IACI,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAKxF;;;;OAIG;IACI,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAM1E;;;;OAIG;IACI,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS;IAKtE;;;;OAIG;IACI,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAQ9D;;;;OAIG;IACI,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;CAO1D"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseEngine } from "@memberjunction/core";
|
|
8
|
+
import { RegisterForStartup } from "@memberjunction/core";
|
|
9
|
+
import { UUIDsEqual } from "@memberjunction/global";
|
|
10
|
+
/**
|
|
11
|
+
* SearchEngineBase provides cached access to SearchProvider metadata.
|
|
12
|
+
* Loads all MJ: Search Providers records via BaseEngine and provides
|
|
13
|
+
* typed getters and lookups for use anywhere (client or server).
|
|
14
|
+
*
|
|
15
|
+
* The server-side SearchEngine class uses SearchEngineBase.Instance to
|
|
16
|
+
* access cached provider metadata instead of loading directly via RunView.
|
|
17
|
+
*
|
|
18
|
+
* Uses BaseEngine for automatic caching and entity-event-based auto-refresh
|
|
19
|
+
* so that provider configuration changes are reflected without manual reload.
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const base = SearchEngineBase.Instance;
|
|
24
|
+
* await base.Config(false, contextUser);
|
|
25
|
+
*
|
|
26
|
+
* // Get all active providers
|
|
27
|
+
* const activeProviders = base.ActiveProviders;
|
|
28
|
+
*
|
|
29
|
+
* // Find a provider by driver class
|
|
30
|
+
* const vectorProvider = base.GetProviderByDriverClass('VectorSearchProvider');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
let SearchEngineBase = class SearchEngineBase extends BaseEngine {
|
|
34
|
+
constructor() {
|
|
35
|
+
super(...arguments);
|
|
36
|
+
this._providers = [];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns the global singleton instance.
|
|
40
|
+
*/
|
|
41
|
+
static get Instance() {
|
|
42
|
+
return super.getInstance();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Configures the engine by loading all search provider records from the database.
|
|
46
|
+
* @param forceRefresh - If true, forces a refresh from the database even if data is cached
|
|
47
|
+
* @param contextUser - Optional user context for server-side operations
|
|
48
|
+
* @param provider - Optional metadata provider
|
|
49
|
+
*/
|
|
50
|
+
async Config(forceRefresh, contextUser, provider) {
|
|
51
|
+
const configs = [
|
|
52
|
+
{
|
|
53
|
+
Type: 'entity',
|
|
54
|
+
EntityName: 'MJ: Search Providers',
|
|
55
|
+
PropertyName: '_providers',
|
|
56
|
+
CacheLocal: true,
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
await this.Load(configs, provider, forceRefresh, contextUser);
|
|
60
|
+
}
|
|
61
|
+
// ================================================================
|
|
62
|
+
// Cached data getters
|
|
63
|
+
// ================================================================
|
|
64
|
+
/** All search provider records (any status) */
|
|
65
|
+
get Providers() {
|
|
66
|
+
return this._providers || [];
|
|
67
|
+
}
|
|
68
|
+
/** Only active search providers, sorted by Priority ascending */
|
|
69
|
+
get ActiveProviders() {
|
|
70
|
+
return this.Providers
|
|
71
|
+
.filter(p => p.Status === 'Active')
|
|
72
|
+
.sort((a, b) => a.Priority - b.Priority);
|
|
73
|
+
}
|
|
74
|
+
/** Active providers that support preview/autocomplete searches */
|
|
75
|
+
get PreviewProviders() {
|
|
76
|
+
return this.ActiveProviders.filter(p => p.SupportsPreview);
|
|
77
|
+
}
|
|
78
|
+
// ================================================================
|
|
79
|
+
// Lookup helpers
|
|
80
|
+
// ================================================================
|
|
81
|
+
/**
|
|
82
|
+
* Find a provider by its DriverClass key.
|
|
83
|
+
* @param driverClass - The DriverClass value (e.g., 'VectorSearchProvider')
|
|
84
|
+
* @returns The provider entity, or undefined if not found
|
|
85
|
+
*/
|
|
86
|
+
GetProviderByDriverClass(driverClass) {
|
|
87
|
+
if (!driverClass)
|
|
88
|
+
return undefined;
|
|
89
|
+
return this._providers.find(p => p.DriverClass === driverClass);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Find a provider by its Name.
|
|
93
|
+
* @param name - The provider name (e.g., 'Semantic')
|
|
94
|
+
* @returns The provider entity, or undefined if not found
|
|
95
|
+
*/
|
|
96
|
+
GetProviderByName(name) {
|
|
97
|
+
if (!name)
|
|
98
|
+
return undefined;
|
|
99
|
+
const lower = name.trim().toLowerCase();
|
|
100
|
+
return this._providers.find(p => p.Name.trim().toLowerCase() === lower);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Find a provider by its ID.
|
|
104
|
+
* @param id - The provider record ID
|
|
105
|
+
* @returns The provider entity, or undefined if not found
|
|
106
|
+
*/
|
|
107
|
+
GetProviderById(id) {
|
|
108
|
+
if (!id)
|
|
109
|
+
return undefined;
|
|
110
|
+
return this._providers.find(p => UUIDsEqual(p.ID, id));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get the display label for a source type, resolving from provider metadata.
|
|
114
|
+
* Falls back to the source type string if no provider matches.
|
|
115
|
+
* @param sourceType - The source type key (e.g., 'vector', 'entity')
|
|
116
|
+
*/
|
|
117
|
+
GetDisplayNameForSourceType(sourceType) {
|
|
118
|
+
const provider = this.ActiveProviders.find(p => {
|
|
119
|
+
const driverLower = p.DriverClass.toLowerCase();
|
|
120
|
+
return driverLower.startsWith(sourceType.toLowerCase());
|
|
121
|
+
});
|
|
122
|
+
return provider?.DisplayName ?? provider?.Name ?? sourceType;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the icon for a source type, resolving from provider metadata.
|
|
126
|
+
* Falls back to a generic icon if no provider matches.
|
|
127
|
+
* @param sourceType - The source type key (e.g., 'vector', 'entity')
|
|
128
|
+
*/
|
|
129
|
+
GetIconForSourceType(sourceType) {
|
|
130
|
+
const provider = this.ActiveProviders.find(p => {
|
|
131
|
+
const driverLower = p.DriverClass.toLowerCase();
|
|
132
|
+
return driverLower.startsWith(sourceType.toLowerCase());
|
|
133
|
+
});
|
|
134
|
+
return provider?.Icon ?? 'fa-solid fa-circle';
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
SearchEngineBase = __decorate([
|
|
138
|
+
RegisterForStartup()
|
|
139
|
+
], SearchEngineBase);
|
|
140
|
+
export { SearchEngineBase };
|
|
141
|
+
//# sourceMappingURL=SearchEngineBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchEngineBase.js","sourceRoot":"","sources":["../../src/engines/SearchEngineBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,9 @@ import { ApplicationInfo, BaseEngine, IMetadataProvider, UserInfo } from '@membe
|
|
|
4
4
|
* - 'installed_active': User has UserApplication record with IsActive=true
|
|
5
5
|
* - 'installed_inactive': User has UserApplication record with IsActive=false
|
|
6
6
|
* - 'not_installed': User has no UserApplication record for this app
|
|
7
|
+
* - 'not_authorized': User's roles do not grant access to the application
|
|
7
8
|
*/
|
|
8
|
-
export type UserApplicationAccessStatus = 'installed_active' | 'installed_inactive' | 'not_installed';
|
|
9
|
+
export type UserApplicationAccessStatus = 'installed_active' | 'installed_inactive' | 'not_installed' | 'not_authorized';
|
|
9
10
|
import { MJUserNotificationEntity, MJUserNotificationTypeEntity, MJWorkspaceEntity, MJUserApplicationEntity, MJUserFavoriteEntity, MJUserRecordLogEntity, MJUserSettingEntity, MJUserNotificationPreferenceEntity } from '../generated/entity_subclasses.js';
|
|
10
11
|
/**
|
|
11
12
|
* UserInfoEngine is a singleton engine that provides centralized access to user-specific data
|
|
@@ -42,6 +43,7 @@ export declare class UserInfoEngine extends BaseEngine<UserInfoEngine> {
|
|
|
42
43
|
private _UserSettings;
|
|
43
44
|
private _NotificationTypes;
|
|
44
45
|
private _UserNotificationPreferences;
|
|
46
|
+
private _applicationRoles;
|
|
45
47
|
private _loadedForUserId;
|
|
46
48
|
private _createDefaultAppsPromise;
|
|
47
49
|
/**
|
|
@@ -231,10 +233,22 @@ export declare class UserInfoEngine extends BaseEngine<UserInfoEngine> {
|
|
|
231
233
|
get LoadedForUserId(): string | null;
|
|
232
234
|
/**
|
|
233
235
|
* Check the user's access status for an application.
|
|
236
|
+
* First checks role-based authorization (ApplicationRole records), then installation status.
|
|
234
237
|
* @param applicationId - The application ID to check
|
|
235
238
|
* @returns The user's access status for this application
|
|
236
239
|
*/
|
|
237
240
|
CheckUserApplicationAccess(applicationId: string): UserApplicationAccessStatus;
|
|
241
|
+
/**
|
|
242
|
+
* Checks if the current user's roles grant access to the application.
|
|
243
|
+
* If no ApplicationRole records exist for the app, access is open (backwards compatible).
|
|
244
|
+
* If records exist, user must have at least one role with CanAccess=1.
|
|
245
|
+
*/
|
|
246
|
+
UserHasApplicationAccess(applicationId: string): boolean;
|
|
247
|
+
/**
|
|
248
|
+
* Checks if the current user can administer a specific application.
|
|
249
|
+
* Requires an explicit ApplicationRole record with CanAdmin=1.
|
|
250
|
+
*/
|
|
251
|
+
UserCanAdminApplication(applicationId: string): boolean;
|
|
238
252
|
/**
|
|
239
253
|
* Check if an application is inactive in the system metadata.
|
|
240
254
|
* @param applicationId - The application ID to check
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserInfoEngine.d.ts","sourceRoot":"","sources":["../../src/engines/UserInfoEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EAEV,iBAAiB,EAGjB,QAAQ,EACT,MAAM,sBAAsB,CAAC;AAG9B
|
|
1
|
+
{"version":3,"file":"UserInfoEngine.d.ts","sourceRoot":"","sources":["../../src/engines/UserInfoEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,8 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
|
|
|
41
41
|
this._NotificationTypes = [];
|
|
42
42
|
// User notification preferences (user-specific)
|
|
43
43
|
this._UserNotificationPreferences = [];
|
|
44
|
+
// Application role assignments (global - not user-specific)
|
|
45
|
+
this._applicationRoles = [];
|
|
44
46
|
// Track the user ID we loaded data for
|
|
45
47
|
this._loadedForUserId = null;
|
|
46
48
|
// Track in-progress CreateDefaultApplications call to prevent duplicate execution
|
|
@@ -148,6 +150,12 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
|
|
|
148
150
|
PropertyName: '_UserNotificationPreferences',
|
|
149
151
|
CacheLocal: true,
|
|
150
152
|
},
|
|
153
|
+
{
|
|
154
|
+
Type: 'entity',
|
|
155
|
+
EntityName: 'MJ: Application Roles',
|
|
156
|
+
PropertyName: '_applicationRoles',
|
|
157
|
+
CacheLocal: true,
|
|
158
|
+
},
|
|
151
159
|
];
|
|
152
160
|
await super.Load(configs, provider, forceRefresh, contextUser);
|
|
153
161
|
this._loadedForUserId = userId;
|
|
@@ -536,16 +544,53 @@ let UserInfoEngine = class UserInfoEngine extends BaseEngine {
|
|
|
536
544
|
// ========================================================================
|
|
537
545
|
/**
|
|
538
546
|
* Check the user's access status for an application.
|
|
547
|
+
* First checks role-based authorization (ApplicationRole records), then installation status.
|
|
539
548
|
* @param applicationId - The application ID to check
|
|
540
549
|
* @returns The user's access status for this application
|
|
541
550
|
*/
|
|
542
551
|
CheckUserApplicationAccess(applicationId) {
|
|
552
|
+
// Step 1: Check role-based authorization first
|
|
553
|
+
if (!this.UserHasApplicationAccess(applicationId)) {
|
|
554
|
+
return 'not_authorized';
|
|
555
|
+
}
|
|
556
|
+
// Step 2: Then check installation status (existing logic)
|
|
543
557
|
const userApp = this.GetUserApplicationByAppId(applicationId);
|
|
544
558
|
if (!userApp) {
|
|
545
559
|
return 'not_installed';
|
|
546
560
|
}
|
|
547
561
|
return userApp.IsActive ? 'installed_active' : 'installed_inactive';
|
|
548
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Checks if the current user's roles grant access to the application.
|
|
565
|
+
* If no ApplicationRole records exist for the app, access is open (backwards compatible).
|
|
566
|
+
* If records exist, user must have at least one role with CanAccess=1.
|
|
567
|
+
*/
|
|
568
|
+
UserHasApplicationAccess(applicationId) {
|
|
569
|
+
const appRoles = this._applicationRoles.filter(ar => UUIDsEqual(ar.ApplicationID, applicationId));
|
|
570
|
+
// No role records = open access (backwards compatible)
|
|
571
|
+
if (appRoles.length === 0)
|
|
572
|
+
return true;
|
|
573
|
+
// Check if any of the user's roles have CanAccess=1
|
|
574
|
+
const md = new Metadata();
|
|
575
|
+
const user = md.CurrentUser;
|
|
576
|
+
if (!user || !user.UserRoles)
|
|
577
|
+
return false;
|
|
578
|
+
return user.UserRoles.some(ur => appRoles.some(ar => UUIDsEqual(ar.RoleID, ur.RoleID) && ar.CanAccess));
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Checks if the current user can administer a specific application.
|
|
582
|
+
* Requires an explicit ApplicationRole record with CanAdmin=1.
|
|
583
|
+
*/
|
|
584
|
+
UserCanAdminApplication(applicationId) {
|
|
585
|
+
const appRoles = this._applicationRoles.filter(ar => UUIDsEqual(ar.ApplicationID, applicationId));
|
|
586
|
+
if (appRoles.length === 0)
|
|
587
|
+
return false; // No admin without explicit grant
|
|
588
|
+
const md = new Metadata();
|
|
589
|
+
const user = md.CurrentUser;
|
|
590
|
+
if (!user || !user.UserRoles)
|
|
591
|
+
return false;
|
|
592
|
+
return user.UserRoles.some(ur => appRoles.some(ar => UUIDsEqual(ar.RoleID, ur.RoleID) && ar.CanAdmin));
|
|
593
|
+
}
|
|
549
594
|
/**
|
|
550
595
|
* Check if an application is inactive in the system metadata.
|
|
551
596
|
* @param applicationId - The application ID to check
|