@memberjunction/integration-engine 5.38.0 → 5.40.0
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/ActionMetadataGenerator.d.ts +8 -1
- package/dist/ActionMetadataGenerator.d.ts.map +1 -1
- package/dist/ActionMetadataGenerator.js +22 -3
- package/dist/ActionMetadataGenerator.js.map +1 -1
- package/dist/AdaptiveConcurrency.d.ts +85 -0
- package/dist/AdaptiveConcurrency.d.ts.map +1 -0
- package/dist/AdaptiveConcurrency.js +148 -0
- package/dist/AdaptiveConcurrency.js.map +1 -0
- package/dist/BaseIntegrationConnector.d.ts +127 -3
- package/dist/BaseIntegrationConnector.d.ts.map +1 -1
- package/dist/BaseIntegrationConnector.js +126 -11
- package/dist/BaseIntegrationConnector.js.map +1 -1
- package/dist/BaseRESTIntegrationConnector.d.ts +80 -15
- package/dist/BaseRESTIntegrationConnector.d.ts.map +1 -1
- package/dist/BaseRESTIntegrationConnector.js +314 -64
- package/dist/BaseRESTIntegrationConnector.js.map +1 -1
- package/dist/ConflictRecency.d.ts +24 -0
- package/dist/ConflictRecency.d.ts.map +1 -0
- package/dist/ConflictRecency.js +25 -0
- package/dist/ConflictRecency.js.map +1 -0
- package/dist/ContentHash.d.ts +28 -0
- package/dist/ContentHash.d.ts.map +1 -0
- package/dist/ContentHash.js +54 -0
- package/dist/ContentHash.js.map +1 -0
- package/dist/EnrichSchemaConstraints.d.ts +59 -0
- package/dist/EnrichSchemaConstraints.d.ts.map +1 -0
- package/dist/EnrichSchemaConstraints.js +168 -0
- package/dist/EnrichSchemaConstraints.js.map +1 -0
- package/dist/FieldMappingEngine.d.ts +22 -0
- package/dist/FieldMappingEngine.d.ts.map +1 -1
- package/dist/FieldMappingEngine.js +66 -5
- package/dist/FieldMappingEngine.js.map +1 -1
- package/dist/HashDiff.d.ts +68 -0
- package/dist/HashDiff.d.ts.map +1 -0
- package/dist/HashDiff.js +108 -0
- package/dist/HashDiff.js.map +1 -0
- package/dist/IntegrationActionGenerator.d.ts +93 -0
- package/dist/IntegrationActionGenerator.d.ts.map +1 -0
- package/dist/IntegrationActionGenerator.js +313 -0
- package/dist/IntegrationActionGenerator.js.map +1 -0
- package/dist/IntegrationConnectorCreationPipeline.d.ts +86 -0
- package/dist/IntegrationConnectorCreationPipeline.d.ts.map +1 -0
- package/dist/IntegrationConnectorCreationPipeline.js +226 -0
- package/dist/IntegrationConnectorCreationPipeline.js.map +1 -0
- package/dist/IntegrationEngine.d.ts +199 -1
- package/dist/IntegrationEngine.d.ts.map +1 -1
- package/dist/IntegrationEngine.js +1592 -109
- package/dist/IntegrationEngine.js.map +1 -1
- package/dist/IntegrationSchemaSync.d.ts +82 -0
- package/dist/IntegrationSchemaSync.d.ts.map +1 -1
- package/dist/IntegrationSchemaSync.js +289 -42
- package/dist/IntegrationSchemaSync.js.map +1 -1
- package/dist/MatchEngine.d.ts.map +1 -1
- package/dist/MatchEngine.js +4 -0
- package/dist/MatchEngine.js.map +1 -1
- package/dist/RateLimiter.d.ts +117 -0
- package/dist/RateLimiter.d.ts.map +1 -0
- package/dist/RateLimiter.js +159 -0
- package/dist/RateLimiter.js.map +1 -0
- package/dist/SyncLogger.d.ts +106 -0
- package/dist/SyncLogger.d.ts.map +1 -0
- package/dist/SyncLogger.js +176 -0
- package/dist/SyncLogger.js.map +1 -0
- package/dist/WatermarkService.d.ts +36 -1
- package/dist/WatermarkService.d.ts.map +1 -1
- package/dist/WatermarkService.js +113 -3
- package/dist/WatermarkService.js.map +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +52 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -6
package/dist/HashDiff.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { computeContentHash } from './ContentHash.js';
|
|
3
|
+
/**
|
|
4
|
+
* Partitioned / Merkle-style hash-diff (§7 "hash-diff / full-table compare to find changed
|
|
5
|
+
* partitions cheaply when no incremental cursor exists").
|
|
6
|
+
*
|
|
7
|
+
* The problem: some sources have NO usable watermark — they can't tell us "what changed since T"
|
|
8
|
+
* (e.g. YourMembership re-fetches every record every time). Per-record content hashing
|
|
9
|
+
* (`computeContentHash`) already lets us skip the per-record load+write for the unchanged majority,
|
|
10
|
+
* but we still have to FETCH every record to hash it. When the remote can expose a cheap per-PARTITION
|
|
11
|
+
* rollup hash (a folder digest, an aggregated checksum, or just a previously-stored snapshot of one),
|
|
12
|
+
* we can compare partition rollups first and only deep-fetch the partitions whose rollup moved.
|
|
13
|
+
*
|
|
14
|
+
* This module builds the local side of that comparison ON TOP of `computeContentHash`:
|
|
15
|
+
* 1. `partitionRecords` — bucket records by an arbitrary partition key.
|
|
16
|
+
* 2. `partitionRollupHash` — fold each bucket's per-record hashes into ONE order-independent digest.
|
|
17
|
+
* 3. `diffPartitions` — compare two partition→rollup maps; only the differing partitions
|
|
18
|
+
* (changed/added/removed) need a deep re-sync.
|
|
19
|
+
*
|
|
20
|
+
* Everything here is pure, deterministic, and free of DB/network — it operates on in-memory
|
|
21
|
+
* record arrays and plain string→string maps, so it is cheaply unit-testable and reusable on either
|
|
22
|
+
* side of the comparison.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Stable partition bucket for a record IDENTITY (e.g. its ExternalID). Hashing the identity (not the
|
|
26
|
+
* content) keeps a record in the SAME partition across syncs even when its content changes — so a
|
|
27
|
+
* content edit shows up as a *changed partition* rather than a record hopping buckets. SHA-256 of the
|
|
28
|
+
* id, first 4 bytes folded modulo `partitionCount`, gives an even, deterministic spread. Default 256
|
|
29
|
+
* buckets is a sane balance (few enough rollups to store, fine-grained enough to skip most work).
|
|
30
|
+
*/
|
|
31
|
+
export function partitionKeyForIdentity(identity, partitionCount = 256) {
|
|
32
|
+
const hex = createHash('sha256').update(identity).digest('hex').slice(0, 8);
|
|
33
|
+
return String(parseInt(hex, 16) % Math.max(1, partitionCount));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Buckets records by a partition key. `getKey` is accepted to keep the call shape symmetric with
|
|
37
|
+
* the rest of the diff pipeline (callers thread a stable record identity through partition + rollup);
|
|
38
|
+
* partitioning itself only needs `getPartition`. Returns a Map keyed by partition string, each value
|
|
39
|
+
* the array of records that fall in that partition. Records arrive in the order encountered — order
|
|
40
|
+
* is preserved within a bucket and never relied upon by the rollup (see `partitionRollupHash`).
|
|
41
|
+
*/
|
|
42
|
+
export function partitionRecords(records, getKey, getPartition) {
|
|
43
|
+
// getKey is part of the documented signature (callers pass a record-identity accessor) but
|
|
44
|
+
// bucketing is driven purely by partition; reference it so the contract stays explicit.
|
|
45
|
+
void getKey;
|
|
46
|
+
const buckets = new Map();
|
|
47
|
+
for (const record of records) {
|
|
48
|
+
const partition = getPartition(record);
|
|
49
|
+
const bucket = buckets.get(partition);
|
|
50
|
+
if (bucket) {
|
|
51
|
+
bucket.push(record);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
buckets.set(partition, [record]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return buckets;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* ORDER-INDEPENDENT rollup of a partition's records into a single hash. Each record's mapped fields
|
|
61
|
+
* are content-hashed via `computeContentHash`, the per-record hashes are SORTED, then the sorted list
|
|
62
|
+
* is concatenated and SHA-256'd. Sorting before combining is what makes the rollup stable regardless
|
|
63
|
+
* of the order records were fetched in — `[a,b]` and `[b,a]` produce the identical partition digest,
|
|
64
|
+
* so a re-fetch that merely reorders rows never spuriously flags the partition as changed.
|
|
65
|
+
*
|
|
66
|
+
* An empty partition rolls up to the SHA-256 of the empty string, a stable sentinel distinct from any
|
|
67
|
+
* non-empty partition.
|
|
68
|
+
*/
|
|
69
|
+
export function partitionRollupHash(records, fieldsOf) {
|
|
70
|
+
const recordHashes = records.map(record => computeContentHash(fieldsOf(record)));
|
|
71
|
+
recordHashes.sort();
|
|
72
|
+
// Length-prefix each hash so the concatenation is unambiguous and can't collide across different
|
|
73
|
+
// record counts. SHA-256 hex is fixed-width, but the prefix keeps the combine future-proof.
|
|
74
|
+
const combined = recordHashes.map(hash => `${hash.length}:${hash}`).join('');
|
|
75
|
+
return createHash('sha256').update(combined).digest('hex');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Compares two partition→rollup maps and reports which partitions diverge. Only `changed`/`added`/
|
|
79
|
+
* `removed` partitions need a deep re-sync; partitions whose rollup matches on both sides are proven
|
|
80
|
+
* identical and can be skipped entirely. The result arrays are sorted for deterministic output.
|
|
81
|
+
*
|
|
82
|
+
* - `changed` — key in BOTH maps, rollup values differ.
|
|
83
|
+
* - `added` — key in `local` only.
|
|
84
|
+
* - `removed` — key in `remote` only.
|
|
85
|
+
*/
|
|
86
|
+
export function diffPartitions(local, remote) {
|
|
87
|
+
const changed = [];
|
|
88
|
+
const added = [];
|
|
89
|
+
for (const [partition, localRollup] of local) {
|
|
90
|
+
if (!remote.has(partition)) {
|
|
91
|
+
added.push(partition);
|
|
92
|
+
}
|
|
93
|
+
else if (remote.get(partition) !== localRollup) {
|
|
94
|
+
changed.push(partition);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const removed = [];
|
|
98
|
+
for (const partition of remote.keys()) {
|
|
99
|
+
if (!local.has(partition)) {
|
|
100
|
+
removed.push(partition);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
changed.sort();
|
|
104
|
+
added.sort();
|
|
105
|
+
removed.sort();
|
|
106
|
+
return { changed, added, removed };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=HashDiff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HashDiff.js","sourceRoot":"","sources":["../src/HashDiff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview On-demand Integration-as-Actions PERSISTER service.
|
|
3
|
+
*
|
|
4
|
+
* Where `ActionMetadataGenerator` produces mj-sync JSON for the design-time CLI,
|
|
5
|
+
* this service generates AND persists a single strongly-typed Action (for one
|
|
6
|
+
* integration / object / verb) directly to the MJ database via BaseEntity.Save().
|
|
7
|
+
*
|
|
8
|
+
* It is the runtime, idempotent counterpart used when an agent/workflow needs an
|
|
9
|
+
* integration action created on the fly:
|
|
10
|
+
*
|
|
11
|
+
* 1. Load the IntegrationObject + its IntegrationObjectFields from the DB.
|
|
12
|
+
* 2. Map them into ActionMetadataGenerator's IntegrationObjectInfo shape.
|
|
13
|
+
* 3. Run the SAME generator the CLI uses, then pick the requested verb's record.
|
|
14
|
+
* 4. Find-or-create the Action Category, then upsert the Action + its params +
|
|
15
|
+
* result codes (idempotent on the deterministic Action Name).
|
|
16
|
+
*
|
|
17
|
+
* The generated Action uses DriverClass='IntegrationActionExecutor' and stores
|
|
18
|
+
* routing info ({IntegrationName, ObjectName, Verb}) in Action.Config_ — the
|
|
19
|
+
* IntegrationActionExecutor (CoreActions) is the single runtime dispatcher.
|
|
20
|
+
*/
|
|
21
|
+
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
22
|
+
/** CRUD verb that an integration action can dispatch to */
|
|
23
|
+
export type IntegrationActionVerb = 'Get' | 'Create' | 'Update' | 'Delete' | 'Upsert' | 'Search' | 'List';
|
|
24
|
+
/** Result of generating+persisting a single integration action */
|
|
25
|
+
export interface GenerateIntegrationActionResult {
|
|
26
|
+
Success: boolean;
|
|
27
|
+
ActionID?: string;
|
|
28
|
+
ActionName?: string;
|
|
29
|
+
Verb: IntegrationActionVerb;
|
|
30
|
+
ObjectName: string;
|
|
31
|
+
/** True if a matching action already existed and was reused (idempotent reuse) */
|
|
32
|
+
AlreadyExisted: boolean;
|
|
33
|
+
Message: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generates and persists strongly-typed integration actions on demand.
|
|
37
|
+
* Idempotent: reuses an existing Action with the same deterministic Name and
|
|
38
|
+
* reconciles its params/result codes rather than duplicating.
|
|
39
|
+
*/
|
|
40
|
+
export declare class IntegrationActionGenerator {
|
|
41
|
+
/** All verbs in canonical order, used by GenerateActionsForObject */
|
|
42
|
+
private static readonly AllVerbs;
|
|
43
|
+
/**
|
|
44
|
+
* Generate + persist ONE strongly-typed action for (integration, object, verb).
|
|
45
|
+
* Idempotent on the deterministic Name "<Integration> - <Verb> <DisplayName>".
|
|
46
|
+
*/
|
|
47
|
+
GenerateAction(integrationName: string, objectName: string, verb: IntegrationActionVerb, contextUser: UserInfo, provider?: IMetadataProvider): Promise<GenerateIntegrationActionResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Generate all applicable verbs for an object. Get/Search/List are always
|
|
50
|
+
* applicable; Create/Update/Delete/Upsert only when the object SupportsWrite.
|
|
51
|
+
*/
|
|
52
|
+
GenerateActionsForObject(integrationName: string, objectName: string, contextUser: UserInfo, provider?: IMetadataProvider): Promise<GenerateIntegrationActionResult[]>;
|
|
53
|
+
private resolveProvider;
|
|
54
|
+
private applicableVerbs;
|
|
55
|
+
/**
|
|
56
|
+
* Loads the IntegrationObject (by integration name + object name) and its
|
|
57
|
+
* fields from the DB, mapping them into the generator's IntegrationObjectInfo.
|
|
58
|
+
*/
|
|
59
|
+
private loadObjectInfo;
|
|
60
|
+
private loadObjectFields;
|
|
61
|
+
private mapField;
|
|
62
|
+
/**
|
|
63
|
+
* Runs ActionMetadataGenerator for this single object and returns the
|
|
64
|
+
* generated record for the requested verb (matched by its Config.Verb).
|
|
65
|
+
* Returns null if the verb isn't produced (e.g., write verb on read-only object).
|
|
66
|
+
*/
|
|
67
|
+
private buildActionRecord;
|
|
68
|
+
/** Find-or-create the flat "<IntegrationName> Integration" Action Category. */
|
|
69
|
+
private ensureCategory;
|
|
70
|
+
private categoryName;
|
|
71
|
+
/**
|
|
72
|
+
* Upserts the Action: reuses an existing one with the same deterministic Name
|
|
73
|
+
* (AlreadyExisted=true, params/result codes reconciled) or creates a new one.
|
|
74
|
+
*/
|
|
75
|
+
private persistAction;
|
|
76
|
+
private findExistingAction;
|
|
77
|
+
private applyActionFields;
|
|
78
|
+
/**
|
|
79
|
+
* Persists Action Params. On reuse, deletes the existing params first so the
|
|
80
|
+
* recreated set stays exactly in sync with the freshly generated metadata.
|
|
81
|
+
*/
|
|
82
|
+
private persistParams;
|
|
83
|
+
/**
|
|
84
|
+
* Persists Action Result Codes. On reuse, deletes the existing ones first to
|
|
85
|
+
* keep them in sync with the generated metadata.
|
|
86
|
+
*/
|
|
87
|
+
private persistResultCodes;
|
|
88
|
+
/** Loads and deletes all rows of a child entity linked to the given ActionID. */
|
|
89
|
+
private deleteRelated;
|
|
90
|
+
private escape;
|
|
91
|
+
private failure;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=IntegrationActionGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationActionGenerator.d.ts","sourceRoot":"","sources":["../src/IntegrationActionGenerator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,iBAAiB,EAAqB,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAkBhG,2DAA2D;AAC3D,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1G,kEAAkE;AAClE,MAAM,WAAW,+BAA+B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAkBD;;;;GAIG;AACH,qBAAa,0BAA0B;IAEnC,qEAAqE;IACrE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAE9B;IAEF;;;OAGG;IACU,cAAc,CACvB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,qBAAqB,EAC3B,WAAW,EAAE,QAAQ,EACrB,QAAQ,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,+BAA+B,CAAC;IAuB3C;;;OAGG;IACU,wBAAwB,CACjC,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,QAAQ,EACrB,QAAQ,CAAC,EAAE,iBAAiB,GAC7B,OAAO,CAAC,+BAA+B,EAAE,CAAC;IAkB7C,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IASvB;;;OAGG;YACW,cAAc;YA8Bd,gBAAgB;IAiB9B,OAAO,CAAC,QAAQ;IAchB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAwBzB,+EAA+E;YACjE,cAAc;IA+B5B,OAAO,CAAC,YAAY;IAMpB;;;OAGG;YACW,aAAa;YAwCb,kBAAkB;IAgBhC,OAAO,CAAC,iBAAiB;IAiBzB;;;OAGG;YACW,aAAa;IA6B3B;;;OAGG;YACW,kBAAkB;IA0BhC,iFAAiF;YACnE,aAAa;IAwB3B,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,OAAO;CAOlB"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview On-demand Integration-as-Actions PERSISTER service.
|
|
3
|
+
*
|
|
4
|
+
* Where `ActionMetadataGenerator` produces mj-sync JSON for the design-time CLI,
|
|
5
|
+
* this service generates AND persists a single strongly-typed Action (for one
|
|
6
|
+
* integration / object / verb) directly to the MJ database via BaseEntity.Save().
|
|
7
|
+
*
|
|
8
|
+
* It is the runtime, idempotent counterpart used when an agent/workflow needs an
|
|
9
|
+
* integration action created on the fly:
|
|
10
|
+
*
|
|
11
|
+
* 1. Load the IntegrationObject + its IntegrationObjectFields from the DB.
|
|
12
|
+
* 2. Map them into ActionMetadataGenerator's IntegrationObjectInfo shape.
|
|
13
|
+
* 3. Run the SAME generator the CLI uses, then pick the requested verb's record.
|
|
14
|
+
* 4. Find-or-create the Action Category, then upsert the Action + its params +
|
|
15
|
+
* result codes (idempotent on the deterministic Action Name).
|
|
16
|
+
*
|
|
17
|
+
* The generated Action uses DriverClass='IntegrationActionExecutor' and stores
|
|
18
|
+
* routing info ({IntegrationName, ObjectName, Verb}) in Action.Config_ — the
|
|
19
|
+
* IntegrationActionExecutor (CoreActions) is the single runtime dispatcher.
|
|
20
|
+
*/
|
|
21
|
+
import { Metadata, RunView, LogError } from '@memberjunction/core';
|
|
22
|
+
import { ActionMetadataGenerator, } from './ActionMetadataGenerator.js';
|
|
23
|
+
// ─── Service ─────────────────────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Generates and persists strongly-typed integration actions on demand.
|
|
26
|
+
* Idempotent: reuses an existing Action with the same deterministic Name and
|
|
27
|
+
* reconciles its params/result codes rather than duplicating.
|
|
28
|
+
*/
|
|
29
|
+
export class IntegrationActionGenerator {
|
|
30
|
+
/** All verbs in canonical order, used by GenerateActionsForObject */
|
|
31
|
+
static { this.AllVerbs = [
|
|
32
|
+
'Get', 'Create', 'Update', 'Delete', 'Upsert', 'Search', 'List',
|
|
33
|
+
]; }
|
|
34
|
+
/**
|
|
35
|
+
* Generate + persist ONE strongly-typed action for (integration, object, verb).
|
|
36
|
+
* Idempotent on the deterministic Name "<Integration> - <Verb> <DisplayName>".
|
|
37
|
+
*/
|
|
38
|
+
async GenerateAction(integrationName, objectName, verb, contextUser, provider) {
|
|
39
|
+
const md = this.resolveProvider(provider);
|
|
40
|
+
try {
|
|
41
|
+
const objectInfo = await this.loadObjectInfo(md, integrationName, objectName, contextUser);
|
|
42
|
+
if (!objectInfo) {
|
|
43
|
+
return this.failure(verb, objectName, `IntegrationObject "${objectName}" not found for integration "${integrationName}"`);
|
|
44
|
+
}
|
|
45
|
+
const record = this.buildActionRecord(integrationName, objectInfo, verb);
|
|
46
|
+
if (!record) {
|
|
47
|
+
return this.failure(verb, objectName, `Verb "${verb}" is not applicable to object "${objectName}" (write not supported)`);
|
|
48
|
+
}
|
|
49
|
+
const categoryID = await this.ensureCategory(md, integrationName, contextUser);
|
|
50
|
+
return await this.persistAction(md, record, verb, objectName, categoryID, contextUser);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
54
|
+
return this.failure(verb, objectName, `Unexpected error: ${msg}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generate all applicable verbs for an object. Get/Search/List are always
|
|
59
|
+
* applicable; Create/Update/Delete/Upsert only when the object SupportsWrite.
|
|
60
|
+
*/
|
|
61
|
+
async GenerateActionsForObject(integrationName, objectName, contextUser, provider) {
|
|
62
|
+
const md = this.resolveProvider(provider);
|
|
63
|
+
const objectInfo = await this.loadObjectInfo(md, integrationName, objectName, contextUser);
|
|
64
|
+
if (!objectInfo) {
|
|
65
|
+
return [this.failure('Get', objectName, `IntegrationObject "${objectName}" not found for integration "${integrationName}"`)];
|
|
66
|
+
}
|
|
67
|
+
const verbs = this.applicableVerbs(objectInfo.SupportsWrite);
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const verb of verbs) {
|
|
70
|
+
results.push(await this.GenerateAction(integrationName, objectName, verb, contextUser, provider));
|
|
71
|
+
}
|
|
72
|
+
return results;
|
|
73
|
+
}
|
|
74
|
+
// ─── Provider ────────────────────────────────────────────────────
|
|
75
|
+
resolveProvider(provider) {
|
|
76
|
+
return provider ?? Metadata.Provider;
|
|
77
|
+
}
|
|
78
|
+
applicableVerbs(supportsWrite) {
|
|
79
|
+
return IntegrationActionGenerator.AllVerbs.filter(v => {
|
|
80
|
+
if (v === 'Create' || v === 'Update' || v === 'Delete' || v === 'Upsert')
|
|
81
|
+
return supportsWrite;
|
|
82
|
+
return true; // Get, Search, List always
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// ─── Object Loading ──────────────────────────────────────────────
|
|
86
|
+
/**
|
|
87
|
+
* Loads the IntegrationObject (by integration name + object name) and its
|
|
88
|
+
* fields from the DB, mapping them into the generator's IntegrationObjectInfo.
|
|
89
|
+
*/
|
|
90
|
+
async loadObjectInfo(md, integrationName, objectName, contextUser) {
|
|
91
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
92
|
+
const objResult = await rv.RunView({
|
|
93
|
+
EntityName: 'MJ: Integration Objects',
|
|
94
|
+
ExtraFilter: `Integration='${this.escape(integrationName)}' AND Name='${this.escape(objectName)}'`,
|
|
95
|
+
MaxRows: 1,
|
|
96
|
+
ResultType: 'entity_object',
|
|
97
|
+
}, contextUser);
|
|
98
|
+
if (!objResult.Success || objResult.Results.length === 0) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const obj = objResult.Results[0];
|
|
102
|
+
const fields = await this.loadObjectFields(md, obj.ID, contextUser);
|
|
103
|
+
return {
|
|
104
|
+
Name: obj.Name,
|
|
105
|
+
DisplayName: obj.DisplayName ?? obj.Name,
|
|
106
|
+
Description: obj.Description ?? undefined,
|
|
107
|
+
SupportsWrite: obj.SupportsWrite,
|
|
108
|
+
Fields: fields,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async loadObjectFields(md, integrationObjectID, contextUser) {
|
|
112
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
113
|
+
const fieldResult = await rv.RunView({
|
|
114
|
+
EntityName: 'MJ: Integration Object Fields',
|
|
115
|
+
ExtraFilter: `IntegrationObjectID='${this.escape(integrationObjectID)}'`,
|
|
116
|
+
OrderBy: 'Sequence ASC, Name ASC',
|
|
117
|
+
ResultType: 'entity_object',
|
|
118
|
+
}, contextUser);
|
|
119
|
+
if (!fieldResult.Success)
|
|
120
|
+
return [];
|
|
121
|
+
return fieldResult.Results.map(f => this.mapField(f));
|
|
122
|
+
}
|
|
123
|
+
mapField(f) {
|
|
124
|
+
return {
|
|
125
|
+
Name: f.Name,
|
|
126
|
+
DisplayName: f.DisplayName ?? f.Name,
|
|
127
|
+
Description: f.Description ?? undefined,
|
|
128
|
+
Type: f.Type,
|
|
129
|
+
IsRequired: f.IsRequired,
|
|
130
|
+
IsReadOnly: f.IsReadOnly,
|
|
131
|
+
IsPrimaryKey: f.IsPrimaryKey,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// ─── Metadata Generation ─────────────────────────────────────────
|
|
135
|
+
/**
|
|
136
|
+
* Runs ActionMetadataGenerator for this single object and returns the
|
|
137
|
+
* generated record for the requested verb (matched by its Config.Verb).
|
|
138
|
+
* Returns null if the verb isn't produced (e.g., write verb on read-only object).
|
|
139
|
+
*/
|
|
140
|
+
buildActionRecord(integrationName, objectInfo, verb) {
|
|
141
|
+
const config = {
|
|
142
|
+
IntegrationName: integrationName,
|
|
143
|
+
CategoryName: this.categoryName(integrationName),
|
|
144
|
+
Objects: [objectInfo],
|
|
145
|
+
// Search/List handled per-verb below; keep them in the generated set.
|
|
146
|
+
IncludeSearch: true,
|
|
147
|
+
IncludeList: true,
|
|
148
|
+
CreateCategory: false, // category is persisted separately via ensureCategory
|
|
149
|
+
};
|
|
150
|
+
const generated = new ActionMetadataGenerator().Generate(config);
|
|
151
|
+
const match = generated.ActionRecords.find(r => r.fields['Config']?.Verb === verb);
|
|
152
|
+
return match ?? null;
|
|
153
|
+
}
|
|
154
|
+
// ─── Category ────────────────────────────────────────────────────
|
|
155
|
+
/** Find-or-create the flat "<IntegrationName> Integration" Action Category. */
|
|
156
|
+
async ensureCategory(md, integrationName, contextUser) {
|
|
157
|
+
const name = this.categoryName(integrationName);
|
|
158
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
159
|
+
const existing = await rv.RunView({
|
|
160
|
+
EntityName: 'MJ: Action Categories',
|
|
161
|
+
ExtraFilter: `Name='${this.escape(name)}'`,
|
|
162
|
+
MaxRows: 1,
|
|
163
|
+
ResultType: 'entity_object',
|
|
164
|
+
}, contextUser);
|
|
165
|
+
if (existing.Success && existing.Results.length > 0) {
|
|
166
|
+
return existing.Results[0].ID;
|
|
167
|
+
}
|
|
168
|
+
const cat = await md.GetEntityObject('MJ: Action Categories', contextUser);
|
|
169
|
+
cat.NewRecord();
|
|
170
|
+
cat.Name = name;
|
|
171
|
+
cat.Description = `Actions for the ${integrationName} integration`;
|
|
172
|
+
cat.Status = 'Active';
|
|
173
|
+
const saved = await cat.Save();
|
|
174
|
+
if (!saved) {
|
|
175
|
+
LogError(`IntegrationActionGenerator: failed to create category '${name}': ${cat.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
return cat.ID;
|
|
179
|
+
}
|
|
180
|
+
categoryName(integrationName) {
|
|
181
|
+
return `${integrationName} Integration`;
|
|
182
|
+
}
|
|
183
|
+
// ─── Persistence (idempotent) ────────────────────────────────────
|
|
184
|
+
/**
|
|
185
|
+
* Upserts the Action: reuses an existing one with the same deterministic Name
|
|
186
|
+
* (AlreadyExisted=true, params/result codes reconciled) or creates a new one.
|
|
187
|
+
*/
|
|
188
|
+
async persistAction(md, record, verb, objectName, categoryID, contextUser) {
|
|
189
|
+
const actionName = record.fields['Name'];
|
|
190
|
+
const existing = await this.findExistingAction(md, actionName, contextUser);
|
|
191
|
+
const action = existing ?? await md.GetEntityObject('MJ: Actions', contextUser);
|
|
192
|
+
const alreadyExisted = !!existing;
|
|
193
|
+
if (!alreadyExisted) {
|
|
194
|
+
action.NewRecord();
|
|
195
|
+
}
|
|
196
|
+
this.applyActionFields(action, record, categoryID);
|
|
197
|
+
const saved = await action.Save();
|
|
198
|
+
if (!saved) {
|
|
199
|
+
return this.failure(verb, objectName, `Failed to save action '${actionName}': ${action.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
200
|
+
}
|
|
201
|
+
await this.persistParams(md, action.ID, record, alreadyExisted, contextUser);
|
|
202
|
+
await this.persistResultCodes(md, action.ID, record, alreadyExisted, contextUser);
|
|
203
|
+
return {
|
|
204
|
+
Success: true,
|
|
205
|
+
ActionID: action.ID,
|
|
206
|
+
ActionName: actionName,
|
|
207
|
+
Verb: verb,
|
|
208
|
+
ObjectName: objectName,
|
|
209
|
+
AlreadyExisted: alreadyExisted,
|
|
210
|
+
Message: alreadyExisted
|
|
211
|
+
? `Reused existing action '${actionName}' and reconciled its params/result codes`
|
|
212
|
+
: `Created action '${actionName}'`,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
async findExistingAction(md, actionName, contextUser) {
|
|
216
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
217
|
+
const result = await rv.RunView({
|
|
218
|
+
EntityName: 'MJ: Actions',
|
|
219
|
+
ExtraFilter: `Name='${this.escape(actionName)}'`,
|
|
220
|
+
MaxRows: 1,
|
|
221
|
+
ResultType: 'entity_object',
|
|
222
|
+
}, contextUser);
|
|
223
|
+
return result.Success && result.Results.length > 0 ? result.Results[0] : null;
|
|
224
|
+
}
|
|
225
|
+
applyActionFields(action, record, categoryID) {
|
|
226
|
+
action.Name = record.fields['Name'];
|
|
227
|
+
action.Description = record.fields['Description'] ?? '';
|
|
228
|
+
action.Type = 'Custom';
|
|
229
|
+
action.Status = 'Active';
|
|
230
|
+
action.DriverClass = record.fields['DriverClass'] ?? 'IntegrationActionExecutor';
|
|
231
|
+
const configObj = record.fields['Config'];
|
|
232
|
+
action.Config_ = typeof configObj === 'string' ? configObj : JSON.stringify(configObj);
|
|
233
|
+
if (categoryID)
|
|
234
|
+
action.CategoryID = categoryID;
|
|
235
|
+
const iconClass = record.fields['IconClass'];
|
|
236
|
+
if (iconClass)
|
|
237
|
+
action.IconClass = iconClass;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Persists Action Params. On reuse, deletes the existing params first so the
|
|
241
|
+
* recreated set stays exactly in sync with the freshly generated metadata.
|
|
242
|
+
*/
|
|
243
|
+
async persistParams(md, actionID, record, alreadyExisted, contextUser) {
|
|
244
|
+
if (alreadyExisted) {
|
|
245
|
+
await this.deleteRelated(md, 'MJ: Action Params', actionID, contextUser);
|
|
246
|
+
}
|
|
247
|
+
const params = record.relatedEntities['MJ: Action Params'] ?? [];
|
|
248
|
+
for (const p of params) {
|
|
249
|
+
const param = await md.GetEntityObject('MJ: Action Params', contextUser);
|
|
250
|
+
param.NewRecord();
|
|
251
|
+
param.ActionID = actionID;
|
|
252
|
+
param.Name = p.fields['Name'];
|
|
253
|
+
param.Type = p.fields['Type'] ?? 'Input';
|
|
254
|
+
param.ValueType = (p.fields['ValueType'] ?? 'Scalar');
|
|
255
|
+
param.IsArray = p.fields['IsArray'] ?? false;
|
|
256
|
+
param.IsRequired = p.fields['IsRequired'] ?? false;
|
|
257
|
+
if (p.fields['Description'])
|
|
258
|
+
param.Description = p.fields['Description'];
|
|
259
|
+
const saved = await param.Save();
|
|
260
|
+
if (!saved) {
|
|
261
|
+
LogError(`IntegrationActionGenerator: failed to save param '${param.Name}' for action ${actionID}: ${param.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Persists Action Result Codes. On reuse, deletes the existing ones first to
|
|
267
|
+
* keep them in sync with the generated metadata.
|
|
268
|
+
*/
|
|
269
|
+
async persistResultCodes(md, actionID, record, alreadyExisted, contextUser) {
|
|
270
|
+
if (alreadyExisted) {
|
|
271
|
+
await this.deleteRelated(md, 'MJ: Action Result Codes', actionID, contextUser);
|
|
272
|
+
}
|
|
273
|
+
const codes = record.relatedEntities['MJ: Action Result Codes'] ?? [];
|
|
274
|
+
for (const c of codes) {
|
|
275
|
+
const code = await md.GetEntityObject('MJ: Action Result Codes', contextUser);
|
|
276
|
+
code.NewRecord();
|
|
277
|
+
code.ActionID = actionID;
|
|
278
|
+
code.ResultCode = c.fields['ResultCode'];
|
|
279
|
+
code.IsSuccess = c.fields['IsSuccess'] ?? false;
|
|
280
|
+
if (c.fields['Description'])
|
|
281
|
+
code.Description = c.fields['Description'];
|
|
282
|
+
const saved = await code.Save();
|
|
283
|
+
if (!saved) {
|
|
284
|
+
LogError(`IntegrationActionGenerator: failed to save result code '${code.ResultCode}' for action ${actionID}: ${code.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** Loads and deletes all rows of a child entity linked to the given ActionID. */
|
|
289
|
+
async deleteRelated(md, entityName, actionID, contextUser) {
|
|
290
|
+
const rv = RunView.FromMetadataProvider(md);
|
|
291
|
+
const result = await rv.RunView({
|
|
292
|
+
EntityName: entityName,
|
|
293
|
+
ExtraFilter: `ActionID='${this.escape(actionID)}'`,
|
|
294
|
+
ResultType: 'entity_object',
|
|
295
|
+
}, contextUser);
|
|
296
|
+
if (!result.Success)
|
|
297
|
+
return;
|
|
298
|
+
for (const row of result.Results) {
|
|
299
|
+
const deleted = await row.Delete();
|
|
300
|
+
if (!deleted) {
|
|
301
|
+
LogError(`IntegrationActionGenerator: failed to delete ${entityName} row ${row.ID}: ${row.LatestResult?.CompleteMessage ?? 'unknown error'}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// ─── Helpers ─────────────────────────────────────────────────────
|
|
306
|
+
escape(value) {
|
|
307
|
+
return value.replace(/'/g, "''");
|
|
308
|
+
}
|
|
309
|
+
failure(verb, objectName, message) {
|
|
310
|
+
return { Success: false, Verb: verb, ObjectName: objectName, AlreadyExisted: false, Message: message };
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=IntegrationActionGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationActionGenerator.js","sourceRoot":"","sources":["../src/IntegrationActionGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { UserInfo, IMetadataProvider } from '@memberjunction/core';
|
|
2
|
+
import type { MJCompanyIntegrationEntity } from '@memberjunction/core-entities';
|
|
3
|
+
import { type IntegrationRunManifest } from '@memberjunction/integration-progress-artifacts';
|
|
4
|
+
import { type LLMOneShotCallback } from '@memberjunction/integration-pk-classifier';
|
|
5
|
+
import { BaseIntegrationConnector } from './BaseIntegrationConnector.js';
|
|
6
|
+
import { type PersistSchemaResult } from './IntegrationSchemaSync.js';
|
|
7
|
+
import type { IntrospectSchemaOptions } from './types.js';
|
|
8
|
+
/** Options for the creation/refresh pipeline run. */
|
|
9
|
+
export interface ConnectorCreationPipelineOptions {
|
|
10
|
+
/** The connector instance to drive (already constructed by caller). */
|
|
11
|
+
Connector: BaseIntegrationConnector;
|
|
12
|
+
/** CompanyIntegration row to authenticate with. */
|
|
13
|
+
CompanyIntegration: MJCompanyIntegrationEntity;
|
|
14
|
+
/** User context for all entity operations. */
|
|
15
|
+
ContextUser: UserInfo;
|
|
16
|
+
/** Optional metadata provider override (multi-provider scenarios). */
|
|
17
|
+
Provider?: IMetadataProvider;
|
|
18
|
+
/** Optional subset filter — limits introspection to a named set of objects. */
|
|
19
|
+
IntrospectOptions?: IntrospectSchemaOptions;
|
|
20
|
+
/** Optional vendor-wide PK convention hint (e.g. "id" for HubSpot). */
|
|
21
|
+
UniversalPKConvention?: string;
|
|
22
|
+
/** Optional one-shot LLM callback for the PK classifier's last-resort step. */
|
|
23
|
+
LLMInference?: LLMOneShotCallback;
|
|
24
|
+
/** Optional pre-fetched sample rows per object for statistical PK detection. */
|
|
25
|
+
SampleRowsByObject?: Record<string, Array<Record<string, unknown>>>;
|
|
26
|
+
/**
|
|
27
|
+
* Directory for structured progress artifacts. Defaults to
|
|
28
|
+
* `<cwd>/logs/integration-runs`. Each run gets its own `<runID>/` subdir
|
|
29
|
+
* containing manifest.json, progress.jsonl, result.json.
|
|
30
|
+
*/
|
|
31
|
+
ArtifactRootDir?: string;
|
|
32
|
+
/** Mirror progress to console (default false). */
|
|
33
|
+
ConsoleMirror?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Optional explicit runID. When omitted, generated as `connector-<ts>-<rand>`.
|
|
36
|
+
* Supply your own when resuming a previously-killed run.
|
|
37
|
+
*/
|
|
38
|
+
RunID?: string;
|
|
39
|
+
/** Trigger reason recorded in the manifest. */
|
|
40
|
+
TriggerType?: 'Manual' | 'Scheduled' | 'Webhook' | 'Pipeline' | 'Restart';
|
|
41
|
+
}
|
|
42
|
+
/** Outcome of a single pipeline invocation. */
|
|
43
|
+
export interface ConnectorCreationPipelineResult {
|
|
44
|
+
RunID: string;
|
|
45
|
+
Success: boolean;
|
|
46
|
+
PersistResult?: PersistSchemaResult;
|
|
47
|
+
PKVerdicts: Array<{
|
|
48
|
+
ObjectName: string;
|
|
49
|
+
Confident: boolean;
|
|
50
|
+
Nominee?: string;
|
|
51
|
+
Confidence: number;
|
|
52
|
+
Strategy: string;
|
|
53
|
+
Reason: string;
|
|
54
|
+
}>;
|
|
55
|
+
/** Objects that ended the run with no PK — these won't be entity-generated. */
|
|
56
|
+
UnresolvedObjects: string[];
|
|
57
|
+
/** Manifest used to identify the run on disk (for resumption tools). */
|
|
58
|
+
Manifest: IntegrationRunManifest;
|
|
59
|
+
/** Final fail reason if Success=false. */
|
|
60
|
+
FailureMessage?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The unified pipeline that drives connector creation / refresh end-to-end:
|
|
64
|
+
*
|
|
65
|
+
* 1. ConnectionTest stage — verifies credentials before any heavy work
|
|
66
|
+
* 2. Introspect stage — parallel describe via the connector
|
|
67
|
+
* 3. Persist stage — bounded-concurrency upsert with overlay precedence
|
|
68
|
+
* 4. PKClassify stage — soft PK classifier on objects still missing a PK
|
|
69
|
+
*
|
|
70
|
+
* Every stage emits structured events through IntegrationProgressEmitter so the
|
|
71
|
+
* stream is identical regardless of vendor. Stages also emit checkpoint events
|
|
72
|
+
* carrying enough resumableState that the orchestrator can pick up from a kill
|
|
73
|
+
* or container restart without re-running prior stages.
|
|
74
|
+
*
|
|
75
|
+
* The pipeline does NOT generate MJ entities itself — that gate (D7) lives in
|
|
76
|
+
* the CodeGen metadata layer: rows without a PK are simply not promoted to
|
|
77
|
+
* `__mj.Entity`. The pipeline emits `entity.skipped-no-pk` events for visibility.
|
|
78
|
+
*/
|
|
79
|
+
export declare class IntegrationConnectorCreationPipeline {
|
|
80
|
+
Run(opts: ConnectorCreationPipelineOptions): Promise<ConnectorCreationPipelineResult>;
|
|
81
|
+
private StageConnectionTest;
|
|
82
|
+
private StageIntrospect;
|
|
83
|
+
private StagePersist;
|
|
84
|
+
private StagePKClassify;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=IntegrationConnectorCreationPipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IntegrationConnectorCreationPipeline.d.ts","sourceRoot":"","sources":["../src/IntegrationConnectorCreationPipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,KAAK,EACR,0BAA0B,EAG7B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEH,KAAK,sBAAsB,EAC9B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAEH,KAAK,kBAAkB,EAC1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAyB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,qDAAqD;AACrD,MAAM,WAAW,gCAAgC;IAC7C,uEAAuE;IACvE,SAAS,EAAE,wBAAwB,CAAC;IACpC,mDAAmD;IACnD,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,8CAA8C;IAC9C,WAAW,EAAE,QAAQ,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,uEAAuE;IACvE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpE;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;CAC7E;AAED,+CAA+C;AAC/C,MAAM,WAAW,+BAA+B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,UAAU,EAAE,KAAK,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,+EAA+E;IAC/E,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,EAAE,sBAAsB,CAAC;IACjC,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,oCAAoC;IAChC,GAAG,CAAC,IAAI,EAAE,gCAAgC,GAAG,OAAO,CAAC,+BAA+B,CAAC;YA4DpF,mBAAmB;YAiBnB,eAAe;YAiCf,YAAY;YAuCZ,eAAe;CAoFhC"}
|