@drip_sync/drip
Version:
Scalable incremental sync for MongoDB aggregation pipelines
64 lines (63 loc) • 2.67 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidUpdateDescription = void 0;
exports.applyUpdateDescription = applyUpdateDescription;
const zod_1 = __importDefault(require("zod"));
class InvalidUpdateDescription extends Error {
}
exports.InvalidUpdateDescription = InvalidUpdateDescription;
function applyUpdateDescription(old, updateDescription) {
if (Object.keys(updateDescription).length === 0) {
// No update
return old;
}
// Copy the given object by one level
const res = { ...old };
for (const [k, v_] of Object.entries(updateDescription)) {
const vParsed = zod_1.default.record(zod_1.default.string(), zod_1.default.unknown()).safeParse(v_);
if (!vParsed.success) {
throw new InvalidUpdateDescription(`Expected object, got ${typeof v_}`);
}
const v = vParsed.data;
switch (k) {
case "d":
for (const nestedKey of Object.keys(v)) {
delete res[nestedKey];
}
break;
case "t":
for (const [nestedKey, newSize] of Object.entries(v)) {
const arr = res[nestedKey];
if (!Array.isArray(arr)) {
throw new InvalidUpdateDescription(`Expected array, got ${typeof arr}`);
}
if (typeof newSize !== "number") {
throw new InvalidUpdateDescription(`Expected number, got ${typeof newSize}`);
}
res[nestedKey] = arr.slice(0, newSize);
}
break;
case "i":
Object.assign(res, v);
break;
default: {
// Must be an embedded change
if (!k.startsWith("s")) {
throw new InvalidUpdateDescription(`Unexpected key: "${k}"`);
}
const nestedFieldName = k.slice(1);
const nestedFieldParsed = zod_1.default
.record(zod_1.default.string(), zod_1.default.unknown())
.safeParse(res[nestedFieldName]);
if (!nestedFieldParsed.success) {
throw new InvalidUpdateDescription(`Expected nested object, got ${typeof res[nestedFieldName]}`);
}
res[nestedFieldName] = applyUpdateDescription(nestedFieldParsed.data, v);
}
}
}
return res;
}