@memberjunction/core 6.2.0-edge.0 → 6.2.0-edge.2
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/JSONType-interfaces/IEntityConfiguration.d.ts +180 -0
- package/dist/generic/JSONType-interfaces/IEntityConfiguration.d.ts.map +1 -1
- package/dist/generic/JSONType-interfaces/IEntityFieldConfiguration.d.ts +28 -0
- package/dist/generic/JSONType-interfaces/IEntityFieldConfiguration.d.ts.map +1 -1
- package/dist/generic/JSONType-interfaces/IEntityRelationshipConfiguration.d.ts +76 -0
- package/dist/generic/JSONType-interfaces/IEntityRelationshipConfiguration.d.ts.map +1 -1
- package/dist/generic/JSONType-interfaces/IEntitySubtypeSelectorConfig.d.ts +14 -0
- package/dist/generic/JSONType-interfaces/IEntitySubtypeSelectorConfig.d.ts.map +1 -1
- package/dist/generic/QueryCache.d.ts +17 -0
- package/dist/generic/QueryCache.d.ts.map +1 -1
- package/dist/generic/QueryCache.js +25 -5
- package/dist/generic/QueryCache.js.map +1 -1
- package/dist/generic/RegisterForStartup.d.ts +5 -5
- package/dist/generic/RegisterForStartup.js +12 -12
- package/dist/generic/applicationInfo.d.ts +4 -2
- package/dist/generic/applicationInfo.d.ts.map +1 -1
- package/dist/generic/applicationInfo.js +13 -9
- package/dist/generic/applicationInfo.js.map +1 -1
- package/dist/generic/baseEngine.d.ts +9 -1
- package/dist/generic/baseEngine.d.ts.map +1 -1
- package/dist/generic/baseEngine.js +13 -3
- package/dist/generic/baseEngine.js.map +1 -1
- package/dist/generic/baseEngineRegistry.d.ts +22 -9
- package/dist/generic/baseEngineRegistry.d.ts.map +1 -1
- package/dist/generic/baseEngineRegistry.js +43 -25
- package/dist/generic/baseEngineRegistry.js.map +1 -1
- package/dist/generic/baseEntity.d.ts +422 -28
- package/dist/generic/baseEntity.d.ts.map +1 -1
- package/dist/generic/baseEntity.js +930 -202
- package/dist/generic/baseEntity.js.map +1 -1
- package/dist/generic/baseInfo.d.ts +12 -0
- package/dist/generic/baseInfo.d.ts.map +1 -1
- package/dist/generic/baseInfo.js +22 -1
- package/dist/generic/baseInfo.js.map +1 -1
- package/dist/generic/column-descriptors.d.ts +25 -5
- package/dist/generic/column-descriptors.d.ts.map +1 -1
- package/dist/generic/column-descriptors.js +45 -5
- package/dist/generic/column-descriptors.js.map +1 -1
- package/dist/generic/compositeKey.d.ts +1 -1
- package/dist/generic/compositeKey.js +2 -2
- package/dist/generic/data-table.js +2 -2
- package/dist/generic/data-table.js.map +1 -1
- package/dist/generic/databaseProviderBase.d.ts +13 -7
- package/dist/generic/databaseProviderBase.d.ts.map +1 -1
- package/dist/generic/databaseProviderBase.js +20 -11
- package/dist/generic/databaseProviderBase.js.map +1 -1
- package/dist/generic/entityConfiguration.d.ts +1 -0
- package/dist/generic/entityConfiguration.d.ts.map +1 -1
- package/dist/generic/entityConfiguration.js.map +1 -1
- package/dist/generic/entityInfo.d.ts +199 -39
- package/dist/generic/entityInfo.d.ts.map +1 -1
- package/dist/generic/entityInfo.js +351 -78
- package/dist/generic/entityInfo.js.map +1 -1
- package/dist/generic/entitySubtypeResolver.d.ts +51 -5
- package/dist/generic/entitySubtypeResolver.d.ts.map +1 -1
- package/dist/generic/entitySubtypeResolver.js +50 -3
- package/dist/generic/entitySubtypeResolver.js.map +1 -1
- package/dist/generic/filters/compositeFilter.d.ts +19 -19
- package/dist/generic/filters/compositeFilter.js +60 -60
- package/dist/generic/graphqlTypeNames.d.ts +6 -0
- package/dist/generic/graphqlTypeNames.d.ts.map +1 -1
- package/dist/generic/graphqlTypeNames.js +18 -6
- package/dist/generic/graphqlTypeNames.js.map +1 -1
- package/dist/generic/interfaces.d.ts +13 -4
- package/dist/generic/interfaces.d.ts.map +1 -1
- package/dist/generic/interfaces.js +3 -3
- package/dist/generic/interfaces.js.map +1 -1
- package/dist/generic/logging.d.ts +2 -0
- package/dist/generic/logging.d.ts.map +1 -1
- package/dist/generic/logging.js +7 -3
- package/dist/generic/logging.js.map +1 -1
- package/dist/generic/metadata.d.ts +1 -1
- package/dist/generic/metadata.js +3 -3
- package/dist/generic/providerBase.d.ts +89 -8
- package/dist/generic/providerBase.d.ts.map +1 -1
- package/dist/generic/providerBase.js +180 -45
- package/dist/generic/providerBase.js.map +1 -1
- package/dist/generic/queryResultEnricher.d.ts +2 -0
- package/dist/generic/queryResultEnricher.d.ts.map +1 -1
- package/dist/generic/queryResultEnricher.js +5 -1
- package/dist/generic/queryResultEnricher.js.map +1 -1
- package/dist/generic/querySQLFilters.d.ts +4 -0
- package/dist/generic/querySQLFilters.d.ts.map +1 -1
- package/dist/generic/querySQLFilters.js +10 -2
- package/dist/generic/querySQLFilters.js.map +1 -1
- package/dist/generic/relatedRecordCollection.d.ts +2 -0
- package/dist/generic/relatedRecordCollection.d.ts.map +1 -1
- package/dist/generic/relatedRecordCollection.js +5 -1
- package/dist/generic/relatedRecordCollection.js.map +1 -1
- package/dist/generic/remoteEventRow.d.ts +55 -0
- package/dist/generic/remoteEventRow.d.ts.map +1 -0
- package/dist/generic/remoteEventRow.js +110 -0
- package/dist/generic/remoteEventRow.js.map +1 -0
- package/dist/generic/remoteOperationDispatch.d.ts +2 -0
- package/dist/generic/remoteOperationDispatch.d.ts.map +1 -1
- package/dist/generic/remoteOperationDispatch.js +5 -1
- package/dist/generic/remoteOperationDispatch.js.map +1 -1
- package/dist/generic/runQuerySQLFilterImplementations.d.ts +8 -0
- package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -1
- package/dist/generic/runQuerySQLFilterImplementations.js +20 -4
- package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -1
- package/dist/generic/schemaHydration.d.ts +8 -0
- package/dist/generic/schemaHydration.d.ts.map +1 -1
- package/dist/generic/schemaHydration.js +21 -5
- package/dist/generic/schemaHydration.js.map +1 -1
- package/dist/generic/securityInfo.d.ts +11 -9
- package/dist/generic/securityInfo.d.ts.map +1 -1
- package/dist/generic/securityInfo.js +31 -27
- package/dist/generic/securityInfo.js.map +1 -1
- package/dist/generic/telemetryManager.d.ts +16 -0
- package/dist/generic/telemetryManager.d.ts.map +1 -1
- package/dist/generic/telemetryManager.js +52 -20
- package/dist/generic/telemetryManager.js.map +1 -1
- package/dist/generic/transactionGroup.d.ts +1 -1
- package/dist/generic/transactionGroup.js +4 -4
- package/dist/generic/transactionGroup.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/views/viewInfo.d.ts +2 -2
- package/dist/views/viewInfo.js +13 -13
- package/dist/views/viewInfo.js.map +1 -1
- package/package.json +3 -3
|
@@ -9,6 +9,19 @@ import { EmbeddedRecord, type EmbeddedRecordOptions } from './embeddedRecord.js'
|
|
|
9
9
|
import { EntitySavePlan } from './entitySavePlan.js';
|
|
10
10
|
import { Subscription } from 'rxjs';
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
+
/**
|
|
13
|
+
* A field's value and dirty-tracking state, as {@link EntityField.GetState} captures them.
|
|
14
|
+
*/
|
|
15
|
+
export interface EntityFieldState {
|
|
16
|
+
/** The field's value. */
|
|
17
|
+
Value: unknown;
|
|
18
|
+
/** The value the field is compared with to decide whether it's dirty. */
|
|
19
|
+
OldValue: unknown;
|
|
20
|
+
/** Whether the source the record was hydrated from omitted the field. See {@link EntityField.NotLoaded}. */
|
|
21
|
+
NotLoaded: boolean;
|
|
22
|
+
/** Whether the field has had no set since it was created or re-armed. */
|
|
23
|
+
NeverSet: boolean;
|
|
24
|
+
}
|
|
12
25
|
/**
|
|
13
26
|
* Represents a field in an instance of the BaseEntity class. This class is used to store the value of the field, dirty state, as well as other run-time information about the field. The class encapsulates the underlying field metadata and exposes some of the more commonly
|
|
14
27
|
* used properties from the entity field metadata.
|
|
@@ -62,10 +75,10 @@ export declare class EntityField {
|
|
|
62
75
|
};
|
|
63
76
|
};
|
|
64
77
|
private _entityFieldInfo;
|
|
65
|
-
private
|
|
66
|
-
private
|
|
67
|
-
private
|
|
68
|
-
private
|
|
78
|
+
private _oldValue;
|
|
79
|
+
private _value;
|
|
80
|
+
private _neverSet;
|
|
81
|
+
private _notLoaded;
|
|
69
82
|
/**
|
|
70
83
|
* True when the source this entity was hydrated from OMITTED this field's key — most
|
|
71
84
|
* commonly because field-level security stripped it before the payload reached us, but
|
|
@@ -90,7 +103,7 @@ export declare class EntityField {
|
|
|
90
103
|
* clears the flag.
|
|
91
104
|
*/
|
|
92
105
|
MarkNotLoaded(): void;
|
|
93
|
-
private
|
|
106
|
+
private _createSuppressed;
|
|
94
107
|
/**
|
|
95
108
|
* True when field-level security bars this user from supplying the field's value on INSERT,
|
|
96
109
|
* so the save path must omit it and let the column take its database default.
|
|
@@ -189,9 +202,18 @@ export declare class EntityField {
|
|
|
189
202
|
ResetOldValue(): void;
|
|
190
203
|
/**
|
|
191
204
|
* Restores the dirty-tracking baseline to a previously captured value.
|
|
192
|
-
* Used by graph rollback so a retried save still sees the pre-attempt dirty set.
|
|
193
205
|
*/
|
|
194
206
|
RestoreOldValue(value: unknown): void;
|
|
207
|
+
/**
|
|
208
|
+
* Framework-internal: the field's value and dirty-tracking state, so a unit of work that rolls
|
|
209
|
+
* back can put them back with {@link RestoreState}.
|
|
210
|
+
*/
|
|
211
|
+
GetState(): EntityFieldState;
|
|
212
|
+
/**
|
|
213
|
+
* Framework-internal: puts back a state {@link GetState} captured. It writes the state as it was,
|
|
214
|
+
* so the read-only and first-set rules of the {@link Value} setter don't apply.
|
|
215
|
+
*/
|
|
216
|
+
RestoreState(state: EntityFieldState): void;
|
|
195
217
|
/**
|
|
196
218
|
* @deprecated No-op as of the active-status relocation. Active-status (deprecated/disabled)
|
|
197
219
|
* assertions are now enforced at BaseEntity.Get/Set/SetMany — the entry points genuine code uses —
|
|
@@ -228,6 +250,46 @@ export interface RestoreContext {
|
|
|
228
250
|
*/
|
|
229
251
|
Reason: string | null;
|
|
230
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Context describing an in-progress clone operation on a BaseEntity.
|
|
255
|
+
*
|
|
256
|
+
* When set on an entity instance via {@link BaseEntity.SetCloneContext}
|
|
257
|
+
* prior to calling Save(), the data provider will write the resulting
|
|
258
|
+
* RecordChange row with `Source='Clone'` and the structured JSON
|
|
259
|
+
* `ChangeContext` column populated.
|
|
260
|
+
*
|
|
261
|
+
* @see plans/record-cloning/README.md §10.3
|
|
262
|
+
*/
|
|
263
|
+
export interface CloneContext {
|
|
264
|
+
/** ID of the RecordCloneLog row coordinating this clone operation. */
|
|
265
|
+
CloneLogID: string;
|
|
266
|
+
/** Entity name of the record being cloned. */
|
|
267
|
+
SourceEntityName: string;
|
|
268
|
+
/** Compact URL segment of the source key (bare value for single-column keys). */
|
|
269
|
+
SourceRecordID: string;
|
|
270
|
+
/** Entity name of the root record of the clone graph. */
|
|
271
|
+
RootEntityName: string;
|
|
272
|
+
/** Source key of the root record. */
|
|
273
|
+
RootSourceRecordID: string;
|
|
274
|
+
/** Target key of the root record after insertion. */
|
|
275
|
+
RootTargetRecordID: string;
|
|
276
|
+
/** Depth within the record graph (0 for root). */
|
|
277
|
+
Depth: number;
|
|
278
|
+
/** Relationship route traversed to reach this record. */
|
|
279
|
+
Route: 'RootSave' | 'Collection' | 'Embedded' | 'IsAChain' | 'Sidecar';
|
|
280
|
+
/** Kinds and field names only. Values are already in FullRecordJSON. */
|
|
281
|
+
FieldChangeSummary: Array<{
|
|
282
|
+
Kind: string;
|
|
283
|
+
Fields: string[];
|
|
284
|
+
}>;
|
|
285
|
+
/** Optional explanation entered at clone time. */
|
|
286
|
+
Reason?: string | null;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* The `ChangeContext` JSON a clone writes on its Record Change rows (`IRecordChangeContext`,
|
|
290
|
+
* Kind 'Clone'). The one serializer every provider path uses, so the shape can't drift.
|
|
291
|
+
*/
|
|
292
|
+
export declare function SerializeCloneChangeContext(context: CloneContext): string;
|
|
231
293
|
/**
|
|
232
294
|
* Discriminator for the `Source` column of a RecordChange row.
|
|
233
295
|
*
|
|
@@ -236,8 +298,10 @@ export interface RestoreContext {
|
|
|
236
298
|
* (records the platform discovers via direct SQL changes)
|
|
237
299
|
* - `Restore`: produced by a user-initiated restore — paired with
|
|
238
300
|
* `RestoredFromID` and optional `RestoreReason` lineage columns
|
|
301
|
+
* - `Clone`: produced by a record clone operation — paired with
|
|
302
|
+
* structured `ChangeContext` JSON provenance
|
|
239
303
|
*/
|
|
240
|
-
export type RecordChangeSource = 'Internal' | 'External' | 'Restore';
|
|
304
|
+
export type RecordChangeSource = 'Internal' | 'External' | 'Restore' | 'Clone';
|
|
241
305
|
/**
|
|
242
306
|
* Dialect-agnostic payload for a RecordChange row.
|
|
243
307
|
*
|
|
@@ -294,6 +358,11 @@ export interface RecordChangePayload {
|
|
|
294
358
|
* not enter one.
|
|
295
359
|
*/
|
|
296
360
|
restoreReason: string | null;
|
|
361
|
+
/**
|
|
362
|
+
* When `source === 'Clone'`, serialized JSON bag carrying structured provenance
|
|
363
|
+
* (shape = `IRecordChangeContext`). Null otherwise.
|
|
364
|
+
*/
|
|
365
|
+
changeContext: string | null;
|
|
297
366
|
}
|
|
298
367
|
export declare class DataObjectRelatedEntityParam {
|
|
299
368
|
relatedEntityName: string;
|
|
@@ -468,13 +537,16 @@ export declare class BaseEntityEvent {
|
|
|
468
537
|
*/
|
|
469
538
|
provider?: IMetadataProvider;
|
|
470
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* Base class used for all entity objects. This class is abstract and is sub-classes for each particular entity using the CodeGen tool. This class provides the basic functionality for loading, saving, and validating entity objects.
|
|
542
|
+
*/
|
|
471
543
|
export declare abstract class BaseEntity<T = unknown> {
|
|
472
544
|
/**
|
|
473
545
|
* Metadata describing this entity (name, fields, keys, relationships). Populated during
|
|
474
546
|
* `SetEntityName()` from `Metadata.EntityByName` and used as the source of truth for
|
|
475
547
|
* field definitions and schema details throughout this class.
|
|
476
548
|
*/
|
|
477
|
-
private
|
|
549
|
+
private _entityInfo;
|
|
478
550
|
/**
|
|
479
551
|
* Runtime field instances for this record — one `EntityField` per column in `_EntityInfo.Fields`.
|
|
480
552
|
* Each holds the current value, old value, dirty state, and per-field validation.
|
|
@@ -490,7 +562,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
490
562
|
* `BaseEntity` are reserved for paths that have already triggered hydration or paths that
|
|
491
563
|
* deliberately want to inspect hydration state (e.g., `Dirty` getter).
|
|
492
564
|
*/
|
|
493
|
-
private
|
|
565
|
+
private _fields;
|
|
494
566
|
/**
|
|
495
567
|
* Tracks whether `_Fields` has been populated. `false` while in "raw mode" (data accessible
|
|
496
568
|
* via `_raw` but no EntityField instances built yet); flips to `true` after the first call to
|
|
@@ -674,6 +746,17 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
674
746
|
* loaded record. Reset to false on NewRecord() and init().
|
|
675
747
|
*/
|
|
676
748
|
private _childEntityDiscoveryDone;
|
|
749
|
+
/**
|
|
750
|
+
* Set only while this record's parent loads it because the parent's subtype rule named it
|
|
751
|
+
* (see {@link tryLinkHintedChildEntity}); read by {@link InnerLoad}.
|
|
752
|
+
*/
|
|
753
|
+
private _subtypeHintProbe;
|
|
754
|
+
/**
|
|
755
|
+
* Set only while {@link AttachToParent} loads this record as the parent it promotes. Child
|
|
756
|
+
* discovery then doesn't ask the subtype rule: the child row being added doesn't exist yet, so
|
|
757
|
+
* a hint would name it and miss.
|
|
758
|
+
*/
|
|
759
|
+
private _skipSubtypeLoadHint;
|
|
677
760
|
/**
|
|
678
761
|
* For **overlapping** subtype parents (AllowMultipleSubtypes = true), stores
|
|
679
762
|
* the list of child entity type names that have records for this PK.
|
|
@@ -700,6 +783,12 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
700
783
|
* routing through the provider: participants stay ignorant of one another.
|
|
701
784
|
*/
|
|
702
785
|
private _entityTransactionScope;
|
|
786
|
+
/**
|
|
787
|
+
* The unit of work this record is saved or deleted in, while it runs as part of a larger one: an
|
|
788
|
+
* IS-A chain's initiator sets it on each parent for the parent's write, and a graph sets it on
|
|
789
|
+
* each of its records. See {@link UnitOfWork}.
|
|
790
|
+
*/
|
|
791
|
+
private _unitOfWork;
|
|
703
792
|
/**
|
|
704
793
|
* Companions registered on this entity, keyed by {@link EntityCompanion.Name}.
|
|
705
794
|
*
|
|
@@ -773,6 +862,14 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
773
862
|
* This is called by Metadata.GetEntityObject() after constructing the entity.
|
|
774
863
|
*/
|
|
775
864
|
InitializeParentEntity(): Promise<void>;
|
|
865
|
+
/**
|
|
866
|
+
* Points this child's disjoint parent back at this instance (`parent._childEntity = this`).
|
|
867
|
+
*
|
|
868
|
+
* Same gate as {@link InitializeParentEntity}: a parent that allows several subtypes keeps no
|
|
869
|
+
* single child. `NewRecord()` sets `_childEntity` to null, so this has to run AFTER the
|
|
870
|
+
* parent's `NewRecord()` — calling it before is wiped out.
|
|
871
|
+
*/
|
|
872
|
+
private linkParentBackToThisChild;
|
|
776
873
|
/**
|
|
777
874
|
* IS-A PROMOTION (#3825): binds this NEW child record to an EXISTING parent row, so saving it
|
|
778
875
|
* ADDS a subtype to a person/org/product that already exists instead of trying to create a
|
|
@@ -837,10 +934,32 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
837
934
|
* This ensures that Save/Delete operations always delegate to the leaf entity,
|
|
838
935
|
* running the full validation and event chain at every level.
|
|
839
936
|
*
|
|
937
|
+
* For a disjoint parent, the entity's subtype rule is asked first (see
|
|
938
|
+
* {@link resolveSubtypeLoadHint}); when it names a child, that child's load, which
|
|
939
|
+
* happens anyway, checks the answer, and the discovery query runs only on a miss.
|
|
940
|
+
*
|
|
840
941
|
* Must be called AFTER a record is loaded (PK must be available).
|
|
841
942
|
* Skipped for entities that are not parent types or have already been discovered.
|
|
842
943
|
*/
|
|
843
944
|
protected InitializeChildEntity(): Promise<void>;
|
|
945
|
+
/**
|
|
946
|
+
* Finds and links the one child of a loaded disjoint parent.
|
|
947
|
+
*
|
|
948
|
+
* Without a hint this is one discovery query plus the child's load. With a hint from the
|
|
949
|
+
* entity's subtype rule, the child's load checks the hint, and the discovery query runs
|
|
950
|
+
* only when that load comes back empty or wasn't tried.
|
|
951
|
+
*
|
|
952
|
+
* For well-formed data the outcome is the one the discovery query alone would give: a hint
|
|
953
|
+
* changes the number of round trips, not which child is linked or whether the load succeeds.
|
|
954
|
+
* Three benign exceptions:
|
|
955
|
+
* - a failure reading the hinted child's row falls back to the discovery query, so a transient
|
|
956
|
+
* failure now recovers (a lasting one reads the row twice, then fails as before);
|
|
957
|
+
* - when the data breaks the disjoint rule with two child rows, the discovery query's
|
|
958
|
+
* unordered `UNION ALL` links either one, where a hint links the one the rule names;
|
|
959
|
+
* - a provider without `FindISAChildEntity` links nothing without a hint, and the hinted child
|
|
960
|
+
* with one.
|
|
961
|
+
*/
|
|
962
|
+
private initializeDisjointChildEntity;
|
|
844
963
|
/**
|
|
845
964
|
* Uses the provider's FindISAChildEntity method (single UNION ALL query) to
|
|
846
965
|
* determine which child entity type, if any, has a record with our PK value.
|
|
@@ -860,13 +979,127 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
860
979
|
* Creates the child entity instance, wires up the shared instance chain
|
|
861
980
|
* (child._parentEntity = this, this._childEntity = child), loads the
|
|
862
981
|
* child's data, and recursively discovers further children.
|
|
982
|
+
*
|
|
983
|
+
* @returns true when the child's row loaded and the child is linked; false when the load
|
|
984
|
+
* came back empty, in which case the link is undone.
|
|
863
985
|
*/
|
|
864
986
|
private createAndLinkChildEntity;
|
|
987
|
+
/**
|
|
988
|
+
* Creates an unlinked child entity instance through this entity's provider, so the child
|
|
989
|
+
* shares the same connection (correct in multi-provider scenarios — never the global default).
|
|
990
|
+
*/
|
|
991
|
+
private createChildEntityObject;
|
|
992
|
+
/**
|
|
993
|
+
* Links `childEntity` into this entity's chain and loads its row under the shared key.
|
|
994
|
+
*
|
|
995
|
+
* @returns true when the row loaded and the child is linked; false when the load came back
|
|
996
|
+
* empty, in which case the link is undone.
|
|
997
|
+
*/
|
|
998
|
+
private linkAndLoadChildEntity;
|
|
999
|
+
/**
|
|
1000
|
+
* Tries to link the child that the subtype rule named, by loading its row directly. That
|
|
1001
|
+
* load is the check on the hint.
|
|
1002
|
+
*
|
|
1003
|
+
* The hint isn't tried when the child object can't be created or the user can't read that
|
|
1004
|
+
* entity: the discovery-only path decides those cases, so a hint can neither expose a child
|
|
1005
|
+
* nor fail a load that works without it. A failure READING the hinted row is logged and
|
|
1006
|
+
* treated the same way: the discovery path runs, and reads the row again only if the discovery
|
|
1007
|
+
* query finds it. A failure after the row was read (the child's hydration, its eager
|
|
1008
|
+
* companions, its own child discovery) propagates, as it does on the discovery-only path.
|
|
1009
|
+
*
|
|
1010
|
+
* @returns `'Linked'` when the hinted child loaded and is linked, `'NotFound'` when its load
|
|
1011
|
+
* came back empty, and `'NotTried'` when it wasn't loaded or reading its row failed.
|
|
1012
|
+
*/
|
|
1013
|
+
private tryLinkHintedChildEntity;
|
|
1014
|
+
/**
|
|
1015
|
+
* Creates the child object the subtype rule named, or returns null when the user can't read
|
|
1016
|
+
* that entity. A failure to create it is logged and returns null too, so the discovery-only
|
|
1017
|
+
* path decides.
|
|
1018
|
+
*/
|
|
1019
|
+
private createReadableHintedChild;
|
|
1020
|
+
/**
|
|
1021
|
+
* Asks the entity's subtype rule which child a LOADED record has, without running a query.
|
|
1022
|
+
*
|
|
1023
|
+
* - A registered {@link EntitySubtypeResolver} owns the rule. It gives a hint only when its
|
|
1024
|
+
* class overrides {@link EntitySubtypeResolver.ResolveLoadHint}. A resolver that doesn't
|
|
1025
|
+
* gives none, and the `SubtypeSelector` isn't consulted in its place: at create time the
|
|
1026
|
+
* resolver overrides the selector, so the selector may not describe the same rule.
|
|
1027
|
+
* - Otherwise a `SubtypeSelector` that sets `UseForLoadedRecords` is walked through rows that
|
|
1028
|
+
* loaded `BaseEngine` caches already hold. A hop that isn't cached gives no hint, not a query.
|
|
1029
|
+
* - An entity with no rule gets no hint. The single-child fallback of
|
|
1030
|
+
* {@link ResolveSubtypeEntityName} is a default for new records, not a rule about existing ones.
|
|
1031
|
+
* - While {@link AttachToParent} loads this record, no rule is asked: the child row being added
|
|
1032
|
+
* doesn't exist yet.
|
|
1033
|
+
*
|
|
1034
|
+
* An answer of "no subtype" also gives no hint: only the discovery query can tell whether an
|
|
1035
|
+
* older record still has a child row.
|
|
1036
|
+
*
|
|
1037
|
+
* @returns A declared IsA child's entity name, or null when there is no usable hint. Never throws.
|
|
1038
|
+
*/
|
|
1039
|
+
private resolveSubtypeLoadHint;
|
|
1040
|
+
/**
|
|
1041
|
+
* The resolver to ask for load hints for an entity, decided once per registration and cached:
|
|
1042
|
+
* null when the registered class doesn't override {@link EntitySubtypeResolver.ResolveLoadHint},
|
|
1043
|
+
* which is read from the class without constructing it, or when constructing it failed.
|
|
1044
|
+
*/
|
|
1045
|
+
private static loadHintResolverFor;
|
|
1046
|
+
/** Whether a registered resolver class overrides `ResolveLoadHint`, read from its prototype. */
|
|
1047
|
+
private static overridesResolveLoadHint;
|
|
1048
|
+
/**
|
|
1049
|
+
* Constructs the registered resolver once, to ask it for load hints. A failure is logged and
|
|
1050
|
+
* gives null; since the answer is cached, that is once per entity.
|
|
1051
|
+
*/
|
|
1052
|
+
private static constructLoadHintResolver;
|
|
1053
|
+
/**
|
|
1054
|
+
* Asks the resolver for a load hint. A resolver that throws or rejects gives no hint for that
|
|
1055
|
+
* record, and is logged once per entity rather than per record.
|
|
1056
|
+
*/
|
|
1057
|
+
private askResolverForLoadHint;
|
|
1058
|
+
/**
|
|
1059
|
+
* Walks the `SubtypeSelector` path through engine caches only. A path that isn't valid for
|
|
1060
|
+
* this entity's metadata is logged once and gives no hint; the create path throws on it instead.
|
|
1061
|
+
*/
|
|
1062
|
+
private evaluateSelectorForLoadHint;
|
|
1063
|
+
/**
|
|
1064
|
+
* Turns a rule's answer into a declared child's canonical entity name. Empty means no subtype,
|
|
1065
|
+
* which gives no hint. A name that isn't a declared IsA child is logged once and gives no hint.
|
|
1066
|
+
*/
|
|
1067
|
+
private declaredChildForLoadHint;
|
|
1068
|
+
/**
|
|
1069
|
+
* Reports a hint the data didn't bear out: the hinted child's row wasn't there.
|
|
1070
|
+
*
|
|
1071
|
+
* When the discovery query finds no child either, that is a normal state, not an error: core
|
|
1072
|
+
* never creates a subtype row on save, so a typed record can exist without one (saved through
|
|
1073
|
+
* a generic form or an import, or older than its type's subtype). It logs one verbose line per
|
|
1074
|
+
* entity and hinted child. When the discovery query finds a DIFFERENT child, the rule and the
|
|
1075
|
+
* data disagree, and each such load costs an extra round trip until one of them is fixed; that
|
|
1076
|
+
* is logged as an error, once per entity, hinted child and child found.
|
|
1077
|
+
*/
|
|
1078
|
+
private reportSubtypeLoadHintMiss;
|
|
1079
|
+
/** Keys of load-hint messages already logged, so each is reported once rather than per record. */
|
|
1080
|
+
private static _loggedSubtypeLoadHintMessages;
|
|
1081
|
+
/** Runs `log` the first time `key` is seen (case-insensitively), and not again until the caches are cleared. */
|
|
1082
|
+
private static logSubtypeLoadHintOnce;
|
|
1083
|
+
private static errorText;
|
|
865
1084
|
private static _subtypeLookupCache;
|
|
1085
|
+
/** Per entity (lowercased name): the resolver asked for load hints, decided once per registration. */
|
|
1086
|
+
private static _subtypeLoadHintResolvers;
|
|
1087
|
+
/** Indexes over engine-cached arrays, keyed by the live array itself; see {@link findEngineCachedRow}. */
|
|
1088
|
+
private static _engineCachedRowIndexes;
|
|
866
1089
|
/**
|
|
867
|
-
* Clears the static
|
|
1090
|
+
* Clears the static caches IsA subtype resolution keeps: the create path's SubtypeSelector
|
|
1091
|
+
* lookup memo, the per-entity decision about which resolver gives load hints, the indexes over
|
|
1092
|
+
* engine-cached rows, and the record of load-hint messages already logged, so each can be
|
|
1093
|
+
* reported again.
|
|
868
1094
|
*/
|
|
869
1095
|
static ClearSubtypeLookupCache(): void;
|
|
1096
|
+
/**
|
|
1097
|
+
* The declared IsA child entity named `name`, matched the way metadata lookups match names
|
|
1098
|
+
* (trimmed, case-insensitive), or undefined when this entity declares no such child. The one
|
|
1099
|
+
* lookup behind {@link ResolveSubtypeEntityName}, {@link EnsureISAChild} and load hints: the
|
|
1100
|
+
* create path throws on a miss, the load path logs it.
|
|
1101
|
+
*/
|
|
1102
|
+
private findDeclaredChild;
|
|
870
1103
|
/**
|
|
871
1104
|
* Prospective counterpart to FindISAChildEntity.
|
|
872
1105
|
* Evaluates which IsA child subtype entity this record should have based on:
|
|
@@ -875,6 +1108,12 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
875
1108
|
* 3. Unconditional single-child IsA fallback (ChildEntities.length === 1)
|
|
876
1109
|
* 4. Otherwise null (no subtype)
|
|
877
1110
|
*
|
|
1111
|
+
* This is the create-time ladder, and steps 1 and 2 may query. When a record is loaded,
|
|
1112
|
+
* BaseEntity asks a narrower, query-free version of it for a hint instead: the resolver's
|
|
1113
|
+
* `ResolveLoadHint` (not `Resolve`) when its class overrides it, the selector only when it sets
|
|
1114
|
+
* `UseForLoadedRecords` and only through rows that loaded `BaseEngine` caches hold, and never
|
|
1115
|
+
* step 3.
|
|
1116
|
+
*
|
|
878
1117
|
* @see plans/sync-composition-axes.md
|
|
879
1118
|
*/
|
|
880
1119
|
ResolveSubtypeEntityName(): Promise<string | null>;
|
|
@@ -888,9 +1127,60 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
888
1127
|
* @returns The linked child BaseEntity, or null if no subtype applies.
|
|
889
1128
|
*/
|
|
890
1129
|
EnsureISAChild(entityName?: string): Promise<BaseEntity | null>;
|
|
1130
|
+
/**
|
|
1131
|
+
* A new parent's child is new too: there is no row to read, so copy the parent's keys.
|
|
1132
|
+
* A saved parent still reads (promotion's usual answer is "no row"), and that miss is not
|
|
1133
|
+
* an error — the same way a subtype-hint probe treats an empty read (MJ#4859).
|
|
1134
|
+
*/
|
|
1135
|
+
private loadOrMirrorChildRow;
|
|
1136
|
+
/** Loads the child by the shared key. An empty result is an answer, not a logged error. */
|
|
1137
|
+
private loadChildRowQuietly;
|
|
891
1138
|
private mirrorSharedKeysToChild;
|
|
1139
|
+
/**
|
|
1140
|
+
* Walks a `SubtypeSelector` path from this record to the column holding the subtype's entity
|
|
1141
|
+
* name, and returns that column's value, or null when a hop's foreign key is empty, a target
|
|
1142
|
+
* isn't found, or the terminal value is empty.
|
|
1143
|
+
*
|
|
1144
|
+
* @param path The dotted path, e.g. `ProductTypeID.ProductExtensionEntity`.
|
|
1145
|
+
* @param findTarget Finds the record a foreign key points at. Create time passes a finder that
|
|
1146
|
+
* may query; load time passes one that reads engine caches only, so a hop missing from them
|
|
1147
|
+
* ends the walk with null instead of a query.
|
|
1148
|
+
* @throws When the path doesn't fit this entity's metadata (a field isn't found, or a hop isn't
|
|
1149
|
+
* a foreign key).
|
|
1150
|
+
*/
|
|
892
1151
|
private evaluateSubtypeSelectorPath;
|
|
893
1152
|
private getSubtypePathTargetEntity;
|
|
1153
|
+
/**
|
|
1154
|
+
* Finds the record a `SubtypeSelector` hop points at among the entity objects that loaded
|
|
1155
|
+
* `BaseEngine` caches already hold. Never queries, and never reads the create path's memo, whose
|
|
1156
|
+
* entries can outlive a change to the row: engine caches are kept current by entity events.
|
|
1157
|
+
*
|
|
1158
|
+
* `pkValue` is one foreign-key column's value, matched against the first primary key of the
|
|
1159
|
+
* cached rows' entity the way UUIDs compare (trimmed, case-insensitive).
|
|
1160
|
+
*
|
|
1161
|
+
* @returns The cached record, or null when no loaded engine holds it as an entity object.
|
|
1162
|
+
*/
|
|
1163
|
+
private static findSubtypePathTargetInEngineCache;
|
|
1164
|
+
/**
|
|
1165
|
+
* Finds the row whose key is `key` in an engine's live cached array through an index over the
|
|
1166
|
+
* array, not a scan per lookup. Keys are read with `Get()`, which leaves the rows an engine holds
|
|
1167
|
+
* in raw mode unhydrated.
|
|
1168
|
+
*
|
|
1169
|
+
* The array is the engine's own and changes under the index: a refresh replaces it, and a save,
|
|
1170
|
+
* delete or remote invalidation pushes a row, splices one out, or swaps one for a copy with the
|
|
1171
|
+
* same key. So the index is keyed by the array itself, and rebuilt when the array's length or
|
|
1172
|
+
* last element differs from when it was built, which every added or removed row changes. A hit
|
|
1173
|
+
* is checked against the row now at that position, and a row that moved makes the index rebuild
|
|
1174
|
+
* before the answer is trusted. A key that isn't indexed is a miss, which gives no hint on load
|
|
1175
|
+
* and falls back to a query at create time, as for a row no engine caches.
|
|
1176
|
+
*/
|
|
1177
|
+
private static findEngineCachedRow;
|
|
1178
|
+
/** The index over `records`, rebuilt when the array's length or last element changed since it was built. */
|
|
1179
|
+
private static currentEngineCachedRowIndex;
|
|
1180
|
+
/** Indexes `records` by key. Anything that isn't an entity object (a `'simple'` cache holds plain rows) is skipped. */
|
|
1181
|
+
private static buildEngineCachedRowIndex;
|
|
1182
|
+
/** A cached row's key, normalized with `NormalizeUUID`; null for a row that isn't an entity object or has no key value. */
|
|
1183
|
+
private static engineCachedRowKey;
|
|
894
1184
|
private captureChainDirtyState;
|
|
895
1185
|
private restoreChainDirtyState;
|
|
896
1186
|
/**
|
|
@@ -1008,6 +1298,18 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1008
1298
|
* ```
|
|
1009
1299
|
*/
|
|
1010
1300
|
protected DeclareRelatedRecords<TChild extends BaseEntity = BaseEntity>(options: RelatedRecordCollectionOptions): RelatedRecordCollection<TChild>;
|
|
1301
|
+
/**
|
|
1302
|
+
* Dynamically registers a database-sourced child collection companion on this entity instance.
|
|
1303
|
+
* Used by generic composite persistence engines (Record Cloning, Metadata Sync) when a relationship
|
|
1304
|
+
* has no static collection companion declared on the generated entity class.
|
|
1305
|
+
*
|
|
1306
|
+
* Refuses duplicate names or re-registering an already existing companion.
|
|
1307
|
+
*
|
|
1308
|
+
* @typeParam TChild - The child entity type.
|
|
1309
|
+
* @param options - The collection declaration options.
|
|
1310
|
+
* @returns The registered collection companion.
|
|
1311
|
+
*/
|
|
1312
|
+
DeclareRelatedRecordsDynamic<TChild extends BaseEntity = BaseEntity>(options: RelatedRecordCollectionOptions): RelatedRecordCollection<TChild>;
|
|
1011
1313
|
/**
|
|
1012
1314
|
* Declares a 1:1 embedded peer on this entity, joined by an owner-held foreign key,
|
|
1013
1315
|
* and registers it as a companion.
|
|
@@ -1228,20 +1530,33 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1228
1530
|
*/
|
|
1229
1531
|
private deleteAsGraphNode;
|
|
1230
1532
|
/**
|
|
1231
|
-
* Captures
|
|
1232
|
-
*
|
|
1533
|
+
* Captures each record's IS-A chain, from its leaf up to its root, so a unit of work that rolls
|
|
1534
|
+
* back can put the chain back with {@link restoreChains}. A record in more than one chain is
|
|
1535
|
+
* captured once.
|
|
1233
1536
|
*/
|
|
1234
|
-
private
|
|
1537
|
+
private static captureChains;
|
|
1235
1538
|
/**
|
|
1236
|
-
*
|
|
1539
|
+
* Puts back, after a rollback, what the unit of work changed in memory. See {@link restoreSnapshot}.
|
|
1237
1540
|
*/
|
|
1238
|
-
private
|
|
1541
|
+
private static restoreChains;
|
|
1239
1542
|
/**
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1543
|
+
* Puts this record back as a snapshot captured it, after the unit of work that finalized it
|
|
1544
|
+
* rolled back.
|
|
1545
|
+
*
|
|
1546
|
+
* A save's `finalizeSave()` rebuilds the record's fields from what its write returned, marks it
|
|
1547
|
+
* saved and empties its result history. The database undid the write, so the record gets back
|
|
1548
|
+
* its saved and loaded flags, its result history, and each field's value and tracking state. A
|
|
1549
|
+
* field edited since then keeps the edit, and is compared with its captured baseline again, since
|
|
1550
|
+
* that is what the database holds after the rollback. (A delete leaves nothing to put back: a
|
|
1551
|
+
* record deleted inside a unit of work isn't reset until the unit commits.)
|
|
1552
|
+
*
|
|
1553
|
+
* The history matters to the caller: a save records its failure only when nothing else did,
|
|
1554
|
+
* judged by the history's length when it started, which an emptied history would make wrong.
|
|
1555
|
+
*
|
|
1556
|
+
* A record still holding the captured field objects was never finalized, so nothing about it
|
|
1557
|
+
* changed and it is left alone.
|
|
1243
1558
|
*/
|
|
1244
|
-
private
|
|
1559
|
+
private restoreSnapshot;
|
|
1245
1560
|
/**
|
|
1246
1561
|
* Records a graph-level failure on this entity's result history.
|
|
1247
1562
|
*
|
|
@@ -1264,6 +1579,49 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1264
1579
|
* would replace the caller's real error with a secondary one that explains less.
|
|
1265
1580
|
*/
|
|
1266
1581
|
private rollbackEntityTransactionScope;
|
|
1582
|
+
/**
|
|
1583
|
+
* The failure path of a save: rolls back the transaction scope this entity holds, if any, then
|
|
1584
|
+
* settles this save's part in its unit of work (see {@link settleRollback}). `part` is null when
|
|
1585
|
+
* this save took none (see `_innerSave`), and then only the scope is rolled back.
|
|
1586
|
+
*/
|
|
1587
|
+
private rollbackChainSave;
|
|
1588
|
+
/**
|
|
1589
|
+
* Starts a unit of work's part in a {@link UnitOfWork}: joins `enclosing` when the unit runs
|
|
1590
|
+
* inside one, and owns a new one when it doesn't. `snapshots` are the unit's records as they are
|
|
1591
|
+
* before it writes them. They join the unit's, so that the outermost unit can put them back.
|
|
1592
|
+
*/
|
|
1593
|
+
private static beginUnitOfWork;
|
|
1594
|
+
/**
|
|
1595
|
+
* Runs `work` on `record` as part of `unit` (see {@link UnitOfWork}), and gives the record back
|
|
1596
|
+
* the unit it was in before, however `work` ends. Used for an IS-A parent's delete, which runs
|
|
1597
|
+
* inside its child's chain, along with the graph of its companions if it has any.
|
|
1598
|
+
*/
|
|
1599
|
+
private static inUnitOfWork;
|
|
1600
|
+
/**
|
|
1601
|
+
* After a unit of work rolls back: puts its records back as they were before it wrote them, and
|
|
1602
|
+
* drops the deletes the rollback undid, so that nothing resets their records. The owner does this
|
|
1603
|
+
* for everything the unit and the units nested in it wrote. A nested part does it for its own
|
|
1604
|
+
* records only; when the owner then rolls back too, restoring them again changes nothing.
|
|
1605
|
+
*/
|
|
1606
|
+
private static settleRollback;
|
|
1607
|
+
/**
|
|
1608
|
+
* After a unit of work commits: its owner resets the records it deleted. A nested part leaves
|
|
1609
|
+
* them to the owner, since the enclosing unit can still roll back.
|
|
1610
|
+
*/
|
|
1611
|
+
private static settleCommit;
|
|
1612
|
+
/**
|
|
1613
|
+
* Resets the records a unit of work deleted, once the unit has committed, as each record's own
|
|
1614
|
+
* `Delete()` does when no unit of work is involved. See {@link UnitOfWork}.
|
|
1615
|
+
*
|
|
1616
|
+
* Last-deleted first, skipping a record that no longer reads as saved. `NewRecord()` on a record
|
|
1617
|
+
* also resets every IS-A level above it, and relinks them. A chain's initiator records its delete
|
|
1618
|
+
* after its parents do, so it's reset first, and its parents with it. Resetting a parent again
|
|
1619
|
+
* after that would unlink it from its child and give it a key the child doesn't share.
|
|
1620
|
+
*
|
|
1621
|
+
* The unit has committed, so a reset that throws is logged and the rest still run: the deletes
|
|
1622
|
+
* stand whatever happens here.
|
|
1623
|
+
*/
|
|
1624
|
+
private static resetDeletedRecords;
|
|
1267
1625
|
/**
|
|
1268
1626
|
* Returns this provider to be used for a given instance of a BaseEntity derived subclass. If the provider is not set, the BaseEntity.Provider is returned.
|
|
1269
1627
|
*/
|
|
@@ -1505,7 +1863,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1505
1863
|
* Callers should gate this behind `EntityInfo.HasInactiveFields` so the common all-Active entity
|
|
1506
1864
|
* skips the field lookup entirely.
|
|
1507
1865
|
*/
|
|
1508
|
-
private
|
|
1866
|
+
private assertFieldActiveStatus;
|
|
1509
1867
|
/**
|
|
1510
1868
|
* Field-level security choke point for the strongly-typed accessor path. Throws when the
|
|
1511
1869
|
* acting user may not READ the field.
|
|
@@ -1527,12 +1885,12 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1527
1885
|
* build) reads `EntityField.Value` directly and never routes through here — that exemption
|
|
1528
1886
|
* is load-bearing, not an oversight. Do not "fix" it.
|
|
1529
1887
|
*/
|
|
1530
|
-
private
|
|
1888
|
+
private assertFieldReadable;
|
|
1531
1889
|
/**
|
|
1532
1890
|
* Internal helper that sets a field value directly on THIS entity's own Fields array
|
|
1533
1891
|
* without IS-A routing. Used by Set() for own-fields and for mirroring parent field values.
|
|
1534
1892
|
*/
|
|
1535
|
-
private
|
|
1893
|
+
private setLocal;
|
|
1536
1894
|
/**
|
|
1537
1895
|
* Returns the value of the field with the given name. If the field is a date, and the value is a string, it will be converted to a date object.
|
|
1538
1896
|
*
|
|
@@ -1565,7 +1923,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1565
1923
|
* a saved/loaded record. This enables entities populated via SetMany (e.g., IS-A parent
|
|
1566
1924
|
* entities) to correctly recognize themselves as existing records.
|
|
1567
1925
|
*/
|
|
1568
|
-
private
|
|
1926
|
+
private updateSavedStateFromPrimaryKeys;
|
|
1569
1927
|
/**
|
|
1570
1928
|
* NOTE: Do not call this method directly. Use the {@link To} method instead
|
|
1571
1929
|
*
|
|
@@ -1703,6 +2061,34 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1703
2061
|
* accidentally tagged as a restore.
|
|
1704
2062
|
*/
|
|
1705
2063
|
ClearRestoreContext(): void;
|
|
2064
|
+
private _cloneContext;
|
|
2065
|
+
/**
|
|
2066
|
+
* Returns the active clone context for the next save, if any.
|
|
2067
|
+
*
|
|
2068
|
+
* Read by the data provider when generating the RecordChange SQL: when
|
|
2069
|
+
* non-null, the resulting RecordChange row is written with
|
|
2070
|
+
* `Source='Clone'` and `ChangeContext` populated with structured JSON provenance.
|
|
2071
|
+
* Returns null for ordinary saves.
|
|
2072
|
+
*/
|
|
2073
|
+
get CloneContext(): CloneContext | null;
|
|
2074
|
+
/**
|
|
2075
|
+
* Marks the next Save() as part of a record clone operation.
|
|
2076
|
+
*
|
|
2077
|
+
* The provider will write a new RecordChange entry with `Source='Clone'`
|
|
2078
|
+
* and `ChangeContext` populated with structured JSON provenance.
|
|
2079
|
+
*
|
|
2080
|
+
* The context persists on the entity until either (a) overwritten by a
|
|
2081
|
+
* subsequent SetCloneContext() call or (b) explicitly cleared via
|
|
2082
|
+
* ClearCloneContext(). It is NOT auto-cleared inside Save() because
|
|
2083
|
+
* TransactionGroup execution is deferred.
|
|
2084
|
+
*
|
|
2085
|
+
* @param context Structured clone context. Throws if missing required fields.
|
|
2086
|
+
*/
|
|
2087
|
+
SetCloneContext(context: CloneContext): void;
|
|
2088
|
+
/**
|
|
2089
|
+
* Clears any pending clone context. Safe to call when no context is set.
|
|
2090
|
+
*/
|
|
2091
|
+
ClearCloneContext(): void;
|
|
1706
2092
|
private _pendingSave$;
|
|
1707
2093
|
/**
|
|
1708
2094
|
* Saves the current state of the object to the database. Uses the active provider to handle the actual saving of the record.
|
|
@@ -1751,12 +2137,12 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1751
2137
|
* @param options
|
|
1752
2138
|
* @returns
|
|
1753
2139
|
*/
|
|
1754
|
-
private
|
|
2140
|
+
private _innerSave;
|
|
1755
2141
|
/**
|
|
1756
2142
|
* Runs all registered PreSave hooks. If any hook returns false or a string
|
|
1757
2143
|
* (error message), the save is rejected by throwing an Error.
|
|
1758
2144
|
*/
|
|
1759
|
-
private
|
|
2145
|
+
private runPreSaveHooks;
|
|
1760
2146
|
/**
|
|
1761
2147
|
* Determines whether the parent entity should be deleted after this child entity
|
|
1762
2148
|
* has been deleted. For overlapping subtype parents (AllowMultipleSubtypes = true),
|
|
@@ -1773,7 +2159,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1773
2159
|
* Caches the entity record name in the provider's EntityRecordNameCache for faster lookups.
|
|
1774
2160
|
* Called automatically after successful Load(), LoadFromData(), and Save() operations.
|
|
1775
2161
|
*/
|
|
1776
|
-
private
|
|
2162
|
+
private cacheRecordName;
|
|
1777
2163
|
/**
|
|
1778
2164
|
* Utility method that returns true if the given permission being checked is enabled for the current user, and false if not.
|
|
1779
2165
|
* @param type
|
|
@@ -1878,6 +2264,14 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
1878
2264
|
* @returns true if success, false otherwise
|
|
1879
2265
|
*/
|
|
1880
2266
|
InnerLoad(CompositeKey: CompositeKey, EntityRelationshipsToLoad?: string[]): Promise<boolean>;
|
|
2267
|
+
/**
|
|
2268
|
+
* The provider's read of the row {@link InnerLoad} loads. While this record is a subtype-hint
|
|
2269
|
+
* probe, a throw from the read is recorded on the probe before it propagates, so the parent
|
|
2270
|
+
* that asked can tell it apart from a failure after the row loaded.
|
|
2271
|
+
*/
|
|
2272
|
+
private readRowForLoad;
|
|
2273
|
+
/** The error {@link InnerLoad} logs when the provider finds no row for the key. */
|
|
2274
|
+
private static logLoadFoundNoRow;
|
|
1881
2275
|
/**
|
|
1882
2276
|
* Re-fetches the current record from the database using its existing primary key, replacing all in-memory field values
|
|
1883
2277
|
* with the latest data from the database. This is useful when you know (or suspect) the record has been modified externally
|
|
@@ -2040,7 +2434,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
2040
2434
|
* @param options
|
|
2041
2435
|
* @returns
|
|
2042
2436
|
*/
|
|
2043
|
-
private
|
|
2437
|
+
private _innerDelete;
|
|
2044
2438
|
/**
|
|
2045
2439
|
* Checks if this entity has any child records in IS-A child entity tables.
|
|
2046
2440
|
* Used for parent delete protection — a parent record cannot be deleted
|
|
@@ -2080,7 +2474,7 @@ export declare abstract class BaseEntity<T = unknown> {
|
|
|
2080
2474
|
* Internal recursive helper for leaf entity resolution.
|
|
2081
2475
|
* Walks down the child hierarchy until no more children are found.
|
|
2082
2476
|
*/
|
|
2083
|
-
private static
|
|
2477
|
+
private static resolveLeafEntityRecursive;
|
|
2084
2478
|
/**
|
|
2085
2479
|
* Enforces disjoint subtype constraint during IS-A child entity creation.
|
|
2086
2480
|
* A parent record can only be ONE child type at a time. Checks all sibling
|