@exabugs/dynamodb-client 1.6.1 → 1.7.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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -0
- package/dist/server/handler.cjs +133 -50
- package/dist/server/handler.cjs.map +4 -4
- package/dist/server/media-handler.cjs +2 -2
- package/dist/server/media-process-handler-dlq.cjs +131 -53
- package/dist/server/media-process-handler-dlq.cjs.map +4 -4
- package/dist/server/media-process-handler.cjs +131 -53
- package/dist/server/media-process-handler.cjs.map +4 -4
- package/dist/server/operations/find/utils.js +2 -2
- package/dist/server/operations/find/utils.js.map +1 -1
- package/dist/server/operations/updateMany.d.ts.map +1 -1
- package/dist/server/operations/updateMany.js +6 -76
- package/dist/server/operations/updateMany.js.map +1 -1
- package/dist/server/operations/updateOne.d.ts.map +1 -1
- package/dist/server/operations/updateOne.js +9 -1
- package/dist/server/operations/updateOne.js.map +1 -1
- package/dist/server/utils/auth.d.ts.map +1 -1
- package/dist/server/utils/auth.js +8 -0
- package/dist/server/utils/auth.js.map +1 -1
- package/dist/server/utils/authHandler.js +1 -1
- package/dist/server/utils/authHandler.js.map +1 -1
- package/dist/server/utils/mergePatch.d.ts +8 -0
- package/dist/server/utils/mergePatch.d.ts.map +1 -0
- package/dist/server/utils/mergePatch.js +127 -0
- package/dist/server/utils/mergePatch.js.map +1 -0
- package/dist/server/utils/timestamps.d.ts.map +1 -1
- package/dist/server/utils/timestamps.js +2 -1
- package/dist/server/utils/timestamps.js.map +1 -1
- package/dist/sharp-layer.zip +0 -0
- package/package.json +1 -1
- package/terraform/README.md +5 -0
- package/terraform/variables.tf +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// @exabugs/dynamodb-client v1.
|
|
2
|
-
// Built: 2026-10-
|
|
1
|
+
// @exabugs/dynamodb-client v1.7.0
|
|
2
|
+
// Built: 2026-10-11T16:38:03.698Z
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -37714,7 +37714,7 @@ var init_types2 = __esm({
|
|
|
37714
37714
|
});
|
|
37715
37715
|
|
|
37716
37716
|
// src/shared/errors/index.ts
|
|
37717
|
-
var AppError, ConfigError, InvalidTokenError;
|
|
37717
|
+
var AppError, ConfigError, InvalidFilterError, InvalidTokenError;
|
|
37718
37718
|
var init_errors4 = __esm({
|
|
37719
37719
|
"src/shared/errors/index.ts"() {
|
|
37720
37720
|
"use strict";
|
|
@@ -37750,6 +37750,14 @@ var init_errors4 = __esm({
|
|
|
37750
37750
|
super("CONFIG_ERROR" /* CONFIG_ERROR */, message, 500, details);
|
|
37751
37751
|
}
|
|
37752
37752
|
};
|
|
37753
|
+
InvalidFilterError = class extends AppError {
|
|
37754
|
+
static {
|
|
37755
|
+
__name(this, "InvalidFilterError");
|
|
37756
|
+
}
|
|
37757
|
+
constructor(message, details) {
|
|
37758
|
+
super("INVALID_FILTER" /* INVALID_FILTER */, message, 400, details);
|
|
37759
|
+
}
|
|
37760
|
+
};
|
|
37753
37761
|
InvalidTokenError = class extends AppError {
|
|
37754
37762
|
static {
|
|
37755
37763
|
__name(this, "InvalidTokenError");
|
|
@@ -46087,7 +46095,7 @@ function parseFilters(filter) {
|
|
|
46087
46095
|
fieldKey,
|
|
46088
46096
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
46089
46097
|
});
|
|
46090
|
-
throw new
|
|
46098
|
+
throw new InvalidFilterError(`Invalid filter field syntax: ${fieldKey}`, {
|
|
46091
46099
|
field: fieldKey,
|
|
46092
46100
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
46093
46101
|
});
|
|
@@ -47347,6 +47355,113 @@ var init_chunking = __esm({
|
|
|
47347
47355
|
}
|
|
47348
47356
|
});
|
|
47349
47357
|
|
|
47358
|
+
// src/server/utils/mergePatch.ts
|
|
47359
|
+
function isPlainObject(value) {
|
|
47360
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47361
|
+
}
|
|
47362
|
+
function invalidPath(path, reason) {
|
|
47363
|
+
return new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, `Invalid patch path "${path}": ${reason}`, 400, {
|
|
47364
|
+
path
|
|
47365
|
+
});
|
|
47366
|
+
}
|
|
47367
|
+
function mergeInto(target, patch) {
|
|
47368
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
47369
|
+
if (key.includes(".")) {
|
|
47370
|
+
setByPath(target, key, value);
|
|
47371
|
+
} else {
|
|
47372
|
+
setKey(target, key, value, key);
|
|
47373
|
+
}
|
|
47374
|
+
}
|
|
47375
|
+
}
|
|
47376
|
+
function setKey(target, key, value, path) {
|
|
47377
|
+
if (key === "__proto__") {
|
|
47378
|
+
throw invalidPath(path, "forbidden segment");
|
|
47379
|
+
}
|
|
47380
|
+
if (value === null) {
|
|
47381
|
+
delete target[key];
|
|
47382
|
+
} else if (isPlainObject(value) && isPlainObject(target[key])) {
|
|
47383
|
+
mergeInto(target[key], value);
|
|
47384
|
+
} else {
|
|
47385
|
+
target[key] = value;
|
|
47386
|
+
}
|
|
47387
|
+
}
|
|
47388
|
+
function setByPath(target, path, value) {
|
|
47389
|
+
const keys = path.split(".");
|
|
47390
|
+
if (keys.some((k4) => k4 === "")) {
|
|
47391
|
+
throw invalidPath(path, "empty segment");
|
|
47392
|
+
}
|
|
47393
|
+
let current = target;
|
|
47394
|
+
for (let i4 = 0; i4 < keys.length; i4++) {
|
|
47395
|
+
const key = keys[i4];
|
|
47396
|
+
const isLast = i4 === keys.length - 1;
|
|
47397
|
+
if (Array.isArray(current)) {
|
|
47398
|
+
if (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= current.length) {
|
|
47399
|
+
throw invalidPath(path, `"${key}" is not a valid index (length ${current.length})`);
|
|
47400
|
+
}
|
|
47401
|
+
const index = Number(key);
|
|
47402
|
+
if (isLast) {
|
|
47403
|
+
if (value === null) {
|
|
47404
|
+
throw invalidPath(path, "array elements cannot be deleted by path");
|
|
47405
|
+
}
|
|
47406
|
+
const existing = current[index];
|
|
47407
|
+
if (isPlainObject(value) && isPlainObject(existing)) {
|
|
47408
|
+
mergeInto(existing, value);
|
|
47409
|
+
} else {
|
|
47410
|
+
current[index] = value;
|
|
47411
|
+
}
|
|
47412
|
+
return;
|
|
47413
|
+
}
|
|
47414
|
+
const next2 = current[index];
|
|
47415
|
+
if (isPlainObject(next2) || Array.isArray(next2)) {
|
|
47416
|
+
current = next2;
|
|
47417
|
+
} else {
|
|
47418
|
+
if (value === null) {
|
|
47419
|
+
return;
|
|
47420
|
+
}
|
|
47421
|
+
const created = {};
|
|
47422
|
+
current[index] = created;
|
|
47423
|
+
current = created;
|
|
47424
|
+
}
|
|
47425
|
+
continue;
|
|
47426
|
+
}
|
|
47427
|
+
if (isLast) {
|
|
47428
|
+
setKey(current, key, value, path);
|
|
47429
|
+
return;
|
|
47430
|
+
}
|
|
47431
|
+
if (key === "__proto__") {
|
|
47432
|
+
throw invalidPath(path, "forbidden segment");
|
|
47433
|
+
}
|
|
47434
|
+
const next = current[key];
|
|
47435
|
+
if (isPlainObject(next) || Array.isArray(next)) {
|
|
47436
|
+
current = next;
|
|
47437
|
+
} else {
|
|
47438
|
+
if (value === null) {
|
|
47439
|
+
return;
|
|
47440
|
+
}
|
|
47441
|
+
const created = {};
|
|
47442
|
+
current[key] = created;
|
|
47443
|
+
current = created;
|
|
47444
|
+
}
|
|
47445
|
+
}
|
|
47446
|
+
}
|
|
47447
|
+
function applyJsonMergePatch(target, patch) {
|
|
47448
|
+
const result = structuredClone(target);
|
|
47449
|
+
mergeInto(result, structuredClone(patch));
|
|
47450
|
+
return result;
|
|
47451
|
+
}
|
|
47452
|
+
var init_mergePatch = __esm({
|
|
47453
|
+
"src/server/utils/mergePatch.ts"() {
|
|
47454
|
+
"use strict";
|
|
47455
|
+
init_shared();
|
|
47456
|
+
__name(isPlainObject, "isPlainObject");
|
|
47457
|
+
__name(invalidPath, "invalidPath");
|
|
47458
|
+
__name(mergeInto, "mergeInto");
|
|
47459
|
+
__name(setKey, "setKey");
|
|
47460
|
+
__name(setByPath, "setByPath");
|
|
47461
|
+
__name(applyJsonMergePatch, "applyJsonMergePatch");
|
|
47462
|
+
}
|
|
47463
|
+
});
|
|
47464
|
+
|
|
47350
47465
|
// src/server/utils/timestamps.ts
|
|
47351
47466
|
var timestamps_exports = {};
|
|
47352
47467
|
__export(timestamps_exports, {
|
|
@@ -47380,8 +47495,8 @@ function addUpdateTimestamp(data) {
|
|
|
47380
47495
|
}
|
|
47381
47496
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
47382
47497
|
return {
|
|
47383
|
-
|
|
47384
|
-
|
|
47498
|
+
...data,
|
|
47499
|
+
[timestampFields.updatedAt]: data[timestampFields.updatedAt] ?? now
|
|
47385
47500
|
};
|
|
47386
47501
|
}
|
|
47387
47502
|
var init_timestamps = __esm({
|
|
@@ -47399,46 +47514,6 @@ var updateMany_exports = {};
|
|
|
47399
47514
|
__export(updateMany_exports, {
|
|
47400
47515
|
handleUpdateMany: () => handleUpdateMany
|
|
47401
47516
|
});
|
|
47402
|
-
function expandDotNotation(patch) {
|
|
47403
|
-
const result = {};
|
|
47404
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
47405
|
-
if (key.includes(".")) {
|
|
47406
|
-
const keys = key.split(".");
|
|
47407
|
-
let current = result;
|
|
47408
|
-
for (let i4 = 0; i4 < keys.length - 1; i4++) {
|
|
47409
|
-
const k4 = keys[i4];
|
|
47410
|
-
if (!(k4 in current)) {
|
|
47411
|
-
current[k4] = {};
|
|
47412
|
-
} else if (typeof current[k4] !== "object" || Array.isArray(current[k4])) {
|
|
47413
|
-
current[k4] = {};
|
|
47414
|
-
}
|
|
47415
|
-
current = current[k4];
|
|
47416
|
-
}
|
|
47417
|
-
const lastKey = keys[keys.length - 1];
|
|
47418
|
-
current[lastKey] = value;
|
|
47419
|
-
} else {
|
|
47420
|
-
result[key] = value;
|
|
47421
|
-
}
|
|
47422
|
-
}
|
|
47423
|
-
return result;
|
|
47424
|
-
}
|
|
47425
|
-
function applyJsonMergePatch(target, patch) {
|
|
47426
|
-
const expandedPatch = expandDotNotation(patch);
|
|
47427
|
-
const result = { ...target };
|
|
47428
|
-
for (const [key, value] of Object.entries(expandedPatch)) {
|
|
47429
|
-
if (value === null) {
|
|
47430
|
-
delete result[key];
|
|
47431
|
-
} else if (typeof value === "object" && !Array.isArray(value) && value !== null && typeof result[key] === "object" && !Array.isArray(result[key]) && result[key] !== null) {
|
|
47432
|
-
result[key] = applyJsonMergePatch(
|
|
47433
|
-
result[key],
|
|
47434
|
-
value
|
|
47435
|
-
);
|
|
47436
|
-
} else {
|
|
47437
|
-
result[key] = value;
|
|
47438
|
-
}
|
|
47439
|
-
}
|
|
47440
|
-
return result;
|
|
47441
|
-
}
|
|
47442
47517
|
async function handleUpdateMany(resource, params, requestId) {
|
|
47443
47518
|
const { data: patchData, options } = params;
|
|
47444
47519
|
const upsert = options?.upsert ?? false;
|
|
@@ -47566,11 +47641,9 @@ async function handleUpdateMany(resource, params, requestId) {
|
|
|
47566
47641
|
const id = existingData.id;
|
|
47567
47642
|
const oldShadowKeys = item.__shadowKeys ?? existingData.__shadowKeys ?? [];
|
|
47568
47643
|
const actualPatchData2 = patchData.$set ? patchData.$set : patchData;
|
|
47569
|
-
const
|
|
47570
|
-
const
|
|
47571
|
-
|
|
47572
|
-
id
|
|
47573
|
-
});
|
|
47644
|
+
const timestampedPatch = addUpdateTimestamp(actualPatchData2);
|
|
47645
|
+
const mergedData = applyJsonMergePatch(removeShadowKeys(existingData), timestampedPatch);
|
|
47646
|
+
const updatedData = { ...mergedData, id };
|
|
47574
47647
|
const newShadowRecords = generateShadowRecords(updatedData, resource, shadowConfig);
|
|
47575
47648
|
const newShadowKeys = newShadowRecords.map((shadow) => shadow.SK);
|
|
47576
47649
|
const mainSK = generateMainRecordSK2(id);
|
|
@@ -47851,10 +47924,9 @@ var init_updateMany = __esm({
|
|
|
47851
47924
|
init_chunking();
|
|
47852
47925
|
init_cost_tracker();
|
|
47853
47926
|
init_dynamodb3();
|
|
47927
|
+
init_mergePatch();
|
|
47854
47928
|
init_timestamps();
|
|
47855
47929
|
logger11 = createLogger({ service: "records-lambda" });
|
|
47856
|
-
__name(expandDotNotation, "expandDotNotation");
|
|
47857
|
-
__name(applyJsonMergePatch, "applyJsonMergePatch");
|
|
47858
47930
|
__name(handleUpdateMany, "handleUpdateMany");
|
|
47859
47931
|
__name(getPreparationErrorCode, "getPreparationErrorCode");
|
|
47860
47932
|
}
|
|
@@ -47990,6 +48062,9 @@ async function handleUpdateOne(resource, params, requestId) {
|
|
|
47990
48062
|
if (updateManyResult.count === 0) {
|
|
47991
48063
|
const error2 = Object.values(updateManyResult.errors || {})[0];
|
|
47992
48064
|
if (error2) {
|
|
48065
|
+
if (error2.code === "VALIDATION_ERROR" /* VALIDATION_ERROR */) {
|
|
48066
|
+
throw new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, error2.message ?? "Invalid patch", 400);
|
|
48067
|
+
}
|
|
47993
48068
|
throw new Error(`Failed to update record: ${error2.message}`);
|
|
47994
48069
|
} else {
|
|
47995
48070
|
throw new Error(`Failed to update record: ${targetId}`);
|
|
@@ -48029,6 +48104,9 @@ async function handleUpdateOne(resource, params, requestId) {
|
|
|
48029
48104
|
if (updateManyResult.count === 0) {
|
|
48030
48105
|
const error2 = Object.values(updateManyResult.errors || {})[0];
|
|
48031
48106
|
if (error2) {
|
|
48107
|
+
if (error2.code === "VALIDATION_ERROR" /* VALIDATION_ERROR */) {
|
|
48108
|
+
throw new AppError("VALIDATION_ERROR" /* VALIDATION_ERROR */, error2.message ?? "Invalid patch", 400);
|
|
48109
|
+
}
|
|
48032
48110
|
throw new Error(`Failed to update record: ${error2.message}`);
|
|
48033
48111
|
} else {
|
|
48034
48112
|
throw new Error(`No records found matching filter`);
|