mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-13 19:08:45 +00:00
86 lines
2.9 KiB
TypeScript
86 lines
2.9 KiB
TypeScript
import { Schema, SchemaTransformation } from "effect"
|
|
import { FileDiff } from "./file-diff.js"
|
|
import { optional } from "./schema.js"
|
|
import { SessionMessage } from "./session-message.js"
|
|
import { Snapshot } from "./snapshot.js"
|
|
|
|
export interface Revert extends Schema.Schema.Type<typeof Revert> {}
|
|
export const Revert = Schema.Struct({
|
|
messageID: SessionMessage.ID,
|
|
/** Legacy V1 compatibility state. */
|
|
partID: Schema.String.pipe(optional),
|
|
snapshot: Snapshot.ID.pipe(optional),
|
|
files: Schema.Array(FileDiff.Info).pipe(optional),
|
|
}).annotate({ identifier: "Session.Revert" })
|
|
|
|
const FileDiffV1 = Schema.Struct({
|
|
path: Schema.String,
|
|
status: Schema.Literals(["added", "modified", "deleted"]),
|
|
additions: Schema.Finite,
|
|
deletions: Schema.Finite,
|
|
patch: Schema.String,
|
|
})
|
|
|
|
export interface RevertV1 extends Schema.Schema.Type<typeof RevertV1> {}
|
|
export const RevertV1 = Schema.Struct({
|
|
messageID: SessionMessage.ID,
|
|
partID: Schema.String.pipe(optional),
|
|
snapshot: Schema.String.pipe(optional),
|
|
diff: Schema.String.pipe(optional),
|
|
files: Schema.Array(FileDiffV1).pipe(optional),
|
|
}).annotate({ identifier: "Session.RevertV1" })
|
|
|
|
const PersistedCurrent = Revert.pipe(
|
|
Schema.decodeTo(
|
|
Schema.Struct({ source: Schema.tag("current"), revert: Schema.toType(Revert) }),
|
|
SchemaTransformation.transform({
|
|
decode: (revert): { readonly source: "current"; readonly revert: Revert } => ({
|
|
source: "current",
|
|
revert,
|
|
}),
|
|
encode: (value) => value.revert,
|
|
}),
|
|
),
|
|
)
|
|
const PersistedLegacy = RevertV1.pipe(
|
|
Schema.decodeTo(
|
|
Schema.Struct({ source: Schema.tag("legacy"), revert: Schema.toType(RevertV1) }),
|
|
SchemaTransformation.transform({
|
|
decode: (revert): { readonly source: "legacy"; readonly revert: RevertV1 } => ({
|
|
source: "legacy",
|
|
revert,
|
|
}),
|
|
encode: (value) => value.revert,
|
|
}),
|
|
),
|
|
)
|
|
|
|
/** Storage decoder for revert state written before FileDiff became canonical. */
|
|
export const PersistedRevert = Schema.Union([PersistedCurrent, PersistedLegacy]).pipe(
|
|
Schema.toTaggedUnion("source"),
|
|
Schema.decodeTo(
|
|
Schema.toType(Revert),
|
|
SchemaTransformation.transform({
|
|
decode: (persisted): Revert => {
|
|
if (persisted.source === "current") return persisted.revert
|
|
return Revert.make({
|
|
messageID: persisted.revert.messageID,
|
|
partID: persisted.revert.partID,
|
|
snapshot: persisted.revert.snapshot ? Snapshot.ID.make(persisted.revert.snapshot) : undefined,
|
|
files: persisted.revert.files?.map((file) => ({
|
|
file: file.path,
|
|
status: file.status,
|
|
additions: file.additions,
|
|
deletions: file.deletions,
|
|
patch: file.patch,
|
|
})),
|
|
})
|
|
},
|
|
encode: (revert): { readonly source: "current"; readonly revert: Revert } => ({
|
|
source: "current",
|
|
revert,
|
|
}),
|
|
}),
|
|
),
|
|
Schema.annotate({ identifier: "Session.Revert.Persisted" }),
|
|
)
|