@memberjunction/record-cloning 0.0.1-seed.1 → 6.2.0-edge.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -0
- package/README.md +98 -3
- package/dist/CloneAuthorization.d.ts +50 -0
- package/dist/CloneAuthorization.d.ts.map +1 -0
- package/dist/CloneAuthorization.js +75 -0
- package/dist/CloneAuthorization.js.map +1 -0
- package/dist/CloneExecutor.d.ts +50 -0
- package/dist/CloneExecutor.d.ts.map +1 -0
- package/dist/CloneExecutor.js +350 -0
- package/dist/CloneExecutor.js.map +1 -0
- package/dist/CloneKeys.d.ts +65 -0
- package/dist/CloneKeys.d.ts.map +1 -0
- package/dist/CloneKeys.js +118 -0
- package/dist/CloneKeys.js.map +1 -0
- package/dist/CloneMaterializer.d.ts +52 -0
- package/dist/CloneMaterializer.d.ts.map +1 -0
- package/dist/CloneMaterializer.js +267 -0
- package/dist/CloneMaterializer.js.map +1 -0
- package/dist/ClonePlanHash.d.ts +11 -0
- package/dist/ClonePlanHash.d.ts.map +1 -0
- package/dist/ClonePlanHash.js +16 -0
- package/dist/ClonePlanHash.js.map +1 -0
- package/dist/ClonePlanner.d.ts +33 -0
- package/dist/ClonePlanner.d.ts.map +1 -0
- package/dist/ClonePlanner.js +870 -0
- package/dist/ClonePlanner.js.map +1 -0
- package/dist/CloneRecordProcessor.d.ts +28 -0
- package/dist/CloneRecordProcessor.d.ts.map +1 -0
- package/dist/CloneRecordProcessor.js +101 -0
- package/dist/CloneRecordProcessor.js.map +1 -0
- package/dist/RecordCloneEngine.d.ts +35 -0
- package/dist/RecordCloneEngine.d.ts.map +1 -0
- package/dist/RecordCloneEngine.js +60 -0
- package/dist/RecordCloneEngine.js.map +1 -0
- package/dist/RecordCloningStartup.d.ts +14 -0
- package/dist/RecordCloningStartup.d.ts.map +1 -0
- package/dist/RecordCloningStartup.js +32 -0
- package/dist/RecordCloningStartup.js.map +1 -0
- package/dist/__tests__/helpers/cloneAuthorizations.d.ts +7 -0
- package/dist/__tests__/helpers/cloneAuthorizations.d.ts.map +1 -0
- package/dist/__tests__/helpers/cloneAuthorizations.js +17 -0
- package/dist/__tests__/helpers/cloneAuthorizations.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/operations.d.ts +64 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +390 -0
- package/dist/operations.js.map +1 -0
- package/package.json +29 -5
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file CloneMaterializer.ts
|
|
3
|
+
* Builds the in-memory entity graph for record cloning.
|
|
4
|
+
* Orchestrates collection routing (declared vs dynamic via DeclareRelatedRecordsDynamic),
|
|
5
|
+
* builds each row from NewRecord() plus the plan's field values, re-stamps join fields,
|
|
6
|
+
* and handles polymorphic IS-A child additions.
|
|
7
|
+
* @see plans/record-cloning/README.md §6, §13.1
|
|
8
|
+
*/
|
|
9
|
+
import { LogError, Metadata, RelatedRecordCollection, } from '@memberjunction/core';
|
|
10
|
+
import { SingleKeyField, ToCompositeKey, ToRecordKeyString } from './CloneKeys.js';
|
|
11
|
+
/** Writes every column of a planned target key (single or composite) onto the new row. */
|
|
12
|
+
function applyTargetKey(entity, targetKey) {
|
|
13
|
+
if (!targetKey)
|
|
14
|
+
return; // server-assigned key
|
|
15
|
+
const ck = ToCompositeKey(entity.EntityInfo, targetKey);
|
|
16
|
+
for (const pair of ck.KeyValuePairs) {
|
|
17
|
+
// An empty column points at a parent whose key the database assigns; the save fills it in.
|
|
18
|
+
if (pair.Value === null || pair.Value === undefined || pair.Value === '')
|
|
19
|
+
continue;
|
|
20
|
+
entity.Set(pair.FieldName, pair.Value);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class CloneMaterializer {
|
|
24
|
+
constructor(provider) {
|
|
25
|
+
this._provider = provider;
|
|
26
|
+
}
|
|
27
|
+
get Provider() {
|
|
28
|
+
return this._provider ?? Metadata.Provider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Materializes a ClonePlan into memory.
|
|
32
|
+
*/
|
|
33
|
+
async Materialize(plan, contextUser) {
|
|
34
|
+
const md = this.Provider;
|
|
35
|
+
const stagedEntities = new Map();
|
|
36
|
+
const sidecarEntities = [];
|
|
37
|
+
const prerequisiteEntities = [];
|
|
38
|
+
// 1. Build and Initialize Root
|
|
39
|
+
const rootPlanNode = plan.Nodes.find((n) => n.Depth === 0);
|
|
40
|
+
if (!rootPlanNode) {
|
|
41
|
+
throw new Error(`Plan contains no root node (Depth === 0).`);
|
|
42
|
+
}
|
|
43
|
+
const rootEntity = await md.GetEntityObject(rootPlanNode.EntityName, contextUser);
|
|
44
|
+
if (!rootEntity) {
|
|
45
|
+
throw new Error(`Failed to instantiate entity object for root '${rootPlanNode.EntityName}'.`);
|
|
46
|
+
}
|
|
47
|
+
rootEntity.NewRecord();
|
|
48
|
+
// The plan's field values are the whole row: excluded and denied fields keep the column default.
|
|
49
|
+
this.applyFieldChanges(rootEntity, rootPlanNode);
|
|
50
|
+
// Assign the planned target key (minted UUID or derived composite; none when server-assigned)
|
|
51
|
+
applyTargetKey(rootEntity, rootPlanNode.TargetKey);
|
|
52
|
+
const rootNodeKey = rootPlanNode.NodeKey ?? rootPlanNode.Key;
|
|
53
|
+
stagedEntities.set(rootNodeKey, rootEntity);
|
|
54
|
+
// Rows that point at another new row through a column other than their join field (a step
|
|
55
|
+
// path's DestinationStepID, a step's SubAgentID) can't save inside the root's graph save,
|
|
56
|
+
// which saves each row's children before its next sibling: the row they point at may not
|
|
57
|
+
// exist yet. They become sidecars, saved after the graph in dependency order.
|
|
58
|
+
const deferred = CloneMaterializer.rowsToDefer(plan);
|
|
59
|
+
const sidecarKeys = new Map();
|
|
60
|
+
// 2. Build Children by Depth (Depth 1, 2, ...)
|
|
61
|
+
const maxDepth = Math.max(...plan.Nodes.map((n) => n.Depth));
|
|
62
|
+
for (let d = 1; d <= maxDepth; d++) {
|
|
63
|
+
const nodesAtDepth = plan.Nodes.filter((n) => n.Depth === d && n.Action === 'Create');
|
|
64
|
+
for (const childNode of nodesAtDepth) {
|
|
65
|
+
const childNodeKey = childNode.NodeKey ?? childNode.Key;
|
|
66
|
+
// Find discovering edge pointing to this child
|
|
67
|
+
const edge = plan.Edges.find((e) => e.ToKey === childNodeKey && e.Policy === 'Deep');
|
|
68
|
+
if (!edge) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const parentEntity = stagedEntities.get(edge.FromKey);
|
|
72
|
+
if (!parentEntity) {
|
|
73
|
+
throw new Error(`Parent entity not found in staged graph for edge '${edge.FromKey}' -> '${childNodeKey}'.`);
|
|
74
|
+
}
|
|
75
|
+
// Determine or establish collection companion
|
|
76
|
+
let childEntity;
|
|
77
|
+
if (edge.Kind === 'ForwardFK') {
|
|
78
|
+
// ForwardFK targets are prerequisite entities that must exist before the parent entity can reference them
|
|
79
|
+
childEntity = await md.GetEntityObject(childNode.EntityName, contextUser);
|
|
80
|
+
childEntity.NewRecord();
|
|
81
|
+
prerequisiteEntities.push(childEntity);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const collection = deferred.has(childNodeKey)
|
|
85
|
+
? null
|
|
86
|
+
: this.resolveOrCreateCollection(parentEntity, childNode.EntityName, edge.JoinField, edge.RelationshipID);
|
|
87
|
+
if (collection) {
|
|
88
|
+
childEntity = await collection.Create();
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Sidecar route: a deferred row, or one whose collection can't be declared
|
|
92
|
+
childEntity = await md.GetEntityObject(childNode.EntityName, contextUser);
|
|
93
|
+
childEntity.NewRecord();
|
|
94
|
+
sidecarEntities.push(childEntity);
|
|
95
|
+
sidecarKeys.set(childEntity, childNodeKey);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// The plan's field values are the whole row: excluded and denied fields keep the column default.
|
|
99
|
+
this.applyFieldChanges(childEntity, childNode);
|
|
100
|
+
// Assign the planned target key (minted UUID or derived composite; none when server-assigned)
|
|
101
|
+
applyTargetKey(childEntity, childNode.TargetKey);
|
|
102
|
+
// CRITICAL RULE (§6.7): Re-set the join field after the planned values.
|
|
103
|
+
// Foreign keys reference a single-column key, so both sides of the join use that column.
|
|
104
|
+
if (edge.Kind === 'ForwardFK') {
|
|
105
|
+
// In a ForwardFK, parentEntity owns the FK pointing to childEntity
|
|
106
|
+
const childKeyField = SingleKeyField(childEntity.EntityInfo, 'Pointing a row at its cloned prerequisite');
|
|
107
|
+
parentEntity.Set(edge.JoinField, childEntity.Get(childKeyField));
|
|
108
|
+
}
|
|
109
|
+
else if (edge.Kind === 'SoftLink') {
|
|
110
|
+
// Polymorphic EntityID/RecordID rows store the parent's record-id string, which
|
|
111
|
+
// works for a composite parent key too.
|
|
112
|
+
childEntity.Set(edge.JoinField, ToRecordKeyString(parentEntity.PrimaryKey));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const parentKeyField = SingleKeyField(parentEntity.EntityInfo, 'Joining a cloned child to its parent');
|
|
116
|
+
childEntity.Set(edge.JoinField, parentEntity.Get(parentKeyField));
|
|
117
|
+
}
|
|
118
|
+
stagedEntities.set(childNodeKey, childEntity);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
RootEntity: rootEntity,
|
|
123
|
+
StagedEntities: stagedEntities,
|
|
124
|
+
SidecarEntities: CloneMaterializer.orderSidecars(plan, sidecarEntities, sidecarKeys),
|
|
125
|
+
DeferredNodeKeys: deferred,
|
|
126
|
+
PrerequisiteEntities: prerequisiteEntities,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create rows with a remapped column, other than the join field to their parent, whose new
|
|
131
|
+
* value is another new row's key: they must save after that row, not inside the graph save.
|
|
132
|
+
*/
|
|
133
|
+
static rowsToDefer(plan) {
|
|
134
|
+
const newRowByKey = CloneMaterializer.newRowsByTargetKey(plan);
|
|
135
|
+
const deferred = new Set();
|
|
136
|
+
for (const node of plan.Nodes) {
|
|
137
|
+
if (node.Depth === 0 || node.Action !== 'Create')
|
|
138
|
+
continue;
|
|
139
|
+
const nodeKey = node.NodeKey ?? node.Key;
|
|
140
|
+
const edge = plan.Edges.find((e) => e.ToKey === nodeKey && e.Policy === 'Deep');
|
|
141
|
+
if (!edge || edge.Kind === 'ForwardFK')
|
|
142
|
+
continue;
|
|
143
|
+
const pointsAtNewRow = CloneMaterializer.remappedTargets(node, edge.JoinField, newRowByKey).some((target) => target !== nodeKey);
|
|
144
|
+
if (pointsAtNewRow)
|
|
145
|
+
deferred.add(nodeKey);
|
|
146
|
+
}
|
|
147
|
+
return deferred;
|
|
148
|
+
}
|
|
149
|
+
/** New rows by their planned key, lower-cased, for matching a remapped column's value. */
|
|
150
|
+
static newRowsByTargetKey(plan) {
|
|
151
|
+
const byKey = new Map();
|
|
152
|
+
for (const node of plan.Nodes) {
|
|
153
|
+
if (node.Action !== 'Create')
|
|
154
|
+
continue;
|
|
155
|
+
const key = ToRecordKeyString(node.TargetKey);
|
|
156
|
+
if (key)
|
|
157
|
+
byKey.set(key.toLowerCase(), node.NodeKey ?? node.Key);
|
|
158
|
+
}
|
|
159
|
+
return byKey;
|
|
160
|
+
}
|
|
161
|
+
/** Plan nodes a row points at through remapped columns other than `joinField`. */
|
|
162
|
+
static remappedTargets(node, joinField, newRowByKey) {
|
|
163
|
+
const targets = [];
|
|
164
|
+
for (const change of node.FieldChanges) {
|
|
165
|
+
if (change.Kind !== 'Remap' || change.Field.toLowerCase() === joinField.toLowerCase())
|
|
166
|
+
continue;
|
|
167
|
+
if (typeof change.NewValue !== 'string')
|
|
168
|
+
continue;
|
|
169
|
+
const target = newRowByKey.get(change.NewValue.toLowerCase());
|
|
170
|
+
if (target)
|
|
171
|
+
targets.push(target);
|
|
172
|
+
}
|
|
173
|
+
return targets;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Sidecars in an order where each saves after the sidecars it depends on: its parent, when
|
|
177
|
+
* the parent is a sidecar too, and the new rows its remapped columns point at. Rows saved in
|
|
178
|
+
* the graph save come first anyway. Stable: independent sidecars keep their planned order.
|
|
179
|
+
*/
|
|
180
|
+
static orderSidecars(plan, sidecars, keys) {
|
|
181
|
+
if (sidecars.length < 2)
|
|
182
|
+
return sidecars;
|
|
183
|
+
const newRowByKey = CloneMaterializer.newRowsByTargetKey(plan);
|
|
184
|
+
const sidecarKeys = new Set(keys.values());
|
|
185
|
+
const dependsOn = new Map();
|
|
186
|
+
for (const [, nodeKey] of keys) {
|
|
187
|
+
const node = plan.Nodes.find((n) => (n.NodeKey ?? n.Key) === nodeKey);
|
|
188
|
+
const edge = plan.Edges.find((e) => e.ToKey === nodeKey && e.Policy === 'Deep');
|
|
189
|
+
if (!node || !edge)
|
|
190
|
+
continue;
|
|
191
|
+
const deps = [edge.FromKey, ...CloneMaterializer.remappedTargets(node, edge.JoinField, newRowByKey)]
|
|
192
|
+
.filter((k) => k !== nodeKey && sidecarKeys.has(k));
|
|
193
|
+
dependsOn.set(nodeKey, deps);
|
|
194
|
+
}
|
|
195
|
+
const ordered = [];
|
|
196
|
+
const done = new Set();
|
|
197
|
+
const visiting = new Set();
|
|
198
|
+
const byKey = new Map([...keys].map(([entity, key]) => [key, entity]));
|
|
199
|
+
const visit = (key) => {
|
|
200
|
+
if (done.has(key) || visiting.has(key))
|
|
201
|
+
return; // a cycle can't all be inserted anyway; keep the planned order
|
|
202
|
+
visiting.add(key);
|
|
203
|
+
for (const dep of dependsOn.get(key) ?? [])
|
|
204
|
+
visit(dep);
|
|
205
|
+
visiting.delete(key);
|
|
206
|
+
done.add(key);
|
|
207
|
+
const entity = byKey.get(key);
|
|
208
|
+
if (entity)
|
|
209
|
+
ordered.push(entity);
|
|
210
|
+
};
|
|
211
|
+
for (const entity of sidecars) {
|
|
212
|
+
const key = keys.get(entity);
|
|
213
|
+
if (key)
|
|
214
|
+
visit(key);
|
|
215
|
+
}
|
|
216
|
+
return ordered;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Resolves an existing writable collection or declares a dynamic one on the parent entity.
|
|
220
|
+
*/
|
|
221
|
+
resolveOrCreateCollection(parent, childEntityName, joinField, relationshipId) {
|
|
222
|
+
// 1. Check if parent already has a declared writable collection for this child
|
|
223
|
+
if (parent.HasCompanions) {
|
|
224
|
+
for (const companion of parent.Companions) {
|
|
225
|
+
if (companion instanceof RelatedRecordCollection) {
|
|
226
|
+
if (companion.RelatedEntityName.toLowerCase() === childEntityName.toLowerCase() &&
|
|
227
|
+
companion.RelatedEntityJoinField.toLowerCase() === joinField.toLowerCase() &&
|
|
228
|
+
!companion.IsReadOnly) {
|
|
229
|
+
return companion;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// 2. Use DeclareRelatedRecordsDynamic to declare runtime collection companion
|
|
235
|
+
const dynamicCollectionName = `_mj_clone_${childEntityName.replace(/[^a-zA-Z0-9_]/g, '_')}_${joinField}`;
|
|
236
|
+
try {
|
|
237
|
+
return parent.DeclareRelatedRecordsDynamic({
|
|
238
|
+
Name: dynamicCollectionName,
|
|
239
|
+
RelatedEntity: childEntityName,
|
|
240
|
+
RelatedEntityJoinField: joinField,
|
|
241
|
+
Source: 'database',
|
|
242
|
+
ReadOnly: false,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
// The row still saves, but after the parent's transaction step rather than inside its
|
|
247
|
+
// save (the sidecar route). Say so: it is the line between the two routes.
|
|
248
|
+
LogError(`[RecordCloning] Could not declare ${childEntityName} rows as a collection of ${parent.EntityInfo?.Name ?? 'the parent'}; saving them as sidecars: ${err instanceof Error ? err.message : String(err)}`);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Writes the plan's field values in pipeline order, so later stages (reset, rename, remap,
|
|
254
|
+
* prompt) win over the copied value. Fields the plan excludes are never set.
|
|
255
|
+
*/
|
|
256
|
+
applyFieldChanges(entity, planNode) {
|
|
257
|
+
for (const change of planNode.FieldChanges) {
|
|
258
|
+
if (change.Kind === 'Excluded' || change.Kind === 'NotWritable' || change.Kind === 'DeniedRead' || change.Kind === 'DeniedCreate') {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (change.NewValue !== undefined) {
|
|
262
|
+
entity.Set(change.Field, change.NewValue);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=CloneMaterializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloneMaterializer.js","sourceRoot":"","sources":["../src/CloneMaterializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ClonePlanHash.ts
|
|
3
|
+
* SHA-256 of a clone plan's canonical form. The hash detects a plan that changed between review
|
|
4
|
+
* and Execute (`PLAN_CHANGED`); only the server computes it, and the browser echoes it back.
|
|
5
|
+
*/
|
|
6
|
+
import { ClonePlanHashInput } from '@memberjunction/record-cloning-base';
|
|
7
|
+
/** Hex SHA-256 of `text`, encoded as UTF-8. */
|
|
8
|
+
export declare function Sha256Hex(text: string): string;
|
|
9
|
+
/** The plan hash: SHA-256 over `CanonicalPlanPayload`, which ignores target keys and masks encrypted values. */
|
|
10
|
+
export declare function ComputeClonePlanHash(plan: ClonePlanHashInput): string;
|
|
11
|
+
//# sourceMappingURL=ClonePlanHash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClonePlanHash.d.ts","sourceRoot":"","sources":["../src/ClonePlanHash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAwB,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAE/F,+CAA+C;AAC/C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,gHAAgH;AAChH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ClonePlanHash.ts
|
|
3
|
+
* SHA-256 of a clone plan's canonical form. The hash detects a plan that changed between review
|
|
4
|
+
* and Execute (`PLAN_CHANGED`); only the server computes it, and the browser echoes it back.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { CanonicalPlanPayload } from '@memberjunction/record-cloning-base';
|
|
8
|
+
/** Hex SHA-256 of `text`, encoded as UTF-8. */
|
|
9
|
+
export function Sha256Hex(text) {
|
|
10
|
+
return createHash('sha256').update(text, 'utf8').digest('hex');
|
|
11
|
+
}
|
|
12
|
+
/** The plan hash: SHA-256 over `CanonicalPlanPayload`, which ignores target keys and masks encrypted values. */
|
|
13
|
+
export function ComputeClonePlanHash(plan) {
|
|
14
|
+
return Sha256Hex(CanonicalPlanPayload(plan));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=ClonePlanHash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClonePlanHash.js","sourceRoot":"","sources":["../src/ClonePlanHash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qCAAqC,CAAC;AAE/F,+CAA+C;AAC/C,MAAM,UAAU,SAAS,CAAC,IAAY;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IACzD,OAAO,SAAS,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ClonePlanner.ts
|
|
3
|
+
* Computes deterministic clone plans for entity records using graph traversal.
|
|
4
|
+
* Enforces caps, permissions, unique key classification, field transformations, and plan hashing.
|
|
5
|
+
* @see plans/record-cloning/README.md §5, §7, §13.1
|
|
6
|
+
*/
|
|
7
|
+
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
8
|
+
import { ClonePlan, RecordCloneRequest } from '@memberjunction/record-cloning-base';
|
|
9
|
+
export interface ClonePlannerOptions {
|
|
10
|
+
Provider?: IMetadataProvider;
|
|
11
|
+
}
|
|
12
|
+
export declare class ClonePlanner {
|
|
13
|
+
private _provider?;
|
|
14
|
+
constructor(options?: ClonePlannerOptions);
|
|
15
|
+
protected get Provider(): IMetadataProvider;
|
|
16
|
+
/**
|
|
17
|
+
* Generates a fully calculated ClonePlan for the requested record.
|
|
18
|
+
*/
|
|
19
|
+
Plan(request: RecordCloneRequest, contextUser: UserInfo): Promise<ClonePlan>;
|
|
20
|
+
/**
|
|
21
|
+
* Values already taken in each field a clone renames, per entity, found with one prefix query
|
|
22
|
+
* per (entity, field). Without them the rename can't avoid "Sales (copy)" on the second clone.
|
|
23
|
+
*/
|
|
24
|
+
private loadExistingNames;
|
|
25
|
+
/**
|
|
26
|
+
* Drops rows matching their relationship's `ExcludeRows`, with every row discovered beneath them.
|
|
27
|
+
* The rule is looked up in the same order as the edge's policy (`ResolveEdgePolicy`): the
|
|
28
|
+
* relationship's own bag, then the root's entry by relationship ID, `Child.JoinField`, then
|
|
29
|
+
* `Child`. One Info warning per relationship.
|
|
30
|
+
*/
|
|
31
|
+
private dropExcludedRows;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=ClonePlanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClonePlanner.d.ts","sourceRoot":"","sources":["../src/ClonePlanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAKH,iBAAiB,EAGjB,QAAQ,EACX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGH,SAAS,EAST,kBAAkB,EAerB,MAAM,qCAAqC,CAAC;AAM7C,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAChC;AA6BD,qBAAa,YAAY;IACrB,OAAO,CAAC,SAAS,CAAC,CAAoB;gBAEnB,OAAO,CAAC,EAAE,mBAAmB;IAIhD,SAAS,KAAK,QAAQ,IAAI,iBAAiB,CAE1C;IAED;;OAEG;IACU,IAAI,CACb,OAAO,EAAE,kBAAkB,EAC3B,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,SAAS,CAAC;IAmxBrB;;;OAGG;YACW,iBAAiB;IA4C/B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;CAuD3B"}
|