Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fawn

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fawn - npm Package Compare versions

Comparing version 1.2.4 to 1.3.1

3

lib/constants.js

@@ -16,5 +16,8 @@ "use strict";

, UPDATE: "update"
, FILE_SAVE: "file_save"
, FILE_REMOVE: "file_remove"
, ESCAPE_PREFIX: "*_**ojlint**escape*__tx__00***___string"
, DEFAULT_COLLECTION: "OJLINTTASKCOLLECTION"
, OJ_FUTURE: "$ojFuture"
, MONGOOSE_READY: 1
};

2

lib/fawn.js

@@ -62,3 +62,3 @@ "use strict";

function checkInitStatus(){
if(!(Roller)){
if (!(Roller)) {
throw new Error("Fawn has not been initialized. Call Fawn.init");

@@ -65,0 +65,0 @@ }

@@ -13,6 +13,8 @@ "use strict";

var DONE = constants.DONE;
var ROLLED = constants.ROLLED;
var SAVE = constants.SAVE;
var UPDATE = constants.UPDATE;
var REMOVE = constants.REMOVE;
var ROLLED = constants.ROLLED;
var FILE_REMOVE = constants.FILE_REMOVE;
var FILE_SAVE = constants.FILE_SAVE;
var TaskMdl;

@@ -108,3 +110,8 @@ var utils;

case UPDATE:
case REMOVE: return rollbackDeleteOrUpdate
case REMOVE:
return rollbackRemoveOrUpdate;
case FILE_SAVE:
return rollbackFileSave;
case FILE_REMOVE:
return rollbackFileRemove;
}

@@ -118,2 +125,4 @@ }

* @param task the task containing the step
*
* @returns {Promise|*}
*/

@@ -129,5 +138,5 @@ function rollbackSave(save, task) {

/**
* Rollback for delete or update step.
* Rollback for remove or update step.
*
* @param step the step to update
* @param step the update or remove step
* @param task the task containing the step.

@@ -137,3 +146,3 @@ *

*/
function rollbackDeleteOrUpdate(step, task){
function rollbackRemoveOrUpdate(step, task) {
var Collection = getModel(step.name);

@@ -145,8 +154,11 @@ var chain = Promise.resolve();

return Collection.findById(data._id).exec().then(function (doc) {
if (doc) {
if (doc && step.type === UPDATE) {
return doc.update(data).exec();
}
else if (!doc && step.type === REMOVE) {
doc = new Collection(data);
return doc.save();
}
doc = new Collection(data);
return doc.save();
return Promise.resolve();
});

@@ -161,2 +173,64 @@ });

/**
* Rollback for file save step.
*
* @param step the file save step
* @param task the task containing the step.
*
* @returns {Promise|*}
*/
function rollbackFileSave(step, task) {
return new Promise(function (resolve, reject) {
var gfs = new Grid(mongoose.connection.db);
utils.removeFile(step.dataStore[0]._id, gfs)
.then(resolve)
.catch(reject);
}).then(function () {
return updateState(task, step.index, ROLLED);
});
}
/**
* Rollback for file remove step.
*
* @param step the file remove step
* @param task the task containing the step.
*
* @returns {Promise|*}
*/
function rollbackFileRemove(step, task) {
return new Promise(function (resolve, reject) {
var gfs = Grid(mongoose.connection.db);
var data = step.dataStore[0];
gfs.exist({_id: data.removed}, function (err, exists) {
if (err) return reject(err);
gfs.findOne({_id: data.shadow}, function (err, shadowFile) {
if (err) return reject(err);
if (!shadowFile) return resolve();
function done() {
utils.removeFile(data.shadow, gfs).then(function () {
updateState(task, step.index, ROLLED)
.then(resolve)
.catch(reject)
});
}
if (exists) return done();
var writeStream = gfs.createWriteStream(shadowFile.metadata.oldFile);
writeStream.on("close", done);
writeStream.on("error", reject);
gfs.createReadStream({_id: data.shadow}).pipe(writeStream);
});
});
});
}
module.exports = RollerProvider;
"use strict";
var mongoose = require("mongoose");
var Promise = require("bluebird");
var Grid = require("gridfs-stream");
var fs = require("fs");
var constants = require("./constants");

@@ -14,4 +16,7 @@

var REMOVE = constants.REMOVE;
var FILE_SAVE = constants.FILE_SAVE;
var FILE_REMOVE = constants.FILE_REMOVE;
// variables which require a mongoose instance
var mongoose;
var utils;

@@ -30,5 +35,4 @@ var updateState;

*
* @param mongoose The mongoose instance to be used
* @param _mongoose The mongoose instance to be used
* @param _TaskMdl The mongoose model for tasks (where tasks are stored)
*
* @returns {Task}

@@ -38,3 +42,5 @@ *

*/
var TaskProvider = function (mongoose, _TaskMdl) {
var TaskProvider = function (_mongoose, _TaskMdl) {
mongoose = _mongoose;
Grid.mongo = mongoose.mongo;
TaskMdl = _TaskMdl;

@@ -48,3 +54,2 @@ Roller = require("./roller")(mongoose, _TaskMdl);

return Task;

@@ -223,2 +228,60 @@ };

/**
* Adds a saveFile step (saveFileObj) to the steps queue
* and increments the index.
*
* @param filePath path of the file to be saved
* @param options options for saving the file
*
* @returns {Task}
*/
task.saveFile = function (filePath, options) {
if (!filePath) throw new Error("File path is required and must be a string");
if (options) {
if (!isObject(options)) throw new Error("options must be an object");
handle$Token(options);
}
var saveFileObj = {
type: FILE_SAVE
, index: index
, state: INITIAL
, data: {
file_path: filePath
}
, options: options
};
steps.push(saveFileObj);
index++;
return task;
};
/**
* Adds a removeFile step (removeFileObj) to the steps queue
* and increments the index.
*
* @param options options for removing the file
*
* @returns {Task}
*/
task.removeFile = function (options) {
if (!isObject(options)) throw new Error("options required. Must be an object");
handle$Token(options);
var removeFileObj = {
type: FILE_REMOVE
, index: index
, state: INITIAL
, options: options
};
steps.push(removeFileObj);
index++;
return task;
};
/**
* Runs a task. This function saves the steps to

@@ -247,6 +310,11 @@ * the db and proceeds to complete each step. If

return chain.then(function (results) {
return _task.remove()
.then(function () {
return Promise.resolve(results);
});
var gfs = Grid(mongoose.connection.db);
var removeChain = utils.makeRemoveChain(_task, gfs);
return removeChain.then(function () {
return _task.remove()
.then(function () {
return Promise.resolve(results);
});
});
}).catch(function (err) {

@@ -274,2 +342,6 @@ return Roller.rollOne(_task).then(function () {

case REMOVE: return performRemove;
case FILE_SAVE:
return performFileSave;
case FILE_REMOVE:
return performFileRemove
}

@@ -281,4 +353,4 @@ }

*
* @param update the update step
* @param task the task containing update
* @param step the update step
* @param task the task which step belongs to
* @param results array of results from previous operations

@@ -288,17 +360,17 @@ *

*/
function performUpdate(update, task, results) {
var Collection = getModel(update.name);
function performUpdate(step, task, results) {
var Collection = getModel(step.name);
handle$Token(update.condition, true);
handle$Token(update.data, true);
handle$Token(step.condition, true);
handle$Token(step.data, true);
resolveFuture(update.condition, results);
resolveFuture(update.data, results);
resolveFuture(step.condition, results);
resolveFuture(step.data, results);
// console.log(update);
return storeOldData(update, task)
return storeOldData(step)
.then(function(){
return updateState(task, update.index, PENDING)
return updateState(task, step.index, PENDING)
.then(function () {
return Collection.update(update.condition, update.data, update.options)
return Collection.update(step.condition, step.data, step.options)
.exec()

@@ -308,3 +380,3 @@ .then(function (result) {

return updateState(task, update.index, DONE, results);
return updateState(task, step.index, DONE, results);
});

@@ -315,8 +387,7 @@ });

/**
* This function handles the save step.
*
* @param save the save step
* @param task the task containing save
* @param step the save step
* @param task the task which step belongs to
* @param results array of results from previous operations

@@ -326,9 +397,9 @@ *

*/
function performSave(save, task, results) {
var Collection = getModel(save.name);
function performSave(step, task, results) {
var Collection = getModel(step.name);
handle$Token(save.data, true);
resolveFuture(save.data, results);
handle$Token(step.data, true);
resolveFuture(step.data, results);
var doc = new Collection(save.data);
var doc = new Collection(step.data);
var dataStore = [];

@@ -339,10 +410,10 @@

task.steps[save.index].dataStore = dataStore;
task.steps[save.index].markModified("dataStore");
step.dataStore = dataStore;
step.markModified("dataStore");
return updateState(task, save.index, PENDING).then(function () {
return updateState(task, step.index, PENDING).then(function () {
return doc.save().then(function (result) {
results.push(result);
return updateState(task, save.index, DONE, results);
return updateState(task, step.index, DONE, results);
});

@@ -355,4 +426,4 @@ });

*
* @param remove the remove step
* @param task the task containing remove
* @param step the remove step
* @param task the task which step belongs to
* @param results array of results from previous operations

@@ -362,14 +433,14 @@ *

*/
function performRemove(remove, task, results) {
var Collection = getModel(remove.name);
function performRemove(step, task, results) {
var Collection = getModel(step.name);
handle$Token(remove.condition, true);
resolveFuture(remove.condition, results);
handle$Token(step.condition, true);
resolveFuture(step.condition, results);
return storeOldData(remove, task).then(function () {
return updateState(task, remove.index, PENDING).then(function () {
return Collection.remove(remove.condition).exec().then(function (result) {
return storeOldData(step).then(function () {
return updateState(task, step.index, PENDING).then(function () {
return Collection.remove(step.condition).exec().then(function (result) {
results.push(result);
return updateState(task, remove.index, DONE, results);
return updateState(task, step.index, DONE, results);
});

@@ -381,2 +452,120 @@ });

/**
* This function handles the file save step.
*
* @param step the file save step
* @param task the task which step belongs to
* @param results array of results from previous operations
*
* @returns {Promise|*}
*/
function performFileSave(step, task, results) {
handle$Token(step.options, true);
resolveFuture(step.options, results);
var options = step.options || {};
var dataStore = [];
options._id = options._id || utils.generateId();
dataStore.push({_id: options._id});
step.options = options;
step.dataStore = dataStore;
step.markModified("dataStore");
step.markModified("options");
return updateState(task, step.index, PENDING).then(function () {
return new Promise(function (resolve, reject) {
var conn = mongoose.connection;
var gfs = Grid(conn.db);
var writeStream = gfs.createWriteStream(options);
writeStream.on("close", function (file) {
results.push(file);
resolve(results);
});
writeStream.on("error", reject);
fs.createReadStream(step.data.file_path).pipe(writeStream);
}).then(function (results) {
return updateState(task, step.index, DONE, results);
});
});
}
/**
* This function handles the file remove step.
*
* @param step the file remove step
* @param task the task which step belongs to
* @param results array of results from previous operations
*
* @returns {Promise|*}
*/
function performFileRemove(step, task, results) {
handle$Token(step.options, true);
resolveFuture(step.options, results);
var options = step.options;
return storeOldFile(step).then(function (file) {
return updateState(task, step.index, PENDING).then(function () {
return new Promise(function (resolve, reject) {
if (!file) {
results.push(null);
return resolve();
}
var gfs = Grid(mongoose.connection.db);
utils.removeFile(options, gfs)
.then(function (result) {
results.push(result);
resolve();
})
.catch(reject);
}).then(function () {
return updateState(task, step.index, DONE, results);
});
});
});
}
/**
* This function stores a file that's about to be
* removed by a step, for rollback purposes
*
* @param step the step
*
* @returns {Promise|*}
*/
function storeOldFile(step) {
return new Promise(function (resolve, reject) {
var dataStore = [];
var gfs = Grid(mongoose.connection.db);
gfs.findOne(step.options, function (err, file) {
if (err) return reject(err);
if (!file) return resolve(false);
dataStore.push({removed: file._id, shadow: utils.generateId()});
step.dataStore = dataStore;
step.save().then(function () {
var writeStream = gfs.createWriteStream({_id: dataStore[0].shadow, metadata: {oldFile: file}});
writeStream.on("close", resolve);
writeStream.on("error", reject);
gfs.createReadStream({_id: file._id}).pipe(writeStream);
});
});
});
}
/**
* This function stores data that's about to be

@@ -386,10 +575,9 @@ * changed by a step, for rollback purposes

* @param step the step
* @param task the task containing step
*
* @returns {Promise|*}
*/
function storeOldData(step, task){
function storeOldData(step) {
var Collection = getModel(step.name);
var options = step.options || step.type === REMOVE ? {multi: true} : null;
var query = Collection.find(step.condition);
var query = Collection.find(step.condition).lean();
var searchQuery = options && options.multi === true

@@ -402,10 +590,4 @@ ? query

.then(function(result) {
var oldData = [];
for (var i = 0; i < result.length; i++) {
oldData.push(result[i].toObject());
}
task.steps[step.index].dataStore = oldData;
task.steps[step.index].markModified("dataStore");
step.dataStore = result;
step.markModified("dataStore");
});

@@ -523,3 +705,3 @@ }

var parts = placeholder.split(".");
if (isNaN(parts[0])) throw new Error("index must be a number");
if (isNaN(parts[0])) throw new Error("step index must be a number");

@@ -534,5 +716,11 @@ var index = parseInt(parts[0]);

if (!isObject(result))throw new Error("Can't use keys on non-object");
if (result instanceof Array) {
if (isNaN(parts[i])) throw new Error("Array index must be a number");
parts[i] = parseInt(parts[i]);
if (parts[i] >= result.length)throw new Error("Array index out of bounds");
}
else if (!isObject(result))throw new Error("Can't use keys on non-object");
if (!result[parts[i]]) throw new Error("No such key exists in result");
result = result[parts[i]]

@@ -539,0 +727,0 @@ }

@@ -10,2 +10,4 @@ "use strict";

var constants = require("./constants");
module.exports = function(_mongoose){

@@ -15,2 +17,12 @@ var mongoose = _mongoose || require("mongoose");

/**
* Updates the state of a task's step.
*
* @param task the task
* @param index the index of the step to update
* @param state the new state of the step
* @param results array of results from previous steps
*
* @returns {Promise|*}
*/
function updateState(task, index, state, results) {

@@ -25,2 +37,8 @@ task.steps[index].state = state;

/**
* gets a collection as a mongoose model.
*
* @param name name of the collection
* @param schema schema for the model
*/
function getCollection(name, schema){

@@ -34,2 +52,8 @@ if (schema) {

/**
* Adds a model to the model cache
*
* @param name name of model
* @param schema schema for the model
*/
function setModel(name, schema){

@@ -39,2 +63,11 @@ modelCache[name] = getCollection(name, schema);

/**
* Gets a mongoose model. Creates one if it
* doesn't exist already.
*
* @param name name of the model to retrieve
* @param schema schema for the model
*
* @returns a mongoose model
*/
function getModel(name, schema){

@@ -66,2 +99,7 @@ if(!modelCache[name]){

/**
* Drops a MongoDB collection. For testing.
*
* @param collection the name of the collection to be dropped
*/
function dropCollection(collection){

@@ -76,2 +114,74 @@ return new Promise(function(resolve, reject){

/**
* Removes a file from the db
*
* @param id file id or options object
* @param gfs GridFS
*/
function removeFile(id, gfs) {
var options = {_id: id};
if (id.constructor && id.constructor === Object) {
options = id;
}
return new Promise(function (resolve, reject) {
gfs.remove(options, function (err, result) {
if (err) return reject(err);
resolve(result);
});
});
}
/**
* Checks if a file exists in the db with the
* specified file name
*
* @param id MongoDB ObjectId
* @param gfs GridFS
*/
function fileExists(id, gfs) {
return new Promise(function (resolve, reject) {
gfs.exist({_id: id}, function (err, exists) {
if (err) return reject(err);
resolve(exists);
});
});
}
/**
* Chains together the deletion of shadow files
* from file remove steps.
*
* @param task the task to check for shadow files
* @param gfs GridFS
*
* @returns {Promise|*}
*/
function makeRemoveChain(task, gfs) {
var removeChain = Promise.resolve();
task.steps.forEach(function (step) {
if (step.type !== constants.FILE_REMOVE) return;
var shadowId = step.dataStore[0].shadow;
removeChain = removeChain.then(function () {
return fileExists(shadowId, gfs)
.then(function (exists) {
if (!exists) return Promise.resolve();
return removeFile(shadowId, gfs);
});
});
});
return removeChain;
}
/**
* generates a MongoDB ObjectId
*/
function generateID(){

@@ -89,3 +199,6 @@ return mongoose.Types.ObjectId();

, generateId: generateID
, removeFile: removeFile
, fileExists: fileExists
, makeRemoveChain: makeRemoveChain
};
};

@@ -13,3 +13,3 @@ /**

, state: {type: Number, required: true}
, name: {type: String, required: true}
, name: {type: String}
, condition: {}

@@ -16,0 +16,0 @@ , dataStore: [{}]

{
"name": "fawn",
"version": "1.2.4",
"version": "1.3.1",
"description": "Library for atomic-ish operations in MongoDB",

@@ -34,2 +34,3 @@ "main": "index.js",

"bluebird": "3.4.1",
"gridfs-stream": "1.1.1",
"mongoose": "4.5.1"

@@ -36,0 +37,0 @@ },

@@ -60,3 +60,3 @@ # Fawn

task.update("Accounts", {firstName: "Broke", lastName: "Ass"}, {$inc: {balance: -20}})
task.update("Accounts", {firstName: "Coke", lastName: "Dealer"}, {$inc: {balance: 20}})
task.update("Accounts", {firstName: "The", lastName: "Plug"}, {$inc: {balance: 20}})
task.run()

@@ -73,5 +73,22 @@ .then(function(){

```
[GridFS]: <https://docs.mongodb.com/manual/core/gridfs/>
The server could crash before a task is complete, You can use the Roller to rollback all incomplete transactions before starting your server.
Files can be saved and removed to and from [GridFS][]:
```javascript
var newImageId = someMongoDbId;
task.saveFile("/path/to/new/profile/img", {_id: newImageId, filename: "profile.png"})
.removeFile({_id: oldImageId})
.update("users", {_id: userId}, {profileImageId: newImageId})
.run()
.then(function(results){
var newImgFile = results[0];
console.log(newImgFile.filename) // profile.png
});
```
The server could crash before a task is complete, You can use the Roller to rollback all incomplete transactions before starting your server:
```javascript

@@ -96,2 +113,4 @@ // assuming Fawn has been initialized. See Fawn.init below

- [task.remove](#task_remove)
- [task.saveFile](#task_savefile)
- [task.removeFile](#task_removefile)
- [task.run](#task_run)

@@ -267,2 +286,45 @@ - [Fawn.Roller](#fawn_roller)

### <a name="task_savefile"></a>task.saveFile(filePath, options): Save a file to the db via [GridFS][]
> filePath (required): Name of the collection we're deleting from or a mongoose model or a mongoose document
> options (optional): Same as in [GridStore](http://mongodb.github.io/node-mongodb-native/api-generated/gridstore.html#constructor)
Saves the file at "filePath" to the database using GridFS. The result of this operation is the saved file's object. See [File object](https://docs.mongodb.com/manual/core/gridfs/#the-files-collection)
```javascript
task.saveFile("path/to/some/file", {filename: "a_string_filename.ext"})
.update("SomeCollection", updateConditions, updateData)
.run()
.then(function(results){
var file = results[0];
console.log(file.filename); // a_string_filename.ext
});
```
*Note: No changes will be made to to your database until you call task.run()*
<br>
### <a name="task_removefile"></a>task.removeFile(options): Remove a file from the db via [GridFS][]
> options (required): Same as in [GridStore](http://mongodb.github.io/node-mongodb-native/api-generated/gridstore.html#constructor)
Removes a file that matches "options" from the database using GridFS. The result of this operation is a GridStore instance (can be ignored). See [GridStore](http://mongodb.github.io/node-mongodb-native/api-generated/gridstore.html)
```javascript
task.removeFile({_id: fileId})
.update("SomeCollection", updateConditions, updateData)
.run()
.then(function(results){
// if you need the gridStore instance
var gridStore = results[0];
});
```
*Note: No changes will be made to to your database until you call task.run()*
<br>
### <a name="task_run"></a>task.run(): Run a task.

@@ -319,2 +381,3 @@

```
<br>

@@ -321,0 +384,0 @@ ## <a name="misc"></a>Miscellaneous

@@ -5,3 +5,3 @@ "use strict";

db: "mongodb://127.0.0.1:27017/"
, DB: "test"
, DB: "OJFAWNTESTS"
, TASKS: "lints"

@@ -12,2 +12,4 @@ , Fawn: require("./lib/fawn")

, TEST_COLLECTION_B: "animals"
, TEST_FILE_TEXT: "This text is used to test file features"
, TEST_FILE_PATH: "./test.oj"
, chai: require("chai")

@@ -14,0 +16,0 @@ };

@@ -8,2 +8,4 @@ "use strict";

var fs = require("fs");
var config = require("../test_conf");

@@ -16,2 +18,6 @@ config.init();

global.mongoose = require("mongoose");
global.Grid = require("gridfs-stream");
Grid.mongo = mongoose.mongo;
global.utils = require("../lib/utils")();

@@ -22,2 +28,6 @@ global.expect = config.expect;

global.TEST_COLLECTION_B = config.TEST_COLLECTION_B;
global.TEST_FILE_PATH = config.TEST_FILE_PATH;
global.TEST_FILE_TEXT = config.TEST_FILE_TEXT;
global.TEST_FILE_NAME = "FAWN_TEST.oj";
global.TEST_FILE_ID = utils.generateId();

@@ -38,5 +48,7 @@ describe("ALL TESTS", function(){

fs.writeFileSync(TEST_FILE_PATH, TEST_FILE_TEXT);
});
after(function(){
fs.unlinkSync(TEST_FILE_PATH);
return utils.dropCollection(TASKS);

@@ -43,0 +55,0 @@ });

@@ -53,2 +53,38 @@ /**

});
it("should rollback file save", function () {
var gfs = Grid(mongoose.connection.db);
var id = utils.generateId();
return task.saveFile(TEST_FILE_PATH, {_id: id})
.remove(TestMdlA, {_id: "fail"})
.run()
.then(failure)
.catch(function () {
return expect(utils.fileExists(id, gfs)).to.eventually.equal(false);
});
});
it("should rollback file remove", function (done) {
var gfs = Grid(mongoose.connection.db);
var id = utils.generateId();
var writeStream = gfs.createWriteStream({_id: id});
writeStream.on("close", function () {
task.removeFile({_id: id})
.remove(TestMdlA, {_id: "fail"})
.run()
.then(failure)
.catch(function () {
utils.fileExists(id, gfs).then(function (exists) {
if (exists) utils.removeFile(id, gfs);
expect(exists).to.equal(true);
done();
});
});
});
require("fs").createReadStream(TEST_FILE_PATH).pipe(writeStream);
});
});

@@ -55,0 +91,0 @@ });

@@ -178,2 +178,28 @@ "use strict";

describe("#saveFile", function () {
it("should save file successfully", function () {
return task.saveFile(TEST_FILE_PATH, {_id: TEST_FILE_ID, filename: TEST_FILE_NAME})
.run();
});
it("Should have file with _id '" + TEST_FILE_ID + "' in database", function () {
var gfs = Grid(mongoose.connection.db);
return expect(utils.fileExists(TEST_FILE_ID, gfs)).to.eventually.equal(true);
});
});
describe("#removeFile", function () {
it("should remove file successfully", function () {
return task.removeFile({filename: TEST_FILE_NAME})
.run();
});
it("Should not have file with _id '" + TEST_FILE_ID + "' in database", function () {
var gfs = Grid(mongoose.connection.db);
return expect(utils.fileExists(TEST_FILE_ID, gfs)).to.eventually.equal(false);
});
});
describe("allTogetherNow", function(){

@@ -222,2 +248,3 @@ it("should save, update and remove successfully", function(){

var gabe = new TestMdlB({name: "Gabe", age: 34});
var id = utils.generateId();

@@ -228,5 +255,7 @@ return expect(

.update(gabe, {age: 64})
.saveFile(TEST_FILE_PATH, {_id: id, filename: {$ojFuture: "0.name"}})
.removeFile({_id: id})
.remove(TEST_COLLECTION_A, {name: "Gabe's Owner"})
.run())
.to.eventually.have.length(4);
.to.eventually.have.length(6);
});

@@ -237,3 +266,3 @@ });

it("task with templated data should run successfully", function () {
var mickey = new TestMdlB({name: "Mickey Mouse", age: 53});
var mickey = new TestMdlB({name: "Mickey Mouse", age: 53, list: [{num: 53}]});
var mick = new TestMdlA({name: "Mick", age: 3});

@@ -244,3 +273,3 @@

.save(TEST_COLLECTION_A, {name: "Alfie", age: {$ojFuture: "1.age"}})
.save(TEST_COLLECTION_B, {name: "Minnie Mouse", age: {$ojFuture: "0.age"}})
.save(TEST_COLLECTION_B, {name: "Minnie Mouse", age: {$ojFuture: "0.list.0.num"}})
.update(TEST_COLLECTION_B, {name: {$ojFuture: "0.name"}}, {age: {$ojFuture: "1.age"}})

@@ -247,0 +276,0 @@ .update(TEST_COLLECTION_A, {name: {$ojFuture: "1.name"}}, {age: {$ojFuture: "3.age"}})

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc