@memberjunction/core-entities 5.38.0 → 5.40.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.
@@ -0,0 +1,407 @@
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, RegisterForStartup, } from '@memberjunction/core';
8
+ import { UUIDsEqual } from '@memberjunction/global';
9
+ /**
10
+ * Internal key used to identify a pending debounced write. Combines the optional
11
+ * applicationId scope with the setting name so that GLOBAL and app-scoped writes
12
+ * for the same name don't collide in the pending map.
13
+ */
14
+ function pendingKey(name, applicationId) {
15
+ return `${applicationId ?? ''}::${name}`;
16
+ }
17
+ /**
18
+ * ApplicationSettingEngine is a singleton engine that provides centralized, cached access to
19
+ * application configuration settings stored in the `MJ: Application Settings` entity
20
+ * (table `ApplicationSetting`).
21
+ *
22
+ * Each setting row has an optional `ApplicationID`:
23
+ * - **NULL** → a GLOBAL setting that applies across all applications.
24
+ * - **non-NULL** → a setting scoped to that single application.
25
+ *
26
+ * **Resolution semantics**: when reading a setting for a given application, an app-scoped row
27
+ * (matching applicationId + name) takes precedence over the GLOBAL row (ApplicationID NULL) of
28
+ * the same name. If neither exists, the read returns `undefined`.
29
+ *
30
+ * This engine mirrors {@link UserInfoEngine}: it loads all setting rows into an in-memory cache
31
+ * via a BaseEnginePropertyConfig (which auto-subscribes to BaseEntity events for reactivity),
32
+ * exposes a reactive observable, and supports debounced writes with read-after-write semantics.
33
+ *
34
+ * Usage:
35
+ * ```typescript
36
+ * const engine = ApplicationSettingEngine.Instance;
37
+ * await engine.Config(false, contextUser);
38
+ *
39
+ * // Read a setting (app-scoped first, then GLOBAL fallback)
40
+ * const raw = engine.GetSetting('feature.flag', applicationId);
41
+ *
42
+ * // Write a GLOBAL setting
43
+ * await engine.SetSetting('feature.flag', 'true');
44
+ *
45
+ * // Write an app-scoped setting
46
+ * await engine.SetSetting('feature.flag', 'false', applicationId);
47
+ * ```
48
+ */
49
+ let ApplicationSettingEngine = class ApplicationSettingEngine extends BaseEngine {
50
+ constructor() {
51
+ super(...arguments);
52
+ // Private storage for the application setting cache (all rows, global + app-scoped)
53
+ this._ApplicationSettings = [];
54
+ // ========================================================================
55
+ // DEBOUNCED SETTINGS SUPPORT
56
+ // ========================================================================
57
+ /**
58
+ * Debounce time in milliseconds for SetSettingDebounced calls.
59
+ * Default is 500ms. Change via the SettingsDebounceMs setter.
60
+ */
61
+ this._settingsDebounceMs = 500;
62
+ /**
63
+ * Map of pending setting updates keyed by `${applicationId}::${name}`.
64
+ * These are queued and flushed after the debounce period of inactivity.
65
+ */
66
+ this._pendingSettings = new Map();
67
+ /**
68
+ * Timer handle for the debounce flush.
69
+ */
70
+ this._settingsDebounceTimer = null;
71
+ /**
72
+ * Promise that resolves when the current flush operation completes.
73
+ * Used to prevent concurrent flush operations.
74
+ */
75
+ this._flushPromise = null;
76
+ }
77
+ /**
78
+ * Returns the global instance of the class. This is a singleton class, so there is only one
79
+ * instance of it in the application. Do not directly create new instances of it, always use
80
+ * this method to get the instance.
81
+ */
82
+ static get Instance() {
83
+ return super.getInstance();
84
+ }
85
+ /**
86
+ * Configures the engine by loading all application settings from the database into the
87
+ * in-memory cache. Application settings are global reference data (not per-user), so all rows
88
+ * are loaded regardless of provider type.
89
+ *
90
+ * @param forceRefresh - If true, forces a refresh from the server even if data is cached
91
+ * @param contextUser - The user context (required for server-side)
92
+ * @param provider - Optional custom metadata provider
93
+ */
94
+ async Config(forceRefresh, contextUser, provider) {
95
+ const configs = [
96
+ {
97
+ Type: 'entity',
98
+ EntityName: 'MJ: Application Settings',
99
+ PropertyName: '_ApplicationSettings',
100
+ CacheLocal: true,
101
+ // Global reference data — no user filter
102
+ },
103
+ ];
104
+ await super.Load(configs, provider, forceRefresh, contextUser);
105
+ }
106
+ // ========================================================================
107
+ // OBSERVABLE ACCESSORS
108
+ // ========================================================================
109
+ /**
110
+ * Observable stream of the application settings cache array. Emits the current array on
111
+ * subscribe and re-emits whenever the cache is mutated (save, delete, remote-invalidate,
112
+ * refresh).
113
+ */
114
+ get ApplicationSettings$() {
115
+ return this.ObserveProperty('_ApplicationSettings');
116
+ }
117
+ // ========================================================================
118
+ // PUBLIC ACCESSORS
119
+ // ========================================================================
120
+ /**
121
+ * Get all application settings in the cache (global + app-scoped, unfiltered).
122
+ */
123
+ get ApplicationSettings() {
124
+ return this._ApplicationSettings || [];
125
+ }
126
+ /**
127
+ * Get all settings for a specific application, OR all GLOBAL settings when no applicationId
128
+ * is supplied.
129
+ *
130
+ * @param applicationId - The application ID to filter by; omit/undefined for GLOBAL settings
131
+ * @returns The matching settings (does NOT merge global fallbacks into the app-scoped list)
132
+ */
133
+ GetAllForApplication(applicationId) {
134
+ if (applicationId) {
135
+ return this.ApplicationSettings.filter((s) => s.ApplicationID != null && UUIDsEqual(s.ApplicationID, applicationId));
136
+ }
137
+ return this.ApplicationSettings.filter((s) => s.ApplicationID == null);
138
+ }
139
+ /**
140
+ * Get an application setting value by name with scope resolution.
141
+ *
142
+ * **Resolution**: if `applicationId` is given and an app-scoped row exists for
143
+ * (applicationId, name), its value is returned. Otherwise the GLOBAL row (ApplicationID NULL)
144
+ * for that name is used as a fallback. Returns `undefined` if neither exists.
145
+ *
146
+ * **Read-after-write semantics**: this consults the in-memory pending-debounced-writes map
147
+ * FIRST (app-scoped pending takes precedence over global pending, mirroring the persisted
148
+ * resolution order). Without that, a `SetSettingDebounced` followed immediately by
149
+ * `GetSetting` would return the old DB-cached value because the debounce timer hasn't fired
150
+ * yet and the entity hasn't been saved.
151
+ *
152
+ * @param name - The setting name to find
153
+ * @param applicationId - Optional application scope; when given, app-scoped overrides global
154
+ * @returns The setting value string, or undefined if not found
155
+ */
156
+ GetSetting(name, applicationId) {
157
+ // 1) Pending app-scoped write (read-after-write)
158
+ if (applicationId) {
159
+ const pendingApp = this._pendingSettings.get(pendingKey(name, applicationId));
160
+ if (pendingApp !== undefined)
161
+ return pendingApp.value;
162
+ }
163
+ // 2) Persisted app-scoped row
164
+ if (applicationId) {
165
+ const appRow = this.findEntity(name, applicationId);
166
+ if (appRow)
167
+ return appRow.Value;
168
+ }
169
+ // 3) Pending GLOBAL write (read-after-write)
170
+ const pendingGlobal = this._pendingSettings.get(pendingKey(name, undefined));
171
+ if (pendingGlobal !== undefined)
172
+ return pendingGlobal.value;
173
+ // 4) Persisted GLOBAL row (fallback)
174
+ const globalRow = this.findEntity(name, undefined);
175
+ return globalRow?.Value ?? undefined;
176
+ }
177
+ /**
178
+ * Get an application setting entity by name with the same scope resolution as
179
+ * {@link GetSetting} (app-scoped first, then GLOBAL fallback). Does NOT consult pending
180
+ * debounced writes — returns the persisted entity instance.
181
+ *
182
+ * @param name - The setting name to find
183
+ * @param applicationId - Optional application scope
184
+ * @returns The MJApplicationSettingEntity, or undefined if not found
185
+ */
186
+ GetSettingEntity(name, applicationId) {
187
+ if (applicationId) {
188
+ const appRow = this.findEntity(name, applicationId);
189
+ if (appRow)
190
+ return appRow;
191
+ }
192
+ return this.findEntity(name, undefined);
193
+ }
194
+ /**
195
+ * Internal: find the cache row that exactly matches (name, scope) WITHOUT fallback.
196
+ * A null/undefined applicationId matches only GLOBAL rows; a non-null applicationId matches
197
+ * only the app-scoped row for that application.
198
+ */
199
+ findEntity(name, applicationId) {
200
+ return this.ApplicationSettings.find((s) => {
201
+ if (s.Name !== name)
202
+ return false;
203
+ if (applicationId) {
204
+ return s.ApplicationID != null && UUIDsEqual(s.ApplicationID, applicationId);
205
+ }
206
+ return s.ApplicationID == null;
207
+ });
208
+ }
209
+ /**
210
+ * Set an application setting by name. Creates a new setting if one doesn't exist for the
211
+ * exact (name, scope) pair; updates it otherwise. When `applicationId` is omitted the setting
212
+ * is written as a GLOBAL setting (ApplicationID NULL).
213
+ *
214
+ * @param name - The setting name
215
+ * @param value - The setting value (string, typically JSON for complex data)
216
+ * @param applicationId - Optional application scope; omit for a GLOBAL setting
217
+ * @param contextUser - Optional user context for server-side use
218
+ * @returns true if successful, false otherwise
219
+ */
220
+ async SetSetting(name, value, applicationId, contextUser) {
221
+ const md = this.ProviderToUse;
222
+ try {
223
+ // Look up the exact (name, scope) row — NOT the resolved fallback, so writing an
224
+ // app-scoped value never accidentally mutates the GLOBAL row.
225
+ let setting = this.findEntity(name, applicationId);
226
+ if (setting) {
227
+ setting.Value = value;
228
+ }
229
+ else {
230
+ setting = await md.GetEntityObject('MJ: Application Settings', contextUser);
231
+ setting.NewRecord();
232
+ setting.ApplicationID = applicationId ?? null;
233
+ setting.Name = name;
234
+ setting.Value = value;
235
+ }
236
+ const saved = await setting.Save();
237
+ if (saved) {
238
+ if (!this._ApplicationSettings.some((s) => UUIDsEqual(s.ID, setting.ID))) {
239
+ this._ApplicationSettings.push(setting);
240
+ }
241
+ return true;
242
+ }
243
+ else {
244
+ console.error('ApplicationSettingEngine.SetSetting: Failed to save:', setting.LatestResult?.CompleteMessage);
245
+ return false;
246
+ }
247
+ }
248
+ catch (error) {
249
+ console.error('ApplicationSettingEngine.SetSetting: Error:', error instanceof Error ? error.message : String(error));
250
+ return false;
251
+ }
252
+ }
253
+ /**
254
+ * Delete an application setting by name and scope.
255
+ *
256
+ * @param name - The setting name to delete
257
+ * @param applicationId - Optional application scope; omit to delete the GLOBAL setting
258
+ * @returns true if successful (or setting didn't exist), false on error
259
+ */
260
+ async DeleteSetting(name, applicationId) {
261
+ const setting = this.findEntity(name, applicationId);
262
+ if (!setting) {
263
+ // Setting doesn't exist, consider it a success
264
+ return true;
265
+ }
266
+ try {
267
+ const deleted = await setting.Delete();
268
+ if (deleted) {
269
+ const index = this._ApplicationSettings.findIndex((s) => UUIDsEqual(s.ID, setting.ID));
270
+ if (index >= 0) {
271
+ this._ApplicationSettings.splice(index, 1);
272
+ }
273
+ return true;
274
+ }
275
+ else {
276
+ console.error('ApplicationSettingEngine.DeleteSetting: Failed to delete:', setting.LatestResult?.CompleteMessage);
277
+ return false;
278
+ }
279
+ }
280
+ catch (error) {
281
+ console.error('ApplicationSettingEngine.DeleteSetting: Error:', error instanceof Error ? error.message : String(error));
282
+ return false;
283
+ }
284
+ }
285
+ // ========================================================================
286
+ // DEBOUNCED SETTINGS METHODS
287
+ // ========================================================================
288
+ /**
289
+ * Get the current debounce time in milliseconds for SetSettingDebounced calls.
290
+ */
291
+ get SettingsDebounceMs() {
292
+ return this._settingsDebounceMs;
293
+ }
294
+ /**
295
+ * Set the debounce time in milliseconds for SetSettingDebounced calls.
296
+ * When changed, any pending settings are flushed first before the new debounce time takes effect.
297
+ * @param value - The debounce time in milliseconds (minimum 100ms, maximum 10000ms)
298
+ */
299
+ set SettingsDebounceMs(value) {
300
+ const clampedValue = Math.max(100, Math.min(10000, value));
301
+ if (clampedValue !== this._settingsDebounceMs) {
302
+ this.FlushPendingSettings();
303
+ this._settingsDebounceMs = clampedValue;
304
+ }
305
+ }
306
+ /**
307
+ * Queue a setting update with debouncing. Multiple calls within the debounce period for the
308
+ * same (name, scope) pair are batched together, with only the last value being saved. The
309
+ * actual database save occurs after the debounce period of inactivity.
310
+ *
311
+ * This is the preferred method for UI components that may update settings frequently.
312
+ *
313
+ * @param name - The setting name
314
+ * @param value - The setting value (string, typically JSON for complex data)
315
+ * @param applicationId - Optional application scope; omit for a GLOBAL setting
316
+ * @param contextUser - Optional user context for server-side use
317
+ */
318
+ SetSettingDebounced(name, value, applicationId, contextUser) {
319
+ this._pendingSettings.set(pendingKey(name, applicationId), {
320
+ name,
321
+ value,
322
+ applicationId,
323
+ contextUser,
324
+ timestamp: Date.now(),
325
+ });
326
+ if (this._settingsDebounceTimer) {
327
+ clearTimeout(this._settingsDebounceTimer);
328
+ }
329
+ this._settingsDebounceTimer = setTimeout(() => {
330
+ this.FlushPendingSettings();
331
+ }, this._settingsDebounceMs);
332
+ }
333
+ /**
334
+ * Immediately flush all pending debounced settings to the database.
335
+ * Call this when you need to ensure settings are saved (e.g., before navigation).
336
+ * Safe to call multiple times - concurrent calls will wait for the current flush to complete.
337
+ *
338
+ * @returns Promise that resolves when all pending settings have been saved
339
+ */
340
+ async FlushPendingSettings() {
341
+ if (this._settingsDebounceTimer) {
342
+ clearTimeout(this._settingsDebounceTimer);
343
+ this._settingsDebounceTimer = null;
344
+ }
345
+ if (this._pendingSettings.size === 0) {
346
+ return;
347
+ }
348
+ if (this._flushPromise) {
349
+ await this._flushPromise;
350
+ if (this._pendingSettings.size > 0) {
351
+ return this.FlushPendingSettings();
352
+ }
353
+ return;
354
+ }
355
+ const settingsToSave = new Map(this._pendingSettings);
356
+ this._pendingSettings.clear();
357
+ this._flushPromise = this.doFlushSettings(settingsToSave);
358
+ try {
359
+ await this._flushPromise;
360
+ }
361
+ finally {
362
+ this._flushPromise = null;
363
+ }
364
+ }
365
+ /**
366
+ * Internal method to perform the actual flush of settings.
367
+ * @param settingsToSave - Map of settings to save
368
+ */
369
+ async doFlushSettings(settingsToSave) {
370
+ const savePromises = [];
371
+ for (const { name, value, applicationId, contextUser } of settingsToSave.values()) {
372
+ savePromises.push(this.SetSetting(name, value, applicationId, contextUser));
373
+ }
374
+ const results = await Promise.all(savePromises);
375
+ const failedCount = results.filter((r) => !r).length;
376
+ if (failedCount > 0) {
377
+ console.warn(`ApplicationSettingEngine.FlushPendingSettings: ${failedCount} of ${results.length} settings failed to save`);
378
+ }
379
+ }
380
+ /**
381
+ * Check if there are any pending debounced settings waiting to be saved.
382
+ */
383
+ get HasPendingSettings() {
384
+ return this._pendingSettings.size > 0;
385
+ }
386
+ /**
387
+ * Get the number of pending debounced settings.
388
+ */
389
+ get PendingSettingsCount() {
390
+ return this._pendingSettings.size;
391
+ }
392
+ // ========================================================================
393
+ // UTILITY METHODS
394
+ // ========================================================================
395
+ /**
396
+ * Force refresh all application setting data.
397
+ * @param contextUser - Optional user context for server-side use
398
+ */
399
+ async Refresh(contextUser) {
400
+ await this.Config(true, contextUser);
401
+ }
402
+ };
403
+ ApplicationSettingEngine = __decorate([
404
+ RegisterForStartup()
405
+ ], ApplicationSettingEngine);
406
+ export { ApplicationSettingEngine };
407
+ //# sourceMappingURL=ApplicationSettingEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApplicationSettingEngine.js","sourceRoot":"","sources":["../../src/engines/ApplicationSettingEngine.ts"],"names":[],"mappings":"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"}