# @note The order in which updates should happen: # (1) UNARCHIVE (top-bottom) should go FIRST, to ensure consistency througout all the stages sequence # * Currently: CANNOT UPDATE (or move) ARCHIVED NODES # * It can unarchive children with same archivedToken # * Changing order to happen after MOVE does NOT prevent this to happen. # * And archived children nodes cannot be moved somewhere else anyway either. # * Within UNARCHIVE, the preferable order would be ALL nodes from leafs to root # * to the purpose of preventing `already unarchived node` errors # * because, from top to bottom, the `unarchivedToken` could have already unarchived children. # * This still does not prevent the unintended consequence of automatic unarchive of children. # * HOWEVER, the error _you can't unarchive a child of an archived node_ suggest that # within UNARCHIVE, the order MUST BE from top-to-bottom, and MOREOVER # * Among nodes with the same `archiveToken` only the topest one should be unarchived (the others follow), # which prevents the errors `already unarchived node` and `can't unarchive child of archived node` # * Children with same `archiveToken` that are not to be unarchived, should be rearchived # * IMPORTANT: this could require to track all the way up to the first archived ancestor, # path from leave-to archive-root, and then for unarchive from top to bottom only those # with different archiveToken. # (1.b) IMPORTANT: automatically unarchived nodes (archivedToken) that should remain archived # should be RE-ARCHIVEd as part of the update (in the ARCHIVE stage) # (2) UPDATE ID (--) needs to happen before # * This allows other commands to refer to nodes and their parents with current ids. # * If INSERT happened before UPDATE ID, they would need to refer to the previous value of `parentId`, # but inserts don't have previous source in NodeDiff (they are new) and only a working-around (i.e. general lookup) # would allow to obtain this value (not really neat) # * Technically, the internal ORDER does NOT MATTER, but if something has to fail, let's make it fail # big: so let's do top-to-bottom. # (2.b) UPDATE NAME can happen anywhere, so let's keep tree consistent and do it as soon as possible. # (3) INSERT (top-bottom) has priority over MOVE, as there may be existing nodes being moved to or inserted to. # * And should happen AFTER the UNARCHIVE, because we could be inserting to an unarchived node # and that would make our inserted node an archived one as well. # * The internal ORDER MATTERS and it's from top to bottom (root to leaves) to prevent unknown parentId error. # (4) MOVE (--) should happen before ARCHIVE and after UNARCHIVE # * This prevents active nodes to be archived from their previous parent node, now being archived. # * It also prevents the error of moving to an archived node, or not being able to move an archived node. # * If it happened before UNARCHIVE, we would be either move ARCHIVED nodes to be unarchived, # or moving other nodes to them before they are unarchived # * Technically, for MOVE, the internal ORDER does NOT MATTER. It would matter for new/inserted nodes, # but we do not move inserted nodes (we add them directly to the parent). # * However, to build the remap tags table, it does matter: from bottom to top. Children should be # retagged first because retagging first parents changes the path of their children retags. # (5) ARCHIVE (bottom-top) should happen always LAST, after nodes have been MOVED. # • The order of archiving should probably be: # (a) although firstly thought go from leafs to root to prevent the `archiveToken` # it should go from top-to-bottom, so precisely the `archiveToken` is generated and history well sorted. # (b) to preventing `already archived node` errors, we should only include the parent # (6) RE-ARCHIVE (bottom-top) see (1.b) all those that were automatically unarchived but should remain archived. # • The neat solution is to recalculate changes with the live_tree and the final desired result, # but perhaps only target those to be re-archived? class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs module Stages STAGES = %i[unarchive id_name insert move archive].freeze def stages STAGES end def stage_idx(stage) stages.index(stage) end def id_update_stage_idx @id_update_stage_idx ||= stage_idx(:id) || stage_idx(:id_name) end def move_stage_idx @move_stage_idx ||= stage_idx(:move) end def after_id_update?(stage) (idx = stage_idx(stage)) && idx > id_update_stage_idx end def during_or_after_move?(stage) (idx = stage_idx(stage)) && idx >= move_stage_idx end end end require_relative 'stages/sortable' require_relative 'stages/diff_sortable' require_relative 'stages/commandable'