In my attempts to better understand svelte I started working with simple-todo-svelte
I noticed that when the Meteor methods are called to change an entry in the collection, and the method returns an error, the change done on the client is invalid and needs to be rolled back. Instead it throws an error.
Exception while simulating the effect of invoking 'tasks.setChecked'
Object { stack: "errorClass@http://localhost:3000/packages/meteor.js?hash=857dafb4b9dff17e29ed8498a22ea5b1a3d6b41d:689:20\ntasks.setChecked@http://localhost:3000/app/app.js?hash=50a292de8a7120160d6915ad8cc822222fe1aad4:83:13\napply/stubReturnValue<@http://localhost:3000/packages/ddp-client.js?hash=5333e09ab08c9651b0cc016f95813ab4ce075f37:976:25\nEVp.withValue@http://localhost:3000/packages/meteor.js?hash=857dafb4b9dff17e29ed8498a22ea5b1a3d6b41d:1207:15\napply@http://localhost:3000/packages/ddp-client.js?hash=5333e09ab08c9651b0cc016f95813ab4ce075f37:967:60\ncall@http://localhost:3000/packages/ddp-client.js?hash=5333e09ab08c9651b0cc016f95813ab4ce075f37:869:17\ntoggleChecked@http://localhost:3000/app/app.js?hash=50a292de8a7120160d6915ad8cc822222fe1aad4:1062:12\n", isClientSafe: true, error: "not-authorized", reason: undefined, details: undefined, message: "[not-authorized]", errorType: "Meteor.Error" }
How should this be handled in Svelte? Do I need to implement a different client stub? In case of the checkbox, the client changes the state of the checkbox even if the method returns an error, how to spring the checkbox back?
can you make a repo that reproduces this? I would like to take a look at what you are seeing
You can use the simple-todo-svelte I linked to and change the methods to only allow logged in users to make modifications.
After pondering over this some more I have come to the conclusion that my observations are exactly what is to be expected.
- the client subscribes to a publication
- the server does not allow the client to modify the publication
- methods are defined to alter the records in the collection
- calling the method it will run on the client (latency compensation) and on the server
- the client modification of the collection in the method needs to be rolled back if the server method fails
The easiest way around this is to only implement the methods on the server, or have a different client-side stub method, eg.
'tasks.setChecked'(taskId, setChecked) {
check(taskId, String);
check(setChecked, Boolean);
if(Meteor.isServer) {
if (!this.userId) {
throw new Meteor.Error('not-authorized');
}
const task = Tasks.findOne(taskId);
if (task.private && task.owner !== this.userId) {
// If the task is private, make sure only the owner can check it off
throw new Meteor.Error('not-authorized');
}
return Tasks.update(taskId, { $set: { checked: setChecked } });
} else {
console.log(`tasks.setChecked ${taskId} to ${setChecked}`)
}
},
The rest is normal stuff. Like for example re-setting the checkbox in Task.svelte
function toggleChecked() {
// Set the checked property to the opposite of its current value
let orig = task.checked
Meteor.call("tasks.setChecked", task._id, !task.checked, (err,res) => {
if(err) {
// restore previous checkbox status
this.checked = orig
} else console.log('tasks.setChecked', res)
});
return false
};