@farukada/aws-langgraph-dynamodb-ts 0.1.0 → 0.2.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 (153) hide show
  1. package/README.md +131 -5
  2. package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
  3. package/dist/checkpointer/actions/delete-thread.js +17 -9
  4. package/dist/checkpointer/actions/delete-thread.js.map +1 -1
  5. package/dist/checkpointer/actions/get-tuple.d.ts.map +1 -1
  6. package/dist/checkpointer/actions/get-tuple.js +70 -32
  7. package/dist/checkpointer/actions/get-tuple.js.map +1 -1
  8. package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
  9. package/dist/checkpointer/actions/put-writes.js +36 -19
  10. package/dist/checkpointer/actions/put-writes.js.map +1 -1
  11. package/dist/checkpointer/actions/put.d.ts.map +1 -1
  12. package/dist/checkpointer/actions/put.js +75 -18
  13. package/dist/checkpointer/actions/put.js.map +1 -1
  14. package/dist/checkpointer/actions/writer.d.ts +6 -4
  15. package/dist/checkpointer/actions/writer.d.ts.map +1 -1
  16. package/dist/checkpointer/actions/writer.js +12 -12
  17. package/dist/checkpointer/actions/writer.js.map +1 -1
  18. package/dist/checkpointer/index.d.ts +11 -4
  19. package/dist/checkpointer/index.d.ts.map +1 -1
  20. package/dist/checkpointer/index.js +97 -72
  21. package/dist/checkpointer/index.js.map +1 -1
  22. package/dist/checkpointer/types/index.d.ts +8 -0
  23. package/dist/checkpointer/types/index.d.ts.map +1 -1
  24. package/dist/checkpointer/utils/deserialization.d.ts.map +1 -1
  25. package/dist/checkpointer/utils/deserialization.js +28 -4
  26. package/dist/checkpointer/utils/deserialization.js.map +1 -1
  27. package/dist/checkpointer/utils/validation.d.ts +8 -8
  28. package/dist/checkpointer/utils/validation.d.ts.map +1 -1
  29. package/dist/checkpointer/utils/validation.js +45 -1
  30. package/dist/checkpointer/utils/validation.js.map +1 -1
  31. package/dist/factory.d.ts +14 -0
  32. package/dist/factory.d.ts.map +1 -1
  33. package/dist/factory.js +39 -20
  34. package/dist/factory.js.map +1 -1
  35. package/dist/history/actions/add-message.d.ts +5 -9
  36. package/dist/history/actions/add-message.d.ts.map +1 -1
  37. package/dist/history/actions/add-message.js +14 -42
  38. package/dist/history/actions/add-message.js.map +1 -1
  39. package/dist/history/actions/add-messages.d.ts +6 -10
  40. package/dist/history/actions/add-messages.d.ts.map +1 -1
  41. package/dist/history/actions/add-messages.js +33 -38
  42. package/dist/history/actions/add-messages.js.map +1 -1
  43. package/dist/history/actions/clear.d.ts.map +1 -1
  44. package/dist/history/actions/clear.js +3 -3
  45. package/dist/history/actions/clear.js.map +1 -1
  46. package/dist/history/actions/get-messages.d.ts.map +1 -1
  47. package/dist/history/actions/get-messages.js +2 -2
  48. package/dist/history/actions/get-messages.js.map +1 -1
  49. package/dist/history/actions/list-sessions.d.ts.map +1 -1
  50. package/dist/history/actions/list-sessions.js +6 -3
  51. package/dist/history/actions/list-sessions.js.map +1 -1
  52. package/dist/history/index.d.ts +41 -5
  53. package/dist/history/index.d.ts.map +1 -1
  54. package/dist/history/index.js +52 -18
  55. package/dist/history/index.js.map +1 -1
  56. package/dist/history/session-adapter.d.ts +39 -0
  57. package/dist/history/session-adapter.d.ts.map +1 -0
  58. package/dist/history/session-adapter.js +74 -0
  59. package/dist/history/session-adapter.js.map +1 -0
  60. package/dist/history/types/index.d.ts +32 -1
  61. package/dist/history/types/index.d.ts.map +1 -1
  62. package/dist/history/utils/index.d.ts +1 -0
  63. package/dist/history/utils/index.d.ts.map +1 -1
  64. package/dist/history/utils/index.js +1 -0
  65. package/dist/history/utils/index.js.map +1 -1
  66. package/dist/history/utils/optimistic-retry.d.ts +31 -0
  67. package/dist/history/utils/optimistic-retry.d.ts.map +1 -0
  68. package/dist/history/utils/optimistic-retry.js +74 -0
  69. package/dist/history/utils/optimistic-retry.js.map +1 -0
  70. package/dist/history/utils/title-generator.d.ts.map +1 -1
  71. package/dist/history/utils/title-generator.js +8 -3
  72. package/dist/history/utils/title-generator.js.map +1 -1
  73. package/dist/history/utils/update-expression-builder.d.ts +18 -21
  74. package/dist/history/utils/update-expression-builder.d.ts.map +1 -1
  75. package/dist/history/utils/update-expression-builder.js +31 -46
  76. package/dist/history/utils/update-expression-builder.js.map +1 -1
  77. package/dist/history/utils/validation.d.ts.map +1 -1
  78. package/dist/history/utils/validation.js +23 -3
  79. package/dist/history/utils/validation.js.map +1 -1
  80. package/dist/index.d.ts +6 -2
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +6 -1
  83. package/dist/index.js.map +1 -1
  84. package/dist/shared/utils/batch-write.d.ts +44 -6
  85. package/dist/shared/utils/batch-write.d.ts.map +1 -1
  86. package/dist/shared/utils/batch-write.js +76 -28
  87. package/dist/shared/utils/batch-write.js.map +1 -1
  88. package/dist/shared/utils/client-factory.d.ts +25 -0
  89. package/dist/shared/utils/client-factory.d.ts.map +1 -0
  90. package/dist/shared/utils/client-factory.js +23 -0
  91. package/dist/shared/utils/client-factory.js.map +1 -0
  92. package/dist/shared/utils/compressor.d.ts +21 -3
  93. package/dist/shared/utils/compressor.d.ts.map +1 -1
  94. package/dist/shared/utils/compressor.js +75 -10
  95. package/dist/shared/utils/compressor.js.map +1 -1
  96. package/dist/shared/utils/constants.d.ts +1 -1
  97. package/dist/shared/utils/constants.d.ts.map +1 -1
  98. package/dist/shared/utils/constants.js +5 -1
  99. package/dist/shared/utils/constants.js.map +1 -1
  100. package/dist/shared/utils/index.d.ts +3 -0
  101. package/dist/shared/utils/index.d.ts.map +1 -1
  102. package/dist/shared/utils/index.js +3 -0
  103. package/dist/shared/utils/index.js.map +1 -1
  104. package/dist/shared/utils/logger.d.ts +27 -0
  105. package/dist/shared/utils/logger.d.ts.map +1 -1
  106. package/dist/shared/utils/logger.js +86 -0
  107. package/dist/shared/utils/logger.js.map +1 -1
  108. package/dist/shared/utils/retry.d.ts +7 -0
  109. package/dist/shared/utils/retry.d.ts.map +1 -1
  110. package/dist/shared/utils/retry.js +75 -17
  111. package/dist/shared/utils/retry.js.map +1 -1
  112. package/dist/shared/utils/s3-offloader.d.ts +10 -3
  113. package/dist/shared/utils/s3-offloader.d.ts.map +1 -1
  114. package/dist/shared/utils/s3-offloader.js +19 -9
  115. package/dist/shared/utils/s3-offloader.js.map +1 -1
  116. package/dist/shared/utils/s3-orphans.d.ts +16 -0
  117. package/dist/shared/utils/s3-orphans.d.ts.map +1 -0
  118. package/dist/shared/utils/s3-orphans.js +79 -0
  119. package/dist/shared/utils/s3-orphans.js.map +1 -0
  120. package/dist/shared/utils/sleep.d.ts +48 -0
  121. package/dist/shared/utils/sleep.d.ts.map +1 -0
  122. package/dist/shared/utils/sleep.js +82 -0
  123. package/dist/shared/utils/sleep.js.map +1 -0
  124. package/dist/shared/utils/ttl.d.ts +6 -2
  125. package/dist/shared/utils/ttl.d.ts.map +1 -1
  126. package/dist/shared/utils/ttl.js +17 -2
  127. package/dist/shared/utils/ttl.js.map +1 -1
  128. package/dist/store/actions/get-operation.d.ts.map +1 -1
  129. package/dist/store/actions/get-operation.js +2 -2
  130. package/dist/store/actions/get-operation.js.map +1 -1
  131. package/dist/store/actions/list-namespaces-operation.d.ts.map +1 -1
  132. package/dist/store/actions/list-namespaces-operation.js +44 -29
  133. package/dist/store/actions/list-namespaces-operation.js.map +1 -1
  134. package/dist/store/actions/put-operation.d.ts.map +1 -1
  135. package/dist/store/actions/put-operation.js +19 -5
  136. package/dist/store/actions/put-operation.js.map +1 -1
  137. package/dist/store/actions/search-operation.d.ts.map +1 -1
  138. package/dist/store/actions/search-operation.js +54 -21
  139. package/dist/store/actions/search-operation.js.map +1 -1
  140. package/dist/store/index.d.ts +1 -0
  141. package/dist/store/index.d.ts.map +1 -1
  142. package/dist/store/index.js +24 -20
  143. package/dist/store/index.js.map +1 -1
  144. package/dist/store/types/index.d.ts +33 -1
  145. package/dist/store/types/index.d.ts.map +1 -1
  146. package/dist/store/utils/filter.d.ts.map +1 -1
  147. package/dist/store/utils/filter.js +63 -1
  148. package/dist/store/utils/filter.js.map +1 -1
  149. package/dist/store/utils/validation.d.ts +6 -2
  150. package/dist/store/utils/validation.d.ts.map +1 -1
  151. package/dist/store/utils/validation.js +21 -5
  152. package/dist/store/utils/validation.js.map +1 -1
  153. package/package.json +36 -25
@@ -15,22 +15,60 @@ interface DeleteWriteRequest {
15
15
  }
16
16
  type WriteRequest = PutWriteRequest | DeleteWriteRequest;
17
17
  /**
18
- * Execute a single batchWrite call with exponential backoff retry for UnprocessedItems
18
+ * Error thrown when `batchWriteWithRetry` / `batchWriteAllWithRetry` exhaust
19
+ * their UnprocessedItems retry budget. Carries enough information for the
20
+ * caller to reason about recovery: how many items persisted before the giveup,
21
+ * how many are still un-acked, and which items remained un-acked.
22
+ *
23
+ * *Partial-success semantics:* DynamoDB's BatchWriteItem is not atomic across
24
+ * items in a batch, and `batchWriteAllWithRetry` issues a sequence of 25-item
25
+ * batches. When this error is thrown, any item not listed in `unprocessed` has
26
+ * already been acked by DynamoDB. Callers that need all-or-nothing must drive
27
+ * reconciliation from `unprocessed` (retry, compensating delete, or surface to
28
+ * the user) — this helper cannot roll back the successful rows for you.
29
+ */
30
+ export declare class BatchWriteIncompleteError extends Error {
31
+ readonly succeededCount: number;
32
+ readonly unprocessed: WriteRequest[];
33
+ constructor(succeededCount: number, unprocessed: WriteRequest[], retries: number);
34
+ }
35
+ export interface BatchWriteOptions {
36
+ /** Optional AbortSignal — short-circuits retry backoff and rejects with the abort reason. */
37
+ signal?: AbortSignal;
38
+ }
39
+ /**
40
+ * Execute a single batchWrite call with exponential backoff retry for UnprocessedItems.
41
+ *
42
+ * @remarks
43
+ * On exhaustion of the UnprocessedItems retry budget this throws a
44
+ * {@link BatchWriteIncompleteError} that carries the un-acked items — items
45
+ * NOT listed there were acked by DynamoDB and persist in the table. There is
46
+ * no rollback: callers that need an all-or-nothing write must use
47
+ * `TransactWriteItems` (capped at 100 items per request) instead of this
48
+ * helper.
19
49
  *
20
50
  * @param client - DynamoDB Document client
21
51
  * @param tableName - Target DynamoDB table name
22
52
  * @param requestItems - Array of write requests (PutRequest or DeleteRequest objects)
23
- * @throws Error if retries are exhausted with remaining unprocessed items
53
+ * @param options.signal - Optional AbortSignal cancelling in-flight retries
54
+ * @throws {BatchWriteIncompleteError} if retries are exhausted with items still unprocessed
24
55
  */
25
- export declare function batchWriteWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[]): Promise<void>;
56
+ export declare function batchWriteWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[], options?: BatchWriteOptions): Promise<void>;
26
57
  /**
27
- * Execute batch writes for an arbitrary number of items, chunking into batches of 25
58
+ * Execute batch writes for an arbitrary number of items, chunking into batches of 25.
59
+ *
60
+ * @remarks
61
+ * Each batch is retried independently. On failure of one batch, any preceding
62
+ * batches in the same call have already been acked by DynamoDB. This helper
63
+ * does not span a transaction across batches — see
64
+ * {@link batchWriteWithRetry} for the partial-success contract.
28
65
  *
29
66
  * @param client - DynamoDB Document client
30
67
  * @param tableName - Target DynamoDB table name
31
68
  * @param requestItems - Array of write requests (can exceed 25)
32
- * @throws Error if any batch fails after exhausting retries
69
+ * @param options.signal - Optional AbortSignal cancelling in-flight retries
70
+ * @throws {BatchWriteIncompleteError} if any batch fails after exhausting retries
33
71
  */
34
- export declare function batchWriteAllWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[]): Promise<void>;
72
+ export declare function batchWriteAllWithRetry(client: DynamoDBDocument, tableName: string, requestItems: WriteRequest[], options?: BatchWriteOptions): Promise<void>;
35
73
  export {};
36
74
  //# sourceMappingURL=batch-write.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAK9D,UAAU,eAAe;IACvB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED,UAAU,kBAAkB;IAC1B,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAED,KAAK,YAAY,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAOf"}
1
+ {"version":3,"file":"batch-write.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAM9D,UAAU,eAAe;IACvB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED,UAAU,kBAAkB;IAC1B,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAChC;AAED,KAAK,YAAY,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC;gBAEzB,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM;CAUjF;AAED,MAAM,WAAW,iBAAiB;IAChC,6FAA6F;IAC7F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,EAAE,EAC5B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -4,59 +4,107 @@
4
4
  * Eliminates duplication of the retry pattern across checkpointer, store, and history modules
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BatchWriteIncompleteError = void 0;
7
8
  exports.batchWriteWithRetry = batchWriteWithRetry;
8
9
  exports.batchWriteAllWithRetry = batchWriteAllWithRetry;
9
10
  const constants_1 = require("./constants");
10
11
  const retry_1 = require("./retry");
12
+ const sleep_1 = require("./sleep");
11
13
  /**
12
- * Execute a single batchWrite call with exponential backoff retry for UnprocessedItems
14
+ * Error thrown when `batchWriteWithRetry` / `batchWriteAllWithRetry` exhaust
15
+ * their UnprocessedItems retry budget. Carries enough information for the
16
+ * caller to reason about recovery: how many items persisted before the giveup,
17
+ * how many are still un-acked, and which items remained un-acked.
18
+ *
19
+ * *Partial-success semantics:* DynamoDB's BatchWriteItem is not atomic across
20
+ * items in a batch, and `batchWriteAllWithRetry` issues a sequence of 25-item
21
+ * batches. When this error is thrown, any item not listed in `unprocessed` has
22
+ * already been acked by DynamoDB. Callers that need all-or-nothing must drive
23
+ * reconciliation from `unprocessed` (retry, compensating delete, or surface to
24
+ * the user) — this helper cannot roll back the successful rows for you.
25
+ */
26
+ class BatchWriteIncompleteError extends Error {
27
+ succeededCount;
28
+ unprocessed;
29
+ constructor(succeededCount, unprocessed, retries) {
30
+ super(`batchWrite did not drain after ${retries} UnprocessedItems retries: ` +
31
+ `${succeededCount} item(s) persisted, ${unprocessed.length} still un-acked. ` +
32
+ `Inspect err.unprocessed to drive reconciliation.`);
33
+ this.name = 'BatchWriteIncompleteError';
34
+ this.succeededCount = succeededCount;
35
+ this.unprocessed = unprocessed;
36
+ }
37
+ }
38
+ exports.BatchWriteIncompleteError = BatchWriteIncompleteError;
39
+ /**
40
+ * Execute a single batchWrite call with exponential backoff retry for UnprocessedItems.
41
+ *
42
+ * @remarks
43
+ * On exhaustion of the UnprocessedItems retry budget this throws a
44
+ * {@link BatchWriteIncompleteError} that carries the un-acked items — items
45
+ * NOT listed there were acked by DynamoDB and persist in the table. There is
46
+ * no rollback: callers that need an all-or-nothing write must use
47
+ * `TransactWriteItems` (capped at 100 items per request) instead of this
48
+ * helper.
13
49
  *
14
50
  * @param client - DynamoDB Document client
15
51
  * @param tableName - Target DynamoDB table name
16
52
  * @param requestItems - Array of write requests (PutRequest or DeleteRequest objects)
17
- * @throws Error if retries are exhausted with remaining unprocessed items
53
+ * @param options.signal - Optional AbortSignal cancelling in-flight retries
54
+ * @throws {BatchWriteIncompleteError} if retries are exhausted with items still unprocessed
18
55
  */
19
- async function batchWriteWithRetry(client, tableName, requestItems) {
56
+ async function batchWriteWithRetry(client, tableName, requestItems, options = {}) {
20
57
  if (requestItems.length === 0)
21
58
  return;
22
- await (0, retry_1.withDynamoDBRetry)(async () => {
23
- const result = await client.batchWrite({
24
- RequestItems: {
25
- [tableName]: requestItems,
26
- },
27
- });
28
- let unprocessed = result.UnprocessedItems?.[tableName];
29
- let retryDelay = 100;
30
- let retryCount = 0;
31
- while (unprocessed && unprocessed.length > 0) {
32
- retryCount++;
33
- if (retryCount > constants_1.MAX_UNPROCESSED_RETRIES) {
34
- throw new Error(`Failed to process all items after ${constants_1.MAX_UNPROCESSED_RETRIES} retries. ` +
35
- `${unprocessed.length} items remain unprocessed.`);
36
- }
37
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
38
- retryDelay = Math.min(retryDelay * 2, 5000);
39
- const retryResult = await client.batchWrite({
40
- RequestItems: { [tableName]: unprocessed },
59
+ // Loop over UnprocessedItems OUTSIDE the transient-error retry wrapper.
60
+ // This way a ThrottlingException during an UnprocessedItems follow-up call
61
+ // doesn't cause the outer loop to re-submit items that already succeeded —
62
+ // which would be an idempotency problem for DeleteRequests against items
63
+ // that have since been recreated.
64
+ const initialCount = requestItems.length;
65
+ let pending = requestItems;
66
+ let retryDelay = sleep_1.INITIAL_BACKOFF_DELAY_MS;
67
+ let retryCount = 0;
68
+ while (pending.length > 0) {
69
+ const result = await (0, retry_1.withDynamoDBRetry)(async () => {
70
+ return await client.batchWrite({
71
+ RequestItems: { [tableName]: pending },
41
72
  });
42
- unprocessed = retryResult.UnprocessedItems?.[tableName];
73
+ }, { signal: options.signal });
74
+ const unprocessed = result.UnprocessedItems?.[tableName] ?? [];
75
+ if (unprocessed.length === 0)
76
+ return;
77
+ retryCount++;
78
+ if (retryCount > constants_1.MAX_UNPROCESSED_RETRIES) {
79
+ throw new BatchWriteIncompleteError(initialCount - unprocessed.length, unprocessed, constants_1.MAX_UNPROCESSED_RETRIES);
43
80
  }
44
- });
81
+ // Full jitter so concurrent batch writers don't re-pressure the partition together.
82
+ await (0, sleep_1.sleep)((0, sleep_1.fullJitter)(retryDelay), options.signal);
83
+ retryDelay = (0, sleep_1.nextBackoffDelay)(retryDelay);
84
+ pending = unprocessed;
85
+ }
45
86
  }
46
87
  /**
47
- * Execute batch writes for an arbitrary number of items, chunking into batches of 25
88
+ * Execute batch writes for an arbitrary number of items, chunking into batches of 25.
89
+ *
90
+ * @remarks
91
+ * Each batch is retried independently. On failure of one batch, any preceding
92
+ * batches in the same call have already been acked by DynamoDB. This helper
93
+ * does not span a transaction across batches — see
94
+ * {@link batchWriteWithRetry} for the partial-success contract.
48
95
  *
49
96
  * @param client - DynamoDB Document client
50
97
  * @param tableName - Target DynamoDB table name
51
98
  * @param requestItems - Array of write requests (can exceed 25)
52
- * @throws Error if any batch fails after exhausting retries
99
+ * @param options.signal - Optional AbortSignal cancelling in-flight retries
100
+ * @throws {BatchWriteIncompleteError} if any batch fails after exhausting retries
53
101
  */
54
- async function batchWriteAllWithRetry(client, tableName, requestItems) {
102
+ async function batchWriteAllWithRetry(client, tableName, requestItems, options = {}) {
55
103
  if (requestItems.length === 0)
56
104
  return;
57
105
  for (let i = 0; i < requestItems.length; i += constants_1.BATCH_WRITE_MAX) {
58
106
  const batch = requestItems.slice(i, i + constants_1.BATCH_WRITE_MAX);
59
- await batchWriteWithRetry(client, tableName, batch);
107
+ await batchWriteWithRetry(client, tableName, batch, options);
60
108
  }
61
109
  }
62
110
  //# sourceMappingURL=batch-write.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAyBH,kDAiCC;AAUD,wDAWC;AA3ED,2CAAuE;AACvE,mCAA4C;AAY5C;;;;;;;GAOG;AACI,KAAK,UAAU,mBAAmB,CACvC,MAAwB,EACxB,SAAiB,EACjB,YAA4B;IAE5B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,MAAM,IAAA,yBAAiB,EAAC,KAAK,IAAI,EAAE;QACjC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACrC,YAAY,EAAE;gBACZ,CAAC,SAAS,CAAC,EAAE,YAAY;aAC1B;SACF,CAAC,CAAC;QAEH,IAAI,WAAW,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,OAAO,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,UAAU,EAAE,CAAC;YACb,IAAI,UAAU,GAAG,mCAAuB,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CACb,qCAAqC,mCAAuB,YAAY;oBACtE,GAAG,WAAW,CAAC,MAAM,4BAA4B,CACpD,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;YAChE,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;gBAC1C,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE;aAC3C,CAAC,CAAC;YACH,WAAW,GAAG,WAAW,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAAwB,EACxB,SAAiB,EACjB,YAA4B;IAE5B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,2BAAe,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,2BAAe,CAAC,CAAC;QACzD,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"batch-write.js","sourceRoot":"","sources":["../../../src/shared/utils/batch-write.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAqEH,kDA4CC;AAiBD,wDAYC;AA1ID,2CAAuE;AACvE,mCAA4C;AAC5C,mCAAwF;AAYxF;;;;;;;;;;;;GAYG;AACH,MAAa,yBAA0B,SAAQ,KAAK;IACzC,cAAc,CAAS;IACvB,WAAW,CAAiB;IAErC,YAAY,cAAsB,EAAE,WAA2B,EAAE,OAAe;QAC9E,KAAK,CACH,kCAAkC,OAAO,6BAA6B;YACpE,GAAG,cAAc,uBAAuB,WAAW,CAAC,MAAM,mBAAmB;YAC7E,kDAAkD,CACrD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAdD,8DAcC;AAOD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,mBAAmB,CACvC,MAAwB,EACxB,SAAiB,EACjB,YAA4B,EAC5B,UAA6B,EAAE;IAE/B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,wEAAwE;IACxE,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,kCAAkC;IAClC,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC;IACzC,IAAI,OAAO,GAAmB,YAAY,CAAC;IAC3C,IAAI,UAAU,GAAG,gCAAwB,CAAC;IAC1C,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EACpC,KAAK,IAAI,EAAE;YACT,OAAO,MAAM,MAAM,CAAC,UAAU,CAAC;gBAC7B,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;aACvC,CAAC,CAAC;QACL,CAAC,EACD,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAC3B,CAAC;QAEF,MAAM,WAAW,GAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC,SAAS,CAAgC,IAAI,EAAE,CAAC;QAC/F,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,UAAU,EAAE,CAAC;QACb,IAAI,UAAU,GAAG,mCAAuB,EAAE,CAAC;YACzC,MAAM,IAAI,yBAAyB,CACjC,YAAY,GAAG,WAAW,CAAC,MAAM,EACjC,WAAW,EACX,mCAAuB,CACxB,CAAC;QACJ,CAAC;QACD,oFAAoF;QACpF,MAAM,IAAA,aAAK,EAAC,IAAA,kBAAU,EAAC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACpD,UAAU,GAAG,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC;QAC1C,OAAO,GAAG,WAAW,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAAwB,EACxB,SAAiB,EACjB,YAA4B,EAC5B,UAA6B,EAAE;IAE/B,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,2BAAe,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,2BAAe,CAAC,CAAC;QACzD,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Shared DynamoDB client resolution for DynamoDBSaver / DynamoDBStore /
3
+ * DynamoDBChatMessageHistory.
4
+ *
5
+ * Each module supports two construction modes:
6
+ * 1. Pass `client` (pre-built DynamoDBDocument): we do not own it and skip cleanup.
7
+ * 2. Pass `clientConfig` (or nothing): we build our own client and own its lifecycle.
8
+ *
9
+ * This helper captures the if/else and the `ownsClient` flag in one place.
10
+ */
11
+ import { DynamoDBClient, type DynamoDBClientConfig } from '@aws-sdk/client-dynamodb';
12
+ import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
13
+ export interface ResolvedDynamoDBClient {
14
+ /** Underlying DynamoDB client — undefined when an external client was injected. */
15
+ ddbClient: DynamoDBClient | undefined;
16
+ /** DocumentClient wrapper used for all operations. */
17
+ client: DynamoDBDocument;
18
+ /** True when this library owns the underlying client and must destroy it. */
19
+ ownsClient: boolean;
20
+ }
21
+ export declare function resolveDynamoDBClient(options: {
22
+ client?: DynamoDBDocument;
23
+ clientConfig?: DynamoDBClientConfig;
24
+ }): ResolvedDynamoDBClient;
25
+ //# sourceMappingURL=client-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-factory.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/client-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,sDAAsD;IACtD,MAAM,EAAE,gBAAgB,CAAC;IACzB,6EAA6E;IAC7E,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,GAAG,sBAAsB,CAMzB"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Shared DynamoDB client resolution for DynamoDBSaver / DynamoDBStore /
4
+ * DynamoDBChatMessageHistory.
5
+ *
6
+ * Each module supports two construction modes:
7
+ * 1. Pass `client` (pre-built DynamoDBDocument): we do not own it and skip cleanup.
8
+ * 2. Pass `clientConfig` (or nothing): we build our own client and own its lifecycle.
9
+ *
10
+ * This helper captures the if/else and the `ownsClient` flag in one place.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.resolveDynamoDBClient = resolveDynamoDBClient;
14
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
15
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
16
+ function resolveDynamoDBClient(options) {
17
+ if (options.client) {
18
+ return { ddbClient: undefined, client: options.client, ownsClient: false };
19
+ }
20
+ const ddbClient = new client_dynamodb_1.DynamoDBClient(options.clientConfig || {});
21
+ return { ddbClient, client: lib_dynamodb_1.DynamoDBDocument.from(ddbClient), ownsClient: true };
22
+ }
23
+ //# sourceMappingURL=client-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-factory.js","sourceRoot":"","sources":["../../../src/shared/utils/client-factory.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAcH,sDASC;AArBD,8DAAqF;AACrF,wDAAyD;AAWzD,SAAgB,qBAAqB,CAAC,OAGrC;IACC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAC7E,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,gCAAc,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACjE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,+BAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACnF,CAAC"}
@@ -12,6 +12,12 @@ export interface CompressionConfig {
12
12
  minSizeBytes?: number;
13
13
  /** Gzip compression level 1-9 (default: 6 = balanced speed/ratio) */
14
14
  level?: number;
15
+ /**
16
+ * Hard cap on decompressed output size in bytes (default: 50 MiB).
17
+ * Protects against gzip-bomb payloads. Decompression throws if the output
18
+ * would exceed this cap.
19
+ */
20
+ maxDecompressedBytes?: number;
15
21
  }
16
22
  /**
17
23
  * Compressor for checkpoint data using gzip
@@ -24,6 +30,7 @@ export interface CompressionConfig {
24
30
  export declare class Compressor {
25
31
  private readonly minSizeBytes;
26
32
  private readonly level;
33
+ private readonly maxDecompressedBytes;
27
34
  constructor(config: CompressionConfig);
28
35
  /**
29
36
  * Compress data if above the minimum size threshold
@@ -33,15 +40,26 @@ export declare class Compressor {
33
40
  */
34
41
  compress(data: Uint8Array): Promise<Uint8Array>;
35
42
  /**
36
- * Decompress data if gzip magic header is detected, otherwise passthrough
37
- * This provides full backward compatibility with uncompressed data
43
+ * Decompress data if it is library-compressed, otherwise passthrough.
44
+ *
45
+ * Detection order:
46
+ * 1. LGC marker: new-format payloads produced by compress() above.
47
+ * 2. Gzip magic: legacy payloads from before the marker was introduced;
48
+ * decompressed for backward compatibility.
49
+ *
50
+ * Raw user binary that happens to start with the gzip magic bytes is still at
51
+ * risk under (2), but new writes use the marker and will be unambiguous.
38
52
  *
39
53
  * @param data - Potentially compressed data
40
54
  * @returns Decompressed data
41
55
  */
42
56
  decompress(data: Uint8Array): Promise<Uint8Array>;
43
57
  /**
44
- * Check if data starts with the gzip magic number
58
+ * Check if data carries the library's compression marker.
59
+ */
60
+ static hasCompressedMarker(data: Uint8Array): boolean;
61
+ /**
62
+ * Check if data starts with the gzip magic number (legacy-format detection).
45
63
  */
46
64
  static isGzipped(data: Uint8Array): boolean;
47
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,MAAM,EAAE,iBAAiB;IAKrC;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBrD;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAQvD;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;CAG5C"}
1
+ {"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAElC,MAAM,EAAE,iBAAiB;IAMrC;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBrD;;;;;;;;;;;;;OAaG;IACG,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BvD;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;IAQrD;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO;CAG5C"}
@@ -9,8 +9,28 @@ const node_util_1 = require("node:util");
9
9
  const node_zlib_1 = require("node:zlib");
10
10
  const gzipAsync = (0, node_util_1.promisify)(node_zlib_1.gzip);
11
11
  const gunzipAsync = (0, node_util_1.promisify)(node_zlib_1.gunzip);
12
- /** Gzip magic number bytes for auto-detection */
12
+ /** Gzip magic number bytes for auto-detection of legacy payloads */
13
13
  const GZIP_MAGIC = new Uint8Array([0x1f, 0x8b]);
14
+ /**
15
+ * 3-byte marker stamped at the start of new compressed payloads. Unambiguously
16
+ * identifies "this is library-compressed" so we do not try to gunzip raw binary
17
+ * that happens to start with the gzip magic bytes. Legacy payloads (pre-marker)
18
+ * are still decompressed on a gzip-magic fallback — see `decompress()`.
19
+ *
20
+ * Bytes 0x4C 0x47 0x43 spell "LGC" (LangGraph-Compressed).
21
+ */
22
+ const COMPRESSED_MARKER = new Uint8Array([0x4c, 0x47, 0x43]);
23
+ /**
24
+ * Default maximum decompressed output size: 50 MiB.
25
+ *
26
+ * Guards against "gzip bomb" payloads that are small on disk / in DynamoDB but
27
+ * expand to multi-gigabyte buffers that would OOM the process. Raise this via
28
+ * `CompressionConfig.maxDecompressedBytes` only if a legitimate workload needs
29
+ * larger checkpoints (remember: a DynamoDB item is hard-capped at 400 KB, so
30
+ * values above this threshold must originate from S3 offloading and should be
31
+ * treated with the same scrutiny).
32
+ */
33
+ const DEFAULT_MAX_DECOMPRESSED_BYTES = 50 * 1024 * 1024;
14
34
  /**
15
35
  * Compressor for checkpoint data using gzip
16
36
  *
@@ -22,9 +42,11 @@ const GZIP_MAGIC = new Uint8Array([0x1f, 0x8b]);
22
42
  class Compressor {
23
43
  minSizeBytes;
24
44
  level;
45
+ maxDecompressedBytes;
25
46
  constructor(config) {
26
47
  this.minSizeBytes = config.minSizeBytes ?? 1024;
27
48
  this.level = config.level ?? 6;
49
+ this.maxDecompressedBytes = config.maxDecompressedBytes ?? DEFAULT_MAX_DECOMPRESSED_BYTES;
28
50
  }
29
51
  /**
30
52
  * Compress data if above the minimum size threshold
@@ -37,28 +59,71 @@ class Compressor {
37
59
  return data;
38
60
  }
39
61
  const compressed = new Uint8Array(await gzipAsync(data, { level: this.level }));
40
- // Only use compressed output if it saves at least 10% space.
41
- // This avoids data expansion for already-compressed or random binary payloads.
42
- if (compressed.length >= data.length * 0.9) {
62
+ // Only use compressed output if it saves enough space to pay for the 3-byte
63
+ // marker overhead plus a reasonable margin (10%). Avoids data expansion for
64
+ // already-compressed or random binary payloads.
65
+ if (compressed.length + COMPRESSED_MARKER.length >= data.length * 0.9) {
43
66
  return data;
44
67
  }
45
- return compressed;
68
+ // Prepend the LGC marker so decompress() can unambiguously identify our output.
69
+ const out = new Uint8Array(COMPRESSED_MARKER.length + compressed.length);
70
+ out.set(COMPRESSED_MARKER, 0);
71
+ out.set(compressed, COMPRESSED_MARKER.length);
72
+ return out;
46
73
  }
47
74
  /**
48
- * Decompress data if gzip magic header is detected, otherwise passthrough
49
- * This provides full backward compatibility with uncompressed data
75
+ * Decompress data if it is library-compressed, otherwise passthrough.
76
+ *
77
+ * Detection order:
78
+ * 1. LGC marker: new-format payloads produced by compress() above.
79
+ * 2. Gzip magic: legacy payloads from before the marker was introduced;
80
+ * decompressed for backward compatibility.
81
+ *
82
+ * Raw user binary that happens to start with the gzip magic bytes is still at
83
+ * risk under (2), but new writes use the marker and will be unambiguous.
50
84
  *
51
85
  * @param data - Potentially compressed data
52
86
  * @returns Decompressed data
53
87
  */
54
88
  async decompress(data) {
55
- if (!Compressor.isGzipped(data)) {
89
+ // zlib rejects with an ERR_BUFFER_TOO_LARGE when the decompressed output
90
+ // would exceed maxOutputLength — caps memory use on hostile gzip-bomb input.
91
+ const opts = { maxOutputLength: this.maxDecompressedBytes };
92
+ try {
93
+ if (Compressor.hasCompressedMarker(data)) {
94
+ const payload = data.subarray(COMPRESSED_MARKER.length);
95
+ return new Uint8Array(await gunzipAsync(payload, opts));
96
+ }
97
+ if (Compressor.isGzipped(data)) {
98
+ // Legacy, pre-marker payload
99
+ return new Uint8Array(await gunzipAsync(data, opts));
100
+ }
56
101
  return data;
57
102
  }
58
- return new Uint8Array(await gunzipAsync(data));
103
+ catch (err) {
104
+ if (err &&
105
+ typeof err === 'object' &&
106
+ err.code === 'ERR_BUFFER_TOO_LARGE') {
107
+ throw new Error(`Refusing to decompress payload: decompressed output would exceed ${this.maxDecompressedBytes} bytes. ` +
108
+ `Raise Compressor's maxDecompressedBytes if this limit is too low.`, { cause: err });
109
+ }
110
+ throw err;
111
+ }
112
+ }
113
+ /**
114
+ * Check if data carries the library's compression marker.
115
+ */
116
+ static hasCompressedMarker(data) {
117
+ if (data.length < COMPRESSED_MARKER.length)
118
+ return false;
119
+ for (let i = 0; i < COMPRESSED_MARKER.length; i++) {
120
+ if (data[i] !== COMPRESSED_MARKER[i])
121
+ return false;
122
+ }
123
+ return true;
59
124
  }
60
125
  /**
61
- * Check if data starts with the gzip magic number
126
+ * Check if data starts with the gzip magic number (legacy-format detection).
62
127
  */
63
128
  static isGzipped(data) {
64
129
  return data.length >= 2 && data[0] === GZIP_MAGIC[0] && data[1] === GZIP_MAGIC[1];
@@ -1 +1 @@
1
- {"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yCAAsC;AACtC,yCAAyC;AAEzC,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,gBAAI,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,IAAA,qBAAS,EAAC,kBAAM,CAAC,CAAC;AAEtC,iDAAiD;AACjD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAchD;;;;;;;GAOG;AACH,MAAa,UAAU;IACJ,YAAY,CAAS;IACrB,KAAK,CAAS;IAE/B,YAAY,MAAyB;QACnC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAgB;QAC7B,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAEhF,6DAA6D;QAC7D,+EAA+E;QAC/E,IAAI,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAU,CAAC,IAAgB;QAC/B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,UAAU,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAgB;QAC/B,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;CACF;AApDD,gCAoDC"}
1
+ {"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../../src/shared/utils/compressor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,yCAAsC;AACtC,yCAAyC;AAEzC,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,gBAAI,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,IAAA,qBAAS,EAAC,kBAAM,CAAC,CAAC;AAEtC,oEAAoE;AACpE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,iBAAiB,GAAG,IAAI,UAAU,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,8BAA8B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAoBxD;;;;;;;GAOG;AACH,MAAa,UAAU;IACJ,YAAY,CAAS;IACrB,KAAK,CAAS;IACd,oBAAoB,CAAS;IAE9C,YAAY,MAAyB;QACnC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,oBAAoB,IAAI,8BAA8B,CAAC;IAC5F,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAgB;QAC7B,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAEhF,4EAA4E;QAC5E,4EAA4E;QAC5E,gDAAgD;QAChD,IAAI,UAAU,CAAC,MAAM,GAAG,iBAAiB,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gFAAgF;QAChF,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,iBAAiB,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACzE,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;QAC9B,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC9C,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,UAAU,CAAC,IAAgB;QAC/B,yEAAyE;QACzE,6EAA6E;QAC7E,MAAM,IAAI,GAAG,EAAE,eAAe,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5D,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;gBACxD,OAAO,IAAI,UAAU,CAAC,MAAM,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,6BAA6B;gBAC7B,OAAO,IAAI,UAAU,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IACE,GAAG;gBACH,OAAO,GAAG,KAAK,QAAQ;gBACtB,GAAyB,CAAC,IAAI,KAAK,sBAAsB,EAC1D,CAAC;gBACD,MAAM,IAAI,KAAK,CACb,oEAAoE,IAAI,CAAC,oBAAoB,UAAU;oBACrG,mEAAmE,EACrE,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAgB;QACzC,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;QACrD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAgB;QAC/B,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;CACF;AAnGD,gCAmGC"}
@@ -2,7 +2,7 @@
2
2
  * Shared constants for validation across store and checkpointer
3
3
  */
4
4
  export declare const MAX_TTL_DAYS: number;
5
- export declare const MAX_LOOP_ITERATIONS = 100;
5
+ export declare const MAX_LOOP_ITERATIONS = 1000;
6
6
  export declare const MAX_TOTAL_ITEMS_IN_MEMORY = 10000;
7
7
  export declare const BATCH_WRITE_MAX = 25;
8
8
  export declare const MAX_UNPROCESSED_RETRIES = 10;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,QAAU,CAAC;AACpC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAC/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgBjE"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,YAAY,QAAU,CAAC;AAKpC,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAC/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgBjE"}
@@ -7,7 +7,11 @@ exports.MAX_UNPROCESSED_RETRIES = exports.BATCH_WRITE_MAX = exports.MAX_TOTAL_IT
7
7
  exports.validateTTLDays = validateTTLDays;
8
8
  // Common DynamoDB limits
9
9
  exports.MAX_TTL_DAYS = 365 * 5; // 5 years
10
- exports.MAX_LOOP_ITERATIONS = 100; // Maximum loop iterations to prevent infinite loops
10
+ // A DynamoDB Query page is bounded by ~1MB. 1000 iterations × 1MB = ~1GB of data,
11
+ // which is well beyond MAX_TOTAL_ITEMS_IN_MEMORY anyway, so the lower memory cap
12
+ // stays the real guard. Previously 100 — too tight for long chat histories or
13
+ // filter-heavy searches where many pages yield few matching items.
14
+ exports.MAX_LOOP_ITERATIONS = 1000;
11
15
  exports.MAX_TOTAL_ITEMS_IN_MEMORY = 10000; // Maximum items to collect in memory
12
16
  exports.BATCH_WRITE_MAX = 25; // DynamoDB BatchWriteItem limit per request
13
17
  exports.MAX_UNPROCESSED_RETRIES = 10; // Maximum retries for UnprocessedItems loops
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAYH,0CAgBC;AA1BD,yBAAyB;AACZ,QAAA,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU;AAClC,QAAA,mBAAmB,GAAG,GAAG,CAAC,CAAC,oDAAoD;AAC/E,QAAA,yBAAyB,GAAG,KAAK,CAAC,CAAC,qCAAqC;AACxE,QAAA,eAAe,GAAG,EAAE,CAAC,CAAC,4CAA4C;AAClE,QAAA,uBAAuB,GAAG,EAAE,CAAC,CAAC,6CAA6C;AAExF;;GAEG;AACH,SAAgB,eAAe,CAAC,OAA2B;IACzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,GAAG,oBAAY,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,oBAAY,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/shared/utils/constants.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAgBH,0CAgBC;AA9BD,yBAAyB;AACZ,QAAA,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU;AAC/C,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,mEAAmE;AACtD,QAAA,mBAAmB,GAAG,IAAI,CAAC;AAC3B,QAAA,yBAAyB,GAAG,KAAK,CAAC,CAAC,qCAAqC;AACxE,QAAA,eAAe,GAAG,EAAE,CAAC,CAAC,4CAA4C;AAClE,QAAA,uBAAuB,GAAG,EAAE,CAAC,CAAC,6CAA6C;AAExF;;GAEG;AACH,SAAgB,eAAe,CAAC,OAA2B;IACzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,GAAG,oBAAY,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,oBAAY,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
@@ -6,6 +6,9 @@ export * from './constants';
6
6
  export * from './logger';
7
7
  export * from './retry';
8
8
  export * from './s3-offloader';
9
+ export * from './s3-orphans';
9
10
  export * from './batch-write';
11
+ export * from './client-factory';
12
+ export * from './sleep';
10
13
  export * from './ttl';
11
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC"}
@@ -22,6 +22,9 @@ __exportStar(require("./constants"), exports);
22
22
  __exportStar(require("./logger"), exports);
23
23
  __exportStar(require("./retry"), exports);
24
24
  __exportStar(require("./s3-offloader"), exports);
25
+ __exportStar(require("./s3-orphans"), exports);
25
26
  __exportStar(require("./batch-write"), exports);
27
+ __exportStar(require("./client-factory"), exports);
28
+ __exportStar(require("./sleep"), exports);
26
29
  __exportStar(require("./ttl"), exports);
27
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,8CAA4B;AAC5B,2CAAyB;AACzB,0CAAwB;AACxB,iDAA+B;AAC/B,gDAA8B;AAC9B,wCAAsB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/utils/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,8CAA4B;AAC5B,2CAAyB;AACzB,0CAAwB;AACxB,iDAA+B;AAC/B,+CAA6B;AAC7B,gDAA8B;AAC9B,mDAAiC;AACjC,0CAAwB;AACxB,wCAAsB"}
@@ -45,4 +45,31 @@ export declare function getLogger(): Logger;
45
45
  * Reset the logger to the default console-based implementation
46
46
  */
47
47
  export declare function resetLogger(): void;
48
+ /**
49
+ * Recursively clone an object, replacing values at any secret-looking key with
50
+ * `[REDACTED]`. Cycles are broken with a WeakSet. Leaves primitives and non-
51
+ * enumerable values untouched. Does not mutate the input.
52
+ *
53
+ * @param value - Arbitrary value to redact
54
+ * @param patterns - Lower-cased substrings to match against each key
55
+ */
56
+ export declare function redactSecrets(value: unknown, patterns?: readonly string[]): unknown;
57
+ /**
58
+ * Wrap an existing logger with automatic secret redaction applied to the
59
+ * variadic args (the message string itself is passed through unchanged — don't
60
+ * interpolate secrets into messages). Strings in args are left as-is; only
61
+ * object properties whose keys match a secret pattern are replaced.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { setGlobalLogger, redactLogger, getLogger } from '@farukada/aws-langgraph-dynamodb-ts';
66
+ * setGlobalLogger(redactLogger(getLogger()));
67
+ * ```
68
+ *
69
+ * @param inner - Logger to wrap
70
+ * @param options.extraKeys - Additional lower-cased substrings to treat as secret keys
71
+ */
72
+ export declare function redactLogger(inner: Logger, options?: {
73
+ extraKeys?: readonly string[];
74
+ }): Logger;
48
75
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAuBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAuBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AA8BD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,SAAS,MAAM,EAAgC,GACxD,OAAO,CA0BT;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAO,GAC9C,MAAM,CAWR"}