ber.bend
ber-core-store@0.1.1.0 · 129 lines · 0 definitions
1import Base
2import ber-core-store@0.1.1.0/src/Store.bend as Store
3import ber-core-store@0.1.1.0/src/Value.bend as Value
4import ber-core-store@0.1.1.0/src/LogicalKey.bend as LogicalKey
5import ber-core-store@0.1.1.0/src/Staging.bend as Staging
6import ber-core-store@0.1.1.0/src/History.bend as History
7import ber-core-store@0.1.1.0/src/StateTree.bend as StateTree
8import ber-core-store@0.1.1.0/src/Comparison.bend as Comparison
9import ber-core-store@0.1.1.0/src/Merging.bend as Merging
10import ber-core-store@0.1.1.0/src/Certificate.bend as Certificate
11import ber-core-store@0.1.1.0/src/JsonAdapter.bend as JsonAdapter
12
13# Public API of ber-core. Single import for consumers; Store carries the
14# Op/Handle session types. Level 2 delegates expose full power with internal
15# types visible; Level 1 composes the common paths into opaque String
16# results. Values are multi-type (text, document, binary blob), never bare
17# text; reports are human-readable Strings, never domain values.
18
19# --- Level 2: domain delegates (1:1) ---
20
21# Stages one value for later commit.
22def put_record(+session_id: String, +namespace_name: String, +record_id: String, value: Value.Value) -> Store.Op<&2, LogicalKey.LogicalKey>:
23 Staging.put_record(session_id, namespace_name, record_id, value)
24
25# Stages a tombstone for later commit.
26def delete_record(+session_id: String, +namespace_name: String, +record_id: String) -> Store.Op<&2, LogicalKey.LogicalKey>:
27 Staging.delete_record(session_id, namespace_name, record_id)
28
29# Materializes stage plus base into a new commit.
30def create_commit(+session_id: String, +parent_ids: List<&2, String>, metadata: List<&2, History.CommitMeta>) -> Store.Op<&2, History.Commit>:
31 History.create_commit(session_id, parent_ids, metadata)
32
33# Reads a namespaced value at a commit.
34def read_value_at(+namespace_name: String, +record_id: String, +commit_id: String) -> Store.Op<&2, Maybe<&2, Value.Value>>:
35 History.read_value_at(namespace_name, record_id, commit_id)
36
37# Reads the tree for a commit identifier.
38def read_tree_at(+commit_id: String) -> Store.Op<&2, Maybe<&2, StateTree.StateTreeNode>>:
39 History.read_tree_at(commit_id)
40
41# Diffs two commits with hash pruning.
42def compare_commits(+first_id: String, +second_id: String) -> Store.Op<&2, Comparison.CompareResult>:
43 Comparison.compare_commits(first_id, second_id)
44
45# Merges two commits by strategy name.
46def merge_commits(+first_id: String, +second_id: String, +strategy_name: String) -> Store.Op<&2, Merging.MergeResult>:
47 Merging.merge_commits(first_id, second_id, strategy_name)
48
49# Verifies a merge certificate against stored trees.
50def verify_certificate(+certificate: Merging.MergeCertificate) -> Store.Op<&2, Bool>:
51 Certificate.verify_certificate(certificate)
52
53# --- Level 1: composed operations (primary API) ---
54
55# Stages a value and commits in one step; returns the new commit identifier.
56def commit_value(+session_id: String, +namespace_name: String, +record_id: String, value: Value.Value, parents: List<&2, String>) -> Store.Op<&2, String>:
57 do Store.Op<&2, String>:
58 staged_key : LogicalKey.LogicalKey <- Staging.put_record(session_id, namespace_name, record_id, value)
59 new_commit : History.Commit <- History.create_commit(session_id, parents, Nil{})
60 return History.commit_identifier_of(new_commit)
61
62# Stages a tombstone and commits in one step; returns the new commit identifier.
63def remove_record(+session_id: String, +namespace_name: String, +record_id: String, parents: List<&2, String>) -> Store.Op<&2, String>:
64 do Store.Op<&2, String>:
65 staged_key : LogicalKey.LogicalKey <- Staging.delete_record(session_id, namespace_name, record_id)
66 new_commit : History.Commit <- History.create_commit(session_id, parents, Nil{})
67 return History.commit_identifier_of(new_commit)
68
69# Renders one diff count line.
70def render_compare_counts(+compare_result: Comparison.CompareResult) -> String:
71 "added=" ++ Nat.show(List.length(&2, LogicalKey.LogicalKey, Comparison.added_keys_of(compare_result))) ++ " removed=" ++ Nat.show(List.length(&2, LogicalKey.LogicalKey, Comparison.removed_keys_of(compare_result))) ++ " modified=" ++ Nat.show(List.length(&2, Comparison.ModifiedEntry, Comparison.modified_entries_of(compare_result)))
72
73# Diffs two commits and renders the counts.
74def compare_summary(+first_id: String, +second_id: String) -> Store.Op<&2, String>:
75 do Store.Op<&2, String>:
76 compared : Comparison.CompareResult <- Comparison.compare_commits(first_id, second_id)
77 return render_compare_counts(compared)
78
79# Renders a verified merge; failed verification is unprovable.
80def decide_verified_text(verified_ok: Bool, +commit_id: String) -> String:
81 match verified_ok:
82 case True{}:
83 "merged:" ++ commit_id
84 case False{}:
85 "unprovable:verify-failed"
86
87# Verifies a successful merge and renders the verdict.
88def verify_successful_merge(+resulting_commit: History.Commit, +certificate: Merging.MergeCertificate) -> Store.Op<&2, String>:
89 do Store.Op<&2, String>:
90 verified_ok : Bool <- Certificate.verify_certificate(certificate)
91 return decide_verified_text(verified_ok, History.commit_identifier_of(resulting_commit))
92
93# Renders a merge outcome; conflicts count keys, unprovable names the reason.
94def verify_merge_outcome(merge_result: Merging.MergeResult) -> Store.Op<&2, String>:
95 match merge_result:
96 case Merging.MergeSuccess{resulting_commit, certificate}:
97 verify_successful_merge(resulting_commit, certificate)
98 case Merging.MergeConflict{conflicting_keys}:
99 Store.Op.pure(&2, String, "conflict:" ++ Nat.show(List.length(&2, LogicalKey.LogicalKey, conflicting_keys)))
100 case Merging.MergeUnprovable{reason}:
101 Store.Op.pure(&2, String, "unprovable:" ++ reason)
102
103# Merges union-disjoint and verifies; renders merged, conflict or unprovable.
104def merge_and_verify(+first_id: String, +second_id: String) -> Store.Op<&2, String>:
105 do Store.Op<&2, String>:
106 merged_result : Merging.MergeResult <- Merging.merge_commits(first_id, second_id, "union-disjoint")
107 verify_merge_outcome(merged_result)
108
109# Renders one found value; blobs show size, never raw bytes.
110def render_found_value(found_value: Value.Value) -> String:
111 match found_value:
112 case Value.Text{content}:
113 "read=" ++ content
114 case Value.Object{document}:
115 "read=" ++ JsonAdapter.encode_canonical(document)
116 case Value.Blob{byte_list}:
117 "read=<blob " ++ Nat.show(List.length(&2, U32, byte_list)) ++ " bytes>"
118
119# Renders a read; absent reads as absent.
120def render_read_value(read_value: Maybe<&2, Value.Value>) -> String:
121 match read_value:
122 case None{}:
123 "read=absent"
124 case Some{found_value}:
125 render_found_value(found_value)
126
127# Renders a read plus diff and merge lines; the demo report shape.
128def format_report(read_value: Maybe<&2, Value.Value>, +diff_line: String, +merge_line: String) -> String:
129 render_read_value(read_value) ++ "\n" ++ diff_line ++ "\n" ++ merge_line