@lix-js/sdk 0.6.0-preview.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/README.md +76 -4
  2. package/dist/errors.d.ts +7 -0
  3. package/dist/errors.js +19 -0
  4. package/dist/index.d.ts +4 -5
  5. package/dist/index.js +3 -3
  6. package/dist/native.d.ts +1 -0
  7. package/dist/native.js +47 -0
  8. package/dist/open-lix.d.ts +39 -201
  9. package/dist/open-lix.js +59 -284
  10. package/dist/result.d.ts +18 -0
  11. package/dist/result.js +48 -0
  12. package/dist/types.d.ts +114 -1
  13. package/dist/value.d.ts +28 -0
  14. package/dist/value.js +245 -0
  15. package/package.json +20 -50
  16. package/SKILL.md +0 -506
  17. package/dist/builtin-schemas.d.ts +0 -1
  18. package/dist/builtin-schemas.js +0 -1
  19. package/dist/engine-wasm/index.d.ts +0 -87
  20. package/dist/engine-wasm/index.js +0 -339
  21. package/dist/engine-wasm/wasm/lix_engine.d.ts +0 -79
  22. package/dist/engine-wasm/wasm/lix_engine.js +0 -821
  23. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  24. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +0 -26
  25. package/dist/generated/builtin-schemas.d.ts +0 -427
  26. package/dist/generated/builtin-schemas.js +0 -643
  27. package/dist/sqlite/index.d.ts +0 -12
  28. package/dist/sqlite/index.js +0 -303
  29. package/dist-engine-src/README.md +0 -18
  30. package/dist-engine-src/src/backend/kv.rs +0 -358
  31. package/dist-engine-src/src/backend/mod.rs +0 -12
  32. package/dist-engine-src/src/backend/testing.rs +0 -658
  33. package/dist-engine-src/src/backend/types.rs +0 -96
  34. package/dist-engine-src/src/binary_cas/chunking.rs +0 -31
  35. package/dist-engine-src/src/binary_cas/codec.rs +0 -346
  36. package/dist-engine-src/src/binary_cas/context.rs +0 -139
  37. package/dist-engine-src/src/binary_cas/kv.rs +0 -1063
  38. package/dist-engine-src/src/binary_cas/mod.rs +0 -11
  39. package/dist-engine-src/src/binary_cas/types.rs +0 -121
  40. package/dist-engine-src/src/catalog/context.rs +0 -412
  41. package/dist-engine-src/src/catalog/mod.rs +0 -10
  42. package/dist-engine-src/src/catalog/schema.rs +0 -4
  43. package/dist-engine-src/src/catalog/snapshot.rs +0 -1114
  44. package/dist-engine-src/src/cel/context.rs +0 -86
  45. package/dist-engine-src/src/cel/error.rs +0 -19
  46. package/dist-engine-src/src/cel/mod.rs +0 -8
  47. package/dist-engine-src/src/cel/provider.rs +0 -9
  48. package/dist-engine-src/src/cel/runtime.rs +0 -167
  49. package/dist-engine-src/src/cel/value.rs +0 -50
  50. package/dist-engine-src/src/commit_graph/context.rs +0 -901
  51. package/dist-engine-src/src/commit_graph/mod.rs +0 -11
  52. package/dist-engine-src/src/commit_graph/types.rs +0 -109
  53. package/dist-engine-src/src/commit_graph/walker.rs +0 -756
  54. package/dist-engine-src/src/commit_store/codec.rs +0 -887
  55. package/dist-engine-src/src/commit_store/context.rs +0 -944
  56. package/dist-engine-src/src/commit_store/materialization.rs +0 -84
  57. package/dist-engine-src/src/commit_store/mod.rs +0 -16
  58. package/dist-engine-src/src/commit_store/storage.rs +0 -600
  59. package/dist-engine-src/src/commit_store/types.rs +0 -215
  60. package/dist-engine-src/src/common/error.rs +0 -313
  61. package/dist-engine-src/src/common/fingerprint.rs +0 -3
  62. package/dist-engine-src/src/common/fs_path.rs +0 -1336
  63. package/dist-engine-src/src/common/identity.rs +0 -145
  64. package/dist-engine-src/src/common/json_pointer.rs +0 -67
  65. package/dist-engine-src/src/common/metadata.rs +0 -40
  66. package/dist-engine-src/src/common/mod.rs +0 -23
  67. package/dist-engine-src/src/common/types.rs +0 -105
  68. package/dist-engine-src/src/common/wire.rs +0 -222
  69. package/dist-engine-src/src/domain.rs +0 -324
  70. package/dist-engine-src/src/engine.rs +0 -225
  71. package/dist-engine-src/src/entity_identity.rs +0 -405
  72. package/dist-engine-src/src/functions/context.rs +0 -292
  73. package/dist-engine-src/src/functions/deterministic.rs +0 -113
  74. package/dist-engine-src/src/functions/mod.rs +0 -18
  75. package/dist-engine-src/src/functions/provider.rs +0 -130
  76. package/dist-engine-src/src/functions/state.rs +0 -336
  77. package/dist-engine-src/src/functions/types.rs +0 -37
  78. package/dist-engine-src/src/init.rs +0 -558
  79. package/dist-engine-src/src/json_store/compression.rs +0 -77
  80. package/dist-engine-src/src/json_store/context.rs +0 -423
  81. package/dist-engine-src/src/json_store/encoded.rs +0 -15
  82. package/dist-engine-src/src/json_store/mod.rs +0 -12
  83. package/dist-engine-src/src/json_store/store.rs +0 -1109
  84. package/dist-engine-src/src/json_store/types.rs +0 -217
  85. package/dist-engine-src/src/lib.rs +0 -62
  86. package/dist-engine-src/src/live_state/context.rs +0 -2019
  87. package/dist-engine-src/src/live_state/mod.rs +0 -15
  88. package/dist-engine-src/src/live_state/overlay.rs +0 -75
  89. package/dist-engine-src/src/live_state/reader.rs +0 -23
  90. package/dist-engine-src/src/live_state/types.rs +0 -222
  91. package/dist-engine-src/src/live_state/visibility.rs +0 -223
  92. package/dist-engine-src/src/plugin/archive.rs +0 -438
  93. package/dist-engine-src/src/plugin/component.rs +0 -183
  94. package/dist-engine-src/src/plugin/install.rs +0 -619
  95. package/dist-engine-src/src/plugin/manifest.rs +0 -516
  96. package/dist-engine-src/src/plugin/materializer.rs +0 -477
  97. package/dist-engine-src/src/plugin/mod.rs +0 -33
  98. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -118
  99. package/dist-engine-src/src/plugin/storage.rs +0 -74
  100. package/dist-engine-src/src/schema/annotations/defaults.rs +0 -275
  101. package/dist-engine-src/src/schema/annotations/mod.rs +0 -1
  102. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -21
  103. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -29
  104. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -29
  105. package/dist-engine-src/src/schema/builtin/lix_change.json +0 -63
  106. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -45
  107. package/dist-engine-src/src/schema/builtin/lix_commit.json +0 -24
  108. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +0 -53
  109. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -52
  110. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -52
  111. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -40
  112. package/dist-engine-src/src/schema/builtin/lix_label.json +0 -29
  113. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +0 -74
  114. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +0 -25
  115. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
  116. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
  117. package/dist-engine-src/src/schema/builtin/mod.rs +0 -222
  118. package/dist-engine-src/src/schema/compatibility.rs +0 -787
  119. package/dist-engine-src/src/schema/definition.json +0 -187
  120. package/dist-engine-src/src/schema/definition.rs +0 -742
  121. package/dist-engine-src/src/schema/key.rs +0 -138
  122. package/dist-engine-src/src/schema/mod.rs +0 -20
  123. package/dist-engine-src/src/schema/seed.rs +0 -14
  124. package/dist-engine-src/src/schema/tests.rs +0 -780
  125. package/dist-engine-src/src/session/context.rs +0 -404
  126. package/dist-engine-src/src/session/create_version.rs +0 -88
  127. package/dist-engine-src/src/session/execute.rs +0 -541
  128. package/dist-engine-src/src/session/merge/analysis.rs +0 -102
  129. package/dist-engine-src/src/session/merge/apply.rs +0 -23
  130. package/dist-engine-src/src/session/merge/conflicts.rs +0 -63
  131. package/dist-engine-src/src/session/merge/mod.rs +0 -11
  132. package/dist-engine-src/src/session/merge/stats.rs +0 -65
  133. package/dist-engine-src/src/session/merge/version.rs +0 -427
  134. package/dist-engine-src/src/session/mod.rs +0 -27
  135. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
  136. package/dist-engine-src/src/session/switch_version.rs +0 -110
  137. package/dist-engine-src/src/session/transaction.rs +0 -76
  138. package/dist-engine-src/src/sql2/change_provider.rs +0 -331
  139. package/dist-engine-src/src/sql2/classify.rs +0 -174
  140. package/dist-engine-src/src/sql2/context.rs +0 -311
  141. package/dist-engine-src/src/sql2/directory_history_provider.rs +0 -631
  142. package/dist-engine-src/src/sql2/directory_provider.rs +0 -2453
  143. package/dist-engine-src/src/sql2/dml.rs +0 -148
  144. package/dist-engine-src/src/sql2/entity_history_provider.rs +0 -440
  145. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  146. package/dist-engine-src/src/sql2/error.rs +0 -215
  147. package/dist-engine-src/src/sql2/execute.rs +0 -3533
  148. package/dist-engine-src/src/sql2/file_history_provider.rs +0 -910
  149. package/dist-engine-src/src/sql2/file_provider.rs +0 -3679
  150. package/dist-engine-src/src/sql2/filesystem_planner.rs +0 -1490
  151. package/dist-engine-src/src/sql2/filesystem_predicates.rs +0 -159
  152. package/dist-engine-src/src/sql2/filesystem_visibility.rs +0 -383
  153. package/dist-engine-src/src/sql2/history_projection.rs +0 -56
  154. package/dist-engine-src/src/sql2/history_provider.rs +0 -412
  155. package/dist-engine-src/src/sql2/history_route.rs +0 -657
  156. package/dist-engine-src/src/sql2/lix_state_provider.rs +0 -2512
  157. package/dist-engine-src/src/sql2/mod.rs +0 -47
  158. package/dist-engine-src/src/sql2/predicate_typecheck.rs +0 -246
  159. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  160. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  161. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
  162. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
  163. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  164. package/dist-engine-src/src/sql2/read_only.rs +0 -63
  165. package/dist-engine-src/src/sql2/record_batch.rs +0 -17
  166. package/dist-engine-src/src/sql2/result_metadata.rs +0 -29
  167. package/dist-engine-src/src/sql2/runtime.rs +0 -60
  168. package/dist-engine-src/src/sql2/session.rs +0 -132
  169. package/dist-engine-src/src/sql2/udfs/common.rs +0 -295
  170. package/dist-engine-src/src/sql2/udfs/lix_active_version_commit_id.rs +0 -53
  171. package/dist-engine-src/src/sql2/udfs/lix_empty_blob.rs +0 -47
  172. package/dist-engine-src/src/sql2/udfs/lix_json.rs +0 -100
  173. package/dist-engine-src/src/sql2/udfs/lix_json_get.rs +0 -99
  174. package/dist-engine-src/src/sql2/udfs/lix_json_get_text.rs +0 -99
  175. package/dist-engine-src/src/sql2/udfs/lix_text_decode.rs +0 -82
  176. package/dist-engine-src/src/sql2/udfs/lix_text_encode.rs +0 -85
  177. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +0 -76
  178. package/dist-engine-src/src/sql2/udfs/lix_uuid_v7.rs +0 -76
  179. package/dist-engine-src/src/sql2/udfs/mod.rs +0 -89
  180. package/dist-engine-src/src/sql2/udfs/public_call.rs +0 -238
  181. package/dist-engine-src/src/sql2/version_provider.rs +0 -1202
  182. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  183. package/dist-engine-src/src/sql2/write_normalization.rs +0 -345
  184. package/dist-engine-src/src/storage/context.rs +0 -356
  185. package/dist-engine-src/src/storage/mod.rs +0 -14
  186. package/dist-engine-src/src/storage/read_scope.rs +0 -88
  187. package/dist-engine-src/src/storage/types.rs +0 -501
  188. package/dist-engine-src/src/storage_bench.rs +0 -4863
  189. package/dist-engine-src/src/test_support.rs +0 -228
  190. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  191. package/dist-engine-src/src/tracked_state/codec.rs +0 -2085
  192. package/dist-engine-src/src/tracked_state/context.rs +0 -1867
  193. package/dist-engine-src/src/tracked_state/diff.rs +0 -686
  194. package/dist-engine-src/src/tracked_state/materialization.rs +0 -403
  195. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  196. package/dist-engine-src/src/tracked_state/merge.rs +0 -492
  197. package/dist-engine-src/src/tracked_state/mod.rs +0 -32
  198. package/dist-engine-src/src/tracked_state/storage.rs +0 -375
  199. package/dist-engine-src/src/tracked_state/tree.rs +0 -3187
  200. package/dist-engine-src/src/tracked_state/types.rs +0 -231
  201. package/dist-engine-src/src/transaction/commit.rs +0 -1484
  202. package/dist-engine-src/src/transaction/context.rs +0 -1548
  203. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  204. package/dist-engine-src/src/transaction/mod.rs +0 -13
  205. package/dist-engine-src/src/transaction/normalization.rs +0 -890
  206. package/dist-engine-src/src/transaction/prep.rs +0 -37
  207. package/dist-engine-src/src/transaction/schema_resolver.rs +0 -149
  208. package/dist-engine-src/src/transaction/staging.rs +0 -1731
  209. package/dist-engine-src/src/transaction/types.rs +0 -460
  210. package/dist-engine-src/src/transaction/validation.rs +0 -5830
  211. package/dist-engine-src/src/untracked_state/codec.rs +0 -307
  212. package/dist-engine-src/src/untracked_state/context.rs +0 -98
  213. package/dist-engine-src/src/untracked_state/materialization.rs +0 -63
  214. package/dist-engine-src/src/untracked_state/mod.rs +0 -15
  215. package/dist-engine-src/src/untracked_state/storage.rs +0 -396
  216. package/dist-engine-src/src/untracked_state/types.rs +0 -146
  217. package/dist-engine-src/src/version/context.rs +0 -40
  218. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  219. package/dist-engine-src/src/version/mod.rs +0 -13
  220. package/dist-engine-src/src/version/refs.rs +0 -330
  221. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  222. package/dist-engine-src/src/version/types.rs +0 -21
  223. package/dist-engine-src/src/wasm/mod.rs +0 -60
@@ -1,394 +0,0 @@
1
- use std::collections::BTreeSet;
2
-
3
- use datafusion::error::DataFusionError;
4
- use datafusion::logical_expr::expr::InList;
5
- use datafusion::logical_expr::{BinaryExpr, Expr, Operator};
6
- use datafusion::scalar::ScalarValue;
7
-
8
- use crate::version::VersionRefReader;
9
- use crate::LixError;
10
- use crate::GLOBAL_VERSION_ID;
11
-
12
- /// Version scope requested by a SQL surface.
13
- ///
14
- /// Active surfaces read through one session version. By-version surfaces either
15
- /// read explicitly filtered versions or, without a version predicate, enumerate
16
- /// every visible version scope before handing the request to live_state.
17
- pub(crate) enum SqlVersionScope {
18
- Active(String),
19
- Explicit(Vec<String>),
20
- AllVisible,
21
- }
22
-
23
- #[derive(Debug, Clone, PartialEq, Eq)]
24
- pub(crate) enum VersionBinding {
25
- Active { version_id: String },
26
- Explicit,
27
- }
28
-
29
- #[derive(Debug, Clone, PartialEq, Eq)]
30
- pub(crate) struct WriteVersionScope {
31
- pub(crate) version_id: String,
32
- pub(crate) global: bool,
33
- }
34
-
35
- impl VersionBinding {
36
- pub(crate) fn active(version_id: impl Into<String>) -> Self {
37
- Self::Active {
38
- version_id: version_id.into(),
39
- }
40
- }
41
-
42
- pub(crate) fn explicit() -> Self {
43
- Self::Explicit
44
- }
45
-
46
- pub(crate) fn active_version_id(&self) -> Option<&str> {
47
- match self {
48
- Self::Active { version_id } => Some(version_id),
49
- Self::Explicit => None,
50
- }
51
- }
52
-
53
- pub(crate) fn require_active_version_id(&self, action: &str) -> Result<String, LixError> {
54
- match self {
55
- Self::Active { version_id } => Ok(version_id.clone()),
56
- Self::Explicit => Err(LixError::new(
57
- "LIX_ERROR_UNKNOWN",
58
- format!("{action} is only supported for active-version SQL surfaces"),
59
- )),
60
- }
61
- }
62
- }
63
-
64
- pub(crate) fn resolve_write_version_scope(
65
- explicit_global: Option<bool>,
66
- explicit_version_id: Option<String>,
67
- fallback_version_id: Option<&str>,
68
- action: &str,
69
- surface: &str,
70
- ) -> Result<WriteVersionScope, DataFusionError> {
71
- if explicit_global == Some(true) {
72
- if explicit_version_id
73
- .as_deref()
74
- .is_some_and(|version_id| version_id != GLOBAL_VERSION_ID)
75
- {
76
- return Err(DataFusionError::Execution(format!(
77
- "{surface} cannot set lixcol_global=true with non-global lixcol_version_id"
78
- )));
79
- }
80
- return Ok(WriteVersionScope {
81
- version_id: GLOBAL_VERSION_ID.to_string(),
82
- global: true,
83
- });
84
- }
85
-
86
- let version_id = explicit_version_id
87
- .or_else(|| fallback_version_id.map(ToOwned::to_owned))
88
- .ok_or_else(|| {
89
- DataFusionError::Execution(format!("{action} requires lixcol_version_id"))
90
- })?;
91
- if explicit_global == Some(false) && version_id == GLOBAL_VERSION_ID {
92
- return Err(DataFusionError::Execution(format!(
93
- "{surface} cannot set lixcol_global=false with global lixcol_version_id"
94
- )));
95
- }
96
- Ok(WriteVersionScope {
97
- global: explicit_global.unwrap_or(version_id == GLOBAL_VERSION_ID),
98
- version_id,
99
- })
100
- }
101
-
102
- impl SqlVersionScope {
103
- pub(crate) fn from_provider(
104
- binding: &VersionBinding,
105
- requested_version_ids: Vec<String>,
106
- ) -> Self {
107
- match binding {
108
- VersionBinding::Active { version_id } => Self::Active(version_id.clone()),
109
- VersionBinding::Explicit if requested_version_ids.is_empty() => Self::AllVisible,
110
- VersionBinding::Explicit => Self::Explicit(requested_version_ids),
111
- }
112
- }
113
- }
114
-
115
- pub(crate) async fn resolve_sql_version_scope(
116
- version_ref: &dyn VersionRefReader,
117
- scope: SqlVersionScope,
118
- ) -> Result<Vec<String>, LixError> {
119
- match scope {
120
- SqlVersionScope::Active(version_id) => Ok(vec![version_id]),
121
- SqlVersionScope::Explicit(version_ids) => Ok(version_ids),
122
- SqlVersionScope::AllVisible => visible_version_ids(version_ref).await,
123
- }
124
- }
125
-
126
- pub(crate) async fn resolve_provider_version_ids(
127
- version_ref: &dyn VersionRefReader,
128
- binding: &VersionBinding,
129
- requested_version_ids: Vec<String>,
130
- ) -> Result<Vec<String>, LixError> {
131
- resolve_sql_version_scope(
132
- version_ref,
133
- SqlVersionScope::from_provider(binding, requested_version_ids),
134
- )
135
- .await
136
- }
137
-
138
- pub(crate) fn explicit_version_ids_from_dml_filters(filters: &[Expr]) -> Vec<String> {
139
- filters
140
- .iter()
141
- .flat_map(version_ids_from_filter)
142
- .collect::<BTreeSet<_>>()
143
- .into_iter()
144
- .collect()
145
- }
146
-
147
- fn version_ids_from_filter(expr: &Expr) -> Vec<String> {
148
- match expr {
149
- Expr::BinaryExpr(binary_expr) if binary_expr.op == Operator::And => {
150
- let mut values = version_ids_from_filter(&binary_expr.left);
151
- values.extend(version_ids_from_filter(&binary_expr.right));
152
- values
153
- }
154
- Expr::BinaryExpr(binary_expr) => version_id_from_binary_filter(binary_expr)
155
- .map(|value| vec![value])
156
- .unwrap_or_default(),
157
- Expr::InList(in_list) => version_ids_from_in_list_filter(in_list).unwrap_or_default(),
158
- _ => Vec::new(),
159
- }
160
- }
161
-
162
- fn version_id_from_binary_filter(binary_expr: &BinaryExpr) -> Option<String> {
163
- if binary_expr.op != Operator::Eq {
164
- return None;
165
- }
166
-
167
- version_id_from_column_literal_filter(&binary_expr.left, &binary_expr.right)
168
- .or_else(|| version_id_from_column_literal_filter(&binary_expr.right, &binary_expr.left))
169
- }
170
-
171
- fn version_ids_from_in_list_filter(in_list: &InList) -> Option<Vec<String>> {
172
- if in_list.negated {
173
- return None;
174
- }
175
- let Expr::Column(column) = in_list.expr.as_ref() else {
176
- return None;
177
- };
178
- if column.name != "lixcol_version_id" {
179
- return None;
180
- }
181
-
182
- let values = in_list
183
- .list
184
- .iter()
185
- .map(string_expr_literal)
186
- .collect::<Option<Vec<_>>>()?;
187
- if values.is_empty() {
188
- return None;
189
- }
190
- Some(values)
191
- }
192
-
193
- fn version_id_from_column_literal_filter(
194
- column_expr: &Expr,
195
- literal_expr: &Expr,
196
- ) -> Option<String> {
197
- let Expr::Column(column) = column_expr else {
198
- return None;
199
- };
200
- if column.name != "lixcol_version_id" {
201
- return None;
202
- }
203
- string_expr_literal(literal_expr)
204
- }
205
-
206
- fn string_expr_literal(expr: &Expr) -> Option<String> {
207
- let Expr::Literal(literal, _) = expr else {
208
- return None;
209
- };
210
- match literal {
211
- ScalarValue::Utf8(Some(value))
212
- | ScalarValue::Utf8View(Some(value))
213
- | ScalarValue::LargeUtf8(Some(value)) => Some(value.clone()),
214
- _ => None,
215
- }
216
- }
217
-
218
- async fn visible_version_ids(version_ref: &dyn VersionRefReader) -> Result<Vec<String>, LixError> {
219
- let mut version_ids = version_ref
220
- .scan_heads()
221
- .await?
222
- .into_iter()
223
- .map(|head| head.version_id)
224
- .collect::<BTreeSet<_>>();
225
- version_ids.insert(GLOBAL_VERSION_ID.to_string());
226
- Ok(version_ids.into_iter().collect())
227
- }
228
-
229
- #[cfg(test)]
230
- mod tests {
231
- use async_trait::async_trait;
232
-
233
- use super::*;
234
- use crate::version::VersionHead;
235
-
236
- #[tokio::test]
237
- async fn active_scope_uses_session_version() {
238
- let version_ref = RowsVersionRefReader::new(Vec::new());
239
- let ids =
240
- resolve_provider_version_ids(&version_ref, &VersionBinding::active("main"), Vec::new())
241
- .await
242
- .expect("scope should resolve");
243
-
244
- assert_eq!(ids, vec!["main".to_string()]);
245
- }
246
-
247
- #[tokio::test]
248
- async fn explicit_scope_keeps_requested_versions() {
249
- let version_ref = RowsVersionRefReader::new(Vec::new());
250
- let ids = resolve_provider_version_ids(
251
- &version_ref,
252
- &VersionBinding::explicit(),
253
- vec!["version-a".to_string(), "global".to_string()],
254
- )
255
- .await
256
- .expect("scope should resolve");
257
-
258
- assert_eq!(ids, vec!["version-a".to_string(), "global".to_string()]);
259
- }
260
-
261
- #[tokio::test]
262
- async fn all_visible_scope_loads_version_refs_and_global() {
263
- let version_ref = RowsVersionRefReader::new(vec![
264
- VersionHead {
265
- version_id: "version-b".to_string(),
266
- commit_id: "commit-version-b".to_string(),
267
- },
268
- VersionHead {
269
- version_id: "version-a".to_string(),
270
- commit_id: "commit-version-a".to_string(),
271
- },
272
- ]);
273
- let ids =
274
- resolve_provider_version_ids(&version_ref, &VersionBinding::explicit(), Vec::new())
275
- .await
276
- .expect("scope should resolve");
277
-
278
- assert_eq!(
279
- ids,
280
- vec![
281
- "global".to_string(),
282
- "version-a".to_string(),
283
- "version-b".to_string(),
284
- ]
285
- );
286
- }
287
-
288
- #[test]
289
- fn write_scope_uses_fallback_version_when_version_is_implicit() {
290
- let scope = resolve_write_version_scope(
291
- None,
292
- None,
293
- Some("active-version"),
294
- "INSERT into surface",
295
- "surface",
296
- )
297
- .expect("scope should resolve");
298
-
299
- assert_eq!(
300
- scope,
301
- WriteVersionScope {
302
- version_id: "active-version".to_string(),
303
- global: false,
304
- }
305
- );
306
- }
307
-
308
- #[test]
309
- fn write_scope_requires_version_without_fallback() {
310
- let error = resolve_write_version_scope(None, None, None, "INSERT into surface", "surface")
311
- .expect_err("missing version should be rejected");
312
-
313
- assert!(error
314
- .to_string()
315
- .contains("INSERT into surface requires lixcol_version_id"));
316
- }
317
-
318
- #[test]
319
- fn write_scope_derives_global_from_global_version_id() {
320
- let scope = resolve_write_version_scope(
321
- None,
322
- Some(GLOBAL_VERSION_ID.to_string()),
323
- None,
324
- "INSERT into surface",
325
- "surface",
326
- )
327
- .expect("scope should resolve");
328
-
329
- assert_eq!(
330
- scope,
331
- WriteVersionScope {
332
- version_id: GLOBAL_VERSION_ID.to_string(),
333
- global: true,
334
- }
335
- );
336
- }
337
-
338
- #[test]
339
- fn write_scope_rejects_non_global_with_global_version_id() {
340
- let error = resolve_write_version_scope(
341
- Some(false),
342
- Some(GLOBAL_VERSION_ID.to_string()),
343
- None,
344
- "INSERT into surface",
345
- "surface",
346
- )
347
- .expect_err("conflicting global/version scope should be rejected");
348
-
349
- assert!(error
350
- .to_string()
351
- .contains("surface cannot set lixcol_global=false with global lixcol_version_id"));
352
- }
353
-
354
- #[test]
355
- fn write_scope_rejects_global_with_non_global_version_id() {
356
- let error = resolve_write_version_scope(
357
- Some(true),
358
- Some("version-a".to_string()),
359
- None,
360
- "INSERT into surface",
361
- "surface",
362
- )
363
- .expect_err("conflicting global/version scope should be rejected");
364
-
365
- assert!(error
366
- .to_string()
367
- .contains("surface cannot set lixcol_global=true with non-global lixcol_version_id"));
368
- }
369
-
370
- struct RowsVersionRefReader {
371
- heads: Vec<VersionHead>,
372
- }
373
-
374
- impl RowsVersionRefReader {
375
- fn new(heads: Vec<VersionHead>) -> Self {
376
- Self { heads }
377
- }
378
- }
379
-
380
- #[async_trait]
381
- impl VersionRefReader for RowsVersionRefReader {
382
- async fn load_head(&self, version_id: &str) -> Result<Option<VersionHead>, LixError> {
383
- Ok(self
384
- .heads
385
- .iter()
386
- .find(|head| head.version_id == version_id)
387
- .cloned())
388
- }
389
-
390
- async fn scan_heads(&self) -> Result<Vec<VersionHead>, LixError> {
391
- Ok(self.heads.clone())
392
- }
393
- }
394
- }