helene
Version:
Real-time Web Apps for Node.js
196 lines • 6.83 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LastStepModifierFunctions = void 0;
const isArray_1 = __importDefault(require("lodash/isArray"));
const has_1 = __importDefault(require("lodash/has"));
const model_1 = require("./model");
/**
* The signature of modifier functions is as follows
* Their structure is always the same: recursively follow the dot notation while creating
* the nested documents if needed, then apply the "last step modifier"
*/
exports.LastStepModifierFunctions = {
/**
* Set a field to a new value
*/
$set: function (obj, field, value) {
obj[field] = value;
},
/**
* Unset a field
*/
$unset: function (obj, field, value) {
delete obj[field];
},
/**
* Push an element to the end of an array field
* Optional modifier $each instead of value to push several values
* Optional modifier $slice to slice the resulting array, see https://docs.mongodb.org/manual/reference/operator/update/slice/
* Différeence with MongoDB: if $slice is specified and not $each, we act as if value is an empty array
*/
$push: function (obj, field, value) {
// Create the array if it doesn't exist
if (!(field in obj)) {
obj[field] = [];
}
if (!(0, isArray_1.default)(obj[field])) {
throw new Error("Can't $push an element on non-array values");
}
if (value !== null &&
typeof value === 'object' &&
value.$slice &&
value.$each === undefined) {
value.$each = [];
}
if (value !== null && typeof value === 'object' && value.$each) {
if (Object.keys(value).length >= 3 ||
(Object.keys(value).length === 2 && value.$slice === undefined)) {
throw new Error('Can only use $slice in cunjunction with $each when $push to array');
}
if (!(0, isArray_1.default)(value.$each)) {
throw new Error('$each requires an array value');
}
value.$each.forEach(function (v) {
obj[field].push(v);
});
if (value.$slice === undefined || typeof value.$slice !== 'number') {
return;
}
if (value.$slice === 0) {
obj[field] = [];
}
else {
let start, end;
const n = obj[field].length;
if (value.$slice < 0) {
start = Math.max(0, n + value.$slice);
end = n;
}
else if (value.$slice > 0) {
start = 0;
end = Math.min(n, value.$slice);
}
obj[field] = obj[field].slice(start, end);
}
}
else {
obj[field].push(value);
}
},
/**
* Add an element to an array field only if it is not already in it
* No modification if the element is already in the array
* Note that it doesn't check whether the original array contains duplicates
*/
$addToSet: function (obj, field, value) {
let addToSet = true;
// Create the array if it doesn't exist
if (!(field in obj)) {
obj[field] = [];
}
if (!(0, isArray_1.default)(obj[field])) {
throw new Error("Can't $addToSet an element on non-array values");
}
if (value !== null && typeof value === 'object' && value.$each) {
if (Object.keys(value).length > 1) {
throw new Error("Can't use another field in conjunction with $each");
}
if (!(0, isArray_1.default)(value.$each)) {
throw new Error('$each requires an array value');
}
value.$each.forEach(function (v) {
exports.LastStepModifierFunctions.$addToSet(obj, field, v);
});
}
else {
obj[field].forEach(function (v) {
if ((0, model_1.compareThings)(v, value) === 0) {
addToSet = false;
}
});
if (addToSet) {
obj[field].push(value);
}
}
},
/**
* Remove the first or last element of an array
*/
$pop: function (obj, field, value) {
if (!(0, isArray_1.default)(obj[field])) {
throw new Error("Can't $pop an element from non-array values");
}
if (typeof value !== 'number') {
throw new Error(value + " isn't an integer, can't use it with $pop");
}
if (value === 0) {
return;
}
if (value > 0) {
obj[field] = obj[field].slice(0, obj[field].length - 1);
}
else {
obj[field] = obj[field].slice(1);
}
},
/**
* Removes all instances of a value from an existing array
*/
$pull: function (obj, field, value) {
let i;
if (!(0, isArray_1.default)(obj[field])) {
throw new Error("Can't $pull an element from non-array values");
}
const arr = obj[field];
for (i = arr.length - 1; i >= 0; i -= 1) {
if ((0, model_1.match)(arr[i], value)) {
arr.splice(i, 1);
}
}
},
/**
* Increment a numeric field's value
*/
$inc: function (obj, field, value) {
if (typeof value !== 'number') {
throw new Error(value + ' must be a number');
}
if (typeof obj[field] !== 'number') {
if (!(0, has_1.default)(obj, field)) {
obj[field] = value;
}
else {
throw new Error("Don't use the $inc modifier on non-number fields");
}
}
else {
obj[field] += value;
}
},
/**
* Updates the value of the field, only if specified field is greater than the current value of the field
*/
$max: function (obj, field, value) {
if (typeof obj[field] === 'undefined') {
obj[field] = value;
}
else if (value > obj[field]) {
obj[field] = value;
}
},
/**
* Updates the value of the field, only if specified field is smaller than the current value of the field
*/
$min: function (obj, field, value) {
if (typeof obj[field] === 'undefined') {
obj[field] = value;
}
else if (value < obj[field]) {
obj[field] = value;
}
},
};
//# sourceMappingURL=last-step-modifier-functions.js.map