Deleting CoValues
The deleteCoValues function allows you to permanently delete CoValues from Jazz. When a CoValue is deleted, it becomes inaccessible to all users.
Deletion is permanent and cannot be undone. Once a CoValue is deleted, it cannot be recovered. Make sure you have proper confirmation flows in your application before calling deleteCoValues.
Only users with admin permissions on a CoValue's group can delete it. Attempting to delete a CoValue without admin access will throw an error.
Deleted values are not deleted from storage immediately, but are marked with a tombstone.
To balance performance considerations, the actual physical deletion of the data from storage is done asynchronously in the background, and is dependent on the sync server's configuration.
Jazz Cloud and jazz-run sync have delete enabled by default on a one minute schedule. If you're running a custom self-hosted sync server, you need to enable this feature.
Deleted CoValues stored in Jazz Cloud may persist in back-ups until they are overwritten. These back-ups undergo no additional processing, and will only be restored for disaster recovery purposes.
Basic Usage
To delete a CoValue, pass the schema and the CoValue's ID to deleteCoValues:
// Delete the note (requires admin permissions) await deleteCoValues(Note, noteId); // After deletion, loading returns a deleted state const deletedNote = await Note.load(noteId, { skipRetry: true }); deletedNote.$isLoaded; // false deletedNote.$jazz.loadingState; // "deleted"
After deletion, any attempt to load the CoValue will return a not-loaded state with loadingState: "deleted".
Deleting Nested CoValues
You can delete a CoValue along with its nested references by providing a resolve query. This works the same way as resolve queries for loading.
// Delete the document along with all attachments and their files await deleteCoValues(Document, documentId, { resolve: { attachments: { $each: { file: true, }, }, }, });
All CoValues specified in the resolve query will be deleted together. This is useful for cleaning up related data, such as deleting a document along with all its attachments and files.
Handling Inaccessible Data
Jazz validates permissions on all CoValues in the resolve query before deleting anything. If any CoValue in the tree cannot be deleted (due to missing admin permissions or inaccessibility), the entire operation fails and no data is deleted.
const me = await MusicaAccount.getMe().$jazz.ensureLoaded({ resolve: { root: { playlists: { $each: { $onError: "catch" }, }, }, }, }); // Delete all playlists referenced in the user's root. // This may include shared playlists. for (const playlist of me.root.playlists.values()) { // Skip playlists we can't even read if (!playlist.$isLoaded) continue; if (me.canAdmin(playlist)) { // Delete all the playlists we own await deleteCoValues(Playlist, playlist.$jazz.id); } else { // Remove ourselves from playlists other users shared with us playlist.$jazz.owner.removeMember(me); } }
When working with collections that might contain values you don't have admin access to, iterate over the items and check permissions before attempting deletion. This allows you to handle mixed-permission scenarios gracefully rather than having the entire delete operation fail.
Groups and Accounts
The deleteCoValues function skips Account and Group CoValues. Calling deleteCoValues on them has no effect:
const me = MusicaAccount.getMe(); const group = Group.create(); // These calls have no effect - Groups and Accounts are silently skipped await deleteCoValues(Group, group.$jazz.id); await deleteCoValues(MusicaAccount, me.$jazz.id); // This deletes the account content, but not the account itself await deleteCoValues(MusicaAccount, me.$jazz.id, { resolve: { profile: { avatar: { $each: true, }, }, root: { rootPlaylist: { tracks: { $each: { file: true, waveform: true, }, }, }, // The list content has been deleted previously playlists: true, }, }, });