@squiz/db-lib 1.76.0 → 1.77.1

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 (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/dynamodb/AbstractDynamoDbRepository.d.ts +1 -1
  3. package/lib/dynamodb/AbstractDynamoDbRepository.d.ts.map +1 -1
  4. package/lib/dynamodb/AbstractDynamoDbRepository.js +6 -5
  5. package/lib/dynamodb/AbstractDynamoDbRepository.js.map +1 -1
  6. package/lib/dynamodb/AbstractDynamoDbRepository.spec.d.ts.map +1 -1
  7. package/lib/dynamodb/AbstractDynamoDbRepository.spec.js +15 -14
  8. package/lib/dynamodb/AbstractDynamoDbRepository.spec.js.map +1 -1
  9. package/lib/dynamodb/getDynamoDbOptions.d.ts.map +1 -1
  10. package/lib/externalized/ExternalizedDynamoDbRepository.d.ts +166 -0
  11. package/lib/externalized/ExternalizedDynamoDbRepository.d.ts.map +1 -0
  12. package/lib/externalized/ExternalizedDynamoDbRepository.js +535 -0
  13. package/lib/externalized/ExternalizedDynamoDbRepository.js.map +1 -0
  14. package/lib/externalized/ExternalizedDynamoDbRepository.spec.d.ts +2 -0
  15. package/lib/externalized/ExternalizedDynamoDbRepository.spec.d.ts.map +1 -0
  16. package/lib/externalized/ExternalizedDynamoDbRepository.spec.js +431 -0
  17. package/lib/externalized/ExternalizedDynamoDbRepository.spec.js.map +1 -0
  18. package/lib/index.d.ts +2 -0
  19. package/lib/index.d.ts.map +1 -1
  20. package/lib/index.js +3 -0
  21. package/lib/index.js.map +1 -1
  22. package/lib/s3/S3ExternalStorage.d.ts +66 -0
  23. package/lib/s3/S3ExternalStorage.d.ts.map +1 -0
  24. package/lib/s3/S3ExternalStorage.js +84 -0
  25. package/lib/s3/S3ExternalStorage.js.map +1 -0
  26. package/lib/s3/S3ExternalStorage.spec.d.ts +12 -0
  27. package/lib/s3/S3ExternalStorage.spec.d.ts.map +1 -0
  28. package/lib/s3/S3ExternalStorage.spec.js +130 -0
  29. package/lib/s3/S3ExternalStorage.spec.js.map +1 -0
  30. package/package.json +7 -6
  31. package/src/dynamodb/AbstractDynamoDbRepository.spec.ts +2 -1
  32. package/src/dynamodb/AbstractDynamoDbRepository.ts +3 -1
  33. package/src/externalized/ExternalizedDynamoDbRepository.spec.ts +539 -0
  34. package/src/externalized/ExternalizedDynamoDbRepository.ts +625 -0
  35. package/src/index.ts +4 -0
  36. package/src/s3/S3ExternalStorage.spec.ts +181 -0
  37. package/src/s3/S3ExternalStorage.ts +118 -0
  38. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,535 @@
1
+ "use strict";
2
+ /*!
3
+ * @file ExternalizedDynamoDbRepository.ts
4
+ * @description This file contains the ExternalizedDynamoDbRepository class, which is used to store and retrieve externalized items from DynamoDB and S3.
5
+ * @author Dean Heffernan
6
+ * @copyright 2025 Squiz
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ExternalizedDynamoDbRepository = void 0;
10
+ // External
11
+ const crypto_1 = require("crypto");
12
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
13
+ // Team Submodules
14
+ const AbstractDynamoDbRepository_1 = require("../dynamodb/AbstractDynamoDbRepository");
15
+ /**
16
+ * The ExternalizedDynamoDbRepository class is used to store and retrieve externalized items from DynamoDB and S3.
17
+ * @class ExternalizedDynamoDbRepository
18
+ * @extends {AbstractDynamoDbRepository<SHAPE, DATA_CLASS>}
19
+ * @param {string} tableName - The name of the DynamoDB table to use for storing externalized items.
20
+ * @param {ContentDynamodbDbManager} dbManager - The DynamoDB database manager to use for storing externalized items.
21
+ * @param {string} entityName - The name of the entity to store externalized items for.
22
+ * @param {EntityDefinition} entityDefinition - The entity definition to use for storing externalized items.
23
+ * @param {DATA_CLASS} classRef - The class to use for storing externalized items.
24
+ * @param {S3ExternalStorage} storage - The S3 storage to use for storing externalized items.
25
+ * @returns {ExternalizedDynamoDbRepository} A new instance of the ExternalizedDynamoDbRepository class.
26
+ */
27
+ class ExternalizedDynamoDbRepository extends AbstractDynamoDbRepository_1.AbstractDynamoDbRepository {
28
+ /**
29
+ * Creates a new instance of the ExternalizedDynamoDbRepository class.
30
+ * @constructor
31
+ * @param {string} tableName - The name of the DynamoDB table to use for storing externalized items.
32
+ * @param {DynamoDbManager} dbManager - The DynamoDB database manager to use for storing externalized items.
33
+ * @param {string} entityName - The name of the entity to store externalized items for.
34
+ * @param {EntityDefinition} entityDefinition - The entity definition to use for storing externalized items.
35
+ * @param {DATA_CLASS} classRef - The class to use for storing externalized items.
36
+ * @param {S3ExternalStorage} storage - The S3 storage to use for storing externalized items.
37
+ * @returns {ExternalizedDynamoDbRepository} A new instance of the ExternalizedDynamoDbRepository class.
38
+ */
39
+ constructor(tableName, dbManager, entityName, entityDefinition, classRef, storage) {
40
+ super(tableName, dbManager, entityName, entityDefinition, classRef);
41
+ this.storage = storage;
42
+ }
43
+ /**
44
+ * Removes storageLocation from the response.
45
+ * storageLocation is an internal S3 storage implementation detail that should never be exposed to API consumers.
46
+ * @param {DATA_CLASS} item - The item to process.
47
+ * @returns {DATA_CLASS} The item without storageLocation.
48
+ */
49
+ removeStorageLocationFromResponse(item) {
50
+ if (item.storageLocation !== undefined) {
51
+ const { storageLocation: _storageLocation, ...itemWithoutStorage } = item;
52
+ return new this.classRef(itemWithoutStorage);
53
+ }
54
+ return item;
55
+ }
56
+ /**
57
+ * Creates a new item in the repository.
58
+ * If the item exceeds DynamoDB's size limit, it will automatically externalize the content to S3.
59
+ * @param {DATA_CLASS} value - The value to create the item for.
60
+ * @param {Transaction} transaction - The transaction to use for creating the item.
61
+ * @param {Partial<SHAPE>} additionalValue - Additional value to use for creating the item.
62
+ * @param {Object} options - The options to use for creating the item.
63
+ * @returns {Promise<DATA_CLASS>} A promise that resolves to the created item.
64
+ */
65
+ async createItem(value, transaction = {}, additionalValue = {}, options = { overrideExisting: false }) {
66
+ try {
67
+ const result = await this.createItemInternal(value, transaction, additionalValue, options);
68
+ return this.removeStorageLocationFromResponse(result);
69
+ }
70
+ catch (error) {
71
+ // If the item exceeds DynamoDB's size limit, externalize the content to S3 and retry
72
+ if (this.isDynamoItemSizeLimitError(error)) {
73
+ console.warn(`ExternalizedDynamoDbRepository: Item exceeded DynamoDB size limit for ${this.entityName}. Retrying with external storage.`);
74
+ const externalizedValue = await this.prepareValueForStorage(value);
75
+ const result = await this.createItemInternal(externalizedValue, transaction, additionalValue, options);
76
+ return this.removeStorageLocationFromResponse(result);
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+ /**
82
+ * Internal method to create an item in the repository.
83
+ * @param {DATA_CLASS} value - The value to create the item for.
84
+ * @param {Transaction} transaction - The transaction to use for creating the item.
85
+ * @param {Partial<SHAPE>} additionalValue - Additional value to use for creating the item.
86
+ * @param {Object} options - The options to use for creating the item.
87
+ * @returns {Promise<DATA_CLASS>} A promise that resolves to the created item.
88
+ */
89
+ async createItemInternal(value, transaction = {}, additionalValue = {}, options = { overrideExisting: false }) {
90
+ let previousLocation;
91
+ if (options === null || options === void 0 ? void 0 : options.overrideExisting) {
92
+ previousLocation = await this.fetchStoredLocation({ ...value, ...additionalValue });
93
+ }
94
+ // If storageLocation exists, we need to save it directly to DynamoDB
95
+ // We can't use super.createItem because it strips storageLocation during model validation
96
+ // So we build the DynamoDB Item manually
97
+ let createdItem;
98
+ if (value.storageLocation) {
99
+ // Manually validate the value (without storageLocation)
100
+ const valueWithoutStorageLocation = { ...value };
101
+ delete valueWithoutStorageLocation.storageLocation;
102
+ new this.classRef(valueWithoutStorageLocation);
103
+ // Build columns from value properties
104
+ const columns = {};
105
+ for (const modelProperty of Object.keys(valueWithoutStorageLocation)) {
106
+ columns[modelProperty] = valueWithoutStorageLocation[modelProperty];
107
+ }
108
+ // Convert fields defined as JSON strings (like 'layouts') to JSON strings
109
+ this.convertSelectedValuesToJsonString(columns);
110
+ // Manually add storageLocation to columns (after JSON conversion)
111
+ columns.storageLocation = value.storageLocation;
112
+ // Build key fields
113
+ const keyFields = {
114
+ [this.keys.pk.attributeName]: this.getPk({ ...value, ...additionalValue }),
115
+ [this.keys.sk.attributeName]: this.getSk({ ...value, ...additionalValue }),
116
+ };
117
+ // Add index fields
118
+ for (const [_key, index] of Object.entries(this.indexes)) {
119
+ try {
120
+ keyFields[index.pk.attributeName] = this.getKey({ ...value, ...additionalValue }, index.pk.attributeName);
121
+ keyFields[index.sk.attributeName] = this.getKey({ ...value, ...additionalValue }, index.sk.attributeName);
122
+ }
123
+ catch (e) {
124
+ // Ignore optional index errors
125
+ if (e.name === 'MissingKeyValuesError') {
126
+ continue;
127
+ }
128
+ throw e;
129
+ }
130
+ }
131
+ // Execute DynamoDB put
132
+ const putCommandInput = {
133
+ TableName: this.tableName,
134
+ Item: {
135
+ ...keyFields,
136
+ ...columns,
137
+ },
138
+ ConditionExpression: options.overrideExisting
139
+ ? undefined
140
+ : `attribute_not_exists(${this.keys.pk.attributeName})`,
141
+ };
142
+ if (transaction.id) {
143
+ // Add to transaction instead of executing directly
144
+ this.dbManager.addWriteTransactionItem(transaction.id, {
145
+ Put: putCommandInput,
146
+ });
147
+ }
148
+ else {
149
+ await this.client.put(putCommandInput);
150
+ }
151
+ createdItem = value;
152
+ }
153
+ else {
154
+ // No storageLocation, use parent's method
155
+ // Strip storageLocation before passing to parent to avoid "Excess properties" error
156
+ const { storageLocation: _, ...valueWithoutStorage } = value;
157
+ createdItem = await super.createItem(valueWithoutStorage, transaction, additionalValue, options);
158
+ }
159
+ // Clean up old S3 file if it exists and is different from new location
160
+ const newLocation = createdItem.storageLocation;
161
+ if (previousLocation && previousLocation.key !== (newLocation === null || newLocation === void 0 ? void 0 : newLocation.key)) {
162
+ await this.storage.delete(previousLocation);
163
+ }
164
+ // Check if we should hydrate from S3
165
+ // Only hydrate if content is actually stored in S3 (not just stale storageLocation)
166
+ if (this.isContentInS3(createdItem)) {
167
+ // Content fields are empty, so full content is in S3
168
+ return (await this.hydrateFromExternalStorage(createdItem)) || createdItem;
169
+ }
170
+ return createdItem;
171
+ }
172
+ /**
173
+ * Updates an item in the repository.
174
+ * If the item exceeds DynamoDB's size limit, it will automatically externalize the content to S3.
175
+ * @param {Partial<SHAPE>} value - The value to update the item with.
176
+ * @returns {Promise<DATA_CLASS | undefined>} A promise that resolves to the updated item.
177
+ */
178
+ async updateItem(value) {
179
+ try {
180
+ const result = await this.updateItemInternal(value);
181
+ return result ? this.removeStorageLocationFromResponse(result) : undefined;
182
+ }
183
+ catch (error) {
184
+ // If the item exceeds DynamoDB's size limit, externalize the content to S3 and retry
185
+ if (this.isDynamoItemSizeLimitError(error)) {
186
+ console.warn(`ExternalizedDynamoDbRepository: Update exceeded DynamoDB size limit for ${this.entityName}. Retrying with external storage.`);
187
+ const externalizedValue = await this.prepareValueForStorage(value);
188
+ const result = await this.updateItemInternal(externalizedValue);
189
+ return result ? this.removeStorageLocationFromResponse(result) : undefined;
190
+ }
191
+ throw error;
192
+ }
193
+ }
194
+ /**
195
+ * Internal method to update an item in the repository.
196
+ * @param {Partial<SHAPE>} value - The value to update the item with.
197
+ * @returns {Promise<DATA_CLASS | undefined>} A promise that resolves to the updated item.
198
+ */
199
+ async updateItemInternal(value) {
200
+ var _a;
201
+ // Fetch previous storageLocation before update
202
+ const previousLocation = await this.fetchStoredLocation(value);
203
+ // If storageLocation exists in the update, we need to save it directly to DynamoDB
204
+ // We can't use super.updateItem because it strips storageLocation during model validation
205
+ let updatedItem;
206
+ if (value.storageLocation) {
207
+ // Get old value first
208
+ const oldValue = await super.getItem(value);
209
+ if (!oldValue) {
210
+ return undefined;
211
+ }
212
+ // Merge old and new values
213
+ const mergedValue = { ...oldValue, ...value };
214
+ // Validate merged value (without storageLocation)
215
+ const mergedWithoutStorageLocation = { ...mergedValue };
216
+ delete mergedWithoutStorageLocation.storageLocation;
217
+ new this.classRef(mergedWithoutStorageLocation);
218
+ // Convert fields defined as JSON strings (like 'layouts') to JSON strings
219
+ const newValueCopy = { ...value };
220
+ this.convertSelectedValuesToJsonString(newValueCopy);
221
+ this.convertSelectedValuesToJsonString(oldValue);
222
+ // Build UpdateExpression manually including storageLocation
223
+ const updateExpression = [];
224
+ const expressionAttributeNames = {};
225
+ const expressionAttributeValues = {};
226
+ const updatedAttributes = [];
227
+ for (const modelProperty of Object.keys(value)) {
228
+ const propValue = newValueCopy[modelProperty];
229
+ if (propValue === oldValue[modelProperty]) {
230
+ continue; // don't update unchanged properties
231
+ }
232
+ const propName = `#${modelProperty}`;
233
+ const propValuePlaceHolder = `:${modelProperty}`;
234
+ updateExpression.push(`${propName} = ${propValuePlaceHolder}`);
235
+ expressionAttributeNames[propName] = modelProperty;
236
+ expressionAttributeValues[propValuePlaceHolder] = propValue;
237
+ updatedAttributes.push(modelProperty);
238
+ }
239
+ if (!updatedAttributes.length) {
240
+ // nothing to update
241
+ updatedItem = mergedValue;
242
+ }
243
+ else {
244
+ // Execute update
245
+ const updateCommandInput = {
246
+ TableName: this.tableName,
247
+ Key: {
248
+ [this.keys.pk.attributeName]: this.getPk(value),
249
+ [this.keys.sk.attributeName]: this.getSk(value),
250
+ },
251
+ UpdateExpression: `SET ${updateExpression.join(', ')}`,
252
+ ExpressionAttributeNames: expressionAttributeNames,
253
+ ExpressionAttributeValues: expressionAttributeValues,
254
+ ConditionExpression: `attribute_exists(${this.keys.pk.attributeName})`,
255
+ ReturnValues: 'ALL_NEW',
256
+ };
257
+ const result = await this.client.update(updateCommandInput);
258
+ updatedItem = result.Attributes ? this.hydrateItem(result.Attributes) : undefined;
259
+ // Preserve storageLocation from DynamoDB response (hydrateItem might strip it)
260
+ if (updatedItem && ((_a = result.Attributes) === null || _a === void 0 ? void 0 : _a.storageLocation)) {
261
+ updatedItem.storageLocation = result.Attributes.storageLocation;
262
+ }
263
+ }
264
+ }
265
+ else {
266
+ // No storageLocation in update value, use parent's method
267
+ // Strip storageLocation before passing to parent to avoid "Excess properties" error
268
+ const { storageLocation: _, ...valueWithoutStorage } = value;
269
+ updatedItem = await super.updateItem(valueWithoutStorage);
270
+ }
271
+ if (!updatedItem) {
272
+ return undefined;
273
+ }
274
+ // Check for stale storageLocation - this happens when content transitions from large (S3) to small (inline DynamoDB)
275
+ // If storageLocation exists but content is NOT in S3 (content is inline), the storageLocation is stale
276
+ let newLocation = updatedItem.storageLocation;
277
+ if (newLocation && !this.isContentInS3(updatedItem)) {
278
+ // Remove the stale storageLocation from DynamoDB
279
+ await this.client.update({
280
+ TableName: this.tableName,
281
+ Key: {
282
+ [this.keys.pk.attributeName]: this.getPk(value),
283
+ [this.keys.sk.attributeName]: this.getSk(value),
284
+ },
285
+ UpdateExpression: 'REMOVE storageLocation',
286
+ });
287
+ // Mark that there's no longer a new S3 location (we just removed it)
288
+ newLocation = undefined;
289
+ delete updatedItem.storageLocation;
290
+ }
291
+ // Clean up old S3 file if it exists and is different from new location
292
+ if (previousLocation && previousLocation.key !== (newLocation === null || newLocation === void 0 ? void 0 : newLocation.key)) {
293
+ await this.storage.delete(previousLocation);
294
+ }
295
+ // Check if we should hydrate from S3
296
+ // Only hydrate if content is actually stored in S3 (not just stale storageLocation)
297
+ // For large->small updates, DynamoDB might still have storageLocation but content is in DynamoDB
298
+ if (this.isContentInS3(updatedItem)) {
299
+ // Content fields are empty, so full content is in S3
300
+ return (await this.hydrateFromExternalStorage(updatedItem)) || updatedItem;
301
+ }
302
+ return updatedItem;
303
+ }
304
+ /**
305
+ * Gets an item from the repository.
306
+ * @param {Partial<SHAPE>} item - The item to get.
307
+ * @returns {Promise<DATA_CLASS | undefined>} A promise that resolves to the item.
308
+ */
309
+ async getItem(item) {
310
+ const record = await super.getItem(item);
311
+ return await this.hydrateFromExternalStorage(record);
312
+ }
313
+ /**
314
+ * Gets items from the repository.
315
+ * @param {Partial<SHAPE>[]} items - The items to get.
316
+ * @returns {Promise<DATA_CLASS[]>} A promise that resolves to the items.
317
+ */
318
+ async getItems(items) {
319
+ const records = await super.getItems(items);
320
+ return (await Promise.all(records.map((record) => this.hydrateFromExternalStorage(record))));
321
+ }
322
+ /**
323
+ * Queries items from the repository.
324
+ * @param {Partial<SHAPE>} item - The item to query.
325
+ * @param {QueryOptions} options - The options to use for querying the items.
326
+ * @returns {Promise<DATA_CLASS[]>} A promise that resolves to the items.
327
+ */
328
+ async queryItems(item, options) {
329
+ const records = await super.queryItems(item, options);
330
+ return (await Promise.all(records.map((record) => this.hydrateFromExternalStorage(record))));
331
+ }
332
+ /**
333
+ * Deletes an item from the repository.
334
+ * @param {Partial<SHAPE>} partialItem - The item to delete.
335
+ * @param {Transaction} transaction - The transaction to use for deleting the item.
336
+ * @returns {Promise<number>} A promise that resolves to the number of items deleted.
337
+ */
338
+ async deleteItem(partialItem, transaction = {}) {
339
+ const location = await this.fetchStoredLocation(partialItem);
340
+ const deleted = await super.deleteItem(partialItem, transaction);
341
+ if (deleted && location) {
342
+ await this.storage.delete(location);
343
+ }
344
+ return deleted;
345
+ }
346
+ /**
347
+ * Deletes items from the repository.
348
+ * @param {Partial<SHAPE>[]} items - The items to delete.
349
+ * @returns {Promise<void>} A promise that resolves when the items are deleted.
350
+ */
351
+ async deleteItems(items) {
352
+ const locations = await Promise.all(items.map((item) => this.fetchStoredLocation(item)));
353
+ await super.deleteItems(items);
354
+ await Promise.all(locations.map((location) => this.storage.delete(location)));
355
+ }
356
+ /**
357
+ * Prepares a value for storage by externalizing large content to S3.
358
+ * @param {DATA_CLASS} value - The value to prepare for storage.
359
+ * @returns {Promise<DATA_CLASS>} A promise that resolves to the prepared value for DynamoDB.
360
+ * @throws {Error} If S3 storage is not configured or if saving to S3 fails.
361
+ */
362
+ async prepareValueForStorage(value) {
363
+ const serialized = JSON.stringify(value);
364
+ const plainObject = JSON.parse(serialized);
365
+ // Remove any existing storageLocation before saving
366
+ delete plainObject.storageLocation;
367
+ // Generate reference ID from pk and sk for consistent S3 key
368
+ const pk = this.getPk(value);
369
+ const sk = this.getSk(value);
370
+ // Create hash of pk and sk for S3 key
371
+ const hash = (0, crypto_1.createHash)('sha256').update(`${pk}#${sk}`).digest('hex');
372
+ // Save full payload to S3
373
+ const { location } = await this.storage.save(this.entityName, hash, plainObject);
374
+ // Create minimal payload for DynamoDB with only key fields
375
+ // Key fields are computed from the entity definition - everything else is externalized
376
+ const minimalPayload = this.getKeyFieldsValues(plainObject);
377
+ // Add storageLocation reference
378
+ minimalPayload.storageLocation = location;
379
+ // Return minimal payload to be stored in DynamoDB
380
+ // DO NOT pass through constructor as it will strip storageLocation!
381
+ // DO NOT mutate the original value - storageLocation is an internal implementation detail
382
+ return minimalPayload;
383
+ }
384
+ /**
385
+ * Extracts only the key field values from an object based on the entity definition.
386
+ * Large content fields (defined in fieldsAsJsonString) are set to empty values.
387
+ * All other fields (key fields and small metadata) are preserved.
388
+ *
389
+ * @param {Record<string, unknown>} obj - The source object to extract key fields from.
390
+ * @returns {Record<string, unknown>} An object containing only the key field values.
391
+ */
392
+ getKeyFieldsValues(obj) {
393
+ const result = {};
394
+ // Copy all properties from the source object
395
+ for (const [key, value] of Object.entries(obj)) {
396
+ // Skip storageLocation as it's handled separately
397
+ if (key === 'storageLocation') {
398
+ continue;
399
+ }
400
+ // If this field is in fieldsAsJsonString, it's large content - set to empty
401
+ if (this.fieldsAsJsonString.includes(key)) {
402
+ // Set arrays to empty arrays, objects to empty objects
403
+ if (Array.isArray(value)) {
404
+ result[key] = [];
405
+ }
406
+ else if (value !== null && typeof value === 'object') {
407
+ result[key] = {};
408
+ }
409
+ // Skip primitive large fields entirely
410
+ continue;
411
+ }
412
+ // Keep all other fields (key fields and small metadata)
413
+ result[key] = value;
414
+ }
415
+ return result;
416
+ }
417
+ /**
418
+ * Override parent's hydrateItem to preserve storageLocation
419
+ * The parent's hydrateItem creates a new instance which strips storageLocation
420
+ */
421
+ hydrateItem(item) {
422
+ // Extract storageLocation before calling parent's hydrateItem
423
+ const storageLocation = item.storageLocation;
424
+ // Call parent's hydrateItem which will strip storageLocation
425
+ const hydrated = super.hydrateItem(item);
426
+ // Add storageLocation back if it existed
427
+ if (storageLocation) {
428
+ hydrated.storageLocation = storageLocation;
429
+ }
430
+ return hydrated;
431
+ }
432
+ /**
433
+ * Checks if content is actually stored in S3 by examining if large content fields are empty.
434
+ * When content is externalized to S3, fieldsAsJsonString fields are set to empty objects/arrays.
435
+ * @param {DATA_CLASS} item - The item to check.
436
+ * @returns {boolean} True if content is in S3, false if content is in DynamoDB.
437
+ */
438
+ isContentInS3(item) {
439
+ if (!item.storageLocation) {
440
+ return false;
441
+ }
442
+ // Check if large content fields are empty (indicating content is in S3)
443
+ for (const fieldName of this.fieldsAsJsonString) {
444
+ const fieldValue = item[fieldName];
445
+ if (fieldValue !== undefined) {
446
+ const isEmpty = typeof fieldValue === 'object' && Object.keys(fieldValue).length === 0;
447
+ if (isEmpty) {
448
+ return true;
449
+ }
450
+ }
451
+ }
452
+ return false;
453
+ }
454
+ /**
455
+ * Hydrates a record from external storage.
456
+ * @param {DATA_CLASS} record - The record to hydrate.
457
+ * @returns {Promise<DATA_CLASS | undefined>} A promise that resolves to the hydrated record (without storageLocation).
458
+ */
459
+ async hydrateFromExternalStorage(record) {
460
+ // If no record or no storageLocation, return record as-is
461
+ if (!record || !record.storageLocation) {
462
+ return record;
463
+ }
464
+ // Load full content from S3
465
+ return (await this.storage.load(record.storageLocation));
466
+ }
467
+ /**
468
+ * Fetches the stored location of an item.
469
+ * @param {Partial<SHAPE>} partialItem - The item to fetch the stored location for.
470
+ * @returns {Promise<S3StorageLocation | undefined>} A promise that resolves to the stored location.
471
+ */
472
+ async fetchStoredLocation(partialItem) {
473
+ var _a;
474
+ try {
475
+ const output = await this.client.get({
476
+ TableName: this.tableName,
477
+ Key: {
478
+ [this.keys.pk.attributeName]: this.getPk(partialItem),
479
+ [this.keys.sk.attributeName]: this.getSk(partialItem),
480
+ },
481
+ ProjectionExpression: 'storageLocation',
482
+ });
483
+ return (_a = output.Item) === null || _a === void 0 ? void 0 : _a.storageLocation;
484
+ }
485
+ catch (error) {
486
+ if (error instanceof client_dynamodb_1.ConditionalCheckFailedException) {
487
+ return undefined;
488
+ }
489
+ throw error;
490
+ }
491
+ }
492
+ /**
493
+ * Check if the error is due to DynamoDB item size limit being exceeded.
494
+ * @param {unknown} error - The error to check.
495
+ * @returns {boolean} True if the error is due to DynamoDB item size limit being exceeded, false otherwise.
496
+ */
497
+ isDynamoItemSizeLimitError(error) {
498
+ var _a, _b, _c, _d;
499
+ if (!error || typeof error !== 'object') {
500
+ return false;
501
+ }
502
+ const err = error;
503
+ const cancellationReasons = ((_a = err === null || err === void 0 ? void 0 : err.CancellationReasons) !== null && _a !== void 0 ? _a : err === null || err === void 0 ? void 0 : err.cancellationReasons);
504
+ const validationCodes = ['ValidationException', 'TransactionCanceledException'];
505
+ const hasValidationCode = validationCodes.includes(err === null || err === void 0 ? void 0 : err.code) ||
506
+ validationCodes.includes(err === null || err === void 0 ? void 0 : err.name) ||
507
+ validationCodes.includes((_b = err === null || err === void 0 ? void 0 : err.originalError) === null || _b === void 0 ? void 0 : _b.code) ||
508
+ validationCodes.includes((_c = err === null || err === void 0 ? void 0 : err.originalError) === null || _c === void 0 ? void 0 : _c.name) ||
509
+ (Array.isArray(cancellationReasons) &&
510
+ cancellationReasons.some((reason) => { var _a; return validationCodes.includes(((_a = reason === null || reason === void 0 ? void 0 : reason.Code) !== null && _a !== void 0 ? _a : reason === null || reason === void 0 ? void 0 : reason.code)); }));
511
+ const hasSizeMessage = this.hasDynamoSizeKeyword(err === null || err === void 0 ? void 0 : err.message) ||
512
+ this.hasDynamoSizeKeyword((_d = err === null || err === void 0 ? void 0 : err.originalError) === null || _d === void 0 ? void 0 : _d.message) ||
513
+ (Array.isArray(cancellationReasons) &&
514
+ cancellationReasons.some((reason) => { var _a; return this.hasDynamoSizeKeyword(((_a = reason === null || reason === void 0 ? void 0 : reason.Message) !== null && _a !== void 0 ? _a : reason === null || reason === void 0 ? void 0 : reason.message)); }));
515
+ return hasValidationCode || hasSizeMessage;
516
+ }
517
+ /**
518
+ * Check if the message contains the DynamoDB size keyword.
519
+ * @param {string} message - The message to check.
520
+ * @returns {boolean} True if the message contains the DynamoDB size keyword, false otherwise.
521
+ */
522
+ hasDynamoSizeKeyword(message) {
523
+ if (typeof message !== 'string') {
524
+ return false;
525
+ }
526
+ const normalized = message.toLowerCase();
527
+ return (normalized.includes('item size') ||
528
+ normalized.includes('maximum allowed size') ||
529
+ normalized.includes('exceeds') ||
530
+ normalized.includes('400 kb') ||
531
+ normalized.includes('400kb'));
532
+ }
533
+ }
534
+ exports.ExternalizedDynamoDbRepository = ExternalizedDynamoDbRepository;
535
+ //# sourceMappingURL=ExternalizedDynamoDbRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalizedDynamoDbRepository.js","sourceRoot":"","sources":["../../src/externalized/ExternalizedDynamoDbRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ExternalizedDynamoDbRepository.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExternalizedDynamoDbRepository.spec.d.ts","sourceRoot":"","sources":["../../src/externalized/ExternalizedDynamoDbRepository.spec.ts"],"names":[],"mappings":""}