Advance M7 workflows and release operations
This commit is contained in:
53
web/protocol/dirty-state.ts
Normal file
53
web/protocol/dirty-state.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
export interface DirtyState {
|
||||
currentMainRevision: number;
|
||||
committedMainRevision: number;
|
||||
dirty: boolean;
|
||||
}
|
||||
|
||||
export type DirtyStateResult =
|
||||
| { ok: true; state: DirtyState }
|
||||
| { ok: false; state: DirtyState; errorCode: "DIRTY_REVISION_INVALID" | "DIRTY_REVISION_STALE" | "DIRTY_SAVE_REVISION_MISMATCH" };
|
||||
|
||||
function validRevision(revision: number): boolean {
|
||||
return Number.isSafeInteger(revision) && revision >= 0;
|
||||
}
|
||||
|
||||
export function createDirtyState(revision = 0): DirtyState {
|
||||
if (!validRevision(revision)) throw new Error("DIRTY_REVISION_INVALID");
|
||||
return { currentMainRevision: revision, committedMainRevision: revision, dirty: false };
|
||||
}
|
||||
|
||||
export function recoverDirtyState(currentMainRevision: number, committedMainRevision: number): DirtyState {
|
||||
if (!validRevision(currentMainRevision) || !validRevision(committedMainRevision) || currentMainRevision < committedMainRevision) {
|
||||
throw new Error("DIRTY_REVISION_INVALID");
|
||||
}
|
||||
return { currentMainRevision, committedMainRevision, dirty: currentMainRevision !== committedMainRevision };
|
||||
}
|
||||
|
||||
export function acceptMainTransaction(state: DirtyState, revision: number): DirtyStateResult {
|
||||
if (!validRevision(revision)) return { ok: false, state, errorCode: "DIRTY_REVISION_INVALID" };
|
||||
if (revision <= state.currentMainRevision) return { ok: false, state, errorCode: "DIRTY_REVISION_STALE" };
|
||||
return {
|
||||
ok: true,
|
||||
state: { ...state, currentMainRevision: revision, dirty: revision !== state.committedMainRevision },
|
||||
};
|
||||
}
|
||||
|
||||
export function acceptMainSave(state: DirtyState, revision: number): DirtyStateResult {
|
||||
if (!validRevision(revision)) return { ok: false, state, errorCode: "DIRTY_REVISION_INVALID" };
|
||||
if (revision !== state.currentMainRevision) return { ok: false, state, errorCode: "DIRTY_SAVE_REVISION_MISMATCH" };
|
||||
return { ok: true, state: { currentMainRevision: revision, committedMainRevision: revision, dirty: false } };
|
||||
}
|
||||
|
||||
export function acceptHistoryTransaction(state: DirtyState, revision: number, matchesCommittedContent: boolean): DirtyStateResult {
|
||||
if (!validRevision(revision)) return { ok: false, state, errorCode: "DIRTY_REVISION_INVALID" };
|
||||
if (revision <= state.currentMainRevision) return { ok: false, state, errorCode: "DIRTY_REVISION_STALE" };
|
||||
return {
|
||||
ok: true,
|
||||
state: {
|
||||
currentMainRevision: revision,
|
||||
committedMainRevision: matchesCommittedContent ? revision : state.committedMainRevision,
|
||||
dirty: !matchesCommittedContent,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user