@adtrackify/at-service-common 4.0.7 → 4.0.8

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 (69) hide show
  1. package/dist/cjs/__tests__/identity-cache/helpers.spec.d.ts +1 -0
  2. package/dist/cjs/__tests__/identity-cache/helpers.spec.js +594 -0
  3. package/dist/cjs/__tests__/identity-cache/helpers.spec.js.map +1 -0
  4. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.d.ts +1 -0
  5. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +556 -0
  6. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -0
  7. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +23 -25
  8. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +1 -1
  9. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +11 -12
  10. package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +1 -1
  11. package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js +64 -21
  12. package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
  13. package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js +1617 -14
  14. package/dist/cjs/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
  15. package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js +711 -0
  16. package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
  17. package/dist/cjs/helpers/identity-cache-helper.d.ts +9 -0
  18. package/dist/cjs/helpers/identity-cache-helper.js +54 -1
  19. package/dist/cjs/helpers/identity-cache-helper.js.map +1 -1
  20. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.d.ts +17 -4
  21. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js +35 -33
  22. package/dist/cjs/services/db/identity-cache-dynamodb-service/helpers.js.map +1 -1
  23. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +4 -2
  24. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +63 -8
  25. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
  26. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +1 -0
  27. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +91 -53
  28. package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
  29. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.d.ts +1 -0
  30. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js +1 -0
  31. package/dist/cjs/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
  32. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.d.ts +16 -0
  33. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js +9 -1
  34. package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
  35. package/dist/esm/__tests__/identity-cache/helpers.spec.d.ts +1 -0
  36. package/dist/esm/__tests__/identity-cache/helpers.spec.js +592 -0
  37. package/dist/esm/__tests__/identity-cache/helpers.spec.js.map +1 -0
  38. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.d.ts +1 -0
  39. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +554 -0
  40. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -0
  41. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js +23 -25
  42. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service-v2-comparison.spec.js.map +1 -1
  43. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js +11 -12
  44. package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-service.spec.js.map +1 -1
  45. package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js +65 -22
  46. package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
  47. package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js +1617 -14
  48. package/dist/esm/__tests__/identity-cache/identity-gateway-service.spec.js.map +1 -1
  49. package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js +712 -1
  50. package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
  51. package/dist/esm/helpers/identity-cache-helper.d.ts +9 -0
  52. package/dist/esm/helpers/identity-cache-helper.js +52 -1
  53. package/dist/esm/helpers/identity-cache-helper.js.map +1 -1
  54. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.d.ts +17 -4
  55. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js +33 -31
  56. package/dist/esm/services/db/identity-cache-dynamodb-service/helpers.js.map +1 -1
  57. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.d.ts +4 -2
  58. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +57 -2
  59. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
  60. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.d.ts +1 -0
  61. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +92 -54
  62. package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
  63. package/dist/esm/services/db/identity-cache-dynamodb-service/index.d.ts +1 -0
  64. package/dist/esm/services/db/identity-cache-dynamodb-service/index.js +1 -0
  65. package/dist/esm/services/db/identity-cache-dynamodb-service/index.js.map +1 -1
  66. package/dist/esm/services/db/identity-cache-dynamodb-service/types.d.ts +16 -0
  67. package/dist/esm/services/db/identity-cache-dynamodb-service/types.js +8 -0
  68. package/dist/esm/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
  69. package/package.json +1 -1
@@ -0,0 +1,592 @@
1
+ import { IDENTITY_CACHE_STALENESS_TIER } from '../../helpers/identity-cache-helper.js';
2
+ import { processCacheHit, stripAddressTimestamps, computeTraitChanges, } from '../../services/db/identity-cache-dynamodb-service/helpers.js';
3
+ import { CACHE_WRITE_REASON } from '../../services/db/identity-cache-dynamodb-service/types.js';
4
+ describe('processCacheHit helper', () => {
5
+ describe('deep equality check behavior', () => {
6
+ it('should return isDeepEqual=true when merged equals cached', () => {
7
+ const cachedIdentity = {
8
+ identityId: 'test-id',
9
+ traits: {
10
+ emails: ['test@email.com'],
11
+ phones: ['555-1234'],
12
+ },
13
+ };
14
+ const incomingIdentity = {
15
+ identityId: 'test-id',
16
+ traits: {
17
+ emails: ['test@email.com'],
18
+ phones: ['555-1234'],
19
+ },
20
+ };
21
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
22
+ expect(result.isDeepEqual).toBe(true);
23
+ expect(result.isCacheStale).toBe(false);
24
+ });
25
+ it('should return isDeepEqual=false when merged differs from cached', () => {
26
+ const cachedIdentity = {
27
+ identityId: 'test-id',
28
+ traits: {
29
+ emails: ['old@email.com'],
30
+ },
31
+ };
32
+ const incomingIdentity = {
33
+ identityId: 'test-id',
34
+ traits: {
35
+ emails: ['old@email.com', 'new@email.com'],
36
+ },
37
+ };
38
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
39
+ expect(result.isDeepEqual).toBe(false);
40
+ expect(result.isCacheStale).toBe(true);
41
+ });
42
+ it('should strip address timestamps before comparison', () => {
43
+ const now = Date.now();
44
+ const cachedIdentity = {
45
+ identityId: 'test-id',
46
+ traits: {
47
+ emails: ['test@email.com'],
48
+ addresses: [{ city: 'NYC', firstName: 'John', cra: now - 10000, upa: now - 5000 }],
49
+ },
50
+ };
51
+ const incomingIdentity = {
52
+ identityId: 'test-id',
53
+ traits: {
54
+ emails: ['test@email.com'],
55
+ },
56
+ };
57
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
58
+ expect(result.isCacheStale).toBe(false);
59
+ });
60
+ it('should detect difference in address content even with timestamp stripping', () => {
61
+ const now = Date.now();
62
+ const cachedIdentity = {
63
+ identityId: 'test-id',
64
+ traits: {
65
+ emails: ['test@email.com'],
66
+ addresses: [{ city: 'NYC', cra: now }],
67
+ },
68
+ };
69
+ const incomingIdentity = {
70
+ identityId: 'test-id',
71
+ traits: {
72
+ emails: ['test@email.com'],
73
+ addresses: [{ city: 'Boston', cra: now }],
74
+ },
75
+ };
76
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
77
+ expect(result.isDeepEqual).toBe(false);
78
+ });
79
+ });
80
+ describe('volatile-only tier handling', () => {
81
+ it('should return isVolatileOnly=true when only ipAddress changes', () => {
82
+ const cachedIdentity = {
83
+ identityId: 'test-id',
84
+ traits: {
85
+ emails: ['test@email.com'],
86
+ },
87
+ };
88
+ const incomingIdentity = {
89
+ identityId: 'test-id',
90
+ traits: {
91
+ emails: ['test@email.com'],
92
+ ipAddress: '10.0.0.1',
93
+ },
94
+ };
95
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
96
+ expect(result.isVolatileOnly).toBe(true);
97
+ expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.VOLATILE_ONLY);
98
+ });
99
+ it('should return isVolatileOnly=true when only userAgent changes', () => {
100
+ const cachedIdentity = {
101
+ identityId: 'test-id',
102
+ traits: {
103
+ emails: ['test@email.com'],
104
+ },
105
+ };
106
+ const incomingIdentity = {
107
+ identityId: 'test-id',
108
+ traits: {
109
+ emails: ['test@email.com'],
110
+ userAgent: 'Mozilla/5.0',
111
+ },
112
+ };
113
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
114
+ expect(result.isVolatileOnly).toBe(true);
115
+ });
116
+ it('should set isCacheStale=false for volatile-only tier (override)', () => {
117
+ const cachedIdentity = {
118
+ identityId: 'test-id',
119
+ traits: {
120
+ emails: ['test@email.com'],
121
+ },
122
+ };
123
+ const incomingIdentity = {
124
+ identityId: 'test-id',
125
+ traits: {
126
+ emails: ['test@email.com'],
127
+ ipAddress: '192.168.1.1',
128
+ userAgent: 'Chrome/100',
129
+ },
130
+ };
131
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
132
+ expect(result.isVolatileOnly).toBe(true);
133
+ expect(result.isCacheStale).toBe(false);
134
+ });
135
+ it('should set skipNeptune=true for volatile-only tier', () => {
136
+ const cachedIdentity = {
137
+ identityId: 'test-id',
138
+ traits: {
139
+ emails: ['test@email.com'],
140
+ },
141
+ };
142
+ const incomingIdentity = {
143
+ identityId: 'test-id',
144
+ traits: {
145
+ emails: ['test@email.com'],
146
+ ipAddress: '10.0.0.1',
147
+ },
148
+ };
149
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
150
+ expect(result.skipNeptune).toBe(true);
151
+ });
152
+ it('should return merged identity with volatile traits', () => {
153
+ const cachedIdentity = {
154
+ identityId: 'test-id',
155
+ traits: {
156
+ emails: ['test@email.com'],
157
+ phones: ['555-cached'],
158
+ },
159
+ };
160
+ const incomingIdentity = {
161
+ identityId: 'test-id',
162
+ traits: {
163
+ emails: ['test@email.com'],
164
+ ipAddress: '10.0.0.1',
165
+ },
166
+ };
167
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
168
+ expect(result.mergedIdentity.traits?.phones).toContain('555-cached');
169
+ expect(result.mergedIdentity.traits?.ipAddress).toBe('10.0.0.1');
170
+ });
171
+ });
172
+ describe('address update tier handling', () => {
173
+ it('should return isAddressUpdate=true when non-IP address is added', () => {
174
+ const cachedIdentity = {
175
+ identityId: 'test-id',
176
+ traits: {
177
+ emails: ['test@email.com'],
178
+ addresses: [],
179
+ },
180
+ };
181
+ const incomingIdentity = {
182
+ identityId: 'test-id',
183
+ traits: {
184
+ emails: ['test@email.com'],
185
+ addresses: [{ firstName: 'John', lastName: 'Doe', city: 'NYC' }],
186
+ },
187
+ };
188
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
189
+ expect(result.isAddressUpdate).toBe(true);
190
+ expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.ADDRESS_UPDATE);
191
+ });
192
+ it('should set writeReason=ADDRESS_UPDATE for address update tier', () => {
193
+ const cachedIdentity = {
194
+ identityId: 'test-id',
195
+ traits: {
196
+ emails: ['test@email.com'],
197
+ addresses: [],
198
+ },
199
+ };
200
+ const incomingIdentity = {
201
+ identityId: 'test-id',
202
+ traits: {
203
+ emails: ['test@email.com'],
204
+ addresses: [{ firstName: 'Jane', city: 'Boston' }],
205
+ },
206
+ };
207
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
208
+ expect(result.writeReason).toBe(CACHE_WRITE_REASON.ADDRESS_UPDATE);
209
+ });
210
+ it('should set skipNeptune=true for address update tier', () => {
211
+ const cachedIdentity = {
212
+ identityId: 'test-id',
213
+ traits: {
214
+ emails: ['test@email.com'],
215
+ addresses: [],
216
+ },
217
+ };
218
+ const incomingIdentity = {
219
+ identityId: 'test-id',
220
+ traits: {
221
+ emails: ['test@email.com'],
222
+ addresses: [{ firstName: 'Test', city: 'TestCity', zip: '12345' }],
223
+ },
224
+ };
225
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
226
+ expect(result.skipNeptune).toBe(true);
227
+ });
228
+ it('should set isCacheStale=true for address update tier', () => {
229
+ const cachedIdentity = {
230
+ identityId: 'test-id',
231
+ traits: {
232
+ emails: ['test@email.com'],
233
+ addresses: [],
234
+ },
235
+ };
236
+ const incomingIdentity = {
237
+ identityId: 'test-id',
238
+ traits: {
239
+ emails: ['test@email.com'],
240
+ addresses: [{ firstName: 'Test', city: 'TestCity' }],
241
+ },
242
+ };
243
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
244
+ expect(result.isCacheStale).toBe(true);
245
+ });
246
+ it('should NOT be address update for IP-sourced addresses', () => {
247
+ const cachedIdentity = {
248
+ identityId: 'test-id',
249
+ traits: {
250
+ emails: ['test@email.com'],
251
+ addresses: [],
252
+ },
253
+ };
254
+ const incomingIdentity = {
255
+ identityId: 'test-id',
256
+ traits: {
257
+ emails: ['test@email.com'],
258
+ addresses: [{ city: 'IPCity', country: 'US' }],
259
+ },
260
+ };
261
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
262
+ expect(result.isAddressUpdate).toBe(false);
263
+ expect(result.isVolatileOnly).toBe(true);
264
+ });
265
+ });
266
+ describe('identity stale tier handling', () => {
267
+ it('should return IDENTITY_STALE when identity-defining trait changes', () => {
268
+ const cachedIdentity = {
269
+ identityId: 'test-id',
270
+ traits: {
271
+ emails: ['old@email.com'],
272
+ },
273
+ };
274
+ const incomingIdentity = {
275
+ identityId: 'test-id',
276
+ traits: {
277
+ emails: ['old@email.com', 'new@email.com'],
278
+ },
279
+ };
280
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
281
+ expect(result.staleTier).toBe(IDENTITY_CACHE_STALENESS_TIER.IDENTITY_STALE);
282
+ expect(result.isCacheStale).toBe(true);
283
+ });
284
+ it('should set writeReason=STALE_TRAITS for identity stale tier', () => {
285
+ const cachedIdentity = {
286
+ identityId: 'test-id',
287
+ traits: {
288
+ emails: ['test@email.com'],
289
+ phones: ['555-old'],
290
+ },
291
+ };
292
+ const incomingIdentity = {
293
+ identityId: 'test-id',
294
+ traits: {
295
+ emails: ['test@email.com'],
296
+ phones: ['555-old', '555-new'],
297
+ },
298
+ };
299
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
300
+ expect(result.writeReason).toBe(CACHE_WRITE_REASON.STALE_TRAITS);
301
+ });
302
+ it('should set skipNeptune=false for identity stale tier', () => {
303
+ const cachedIdentity = {
304
+ identityId: 'test-id',
305
+ traits: {
306
+ emails: ['test@email.com'],
307
+ },
308
+ };
309
+ const incomingIdentity = {
310
+ identityId: 'test-id',
311
+ traits: {
312
+ emails: ['test@email.com'],
313
+ userIds: ['user-123'],
314
+ },
315
+ };
316
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
317
+ expect(result.skipNeptune).toBe(false);
318
+ });
319
+ it('should populate staleTraits with changed trait names', () => {
320
+ const cachedIdentity = {
321
+ identityId: 'test-id',
322
+ traits: {
323
+ emails: ['old@email.com'],
324
+ },
325
+ };
326
+ const incomingIdentity = {
327
+ identityId: 'test-id',
328
+ traits: {
329
+ emails: ['old@email.com', 'new@email.com'],
330
+ phones: ['555-new'],
331
+ },
332
+ };
333
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
334
+ expect(result.staleTraits).toContain('emails');
335
+ expect(result.staleTraits).toContain('phones');
336
+ });
337
+ });
338
+ describe('deep equality override for isCacheStale', () => {
339
+ it('should set isCacheStale=false when deep equal regardless of staleness computation', () => {
340
+ const cachedIdentity = {
341
+ identityId: 'test-id',
342
+ traits: {
343
+ emails: ['test@email.com'],
344
+ },
345
+ };
346
+ const incomingIdentity = {
347
+ identityId: 'test-id',
348
+ traits: {
349
+ emails: ['test@email.com'],
350
+ },
351
+ };
352
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
353
+ expect(result.isDeepEqual).toBe(true);
354
+ expect(result.isCacheStale).toBe(false);
355
+ });
356
+ });
357
+ describe('staleTracker population', () => {
358
+ it('should return populated staleTracker from mergeAndComputeIdentityStaleness', () => {
359
+ const cachedIdentity = {
360
+ identityId: 'test-id',
361
+ traits: {
362
+ emails: ['old@email.com'],
363
+ },
364
+ };
365
+ const incomingIdentity = {
366
+ identityId: 'test-id',
367
+ traits: {
368
+ emails: ['old@email.com', 'new@email.com'],
369
+ },
370
+ };
371
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
372
+ expect(result.staleTracker).toBeDefined();
373
+ expect(result.staleTracker.isEmailsStale).toBe(true);
374
+ });
375
+ });
376
+ describe('merged identity correctness', () => {
377
+ it('should merge traits from both incoming and cached', () => {
378
+ const cachedIdentity = {
379
+ identityId: 'test-id',
380
+ traits: {
381
+ emails: ['cached@email.com'],
382
+ phones: ['555-cached'],
383
+ },
384
+ };
385
+ const incomingIdentity = {
386
+ identityId: 'test-id',
387
+ traits: {
388
+ emails: ['cached@email.com', 'new@email.com'],
389
+ },
390
+ };
391
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
392
+ expect(result.mergedIdentity.traits?.emails).toContain('cached@email.com');
393
+ expect(result.mergedIdentity.traits?.emails).toContain('new@email.com');
394
+ expect(result.mergedIdentity.traits?.phones).toContain('555-cached');
395
+ });
396
+ it('should preserve identityId from incoming (incoming spreads first)', () => {
397
+ const cachedIdentity = {
398
+ identityId: 'cached-identity-id',
399
+ traits: { emails: ['test@email.com'] },
400
+ };
401
+ const incomingIdentity = {
402
+ identityId: 'incoming-identity-id',
403
+ traits: { emails: ['test@email.com'] },
404
+ };
405
+ const result = processCacheHit(incomingIdentity, cachedIdentity);
406
+ expect(result.mergedIdentity.identityId).toBe('incoming-identity-id');
407
+ });
408
+ });
409
+ });
410
+ describe('stripAddressTimestamps helper', () => {
411
+ it('should remove cra and upa from addresses', () => {
412
+ const identity = {
413
+ identityId: 'test',
414
+ traits: {
415
+ addresses: [
416
+ { city: 'NYC', cra: 1234567890, upa: 1234567899 },
417
+ { city: 'LA', cra: 9876543210, upa: 9876543219 },
418
+ ],
419
+ },
420
+ };
421
+ const result = stripAddressTimestamps(identity);
422
+ expect(result.traits?.addresses?.[0]).not.toHaveProperty('cra');
423
+ expect(result.traits?.addresses?.[0]).not.toHaveProperty('upa');
424
+ expect(result.traits?.addresses?.[0]?.city).toBe('NYC');
425
+ expect(result.traits?.addresses?.[1]).not.toHaveProperty('cra');
426
+ expect(result.traits?.addresses?.[1]).not.toHaveProperty('upa');
427
+ expect(result.traits?.addresses?.[1]?.city).toBe('LA');
428
+ });
429
+ it('should return original identity if no addresses', () => {
430
+ const identity = {
431
+ identityId: 'test',
432
+ traits: {
433
+ emails: ['test@email.com'],
434
+ },
435
+ };
436
+ const result = stripAddressTimestamps(identity);
437
+ expect(result).toEqual(identity);
438
+ });
439
+ it('should return original identity if addresses array is empty', () => {
440
+ const identity = {
441
+ identityId: 'test',
442
+ traits: {
443
+ addresses: [],
444
+ },
445
+ };
446
+ const result = stripAddressTimestamps(identity);
447
+ expect(result).toEqual(identity);
448
+ });
449
+ it('should preserve other address fields', () => {
450
+ const identity = {
451
+ identityId: 'test',
452
+ traits: {
453
+ addresses: [
454
+ {
455
+ firstName: 'John',
456
+ lastName: 'Doe',
457
+ city: 'NYC',
458
+ zip: '10001',
459
+ country: 'US',
460
+ cra: 123456,
461
+ upa: 789012,
462
+ },
463
+ ],
464
+ },
465
+ };
466
+ const result = stripAddressTimestamps(identity);
467
+ const addr = result.traits?.addresses?.[0];
468
+ expect(addr?.firstName).toBe('John');
469
+ expect(addr?.lastName).toBe('Doe');
470
+ expect(addr?.city).toBe('NYC');
471
+ expect(addr?.zip).toBe('10001');
472
+ expect(addr?.country).toBe('US');
473
+ expect(addr).not.toHaveProperty('cra');
474
+ expect(addr).not.toHaveProperty('upa');
475
+ });
476
+ });
477
+ describe('computeTraitChanges helper', () => {
478
+ it('should detect email changes', () => {
479
+ const cached = {
480
+ identityId: 'test',
481
+ traits: { emails: ['old@email.com'] },
482
+ };
483
+ const resolved = {
484
+ identityId: 'test',
485
+ traits: { emails: ['old@email.com', 'new@email.com'] },
486
+ };
487
+ const changes = computeTraitChanges(cached, resolved);
488
+ expect(changes.emails).toBeDefined();
489
+ expect(changes.emails?.cached).toEqual(['old@email.com']);
490
+ expect(changes.emails?.resolved).toEqual(['old@email.com', 'new@email.com']);
491
+ });
492
+ it('should detect phone changes', () => {
493
+ const cached = {
494
+ identityId: 'test',
495
+ traits: { phones: ['555-old'] },
496
+ };
497
+ const resolved = {
498
+ identityId: 'test',
499
+ traits: { phones: ['555-old', '555-new'] },
500
+ };
501
+ const changes = computeTraitChanges(cached, resolved);
502
+ expect(changes.phones).toBeDefined();
503
+ expect(changes.phones?.cached).toEqual(['555-old']);
504
+ expect(changes.phones?.resolved).toContain('555-new');
505
+ });
506
+ it('should detect address changes', () => {
507
+ const cached = {
508
+ identityId: 'test',
509
+ traits: { addresses: [{ city: 'NYC' }] },
510
+ };
511
+ const resolved = {
512
+ identityId: 'test',
513
+ traits: { addresses: [{ city: 'NYC' }, { city: 'LA' }] },
514
+ };
515
+ const changes = computeTraitChanges(cached, resolved);
516
+ expect(changes.addresses).toBeDefined();
517
+ });
518
+ it('should detect identityId changes', () => {
519
+ const cached = {
520
+ identityId: 'old-id',
521
+ traits: {},
522
+ };
523
+ const resolved = {
524
+ identityId: 'new-id',
525
+ traits: {},
526
+ };
527
+ const changes = computeTraitChanges(cached, resolved);
528
+ expect(changes.identityId).toBeDefined();
529
+ expect(changes.identityId?.cached).toBe('old-id');
530
+ expect(changes.identityId?.resolved).toBe('new-id');
531
+ });
532
+ it('should detect ipAddress changes', () => {
533
+ const cached = {
534
+ identityId: 'test',
535
+ traits: { ipAddress: '10.0.0.1' },
536
+ };
537
+ const resolved = {
538
+ identityId: 'test',
539
+ traits: { ipAddress: '10.0.0.2' },
540
+ };
541
+ const changes = computeTraitChanges(cached, resolved);
542
+ expect(changes.ipAddress).toBeDefined();
543
+ expect(changes.ipAddress?.cached).toBe('10.0.0.1');
544
+ expect(changes.ipAddress?.resolved).toBe('10.0.0.2');
545
+ });
546
+ it('should detect userAgent changes', () => {
547
+ const cached = {
548
+ identityId: 'test',
549
+ traits: { userAgent: 'Mozilla/5.0 Old' },
550
+ };
551
+ const resolved = {
552
+ identityId: 'test',
553
+ traits: { userAgent: 'Mozilla/5.0 New' },
554
+ };
555
+ const changes = computeTraitChanges(cached, resolved);
556
+ expect(changes.userAgent).toBeDefined();
557
+ });
558
+ it('should not include unchanged traits', () => {
559
+ const cached = {
560
+ identityId: 'test',
561
+ traits: {
562
+ emails: ['same@email.com'],
563
+ phones: ['555-same'],
564
+ },
565
+ };
566
+ const resolved = {
567
+ identityId: 'test',
568
+ traits: {
569
+ emails: ['same@email.com'],
570
+ phones: ['555-same'],
571
+ },
572
+ };
573
+ const changes = computeTraitChanges(cached, resolved);
574
+ expect(changes.emails).toBeUndefined();
575
+ expect(changes.phones).toBeUndefined();
576
+ });
577
+ it('should handle undefined traits gracefully', () => {
578
+ const cached = {
579
+ identityId: 'test',
580
+ traits: undefined,
581
+ };
582
+ const resolved = {
583
+ identityId: 'test',
584
+ traits: { emails: ['new@email.com'] },
585
+ };
586
+ const changes = computeTraitChanges(cached, resolved);
587
+ expect(changes.emails).toBeDefined();
588
+ expect(changes.emails?.cached).toEqual([]);
589
+ expect(changes.emails?.resolved).toEqual(['new@email.com']);
590
+ });
591
+ });
592
+ //# sourceMappingURL=helpers.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.spec.js","sourceRoot":"","sources":["../../../../src/__tests__/identity-cache/helpers.spec.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,8DAA8D,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAEhG,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IAStC,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,MAAM,EAAE,CAAC,UAAU,CAAC;iBACrB;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,MAAM,EAAE,CAAC,UAAU,CAAC;iBACrB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,CAAC;iBAC1B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;iBAC3C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAIvB,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,EAAE,CAAC;iBACnF;aACF,CAAC;YAIF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAG3B;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAIjE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;YACnF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEvB,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;iBACvC;aACF,CAAC;YAGF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;iBAC1C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAE3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,UAAU;iBACtB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,aAAa,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAE3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,aAAa;iBACzB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAC3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,aAAa;oBACxB,SAAS,EAAE,YAAY;iBACxB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAGjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAC3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,UAAU;iBACtB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,MAAM,EAAE,CAAC,YAAY,CAAC;iBACvB;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,UAAU;iBACtB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAGjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACrE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,EAAE;iBACd;aACF,CAAC;YAGF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;iBACjE;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,cAAc,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,EAAE;iBACd;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;iBACnD;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,EAAE;iBACd;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;iBACnE;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,EAAE;iBACd;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;iBACrD;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAGjE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,EAAE;iBACd;aACF,CAAC;YAGF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iBAC/C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAGjE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;YAC3E,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,CAAC;iBAC1B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;iBAC3C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,cAAc,CAAC,CAAC;YAC5E,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,MAAM,EAAE,CAAC,SAAS,CAAC;iBACpB;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;iBAC/B;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAC3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;oBAC1B,OAAO,EAAE,CAAC,UAAU,CAAC;iBACtB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,CAAC;iBAC1B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;oBAC1C,MAAM,EAAE,CAAC,SAAS,CAAC;iBACpB;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACvD,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;YAG3F,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAC3B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;iBAC3B;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;YACpF,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,CAAC;iBAC1B;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;iBAC3C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAEjE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,kBAAkB,CAAC;oBAC5B,MAAM,EAAE,CAAC,YAAY,CAAC;iBACvB;aACF,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,SAAS;gBACrB,MAAM,EAAE;oBACN,MAAM,EAAE,CAAC,kBAAkB,EAAE,eAAe,CAAC;iBAC9C;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAGjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAC3E,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YACxE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;YAC3E,MAAM,cAAc,GAAkB;gBACpC,UAAU,EAAE,oBAAoB;gBAChC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;aACvC,CAAC;YAEF,MAAM,gBAAgB,GAAkB;gBACtC,UAAU,EAAE,sBAAsB;gBAClC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;aACvC,CAAC;YAEF,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAIjE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE;oBACjD,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE;iBACjD;aACF;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;aAC3B;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,SAAS,EAAE,EAAE;aACd;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT;wBACE,SAAS,EAAE,MAAM;wBACjB,QAAQ,EAAE,KAAK;wBACf,IAAI,EAAE,KAAK;wBACX,GAAG,EAAE,OAAO;wBACZ,OAAO,EAAE,IAAI;wBACb,GAAG,EAAE,MAAM;wBACX,GAAG,EAAE,MAAM;qBACZ;iBACF;aACF;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE;SACtC,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE;SACvD,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;SAChC,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE;SAC3C,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;SACzC,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE;SACzD,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,EAAE;SACX,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;SAClC,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE;SAClC,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE;SACzC,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE;SACzC,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;gBAC1B,MAAM,EAAE,CAAC,UAAU,CAAC;aACrB;SACF,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE;gBACN,MAAM,EAAE,CAAC,gBAAgB,CAAC;gBAC1B,MAAM,EAAE,CAAC,UAAU,CAAC;aACrB;SACF,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,MAAM,GAAkB;YAC5B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,MAAM;YAClB,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE;SACtC,CAAC;QAEF,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}