@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.
Files changed (48) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/custom/FormScope/FormContributionClaims.d.ts +20 -0
  3. package/dist/custom/FormScope/FormContributionClaims.d.ts.map +1 -0
  4. package/dist/custom/FormScope/FormContributionClaims.js +33 -0
  5. package/dist/custom/FormScope/FormContributionClaims.js.map +1 -0
  6. package/dist/custom/FormScope/FormContributionLifecycle.d.ts +43 -0
  7. package/dist/custom/FormScope/FormContributionLifecycle.d.ts.map +1 -0
  8. package/dist/custom/FormScope/FormContributionLifecycle.js +47 -0
  9. package/dist/custom/FormScope/FormContributionLifecycle.js.map +1 -0
  10. package/dist/custom/FormScope/FormContributionRow.d.ts +40 -0
  11. package/dist/custom/FormScope/FormContributionRow.d.ts.map +1 -0
  12. package/dist/custom/FormScope/FormContributionRow.js +84 -0
  13. package/dist/custom/FormScope/FormContributionRow.js.map +1 -0
  14. package/dist/custom/FormScope/FormPanelHides.d.ts +14 -0
  15. package/dist/custom/FormScope/FormPanelHides.d.ts.map +1 -0
  16. package/dist/custom/FormScope/FormPanelHides.js +32 -0
  17. package/dist/custom/FormScope/FormPanelHides.js.map +1 -0
  18. package/dist/custom/FormScope/FormScopeRules.d.ts +220 -0
  19. package/dist/custom/FormScope/FormScopeRules.d.ts.map +1 -0
  20. package/dist/custom/FormScope/FormScopeRules.js +295 -0
  21. package/dist/custom/FormScope/FormScopeRules.js.map +1 -0
  22. package/dist/engines/IdentityClaimEngine.d.ts +15 -2
  23. package/dist/engines/IdentityClaimEngine.d.ts.map +1 -1
  24. package/dist/engines/IdentityClaimEngine.js.map +1 -1
  25. package/dist/engines/QueryEngine.d.ts.map +1 -1
  26. package/dist/engines/QueryEngine.js +2 -1
  27. package/dist/engines/QueryEngine.js.map +1 -1
  28. package/dist/engines/component-metadata.d.ts +3 -1
  29. package/dist/engines/component-metadata.d.ts.map +1 -1
  30. package/dist/engines/component-metadata.js +12 -5
  31. package/dist/engines/component-metadata.js.map +1 -1
  32. package/dist/engines/interactive-forms.d.ts +128 -9
  33. package/dist/engines/interactive-forms.d.ts.map +1 -1
  34. package/dist/engines/interactive-forms.js +268 -14
  35. package/dist/engines/interactive-forms.js.map +1 -1
  36. package/dist/generated/entities/__mj.d.ts +4308 -203
  37. package/dist/generated/entities/__mj.d.ts.map +1 -1
  38. package/dist/generated/entities/__mj.js +11370 -5862
  39. package/dist/generated/entities/__mj.js.map +1 -1
  40. package/dist/generated/remote_operations.d.ts +262 -0
  41. package/dist/generated/remote_operations.d.ts.map +1 -1
  42. package/dist/generated/remote_operations.js +126 -0
  43. package/dist/generated/remote_operations.js.map +1 -1
  44. package/dist/index.d.ts +5 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +5 -0
  47. package/dist/index.js.map +1 -1
  48. 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: load `Type='Form'` Components only
28
- * (small dataset — a few dozen per typical deployment, ~5MB max) plus
29
- * **all** `EntityFormOverride` rows (tiny). Specification is included
30
- * because the cockpit + Skip rendering both need it. Loaded as
31
- * `entity_object` so callers can call `.Save()` / `.Delete()` on the
32
- * cached instances directly.
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,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEzG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAEpG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,qBAAa,sBAAuB,SAAQ,UAAU,CAAC,sBAAsB,CAAC;IAC1E,8DAA8D;IAC9D,WAAkB,QAAQ,IAAI,sBAAsB,CAEnD;IAED,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAoC;IAEtD;;;OAGG;IACU,MAAM,CACf,YAAY,CAAC,EAAE,OAAO,EACtB,WAAW,CAAC,EAAE,QAAQ,EACtB,QAAQ,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAqBhB,uCAAuC;IACvC,IAAW,KAAK,IAAI,iBAAiB,EAAE,CAEtC;IAED,wEAAwE;IACxE,IAAW,SAAS,IAAI,0BAA0B,EAAE,CAEnD;IAED;;;;;;;;;;;OAWG;IACH,IAAW,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAEnD;IAED,qFAAqF;IACrF,IAAW,UAAU,IAAI,UAAU,CAAC,0BAA0B,EAAE,CAAC,CAEhE;IAID;;;;;OAKG;IACI,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,0BAA0B,EAAE;IAOrE;;;;;;;;;;OAUG;IACI,0BAA0B,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC/B,0BAA0B,GAAG,IAAI;IA4BpC;;;;OAIG;IACI,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAQ1D,uFAAuF;IAChF,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAM9D,+CAA+C;IACxC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS;CAK9E"}
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: load `Type='Form'` Components only
27
- * (small dataset — a few dozen per typical deployment, ~5MB max) plus
28
- * **all** `EntityFormOverride` rows (tiny). Specification is included
29
- * because the cockpit + Skip rendering both need it. Loaded as
30
- * `entity_object` so callers can call `.Save()` / `.Delete()` on the
31
- * cached instances directly.
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 Overrides',
98
- PropertyName: '_overrides',
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":"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"}
1
+ {"version":3,"file":"interactive-forms.js","sourceRoot":"","sources":["../../src/engines/interactive-forms.ts"],"names":[],"mappings":"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"}