@memberjunction/core 3.4.0 → 4.1.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.
Files changed (107) hide show
  1. package/dist/generic/InMemoryLocalStorageProvider.d.ts +1 -1
  2. package/dist/generic/InMemoryLocalStorageProvider.js +2 -6
  3. package/dist/generic/InMemoryLocalStorageProvider.js.map +1 -1
  4. package/dist/generic/QueryCache.d.ts +1 -1
  5. package/dist/generic/QueryCache.js +6 -10
  6. package/dist/generic/QueryCache.js.map +1 -1
  7. package/dist/generic/QueryCacheConfig.js +1 -2
  8. package/dist/generic/RegisterForStartup.d.ts +2 -2
  9. package/dist/generic/RegisterForStartup.js +7 -12
  10. package/dist/generic/RegisterForStartup.js.map +1 -1
  11. package/dist/generic/applicationInfo.d.ts +3 -3
  12. package/dist/generic/applicationInfo.js +4 -10
  13. package/dist/generic/applicationInfo.js.map +1 -1
  14. package/dist/generic/authEvaluator.d.ts +1 -1
  15. package/dist/generic/authEvaluator.js +4 -8
  16. package/dist/generic/authEvaluator.js.map +1 -1
  17. package/dist/generic/authTypes.js +1 -4
  18. package/dist/generic/authTypes.js.map +1 -1
  19. package/dist/generic/baseEngine.d.ts +5 -5
  20. package/dist/generic/baseEngine.js +51 -56
  21. package/dist/generic/baseEngine.js.map +1 -1
  22. package/dist/generic/baseEngineRegistry.js +13 -17
  23. package/dist/generic/baseEngineRegistry.js.map +1 -1
  24. package/dist/generic/baseEntity.d.ts +171 -5
  25. package/dist/generic/baseEntity.d.ts.map +1 -1
  26. package/dist/generic/baseEntity.js +651 -121
  27. package/dist/generic/baseEntity.js.map +1 -1
  28. package/dist/generic/baseInfo.js +3 -7
  29. package/dist/generic/baseInfo.js.map +1 -1
  30. package/dist/generic/compositeKey.d.ts +2 -2
  31. package/dist/generic/compositeKey.js +5 -11
  32. package/dist/generic/compositeKey.js.map +1 -1
  33. package/dist/generic/databaseProviderBase.d.ts +2 -2
  34. package/dist/generic/databaseProviderBase.js +2 -6
  35. package/dist/generic/databaseProviderBase.js.map +1 -1
  36. package/dist/generic/entityInfo.d.ts +84 -5
  37. package/dist/generic/entityInfo.d.ts.map +1 -1
  38. package/dist/generic/entityInfo.js +235 -108
  39. package/dist/generic/entityInfo.js.map +1 -1
  40. package/dist/generic/explorerNavigationItem.d.ts +1 -1
  41. package/dist/generic/explorerNavigationItem.js +2 -6
  42. package/dist/generic/explorerNavigationItem.js.map +1 -1
  43. package/dist/generic/graphqlTypeNames.d.ts +1 -1
  44. package/dist/generic/graphqlTypeNames.js +4 -9
  45. package/dist/generic/graphqlTypeNames.js.map +1 -1
  46. package/dist/generic/interfaces.d.ts +104 -14
  47. package/dist/generic/interfaces.d.ts.map +1 -1
  48. package/dist/generic/interfaces.js +28 -30
  49. package/dist/generic/interfaces.js.map +1 -1
  50. package/dist/generic/libraryInfo.d.ts +1 -1
  51. package/dist/generic/libraryInfo.js +2 -6
  52. package/dist/generic/libraryInfo.js.map +1 -1
  53. package/dist/generic/localCacheManager.d.ts +2 -2
  54. package/dist/generic/localCacheManager.js +44 -48
  55. package/dist/generic/localCacheManager.js.map +1 -1
  56. package/dist/generic/logging.d.ts.map +1 -1
  57. package/dist/generic/logging.js +54 -67
  58. package/dist/generic/logging.js.map +1 -1
  59. package/dist/generic/metadata.d.ts +12 -12
  60. package/dist/generic/metadata.d.ts.map +1 -1
  61. package/dist/generic/metadata.js +21 -25
  62. package/dist/generic/metadata.js.map +1 -1
  63. package/dist/generic/metadataUtil.d.ts +1 -1
  64. package/dist/generic/metadataUtil.js +3 -7
  65. package/dist/generic/metadataUtil.js.map +1 -1
  66. package/dist/generic/providerBase.d.ts +63 -16
  67. package/dist/generic/providerBase.d.ts.map +1 -1
  68. package/dist/generic/providerBase.js +253 -130
  69. package/dist/generic/providerBase.js.map +1 -1
  70. package/dist/generic/queryInfo.d.ts +5 -5
  71. package/dist/generic/queryInfo.js +21 -30
  72. package/dist/generic/queryInfo.js.map +1 -1
  73. package/dist/generic/queryInfoInterfaces.js +1 -2
  74. package/dist/generic/queryInfoInterfaces.js.map +1 -1
  75. package/dist/generic/querySQLFilters.js +5 -10
  76. package/dist/generic/querySQLFilters.js.map +1 -1
  77. package/dist/generic/runQuery.d.ts +2 -2
  78. package/dist/generic/runQuery.js +5 -9
  79. package/dist/generic/runQuery.js.map +1 -1
  80. package/dist/generic/runQuerySQLFilterImplementations.d.ts +1 -1
  81. package/dist/generic/runQuerySQLFilterImplementations.js +4 -8
  82. package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -1
  83. package/dist/generic/runReport.d.ts +2 -2
  84. package/dist/generic/runReport.js +5 -9
  85. package/dist/generic/runReport.js.map +1 -1
  86. package/dist/generic/securityInfo.d.ts +2 -2
  87. package/dist/generic/securityInfo.js +10 -20
  88. package/dist/generic/securityInfo.js.map +1 -1
  89. package/dist/generic/telemetryManager.js +20 -32
  90. package/dist/generic/telemetryManager.js.map +1 -1
  91. package/dist/generic/transactionGroup.d.ts +1 -1
  92. package/dist/generic/transactionGroup.d.ts.map +1 -1
  93. package/dist/generic/transactionGroup.js +11 -19
  94. package/dist/generic/transactionGroup.js.map +1 -1
  95. package/dist/generic/util.js +15 -31
  96. package/dist/generic/util.js.map +1 -1
  97. package/dist/index.d.ts +34 -34
  98. package/dist/index.js +45 -63
  99. package/dist/index.js.map +1 -1
  100. package/dist/views/runView.d.ts +3 -3
  101. package/dist/views/runView.js +6 -11
  102. package/dist/views/runView.js.map +1 -1
  103. package/dist/views/viewInfo.d.ts +3 -3
  104. package/dist/views/viewInfo.js +10 -17
  105. package/dist/views/viewInfo.js.map +1 -1
  106. package/package.json +11 -10
  107. package/readme.md +871 -1271
@@ -1,22 +1,18 @@
1
- "use strict";
2
- var _a;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.ProviderBase = exports.AllMetadataArrays = exports.MetadataFromSimpleObjectWithoutUser = exports.MetadataFromSimpleObject = void 0;
5
- const baseEntity_1 = require("./baseEntity");
6
- const entityInfo_1 = require("./entityInfo");
7
- const interfaces_1 = require("./interfaces");
8
- const localCacheManager_1 = require("./localCacheManager");
9
- const applicationInfo_1 = require("../generic/applicationInfo");
10
- const securityInfo_1 = require("./securityInfo");
11
- const global_1 = require("@memberjunction/global");
12
- const telemetryManager_1 = require("./telemetryManager");
13
- const logging_1 = require("./logging");
14
- const queryInfo_1 = require("./queryInfo");
15
- const libraryInfo_1 = require("./libraryInfo");
16
- const compositeKey_1 = require("./compositeKey");
17
- const explorerNavigationItem_1 = require("./explorerNavigationItem");
18
- const metadata_1 = require("./metadata");
19
- const runView_1 = require("../views/runView");
1
+ import { BaseEntity } from "./baseEntity.js";
2
+ import { EntityDocumentTypeInfo, EntityInfo } from "./entityInfo.js";
3
+ import { AllMetadata } from "./interfaces.js";
4
+ import { LocalCacheManager } from "./localCacheManager.js";
5
+ import { ApplicationInfo } from "../generic/applicationInfo.js";
6
+ import { AuditLogTypeInfo, AuthorizationInfo, RoleInfo, RowLevelSecurityFilterInfo, UserInfo } from "./securityInfo.js";
7
+ import { MJGlobal } from "@memberjunction/global";
8
+ import { TelemetryManager } from "./telemetryManager.js";
9
+ import { LogError, LogStatus, LogStatusEx } from "./logging.js";
10
+ import { QueryCategoryInfo, QueryFieldInfo, QueryInfo, QueryPermissionInfo, QueryEntityInfo, QueryParameterInfo } from "./queryInfo.js";
11
+ import { LibraryInfo } from "./libraryInfo.js";
12
+ import { CompositeKey } from "./compositeKey.js";
13
+ import { ExplorerNavigationItem } from "./explorerNavigationItem.js";
14
+ import { Metadata } from "./metadata.js";
15
+ import { RunView } from "../views/runView.js";
20
16
  /**
21
17
  * Creates a new instance of AllMetadata from a simple object.
22
18
  * Handles deserialization and proper instantiation of all metadata classes.
@@ -24,17 +20,16 @@ const runView_1 = require("../views/runView");
24
20
  * @param md - The metadata provider for context
25
21
  * @returns A fully populated AllMetadata instance with proper type instances
26
22
  */
27
- function MetadataFromSimpleObject(data, md) {
23
+ export function MetadataFromSimpleObject(data, md) {
28
24
  try {
29
25
  const newObject = MetadataFromSimpleObjectWithoutUser(data, md);
30
- newObject.CurrentUser = data.CurrentUser ? new securityInfo_1.UserInfo(md, data.CurrentUser) : null;
26
+ newObject.CurrentUser = data.CurrentUser ? new UserInfo(md, data.CurrentUser) : null;
31
27
  return newObject;
32
28
  }
33
29
  catch (e) {
34
- (0, logging_1.LogError)(e);
30
+ LogError(e);
35
31
  }
36
32
  }
37
- exports.MetadataFromSimpleObject = MetadataFromSimpleObject;
38
33
  /**
39
34
  * Creates a new instance of AllMetadata from a simple object, but does NOT set the CurrentUser property
40
35
  * Handles deserialization and proper instantiation of all metadata classes.
@@ -42,11 +37,11 @@ exports.MetadataFromSimpleObject = MetadataFromSimpleObject;
42
37
  * @param md - The metadata provider for context
43
38
  * @returns A fully populated AllMetadata instance with proper type instances
44
39
  */
45
- function MetadataFromSimpleObjectWithoutUser(data, md) {
40
+ export function MetadataFromSimpleObjectWithoutUser(data, md) {
46
41
  try {
47
- const returnMetadata = new interfaces_1.AllMetadata();
42
+ const returnMetadata = new AllMetadata();
48
43
  // now iterate through the AllMetadataMapping array and construct the return type
49
- for (let m of exports.AllMetadataArrays) {
44
+ for (let m of AllMetadataArrays) {
50
45
  let simpleKey = m.key;
51
46
  if (!data.hasOwnProperty(simpleKey)) {
52
47
  simpleKey = simpleKey.substring(3); // remove the All prefix
@@ -62,44 +57,164 @@ function MetadataFromSimpleObjectWithoutUser(data, md) {
62
57
  return returnMetadata;
63
58
  }
64
59
  catch (e) {
65
- (0, logging_1.LogError)(e);
60
+ LogError(e);
66
61
  }
67
62
  }
68
- exports.MetadataFromSimpleObjectWithoutUser = MetadataFromSimpleObjectWithoutUser;
69
63
  /**
70
64
  * This is a list of all metadata classes that are used in the AllMetadata class.
71
65
  * Used to automatically determine the class type when deserializing the metadata and
72
66
  * for iterating through all metadata collections.
73
67
  * Each entry maps a property key to its corresponding class constructor.
74
68
  */
75
- exports.AllMetadataArrays = [
76
- { key: 'AllEntities', class: entityInfo_1.EntityInfo },
77
- { key: 'AllApplications', class: applicationInfo_1.ApplicationInfo },
78
- { key: 'AllRoles', class: securityInfo_1.RoleInfo },
79
- { key: 'AllRowLevelSecurityFilters', class: securityInfo_1.RowLevelSecurityFilterInfo },
80
- { key: 'AllAuditLogTypes', class: securityInfo_1.AuditLogTypeInfo },
81
- { key: 'AllAuthorizations', class: securityInfo_1.AuthorizationInfo },
82
- { key: 'AllQueryCategories', class: queryInfo_1.QueryCategoryInfo },
83
- { key: 'AllQueries', class: queryInfo_1.QueryInfo },
84
- { key: 'AllQueryFields', class: queryInfo_1.QueryFieldInfo },
85
- { key: 'AllQueryPermissions', class: queryInfo_1.QueryPermissionInfo },
86
- { key: 'AllQueryEntities', class: queryInfo_1.QueryEntityInfo },
87
- { key: 'AllQueryParameters', class: queryInfo_1.QueryParameterInfo },
88
- { key: 'AllEntityDocumentTypes', class: entityInfo_1.EntityDocumentTypeInfo },
89
- { key: 'AllLibraries', class: libraryInfo_1.LibraryInfo },
90
- { key: 'AllExplorerNavigationItems', class: explorerNavigationItem_1.ExplorerNavigationItem }
69
+ export const AllMetadataArrays = [
70
+ { key: 'AllEntities', class: EntityInfo },
71
+ { key: 'AllApplications', class: ApplicationInfo },
72
+ { key: 'AllRoles', class: RoleInfo },
73
+ { key: 'AllRowLevelSecurityFilters', class: RowLevelSecurityFilterInfo },
74
+ { key: 'AllAuditLogTypes', class: AuditLogTypeInfo },
75
+ { key: 'AllAuthorizations', class: AuthorizationInfo },
76
+ { key: 'AllQueryCategories', class: QueryCategoryInfo },
77
+ { key: 'AllQueries', class: QueryInfo },
78
+ { key: 'AllQueryFields', class: QueryFieldInfo },
79
+ { key: 'AllQueryPermissions', class: QueryPermissionInfo },
80
+ { key: 'AllQueryEntities', class: QueryEntityInfo },
81
+ { key: 'AllQueryParameters', class: QueryParameterInfo },
82
+ { key: 'AllEntityDocumentTypes', class: EntityDocumentTypeInfo },
83
+ { key: 'AllLibraries', class: LibraryInfo },
84
+ { key: 'AllExplorerNavigationItems', class: ExplorerNavigationItem }
91
85
  ];
92
86
  /**
93
87
  * Base class for all metadata providers in MemberJunction.
94
88
  * Implements common functionality for metadata caching, refresh, and dataset management.
95
89
  * Subclasses must implement abstract methods for provider-specific operations.
96
90
  */
97
- class ProviderBase {
91
+ export class ProviderBase {
98
92
  constructor() {
99
- this._localMetadata = new interfaces_1.AllMetadata();
93
+ this._localMetadata = new AllMetadata();
94
+ this._entityRecordNameCache = new Map();
100
95
  this._refresh = false;
101
96
  this._cachedVisibleExplorerNavigationItems = null;
102
97
  }
98
+ /**
99
+ * Helper to generate cache key for entity record names
100
+ */
101
+ getCacheKey(entityName, compositeKey) {
102
+ return `${entityName}|${compositeKey.ToString()}`;
103
+ }
104
+ /**
105
+ * Asynchronous lookup of a cached entity record name. Returns the cached name if available, or undefined if not cached.
106
+ * Use this for synchronous contexts (like template rendering) where you can't await GetEntityRecordName().
107
+ * @param entityName - The name of the entity
108
+ * @param compositeKey - The primary key value(s) for the record
109
+ * @param loadIfNeeded - If set to true, will load from database if not already cached
110
+ * @returns The cached display name, or undefined if not in cache
111
+ */
112
+ async GetCachedRecordName(entityName, compositeKey, loadIfNeeded) {
113
+ let cachedEntry = this._entityRecordNameCache.get(this.getCacheKey(entityName, compositeKey));
114
+ if (!cachedEntry && loadIfNeeded) {
115
+ cachedEntry = await this.GetEntityRecordName(entityName, compositeKey);
116
+ }
117
+ return cachedEntry;
118
+ }
119
+ /**
120
+ * Stores a record name in the cache for later synchronous retrieval via GetCachedRecordName().
121
+ * Called automatically by BaseEntity after Load(), LoadFromData(), and Save() operations.
122
+ * @param entityName - The name of the entity
123
+ * @param compositeKey - The primary key value(s) for the record
124
+ * @param recordName - The display name to cache
125
+ */
126
+ SetCachedRecordName(entityName, compositeKey, recordName) {
127
+ this._entityRecordNameCache.set(this.getCacheKey(entityName, compositeKey), recordName);
128
+ }
129
+ /**
130
+ * Gets the display name for a single entity record with caching.
131
+ * Uses the entity's IsNameField or falls back to 'Name' field if available.
132
+ * @param entityName - The name of the entity
133
+ * @param compositeKey - The primary key value(s) for the record
134
+ * @param contextUser - Optional user context for permissions
135
+ * @param forceRefresh - If true, bypasses cache and queries database
136
+ * @returns The display name of the record or null if not found
137
+ */
138
+ async GetEntityRecordName(entityName, compositeKey, contextUser, forceRefresh = false) {
139
+ const cacheKey = this.getCacheKey(entityName, compositeKey);
140
+ // Check cache unless forceRefresh
141
+ if (!forceRefresh) {
142
+ const cached = this._entityRecordNameCache.get(cacheKey);
143
+ if (cached !== undefined) {
144
+ return cached;
145
+ }
146
+ }
147
+ // Fetch from database via provider-specific implementation
148
+ const name = await this.InternalGetEntityRecordName(entityName, compositeKey, contextUser);
149
+ if (name) {
150
+ this._entityRecordNameCache.set(cacheKey, name);
151
+ }
152
+ return name;
153
+ }
154
+ /**
155
+ * Gets display names for multiple entity records in a single operation with caching.
156
+ * More efficient than multiple GetEntityRecordName calls.
157
+ * @param info - Array of entity/key pairs to lookup
158
+ * @param contextUser - Optional user context for permissions
159
+ * @param forceRefresh - If true, bypasses cache and queries database for all records
160
+ * @returns Array of results with names and status for each requested record
161
+ */
162
+ async GetEntityRecordNames(info, contextUser, forceRefresh = false) {
163
+ if (!forceRefresh) {
164
+ // Check cache for each item, collect uncached items
165
+ const results = [];
166
+ const uncachedInfo = [];
167
+ const uncachedIndexes = [];
168
+ for (let i = 0; i < info.length; i++) {
169
+ const item = info[i];
170
+ const cacheKey = this.getCacheKey(item.EntityName, item.CompositeKey);
171
+ const cached = this._entityRecordNameCache.get(cacheKey);
172
+ if (cached !== undefined) {
173
+ // Cache hit
174
+ results[i] = {
175
+ EntityName: item.EntityName,
176
+ CompositeKey: item.CompositeKey,
177
+ Status: 'cached',
178
+ Success: true,
179
+ RecordName: cached
180
+ };
181
+ }
182
+ else {
183
+ // Cache miss - need to fetch
184
+ uncachedInfo.push(item);
185
+ uncachedIndexes.push(i);
186
+ }
187
+ }
188
+ // Fetch uncached items from database
189
+ if (uncachedInfo.length > 0) {
190
+ const uncachedResults = await this.InternalGetEntityRecordNames(uncachedInfo, contextUser);
191
+ // Merge results and update cache
192
+ for (let i = 0; i < uncachedResults.length; i++) {
193
+ const result = uncachedResults[i];
194
+ const originalIndex = uncachedIndexes[i];
195
+ results[originalIndex] = result;
196
+ // Cache successful results
197
+ if (result.Success && result.RecordName) {
198
+ const cacheKey = this.getCacheKey(result.EntityName, result.CompositeKey);
199
+ this._entityRecordNameCache.set(cacheKey, result.RecordName);
200
+ }
201
+ }
202
+ }
203
+ return results;
204
+ }
205
+ else {
206
+ // Force refresh - bypass cache entirely
207
+ const results = await this.InternalGetEntityRecordNames(info, contextUser);
208
+ // Update cache with fresh results
209
+ for (const result of results) {
210
+ if (result.Success && result.RecordName) {
211
+ const cacheKey = this.getCacheKey(result.EntityName, result.CompositeKey);
212
+ this._entityRecordNameCache.set(cacheKey, result.RecordName);
213
+ }
214
+ }
215
+ return results;
216
+ }
217
+ }
103
218
  // ========================================================================
104
219
  // PUBLIC API METHODS - Orchestrate Pre → Cache → Internal → Post flow
105
220
  // ========================================================================
@@ -135,7 +250,7 @@ class ProviderBase {
135
250
  // Check for cached results - if all are cached, end telemetry and return early
136
251
  if (preResult.allCached && preResult.cachedResults) {
137
252
  const totalResults = preResult.cachedResults.reduce((sum, r) => sum + (r.Results?.length ?? 0), 0);
138
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
253
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
139
254
  cacheHit: true,
140
255
  allCached: true,
141
256
  batchSize: params.length,
@@ -166,7 +281,7 @@ class ProviderBase {
166
281
  const preResult = await this.PreRunQuery(params, contextUser);
167
282
  // Check for cached result - end telemetry with cache hit info
168
283
  if (preResult.cachedResult) {
169
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
284
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
170
285
  cacheHit: true,
171
286
  cacheStatus: preResult.cacheStatus,
172
287
  resultCount: preResult.cachedResult.Results?.length ?? 0
@@ -192,7 +307,7 @@ class ProviderBase {
192
307
  // Check for cached results - if all are cached, end telemetry and return early
193
308
  if (preResult.allCached && preResult.cachedResults) {
194
309
  const totalResults = preResult.cachedResults.reduce((sum, r) => sum + (r.Results?.length ?? 0), 0);
195
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
310
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
196
311
  cacheHit: true,
197
312
  allCached: true,
198
313
  batchSize: params.length,
@@ -218,12 +333,12 @@ class ProviderBase {
218
333
  * @param callerName
219
334
  */
220
335
  async EntityStatusCheck(params, callerName) {
221
- const entityName = await runView_1.RunView.GetEntityNameFromRunViewParams(params, this);
336
+ const entityName = await RunView.GetEntityNameFromRunViewParams(params, this);
222
337
  const entity = this.Entities.find(e => e.Name.trim().toLowerCase() === entityName?.trim().toLowerCase());
223
338
  if (!entity) {
224
339
  throw new Error(`Entity ${entityName} not found in metadata`);
225
340
  }
226
- entityInfo_1.EntityInfo.AssertEntityActiveStatus(entity, callerName);
341
+ EntityInfo.AssertEntityActiveStatus(entity, callerName);
227
342
  }
228
343
  // Type aliases for cleaner code
229
344
  get PreRunViewResult() { return this._preRunViewResultType; }
@@ -244,7 +359,7 @@ class ProviderBase {
244
359
  const preViewStart = performance.now();
245
360
  // Start telemetry tracking
246
361
  const telemetryStart = performance.now();
247
- const telemetryEventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunView', {
362
+ const telemetryEventId = TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunView', {
248
363
  EntityName: params.EntityName,
249
364
  ViewID: params.ViewID,
250
365
  ViewName: params.ViewName,
@@ -275,9 +390,9 @@ class ProviderBase {
275
390
  let cacheStatus = 'disabled';
276
391
  let cachedResult;
277
392
  let fingerprint;
278
- if (params.CacheLocal && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
279
- fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(params, this.InstanceConnectionString);
280
- const cached = await localCacheManager_1.LocalCacheManager.Instance.GetRunViewResult(fingerprint);
393
+ if (params.CacheLocal && LocalCacheManager.Instance.IsInitialized) {
394
+ fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(params, this.InstanceConnectionString);
395
+ const cached = await LocalCacheManager.Instance.GetRunViewResult(fingerprint);
281
396
  if (cached) {
282
397
  // Reconstruct RunViewResult from cached data
283
398
  cachedResult = {
@@ -299,7 +414,7 @@ class ProviderBase {
299
414
  const cacheCheckTime = performance.now() - cacheCheckStart;
300
415
  const totalPreTime = performance.now() - preViewStart;
301
416
  if (totalPreTime > 50) {
302
- console.log(`[PERF-PRE] PreRunView ${params.EntityName}: ${totalPreTime.toFixed(1)}ms (telemetry=${telemetryTime.toFixed(1)}ms, entityCheck=${entityCheckTime.toFixed(1)}ms, entityLookup=${entityLookupTime.toFixed(1)}ms, cache=${cacheCheckTime.toFixed(1)}ms)`);
417
+ LogStatus(`[PERF-PRE] PreRunView ${params.EntityName}: ${totalPreTime.toFixed(1)}ms (telemetry=${telemetryTime.toFixed(1)}ms, entityCheck=${entityCheckTime.toFixed(1)}ms, entityLookup=${entityLookupTime.toFixed(1)}ms, cache=${cacheCheckTime.toFixed(1)}ms)`);
303
418
  }
304
419
  return {
305
420
  telemetryEventId,
@@ -318,7 +433,7 @@ class ProviderBase {
318
433
  async PreRunViews(params, contextUser) {
319
434
  // Start telemetry tracking for batch operation
320
435
  const fromEngine = params.some(p => p._fromEngine);
321
- const telemetryEventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunViews', {
436
+ const telemetryEventId = TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunViews', {
322
437
  BatchSize: params.length,
323
438
  Entities: params.map(p => p.EntityName || p.ViewName || p.ViewID).filter(Boolean),
324
439
  _fromEngine: fromEngine
@@ -326,7 +441,7 @@ class ProviderBase {
326
441
  // Check if any params have CacheLocal enabled - smart caching is always used when caching locally
327
442
  const useSmartCacheCheck = params.some(p => p.CacheLocal);
328
443
  // If local caching is enabled, use smart cache check flow
329
- if (useSmartCacheCheck && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
444
+ if (useSmartCacheCheck && LocalCacheManager.Instance.IsInitialized) {
330
445
  return this.prepareSmartCacheCheckParams(params, telemetryEventId, contextUser);
331
446
  }
332
447
  // Traditional caching flow
@@ -347,9 +462,9 @@ class ProviderBase {
347
462
  param.Fields = entity.Fields.map(f => f.Name);
348
463
  }
349
464
  // Check local cache if enabled
350
- if (param.CacheLocal && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
351
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
352
- const cached = await localCacheManager_1.LocalCacheManager.Instance.GetRunViewResult(fingerprint);
465
+ if (param.CacheLocal && LocalCacheManager.Instance.IsInitialized) {
466
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
467
+ const cached = await LocalCacheManager.Instance.GetRunViewResult(fingerprint);
353
468
  if (cached) {
354
469
  const cachedViewResult = {
355
470
  Success: true,
@@ -404,9 +519,9 @@ class ProviderBase {
404
519
  }
405
520
  // Build the cache check param with optional cache status
406
521
  let cacheStatus;
407
- if (param.CacheLocal && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
408
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
409
- const cached = await localCacheManager_1.LocalCacheManager.Instance.GetRunViewResult(fingerprint);
522
+ if (param.CacheLocal && LocalCacheManager.Instance.IsInitialized) {
523
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
524
+ const cached = await LocalCacheManager.Instance.GetRunViewResult(fingerprint);
410
525
  if (cached) {
411
526
  cacheStatus = {
412
527
  maxUpdatedAt: cached.maxUpdatedAt,
@@ -442,8 +557,8 @@ class ProviderBase {
442
557
  const response = await provider.RunViewsWithCacheCheck(preResult.smartCacheCheckParams, contextUser);
443
558
  if (!response.success) {
444
559
  // If the smart cache check failed, log and return empty results
445
- (0, logging_1.LogError)(`SmartCacheCheck failed: ${response.errorMessage}`);
446
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
560
+ LogError(`SmartCacheCheck failed: ${response.errorMessage}`);
561
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
447
562
  smartCacheCheck: true,
448
563
  success: false,
449
564
  errorMessage: response.errorMessage
@@ -471,7 +586,7 @@ class ProviderBase {
471
586
  cacheMisses++;
472
587
  }
473
588
  // End telemetry
474
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
589
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
475
590
  smartCacheCheck: true,
476
591
  success: true,
477
592
  cacheHits,
@@ -503,8 +618,8 @@ class ProviderBase {
503
618
  }
504
619
  if (checkResult.status === 'current') {
505
620
  // Cache is current - use cached data
506
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
507
- const cached = await localCacheManager_1.LocalCacheManager.Instance.GetRunViewResult(fingerprint);
621
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
622
+ const cached = await LocalCacheManager.Instance.GetRunViewResult(fingerprint);
508
623
  if (cached) {
509
624
  const cachedResult = {
510
625
  Success: true,
@@ -539,13 +654,13 @@ class ProviderBase {
539
654
  }
540
655
  else if (checkResult.status === 'differential') {
541
656
  // Cache is stale but we have differential data - merge with cached data
542
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
657
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
543
658
  // Get entity info for primary key field name
544
659
  const entity = this.Entities.find(e => e.Name.trim().toLowerCase() === param.EntityName?.trim().toLowerCase());
545
660
  const primaryKeyFieldName = entity?.FirstPrimaryKey?.Name || 'ID';
546
661
  // Apply differential update to cache
547
- if (param.CacheLocal && checkResult.differentialData && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
548
- const merged = await localCacheManager_1.LocalCacheManager.Instance.ApplyDifferentialUpdate(fingerprint, param, checkResult.differentialData.updatedRows, checkResult.differentialData.deletedRecordIDs, primaryKeyFieldName, checkResult.maxUpdatedAt || new Date().toISOString(), checkResult.rowCount || 0, checkResult.aggregateResults // Pass fresh aggregate results (can't be differentially computed)
662
+ if (param.CacheLocal && checkResult.differentialData && LocalCacheManager.Instance.IsInitialized) {
663
+ const merged = await LocalCacheManager.Instance.ApplyDifferentialUpdate(fingerprint, param, checkResult.differentialData.updatedRows, checkResult.differentialData.deletedRecordIDs, primaryKeyFieldName, checkResult.maxUpdatedAt || new Date().toISOString(), checkResult.rowCount || 0, checkResult.aggregateResults // Pass fresh aggregate results (can't be differentially computed)
549
664
  );
550
665
  if (merged) {
551
666
  const mergedResult = {
@@ -584,12 +699,12 @@ class ProviderBase {
584
699
  AggregateResults: checkResult.aggregateResults // Include fresh aggregate results
585
700
  };
586
701
  // Update the local cache with fresh data (don't await - fire and forget for performance)
587
- if (param.CacheLocal && checkResult.maxUpdatedAt && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
588
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
702
+ if (param.CacheLocal && checkResult.maxUpdatedAt && LocalCacheManager.Instance.IsInitialized) {
703
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(param, this.InstanceConnectionString);
589
704
  // Note: We don't await here to avoid blocking the response
590
705
  // Cache update happens in background
591
- localCacheManager_1.LocalCacheManager.Instance.SetRunViewResult(fingerprint, param, checkResult.results || [], checkResult.maxUpdatedAt, checkResult.aggregateResults // Include aggregate results in cache
592
- ).catch(e => (0, logging_1.LogError)(`Failed to update cache: ${e}`));
706
+ LocalCacheManager.Instance.SetRunViewResult(fingerprint, param, checkResult.results || [], checkResult.maxUpdatedAt, checkResult.aggregateResults // Include aggregate results in cache
707
+ ).catch(e => LogError(`Failed to update cache: ${e}`));
593
708
  }
594
709
  // Transform to entity objects if needed
595
710
  await this.TransformSimpleObjectToEntityObject(param, freshResult, contextUser);
@@ -621,7 +736,7 @@ class ProviderBase {
621
736
  */
622
737
  async PreRunQuery(params, contextUser) {
623
738
  // Start telemetry tracking
624
- const telemetryEventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunQuery', 'ProviderBase.RunQuery', {
739
+ const telemetryEventId = TelemetryManager.Instance.StartEvent('RunQuery', 'ProviderBase.RunQuery', {
625
740
  QueryID: params.QueryID,
626
741
  QueryName: params.QueryName,
627
742
  CategoryPath: params.CategoryPath,
@@ -648,7 +763,7 @@ class ProviderBase {
648
763
  */
649
764
  async PreRunQueries(params, contextUser) {
650
765
  // Start telemetry tracking for batch operation
651
- const telemetryEventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunQuery', 'ProviderBase.RunQueries', {
766
+ const telemetryEventId = TelemetryManager.Instance.StartEvent('RunQuery', 'ProviderBase.RunQueries', {
652
767
  BatchSize: params.length,
653
768
  Queries: params.map(p => p.QueryName || p.QueryID).filter(Boolean)
654
769
  }, contextUser?.ID);
@@ -676,15 +791,15 @@ class ProviderBase {
676
791
  // Transform the result set into BaseEntity-derived objects, if needed
677
792
  await this.TransformSimpleObjectToEntityObject(params, result, contextUser);
678
793
  // Store in local cache if enabled and we have a successful result
679
- if (params.CacheLocal && result.Success && preResult.fingerprint && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
794
+ if (params.CacheLocal && result.Success && preResult.fingerprint && LocalCacheManager.Instance.IsInitialized) {
680
795
  // Extract maxUpdatedAt from results if available
681
796
  const maxUpdatedAt = this.extractMaxUpdatedAt(result.Results);
682
- await localCacheManager_1.LocalCacheManager.Instance.SetRunViewResult(preResult.fingerprint, params, result.Results, maxUpdatedAt, result.AggregateResults // Include aggregate results in cache
797
+ await LocalCacheManager.Instance.SetRunViewResult(preResult.fingerprint, params, result.Results, maxUpdatedAt, result.AggregateResults // Include aggregate results in cache
683
798
  );
684
799
  }
685
800
  // End telemetry tracking with cache miss info
686
801
  if (preResult.telemetryEventId) {
687
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
802
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
688
803
  cacheHit: false,
689
804
  cacheStatus: preResult.cacheStatus,
690
805
  resultCount: result.Results?.length ?? 0,
@@ -706,10 +821,10 @@ class ProviderBase {
706
821
  for (let i = 0; i < results.length; i++) {
707
822
  promises.push(this.TransformSimpleObjectToEntityObject(params[i], results[i], contextUser));
708
823
  // Store in local cache if enabled
709
- if (params[i].CacheLocal && results[i].Success && localCacheManager_1.LocalCacheManager.Instance.IsInitialized) {
710
- const fingerprint = localCacheManager_1.LocalCacheManager.Instance.GenerateRunViewFingerprint(params[i], this.InstanceConnectionString);
824
+ if (params[i].CacheLocal && results[i].Success && LocalCacheManager.Instance.IsInitialized) {
825
+ const fingerprint = LocalCacheManager.Instance.GenerateRunViewFingerprint(params[i], this.InstanceConnectionString);
711
826
  const maxUpdatedAt = this.extractMaxUpdatedAt(results[i].Results);
712
- promises.push(localCacheManager_1.LocalCacheManager.Instance.SetRunViewResult(fingerprint, params[i], results[i].Results, maxUpdatedAt, results[i].AggregateResults // Include aggregate results in cache
827
+ promises.push(LocalCacheManager.Instance.SetRunViewResult(fingerprint, params[i], results[i].Results, maxUpdatedAt, results[i].AggregateResults // Include aggregate results in cache
713
828
  ));
714
829
  }
715
830
  }
@@ -720,7 +835,7 @@ class ProviderBase {
720
835
  const cachedCount = preResult.cacheStatusMap
721
836
  ? [...preResult.cacheStatusMap.values()].filter(s => s.status === 'hit').length
722
837
  : 0;
723
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
838
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
724
839
  cacheHit: false,
725
840
  allCached: false,
726
841
  batchSize: params.length,
@@ -742,7 +857,7 @@ class ProviderBase {
742
857
  // Query caching is handled internally by the provider
743
858
  // End telemetry tracking with cache miss info
744
859
  if (preResult.telemetryEventId) {
745
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
860
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
746
861
  cacheHit: false,
747
862
  cacheStatus: preResult.cacheStatus,
748
863
  resultCount: result.Results?.length ?? 0,
@@ -766,7 +881,7 @@ class ProviderBase {
766
881
  const cachedCount = preResult.cacheStatusMap
767
882
  ? [...preResult.cacheStatusMap.values()].filter(s => s.status === 'hit').length
768
883
  : 0;
769
- telemetryManager_1.TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
884
+ TelemetryManager.Instance.EndEvent(preResult.telemetryEventId, {
770
885
  cacheHit: false,
771
886
  allCached: false,
772
887
  batchSize: params.length,
@@ -856,7 +971,7 @@ class ProviderBase {
856
971
  */
857
972
  async PreProcessRunView(params, contextUser) {
858
973
  // Start telemetry tracking
859
- const eventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunView', {
974
+ const eventId = TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunView', {
860
975
  EntityName: params.EntityName,
861
976
  ViewID: params.ViewID,
862
977
  ViewName: params.ViewName,
@@ -892,7 +1007,7 @@ class ProviderBase {
892
1007
  // End telemetry tracking
893
1008
  const eventId = params._telemetryEventId;
894
1009
  if (eventId) {
895
- telemetryManager_1.TelemetryManager.Instance.EndEvent(eventId);
1010
+ TelemetryManager.Instance.EndEvent(eventId);
896
1011
  delete params._telemetryEventId;
897
1012
  }
898
1013
  }
@@ -906,7 +1021,7 @@ class ProviderBase {
906
1021
  async PreProcessRunViews(params, contextUser) {
907
1022
  // Start telemetry tracking for batch operation
908
1023
  const fromEngine = params.some(p => p._fromEngine);
909
- const eventId = telemetryManager_1.TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunViews', {
1024
+ const eventId = TelemetryManager.Instance.StartEvent('RunView', 'ProviderBase.RunViews', {
910
1025
  BatchSize: params.length,
911
1026
  Entities: params.map(p => p.EntityName || p.ViewName || p.ViewID).filter(Boolean),
912
1027
  _fromEngine: fromEngine
@@ -950,7 +1065,7 @@ class ProviderBase {
950
1065
  // End telemetry tracking for batch operation
951
1066
  const eventId = params[0]._telemetryBatchEventId;
952
1067
  if (eventId) {
953
- telemetryManager_1.TelemetryManager.Instance.EndEvent(eventId);
1068
+ TelemetryManager.Instance.EndEvent(eventId);
954
1069
  delete params[0]._telemetryBatchEventId;
955
1070
  }
956
1071
  }
@@ -967,7 +1082,7 @@ class ProviderBase {
967
1082
  // we need to transform each of the items in the result set into a BaseEntity-derived object
968
1083
  // Create entities and load data in parallel for better performance
969
1084
  const entityPromises = result.Results.map(async (item) => {
970
- if (item instanceof baseEntity_1.BaseEntity || (typeof item.Save === 'function')) {
1085
+ if (item instanceof BaseEntity || (typeof item.Save === 'function')) {
971
1086
  // the second check is a "duck-typing" check in case we have different runtime
972
1087
  // loading sources where the instanceof will fail
973
1088
  return item;
@@ -998,7 +1113,7 @@ class ProviderBase {
998
1113
  this._ConfigData = data;
999
1114
  // first, let's check to see if we have an existing Metadata.Provider registered, if so
1000
1115
  // unless our data.IgnoreExistingMetadata is set to true, we will not refresh the metadata
1001
- if (metadata_1.Metadata.Provider && !data.IgnoreExistingMetadata) {
1116
+ if (Metadata.Provider && !data.IgnoreExistingMetadata) {
1002
1117
  // we have an existing globally registered provider AND we are not
1003
1118
  // requested to ignore the existing metadata, so we will not refresh it
1004
1119
  if (this.CopyMetadataFromGlobalProvider()) {
@@ -1015,7 +1130,7 @@ class ProviderBase {
1015
1130
  const start = new Date().getTime();
1016
1131
  const res = await this.GetAllMetadata(providerToUse);
1017
1132
  const end = new Date().getTime();
1018
- (0, logging_1.LogStatus)(`GetAllMetadata() took ${end - start} ms`);
1133
+ LogStatusEx({ message: `GetAllMetadata() took ${end - start} ms`, verboseOnly: true });
1019
1134
  if (res) {
1020
1135
  // Atomic swap via UpdateLocalMetadata: single property assignment is atomic in JavaScript
1021
1136
  // Readers now see new metadata instead of old
@@ -1027,7 +1142,7 @@ class ProviderBase {
1027
1142
  }
1028
1143
  else {
1029
1144
  // GetAllMetadata failed - log error but keep existing metadata
1030
- (0, logging_1.LogError)('GetAllMetadata() returned undefined - metadata not updated');
1145
+ LogError('GetAllMetadata() returned undefined - metadata not updated');
1031
1146
  }
1032
1147
  }
1033
1148
  return true;
@@ -1046,14 +1161,14 @@ class ProviderBase {
1046
1161
  */
1047
1162
  CopyMetadataFromGlobalProvider() {
1048
1163
  try {
1049
- if (metadata_1.Metadata.Provider && metadata_1.Metadata.Provider !== this && metadata_1.Metadata.Provider.AllMetadata) {
1050
- this._localMetadata = this.CloneAllMetadata(metadata_1.Metadata.Provider.AllMetadata);
1164
+ if (Metadata.Provider && Metadata.Provider !== this && Metadata.Provider.AllMetadata) {
1165
+ this._localMetadata = this.CloneAllMetadata(Metadata.Provider.AllMetadata);
1051
1166
  return true;
1052
1167
  }
1053
1168
  return false;
1054
1169
  }
1055
1170
  catch (e) {
1056
- (0, logging_1.LogError)(`Failed to copy metadata from global provider: ${e.message}`);
1171
+ LogError(`Failed to copy metadata from global provider: ${e.message}`);
1057
1172
  return false; // if we fail to copy the metadata, we will return false
1058
1173
  }
1059
1174
  }
@@ -1077,7 +1192,7 @@ class ProviderBase {
1077
1192
  if (excludeSchemaList && excludeSchemaList.length > 0 && excludeSchemaList.indexOf(mjcSchema) !== -1) {
1078
1193
  const index = excludeSchemaList.indexOf(mjcSchema);
1079
1194
  excludeSchemaList.splice(index, 1);
1080
- (0, logging_1.LogStatus)(`Removed MJ Core schema (${mjcSchema}) from ExcludeSchemas list because it is required for the API to function correctly`);
1195
+ LogStatus(`Removed MJ Core schema (${mjcSchema}) from ExcludeSchemas list because it is required for the API to function correctly`);
1081
1196
  }
1082
1197
  let schemaFilter = '';
1083
1198
  if (includeSchemaList && includeSchemaList.length > 0) {
@@ -1092,6 +1207,7 @@ class ProviderBase {
1092
1207
  }
1093
1208
  return f;
1094
1209
  }
1210
+ static { this._mjMetadataDatasetName = 'MJ_Metadata'; }
1095
1211
  /**
1096
1212
  * Retrieves all metadata from the server and constructs typed instances.
1097
1213
  * Uses the MJ_Metadata dataset for efficient bulk loading.
@@ -1103,10 +1219,10 @@ class ProviderBase {
1103
1219
  //const start1 = new Date().getTime();
1104
1220
  const f = this.BuildDatasetFilterFromConfig();
1105
1221
  // Get the dataset and cache it for anyone else who wants to use it
1106
- const d = await this.GetDatasetByName(_a._mjMetadataDatasetName, f.length > 0 ? f : null, this.CurrentUser, providerToUse);
1222
+ const d = await this.GetDatasetByName(ProviderBase._mjMetadataDatasetName, f.length > 0 ? f : null, this.CurrentUser, providerToUse);
1107
1223
  if (d && d.Success) {
1108
1224
  // cache the dataset for anyone who wants to use it
1109
- await this.CacheDataset(_a._mjMetadataDatasetName, f.length > 0 ? f : null, d);
1225
+ await this.CacheDataset(ProviderBase._mjMetadataDatasetName, f.length > 0 ? f : null, d);
1110
1226
  // got the results, let's build our response in the format we need
1111
1227
  const simpleMetadata = {};
1112
1228
  for (let r of d.Results) {
@@ -1118,7 +1234,7 @@ class ProviderBase {
1118
1234
  simpleMetadata.AllApplications = simpleMetadata.Applications.map((a) => {
1119
1235
  a.ApplicationEntities = simpleMetadata.ApplicationEntities.filter((ae) => ae.ApplicationID === a.ID);
1120
1236
  a.ApplicationSettings = simpleMetadata.ApplicationSettings.filter((as) => as.ApplicationID === a.ID);
1121
- return new applicationInfo_1.ApplicationInfo(a, this);
1237
+ return new ApplicationInfo(a, this);
1122
1238
  });
1123
1239
  // now we need to construct our return type. The way the return type works, which is an instance of AllMetadata, we have to
1124
1240
  // construst each item so it contains an array of the correct type. This is because the AllMetadata class has an array of each type of metadata
@@ -1129,11 +1245,11 @@ class ProviderBase {
1129
1245
  return returnMetadata;
1130
1246
  }
1131
1247
  else {
1132
- (0, logging_1.LogError)('GetAllMetadata() - Error getting metadata from server' + (d ? ': ' + d.Status : ''));
1248
+ LogError('GetAllMetadata() - Error getting metadata from server' + (d ? ': ' + d.Status : ''));
1133
1249
  }
1134
1250
  }
1135
1251
  catch (e) {
1136
- (0, logging_1.LogError)(e);
1252
+ LogError(e);
1137
1253
  }
1138
1254
  }
1139
1255
  /**
@@ -1162,7 +1278,7 @@ class ProviderBase {
1162
1278
  e.EntityPermissions = permissions.filter(p => p.EntityID === e.ID);
1163
1279
  e.EntityRelationships = relationships.filter(r => r.EntityID === e.ID);
1164
1280
  e.EntitySettings = settings.filter(s => s.EntityID === e.ID);
1165
- result.push(new entityInfo_1.EntityInfo(e));
1281
+ result.push(new EntityInfo(e));
1166
1282
  }
1167
1283
  return result;
1168
1284
  }
@@ -1333,7 +1449,7 @@ class ProviderBase {
1333
1449
  // Determine which overload was called
1334
1450
  let actualLoadKey;
1335
1451
  let actualContextUser;
1336
- if (loadKeyOrContextUser instanceof compositeKey_1.CompositeKey) {
1452
+ if (loadKeyOrContextUser instanceof CompositeKey) {
1337
1453
  // Second overload: entityName, loadKey, contextUser
1338
1454
  actualLoadKey = loadKeyOrContextUser;
1339
1455
  actualContextUser = contextUser;
@@ -1352,8 +1468,10 @@ class ProviderBase {
1352
1468
  // Use the MJGlobal Class Factory to do our object instantiation - we do NOT use metadata for this anymore, doesn't work well to have file paths with node dynamically at runtime
1353
1469
  // type reference registration by any module via MJ Global is the way to go as it is reliable across all platforms.
1354
1470
  try {
1355
- const newObject = global_1.MJGlobal.Instance.ClassFactory.CreateInstance(baseEntity_1.BaseEntity, entityName, entity, this);
1471
+ const newObject = MJGlobal.Instance.ClassFactory.CreateInstance(BaseEntity, entityName, entity, this);
1356
1472
  await newObject.Config(actualContextUser);
1473
+ // Initialize IS-A parent entity composition chain before any data operations
1474
+ await newObject.InitializeParentEntity();
1357
1475
  if (actualLoadKey) {
1358
1476
  // Load existing record
1359
1477
  const loadResult = await newObject.InnerLoad(actualLoadKey);
@@ -1369,7 +1487,7 @@ class ProviderBase {
1369
1487
  return newObject;
1370
1488
  }
1371
1489
  catch (e) {
1372
- (0, logging_1.LogError)(e);
1490
+ LogError(e);
1373
1491
  throw new Error(`Entity ${entityName} could not be instantiated via MJGlobal Class Factory. Make sure you have registered the class reference with MJGlobal.Instance.ClassFactory.Register(). ALSO, make sure you call LoadGeneratedEntities() from the GeneratedEntities project within your project as tree-shaking sometimes removes subclasses and could be causing this error!`);
1374
1492
  }
1375
1493
  }
@@ -1377,7 +1495,7 @@ class ProviderBase {
1377
1495
  throw new Error(`Entity ${entityName} not found in metadata`);
1378
1496
  }
1379
1497
  catch (ex) {
1380
- (0, logging_1.LogError)(ex);
1498
+ LogError(ex);
1381
1499
  return null;
1382
1500
  }
1383
1501
  }
@@ -1406,7 +1524,7 @@ class ProviderBase {
1406
1524
  return result;
1407
1525
  }
1408
1526
  catch (e) {
1409
- (0, logging_1.LogError)(e);
1527
+ LogError(e);
1410
1528
  throw e;
1411
1529
  }
1412
1530
  }
@@ -1557,7 +1675,7 @@ class ProviderBase {
1557
1675
  * @returns
1558
1676
  */
1559
1677
  GetDatasetCacheKey(datasetName, itemFilters) {
1560
- return this.LocalStoragePrefix + _a.localStorageRootKey + this.InstanceConnectionString + '__DATASET__' + datasetName + this.ConvertItemFiltersToUniqueKey(itemFilters);
1678
+ return this.LocalStoragePrefix + ProviderBase.localStorageRootKey + this.InstanceConnectionString + '__DATASET__' + datasetName + this.ConvertItemFiltersToUniqueKey(itemFilters);
1561
1679
  }
1562
1680
  /**
1563
1681
  * Converts dataset item filters into a unique string key for caching.
@@ -1608,7 +1726,7 @@ class ProviderBase {
1608
1726
  */
1609
1727
  async GetLatestMetadataUpdates(providerToUse) {
1610
1728
  const f = this.BuildDatasetFilterFromConfig();
1611
- const d = await this.GetDatasetStatusByName(_a._mjMetadataDatasetName, f.length > 0 ? f : null, this.CurrentUser, providerToUse);
1729
+ const d = await this.GetDatasetStatusByName(ProviderBase._mjMetadataDatasetName, f.length > 0 ? f : null, this.CurrentUser, providerToUse);
1612
1730
  if (d && d.Success) {
1613
1731
  const ret = d.EntityUpdateDates.map(e => {
1614
1732
  return {
@@ -1699,6 +1817,14 @@ class ProviderBase {
1699
1817
  UpdateLocalMetadata(res) {
1700
1818
  this._localMetadata = res;
1701
1819
  }
1820
+ /**
1821
+ * Returns the filesystem provider for the current environment.
1822
+ * Default implementation returns null (no filesystem access).
1823
+ * Server-side providers should override this to return a NodeFileSystemProvider.
1824
+ */
1825
+ get FileSystemProvider() {
1826
+ return null;
1827
+ }
1702
1828
  /**
1703
1829
  * Loads metadata from local storage if available.
1704
1830
  * Deserializes and reconstructs typed metadata objects.
@@ -1708,8 +1834,8 @@ class ProviderBase {
1708
1834
  const ls = this.LocalStorageProvider;
1709
1835
  if (ls) {
1710
1836
  // execution environment supports local storage, use it
1711
- this._latestLocalMetadataTimestamps = JSON.parse(await ls.GetItem(this.LocalStoragePrefix + _a.localStorageTimestampsKey));
1712
- const temp = JSON.parse(await ls.GetItem(this.LocalStoragePrefix + _a.localStorageAllMetadataKey)); // we now have a simple object for all the metadata
1837
+ this._latestLocalMetadataTimestamps = JSON.parse(await ls.GetItem(this.LocalStoragePrefix + ProviderBase.localStorageTimestampsKey));
1838
+ const temp = JSON.parse(await ls.GetItem(this.LocalStoragePrefix + ProviderBase.localStorageAllMetadataKey)); // we now have a simple object for all the metadata
1713
1839
  if (temp) {
1714
1840
  // we have local metadata
1715
1841
  const metadata = MetadataFromSimpleObject(temp, this); // create a new object to start this up
@@ -1721,6 +1847,13 @@ class ProviderBase {
1721
1847
  // some enviroments don't support local storage
1722
1848
  }
1723
1849
  }
1850
+ static { this.localStorageRootKey = '___MJCore_Metadata'; }
1851
+ static { this.localStorageTimestampsKey = this.localStorageRootKey + '_Timestamps'; }
1852
+ static { this.localStorageAllMetadataKey = this.localStorageRootKey + '_AllMetadata'; }
1853
+ static { this.localStorageKeys = [
1854
+ ProviderBase.localStorageTimestampsKey,
1855
+ ProviderBase.localStorageAllMetadataKey,
1856
+ ]; }
1724
1857
  /**
1725
1858
  * This property will return the prefix to use for local storage keys. This is useful if you have multiple instances of a provider running in the same environment
1726
1859
  * and you want to keep their local storage keys separate. The default implementation returns an empty string, but subclasses can override this to return a unique string
@@ -1738,14 +1871,14 @@ class ProviderBase {
1738
1871
  const ls = this.LocalStorageProvider;
1739
1872
  if (ls) {
1740
1873
  // execution environment supports local storage, use it
1741
- await ls.SetItem(this.LocalStoragePrefix + _a.localStorageTimestampsKey, JSON.stringify(this._latestLocalMetadataTimestamps));
1874
+ await ls.SetItem(this.LocalStoragePrefix + ProviderBase.localStorageTimestampsKey, JSON.stringify(this._latestLocalMetadataTimestamps));
1742
1875
  // now persist the AllMetadata object
1743
- await ls.SetItem(this.LocalStoragePrefix + _a.localStorageAllMetadataKey, JSON.stringify(this._localMetadata));
1876
+ await ls.SetItem(this.LocalStoragePrefix + ProviderBase.localStorageAllMetadataKey, JSON.stringify(this._localMetadata));
1744
1877
  }
1745
1878
  }
1746
1879
  catch (e) {
1747
1880
  // some enviroments don't support local storage
1748
- (0, logging_1.LogError)(e);
1881
+ LogError(e);
1749
1882
  }
1750
1883
  }
1751
1884
  /**
@@ -1755,24 +1888,14 @@ class ProviderBase {
1755
1888
  async RemoveLocalMetadataFromStorage() {
1756
1889
  try {
1757
1890
  const ls = this.LocalStorageProvider;
1758
- for (let i = 0; i < _a.localStorageKeys.length; i++) {
1759
- await ls.Remove(this.LocalStoragePrefix + _a.localStorageKeys[i]);
1891
+ for (let i = 0; i < ProviderBase.localStorageKeys.length; i++) {
1892
+ await ls.Remove(this.LocalStoragePrefix + ProviderBase.localStorageKeys[i]);
1760
1893
  }
1761
1894
  }
1762
1895
  catch (e) {
1763
1896
  // some enviroments don't support local storage
1764
- (0, logging_1.LogError)(e);
1897
+ LogError(e);
1765
1898
  }
1766
1899
  }
1767
1900
  }
1768
- exports.ProviderBase = ProviderBase;
1769
- _a = ProviderBase;
1770
- ProviderBase._mjMetadataDatasetName = 'MJ_Metadata';
1771
- ProviderBase.localStorageRootKey = '___MJCore_Metadata';
1772
- ProviderBase.localStorageTimestampsKey = _a.localStorageRootKey + '_Timestamps';
1773
- ProviderBase.localStorageAllMetadataKey = _a.localStorageRootKey + '_AllMetadata';
1774
- ProviderBase.localStorageKeys = [
1775
- _a.localStorageTimestampsKey,
1776
- _a.localStorageAllMetadataKey,
1777
- ];
1778
1901
  //# sourceMappingURL=providerBase.js.map