@contractspec/example.integration-hub 0.0.0-canary-20260113170453

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -0
  3. package/dist/connection/connection.enum.d.ts +10 -0
  4. package/dist/connection/connection.enum.d.ts.map +1 -0
  5. package/dist/connection/connection.enum.js +17 -0
  6. package/dist/connection/connection.enum.js.map +1 -0
  7. package/dist/connection/connection.operation.d.ts +107 -0
  8. package/dist/connection/connection.operation.d.ts.map +1 -0
  9. package/dist/connection/connection.operation.js +63 -0
  10. package/dist/connection/connection.operation.js.map +1 -0
  11. package/dist/connection/connection.presentation.d.ts +8 -0
  12. package/dist/connection/connection.presentation.d.ts.map +1 -0
  13. package/dist/connection/connection.presentation.js +60 -0
  14. package/dist/connection/connection.presentation.js.map +1 -0
  15. package/dist/connection/connection.schema.d.ts +68 -0
  16. package/dist/connection/connection.schema.d.ts.map +1 -0
  17. package/dist/connection/connection.schema.js +76 -0
  18. package/dist/connection/connection.schema.js.map +1 -0
  19. package/dist/connection/index.d.ts +4 -0
  20. package/dist/connection/index.js +5 -0
  21. package/dist/docs/index.d.ts +1 -0
  22. package/dist/docs/index.js +1 -0
  23. package/dist/docs/integration-hub.docblock.d.ts +1 -0
  24. package/dist/docs/integration-hub.docblock.js +115 -0
  25. package/dist/docs/integration-hub.docblock.js.map +1 -0
  26. package/dist/events.d.ts +153 -0
  27. package/dist/events.d.ts.map +1 -0
  28. package/dist/events.js +289 -0
  29. package/dist/events.js.map +1 -0
  30. package/dist/example.d.ts +7 -0
  31. package/dist/example.d.ts.map +1 -0
  32. package/dist/example.js +58 -0
  33. package/dist/example.js.map +1 -0
  34. package/dist/handlers/index.d.ts +2 -0
  35. package/dist/handlers/index.js +3 -0
  36. package/dist/handlers/integration.handlers.d.ts +130 -0
  37. package/dist/handlers/integration.handlers.d.ts.map +1 -0
  38. package/dist/handlers/integration.handlers.js +282 -0
  39. package/dist/handlers/integration.handlers.js.map +1 -0
  40. package/dist/index.d.ts +19 -0
  41. package/dist/index.js +20 -0
  42. package/dist/integration/index.d.ts +4 -0
  43. package/dist/integration/index.js +5 -0
  44. package/dist/integration/integration.enum.d.ts +10 -0
  45. package/dist/integration/integration.enum.d.ts.map +1 -0
  46. package/dist/integration/integration.enum.js +17 -0
  47. package/dist/integration/integration.enum.js.map +1 -0
  48. package/dist/integration/integration.operations.d.ts +99 -0
  49. package/dist/integration/integration.operations.d.ts.map +1 -0
  50. package/dist/integration/integration.operations.js +57 -0
  51. package/dist/integration/integration.operations.js.map +1 -0
  52. package/dist/integration/integration.presentation.d.ts +9 -0
  53. package/dist/integration/integration.presentation.d.ts.map +1 -0
  54. package/dist/integration/integration.presentation.js +77 -0
  55. package/dist/integration/integration.presentation.js.map +1 -0
  56. package/dist/integration/integration.schema.d.ts +68 -0
  57. package/dist/integration/integration.schema.d.ts.map +1 -0
  58. package/dist/integration/integration.schema.js +76 -0
  59. package/dist/integration/integration.schema.js.map +1 -0
  60. package/dist/integration-hub.capability.d.ts +9 -0
  61. package/dist/integration-hub.capability.d.ts.map +1 -0
  62. package/dist/integration-hub.capability.js +38 -0
  63. package/dist/integration-hub.capability.js.map +1 -0
  64. package/dist/integration-hub.feature.d.ts +7 -0
  65. package/dist/integration-hub.feature.d.ts.map +1 -0
  66. package/dist/integration-hub.feature.js +244 -0
  67. package/dist/integration-hub.feature.js.map +1 -0
  68. package/dist/seeders/index.d.ts +10 -0
  69. package/dist/seeders/index.d.ts.map +1 -0
  70. package/dist/seeders/index.js +19 -0
  71. package/dist/seeders/index.js.map +1 -0
  72. package/dist/sync/index.d.ts +4 -0
  73. package/dist/sync/index.js +5 -0
  74. package/dist/sync/sync.enum.d.ts +18 -0
  75. package/dist/sync/sync.enum.d.ts.map +1 -0
  76. package/dist/sync/sync.enum.js +35 -0
  77. package/dist/sync/sync.enum.js.map +1 -0
  78. package/dist/sync/sync.operations.d.ts +509 -0
  79. package/dist/sync/sync.operations.d.ts.map +1 -0
  80. package/dist/sync/sync.operations.js +203 -0
  81. package/dist/sync/sync.operations.js.map +1 -0
  82. package/dist/sync/sync.presentation.d.ts +12 -0
  83. package/dist/sync/sync.presentation.d.ts.map +1 -0
  84. package/dist/sync/sync.presentation.js +168 -0
  85. package/dist/sync/sync.presentation.js.map +1 -0
  86. package/dist/sync/sync.schema.d.ts +356 -0
  87. package/dist/sync/sync.schema.d.ts.map +1 -0
  88. package/dist/sync/sync.schema.js +304 -0
  89. package/dist/sync/sync.schema.js.map +1 -0
  90. package/dist/sync-engine/index.d.ts +109 -0
  91. package/dist/sync-engine/index.d.ts.map +1 -0
  92. package/dist/sync-engine/index.js +148 -0
  93. package/dist/sync-engine/index.js.map +1 -0
  94. package/dist/tests/operations.test-spec.d.ts +9 -0
  95. package/dist/tests/operations.test-spec.d.ts.map +1 -0
  96. package/dist/tests/operations.test-spec.js +94 -0
  97. package/dist/tests/operations.test-spec.js.map +1 -0
  98. package/dist/ui/IntegrationDashboard.d.ts +7 -0
  99. package/dist/ui/IntegrationDashboard.d.ts.map +1 -0
  100. package/dist/ui/IntegrationDashboard.js +266 -0
  101. package/dist/ui/IntegrationDashboard.js.map +1 -0
  102. package/dist/ui/hooks/index.d.ts +2 -0
  103. package/dist/ui/hooks/index.js +5 -0
  104. package/dist/ui/hooks/useIntegrationData.d.ts +23 -0
  105. package/dist/ui/hooks/useIntegrationData.d.ts.map +1 -0
  106. package/dist/ui/hooks/useIntegrationData.js +59 -0
  107. package/dist/ui/hooks/useIntegrationData.js.map +1 -0
  108. package/dist/ui/index.d.ts +6 -0
  109. package/dist/ui/index.js +6 -0
  110. package/dist/ui/renderers/index.d.ts +2 -0
  111. package/dist/ui/renderers/index.js +3 -0
  112. package/dist/ui/renderers/integration.markdown.d.ts +28 -0
  113. package/dist/ui/renderers/integration.markdown.d.ts.map +1 -0
  114. package/dist/ui/renderers/integration.markdown.js +256 -0
  115. package/dist/ui/renderers/integration.markdown.js.map +1 -0
  116. package/package.json +111 -0
@@ -0,0 +1,109 @@
1
+ //#region src/sync-engine/index.d.ts
2
+ /**
3
+ * Sync Engine
4
+ *
5
+ * Core sync logic for the Integration Hub.
6
+ */
7
+ interface FieldMapping {
8
+ sourceField: string;
9
+ targetField: string;
10
+ mappingType: 'DIRECT' | 'TRANSFORM' | 'LOOKUP' | 'CONSTANT' | 'COMPUTED';
11
+ transformExpression?: string;
12
+ lookupConfig?: LookupConfig;
13
+ constantValue?: unknown;
14
+ isRequired: boolean;
15
+ defaultValue?: unknown;
16
+ }
17
+ interface LookupConfig {
18
+ sourceObject: string;
19
+ lookupField: string;
20
+ returnField: string;
21
+ }
22
+ interface SyncConfig {
23
+ id: string;
24
+ direction: 'INBOUND' | 'OUTBOUND' | 'BIDIRECTIONAL';
25
+ sourceObject: string;
26
+ targetObject: string;
27
+ fieldMappings: FieldMapping[];
28
+ createNew: boolean;
29
+ updateExisting: boolean;
30
+ deleteRemoved: boolean;
31
+ sourceFilter?: Record<string, unknown>;
32
+ }
33
+ interface SyncContext {
34
+ runId: string;
35
+ config: SyncConfig;
36
+ connection: {
37
+ id: string;
38
+ authType: string;
39
+ credentials?: Record<string, unknown>;
40
+ };
41
+ }
42
+ interface SyncResult {
43
+ success: boolean;
44
+ recordsProcessed: number;
45
+ recordsCreated: number;
46
+ recordsUpdated: number;
47
+ recordsDeleted: number;
48
+ recordsFailed: number;
49
+ recordsSkipped: number;
50
+ errors: SyncError[];
51
+ }
52
+ interface SyncError {
53
+ recordId?: string;
54
+ field?: string;
55
+ message: string;
56
+ code: string;
57
+ }
58
+ interface SourceRecord {
59
+ id: string;
60
+ data: Record<string, unknown>;
61
+ checksum?: string;
62
+ }
63
+ interface TargetRecord {
64
+ id: string;
65
+ data: Record<string, unknown>;
66
+ checksum?: string;
67
+ }
68
+ interface ISyncEngine {
69
+ /**
70
+ * Execute a sync operation.
71
+ */
72
+ sync(context: SyncContext): Promise<SyncResult>;
73
+ /**
74
+ * Transform a source record to target format.
75
+ */
76
+ transformRecord(sourceRecord: SourceRecord, mappings: FieldMapping[], context: SyncContext): TargetRecord;
77
+ /**
78
+ * Validate a transformed record.
79
+ */
80
+ validateRecord(record: TargetRecord, mappings: FieldMapping[]): {
81
+ valid: boolean;
82
+ errors: SyncError[];
83
+ };
84
+ }
85
+ interface IFieldTransformer {
86
+ transform(value: unknown, expression: string): unknown;
87
+ }
88
+ declare class BasicFieldTransformer implements IFieldTransformer {
89
+ transform(value: unknown, expression: string): unknown;
90
+ }
91
+ declare class BasicSyncEngine implements ISyncEngine {
92
+ private transformer;
93
+ constructor(transformer?: IFieldTransformer);
94
+ sync(_context: SyncContext): Promise<SyncResult>;
95
+ transformRecord(sourceRecord: SourceRecord, mappings: FieldMapping[], _context: SyncContext): TargetRecord;
96
+ validateRecord(record: TargetRecord, mappings: FieldMapping[]): {
97
+ valid: boolean;
98
+ errors: SyncError[];
99
+ };
100
+ private getNestedValue;
101
+ private setNestedValue;
102
+ private evaluateComputed;
103
+ }
104
+ declare function createSyncEngine(transformer?: IFieldTransformer): ISyncEngine;
105
+ declare function computeChecksum(data: Record<string, unknown>): string;
106
+ declare function hasChanges(sourceChecksum: string | undefined, targetChecksum: string | undefined): boolean;
107
+ //#endregion
108
+ export { BasicFieldTransformer, BasicSyncEngine, FieldMapping, IFieldTransformer, ISyncEngine, LookupConfig, SourceRecord, SyncConfig, SyncContext, SyncError, SyncResult, TargetRecord, computeChecksum, createSyncEngine, hasChanges };
109
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/sync-engine/index.ts"],"sourcesContent":[],"mappings":";;AAQA;AAWA;AAMA;AAYA;AAUiB,UAvCA,YAAA,CA+CP;EAGO,WAAA,EAAS,MAAA;EAOT,WAAA,EAAA,MAAY;EAMZ,WAAA,EAAA,QAAY,GAAA,WAEf,GAAA,QAAA,GAAA,UAAA,GAAA,UAAA;EAMG,mBAAW,CAAA,EAAA,MAAA;EAIZ,YAAA,CAAA,EAtEC,YAsED;EAAsB,aAAA,CAAA,EAAA,OAAA;EAAR,UAAA,EAAA,OAAA;EAMZ,YAAA,CAAA,EAAA,OAAA;;AAEL,UAxEI,YAAA,CAwEJ;EACR,YAAA,EAAA,MAAA;EAMO,WAAA,EAAA,MAAA;EACE,WAAA,EAAA,MAAA;;AAC0B,UA3EvB,UAAA,CA2EuB;EAKvB,EAAA,EAAA,MAAA;EAIJ,SAAA,EAAA,SAAA,GAAA,UAAsB,GAAW,eAAA;EAoDjC,YAAA,EAAA,MAAgB;EAGD,YAAA,EAAA,MAAA;EAIL,aAAA,EA1IN,YA0IM,EAAA;EAAsB,SAAA,EAAA,OAAA;EAAR,cAAA,EAAA,OAAA;EAuBnB,aAAA,EAAA,OAAA;EACJ,YAAA,CAAA,EA9JG,MA8JH,CAAA,MAAA,EAAA,OAAA,CAAA;;AAET,UA7JY,WAAA,CA6JZ;EAgEO,KAAA,EAAA,MAAA;EACE,MAAA,EA5NJ,UA4NI;EACiB,UAAA,EAAA;IAnGS,EAAA,EAAA,MAAA;IAAW,QAAA,EAAA,MAAA;IAoLnC,WAAA,CAAA,EA1SE,MA0Sc,CAAA,MAAe,EAAA,OAAA,CAAA;EAM/B,CAAA;AAahB;UAzTiB,UAAA;;;;;;;;UAQP;;UAGO,SAAA;;;;;;UAOA,YAAA;;QAET;;;UAIS,YAAA;;QAET;;;UAMS,WAAA;;;;gBAID,cAAc,QAAQ;;;;gCAMpB,wBACJ,yBACD,cACR;;;;yBAMO,wBACE;;YACiB;;;UAKd,iBAAA;;;cAIJ,qBAAA,YAAiC;;;cAoDjC,eAAA,YAA2B;;4BAGZ;iBAIL,cAAc,QAAQ;gCAuB3B,wBACJ,0BACA,cACT;yBAgEO,wBACE;;YACiB;;;;;;iBAiFf,gBAAA,eAA+B,oBAAoB;iBAMnD,eAAA,OAAsB;iBAatB,UAAA"}
@@ -0,0 +1,148 @@
1
+ //#region src/sync-engine/index.ts
2
+ var BasicFieldTransformer = class {
3
+ transform(value, expression) {
4
+ try {
5
+ if (expression.startsWith("uppercase")) return typeof value === "string" ? value.toUpperCase() : value;
6
+ if (expression.startsWith("lowercase")) return typeof value === "string" ? value.toLowerCase() : value;
7
+ if (expression.startsWith("trim")) return typeof value === "string" ? value.trim() : value;
8
+ if (expression.startsWith("default:")) {
9
+ const defaultVal = expression.replace("default:", "");
10
+ return value ?? JSON.parse(defaultVal);
11
+ }
12
+ if (expression.startsWith("concat:")) {
13
+ const separator = expression.replace("concat:", "") || " ";
14
+ if (Array.isArray(value)) return value.join(separator);
15
+ return value;
16
+ }
17
+ if (expression.startsWith("split:")) {
18
+ const separator = expression.replace("split:", "") || ",";
19
+ if (typeof value === "string") return value.split(separator);
20
+ return value;
21
+ }
22
+ if (expression.startsWith("number")) return Number(value);
23
+ if (expression.startsWith("boolean")) return Boolean(value);
24
+ if (expression.startsWith("string")) return String(value);
25
+ return value;
26
+ } catch {
27
+ return value;
28
+ }
29
+ }
30
+ };
31
+ var BasicSyncEngine = class {
32
+ transformer;
33
+ constructor(transformer) {
34
+ this.transformer = transformer ?? new BasicFieldTransformer();
35
+ }
36
+ async sync(_context) {
37
+ return {
38
+ success: true,
39
+ recordsProcessed: 0,
40
+ recordsCreated: 0,
41
+ recordsUpdated: 0,
42
+ recordsDeleted: 0,
43
+ recordsFailed: 0,
44
+ recordsSkipped: 0,
45
+ errors: []
46
+ };
47
+ }
48
+ transformRecord(sourceRecord, mappings, _context) {
49
+ const targetData = {};
50
+ for (const mapping of mappings) {
51
+ let value;
52
+ let sourceValue;
53
+ switch (mapping.mappingType) {
54
+ case "DIRECT":
55
+ value = this.getNestedValue(sourceRecord.data, mapping.sourceField);
56
+ break;
57
+ case "TRANSFORM":
58
+ sourceValue = this.getNestedValue(sourceRecord.data, mapping.sourceField);
59
+ value = mapping.transformExpression ? this.transformer.transform(sourceValue, mapping.transformExpression) : sourceValue;
60
+ break;
61
+ case "CONSTANT":
62
+ value = mapping.constantValue;
63
+ break;
64
+ case "LOOKUP":
65
+ value = this.getNestedValue(sourceRecord.data, mapping.sourceField);
66
+ break;
67
+ case "COMPUTED":
68
+ value = mapping.transformExpression ? this.evaluateComputed(sourceRecord.data, mapping.transformExpression) : null;
69
+ break;
70
+ default: value = this.getNestedValue(sourceRecord.data, mapping.sourceField);
71
+ }
72
+ if (value === void 0 || value === null) value = mapping.defaultValue;
73
+ this.setNestedValue(targetData, mapping.targetField, value);
74
+ }
75
+ return {
76
+ id: sourceRecord.id,
77
+ data: targetData
78
+ };
79
+ }
80
+ validateRecord(record, mappings) {
81
+ const errors = [];
82
+ for (const mapping of mappings) if (mapping.isRequired) {
83
+ const value = this.getNestedValue(record.data, mapping.targetField);
84
+ if (value === void 0 || value === null) errors.push({
85
+ recordId: record.id,
86
+ field: mapping.targetField,
87
+ message: `Required field ${mapping.targetField} is missing`,
88
+ code: "REQUIRED_FIELD_MISSING"
89
+ });
90
+ }
91
+ return {
92
+ valid: errors.length === 0,
93
+ errors
94
+ };
95
+ }
96
+ getNestedValue(obj, path) {
97
+ const parts = path.split(".");
98
+ let current = obj;
99
+ for (const part of parts) {
100
+ if (current === null || current === void 0) return;
101
+ current = current[part];
102
+ }
103
+ return current;
104
+ }
105
+ setNestedValue(obj, path, value) {
106
+ const parts = path.split(".");
107
+ let current = obj;
108
+ for (let i = 0; i < parts.length - 1; i++) {
109
+ const part = parts[i];
110
+ if (part === void 0) continue;
111
+ if (!(part in current)) current[part] = {};
112
+ current = current[part];
113
+ }
114
+ const lastPart = parts[parts.length - 1];
115
+ if (lastPart !== void 0) current[lastPart] = value;
116
+ }
117
+ evaluateComputed(data, expression) {
118
+ try {
119
+ return expression.replace(/\$\{([^}]+)\}/g, (_, path) => {
120
+ const value = this.getNestedValue(data, path);
121
+ return String(value ?? "");
122
+ });
123
+ } catch {
124
+ return null;
125
+ }
126
+ }
127
+ };
128
+ function createSyncEngine(transformer) {
129
+ return new BasicSyncEngine(transformer);
130
+ }
131
+ function computeChecksum(data) {
132
+ const str = JSON.stringify(data, Object.keys(data).sort());
133
+ let hash = 0;
134
+ for (let i = 0; i < str.length; i++) {
135
+ const char = str.charCodeAt(i);
136
+ hash = (hash << 5) - hash + char;
137
+ hash = hash & hash;
138
+ }
139
+ return hash.toString(16);
140
+ }
141
+ function hasChanges(sourceChecksum, targetChecksum) {
142
+ if (!sourceChecksum || !targetChecksum) return true;
143
+ return sourceChecksum !== targetChecksum;
144
+ }
145
+
146
+ //#endregion
147
+ export { BasicFieldTransformer, BasicSyncEngine, computeChecksum, createSyncEngine, hasChanges };
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/sync-engine/index.ts"],"sourcesContent":["/**\n * Sync Engine\n *\n * Core sync logic for the Integration Hub.\n */\n\n// ============ Types ============\n\nexport interface FieldMapping {\n sourceField: string;\n targetField: string;\n mappingType: 'DIRECT' | 'TRANSFORM' | 'LOOKUP' | 'CONSTANT' | 'COMPUTED';\n transformExpression?: string;\n lookupConfig?: LookupConfig;\n constantValue?: unknown;\n isRequired: boolean;\n defaultValue?: unknown;\n}\n\nexport interface LookupConfig {\n sourceObject: string;\n lookupField: string;\n returnField: string;\n}\n\nexport interface SyncConfig {\n id: string;\n direction: 'INBOUND' | 'OUTBOUND' | 'BIDIRECTIONAL';\n sourceObject: string;\n targetObject: string;\n fieldMappings: FieldMapping[];\n createNew: boolean;\n updateExisting: boolean;\n deleteRemoved: boolean;\n sourceFilter?: Record<string, unknown>;\n}\n\nexport interface SyncContext {\n runId: string;\n config: SyncConfig;\n connection: {\n id: string;\n authType: string;\n credentials?: Record<string, unknown>;\n };\n}\n\nexport interface SyncResult {\n success: boolean;\n recordsProcessed: number;\n recordsCreated: number;\n recordsUpdated: number;\n recordsDeleted: number;\n recordsFailed: number;\n recordsSkipped: number;\n errors: SyncError[];\n}\n\nexport interface SyncError {\n recordId?: string;\n field?: string;\n message: string;\n code: string;\n}\n\nexport interface SourceRecord {\n id: string;\n data: Record<string, unknown>;\n checksum?: string;\n}\n\nexport interface TargetRecord {\n id: string;\n data: Record<string, unknown>;\n checksum?: string;\n}\n\n// ============ Sync Engine Interface ============\n\nexport interface ISyncEngine {\n /**\n * Execute a sync operation.\n */\n sync(context: SyncContext): Promise<SyncResult>;\n\n /**\n * Transform a source record to target format.\n */\n transformRecord(\n sourceRecord: SourceRecord,\n mappings: FieldMapping[],\n context: SyncContext\n ): TargetRecord;\n\n /**\n * Validate a transformed record.\n */\n validateRecord(\n record: TargetRecord,\n mappings: FieldMapping[]\n ): { valid: boolean; errors: SyncError[] };\n}\n\n// ============ Field Transformer ============\n\nexport interface IFieldTransformer {\n transform(value: unknown, expression: string): unknown;\n}\n\nexport class BasicFieldTransformer implements IFieldTransformer {\n transform(value: unknown, expression: string): unknown {\n // Simple expression evaluation\n // In production, use a proper expression language\n try {\n if (expression.startsWith('uppercase')) {\n return typeof value === 'string' ? value.toUpperCase() : value;\n }\n if (expression.startsWith('lowercase')) {\n return typeof value === 'string' ? value.toLowerCase() : value;\n }\n if (expression.startsWith('trim')) {\n return typeof value === 'string' ? value.trim() : value;\n }\n if (expression.startsWith('default:')) {\n const defaultVal = expression.replace('default:', '');\n return value ?? JSON.parse(defaultVal);\n }\n if (expression.startsWith('concat:')) {\n const separator = expression.replace('concat:', '') || ' ';\n if (Array.isArray(value)) {\n return value.join(separator);\n }\n return value;\n }\n if (expression.startsWith('split:')) {\n const separator = expression.replace('split:', '') || ',';\n if (typeof value === 'string') {\n return value.split(separator);\n }\n return value;\n }\n if (expression.startsWith('number')) {\n return Number(value);\n }\n if (expression.startsWith('boolean')) {\n return Boolean(value);\n }\n if (expression.startsWith('string')) {\n return String(value);\n }\n\n // Return as-is if no transformation matches\n return value;\n } catch {\n return value;\n }\n }\n}\n\n// ============ Basic Sync Engine ============\n\nexport class BasicSyncEngine implements ISyncEngine {\n private transformer: IFieldTransformer;\n\n constructor(transformer?: IFieldTransformer) {\n this.transformer = transformer ?? new BasicFieldTransformer();\n }\n\n async sync(_context: SyncContext): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n recordsProcessed: 0,\n recordsCreated: 0,\n recordsUpdated: 0,\n recordsDeleted: 0,\n recordsFailed: 0,\n recordsSkipped: 0,\n errors: [],\n };\n\n // In a real implementation, this would:\n // 1. Fetch records from source\n // 2. Transform each record\n // 3. Validate each record\n // 4. Upsert to target\n // 5. Track sync records for deduplication\n\n return result;\n }\n\n transformRecord(\n sourceRecord: SourceRecord,\n mappings: FieldMapping[],\n _context: SyncContext\n ): TargetRecord {\n const targetData: Record<string, unknown> = {};\n\n for (const mapping of mappings) {\n let value: unknown;\n let sourceValue: unknown;\n\n switch (mapping.mappingType) {\n case 'DIRECT':\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n break;\n\n case 'TRANSFORM':\n sourceValue = this.getNestedValue(\n sourceRecord.data,\n mapping.sourceField\n );\n value = mapping.transformExpression\n ? this.transformer.transform(\n sourceValue,\n mapping.transformExpression\n )\n : sourceValue;\n break;\n\n case 'CONSTANT':\n value = mapping.constantValue;\n break;\n\n case 'LOOKUP':\n // In production, this would fetch from a lookup table\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n break;\n\n case 'COMPUTED':\n // In production, this would evaluate a computed expression\n value = mapping.transformExpression\n ? this.evaluateComputed(\n sourceRecord.data,\n mapping.transformExpression\n )\n : null;\n break;\n\n default:\n value = this.getNestedValue(sourceRecord.data, mapping.sourceField);\n }\n\n // Apply default value if needed\n if (value === undefined || value === null) {\n value = mapping.defaultValue;\n }\n\n // Set the target field\n this.setNestedValue(targetData, mapping.targetField, value);\n }\n\n return {\n id: sourceRecord.id,\n data: targetData,\n };\n }\n\n validateRecord(\n record: TargetRecord,\n mappings: FieldMapping[]\n ): { valid: boolean; errors: SyncError[] } {\n const errors: SyncError[] = [];\n\n for (const mapping of mappings) {\n if (mapping.isRequired) {\n const value = this.getNestedValue(record.data, mapping.targetField);\n if (value === undefined || value === null) {\n errors.push({\n recordId: record.id,\n field: mapping.targetField,\n message: `Required field ${mapping.targetField} is missing`,\n code: 'REQUIRED_FIELD_MISSING',\n });\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n private getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n }\n\n private setNestedValue(\n obj: Record<string, unknown>,\n path: string,\n value: unknown\n ): void {\n const parts = path.split('.');\n let current = obj;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (part === undefined) continue;\n if (!(part in current)) {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n\n const lastPart = parts[parts.length - 1];\n if (lastPart !== undefined) {\n current[lastPart] = value;\n }\n }\n\n private evaluateComputed(\n data: Record<string, unknown>,\n expression: string\n ): unknown {\n // Simple computed field evaluation\n // In production, use a proper expression evaluator\n try {\n // Support simple field references like ${field.path}\n const result = expression.replace(/\\$\\{([^}]+)\\}/g, (_, path) => {\n const value = this.getNestedValue(data, path);\n return String(value ?? '');\n });\n return result;\n } catch {\n return null;\n }\n }\n}\n\n// ============ Factory ============\n\nexport function createSyncEngine(transformer?: IFieldTransformer): ISyncEngine {\n return new BasicSyncEngine(transformer);\n}\n\n// ============ Checksum Utilities ============\n\nexport function computeChecksum(data: Record<string, unknown>): string {\n // Simple checksum based on JSON serialization\n // In production, use a proper hash function\n const str = JSON.stringify(data, Object.keys(data).sort());\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return hash.toString(16);\n}\n\nexport function hasChanges(\n sourceChecksum: string | undefined,\n targetChecksum: string | undefined\n): boolean {\n if (!sourceChecksum || !targetChecksum) {\n return true;\n }\n return sourceChecksum !== targetChecksum;\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import * as _contractspec_lib_contracts30 from "@contractspec/lib.contracts";
2
+
3
+ //#region src/tests/operations.test-spec.d.ts
4
+ declare const SyncConfigCreateTest: _contractspec_lib_contracts30.TestSpec;
5
+ declare const FieldMappingAddTest: _contractspec_lib_contracts30.TestSpec;
6
+ declare const SyncRunListTest: _contractspec_lib_contracts30.TestSpec;
7
+ //#endregion
8
+ export { FieldMappingAddTest, SyncConfigCreateTest, SyncRunListTest };
9
+ //# sourceMappingURL=operations.test-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.d.ts","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":[],"mappings":";;;cAEa,sBAyBX,6BAAA,CAzB+B;cA2BpB,qBAyBX,6BAAA,CAzB8B;cA2BnB,iBAyBX,6BAAA,CAzB0B"}
@@ -0,0 +1,94 @@
1
+ import { defineTestSpec } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/tests/operations.test-spec.ts
4
+ const SyncConfigCreateTest = defineTestSpec({
5
+ meta: {
6
+ key: "integration.syncConfig.create.test",
7
+ version: "1.0.0",
8
+ stability: "experimental",
9
+ owners: ["@example.integration-hub"],
10
+ description: "Test for creating sync config",
11
+ tags: ["test"]
12
+ },
13
+ target: {
14
+ type: "operation",
15
+ operation: {
16
+ key: "integration.syncConfig.create",
17
+ version: "1.0.0"
18
+ }
19
+ },
20
+ scenarios: [{
21
+ key: "success",
22
+ when: { operation: { key: "integration.syncConfig.create" } },
23
+ then: [{
24
+ type: "expectOutput",
25
+ match: {}
26
+ }]
27
+ }, {
28
+ key: "error",
29
+ when: { operation: { key: "integration.syncConfig.create" } },
30
+ then: [{ type: "expectError" }]
31
+ }]
32
+ });
33
+ const FieldMappingAddTest = defineTestSpec({
34
+ meta: {
35
+ key: "integration.fieldMapping.add.test",
36
+ version: "1.0.0",
37
+ stability: "experimental",
38
+ owners: ["@example.integration-hub"],
39
+ description: "Test for adding field mapping",
40
+ tags: ["test"]
41
+ },
42
+ target: {
43
+ type: "operation",
44
+ operation: {
45
+ key: "integration.fieldMapping.add",
46
+ version: "1.0.0"
47
+ }
48
+ },
49
+ scenarios: [{
50
+ key: "success",
51
+ when: { operation: { key: "integration.fieldMapping.add" } },
52
+ then: [{
53
+ type: "expectOutput",
54
+ match: {}
55
+ }]
56
+ }, {
57
+ key: "error",
58
+ when: { operation: { key: "integration.fieldMapping.add" } },
59
+ then: [{ type: "expectError" }]
60
+ }]
61
+ });
62
+ const SyncRunListTest = defineTestSpec({
63
+ meta: {
64
+ key: "integration.syncRun.list.test",
65
+ version: "1.0.0",
66
+ stability: "experimental",
67
+ owners: ["@example.integration-hub"],
68
+ description: "Test for listing sync runs",
69
+ tags: ["test"]
70
+ },
71
+ target: {
72
+ type: "operation",
73
+ operation: {
74
+ key: "integration.syncRun.list",
75
+ version: "1.0.0"
76
+ }
77
+ },
78
+ scenarios: [{
79
+ key: "success",
80
+ when: { operation: { key: "integration.syncRun.list" } },
81
+ then: [{
82
+ type: "expectOutput",
83
+ match: {}
84
+ }]
85
+ }, {
86
+ key: "error",
87
+ when: { operation: { key: "integration.syncRun.list" } },
88
+ then: [{ type: "expectError" }]
89
+ }]
90
+ });
91
+
92
+ //#endregion
93
+ export { FieldMappingAddTest, SyncConfigCreateTest, SyncRunListTest };
94
+ //# sourceMappingURL=operations.test-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.js","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":["import { defineTestSpec } from '@contractspec/lib.contracts';\n\nexport const SyncConfigCreateTest = defineTestSpec({\n meta: {\n key: 'integration.syncConfig.create.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for creating sync config',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.syncConfig.create', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.syncConfig.create' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.syncConfig.create' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const FieldMappingAddTest = defineTestSpec({\n meta: {\n key: 'integration.fieldMapping.add.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for adding field mapping',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.fieldMapping.add', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.fieldMapping.add' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.fieldMapping.add' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const SyncRunListTest = defineTestSpec({\n meta: {\n key: 'integration.syncRun.list.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.integration-hub'],\n description: 'Test for listing sync runs',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'integration.syncRun.list', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'integration.syncRun.list' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'integration.syncRun.list' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n"],"mappings":";;;AAEA,MAAa,uBAAuB,eAAe;CACjD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAiC,SAAS;GAAS;EACtE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,sBAAsB,eAAe;CAChD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAgC,SAAS;GAAS;EACrE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,gCAAgC,EAAE;EAC5D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,gCAAgC,EAAE;EAC5D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,kBAAkB,eAAe;CAC5C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,2BAA2B;EACpC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAA4B,SAAS;GAAS;EACjE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,4BAA4B,EAAE;EACxD,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,4BAA4B,EAAE;EACxD,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/ui/IntegrationDashboard.d.ts
4
+ declare function IntegrationDashboard(): react_jsx_runtime0.JSX.Element;
5
+ //#endregion
6
+ export { IntegrationDashboard };
7
+ //# sourceMappingURL=IntegrationDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationDashboard.d.ts","names":[],"sources":["../../src/ui/IntegrationDashboard.tsx"],"sourcesContent":[],"mappings":";;;iBA4CgB,oBAAA,CAAA,GAAoB,kBAAA,CAAA,GAAA,CAAA"}