@memberjunction/core-entities 6.2.0-edge.2 → 6.2.0-edge.3
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/.tsbuildinfo +1 -1
- package/dist/custom/FormScope/FormContributionClaims.d.ts +20 -0
- package/dist/custom/FormScope/FormContributionClaims.d.ts.map +1 -0
- package/dist/custom/FormScope/FormContributionClaims.js +33 -0
- package/dist/custom/FormScope/FormContributionClaims.js.map +1 -0
- package/dist/custom/FormScope/FormContributionLifecycle.d.ts +43 -0
- package/dist/custom/FormScope/FormContributionLifecycle.d.ts.map +1 -0
- package/dist/custom/FormScope/FormContributionLifecycle.js +47 -0
- package/dist/custom/FormScope/FormContributionLifecycle.js.map +1 -0
- package/dist/custom/FormScope/FormContributionRow.d.ts +40 -0
- package/dist/custom/FormScope/FormContributionRow.d.ts.map +1 -0
- package/dist/custom/FormScope/FormContributionRow.js +84 -0
- package/dist/custom/FormScope/FormContributionRow.js.map +1 -0
- package/dist/custom/FormScope/FormPanelHides.d.ts +14 -0
- package/dist/custom/FormScope/FormPanelHides.d.ts.map +1 -0
- package/dist/custom/FormScope/FormPanelHides.js +32 -0
- package/dist/custom/FormScope/FormPanelHides.js.map +1 -0
- package/dist/custom/FormScope/FormScopeRules.d.ts +220 -0
- package/dist/custom/FormScope/FormScopeRules.d.ts.map +1 -0
- package/dist/custom/FormScope/FormScopeRules.js +295 -0
- package/dist/custom/FormScope/FormScopeRules.js.map +1 -0
- package/dist/engines/IdentityClaimEngine.d.ts +15 -2
- package/dist/engines/IdentityClaimEngine.d.ts.map +1 -1
- package/dist/engines/IdentityClaimEngine.js.map +1 -1
- package/dist/engines/QueryEngine.d.ts.map +1 -1
- package/dist/engines/QueryEngine.js +2 -1
- package/dist/engines/QueryEngine.js.map +1 -1
- package/dist/engines/component-metadata.d.ts +3 -1
- package/dist/engines/component-metadata.d.ts.map +1 -1
- package/dist/engines/component-metadata.js +12 -5
- package/dist/engines/component-metadata.js.map +1 -1
- package/dist/engines/interactive-forms.d.ts +128 -9
- package/dist/engines/interactive-forms.d.ts.map +1 -1
- package/dist/engines/interactive-forms.js +268 -14
- package/dist/engines/interactive-forms.js.map +1 -1
- package/dist/generated/entities/__mj.d.ts +4308 -203
- package/dist/generated/entities/__mj.d.ts.map +1 -1
- package/dist/generated/entities/__mj.js +11370 -5862
- package/dist/generated/entities/__mj.js.map +1 -1
- package/dist/generated/remote_operations.d.ts +262 -0
- package/dist/generated/remote_operations.d.ts.map +1 -1
- package/dist/generated/remote_operations.js +126 -0
- package/dist/generated/remote_operations.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { BaseEngine, IMetadataProvider, UserInfo } from "@memberjunction/core";
|
|
1
|
+
import { BaseEngine, IMetadataProvider, UserInfo, type BaseEntityEvent } from "@memberjunction/core";
|
|
2
2
|
import type { Observable } from "rxjs";
|
|
3
|
-
import type { MJComponentEntity, MJEntityFormOverrideEntity } from "../generated/entity_subclasses.js";
|
|
3
|
+
import type { MJComponentEntity, MJEntityFormContributionEntity, MJEntityFormOverrideEntity } from "../generated/entity_subclasses.js";
|
|
4
|
+
import type { InstanceConfigEngine } from "./InstanceConfigEngine.js";
|
|
4
5
|
/**
|
|
5
6
|
* Cache of MemberJunction interactive-form metadata: the form-role
|
|
6
7
|
* `MJ: Components` rows and their `MJ: Entity Form Overrides`. Designed
|
|
@@ -24,12 +25,22 @@ import type { MJComponentEntity, MJEntityFormOverrideEntity } from "../generated
|
|
|
24
25
|
* because the full Component table includes ~150MB of `Specification`
|
|
25
26
|
* JSON across non-form types (Skip artifacts, dashboards, etc.).
|
|
26
27
|
*
|
|
27
|
-
* This engine threads the needle:
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* This engine threads the needle: it loads `Type='Form'` Components (small
|
|
29
|
+
* dataset — a few dozen per typical deployment, ~5MB max), the
|
|
30
|
+
* `EntityFormOverride` rows (tiny) and, unless metadata contributions are
|
|
31
|
+
* switched off, the `MJ: Entity Form Contributions` rows. In the browser it
|
|
32
|
+
* loads the shared overrides and contributions and the signed-in user's own;
|
|
33
|
+
* on a server it loads every row. Specification is included because
|
|
34
|
+
* the cockpit + Skip rendering both need it. Loaded as `entity_object` so
|
|
35
|
+
* callers can call `.Save()` / `.Delete()` on the cached instances directly.
|
|
36
|
+
*
|
|
37
|
+
* It deliberately does NOT load `Type='Widget'` rows: `Widget` is an open set
|
|
38
|
+
* grown by registry sync and general authoring, unrelated to form-panel
|
|
39
|
+
* adoption, and this cache is written to client local storage on every boot.
|
|
40
|
+
* The widget a contribution renders is fetched by ID on first use
|
|
41
|
+
* ({@link InteractiveFormsEngine.GetComponentByID}) and kept in memory until any
|
|
42
|
+
* `MJ: Components` row is saved, deleted or changed on another server, so each
|
|
43
|
+
* distinct panel component costs one query, not one per mount.
|
|
33
44
|
*
|
|
34
45
|
* ## Reactivity for free
|
|
35
46
|
*
|
|
@@ -73,13 +84,57 @@ import type { MJComponentEntity, MJEntityFormOverrideEntity } from "../generated
|
|
|
73
84
|
export declare class InteractiveFormsEngine extends BaseEngine<InteractiveFormsEngine> {
|
|
74
85
|
/** Standard singleton accessor — never construct directly. */
|
|
75
86
|
static get Instance(): InteractiveFormsEngine;
|
|
87
|
+
/**
|
|
88
|
+
* Instance-level kill switch for metadata-registered form contributions.
|
|
89
|
+
*
|
|
90
|
+
* When false the engine loads no contribution rows and keeps the Components filter
|
|
91
|
+
* narrow, so every consumer sees exactly the pre-feature behavior: compiled
|
|
92
|
+
* `BaseFormPanel` registrations only. This is the rollback path for a bad load or a
|
|
93
|
+
* misbehaving panel — no migration, no deployment of a code change.
|
|
94
|
+
*
|
|
95
|
+
* Seeded from `MJ_FORMS_METADATA_CONTRIBUTIONS=false` where an environment exists
|
|
96
|
+
* (server, CLI). The browser has no environment: the Explorer shell calls
|
|
97
|
+
* {@link ApplyInstanceConfiguration} after Instance Config loads and before any form opens, and
|
|
98
|
+
* another browser host can do the same or set this directly before the first `Config()`.
|
|
99
|
+
*/
|
|
100
|
+
private static _metadataContributionsEnabled;
|
|
101
|
+
/** The `MJ: Instance Configurations` key that turns metadata contributions off in the browser. */
|
|
102
|
+
static readonly MetadataContributionsConfigKey = "Forms.MetadataContributions.Enabled";
|
|
103
|
+
static get MetadataContributionsEnabled(): boolean;
|
|
104
|
+
static set MetadataContributionsEnabled(value: boolean);
|
|
105
|
+
/**
|
|
106
|
+
* Turns metadata contributions off when the instance configuration
|
|
107
|
+
* ({@link MetadataContributionsConfigKey}) is `false`. A missing key leaves the switch as it is,
|
|
108
|
+
* and a `true` never turns back on a switch that is already off.
|
|
109
|
+
*
|
|
110
|
+
* Call it after `InstanceConfigEngine.Config()` has finished and before the first form opens.
|
|
111
|
+
* Before Instance Config has loaded, or when it fails to load, the key reads as missing and
|
|
112
|
+
* the switch stays on.
|
|
113
|
+
*/
|
|
114
|
+
static ApplyInstanceConfiguration(config: Pick<InstanceConfigEngine, 'GetBoolean'>): void;
|
|
115
|
+
private static readContributionsFlag;
|
|
76
116
|
private _forms;
|
|
77
117
|
private _overrides;
|
|
118
|
+
private _contributions;
|
|
119
|
+
/** Components fetched by {@link GetComponentByID}, by normalized ID. */
|
|
120
|
+
private _componentsByID;
|
|
121
|
+
/** Lookups in flight, by normalized ID, so panels that mount together share one query. */
|
|
122
|
+
private _componentLookups;
|
|
123
|
+
private _componentInvalidationSubscribed;
|
|
78
124
|
/**
|
|
79
125
|
* Lazy-load the form Component + override caches. Safe to call from
|
|
80
126
|
* every entry point — no-op if already loaded (unless `forceRefresh`).
|
|
81
127
|
*/
|
|
82
128
|
Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* The filter for the override and contribution loads: in the browser, every shared row plus
|
|
131
|
+
* the signed-in user's own personal rows; on a server, none.
|
|
132
|
+
*
|
|
133
|
+
* A browser cache holds one user's view, so other users' personal rows (with their Notes and
|
|
134
|
+
* Configuration) stay on the server. A server cache is shared by every user of the process,
|
|
135
|
+
* so it holds every row and each reader filters what it serves.
|
|
136
|
+
*/
|
|
137
|
+
private static personalRowsLoadFilter;
|
|
83
138
|
/** All cached form-role Components. */
|
|
84
139
|
get Forms(): MJComponentEntity[];
|
|
85
140
|
/** All cached EntityFormOverride rows (all scopes — caller filters). */
|
|
@@ -106,12 +161,76 @@ export declare class InteractiveFormsEngine extends BaseEngine<InteractiveFormsE
|
|
|
106
161
|
* the resolver-style lookup that considers all scopes.
|
|
107
162
|
*/
|
|
108
163
|
GetUserOverrides(userID: string): MJEntityFormOverrideEntity[];
|
|
164
|
+
/**
|
|
165
|
+
* All cached EntityFormContribution rows (all scopes, all statuses — callers filter).
|
|
166
|
+
*
|
|
167
|
+
* Returns nothing while the kill switch is off. Dropping the entity from the load list is
|
|
168
|
+
* not enough on its own: a process that already loaded rows would keep serving them from
|
|
169
|
+
* the engine's data map, so the switch would appear to do nothing until a restart. The
|
|
170
|
+
* rollback path has to work in the process that is misbehaving.
|
|
171
|
+
*/
|
|
172
|
+
get Contributions(): MJEntityFormContributionEntity[];
|
|
173
|
+
/** Emits on every save / delete / remote-invalidate that touches `MJ: Entity Form Contributions`. */
|
|
174
|
+
get Contributions$(): Observable<MJEntityFormContributionEntity[]>;
|
|
175
|
+
/**
|
|
176
|
+
* True once the contribution cache has completed its first load.
|
|
177
|
+
*
|
|
178
|
+
* Slot hosts wait on this before the first mount: rendering compiled contributions and
|
|
179
|
+
* then adding rows a tick later is visible, and for a `bare` hero that replaces a baked
|
|
180
|
+
* section it means the user watches the Details panel render and then disappear.
|
|
181
|
+
*/
|
|
182
|
+
get ContributionsReady(): boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Active contribution rows that apply to (entity, user, roles): User rows for this
|
|
185
|
+
* user, Role rows for any of the user's roles, and Global rows. Sorted by
|
|
186
|
+
* `Precedence` DESC then `SortKey` DESC. Last-wins collapse against compiled
|
|
187
|
+
* registrations happens in ng-base-forms, not here.
|
|
188
|
+
*
|
|
189
|
+
* On an identity or permission entity only the user's own rows apply
|
|
190
|
+
* ({@link FormScopeAllowedOnEntity}). The clamp is applied here, on the read path, because
|
|
191
|
+
* `mj sync` — the path an OpenApp actually uses — and direct SQL bypass the actions.
|
|
192
|
+
*/
|
|
193
|
+
GetApplicableContributions(entityID: string, userID: string, roleIDs: ReadonlyArray<string>): MJEntityFormContributionEntity[];
|
|
194
|
+
/**
|
|
195
|
+
* A form from the loaded forms, or a widget {@link GetComponentByID} has already fetched.
|
|
196
|
+
* Undefined for a widget not fetched yet.
|
|
197
|
+
*/
|
|
198
|
+
FindComponentByID(id: string): MJComponentEntity | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Any Component by ID: a whole form from the loaded forms, otherwise one query by ID, kept in
|
|
201
|
+
* memory for the next caller. Panels that ask at the same time share one query. A failed or
|
|
202
|
+
* empty lookup is not kept, so the next caller tries again. Every kept component is dropped
|
|
203
|
+
* when any `MJ: Components` row is saved, deleted or changed on another server.
|
|
204
|
+
*
|
|
205
|
+
* @returns The component, or null when it does not exist or the lookup failed.
|
|
206
|
+
*/
|
|
207
|
+
GetComponentByID(id: string, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<MJComponentEntity | null>;
|
|
208
|
+
/** Drops every component {@link GetComponentByID} kept. */
|
|
209
|
+
ClearComponentCache(): void;
|
|
210
|
+
private queryComponentByID;
|
|
211
|
+
/**
|
|
212
|
+
* A save of any `MJ: Components` row, and a change to one on another server, refreshes the
|
|
213
|
+
* forms array (a widget is not in it, so the save is not applied in place), and that emission
|
|
214
|
+
* drops what {@link GetComponentByID} kept. A delete of a row outside the array changes no
|
|
215
|
+
* array; {@link HandleIndividualBaseEntityEvent} covers it. Subscribed before anything is
|
|
216
|
+
* kept, so the replay on subscribe clears nothing.
|
|
217
|
+
*/
|
|
218
|
+
private subscribeComponentInvalidation;
|
|
219
|
+
/**
|
|
220
|
+
* Drops what {@link GetComponentByID} kept when an `MJ: Components` row is deleted, here or on
|
|
221
|
+
* another server, then handles the event as every engine does. BaseEngine ignores a delete of a
|
|
222
|
+
* row that is not in a loaded array, which a fetched widget never is.
|
|
223
|
+
*/
|
|
224
|
+
protected HandleIndividualBaseEntityEvent(event: BaseEntityEvent): Promise<boolean>;
|
|
225
|
+
private static isComponentDelete;
|
|
109
226
|
/**
|
|
110
227
|
* Resolver-style lookup matching the runtime form-resolver's scope
|
|
111
228
|
* priority: User > Role > Global. Returns the highest-priority
|
|
112
229
|
* Active override for the given (entity, user, roles) tuple, or null
|
|
113
230
|
* if none match. Within the same scope, lower `Priority` wins (the
|
|
114
|
-
* resolver convention — Priority is sort key, not boost).
|
|
231
|
+
* resolver convention — Priority is sort key, not boost). On an identity
|
|
232
|
+
* or permission entity only the user's own forms count
|
|
233
|
+
* ({@link FormScopeAllowedOnEntity}).
|
|
115
234
|
*
|
|
116
235
|
* @param entityID The target `MJ: Entities.ID`.
|
|
117
236
|
* @param userID The current user's `MJ: Users.ID`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-forms.d.ts","sourceRoot":"","sources":["../../src/engines/interactive-forms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"interactive-forms.d.ts","sourceRoot":"","sources":["../../src/engines/interactive-forms.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { BaseEngine } from "@memberjunction/core";
|
|
2
|
-
import { NormalizeUUID, UUIDsEqual } from "@memberjunction/global";
|
|
1
|
+
import { BaseEngine, LogError, ProviderType, RunView } from "@memberjunction/core";
|
|
2
|
+
import { EscapeSQLString, NormalizeUUID, UUIDsEqual } from "@memberjunction/global";
|
|
3
|
+
import { FormScopeAllowedOnEntity } from "../custom/FormScope/FormScopeRules.js";
|
|
3
4
|
/**
|
|
4
5
|
* Cache of MemberJunction interactive-form metadata: the form-role
|
|
5
6
|
* `MJ: Components` rows and their `MJ: Entity Form Overrides`. Designed
|
|
@@ -23,12 +24,22 @@ import { NormalizeUUID, UUIDsEqual } from "@memberjunction/global";
|
|
|
23
24
|
* because the full Component table includes ~150MB of `Specification`
|
|
24
25
|
* JSON across non-form types (Skip artifacts, dashboards, etc.).
|
|
25
26
|
*
|
|
26
|
-
* This engine threads the needle:
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* This engine threads the needle: it loads `Type='Form'` Components (small
|
|
28
|
+
* dataset — a few dozen per typical deployment, ~5MB max), the
|
|
29
|
+
* `EntityFormOverride` rows (tiny) and, unless metadata contributions are
|
|
30
|
+
* switched off, the `MJ: Entity Form Contributions` rows. In the browser it
|
|
31
|
+
* loads the shared overrides and contributions and the signed-in user's own;
|
|
32
|
+
* on a server it loads every row. Specification is included because
|
|
33
|
+
* the cockpit + Skip rendering both need it. Loaded as `entity_object` so
|
|
34
|
+
* callers can call `.Save()` / `.Delete()` on the cached instances directly.
|
|
35
|
+
*
|
|
36
|
+
* It deliberately does NOT load `Type='Widget'` rows: `Widget` is an open set
|
|
37
|
+
* grown by registry sync and general authoring, unrelated to form-panel
|
|
38
|
+
* adoption, and this cache is written to client local storage on every boot.
|
|
39
|
+
* The widget a contribution renders is fetched by ID on first use
|
|
40
|
+
* ({@link InteractiveFormsEngine.GetComponentByID}) and kept in memory until any
|
|
41
|
+
* `MJ: Components` row is saved, deleted or changed on another server, so each
|
|
42
|
+
* distinct panel component costs one query, not one per mount.
|
|
32
43
|
*
|
|
33
44
|
* ## Reactivity for free
|
|
34
45
|
*
|
|
@@ -74,33 +85,124 @@ export class InteractiveFormsEngine extends BaseEngine {
|
|
|
74
85
|
super(...arguments);
|
|
75
86
|
this._forms = [];
|
|
76
87
|
this._overrides = [];
|
|
88
|
+
this._contributions = [];
|
|
89
|
+
/** Components fetched by {@link GetComponentByID}, by normalized ID. */
|
|
90
|
+
this._componentsByID = new Map();
|
|
91
|
+
/** Lookups in flight, by normalized ID, so panels that mount together share one query. */
|
|
92
|
+
this._componentLookups = new Map();
|
|
93
|
+
this._componentInvalidationSubscribed = false;
|
|
77
94
|
}
|
|
78
95
|
/** Standard singleton accessor — never construct directly. */
|
|
79
96
|
static get Instance() {
|
|
80
97
|
return super.getInstance();
|
|
81
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Instance-level kill switch for metadata-registered form contributions.
|
|
101
|
+
*
|
|
102
|
+
* When false the engine loads no contribution rows and keeps the Components filter
|
|
103
|
+
* narrow, so every consumer sees exactly the pre-feature behavior: compiled
|
|
104
|
+
* `BaseFormPanel` registrations only. This is the rollback path for a bad load or a
|
|
105
|
+
* misbehaving panel — no migration, no deployment of a code change.
|
|
106
|
+
*
|
|
107
|
+
* Seeded from `MJ_FORMS_METADATA_CONTRIBUTIONS=false` where an environment exists
|
|
108
|
+
* (server, CLI). The browser has no environment: the Explorer shell calls
|
|
109
|
+
* {@link ApplyInstanceConfiguration} after Instance Config loads and before any form opens, and
|
|
110
|
+
* another browser host can do the same or set this directly before the first `Config()`.
|
|
111
|
+
*/
|
|
112
|
+
static { this._metadataContributionsEnabled = InteractiveFormsEngine.readContributionsFlag(); }
|
|
113
|
+
/** The `MJ: Instance Configurations` key that turns metadata contributions off in the browser. */
|
|
114
|
+
static { this.MetadataContributionsConfigKey = 'Forms.MetadataContributions.Enabled'; }
|
|
115
|
+
static get MetadataContributionsEnabled() {
|
|
116
|
+
return InteractiveFormsEngine._metadataContributionsEnabled;
|
|
117
|
+
}
|
|
118
|
+
static set MetadataContributionsEnabled(value) {
|
|
119
|
+
InteractiveFormsEngine._metadataContributionsEnabled = value;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Turns metadata contributions off when the instance configuration
|
|
123
|
+
* ({@link MetadataContributionsConfigKey}) is `false`. A missing key leaves the switch as it is,
|
|
124
|
+
* and a `true` never turns back on a switch that is already off.
|
|
125
|
+
*
|
|
126
|
+
* Call it after `InstanceConfigEngine.Config()` has finished and before the first form opens.
|
|
127
|
+
* Before Instance Config has loaded, or when it fails to load, the key reads as missing and
|
|
128
|
+
* the switch stays on.
|
|
129
|
+
*/
|
|
130
|
+
static ApplyInstanceConfiguration(config) {
|
|
131
|
+
if (!config.GetBoolean(InteractiveFormsEngine.MetadataContributionsConfigKey, true)) {
|
|
132
|
+
InteractiveFormsEngine.MetadataContributionsEnabled = false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
static readContributionsFlag() {
|
|
136
|
+
// Guarded: this class runs in the browser too, where `process` does not exist.
|
|
137
|
+
const env = typeof process !== 'undefined' ? process?.env?.MJ_FORMS_METADATA_CONTRIBUTIONS : undefined;
|
|
138
|
+
if (env === undefined || env === null || env.trim().length === 0)
|
|
139
|
+
return true;
|
|
140
|
+
const v = env.trim().toLowerCase();
|
|
141
|
+
return !(v === 'false' || v === '0' || v === 'off' || v === 'no');
|
|
142
|
+
}
|
|
82
143
|
/**
|
|
83
144
|
* Lazy-load the form Component + override caches. Safe to call from
|
|
84
145
|
* every entry point — no-op if already loaded (unless `forceRefresh`).
|
|
85
146
|
*/
|
|
86
147
|
async Config(forceRefresh, contextUser, provider) {
|
|
148
|
+
const contributionsEnabled = InteractiveFormsEngine.MetadataContributionsEnabled;
|
|
149
|
+
const personalRowsFilter = InteractiveFormsEngine.personalRowsLoadFilter(provider ?? this.ProviderToUse, contextUser);
|
|
150
|
+
const overrides = {
|
|
151
|
+
Type: 'entity',
|
|
152
|
+
EntityName: 'MJ: Entity Form Overrides',
|
|
153
|
+
PropertyName: '_overrides',
|
|
154
|
+
CacheLocal: true,
|
|
155
|
+
};
|
|
156
|
+
if (personalRowsFilter)
|
|
157
|
+
overrides.Filter = personalRowsFilter;
|
|
87
158
|
const c = [
|
|
88
159
|
{
|
|
89
160
|
Type: 'entity',
|
|
90
161
|
EntityName: 'MJ: Components',
|
|
91
162
|
PropertyName: '_forms',
|
|
163
|
+
// Whole forms only — deliberately NOT widened to all widgets: `Widget` is an
|
|
164
|
+
// open set grown by registry sync and general authoring, and this cache is
|
|
165
|
+
// written to client local storage on every boot.
|
|
166
|
+
//
|
|
167
|
+
// A contribution's panel Component (Type='Widget') is therefore NOT in this
|
|
168
|
+
// cache; `GetComponentByID` fetches it by ID on first use. The filter takes no
|
|
169
|
+
// subquery over `vwEntityFormContributions`: a view name resolves against the
|
|
170
|
+
// connecting user's default schema rather than the core schema, and a filter
|
|
171
|
+
// that fails takes the WHOLE engine down with it, so every form would wait on a
|
|
172
|
+
// cache that never loads. Fetching exactly the components that render, lazily,
|
|
173
|
+
// needs no cross-schema SQL at all.
|
|
92
174
|
Filter: "Type='Form'",
|
|
93
175
|
CacheLocal: true,
|
|
94
176
|
},
|
|
95
|
-
|
|
177
|
+
overrides,
|
|
178
|
+
];
|
|
179
|
+
if (contributionsEnabled) {
|
|
180
|
+
const contributions = {
|
|
96
181
|
Type: 'entity',
|
|
97
|
-
EntityName: 'MJ: Entity Form
|
|
98
|
-
PropertyName: '
|
|
182
|
+
EntityName: 'MJ: Entity Form Contributions',
|
|
183
|
+
PropertyName: '_contributions',
|
|
99
184
|
CacheLocal: true,
|
|
100
|
-
}
|
|
101
|
-
|
|
185
|
+
};
|
|
186
|
+
if (personalRowsFilter)
|
|
187
|
+
contributions.Filter = personalRowsFilter;
|
|
188
|
+
c.push(contributions);
|
|
189
|
+
}
|
|
102
190
|
await this.Load(c, provider, forceRefresh, contextUser);
|
|
103
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* The filter for the override and contribution loads: in the browser, every shared row plus
|
|
194
|
+
* the signed-in user's own personal rows; on a server, none.
|
|
195
|
+
*
|
|
196
|
+
* A browser cache holds one user's view, so other users' personal rows (with their Notes and
|
|
197
|
+
* Configuration) stay on the server. A server cache is shared by every user of the process,
|
|
198
|
+
* so it holds every row and each reader filters what it serves.
|
|
199
|
+
*/
|
|
200
|
+
static personalRowsLoadFilter(provider, contextUser) {
|
|
201
|
+
if (!provider || provider.ProviderType === ProviderType.Database)
|
|
202
|
+
return null;
|
|
203
|
+
const userID = (contextUser ?? provider.CurrentUser)?.ID;
|
|
204
|
+
return userID ? `Scope <> 'User' OR UserID = '${EscapeSQLString(userID)}'` : null;
|
|
205
|
+
}
|
|
104
206
|
// ─── Read-side accessors ────────────────────────────────────────────────
|
|
105
207
|
/** All cached form-role Components. */
|
|
106
208
|
get Forms() {
|
|
@@ -141,12 +243,163 @@ export class InteractiveFormsEngine extends BaseEngine {
|
|
|
141
243
|
return [];
|
|
142
244
|
return this.Overrides.filter(o => o.Scope === 'User' && o.UserID && UUIDsEqual(o.UserID, userID));
|
|
143
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* All cached EntityFormContribution rows (all scopes, all statuses — callers filter).
|
|
248
|
+
*
|
|
249
|
+
* Returns nothing while the kill switch is off. Dropping the entity from the load list is
|
|
250
|
+
* not enough on its own: a process that already loaded rows would keep serving them from
|
|
251
|
+
* the engine's data map, so the switch would appear to do nothing until a restart. The
|
|
252
|
+
* rollback path has to work in the process that is misbehaving.
|
|
253
|
+
*/
|
|
254
|
+
get Contributions() {
|
|
255
|
+
if (!InteractiveFormsEngine.MetadataContributionsEnabled)
|
|
256
|
+
return [];
|
|
257
|
+
return this.GetConfigData('_contributions');
|
|
258
|
+
}
|
|
259
|
+
/** Emits on every save / delete / remote-invalidate that touches `MJ: Entity Form Contributions`. */
|
|
260
|
+
get Contributions$() {
|
|
261
|
+
return this.ObserveProperty('_contributions');
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* True once the contribution cache has completed its first load.
|
|
265
|
+
*
|
|
266
|
+
* Slot hosts wait on this before the first mount: rendering compiled contributions and
|
|
267
|
+
* then adding rows a tick later is visible, and for a `bare` hero that replaces a baked
|
|
268
|
+
* section it means the user watches the Details panel render and then disappear.
|
|
269
|
+
*/
|
|
270
|
+
get ContributionsReady() {
|
|
271
|
+
return this.Loaded || this.IsPermissionConstrained;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Active contribution rows that apply to (entity, user, roles): User rows for this
|
|
275
|
+
* user, Role rows for any of the user's roles, and Global rows. Sorted by
|
|
276
|
+
* `Precedence` DESC then `SortKey` DESC. Last-wins collapse against compiled
|
|
277
|
+
* registrations happens in ng-base-forms, not here.
|
|
278
|
+
*
|
|
279
|
+
* On an identity or permission entity only the user's own rows apply
|
|
280
|
+
* ({@link FormScopeAllowedOnEntity}). The clamp is applied here, on the read path, because
|
|
281
|
+
* `mj sync` — the path an OpenApp actually uses — and direct SQL bypass the actions.
|
|
282
|
+
*/
|
|
283
|
+
GetApplicableContributions(entityID, userID, roleIDs) {
|
|
284
|
+
if (!entityID)
|
|
285
|
+
return [];
|
|
286
|
+
const rows = this.Contributions.filter(c => c.EntityID && UUIDsEqual(c.EntityID, entityID)
|
|
287
|
+
&& c.Status === 'Active'
|
|
288
|
+
&& FormScopeAllowedOnEntity(c.Entity, c.Scope)
|
|
289
|
+
&& ((c.Scope === 'User' && !!c.UserID && !!userID && UUIDsEqual(c.UserID, userID)) ||
|
|
290
|
+
(c.Scope === 'Role' && !!c.RoleID && roleIDs.some(r => UUIDsEqual(r, c.RoleID))) ||
|
|
291
|
+
(c.Scope === 'Global')));
|
|
292
|
+
return rows.sort((a, b) => {
|
|
293
|
+
const p = (b.Precedence ?? 0) - (a.Precedence ?? 0);
|
|
294
|
+
if (p !== 0)
|
|
295
|
+
return p;
|
|
296
|
+
return (b.SortKey ?? 0) - (a.SortKey ?? 0);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* A form from the loaded forms, or a widget {@link GetComponentByID} has already fetched.
|
|
301
|
+
* Undefined for a widget not fetched yet.
|
|
302
|
+
*/
|
|
303
|
+
FindComponentByID(id) {
|
|
304
|
+
if (!id)
|
|
305
|
+
return undefined;
|
|
306
|
+
return this.FindFormByID(id) ?? this._componentsByID.get(NormalizeUUID(id));
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Any Component by ID: a whole form from the loaded forms, otherwise one query by ID, kept in
|
|
310
|
+
* memory for the next caller. Panels that ask at the same time share one query. A failed or
|
|
311
|
+
* empty lookup is not kept, so the next caller tries again. Every kept component is dropped
|
|
312
|
+
* when any `MJ: Components` row is saved, deleted or changed on another server.
|
|
313
|
+
*
|
|
314
|
+
* @returns The component, or null when it does not exist or the lookup failed.
|
|
315
|
+
*/
|
|
316
|
+
async GetComponentByID(id, contextUser, provider) {
|
|
317
|
+
if (!id)
|
|
318
|
+
return null;
|
|
319
|
+
const loaded = this.FindComponentByID(id);
|
|
320
|
+
if (loaded)
|
|
321
|
+
return loaded;
|
|
322
|
+
this.subscribeComponentInvalidation();
|
|
323
|
+
const key = NormalizeUUID(id);
|
|
324
|
+
const inFlight = this._componentLookups.get(key);
|
|
325
|
+
if (inFlight)
|
|
326
|
+
return inFlight;
|
|
327
|
+
const lookup = this.queryComponentByID(id, contextUser, provider).then((component) => {
|
|
328
|
+
// A component change during the query cleared the maps; this result is then stale.
|
|
329
|
+
if (this._componentLookups.get(key) !== lookup)
|
|
330
|
+
return component;
|
|
331
|
+
this._componentLookups.delete(key);
|
|
332
|
+
if (component)
|
|
333
|
+
this._componentsByID.set(key, component);
|
|
334
|
+
return component;
|
|
335
|
+
});
|
|
336
|
+
this._componentLookups.set(key, lookup);
|
|
337
|
+
return lookup;
|
|
338
|
+
}
|
|
339
|
+
/** Drops every component {@link GetComponentByID} kept. */
|
|
340
|
+
ClearComponentCache() {
|
|
341
|
+
this._componentsByID.clear();
|
|
342
|
+
this._componentLookups.clear();
|
|
343
|
+
}
|
|
344
|
+
async queryComponentByID(id, contextUser, provider) {
|
|
345
|
+
const source = provider ?? this.ProviderToUse;
|
|
346
|
+
try {
|
|
347
|
+
const result = await RunView.FromMetadataProvider(source).RunView({
|
|
348
|
+
EntityName: 'MJ: Components',
|
|
349
|
+
ExtraFilter: `ID='${EscapeSQLString(id)}'`,
|
|
350
|
+
ResultType: 'entity_object',
|
|
351
|
+
MaxRows: 1,
|
|
352
|
+
}, contextUser ?? source?.CurrentUser);
|
|
353
|
+
if (!result.Success) {
|
|
354
|
+
LogError(`InteractiveFormsEngine: component lookup failed for ${id}: ${result.ErrorMessage ?? 'unknown error'}`);
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
return (result.Results ?? [])[0] ?? null;
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
LogError(`InteractiveFormsEngine: component lookup threw for ${id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* A save of any `MJ: Components` row, and a change to one on another server, refreshes the
|
|
366
|
+
* forms array (a widget is not in it, so the save is not applied in place), and that emission
|
|
367
|
+
* drops what {@link GetComponentByID} kept. A delete of a row outside the array changes no
|
|
368
|
+
* array; {@link HandleIndividualBaseEntityEvent} covers it. Subscribed before anything is
|
|
369
|
+
* kept, so the replay on subscribe clears nothing.
|
|
370
|
+
*/
|
|
371
|
+
subscribeComponentInvalidation() {
|
|
372
|
+
if (this._componentInvalidationSubscribed)
|
|
373
|
+
return;
|
|
374
|
+
this._componentInvalidationSubscribed = true;
|
|
375
|
+
this.Forms$.subscribe(() => this.ClearComponentCache());
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Drops what {@link GetComponentByID} kept when an `MJ: Components` row is deleted, here or on
|
|
379
|
+
* another server, then handles the event as every engine does. BaseEngine ignores a delete of a
|
|
380
|
+
* row that is not in a loaded array, which a fetched widget never is.
|
|
381
|
+
*/
|
|
382
|
+
async HandleIndividualBaseEntityEvent(event) {
|
|
383
|
+
if (InteractiveFormsEngine.isComponentDelete(event))
|
|
384
|
+
this.ClearComponentCache();
|
|
385
|
+
return super.HandleIndividualBaseEntityEvent(event);
|
|
386
|
+
}
|
|
387
|
+
static isComponentDelete(event) {
|
|
388
|
+
const entityName = (event.baseEntity?.EntityInfo?.Name ?? event.entityName ?? '').trim().toLowerCase();
|
|
389
|
+
if (entityName !== 'mj: components')
|
|
390
|
+
return false;
|
|
391
|
+
if (event.type === 'delete')
|
|
392
|
+
return true;
|
|
393
|
+
return event.type === 'remote-invalidate' && event.payload?.action === 'delete';
|
|
394
|
+
}
|
|
144
395
|
/**
|
|
145
396
|
* Resolver-style lookup matching the runtime form-resolver's scope
|
|
146
397
|
* priority: User > Role > Global. Returns the highest-priority
|
|
147
398
|
* Active override for the given (entity, user, roles) tuple, or null
|
|
148
399
|
* if none match. Within the same scope, lower `Priority` wins (the
|
|
149
|
-
* resolver convention — Priority is sort key, not boost).
|
|
400
|
+
* resolver convention — Priority is sort key, not boost). On an identity
|
|
401
|
+
* or permission entity only the user's own forms count
|
|
402
|
+
* ({@link FormScopeAllowedOnEntity}).
|
|
150
403
|
*
|
|
151
404
|
* @param entityID The target `MJ: Entities.ID`.
|
|
152
405
|
* @param userID The current user's `MJ: Users.ID`.
|
|
@@ -157,6 +410,7 @@ export class InteractiveFormsEngine extends BaseEngine {
|
|
|
157
410
|
return null;
|
|
158
411
|
const candidates = this.Overrides.filter(o => o.EntityID && UUIDsEqual(o.EntityID, entityID)
|
|
159
412
|
&& o.Status === 'Active'
|
|
413
|
+
&& FormScopeAllowedOnEntity(o.Entity, o.Scope)
|
|
160
414
|
&& ((o.Scope === 'User' && o.UserID && userID && UUIDsEqual(o.UserID, userID)) ||
|
|
161
415
|
(o.Scope === 'Role' && o.RoleID && roleIDs.some(r => UUIDsEqual(r, o.RoleID))) ||
|
|
162
416
|
(o.Scope === 'Global')));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-forms.js","sourceRoot":"","sources":["../../src/engines/interactive-forms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"interactive-forms.js","sourceRoot":"","sources":["../../src/engines/interactive-forms.ts"],"names":[],"mappings":"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"}
|