@memberjunction/core 6.2.0-edge.5 → 6.2.0-edge.7
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/generic/BaseEntitySaveQueue.d.ts +15 -0
- package/dist/generic/BaseEntitySaveQueue.d.ts.map +1 -1
- package/dist/generic/BaseEntitySaveQueue.js +21 -0
- package/dist/generic/BaseEntitySaveQueue.js.map +1 -1
- package/dist/generic/EntityFieldRules.d.ts.map +1 -1
- package/dist/generic/EntityFieldRules.js +1 -0
- package/dist/generic/EntityFieldRules.js.map +1 -1
- package/dist/generic/alternateBaseViews.d.ts +119 -0
- package/dist/generic/alternateBaseViews.d.ts.map +1 -0
- package/dist/generic/alternateBaseViews.js +223 -0
- package/dist/generic/alternateBaseViews.js.map +1 -0
- package/dist/generic/baseEngine.d.ts +171 -17
- package/dist/generic/baseEngine.d.ts.map +1 -1
- package/dist/generic/baseEngine.js +722 -117
- package/dist/generic/baseEngine.js.map +1 -1
- package/dist/generic/baseEngineRegistry.d.ts.map +1 -1
- package/dist/generic/baseEngineRegistry.js +2 -1
- package/dist/generic/baseEngineRegistry.js.map +1 -1
- package/dist/generic/baseEntity.d.ts +216 -21
- package/dist/generic/baseEntity.d.ts.map +1 -1
- package/dist/generic/baseEntity.js +969 -100
- package/dist/generic/baseEntity.js.map +1 -1
- package/dist/generic/baseRemotableOperation.d.ts +95 -6
- package/dist/generic/baseRemotableOperation.d.ts.map +1 -1
- package/dist/generic/baseRemotableOperation.js +112 -8
- package/dist/generic/baseRemotableOperation.js.map +1 -1
- package/dist/generic/contextTokens.d.ts +136 -0
- package/dist/generic/contextTokens.d.ts.map +1 -0
- package/dist/generic/contextTokens.js +319 -0
- package/dist/generic/contextTokens.js.map +1 -0
- package/dist/generic/databaseProviderBase.d.ts +103 -5
- package/dist/generic/databaseProviderBase.d.ts.map +1 -1
- package/dist/generic/databaseProviderBase.js +381 -52
- package/dist/generic/databaseProviderBase.js.map +1 -1
- package/dist/generic/embeddedRecord.d.ts +6 -0
- package/dist/generic/embeddedRecord.d.ts.map +1 -1
- package/dist/generic/embeddedRecord.js +15 -1
- package/dist/generic/embeddedRecord.js.map +1 -1
- package/dist/generic/entityCompanion.d.ts +7 -0
- package/dist/generic/entityCompanion.d.ts.map +1 -1
- package/dist/generic/entityCompanion.js +8 -0
- package/dist/generic/entityCompanion.js.map +1 -1
- package/dist/generic/entityInfo.d.ts +234 -9
- package/dist/generic/entityInfo.d.ts.map +1 -1
- package/dist/generic/entityInfo.js +592 -77
- package/dist/generic/entityInfo.js.map +1 -1
- package/dist/generic/entityValueFieldSecurity.d.ts +139 -0
- package/dist/generic/entityValueFieldSecurity.d.ts.map +1 -0
- package/dist/generic/entityValueFieldSecurity.js +250 -0
- package/dist/generic/entityValueFieldSecurity.js.map +1 -0
- package/dist/generic/externalDataSourceReadRouter.d.ts +10 -0
- package/dist/generic/externalDataSourceReadRouter.d.ts.map +1 -1
- package/dist/generic/externalDataSourceReadRouter.js +12 -0
- package/dist/generic/externalDataSourceReadRouter.js.map +1 -1
- package/dist/generic/fieldSecuritySQLGate.d.ts +359 -0
- package/dist/generic/fieldSecuritySQLGate.d.ts.map +1 -0
- package/dist/generic/fieldSecuritySQLGate.js +902 -0
- package/dist/generic/fieldSecuritySQLGate.js.map +1 -0
- package/dist/generic/indexRestrictedFields.d.ts +47 -0
- package/dist/generic/indexRestrictedFields.d.ts.map +1 -0
- package/dist/generic/indexRestrictedFields.js +129 -0
- package/dist/generic/indexRestrictedFields.js.map +1 -0
- package/dist/generic/interfaces.d.ts +64 -2
- package/dist/generic/interfaces.d.ts.map +1 -1
- package/dist/generic/interfaces.js.map +1 -1
- package/dist/generic/listMembershipFilter.d.ts +5 -0
- package/dist/generic/listMembershipFilter.d.ts.map +1 -0
- package/dist/generic/listMembershipFilter.js +23 -0
- package/dist/generic/listMembershipFilter.js.map +1 -0
- package/dist/generic/localCacheManager.d.ts +126 -14
- package/dist/generic/localCacheManager.d.ts.map +1 -1
- package/dist/generic/localCacheManager.js +348 -48
- package/dist/generic/localCacheManager.js.map +1 -1
- package/dist/generic/logging.d.ts.map +1 -1
- package/dist/generic/logging.js +7 -1
- package/dist/generic/logging.js.map +1 -1
- package/dist/generic/metadata.d.ts +3 -2
- package/dist/generic/metadata.d.ts.map +1 -1
- package/dist/generic/metadata.js +5 -2
- package/dist/generic/metadata.js.map +1 -1
- package/dist/generic/platformSQL.d.ts +54 -0
- package/dist/generic/platformSQL.d.ts.map +1 -1
- package/dist/generic/platformSQL.js +55 -0
- package/dist/generic/platformSQL.js.map +1 -1
- package/dist/generic/providerBase.d.ts +408 -57
- package/dist/generic/providerBase.d.ts.map +1 -1
- package/dist/generic/providerBase.js +1051 -310
- package/dist/generic/providerBase.js.map +1 -1
- package/dist/generic/queryInfo.d.ts +13 -0
- package/dist/generic/queryInfo.d.ts.map +1 -1
- package/dist/generic/queryInfo.js +13 -0
- package/dist/generic/queryInfo.js.map +1 -1
- package/dist/generic/queryInfoInterfaces.d.ts +8 -0
- package/dist/generic/queryInfoInterfaces.d.ts.map +1 -1
- package/dist/generic/queryTemplateContext.d.ts +49 -0
- package/dist/generic/queryTemplateContext.d.ts.map +1 -0
- package/dist/generic/queryTemplateContext.js +113 -0
- package/dist/generic/queryTemplateContext.js.map +1 -0
- package/dist/generic/recordChangeFieldSecurity.d.ts.map +1 -1
- package/dist/generic/recordChangeFieldSecurity.js +13 -2
- package/dist/generic/recordChangeFieldSecurity.js.map +1 -1
- package/dist/generic/relatedRecordCollection.d.ts +18 -0
- package/dist/generic/relatedRecordCollection.d.ts.map +1 -1
- package/dist/generic/relatedRecordCollection.js +55 -7
- package/dist/generic/relatedRecordCollection.js.map +1 -1
- package/dist/generic/remoteOperationDispatch.d.ts.map +1 -1
- package/dist/generic/remoteOperationDispatch.js +14 -2
- package/dist/generic/remoteOperationDispatch.js.map +1 -1
- package/dist/generic/runQuery.d.ts +42 -0
- package/dist/generic/runQuery.d.ts.map +1 -1
- package/dist/generic/runQuery.js +14 -0
- package/dist/generic/runQuery.js.map +1 -1
- package/dist/generic/runQuerySQLFilterImplementations.d.ts +33 -6
- package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -1
- package/dist/generic/runQuerySQLFilterImplementations.js +119 -29
- package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -1
- package/dist/generic/saveEntityGraphOperation.d.ts.map +1 -1
- package/dist/generic/saveEntityGraphOperation.js +3 -0
- package/dist/generic/saveEntityGraphOperation.js.map +1 -1
- package/dist/generic/securityInfo.d.ts +11 -0
- package/dist/generic/securityInfo.d.ts.map +1 -1
- package/dist/generic/securityInfo.js +15 -0
- package/dist/generic/securityInfo.js.map +1 -1
- package/dist/generic/telemetryManager.d.ts +9 -0
- package/dist/generic/telemetryManager.d.ts.map +1 -1
- package/dist/generic/telemetryManager.js +5 -1
- package/dist/generic/telemetryManager.js.map +1 -1
- package/dist/generic/transportError.d.ts +41 -0
- package/dist/generic/transportError.d.ts.map +1 -0
- package/dist/generic/transportError.js +167 -0
- package/dist/generic/transportError.js.map +1 -0
- package/dist/generic/util.d.ts +12 -0
- package/dist/generic/util.d.ts.map +1 -1
- package/dist/generic/util.js +52 -3
- package/dist/generic/util.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/views/runView.d.ts +102 -0
- package/dist/views/runView.d.ts.map +1 -1
- package/dist/views/runView.js +40 -0
- package/dist/views/runView.js.map +1 -1
- package/dist/views/viewProperties.d.ts +55 -0
- package/dist/views/viewProperties.d.ts.map +1 -0
- package/dist/views/viewProperties.js +258 -0
- package/dist/views/viewProperties.js.map +1 -0
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseEntity, BaseEntityEvent } from "./baseEntity.js";
|
|
2
2
|
import { EntityDependency, EntityDocumentTypeInfo, EntityInfo, RecordDependency, RecordMergeRequest, RecordMergeResult } from "./entityInfo.js";
|
|
3
|
-
import { IMetadataProvider, MetadataSweepResult, ProviderConfigDataBase, MetadataInfo, ILocalStorageProvider, IFileSystemProvider, DatasetResultType, DatasetStatusResultType, DatasetItemFilterType, EntityRecordNameInput, EntityRecordNameResult, ProviderType, PotentialDuplicateRequest, PotentialDuplicateResponse, EntityMergeOptions, AllMetadata, IRunViewProvider, RunViewResult, IRunQueryProvider, RunQueryResult, RunViewWithCacheCheckParams, FullTextSearchParams, FullTextSearchResult, SearchEntityParams, EntitySearchResult, IRemoteOperationProvider, RemoteOpInvokeOptions, RemoteOpResult } from "./interfaces.js";
|
|
3
|
+
import { IMetadataProvider, MetadataSweepResult, ProviderConfigDataBase, MetadataInfo, ILocalStorageProvider, IFileSystemProvider, DatasetResultType, DatasetStatusResultType, DatasetItemFilterType, EntityRecordNameInput, EntityRecordNameResult, ProviderType, PotentialDuplicateRequest, PotentialDuplicateResponse, EntityMergeOptions, GetRecordDependenciesOptions, AllMetadata, IRunViewProvider, RunViewResult, IRunQueryProvider, RunQueryResult, RunViewWithCacheCheckParams, FullTextSearchParams, FullTextSearchResult, SearchEntityParams, EntitySearchResult, IRemoteOperationProvider, RemoteOpInvokeOptions, RemoteOpResult } from "./interfaces.js";
|
|
4
4
|
import { ScoredCandidate } from "./scoring/ReciprocalRankFusion.js";
|
|
5
5
|
import { RunQueryParams } from "./runQuery.js";
|
|
6
6
|
import { CachedRunViewResult } from "./localCacheManager.js";
|
|
@@ -15,6 +15,7 @@ import { CompositeKey } from "./compositeKey.js";
|
|
|
15
15
|
import { ExplorerNavigationItem } from "./explorerNavigationItem.js";
|
|
16
16
|
import { RunViewParams } from "../views/runView.js";
|
|
17
17
|
import { DatabasePlatform, PlatformSQL } from "./platformSQL.js";
|
|
18
|
+
import { ContextToken } from "./contextTokens.js";
|
|
18
19
|
/**
|
|
19
20
|
* Creates a new instance of AllMetadata from a simple object.
|
|
20
21
|
* Handles deserialization and proper instantiation of all metadata classes.
|
|
@@ -51,6 +52,12 @@ export interface QueryCacheAuthorization {
|
|
|
51
52
|
categoryPath?: string;
|
|
52
53
|
/** Resolved query name — for log messages when the request was by ID only. */
|
|
53
54
|
queryName?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The context tokens the resolved query's template reads, with every query it composes
|
|
57
|
+
* (`FindQueryContextTokens`). Their values join the fingerprint, so a result that depends on
|
|
58
|
+
* the user or the date is never served to another user or on another day.
|
|
59
|
+
*/
|
|
60
|
+
contextTokens?: ContextToken[];
|
|
54
61
|
/**
|
|
55
62
|
* Resolved query ID. With `queryName`, the identity the RunQuery fingerprint is built from, so
|
|
56
63
|
* a request by ID, by name, or by both reaches the same slot.
|
|
@@ -62,6 +69,12 @@ export interface QueryCacheAuthorization {
|
|
|
62
69
|
* provider cannot compute one (a client, whose slots the server validates instead).
|
|
63
70
|
*/
|
|
64
71
|
definition?: QueryDefinitionSignature;
|
|
72
|
+
/**
|
|
73
|
+
* The user's field-security profile (`FieldSecuritySQLGate.CatalogDenialProfileKey`) when the
|
|
74
|
+
* run drops denied columns from its rows; it joins the fingerprint, so users with different
|
|
75
|
+
* denials never share a slot. Undefined when the rows are the same for every authorized user.
|
|
76
|
+
*/
|
|
77
|
+
fieldSecurityKey?: string;
|
|
65
78
|
}
|
|
66
79
|
export declare const AllMetadataArrays: ({
|
|
67
80
|
key: string;
|
|
@@ -123,6 +136,7 @@ export type EntityMetadataRow = BaseMetadataRow & {
|
|
|
123
136
|
EntityRelationships?: unknown[];
|
|
124
137
|
EntitySettings?: unknown[];
|
|
125
138
|
EntityOrganicKeys?: unknown[];
|
|
139
|
+
EntityAlternateBaseViews?: unknown[];
|
|
126
140
|
};
|
|
127
141
|
export type EntityFieldMetadataRow = BaseMetadataRow & {
|
|
128
142
|
ID: string;
|
|
@@ -401,10 +415,11 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
401
415
|
*/
|
|
402
416
|
private _metadataReadsJoinTransaction;
|
|
403
417
|
/**
|
|
404
|
-
* The MJ_Metadata dataset items (code + entity name) as of the last
|
|
418
|
+
* The MJ_Metadata dataset items (code + entity name + row count) as of the last load. The remote
|
|
405
419
|
* timestamps ({@link GetLatestMetadataUpdates}) are keyed by entity name while a dataset
|
|
406
420
|
* read is scoped by item code, so this is the bridge that lets a staleness check be turned
|
|
407
|
-
* into a scoped reload (see {@link PartialRefreshItemCodes})
|
|
421
|
+
* into a scoped reload (see {@link PartialRefreshItemCodes}) and lets {@link adoptServerMetadata}
|
|
422
|
+
* verify that the received dataset items' row counts match `_latestRemoteMetadataTimestamps`.
|
|
408
423
|
*/
|
|
409
424
|
private _metadataDatasetItems;
|
|
410
425
|
/**
|
|
@@ -812,11 +827,41 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
812
827
|
* @returns Array of view results (shallow-copied Results per caller)
|
|
813
828
|
*/
|
|
814
829
|
RunViews<T = any>(params: RunViewParams[], contextUser?: UserInfo): Promise<RunViewResult<T>[]>;
|
|
830
|
+
/**
|
|
831
|
+
* Stashes resolved RunViews results on `_inflightViews` for `DedupLingerMs` and schedules
|
|
832
|
+
* cleanup via an isolated static `WeakRef` timer helper so the timer closure's V8 lexical
|
|
833
|
+
* context never retains `this`, `promise`, or `results` on short-lived per-request providers.
|
|
834
|
+
*/
|
|
835
|
+
private stashInflightLingerResult;
|
|
836
|
+
private static scheduleInflightLingerExpiry;
|
|
815
837
|
/**
|
|
816
838
|
* The original RunViews execution pipeline (pre-processing, cache,
|
|
817
839
|
* internal execution, post-processing).
|
|
818
840
|
*/
|
|
819
841
|
private executeRunViewsPipeline;
|
|
842
|
+
/**
|
|
843
|
+
* Puts each refused view's result back at its own index of the caller's batch, with the
|
|
844
|
+
* admitted views' results filling the remaining indexes in order.
|
|
845
|
+
*/
|
|
846
|
+
private static interleaveRefusedResults;
|
|
847
|
+
/**
|
|
848
|
+
* Keeps the `TotalRowCount` contract on every way out of the pipeline: a caller that passed
|
|
849
|
+
* `SkipTotalRowCount` gets `undefined`, never a number. Cache hits, the smart-cache check and
|
|
850
|
+
* the GraphQL wire each rebuild a result and each have a reason to fill in a row count, so the
|
|
851
|
+
* contract is applied once here rather than at each of those sites.
|
|
852
|
+
*/
|
|
853
|
+
private static clearSkippedTotalRowCount;
|
|
854
|
+
/**
|
|
855
|
+
* Runs a RunViews batch of the views the field-security predicate gate admitted, and applies
|
|
856
|
+
* the `TotalRowCount` contract to whichever stage produced each result.
|
|
857
|
+
*/
|
|
858
|
+
private runAdmittedViews;
|
|
859
|
+
/**
|
|
860
|
+
* The cache, database and post-processing stages of a RunViews batch, for the views the
|
|
861
|
+
* field-security predicate gate admitted. `params` and every index map in `preResult`
|
|
862
|
+
* describe the same admitted views.
|
|
863
|
+
*/
|
|
864
|
+
private runAdmittedViewStages;
|
|
820
865
|
/**
|
|
821
866
|
* Enqueues a RunViews call for coalescing. Multiple calls arriving within
|
|
822
867
|
* CoalesceWindowMs are merged into a single mega-batch, executed once, and
|
|
@@ -890,6 +935,34 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
890
935
|
* - entities where server caching is disallowed
|
|
891
936
|
*/
|
|
892
937
|
protected runViewCacheEligible(param: RunViewParams): boolean;
|
|
938
|
+
/**
|
|
939
|
+
* True when the caller explicitly requested a non-empty `Fields` projection on a plain-object
|
|
940
|
+
* (`ResultType !== 'entity_object'`) read.
|
|
941
|
+
*/
|
|
942
|
+
protected hasNarrowFieldsOverride(param: RunViewParams): boolean;
|
|
943
|
+
/**
|
|
944
|
+
* True when a cache-miss read should widen `Fields` to the full entity superset AND populate
|
|
945
|
+
* `LocalCacheManager` with that superset.
|
|
946
|
+
*
|
|
947
|
+
* On the server (`TrustLocalCacheCompletely === true`), cache-allowed entities (`AllowCaching === true`)
|
|
948
|
+
* widen on miss by default so the Fields-agnostic superset slot serves any future `Fields` subset
|
|
949
|
+
* (`server-cache` S1 -> S2 -> S3), UNLESS the caller explicitly opts out via `CacheLocal: false` or
|
|
950
|
+
* `BypassCache: true` (in which case narrow SQL `SELECT` pushdown is preserved end-to-end without
|
|
951
|
+
* polluting the cache). On the client (`TrustLocalCacheCompletely === false`), only `CacheLocal: true`
|
|
952
|
+
* widens and caches.
|
|
953
|
+
*/
|
|
954
|
+
protected shouldWidenAndPopulateCache(param: RunViewParams): boolean;
|
|
955
|
+
/**
|
|
956
|
+
* True when the request targets an `AlternateBaseView` (explicitly on `param.AlternateBaseView`
|
|
957
|
+
* or pinned on `param.ViewEntity`) whose `CachePolicy` (or an ancestor's `CachePolicy` in its
|
|
958
|
+
* `ParentID` chain) is `'Bypass'` (`IsBypassCache === true`), when the requested alternate
|
|
959
|
+
* base view does not resolve to a usable view on the entity, or when a saved User View is
|
|
960
|
+
* referenced only by `ViewID`/`ViewName` without a loaded `ViewEntity` (fail-closed: we cannot
|
|
961
|
+
* synchronously inspect `DisplayState.alternateBaseView` until the view is loaded).
|
|
962
|
+
*/
|
|
963
|
+
protected isAlternateBaseViewCacheBypassed(param: RunViewParams): boolean;
|
|
964
|
+
/** True when a run carries view properties (even an empty map): the browser sends it to the server as it is. */
|
|
965
|
+
private static carriesViewProperties;
|
|
893
966
|
/** True when the entity is a CodeGen materialized-query wrapper (materialized_vw*) whose snapshot is
|
|
894
967
|
* refreshed out-of-band — the same one IsServerCacheAllowedForEntity excludes from the server cache. */
|
|
895
968
|
protected isMaterializedWrapperEntity(param: RunViewParams): boolean;
|
|
@@ -1120,6 +1193,13 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1120
1193
|
* the miss path also checked entity read permissions).
|
|
1121
1194
|
*/
|
|
1122
1195
|
protected ResolveQueryCacheAuthorization(params: RunQueryParams, user?: UserInfo): QueryCacheAuthorization;
|
|
1196
|
+
/**
|
|
1197
|
+
* The fingerprint segment for what the server sets on a run: `ServerParameters`, and the
|
|
1198
|
+
* `Context.*` values the query reads, worked out for this user, zone and day. Empty when the
|
|
1199
|
+
* run has neither, so the fingerprint is exactly what it was before either existed.
|
|
1200
|
+
* @returns null when the query reads `Context.Now`: such a result is never reused
|
|
1201
|
+
*/
|
|
1202
|
+
private queryCacheServerSegment;
|
|
1123
1203
|
RunQuery(params: RunQueryParams, contextUser?: UserInfo): Promise<RunQueryResult>;
|
|
1124
1204
|
/**
|
|
1125
1205
|
* Executes a query from a `QueryExecutionSpec` — the lower-layer interface-based entry point.
|
|
@@ -1151,6 +1231,12 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1151
1231
|
* @param callerName
|
|
1152
1232
|
*/
|
|
1153
1233
|
protected EntityStatusCheck(params: RunViewParams, callerName: string, contextUser?: UserInfo): Promise<void>;
|
|
1234
|
+
/**
|
|
1235
|
+
* Emits a `[Deprecated]` warning when a cache-hit RunView served rows for a deprecated
|
|
1236
|
+
* `AlternateBaseView` (or an alternate view whose ancestor in `ParentID` is deprecated).
|
|
1237
|
+
* Cache misses log deprecation once inside `ResolveAlternateBaseView` during execution.
|
|
1238
|
+
*/
|
|
1239
|
+
protected logDeprecatedAlternateBaseViewIfAny(params: RunViewParams, callerName: string): void;
|
|
1154
1240
|
/**
|
|
1155
1241
|
* Result from PreRunView hook containing cache status and optional cached result
|
|
1156
1242
|
*/
|
|
@@ -1166,6 +1252,11 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1166
1252
|
* to project cache-miss DB results back down to the requested shape.
|
|
1167
1253
|
*/
|
|
1168
1254
|
callerRequestedFields?: string[] | null;
|
|
1255
|
+
/**
|
|
1256
|
+
* True when PreRunView determined that a cache-miss result holds a full superset
|
|
1257
|
+
* projection eligible to populate the Fields-agnostic cache slot in PostRunView.
|
|
1258
|
+
*/
|
|
1259
|
+
populateCache?: boolean;
|
|
1169
1260
|
};
|
|
1170
1261
|
/**
|
|
1171
1262
|
* Result from PreRunViews hook containing cache status for batch operations
|
|
@@ -1196,12 +1287,25 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1196
1287
|
* fingerprint string for every batch item.
|
|
1197
1288
|
*/
|
|
1198
1289
|
fingerprintMap?: Map<number, string>;
|
|
1290
|
+
/**
|
|
1291
|
+
* Param indexes whose cache-miss result holds a full superset projection eligible to
|
|
1292
|
+
* populate the Fields-agnostic cache slot in PostRunViews.
|
|
1293
|
+
*/
|
|
1294
|
+
populateCacheSet?: Set<number>;
|
|
1199
1295
|
/**
|
|
1200
1296
|
* Pre-resolved local cache entries keyed by client cache fingerprint, populated
|
|
1201
1297
|
* during prepareSmartCacheCheckParams so executeSmartCacheCheck can reuse the
|
|
1202
1298
|
* already-parsed results for 'current' items without a second IndexedDB read.
|
|
1203
1299
|
*/
|
|
1204
1300
|
preResolvedCache?: Map<string, CachedRunViewResult | null>;
|
|
1301
|
+
/**
|
|
1302
|
+
* Views the field-security predicate gate refused, keyed by their index in the caller's
|
|
1303
|
+
* batch, each with its `Success: false` result. Present only when at least one view was
|
|
1304
|
+
* refused. Every other field of this result — the index maps, `cachedResults`,
|
|
1305
|
+
* `uncachedParams`, `smartCacheCheckParams` — then describes the ADMITTED views only,
|
|
1306
|
+
* indexed by their position among them.
|
|
1307
|
+
*/
|
|
1308
|
+
refusedResults?: Map<number, RunViewResult>;
|
|
1205
1309
|
};
|
|
1206
1310
|
/**
|
|
1207
1311
|
* Result from PreRunQuery hook containing cache status and optional cached result
|
|
@@ -1263,7 +1367,7 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1263
1367
|
*/
|
|
1264
1368
|
protected ComputeRunViewRLSWhereClause(params: RunViewParams, contextUser?: UserInfo): string;
|
|
1265
1369
|
/**
|
|
1266
|
-
* The
|
|
1370
|
+
* The field-security cache key for one entity: a canonical list of the fields the user MAY read.
|
|
1267
1371
|
*
|
|
1268
1372
|
* Keyed on the ALLOWED set rather than the denied set for two reasons. Once metadata ships
|
|
1269
1373
|
* to browsers filtered to what a user may see ([#3485](https://github.com/MemberJunction/MJ/issues/3485)),
|
|
@@ -1275,36 +1379,90 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1275
1379
|
* Returns '' when the entity has field security off or the user is denied nothing, so
|
|
1276
1380
|
* unrestricted users keep byte-identical fingerprints and shared slots.
|
|
1277
1381
|
*
|
|
1278
|
-
*
|
|
1279
|
-
*
|
|
1280
|
-
*
|
|
1382
|
+
* Reads the denied set through {@link ResolveRequestDeniedReadFields}, so the key and the
|
|
1383
|
+
* SELECT list a database provider builds for the same request describe the same columns.
|
|
1384
|
+
*
|
|
1385
|
+
* @param params - The request; also the memo the denied set is shared through
|
|
1386
|
+
* @param contextUser - The request's user; defaults to {@link CurrentUser}
|
|
1387
|
+
*/
|
|
1388
|
+
protected ComputeClientFLSAllowedKey(params: RunViewParams, contextUser?: UserInfo): string;
|
|
1389
|
+
/**
|
|
1390
|
+
* The field-security segment for a {@link LocalCacheManager} RunView fingerprint, on both
|
|
1391
|
+
* tiers: the slot a request reads and fills belongs to the user's permission class.
|
|
1392
|
+
*
|
|
1393
|
+
* - **The entity's allowed columns** ({@link ComputeClientFLSAllowedKey}). A database
|
|
1394
|
+
* provider selects only the columns the reader may see, so a restricted reader's fill is
|
|
1395
|
+
* narrower than an unrestricted one's, and the two must never share a slot. A browser
|
|
1396
|
+
* stores rows exactly as the server returned them and never projects on read, so its
|
|
1397
|
+
* slots need the same identity. It also keeps user searches apart: which rows match a
|
|
1398
|
+
* search depends on which columns the reader may search.
|
|
1399
|
+
* - **For a saved view, the user's denials on every entity.** A view's stored clause can
|
|
1400
|
+
* reach other entities (nested view filters), and those clauses are only screened when the
|
|
1401
|
+
* database runs them, on a miss. Keying the slot on the whole denial profile means a hit
|
|
1402
|
+
* is only ever served from a fill by a user whose clauses screen identically.
|
|
1403
|
+
*
|
|
1404
|
+
* Empty for a user denied nothing, so unrestricted users keep byte-identical fingerprints
|
|
1405
|
+
* and share slots. Read-time projection ({@link ApplyFieldSecurityProjection}) still runs on
|
|
1406
|
+
* every hit and miss, as a backstop.
|
|
1407
|
+
*
|
|
1408
|
+
* @param params - The request
|
|
1409
|
+
* @param contextUser - The request's user; defaults to {@link CurrentUser}. On a server
|
|
1410
|
+
* this must be the request's user, never the process user.
|
|
1411
|
+
*/
|
|
1412
|
+
protected ComputeRunViewFLSFingerprintKey(params: RunViewParams, contextUser?: UserInfo): string;
|
|
1413
|
+
/**
|
|
1414
|
+
* Every field `user` may not read, across all entities: one `entityID:field,field` entry per
|
|
1415
|
+
* entity on which the user is denied something, sorted. '' for a user denied nothing.
|
|
1416
|
+
*
|
|
1417
|
+
* @param user - The user whose denials to describe
|
|
1418
|
+
*/
|
|
1419
|
+
protected ComputeFieldSecurityProfileKey(user: UserInfo): string;
|
|
1420
|
+
/**
|
|
1421
|
+
* The fingerprint of the server-cache slot a RunView reads and fills for `contextUser`:
|
|
1422
|
+
* the request, this provider's connection, the user's row-level-security clause and the
|
|
1423
|
+
* user's field-security key. Every server path that reads or writes a RunView slot builds
|
|
1424
|
+
* its fingerprint here, so none of them can leave a segment out — a path that omitted the
|
|
1425
|
+
* user's segments would read or fill another permission class's slot.
|
|
1426
|
+
*
|
|
1427
|
+
* @param params - The request
|
|
1428
|
+
* @param contextUser - The request's user; defaults to {@link CurrentUser}
|
|
1281
1429
|
*/
|
|
1282
|
-
|
|
1430
|
+
ComputeRunViewCacheFingerprint(params: RunViewParams, contextUser?: UserInfo): string;
|
|
1283
1431
|
/**
|
|
1284
|
-
* The field-security
|
|
1285
|
-
*
|
|
1432
|
+
* The field-security key a browser sends with a cached slot's status, and the one a server
|
|
1433
|
+
* compares it with: a hash of {@link ComputeRunViewFLSFingerprintKey}, or '' for a user
|
|
1434
|
+
* denied nothing.
|
|
1286
1435
|
*
|
|
1287
|
-
*
|
|
1288
|
-
*
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1436
|
+
* The currency check otherwise compares only `maxUpdatedAt` and `rowCount`, and neither
|
|
1437
|
+
* changes when a user loses a column. A browser whose metadata has not refreshed yet keeps
|
|
1438
|
+
* its old slot (same fingerprint) and would be told "current" while still showing the
|
|
1439
|
+
* column; with this key the server sees the mismatch and answers "stale" with fresh rows.
|
|
1291
1440
|
*
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
*
|
|
1441
|
+
* @param params - The request
|
|
1442
|
+
* @param contextUser - The request's user; defaults to {@link CurrentUser}
|
|
1443
|
+
*/
|
|
1444
|
+
protected ComputeFieldSecurityCacheStatusKey(params: RunViewParams, contextUser?: UserInfo): string;
|
|
1445
|
+
/**
|
|
1446
|
+
* The fields `user` may not read on `entity` for this one request, resolved once and reused by
|
|
1447
|
+
* everything that asks again for the same request (`params` object), user object and entity.
|
|
1448
|
+
*
|
|
1449
|
+
* The cache key and the SELECT list are built at different moments of a request. Read
|
|
1450
|
+
* independently, a metadata refresh landing between the two would key a slot for one
|
|
1451
|
+
* permission class and fill it with another's columns. Sharing one answer per request rules
|
|
1452
|
+
* that out. Empty when field security does not apply.
|
|
1298
1453
|
*
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1454
|
+
* @param params - The request; the memo is keyed on this object
|
|
1455
|
+
* @param entity - The entity being read
|
|
1456
|
+
* @param user - The request's user
|
|
1301
1457
|
*/
|
|
1302
|
-
protected
|
|
1458
|
+
protected ResolveRequestDeniedReadFields(params: RunViewParams, entity: EntityInfo, user: UserInfo | undefined): Set<string>;
|
|
1459
|
+
private _requestDeniedReadFields;
|
|
1303
1460
|
/**
|
|
1304
1461
|
* The fetch-widening field list for a cache-eligible request: always every entity field.
|
|
1305
|
-
* One slot per (entity, filter, order) serves every caller regardless of
|
|
1306
|
-
* they asked for
|
|
1307
|
-
*
|
|
1462
|
+
* One slot per (entity, filter, order, permission class) serves every caller regardless of
|
|
1463
|
+
* the field subset they asked for. Field security is not applied here: a database provider
|
|
1464
|
+
* leaves the user's denied columns out of the SELECT it builds from this list, and the slot
|
|
1465
|
+
* key carries the user's class ({@link ComputeRunViewFLSFingerprintKey}).
|
|
1308
1466
|
*/
|
|
1309
1467
|
protected ComputeRunViewFetchFields(entity: EntityInfo, params?: RunViewParams): string[];
|
|
1310
1468
|
/**
|
|
@@ -1338,28 +1496,44 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1338
1496
|
* @returns Pre-processing result with cache status and optional cached result
|
|
1339
1497
|
*/
|
|
1340
1498
|
/**
|
|
1341
|
-
* Rejects a RunView whose
|
|
1342
|
-
*
|
|
1499
|
+
* Rejects a RunView whose caller-authored SQL reads a field the user cannot read: `ExtraFilter`,
|
|
1500
|
+
* `OrderBy`, `OverrideExcludeFilter`, every `Aggregates[].expression`, and — when the request
|
|
1501
|
+
* carries a loaded `ViewEntity` — that view's stored `WhereClause` and `OrderByClause`.
|
|
1343
1502
|
*
|
|
1344
1503
|
* Output projection alone is security theater. A user denied `Salary` can send
|
|
1345
1504
|
* `ExtraFilter: "Salary > 200000"` or `OrderBy: "Salary DESC"` and reconstruct the values
|
|
1346
1505
|
* from which rows come back and in what order — the column never appears in a result, so
|
|
1347
1506
|
* every output-stripping point reports "secure." Aggregates are the same channel in a purer
|
|
1348
1507
|
* form: `Aggregates: [{expression: 'MIN(Salary)'}]` under a narrow filter returns a denied
|
|
1349
|
-
* field's exact values directly.
|
|
1350
|
-
*
|
|
1351
|
-
* surface (`UserSearchString` is handled by excluding denied fields from the searched set,
|
|
1352
|
-
* not by rejection — see below).
|
|
1508
|
+
* field's exact values directly. `UserSearchString` is handled by excluding denied fields from
|
|
1509
|
+
* the searched set, not by rejection.
|
|
1353
1510
|
*
|
|
1354
|
-
* Lives at the provider layer
|
|
1355
|
-
*
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1511
|
+
* Lives at the provider layer because every RunView funnels through here — the batch path,
|
|
1512
|
+
* server-internal agents and actions running under a restricted `contextUser`, and the
|
|
1513
|
+
* resolver alike. A database provider checks the clauses it actually runs a second time, once
|
|
1514
|
+
* a saved view is resolved, so a request that names only a `ViewID` is covered too.
|
|
1358
1515
|
*
|
|
1359
|
-
* The
|
|
1360
|
-
* see {@link ProviderBase.FieldSecurityDenialMessage}.
|
|
1516
|
+
* The reading of each clause, and the error it raises, is {@link FieldSecuritySQLGate}'s.
|
|
1361
1517
|
*/
|
|
1362
1518
|
protected AssertPredicatesRespectFieldSecurity(params: RunViewParams, contextUser?: UserInfo): void;
|
|
1519
|
+
/**
|
|
1520
|
+
* Throws a {@link FieldSecurityError} when any of `clauses` — SQL fragments that run against
|
|
1521
|
+
* `entity`'s view — reads a field `user` cannot read, reads whole rows of an entity the user is
|
|
1522
|
+
* denied fields on, or cannot be read well enough to tell. Non-string and blank entries are
|
|
1523
|
+
* skipped. A no-op, with nothing scanned, for a user denied nothing on any entity.
|
|
1524
|
+
*
|
|
1525
|
+
* The shared entry point for every clause slot a provider runs: RunView parameters, a saved
|
|
1526
|
+
* view's stored clauses, dataset item filters, user-search text spliced as SQL.
|
|
1527
|
+
*/
|
|
1528
|
+
protected AssertClausesRespectFieldSecurityForEntity(entity: EntityInfo, clauses: Iterable<unknown>, user: UserInfo): void;
|
|
1529
|
+
/**
|
|
1530
|
+
* {@link AssertClausesRespectFieldSecurityForEntity} for ORDER BY fragments, which also refuses
|
|
1531
|
+
* a sort by column position for a user denied a field on `entity`
|
|
1532
|
+
* ({@link FieldSecuritySQLGate.FindSortViolation}).
|
|
1533
|
+
*/
|
|
1534
|
+
protected AssertSortRespectsFieldSecurityForEntity(entity: EntityInfo, orderBys: Iterable<unknown>, user: UserInfo): void;
|
|
1535
|
+
/** Throws the field-security error for the first of `fragments` that `find` refuses. */
|
|
1536
|
+
private assertFragmentsAllowed;
|
|
1363
1537
|
/**
|
|
1364
1538
|
* The single wording for "you cannot use this field," modeled on SQL Server's posture of
|
|
1365
1539
|
* never disclosing whether an object is missing or merely inaccessible.
|
|
@@ -1376,15 +1550,13 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1376
1550
|
/**
|
|
1377
1551
|
* Strips fields the user cannot read from plain-object result rows.
|
|
1378
1552
|
*
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
* restricted service account has no business holding: the `simple`-path SELECT-list
|
|
1387
|
-
* intersection, and `Load()`'s allowed-column SELECT.
|
|
1553
|
+
* The backstop behind slot segmentation: cache slots are keyed by the reader's permission
|
|
1554
|
+
* class ({@link ComputeRunViewFLSFingerprintKey}) and filled with only that class's columns,
|
|
1555
|
+
* and this still runs on BOTH cache hits and cache misses, checking every row. A slot can hold
|
|
1556
|
+
* more than its class may read (an `entity_object` fill selects every column, and a slot keyed
|
|
1557
|
+
* just before a permission change keeps its old width), and this is what keeps such a slot
|
|
1558
|
+
* from reaching a reader. It reads live metadata, so a tightened permission applies here from
|
|
1559
|
+
* the next metadata refresh.
|
|
1388
1560
|
*
|
|
1389
1561
|
* NEVER applied to `entity_object` results. Those become `BaseEntity` instances whose
|
|
1390
1562
|
* fields round-trip through `GenerateSaveSQL`, which iterates ALL `IsSPParameter` fields
|
|
@@ -1396,13 +1568,30 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1396
1568
|
protected ApplyFieldSecurityProjection<T>(rows: T[], params: RunViewParams, contextUser?: UserInfo): T[];
|
|
1397
1569
|
/**
|
|
1398
1570
|
* Row-loop half of {@link ApplyFieldSecurityProjection}, split out so the policy above reads
|
|
1399
|
-
* as policy. Mirrors {@link ProjectRowsToFields}' matching semantics (trim + lowercase)
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1571
|
+
* as policy. Mirrors {@link ProjectRowsToFields}' matching semantics (trim + lowercase).
|
|
1572
|
+
*
|
|
1573
|
+
* Every row is checked on its own: rows in one result need not share a shape (a slot can mix
|
|
1574
|
+
* rows written by different paths), so no row stands in for the others. A row carrying no
|
|
1575
|
+
* denied key is kept as is, and when none do the input array itself is returned.
|
|
1576
|
+
*
|
|
1577
|
+
* The per-key work (trim, lowercase, set lookup) is done once per key SHAPE rather than once
|
|
1578
|
+
* per row: rows with the same keys in the same order share one {@link RowProjectionPlan}. A
|
|
1579
|
+
* result is almost always a single shape, so a restricted user's 10k-row result pays for one
|
|
1580
|
+
* row's worth of key matching plus a copy per row.
|
|
1402
1581
|
*
|
|
1403
1582
|
* @param deniedLowercase field names to omit, already lowercased
|
|
1404
1583
|
*/
|
|
1405
1584
|
private static omitFieldsFromRows;
|
|
1585
|
+
/** One row of {@link omitFieldsFromRows}: the row itself when it carries no denied key, else a copy without them. */
|
|
1586
|
+
private static omitFieldsFromRow;
|
|
1587
|
+
/**
|
|
1588
|
+
* The plan for a row with exactly these keys, built on first sight of the shape. The last plan
|
|
1589
|
+
* used is tried first; otherwise plans are found by the joined key list. Either way the plan's
|
|
1590
|
+
* own key list is compared with the row's before it is used, so two different shapes can
|
|
1591
|
+
* never share a plan.
|
|
1592
|
+
*/
|
|
1593
|
+
private static rowProjectionPlanFor;
|
|
1594
|
+
private static sameKeys;
|
|
1406
1595
|
/**
|
|
1407
1596
|
* Strips or narrows the `MJ: Record Changes` payload columns a user may not read, using the
|
|
1408
1597
|
* denied set of the entity each row is ABOUT rather than of Record Changes itself.
|
|
@@ -1413,6 +1602,9 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1413
1602
|
* Everything about the per-row denied set, the payload treatment, and the fail-closed decision
|
|
1414
1603
|
* lives in {@link RecordChangeFieldSecurityProjector}; this is only the RunView wiring.
|
|
1415
1604
|
*
|
|
1605
|
+
* A request whose entity cannot be resolved without I/O (only a `ViewID` or `ViewName`) is
|
|
1606
|
+
* projected too, so a saved view over Record Changes is not a way around it.
|
|
1607
|
+
*
|
|
1416
1608
|
* Runs at all four RunView projection points, matching the main projection: both cache-hit
|
|
1417
1609
|
* paths and both cache-miss paths. The cache-hit path is not optional — it is the exact path
|
|
1418
1610
|
* the original cross-user leak runs through, an unrestricted user warming a full-width slot
|
|
@@ -1448,11 +1640,34 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1448
1640
|
/**
|
|
1449
1641
|
* Pre-processing hook for RunViews (batch).
|
|
1450
1642
|
* Handles telemetry, validation, and cache lookup for multiple views.
|
|
1643
|
+
* A view the field-security predicate gate refuses is left out of every later stage and
|
|
1644
|
+
* reported in `refusedResults`; the cache status describes the admitted views only.
|
|
1451
1645
|
* @param params - Array of view parameters
|
|
1452
1646
|
* @param contextUser - Optional user context
|
|
1453
|
-
* @returns Pre-processing result with cache status for each view
|
|
1647
|
+
* @returns Pre-processing result with cache status for each admitted view
|
|
1454
1648
|
*/
|
|
1455
1649
|
protected PreRunViews(params: RunViewParams[], contextUser?: UserInfo): Promise<typeof this._preRunViewsResultType>;
|
|
1650
|
+
/**
|
|
1651
|
+
* Runs each view's PreRunView hooks, replacing `params[i]` with the hooked params, then the
|
|
1652
|
+
* field-security predicate gate — the same contract as the single-view path, except that a
|
|
1653
|
+
* refusal fails only its own view: it becomes that view's `Success: false` result, carrying
|
|
1654
|
+
* the refusal's ambiguous message, so the views batched with it still run. A batch is often
|
|
1655
|
+
* several independent reads (a dashboard's panels), and one unreadable column in one of them
|
|
1656
|
+
* must not blank the rest; the refusal is still reported, at the refused view's index. Any
|
|
1657
|
+
* other error from the gate is thrown and fails the batch.
|
|
1658
|
+
* @returns The refused views' results keyed by batch index, or `undefined` when none was refused.
|
|
1659
|
+
*/
|
|
1660
|
+
private runBatchHooksAndPredicateGate;
|
|
1661
|
+
/** `error` as a failed view result when it is a field-security refusal; otherwise rethrows it. */
|
|
1662
|
+
protected static fieldSecurityRefusalAsResult<T = unknown>(error: unknown): RunViewResult<T>;
|
|
1663
|
+
/**
|
|
1664
|
+
* The cache stage of PreRunViews for the views the predicate gate admitted. An empty batch
|
|
1665
|
+
* (every view refused) is reported as fully cached, so the pipeline returns without a
|
|
1666
|
+
* database call and still ends the batch's telemetry event.
|
|
1667
|
+
*/
|
|
1668
|
+
private lookUpAdmittedViews;
|
|
1669
|
+
/** The server's trusted-cache lookup for a batch: serves hits, and lists the misses to run. */
|
|
1670
|
+
private lookUpBatchCache;
|
|
1456
1671
|
/**
|
|
1457
1672
|
* Prepares smart cache check parameters for RunViews when CacheLocal is enabled.
|
|
1458
1673
|
* Instead of returning cached data immediately, this builds params to send to the server
|
|
@@ -1502,6 +1717,22 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1502
1717
|
* @param preResult - The pre-processing result
|
|
1503
1718
|
* @param contextUser - Optional user context
|
|
1504
1719
|
*/
|
|
1720
|
+
/**
|
|
1721
|
+
* Hook allowing server database providers to substitute pre-decryption (ciphertext-preserving)
|
|
1722
|
+
* rows before storing view results in {@link LocalCacheManager} / Redis, ensuring decrypted
|
|
1723
|
+
* plaintext secrets are never persisted in local or shared caches.
|
|
1724
|
+
*
|
|
1725
|
+
* Client-side providers inherit this default identity implementation.
|
|
1726
|
+
*/
|
|
1727
|
+
protected PrepareRowsForCacheStorage(rows: unknown[], _entityInfo?: EntityInfo): unknown[];
|
|
1728
|
+
/**
|
|
1729
|
+
* Hook allowing server database providers to decrypt ciphertext-at-rest rows retrieved from
|
|
1730
|
+
* {@link LocalCacheManager} for in-process callers (or selectively preserve restricted
|
|
1731
|
+
* ciphertext when `preserveRestrictedApiCiphertext` is `true`).
|
|
1732
|
+
*
|
|
1733
|
+
* Client-side providers inherit this default identity implementation.
|
|
1734
|
+
*/
|
|
1735
|
+
protected MaterializeCachedRowsForCaller(rows: Record<string, unknown>[], _entityInfo?: EntityInfo, _contextUser?: UserInfo, _preserveRestrictedApiCiphertext?: boolean): Promise<Record<string, unknown>[]>;
|
|
1505
1736
|
protected PostRunView(result: RunViewResult, params: RunViewParams, preResult: typeof this._preRunViewResultType, contextUser?: UserInfo): Promise<void>;
|
|
1506
1737
|
/**
|
|
1507
1738
|
* Post-processing hook for RunViews (batch).
|
|
@@ -1512,6 +1743,16 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1512
1743
|
* @param contextUser - Optional user context
|
|
1513
1744
|
*/
|
|
1514
1745
|
protected PostRunViews(results: RunViewResult[], params: RunViewParams[], preResult: typeof this._preRunViewsResultType, contextUser?: UserInfo): Promise<void>;
|
|
1746
|
+
/**
|
|
1747
|
+
* Works out a stored view's property values ({@link RunViewParams.Properties},
|
|
1748
|
+
* {@link RunViewParams.ServerProperties}, and each property's default) before the run's cache
|
|
1749
|
+
* lookup, so the result-cache fingerprint keys on the values the run will actually use. Called
|
|
1750
|
+
* on the run's own params copy, after the PreRunView hooks. Must never throw: a run whose
|
|
1751
|
+
* properties would be refused is left for the provider's run path to refuse with its message.
|
|
1752
|
+
*
|
|
1753
|
+
* Does nothing here. A database provider, which resolves token defaults on the server, overrides it.
|
|
1754
|
+
*/
|
|
1755
|
+
protected PrepareRunViewProperties(_params: RunViewParams, _contextUser?: UserInfo): Promise<void>;
|
|
1515
1756
|
/**
|
|
1516
1757
|
* Runs all registered PreRunView hooks against a single RunViewParams,
|
|
1517
1758
|
* returning the (possibly mutated) params.
|
|
@@ -1711,6 +1952,7 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1711
1952
|
* Resolves the {@link EntityInfo} normalization should read field types from, using only
|
|
1712
1953
|
* synchronously available information on the params.
|
|
1713
1954
|
*/
|
|
1955
|
+
protected resolveEntityForRunViewParams(param: RunViewParams): EntityInfo | undefined;
|
|
1714
1956
|
private resolveEntityForNormalization;
|
|
1715
1957
|
/**
|
|
1716
1958
|
* The row keys each field of the given TSType can appear under, one entry per field.
|
|
@@ -1753,13 +1995,23 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1753
1995
|
protected ReloadMetadata(hardRefresh: boolean, providerToUse?: IMetadataProvider, scopedFirst?: boolean): Promise<boolean>;
|
|
1754
1996
|
/**
|
|
1755
1997
|
* Adopts a metadata snapshot just loaded from the server: swaps it in, records that the
|
|
1756
|
-
* local copy now matches the server's timestamps
|
|
1998
|
+
* local copy now matches the server's timestamps (verified per item against the received
|
|
1999
|
+
* dataset row counts), and persists it to local storage.
|
|
1757
2000
|
*
|
|
1758
2001
|
* The swap goes through UpdateLocalMetadata — a single property assignment, atomic in
|
|
1759
2002
|
* JavaScript, so readers see the old snapshot until the new one is complete — which keeps
|
|
1760
2003
|
* it consistent with LoadLocalMetadataFromStorage() and lets subclasses override it.
|
|
1761
2004
|
*/
|
|
1762
2005
|
private adoptServerMetadata;
|
|
2006
|
+
/**
|
|
2007
|
+
* Verifies that each item in `_latestRemoteMetadataTimestamps` matches the row count actually
|
|
2008
|
+
* received in the loaded `MJ_Metadata` dataset (or `AllMetadata` collections) before advancing
|
|
2009
|
+
* `_latestLocalMetadataTimestamps`. If any item has a mismatched row count (e.g., because a
|
|
2010
|
+
* server cache slot returned stale rows while the SQL status probe reported newer counts),
|
|
2011
|
+
* logs a warning and preserves the unadvanced local timestamp for that item so the next
|
|
2012
|
+
* staleness check (`LocalMetadataObsolete`) detects the discrepancy and self-heals.
|
|
2013
|
+
*/
|
|
2014
|
+
private reconcileAdoptedMetadataTimestamps;
|
|
1763
2015
|
/**
|
|
1764
2016
|
* Decides whether the current staleness can be served by a scoped reload of the saved-query
|
|
1765
2017
|
* family. Compares local and remote timestamps item by item (the same test as
|
|
@@ -1865,14 +2117,30 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1865
2117
|
* customized adoption through CloneAllMetadata. Remove the CloneAllMetadata
|
|
1866
2118
|
* override to activate a CreateSharedMetadataShell override.
|
|
1867
2119
|
*/
|
|
2120
|
+
/**
|
|
2121
|
+
* Builds this instance's AllMetadata as a zero-copy prototype-delegated shell over
|
|
2122
|
+
* another provider's already-loaded metadata (`Object.create(shared)`), keeping
|
|
2123
|
+
* `CurrentUser` as an own property on the shell instance.
|
|
2124
|
+
*
|
|
2125
|
+
* Why zero-copy prototype delegation is safe: the metadata graph (`AllMetadata` and its
|
|
2126
|
+
* arrays) is treated as immutable after `Config`. Refreshes swap the entire `AllMetadata`
|
|
2127
|
+
* reference via `UpdateLocalMetadata` rather than mutating the previous `AllMetadata`
|
|
2128
|
+
* instance in place, so in-flight shells continue reading a consistent snapshot while
|
|
2129
|
+
* avoiding 19 array shallow-copies on every per-request provider creation.
|
|
2130
|
+
*/
|
|
1868
2131
|
protected CreateSharedMetadataShell(shared: AllMetadata): AllMetadata;
|
|
1869
2132
|
/**
|
|
1870
2133
|
* Adopts the global provider's metadata for this instance without reloading it
|
|
1871
2134
|
* from the server: shares the (immutable post-Config) metadata arrays by
|
|
1872
|
-
* reference via {@link CreateSharedMetadataShell} and builds this instance's
|
|
2135
|
+
* reference via {@link CreateSharedMetadataShell} and shares or builds this instance's
|
|
1873
2136
|
* entity lookup maps.
|
|
1874
2137
|
*/
|
|
1875
2138
|
protected CopyMetadataFromGlobalProvider(): boolean;
|
|
2139
|
+
/**
|
|
2140
|
+
* Re-adopts the immutable read-only metadata catalog shell and lookup maps from
|
|
2141
|
+
* `Metadata.Provider` after the global provider completes a metadata refresh.
|
|
2142
|
+
*/
|
|
2143
|
+
SyncMetadataFromGlobalProvider(): boolean;
|
|
1876
2144
|
/**
|
|
1877
2145
|
* Builds dataset filters based on the provider configuration.
|
|
1878
2146
|
* Ensures MJ Core schema is always included and never excluded.
|
|
@@ -1917,7 +2185,7 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
1917
2185
|
* metadata post-processing, replacing repeated O(N*M) filter scans.
|
|
1918
2186
|
*/
|
|
1919
2187
|
private groupByNormalizedUUID;
|
|
1920
|
-
protected PostProcessEntityMetadata(entities: EntityMetadataRow[], fields: EntityFieldMetadataRow[], fieldValues: EntityFieldValueMetadataRow[], permissions: EntityChildMetadataRow[], relationships: EntityChildMetadataRow[], settings: EntityChildMetadataRow[], organicKeys?: OrganicKeyMetadataRow[], organicKeyRelatedEntities?: OrganicKeyRelatedEntityMetadataRow[], fieldPermissions?: EntityFieldPermissionMetadataRow[]): EntityInfo[];
|
|
2188
|
+
protected PostProcessEntityMetadata(entities: EntityMetadataRow[], fields: EntityFieldMetadataRow[], fieldValues: EntityFieldValueMetadataRow[], permissions: EntityChildMetadataRow[], relationships: EntityChildMetadataRow[], settings: EntityChildMetadataRow[], organicKeys?: OrganicKeyMetadataRow[], organicKeyRelatedEntities?: OrganicKeyRelatedEntityMetadataRow[], fieldPermissions?: EntityFieldPermissionMetadataRow[], alternateBaseViews?: EntityChildMetadataRow[]): EntityInfo[];
|
|
1921
2189
|
/**
|
|
1922
2190
|
* Gets the configuration data that was provided to the provider.
|
|
1923
2191
|
* @returns The provider configuration including schema filters
|
|
@@ -2040,6 +2308,27 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
2040
2308
|
* RefreshIfNeeded load outside Config's reload single-flight). For the same reason it gets
|
|
2041
2309
|
* `false`, not the owner's rejection, when the owner's check throws.
|
|
2042
2310
|
* @returns True if refresh is needed, false otherwise
|
|
2311
|
+
*
|
|
2312
|
+
* @remarks
|
|
2313
|
+
* This is a **freshness question, not a load**, so it never throws on an unreachable
|
|
2314
|
+
* server. {@link ReadRemoteMetadataTimestamps} reports whether the server was reached at
|
|
2315
|
+
* all, and when it was NOT the honest answer here depends on whether we hold anything to
|
|
2316
|
+
* serve:
|
|
2317
|
+
*
|
|
2318
|
+
* - **We hold local metadata** → answer `false` ("do not tear this down"). The cached
|
|
2319
|
+
* snapshot may be a few seconds stale; a rejected status query is no reason to throw
|
|
2320
|
+
* it away, and every caller of this method treats `false` as "carry on with what you
|
|
2321
|
+
* have".
|
|
2322
|
+
* - **We hold nothing** → answer `true`, so the caller attempts a real load against the
|
|
2323
|
+
* actual metadata fetch. That load logs its own failure and leaves the graph empty;
|
|
2324
|
+
* `SetupGraphQLClient` turns an empty graph into an error carrying it, while a caller
|
|
2325
|
+
* that only checks {@link Config}'s return value sees `true`.
|
|
2326
|
+
*
|
|
2327
|
+
* Before this, an unreachable status query propagated an exception out of
|
|
2328
|
+
* {@link Config} and the Explorer's single boot catch turned it into a non-retryable
|
|
2329
|
+
* "System Error" — the whole app dead over a freshness check it did not need an answer
|
|
2330
|
+
* to. The two warm callers ({@link backgroundValidateAndRefresh},
|
|
2331
|
+
* {@link preValidateAndRefresh}) already caught it; {@link Config} did not.
|
|
2043
2332
|
*/
|
|
2044
2333
|
CheckToSeeIfRefreshNeeded(providerToUse?: IMetadataProvider, bypassMinCheckInterval?: boolean): Promise<boolean>;
|
|
2045
2334
|
/**
|
|
@@ -2097,9 +2386,11 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
2097
2386
|
* is within the EntityField table and specifically the RelatedEntity and RelatedEntityField columns. In turn, this method uses that metadata and queries the database to determine the dependencies. To get the list of entity dependencies
|
|
2098
2387
|
* you can use the utility method GetEntityDependencies(), which doesn't check for dependencies on a specific record, but rather gets the metadata in one shot that can be used for dependency checking.
|
|
2099
2388
|
* @param entityName the name of the entity to check
|
|
2100
|
-
* @param
|
|
2389
|
+
* @param CompositeKey the values of the primary key of the record to check
|
|
2390
|
+
* @param contextUser optional user context (or options when called with 3 arguments)
|
|
2391
|
+
* @param options optional filtering options for dependency discovery
|
|
2101
2392
|
*/
|
|
2102
|
-
abstract GetRecordDependencies(entityName: string, CompositeKey: CompositeKey, contextUser?: UserInfo): Promise<RecordDependency[]>;
|
|
2393
|
+
abstract GetRecordDependencies(entityName: string, CompositeKey: CompositeKey, contextUser?: UserInfo | GetRecordDependenciesOptions, options?: GetRecordDependenciesOptions): Promise<RecordDependency[]>;
|
|
2103
2394
|
/**
|
|
2104
2395
|
* Returns a list of record IDs that are possible duplicates of the specified record.
|
|
2105
2396
|
*
|
|
@@ -2164,6 +2455,11 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
2164
2455
|
* @returns
|
|
2165
2456
|
*/
|
|
2166
2457
|
IsDatasetCacheUpToDate(datasetName: string, itemFilters?: DatasetItemFilterType[]): Promise<boolean>;
|
|
2458
|
+
/**
|
|
2459
|
+
* Normalizes a dataset `LatestUpdateDate` to a valid `Date`, or `null` when absent or invalid
|
|
2460
|
+
* (for example, when a dataset or dataset-status call fails and returns `LatestUpdateDate: null`).
|
|
2461
|
+
*/
|
|
2462
|
+
private validDatasetDate;
|
|
2167
2463
|
/**
|
|
2168
2464
|
* Compares the per-entity row counts of a cached dataset against the server's status.
|
|
2169
2465
|
*
|
|
@@ -2288,15 +2584,68 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
2288
2584
|
get LatestLocalMetadata(): MetadataInfo[];
|
|
2289
2585
|
/**
|
|
2290
2586
|
* Retrieves the latest metadata update timestamps from the server.
|
|
2291
|
-
* @returns Array of metadata update information
|
|
2587
|
+
* @returns Array of metadata update information, or `undefined` when the server could not
|
|
2588
|
+
* be asked (transport failure, timeout, gateway error) or answered unsuccessfully.
|
|
2589
|
+
*
|
|
2590
|
+
* @remarks
|
|
2591
|
+
* This is the ONE network call behind every staleness check, and it is a question about
|
|
2592
|
+
* freshness — never the metadata itself. A rejected status query therefore returns
|
|
2593
|
+
* `undefined` (an absent answer) rather than propagating: its callers already treat a
|
|
2594
|
+
* falsy result as "could not tell", while an exception out of here travelled unguarded
|
|
2595
|
+
* through {@link RefreshRemoteMetadataTimestamps} → {@link CheckToSeeIfRefreshNeeded} →
|
|
2596
|
+
* {@link Config} and killed the caller's whole bootstrap.
|
|
2597
|
+
*
|
|
2598
|
+
* The failure is logged at error level, not swallowed quietly: "we are running on a
|
|
2599
|
+
* cached snapshot because the server did not answer" is something an operator needs to
|
|
2600
|
+
* see in the console.
|
|
2292
2601
|
*/
|
|
2293
2602
|
protected GetLatestMetadataUpdates(providerToUse?: IMetadataProvider): Promise<MetadataInfo[]>;
|
|
2603
|
+
/**
|
|
2604
|
+
* The metadata-status read, with **why** it failed preserved.
|
|
2605
|
+
*
|
|
2606
|
+
* Two failures look the same to {@link GetLatestMetadataUpdates} — both give `undefined` —
|
|
2607
|
+
* but they call for opposite responses, so callers that can act on the difference read it
|
|
2608
|
+
* here instead:
|
|
2609
|
+
*
|
|
2610
|
+
* - `Reached: false` — the request never got an answer (transport failure, timeout, 504).
|
|
2611
|
+
* Transient. Nothing can be concluded about freshness, and a full metadata load would hit
|
|
2612
|
+
* the same wall, so the right move is to keep serving what we have.
|
|
2613
|
+
* - `Reached: true` with no `Timestamps` — the server answered `Success: false`. A
|
|
2614
|
+
* *permanent* condition (the dataset is missing or misconfigured), not a network blip.
|
|
2615
|
+
* Degrading here would serve a stale cache forever; the historical behaviour of treating
|
|
2616
|
+
* it as "obsolete" and attempting the real load is correct, because `GetDatasetByName`
|
|
2617
|
+
* may well still work.
|
|
2618
|
+
* - A rejection that is NOT a transport failure — an authorization denial ("this API key
|
|
2619
|
+
* requires the dataset:read scope"), a validation rejection, a programming error — is
|
|
2620
|
+
* the server (or our own code) answering, not the wire failing. It propagates exactly
|
|
2621
|
+
* as it did before this method existed. {@link IsTransportError} draws the line. The
|
|
2622
|
+
* integration tier's FLS fixture depends on this: it builds a reader whose scope rule
|
|
2623
|
+
* has not propagated yet and retries `Config()` until the denial stops — a denial
|
|
2624
|
+
* swallowed into `Reached: false` left that reader with an empty snapshot for good.
|
|
2625
|
+
*
|
|
2626
|
+
* Conflating these is how a broken status endpoint — or a refused identity — would become
|
|
2627
|
+
* permanently invisible.
|
|
2628
|
+
*/
|
|
2629
|
+
protected ReadRemoteMetadataTimestamps(providerToUse?: IMetadataProvider): Promise<{
|
|
2630
|
+
Reached: boolean;
|
|
2631
|
+
Timestamps: MetadataInfo[] | undefined;
|
|
2632
|
+
}>;
|
|
2633
|
+
/** Shape a dataset-status answer into the timestamp list, or `undefined` if it failed. */
|
|
2634
|
+
private mapDatasetStatusToTimestamps;
|
|
2294
2635
|
/**
|
|
2295
2636
|
* Refreshes the remote metadata timestamps from the server.
|
|
2296
2637
|
* Updates the internal cache of remote timestamps.
|
|
2297
2638
|
* @returns True if timestamps were successfully refreshed
|
|
2298
2639
|
*/
|
|
2299
2640
|
RefreshRemoteMetadataTimestamps(providerToUse?: IMetadataProvider): Promise<boolean>;
|
|
2641
|
+
/**
|
|
2642
|
+
* Whether the most recent {@link RefreshRemoteMetadataTimestamps} actually REACHED the
|
|
2643
|
+
* server, regardless of whether it came back with usable timestamps.
|
|
2644
|
+
*
|
|
2645
|
+
* Starts `true` so that nothing reads "unreachable" before a read has been attempted.
|
|
2646
|
+
* See {@link ReadRemoteMetadataTimestamps} for why the distinction exists.
|
|
2647
|
+
*/
|
|
2648
|
+
private _lastRemoteTimestampReadReached;
|
|
2300
2649
|
/**
|
|
2301
2650
|
* Checks if local metadata is obsolete compared to remote metadata.
|
|
2302
2651
|
* Compares timestamps and row counts to detect changes.
|
|
@@ -2311,6 +2660,8 @@ export declare abstract class ProviderBase implements IMetadataProvider, IRunVie
|
|
|
2311
2660
|
protected UpdateLocalMetadata(res: AllMetadata): void;
|
|
2312
2661
|
/**
|
|
2313
2662
|
* Rebuilds the O(1) entity lookup Maps from the current AllEntities array.
|
|
2663
|
+
* Allocates fresh Map instances so any per-request provider sharing a previous
|
|
2664
|
+
* snapshot's maps is unaffected by a subsequent refresh.
|
|
2314
2665
|
* Called automatically from UpdateLocalMetadata().
|
|
2315
2666
|
*/
|
|
2316
2667
|
protected RebuildEntityMaps(): void;
|