I'm using CollectionFS for managing images. Furthermore I'm using graphicsmagick gm() for manipulating images.
Now I want to crop a already saved image. Therefore on a click event a server-method is called, which does the crop(). But after doing this, in the collection I find an empty image with size=0 updated on the correct date.
I don't see, what I am doing wrong.
shared.js
Images = new FS.Collection("images", {
    stores: [
        new FS.Store.FileSystem("thumbnail", { 
            transformWrite: function(fileObj, readStream, writeStream) {
                gm(readStream, fileObj.name()).autoOrient().resize('96', '96' + '^').gravity('Center').extent('96', '96').stream().pipe(writeStream);
            } 
        }),
        new FS.Store.FileSystem("public"),
    ]
});
server.js
Meteor.methods({
    'crop': function (fileId, selection) {
        var file = Images.findOne({ _id: fileId }),
            read = file.createReadStream('public'),
            write = file.createWriteStream('public');
        gm(read)
            .crop(selection.width, selection.height, selection.left, selection.top)
        .stream()
        .pipe(write);
    }
});
client.js
Template.editor.events({
    'click #crop': function () { 
        var fileId      = '123456789',
            selection   = { height: 100, width: 100, top: 10, left: 10 }; 
        Meteor.call('crop', fileId, selection);
    }
});
Update
As recommended by Christian I'm using a tmp-file for the writeStream, because the writeStream can't be the same like the readStream - which caused the empty result.
But after writing to the tmp-file, the content of it has to be copied back to the public store. How do I do that?
Meteor.methods({
    'crop': function (fileId, selection) {
        var fs   = Meteor.npmRequire('fs'),
            file = Images.findOne({ _id: fileId }),
            read = file.createReadStream('public'),
            filename = '/tmp/gm_' + Date.now(),
            tmp  = fs.createWriteStream(filename);
        gm(read)
            .crop(selection.width, selection.height, selection.left, selection.top)
        .stream()
        .pipe(tmp);
        // After writing to tmp -> copy back to stream and delete tmp-file
    }
});
Update 2 I tried this one:
// Add temp store
new FS.Store.FileSystem("temp")
// Method
Meteor.methods({
    'crop': function (fileId, selection) {
        var file  = Images.findOne({ _id: fileId }),
            read  = file.createReadStream('public'),
            temp  = file.createWriteStream('temp');
        gm(read)
            .crop(selection.width, selection.height, selection.left, selection.top)
        .stream()
        .pipe(tmp)
        .on('end', function () {
            var tmpread  = file.createReadStream('temp'),
                write    = file.createWriteStream('public');
            gm(tmpread).stream().pipe(write);
        });
    }
});