@memberjunction/integration-engine 0.0.1 → 5.8.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.
Files changed (46) hide show
  1. package/README.md +142 -28
  2. package/dist/BaseIntegrationConnector.d.ts +142 -0
  3. package/dist/BaseIntegrationConnector.d.ts.map +1 -0
  4. package/dist/BaseIntegrationConnector.js +91 -0
  5. package/dist/BaseIntegrationConnector.js.map +1 -0
  6. package/dist/ConnectorFactory.d.ts +30 -0
  7. package/dist/ConnectorFactory.d.ts.map +1 -0
  8. package/dist/ConnectorFactory.js +50 -0
  9. package/dist/ConnectorFactory.js.map +1 -0
  10. package/dist/FieldMappingEngine.d.ts +94 -0
  11. package/dist/FieldMappingEngine.d.ts.map +1 -0
  12. package/dist/FieldMappingEngine.js +250 -0
  13. package/dist/FieldMappingEngine.js.map +1 -0
  14. package/dist/IntegrationOrchestrator.d.ts +126 -0
  15. package/dist/IntegrationOrchestrator.d.ts.map +1 -0
  16. package/dist/IntegrationOrchestrator.js +548 -0
  17. package/dist/IntegrationOrchestrator.js.map +1 -0
  18. package/dist/MatchEngine.d.ts +50 -0
  19. package/dist/MatchEngine.d.ts.map +1 -0
  20. package/dist/MatchEngine.js +124 -0
  21. package/dist/MatchEngine.js.map +1 -0
  22. package/dist/RetryRunner.d.ts +27 -0
  23. package/dist/RetryRunner.d.ts.map +1 -0
  24. package/dist/RetryRunner.js +59 -0
  25. package/dist/RetryRunner.js.map +1 -0
  26. package/dist/WatermarkService.d.ts +44 -0
  27. package/dist/WatermarkService.d.ts.map +1 -0
  28. package/dist/WatermarkService.js +97 -0
  29. package/dist/WatermarkService.js.map +1 -0
  30. package/dist/entity-types.d.ts +90 -0
  31. package/dist/entity-types.d.ts.map +1 -0
  32. package/dist/entity-types.js +13 -0
  33. package/dist/entity-types.js.map +1 -0
  34. package/dist/index.d.ts +14 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +16 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/transforms.d.ts +75 -0
  39. package/dist/transforms.d.ts.map +1 -0
  40. package/dist/transforms.js +2 -0
  41. package/dist/transforms.js.map +1 -0
  42. package/dist/types.d.ts +192 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +44 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +29 -7
@@ -0,0 +1,124 @@
1
+ import { RunView } from '@memberjunction/core';
2
+ /**
3
+ * Resolves mapped records against existing MJ data to determine
4
+ * whether each record should be Created, Updated, Skipped, or Deleted.
5
+ */
6
+ export class MatchEngine {
7
+ /**
8
+ * Resolves change types for a batch of mapped records by checking for existing
9
+ * MJ records via key field matching and record map lookups.
10
+ *
11
+ * @param records - Mapped records with preliminary change types
12
+ * @param entityMap - The entity map configuration for this object
13
+ * @param fieldMaps - Active field maps for identifying key fields
14
+ * @param contextUser - User context for data access
15
+ * @returns Updated mapped records with resolved ChangeType and MatchedMJRecordID
16
+ */
17
+ async Resolve(records, entityMap, fieldMaps, contextUser) {
18
+ const keyFields = fieldMaps.filter(fm => fm.IsKeyField && fm.Status === 'Active');
19
+ const conflictResolution = entityMap.ConflictResolution;
20
+ const results = [];
21
+ for (const record of records) {
22
+ const resolved = await this.ResolveSingleRecord(record, entityMap, keyFields, conflictResolution, contextUser);
23
+ results.push(resolved);
24
+ }
25
+ return results;
26
+ }
27
+ /**
28
+ * Resolves a single record by checking for an existing MJ match.
29
+ */
30
+ async ResolveSingleRecord(record, entityMap, keyFields, conflictResolution, contextUser) {
31
+ if (record.ExternalRecord.IsDeleted) {
32
+ return this.ResolveDeletedRecord(record, entityMap, contextUser);
33
+ }
34
+ const existingID = await this.FindExistingRecord(record, entityMap, keyFields, contextUser);
35
+ if (existingID) {
36
+ return this.ResolveExistingRecord(record, existingID, conflictResolution);
37
+ }
38
+ return { ...record, ChangeType: 'Create' };
39
+ }
40
+ /**
41
+ * Handles records marked as deleted in the external system.
42
+ */
43
+ async ResolveDeletedRecord(record, entityMap, contextUser) {
44
+ const existingID = await this.FindRecordMapEntry(entityMap.CompanyIntegrationID, record.ExternalRecord.ExternalID, entityMap.EntityID, contextUser);
45
+ if (existingID) {
46
+ return { ...record, ChangeType: 'Delete', MatchedMJRecordID: existingID };
47
+ }
48
+ return { ...record, ChangeType: 'Skip' };
49
+ }
50
+ /**
51
+ * Determines change type for a record that matches an existing MJ record.
52
+ */
53
+ ResolveExistingRecord(record, existingID, conflictResolution) {
54
+ if (conflictResolution === 'Manual') {
55
+ return { ...record, ChangeType: 'Skip', MatchedMJRecordID: existingID };
56
+ }
57
+ return { ...record, ChangeType: 'Update', MatchedMJRecordID: existingID };
58
+ }
59
+ /**
60
+ * Attempts to find an existing MJ record by key field matching, then falls back
61
+ * to the CompanyIntegrationRecordMap.
62
+ */
63
+ async FindExistingRecord(record, entityMap, keyFields, contextUser) {
64
+ if (keyFields.length > 0) {
65
+ const idByKeys = await this.FindByKeyFields(record, keyFields, contextUser);
66
+ if (idByKeys)
67
+ return idByKeys;
68
+ }
69
+ return this.FindRecordMapEntry(entityMap.CompanyIntegrationID, record.ExternalRecord.ExternalID, entityMap.EntityID, contextUser);
70
+ }
71
+ /**
72
+ * Searches for an existing MJ record using key field values.
73
+ */
74
+ async FindByKeyFields(record, keyFields, contextUser) {
75
+ const filterClauses = this.BuildKeyFieldFilter(record, keyFields);
76
+ if (filterClauses.length === 0)
77
+ return null;
78
+ const rv = new RunView();
79
+ const result = await rv.RunView({
80
+ EntityName: record.MJEntityName,
81
+ ExtraFilter: filterClauses.join(' AND '),
82
+ Fields: ['ID'],
83
+ MaxRows: 1,
84
+ ResultType: 'simple',
85
+ }, contextUser);
86
+ if (!result.Success || result.Results.length === 0)
87
+ return null;
88
+ return result.Results[0].ID;
89
+ }
90
+ /**
91
+ * Builds a SQL filter clause from key field values on a mapped record.
92
+ */
93
+ BuildKeyFieldFilter(record, keyFields) {
94
+ const clauses = [];
95
+ for (const kf of keyFields) {
96
+ const value = record.MappedFields[kf.DestinationFieldName];
97
+ if (value == null)
98
+ continue;
99
+ const escaped = String(value).replace(/'/g, "''");
100
+ clauses.push(`[${kf.DestinationFieldName}] = '${escaped}'`);
101
+ }
102
+ return clauses;
103
+ }
104
+ /**
105
+ * Checks the CompanyIntegrationRecordMap for a previous external↔MJ mapping.
106
+ */
107
+ async FindRecordMapEntry(companyIntegrationID, externalID, entityID, contextUser) {
108
+ const rv = new RunView();
109
+ const escapedExternalID = externalID.replace(/'/g, "''");
110
+ const result = await rv.RunView({
111
+ EntityName: 'MJ: Company Integration Record Maps',
112
+ ExtraFilter: `CompanyIntegrationID='${companyIntegrationID}' ` +
113
+ `AND ExternalSystemRecordID='${escapedExternalID}' ` +
114
+ `AND EntityID='${entityID}'`,
115
+ Fields: ['EntityRecordID'],
116
+ MaxRows: 1,
117
+ ResultType: 'simple',
118
+ }, contextUser);
119
+ if (!result.Success || result.Results.length === 0)
120
+ return null;
121
+ return result.Results[0].EntityRecordID;
122
+ }
123
+ }
124
+ //# sourceMappingURL=MatchEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatchEngine.js","sourceRoot":"","sources":["../src/MatchEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Configuration for retry behavior with exponential backoff.
3
+ */
4
+ export interface RetryConfig {
5
+ /** Maximum number of attempts (including the initial one). Default: 3 */
6
+ MaxAttempts: number;
7
+ /** Initial backoff delay in milliseconds. Default: 1000 */
8
+ InitialBackoffMs: number;
9
+ /** Maximum backoff delay in milliseconds. Default: 30000 */
10
+ MaxBackoffMs: number;
11
+ /** Fraction of jitter to add (0-1). Default: 0.1 */
12
+ JitterFraction: number;
13
+ }
14
+ /** Default retry configuration */
15
+ export declare const DEFAULT_RETRY_CONFIG: RetryConfig;
16
+ /**
17
+ * Executes an operation with retry logic using exponential backoff.
18
+ *
19
+ * @param operation - The async operation to execute
20
+ * @param config - Retry configuration (uses defaults if not provided)
21
+ * @param isRetryable - Predicate to determine if a caught error should trigger a retry
22
+ * @param onRetry - Optional callback invoked before each retry with attempt number, error, and delay
23
+ * @returns The result of the operation
24
+ * @throws The last error encountered if all attempts fail
25
+ */
26
+ export declare function WithRetry<T>(operation: () => Promise<T>, config?: RetryConfig, isRetryable?: (error: unknown) => boolean, onRetry?: (attempt: number, error: unknown, delayMs: number) => void): Promise<T>;
27
+ //# sourceMappingURL=RetryRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetryRunner.d.ts","sourceRoot":"","sources":["../src/RetryRunner.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,kCAAkC;AAClC,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAeF;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC7B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,MAAM,GAAE,WAAkC,EAC1C,WAAW,GAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAoB,EACrD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACrE,OAAO,CAAC,CAAC,CAAC,CAyBZ"}
@@ -0,0 +1,59 @@
1
+ /** Default retry configuration */
2
+ export const DEFAULT_RETRY_CONFIG = {
3
+ MaxAttempts: 3,
4
+ InitialBackoffMs: 1000,
5
+ MaxBackoffMs: 30000,
6
+ JitterFraction: 0.1,
7
+ };
8
+ /**
9
+ * Computes the delay for a given attempt using exponential backoff with jitter.
10
+ * @param attempt - The current attempt number (1-based)
11
+ * @param config - Retry configuration
12
+ * @returns Delay in milliseconds
13
+ */
14
+ function computeDelay(attempt, config) {
15
+ const exponentialDelay = config.InitialBackoffMs * Math.pow(2, attempt - 1);
16
+ const capped = Math.min(exponentialDelay, config.MaxBackoffMs);
17
+ const jitter = capped * config.JitterFraction * Math.random();
18
+ return capped + jitter;
19
+ }
20
+ /**
21
+ * Executes an operation with retry logic using exponential backoff.
22
+ *
23
+ * @param operation - The async operation to execute
24
+ * @param config - Retry configuration (uses defaults if not provided)
25
+ * @param isRetryable - Predicate to determine if a caught error should trigger a retry
26
+ * @param onRetry - Optional callback invoked before each retry with attempt number, error, and delay
27
+ * @returns The result of the operation
28
+ * @throws The last error encountered if all attempts fail
29
+ */
30
+ export async function WithRetry(operation, config = DEFAULT_RETRY_CONFIG, isRetryable = () => true, onRetry) {
31
+ let lastError;
32
+ for (let attempt = 1; attempt <= config.MaxAttempts; attempt++) {
33
+ try {
34
+ return await operation();
35
+ }
36
+ catch (err) {
37
+ lastError = err;
38
+ const isLastAttempt = attempt === config.MaxAttempts;
39
+ if (isLastAttempt || !isRetryable(err)) {
40
+ throw err;
41
+ }
42
+ const delayMs = computeDelay(attempt, config);
43
+ if (onRetry) {
44
+ onRetry(attempt, err, delayMs);
45
+ }
46
+ await sleep(delayMs);
47
+ }
48
+ }
49
+ // Should not reach here, but TypeScript needs this
50
+ throw lastError;
51
+ }
52
+ /**
53
+ * Returns a promise that resolves after the specified delay.
54
+ * @param ms - Delay in milliseconds
55
+ */
56
+ function sleep(ms) {
57
+ return new Promise(resolve => setTimeout(resolve, ms));
58
+ }
59
+ //# sourceMappingURL=RetryRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetryRunner.js","sourceRoot":"","sources":["../src/RetryRunner.ts"],"names":[],"mappings":"AAcA,kCAAkC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC7C,WAAW,EAAE,CAAC;IACd,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,GAAG;CACtB,CAAC;AAEF;;;;;GAKG;AACH,SAAS,YAAY,CAAC,OAAe,EAAE,MAAmB;IACtD,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC9D,OAAO,MAAM,GAAG,MAAM,CAAC;AAC3B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC3B,SAA2B,EAC3B,SAAsB,oBAAoB,EAC1C,cAA2C,GAAG,EAAE,CAAC,IAAI,EACrD,OAAoE;IAEpE,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QAC7D,IAAI,CAAC;YACD,OAAO,MAAM,SAAS,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,SAAS,GAAG,GAAG,CAAC;YAEhB,MAAM,aAAa,GAAG,OAAO,KAAK,MAAM,CAAC,WAAW,CAAC;YACrD,IAAI,aAAa,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,MAAM,GAAG,CAAC;YACd,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IAED,mDAAmD;IACnD,MAAM,SAAS,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,KAAK,CAAC,EAAU;IACrB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { type UserInfo } from '@memberjunction/core';
2
+ import type { ICompanyIntegrationSyncWatermark } from './entity-types.js';
3
+ import type { WatermarkType } from './types.js';
4
+ /**
5
+ * Service for loading and updating sync watermarks used for incremental data fetching.
6
+ * Watermarks track the "last known position" so each sync only fetches changes since the last run.
7
+ */
8
+ export declare class WatermarkService {
9
+ /**
10
+ * Loads the current watermark for a specific entity map direction.
11
+ *
12
+ * @param entityMapID - The CompanyIntegrationEntityMap ID to load the watermark for
13
+ * @param contextUser - User context for data access
14
+ * @returns The watermark entity if found, or null if no watermark exists yet
15
+ */
16
+ Load(entityMapID: string, contextUser: UserInfo): Promise<ICompanyIntegrationSyncWatermark | null>;
17
+ /**
18
+ * Updates or creates the watermark for a specific entity map.
19
+ * If a watermark record already exists, it is updated in place.
20
+ * If none exists, a new record is created.
21
+ *
22
+ * @param entityMapID - The CompanyIntegrationEntityMap ID to update the watermark for
23
+ * @param newValue - The new watermark value to store
24
+ * @param contextUser - User context for data access
25
+ */
26
+ Update(entityMapID: string, newValue: string, contextUser: UserInfo): Promise<void>;
27
+ /**
28
+ * Validates a watermark value against its expected type.
29
+ *
30
+ * @param watermarkValue - The watermark value to validate
31
+ * @param watermarkType - The expected type of watermark
32
+ * @returns true if the watermark is valid for its type, false otherwise
33
+ */
34
+ ValidateWatermark(watermarkValue: string, watermarkType: WatermarkType): boolean;
35
+ /**
36
+ * Updates an existing watermark record with a new value and timestamp.
37
+ */
38
+ private UpdateExistingWatermark;
39
+ /**
40
+ * Creates a new watermark record for the given entity map.
41
+ */
42
+ private CreateNewWatermark;
43
+ }
44
+ //# sourceMappingURL=WatermarkService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WatermarkService.d.ts","sourceRoot":"","sources":["../src/WatermarkService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,qBAAa,gBAAgB;IACzB;;;;;;OAMG;IACU,IAAI,CACb,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,gCAAgC,GAAG,IAAI,CAAC;IAanD;;;;;;;;OAQG;IACU,MAAM,CACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,IAAI,CAAC;IAShB;;;;;;OAMG;IACI,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,GAAG,OAAO;IAkBvF;;OAEG;YACW,uBAAuB;IAYrC;;OAEG;YACW,kBAAkB;CAuBnC"}
@@ -0,0 +1,97 @@
1
+ import { Metadata, RunView } from '@memberjunction/core';
2
+ /**
3
+ * Service for loading and updating sync watermarks used for incremental data fetching.
4
+ * Watermarks track the "last known position" so each sync only fetches changes since the last run.
5
+ */
6
+ export class WatermarkService {
7
+ /**
8
+ * Loads the current watermark for a specific entity map direction.
9
+ *
10
+ * @param entityMapID - The CompanyIntegrationEntityMap ID to load the watermark for
11
+ * @param contextUser - User context for data access
12
+ * @returns The watermark entity if found, or null if no watermark exists yet
13
+ */
14
+ async Load(entityMapID, contextUser) {
15
+ const rv = new RunView();
16
+ const result = await rv.RunView({
17
+ EntityName: 'MJ: Company Integration Sync Watermarks',
18
+ ExtraFilter: `EntityMapID='${entityMapID}'`,
19
+ MaxRows: 1,
20
+ ResultType: 'entity_object',
21
+ }, contextUser);
22
+ if (!result.Success || result.Results.length === 0)
23
+ return null;
24
+ return result.Results[0];
25
+ }
26
+ /**
27
+ * Updates or creates the watermark for a specific entity map.
28
+ * If a watermark record already exists, it is updated in place.
29
+ * If none exists, a new record is created.
30
+ *
31
+ * @param entityMapID - The CompanyIntegrationEntityMap ID to update the watermark for
32
+ * @param newValue - The new watermark value to store
33
+ * @param contextUser - User context for data access
34
+ */
35
+ async Update(entityMapID, newValue, contextUser) {
36
+ const existing = await this.Load(entityMapID, contextUser);
37
+ if (existing) {
38
+ await this.UpdateExistingWatermark(existing, newValue);
39
+ }
40
+ else {
41
+ await this.CreateNewWatermark(entityMapID, newValue, contextUser);
42
+ }
43
+ }
44
+ /**
45
+ * Validates a watermark value against its expected type.
46
+ *
47
+ * @param watermarkValue - The watermark value to validate
48
+ * @param watermarkType - The expected type of watermark
49
+ * @returns true if the watermark is valid for its type, false otherwise
50
+ */
51
+ ValidateWatermark(watermarkValue, watermarkType) {
52
+ if (!watermarkValue || watermarkValue.trim().length === 0) {
53
+ return false;
54
+ }
55
+ switch (watermarkType) {
56
+ case 'Timestamp':
57
+ return !isNaN(Date.parse(watermarkValue));
58
+ case 'Version':
59
+ return /^\d+$/.test(watermarkValue);
60
+ case 'Cursor':
61
+ case 'ChangeToken':
62
+ return watermarkValue.length > 0;
63
+ default:
64
+ return watermarkValue.length > 0;
65
+ }
66
+ }
67
+ /**
68
+ * Updates an existing watermark record with a new value and timestamp.
69
+ */
70
+ async UpdateExistingWatermark(watermark, newValue) {
71
+ watermark.WatermarkValue = newValue;
72
+ watermark.LastSyncAt = new Date();
73
+ const saved = await watermark.Save();
74
+ if (!saved) {
75
+ throw new Error(`Failed to update watermark for EntityMapID=${watermark.EntityMapID}`);
76
+ }
77
+ }
78
+ /**
79
+ * Creates a new watermark record for the given entity map.
80
+ */
81
+ async CreateNewWatermark(entityMapID, newValue, contextUser) {
82
+ const md = new Metadata();
83
+ const watermark = await md.GetEntityObject('MJ: Company Integration Sync Watermarks', contextUser);
84
+ watermark.NewRecord();
85
+ watermark.EntityMapID = entityMapID;
86
+ watermark.WatermarkValue = newValue;
87
+ watermark.Direction = 'Pull';
88
+ watermark.WatermarkType = 'Timestamp';
89
+ watermark.LastSyncAt = new Date();
90
+ watermark.RecordsSynced = 0;
91
+ const saved = await watermark.Save();
92
+ if (!saved) {
93
+ throw new Error(`Failed to create watermark for EntityMapID=${entityMapID}`);
94
+ }
95
+ }
96
+ }
97
+ //# sourceMappingURL=WatermarkService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WatermarkService.js","sourceRoot":"","sources":["../src/WatermarkService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Local interface definitions for integration-engine entity types.
3
+ *
4
+ * These interfaces mirror the properties used from the generated entity classes
5
+ * in @memberjunction/core-entities. They are defined locally because CodeGen
6
+ * has not yet been run against the new integration tables, so the generated
7
+ * classes are not yet exported from core-entities.
8
+ *
9
+ * Once CodeGen is run and core-entities is rebuilt, these can be replaced
10
+ * with the real generated entity types.
11
+ */
12
+ /**
13
+ * Mirrors MJIntegrationSourceTypeEntity from the IntegrationSourceType table.
14
+ * @see migrations/v2/V202603040356__v5.7.x_Create_IntegrationSourceType.sql
15
+ */
16
+ export interface IIntegrationSourceType {
17
+ ID: string;
18
+ Name: string;
19
+ Description: string | null;
20
+ DriverClass: string;
21
+ IconClass: string | null;
22
+ Status: 'Active' | 'Inactive';
23
+ Get(fieldName: string): unknown;
24
+ Set?(fieldName: string, value: unknown): void;
25
+ Save?(): Promise<boolean>;
26
+ }
27
+ /**
28
+ * Mirrors MJCompanyIntegrationEntityMapEntity from the CompanyIntegrationEntityMap table.
29
+ * @see migrations/v2/V202603040357__v5.7.x_Create_CompanyIntegrationEntityMap.sql
30
+ */
31
+ export interface ICompanyIntegrationEntityMap {
32
+ ID: string;
33
+ CompanyIntegrationID: string;
34
+ ExternalObjectName: string;
35
+ ExternalObjectLabel: string | null;
36
+ EntityID: string;
37
+ SyncDirection: 'Pull' | 'Push' | 'Bidirectional';
38
+ SyncEnabled: boolean;
39
+ MatchStrategy: string | null;
40
+ ConflictResolution: 'SourceWins' | 'DestWins' | 'MostRecent' | 'Manual';
41
+ Priority: number;
42
+ DeleteBehavior: 'SoftDelete' | 'DoNothing' | 'HardDelete';
43
+ Status: 'Active' | 'Inactive';
44
+ Configuration: string | null;
45
+ /** View field: joined entity name */
46
+ Entity: string;
47
+ Get(fieldName: string): unknown;
48
+ Set?(fieldName: string, value: unknown): void;
49
+ Save?(): Promise<boolean>;
50
+ }
51
+ /**
52
+ * Mirrors MJCompanyIntegrationFieldMapEntity from the CompanyIntegrationFieldMap table.
53
+ * @see migrations/v2/V202603040358__v5.7.x_Create_CompanyIntegrationFieldMap.sql
54
+ */
55
+ export interface ICompanyIntegrationFieldMap {
56
+ ID: string;
57
+ EntityMapID: string;
58
+ SourceFieldName: string;
59
+ SourceFieldLabel: string | null;
60
+ DestinationFieldName: string;
61
+ DestinationFieldLabel: string | null;
62
+ Direction: 'SourceToDest' | 'DestToSource' | 'Both';
63
+ TransformPipeline: string | null;
64
+ IsKeyField: boolean;
65
+ IsRequired: boolean;
66
+ DefaultValue: string | null;
67
+ Priority: number;
68
+ Status: 'Active' | 'Inactive';
69
+ Get(fieldName: string): unknown;
70
+ Set?(fieldName: string, value: unknown): void;
71
+ Save?(): Promise<boolean>;
72
+ }
73
+ /**
74
+ * Mirrors MJCompanyIntegrationSyncWatermarkEntity from the CompanyIntegrationSyncWatermark table.
75
+ * @see migrations/v2/V202603040359__v5.7.x_Create_CompanyIntegrationSyncWatermark.sql
76
+ */
77
+ export interface ICompanyIntegrationSyncWatermark {
78
+ ID: string;
79
+ EntityMapID: string;
80
+ Direction: 'Pull' | 'Push';
81
+ WatermarkType: 'Timestamp' | 'Cursor' | 'ChangeToken' | 'Version';
82
+ WatermarkValue: string | null;
83
+ LastSyncAt: Date | null;
84
+ RecordsSynced: number;
85
+ Get(fieldName: string): unknown;
86
+ Set?(fieldName: string, value: unknown): void;
87
+ Save?(): Promise<boolean>;
88
+ NewRecord?(): void;
89
+ }
90
+ //# sourceMappingURL=entity-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-types.d.ts","sourceRoot":"","sources":["../src/entity-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Local interface definitions for integration-engine entity types.
3
+ *
4
+ * These interfaces mirror the properties used from the generated entity classes
5
+ * in @memberjunction/core-entities. They are defined locally because CodeGen
6
+ * has not yet been run against the new integration tables, so the generated
7
+ * classes are not yet exported from core-entities.
8
+ *
9
+ * Once CodeGen is run and core-entities is rebuilt, these can be replaced
10
+ * with the real generated entity types.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=entity-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-types.js","sourceRoot":"","sources":["../src/entity-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,14 @@
1
+ export type { IIntegrationSourceType, ICompanyIntegrationEntityMap, ICompanyIntegrationFieldMap, ICompanyIntegrationSyncWatermark, } from './entity-types.js';
2
+ export type { SyncDirection, SyncTriggerType, WatermarkType, ConflictResolution, DeleteBehavior, RecordChangeType, IntegrationRunStatus, ExternalRecord, MappedRecord, SyncResult, SyncRecordError, DefaultFieldMapping, SyncErrorCode, ErrorSeverity, SyncProgress, OnProgressCallback, SyncNotificationEvent, SyncNotificationSeverity, SyncNotification, OnNotificationCallback, SourceSchemaInfo, SourceObjectInfo, SourceFieldInfo, SourceRelationshipInfo, } from './types.js';
3
+ export { IsRetryableError, ClassifyError } from './types.js';
4
+ export type { TransformType, TransformOnError, TransformStep, TransformConfig, DirectConfig, RegexConfig, SplitConfig, CombineConfig, LookupConfig, FormatConfig, CoerceConfig, SubstringConfig, CustomConfig, } from './transforms.js';
5
+ export { BaseIntegrationConnector, WithTimeout, DEFAULT_OPERATION_TIMEOUTS, } from './BaseIntegrationConnector.js';
6
+ export type { ConnectionTestResult, ExternalObjectSchema, ExternalFieldSchema, FetchContext, FetchBatchResult, OperationTimeouts, } from './BaseIntegrationConnector.js';
7
+ export { ConnectorFactory } from './ConnectorFactory.js';
8
+ export { FieldMappingEngine } from './FieldMappingEngine.js';
9
+ export { MatchEngine } from './MatchEngine.js';
10
+ export { WatermarkService } from './WatermarkService.js';
11
+ export { WithRetry, DEFAULT_RETRY_CONFIG } from './RetryRunner.js';
12
+ export type { RetryConfig } from './RetryRunner.js';
13
+ export { IntegrationOrchestrator } from './IntegrationOrchestrator.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACR,sBAAsB,EACtB,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,GACnC,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACR,aAAa,EACb,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,sBAAsB,GACzB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG7D,YAAY,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,GACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACH,wBAAwB,EACxB,WAAW,EACX,0BAA0B,GAC7B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACR,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GACpB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // Error classification helpers
2
+ export { IsRetryableError, ClassifyError } from './types.js';
3
+ // Connector
4
+ export { BaseIntegrationConnector, WithTimeout, DEFAULT_OPERATION_TIMEOUTS, } from './BaseIntegrationConnector.js';
5
+ // Factory
6
+ export { ConnectorFactory } from './ConnectorFactory.js';
7
+ // Engines
8
+ export { FieldMappingEngine } from './FieldMappingEngine.js';
9
+ export { MatchEngine } from './MatchEngine.js';
10
+ // Services
11
+ export { WatermarkService } from './WatermarkService.js';
12
+ // Retry
13
+ export { WithRetry, DEFAULT_RETRY_CONFIG } from './RetryRunner.js';
14
+ // Orchestrator
15
+ export { IntegrationOrchestrator } from './IntegrationOrchestrator.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoCA,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmB7D,YAAY;AACZ,OAAO,EACH,wBAAwB,EACxB,WAAW,EACX,0BAA0B,GAC7B,MAAM,+BAA+B,CAAC;AAUvC,UAAU;AACV,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,UAAU;AACV,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,WAAW;AACX,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,QAAQ;AACR,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGnE,eAAe;AACf,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,75 @@
1
+ /** Supported transform types for field value transformation */
2
+ export type TransformType = 'direct' | 'regex' | 'split' | 'combine' | 'lookup' | 'format' | 'coerce' | 'substring' | 'custom';
3
+ /** What to do when a transform step encounters an error */
4
+ export type TransformOnError = 'Skip' | 'Null' | 'Fail';
5
+ /** A single step in a field value transformation pipeline */
6
+ export interface TransformStep {
7
+ /** The type of transform to apply */
8
+ Type: TransformType;
9
+ /** Configuration for the transform step */
10
+ Config: TransformConfig;
11
+ /** Error handling strategy for this step. Defaults to 'Fail' */
12
+ OnError?: TransformOnError;
13
+ }
14
+ /** Union of all transform configuration types */
15
+ export type TransformConfig = DirectConfig | RegexConfig | SplitConfig | CombineConfig | LookupConfig | FormatConfig | CoerceConfig | SubstringConfig | CustomConfig;
16
+ /** Configuration for direct pass-through (no transformation) */
17
+ export interface DirectConfig {
18
+ /** Optional default value if source is null/undefined */
19
+ DefaultValue?: unknown;
20
+ }
21
+ /** Configuration for regex-based string transformation */
22
+ export interface RegexConfig {
23
+ /** Regular expression pattern to match */
24
+ Pattern: string;
25
+ /** Replacement string (supports $1, $2, etc. for capture groups) */
26
+ Replacement: string;
27
+ /** Regex flags (e.g., 'gi' for global, case-insensitive) */
28
+ Flags?: string;
29
+ }
30
+ /** Configuration for splitting a string value and extracting a portion */
31
+ export interface SplitConfig {
32
+ /** Delimiter to split on */
33
+ Delimiter: string;
34
+ /** Zero-based index of the part to extract */
35
+ Index: number;
36
+ }
37
+ /** Configuration for combining multiple source field values */
38
+ export interface CombineConfig {
39
+ /** Names of source fields to combine */
40
+ SourceFields: string[];
41
+ /** Separator to place between combined values */
42
+ Separator: string;
43
+ }
44
+ /** Configuration for value lookup/mapping */
45
+ export interface LookupConfig {
46
+ /** Map of source values to destination values. Keys are matched case-insensitively */
47
+ Map: Record<string, unknown>;
48
+ /** Value to use when the source value is not found in the map */
49
+ Default?: unknown;
50
+ }
51
+ /** Configuration for date/number formatting */
52
+ export interface FormatConfig {
53
+ /** The target format string. For dates: ISO8601 locale format specifiers */
54
+ FormatString: string;
55
+ /** The type of formatting to apply */
56
+ FormatType: 'date' | 'number' | 'string';
57
+ }
58
+ /** Configuration for type coercion */
59
+ export interface CoerceConfig {
60
+ /** Target type to coerce the value into */
61
+ TargetType: 'string' | 'number' | 'boolean' | 'date';
62
+ }
63
+ /** Configuration for extracting a substring */
64
+ export interface SubstringConfig {
65
+ /** Start index (zero-based) */
66
+ Start: number;
67
+ /** Number of characters to extract. If omitted, extracts to end */
68
+ Length?: number;
69
+ }
70
+ /** Configuration for custom JavaScript expression evaluation */
71
+ export interface CustomConfig {
72
+ /** JavaScript expression to evaluate. The source value is available as 'value' and all fields as 'fields' */
73
+ Expression: string;
74
+ }
75
+ //# sourceMappingURL=transforms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GACnB,QAAQ,GACR,OAAO,GACP,OAAO,GACP,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,QAAQ,CAAC;AAEf,2DAA2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAExD,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC1B,qCAAqC;IACrC,IAAI,EAAE,aAAa,CAAC;IACpB,2CAA2C;IAC3C,MAAM,EAAE,eAAe,CAAC;IACxB,gEAAgE;IAChE,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,iDAAiD;AACjD,MAAM,MAAM,eAAe,GACrB,YAAY,GACZ,WAAW,GACX,WAAW,GACX,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,YAAY,CAAC;AAEnB,gEAAgE;AAChE,MAAM,WAAW,YAAY;IACzB,yDAAyD;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IACxB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IACxB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC1B,wCAAwC;IACxC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IACzB,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IACzB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC5C;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IACzB,2CAA2C;IAC3C,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CACxD;AAED,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC5B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,MAAM,WAAW,YAAY;IACzB,6GAA6G;IAC7G,UAAU,EAAE,MAAM,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":""}