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

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 (169) hide show
  1. package/SKILL.md +46 -8
  2. package/dist/engine-wasm/wasm/lix_engine.d.ts +25 -1
  3. package/dist/engine-wasm/wasm/lix_engine.js +60 -2
  4. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  5. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +5 -0
  6. package/dist/generated/builtin-schemas.d.ts +87 -162
  7. package/dist/generated/builtin-schemas.js +139 -236
  8. package/dist/open-lix.d.ts +10 -3
  9. package/dist/open-lix.js +39 -0
  10. package/dist-engine-src/src/binary_cas/types.rs +0 -6
  11. package/dist-engine-src/src/catalog/context.rs +412 -0
  12. package/dist-engine-src/src/catalog/mod.rs +10 -0
  13. package/dist-engine-src/src/catalog/schema.rs +4 -0
  14. package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
  15. package/dist-engine-src/src/cel/mod.rs +1 -1
  16. package/dist-engine-src/src/cel/provider.rs +1 -1
  17. package/dist-engine-src/src/commit_graph/context.rs +328 -1015
  18. package/dist-engine-src/src/commit_graph/mod.rs +2 -3
  19. package/dist-engine-src/src/commit_graph/types.rs +7 -43
  20. package/dist-engine-src/src/commit_graph/walker.rs +57 -81
  21. package/dist-engine-src/src/commit_store/codec.rs +887 -0
  22. package/dist-engine-src/src/commit_store/context.rs +944 -0
  23. package/dist-engine-src/src/commit_store/materialization.rs +84 -0
  24. package/dist-engine-src/src/commit_store/mod.rs +16 -0
  25. package/dist-engine-src/src/commit_store/storage.rs +600 -0
  26. package/dist-engine-src/src/commit_store/types.rs +215 -0
  27. package/dist-engine-src/src/common/identity.rs +15 -5
  28. package/dist-engine-src/src/common/json_pointer.rs +67 -0
  29. package/dist-engine-src/src/common/metadata.rs +17 -12
  30. package/dist-engine-src/src/common/mod.rs +5 -5
  31. package/dist-engine-src/src/domain.rs +324 -0
  32. package/dist-engine-src/src/engine.rs +29 -43
  33. package/dist-engine-src/src/entity_identity.rs +238 -118
  34. package/dist-engine-src/src/functions/context.rs +17 -52
  35. package/dist-engine-src/src/functions/deterministic.rs +1 -1
  36. package/dist-engine-src/src/functions/mod.rs +1 -1
  37. package/dist-engine-src/src/functions/provider.rs +4 -4
  38. package/dist-engine-src/src/functions/state.rs +39 -66
  39. package/dist-engine-src/src/functions/types.rs +1 -1
  40. package/dist-engine-src/src/init.rs +204 -151
  41. package/dist-engine-src/src/json_store/context.rs +354 -60
  42. package/dist-engine-src/src/json_store/encoded.rs +6 -6
  43. package/dist-engine-src/src/json_store/mod.rs +4 -1
  44. package/dist-engine-src/src/json_store/store.rs +884 -11
  45. package/dist-engine-src/src/json_store/types.rs +166 -1
  46. package/dist-engine-src/src/lib.rs +11 -10
  47. package/dist-engine-src/src/live_state/context.rs +608 -830
  48. package/dist-engine-src/src/live_state/mod.rs +3 -3
  49. package/dist-engine-src/src/live_state/overlay.rs +7 -7
  50. package/dist-engine-src/src/live_state/reader.rs +5 -5
  51. package/dist-engine-src/src/live_state/types.rs +19 -36
  52. package/dist-engine-src/src/live_state/visibility.rs +19 -14
  53. package/dist-engine-src/src/plugin/archive.rs +3 -6
  54. package/dist-engine-src/src/plugin/install.rs +0 -18
  55. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
  56. package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
  57. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
  58. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
  59. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
  60. package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
  61. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
  62. package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
  63. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
  64. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
  65. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
  66. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
  67. package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
  68. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
  69. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
  70. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
  71. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
  72. package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
  73. package/dist-engine-src/src/schema/compatibility.rs +787 -0
  74. package/dist-engine-src/src/schema/definition.json +47 -17
  75. package/dist-engine-src/src/schema/definition.rs +202 -96
  76. package/dist-engine-src/src/schema/key.rs +9 -77
  77. package/dist-engine-src/src/schema/mod.rs +4 -4
  78. package/dist-engine-src/src/schema/tests.rs +133 -92
  79. package/dist-engine-src/src/session/context.rs +86 -48
  80. package/dist-engine-src/src/session/create_version.rs +22 -14
  81. package/dist-engine-src/src/session/execute.rs +117 -23
  82. package/dist-engine-src/src/session/merge/apply.rs +4 -4
  83. package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
  84. package/dist-engine-src/src/session/merge/stats.rs +1 -1
  85. package/dist-engine-src/src/session/merge/version.rs +35 -45
  86. package/dist-engine-src/src/session/mod.rs +9 -7
  87. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
  88. package/dist-engine-src/src/session/switch_version.rs +17 -28
  89. package/dist-engine-src/src/session/transaction.rs +76 -0
  90. package/dist-engine-src/src/sql2/change_provider.rs +14 -20
  91. package/dist-engine-src/src/sql2/classify.rs +75 -48
  92. package/dist-engine-src/src/sql2/context.rs +22 -18
  93. package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
  94. package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
  95. package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
  96. package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
  97. package/dist-engine-src/src/sql2/error.rs +24 -5
  98. package/dist-engine-src/src/sql2/execute.rs +426 -272
  99. package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
  100. package/dist-engine-src/src/sql2/file_provider.rs +533 -108
  101. package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
  102. package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
  103. package/dist-engine-src/src/sql2/history_projection.rs +3 -27
  104. package/dist-engine-src/src/sql2/history_provider.rs +11 -17
  105. package/dist-engine-src/src/sql2/history_route.rs +22 -8
  106. package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
  107. package/dist-engine-src/src/sql2/mod.rs +8 -4
  108. package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
  109. package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
  110. package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
  111. package/dist-engine-src/src/sql2/public_bind/dml.rs +172 -0
  112. package/dist-engine-src/src/sql2/public_bind/mod.rs +26 -0
  113. package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
  114. package/dist-engine-src/src/sql2/read_only.rs +10 -12
  115. package/dist-engine-src/src/sql2/session.rs +7 -10
  116. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
  117. package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
  118. package/dist-engine-src/src/sql2/udfs/public_call.rs +238 -0
  119. package/dist-engine-src/src/sql2/version_provider.rs +46 -31
  120. package/dist-engine-src/src/sql2/version_scope.rs +4 -4
  121. package/dist-engine-src/src/storage_bench.rs +1782 -325
  122. package/dist-engine-src/src/test_support.rs +183 -36
  123. package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
  124. package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
  125. package/dist-engine-src/src/tracked_state/context.rs +1155 -271
  126. package/dist-engine-src/src/tracked_state/diff.rs +249 -57
  127. package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
  128. package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
  129. package/dist-engine-src/src/tracked_state/merge.rs +37 -19
  130. package/dist-engine-src/src/tracked_state/mod.rs +8 -7
  131. package/dist-engine-src/src/tracked_state/storage.rs +138 -6
  132. package/dist-engine-src/src/tracked_state/tree.rs +695 -252
  133. package/dist-engine-src/src/tracked_state/types.rs +176 -6
  134. package/dist-engine-src/src/transaction/commit.rs +695 -435
  135. package/dist-engine-src/src/transaction/context.rs +551 -310
  136. package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
  137. package/dist-engine-src/src/transaction/mod.rs +2 -0
  138. package/dist-engine-src/src/transaction/normalization.rs +311 -447
  139. package/dist-engine-src/src/transaction/prep.rs +37 -0
  140. package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
  141. package/dist-engine-src/src/transaction/staging.rs +701 -406
  142. package/dist-engine-src/src/transaction/types.rs +231 -122
  143. package/dist-engine-src/src/transaction/validation.rs +2717 -1698
  144. package/dist-engine-src/src/untracked_state/codec.rs +40 -96
  145. package/dist-engine-src/src/untracked_state/context.rs +21 -5
  146. package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
  147. package/dist-engine-src/src/untracked_state/mod.rs +3 -5
  148. package/dist-engine-src/src/untracked_state/storage.rs +105 -57
  149. package/dist-engine-src/src/untracked_state/types.rs +63 -13
  150. package/dist-engine-src/src/version/context.rs +1 -13
  151. package/dist-engine-src/src/version/lifecycle.rs +221 -0
  152. package/dist-engine-src/src/version/mod.rs +3 -2
  153. package/dist-engine-src/src/version/refs.rs +12 -103
  154. package/dist-engine-src/src/version/stage_rows.rs +15 -19
  155. package/package.json +1 -1
  156. package/dist-engine-src/src/changelog/codec.rs +0 -321
  157. package/dist-engine-src/src/changelog/context.rs +0 -92
  158. package/dist-engine-src/src/changelog/materialization.rs +0 -121
  159. package/dist-engine-src/src/changelog/mod.rs +0 -13
  160. package/dist-engine-src/src/changelog/reader.rs +0 -20
  161. package/dist-engine-src/src/changelog/storage.rs +0 -220
  162. package/dist-engine-src/src/changelog/types.rs +0 -38
  163. package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
  164. package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
  165. package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
  166. package/dist-engine-src/src/schema_registry.rs +0 -294
  167. package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
  168. package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
  169. package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
@@ -1,17 +1,15 @@
1
1
  use std::sync::Arc;
2
2
 
3
- use serde_json::json;
4
3
  use tokio::sync::Mutex;
5
4
 
6
5
  use crate::entity_identity::EntityIdentity;
7
- use crate::json_store::JsonStoreWriter;
8
6
  use crate::storage::{StorageReader, StorageWriteSet};
9
7
  use crate::untracked_state::{
10
- canonicalize_materialized_row, MaterializedUntrackedStateRow, UntrackedStateContext,
11
- UntrackedStateFilter, UntrackedStateRow, UntrackedStateRowRequest, UntrackedStateScanRequest,
8
+ MaterializedUntrackedStateRow, UntrackedStateContext, UntrackedStateFilter, UntrackedStateRow,
9
+ UntrackedStateRowRequest, UntrackedStateScanRequest,
12
10
  };
11
+ use crate::version::VERSION_REF_SCHEMA_KEY;
13
12
  use crate::version::{VersionHead, VersionRefReader};
14
- use crate::version::{VERSION_REF_SCHEMA_KEY, VERSION_REF_SCHEMA_VERSION};
15
13
  use crate::GLOBAL_VERSION_ID;
16
14
  use crate::{LixError, NullableKeyFilter};
17
15
 
@@ -109,7 +107,7 @@ where
109
107
  let mut heads = rows
110
108
  .iter()
111
109
  .map(|row| {
112
- let version_id = row.entity_id.as_string()?;
110
+ let version_id = row.entity_id.as_single_string_owned()?;
113
111
  decode_version_head(&version_id, row)
114
112
  })
115
113
  .collect::<Result<Vec<_>, _>>()?
@@ -147,21 +145,12 @@ pub(super) struct VersionRefWriter<'a> {
147
145
 
148
146
  impl VersionRefWriter<'_> {
149
147
  pub(crate) fn stage_rows(&mut self, rows: &[UntrackedStateRow]) -> Result<(), LixError> {
150
- self.untracked_state.writer(self.writes).stage_rows(rows)
148
+ self.untracked_state
149
+ .writer(self.writes)
150
+ .stage_rows(rows.iter().map(|row| row.as_ref()))
151
151
  }
152
152
  }
153
153
 
154
- pub(super) fn canonical_version_ref_row(
155
- writes: &mut StorageWriteSet,
156
- json_writer: &mut JsonStoreWriter,
157
- version_id: &str,
158
- commit_id: &str,
159
- timestamp: &str,
160
- ) -> Result<UntrackedStateRow, LixError> {
161
- let row = version_ref_row(version_id, commit_id, timestamp)?;
162
- canonicalize_materialized_row(writes, json_writer, &row)
163
- }
164
-
165
154
  fn decode_version_head(
166
155
  requested_version_id: &str,
167
156
  row: &MaterializedUntrackedStateRow,
@@ -173,7 +162,7 @@ fn decode_version_head(
173
162
  serde_json::from_str::<serde_json::Value>(snapshot_content).map_err(|error| {
174
163
  LixError::new(
175
164
  "LIX_ERROR_UNKNOWN",
176
- format!("engine2 version-ref snapshot parse failed: {error}"),
165
+ format!("engine version-ref snapshot parse failed: {error}"),
177
166
  )
178
167
  })?;
179
168
  let commit_id = snapshot
@@ -191,46 +180,14 @@ fn decode_version_head(
191
180
  }))
192
181
  }
193
182
 
194
- fn version_ref_row(
195
- version_id: &str,
196
- commit_id: &str,
197
- timestamp: &str,
198
- ) -> Result<MaterializedUntrackedStateRow, LixError> {
199
- let snapshot_content = serde_json::to_string(&json!({
200
- "id": version_id,
201
- "commit_id": commit_id,
202
- }))
203
- .map_err(|error| {
204
- LixError::new(
205
- "LIX_ERROR_UNKNOWN",
206
- format!("engine2 version-ref snapshot serialization failed: {error}"),
207
- )
208
- })?;
209
-
210
- Ok(MaterializedUntrackedStateRow {
211
- entity_id: crate::entity_identity::EntityIdentity::single(version_id),
212
- schema_key: VERSION_REF_SCHEMA_KEY.to_string(),
213
- file_id: None,
214
- snapshot_content: Some(snapshot_content),
215
- metadata: None,
216
- schema_version: VERSION_REF_SCHEMA_VERSION.to_string(),
217
- created_at: timestamp.to_string(),
218
- updated_at: timestamp.to_string(),
219
- global: true,
220
- version_id: GLOBAL_VERSION_ID.to_string(),
221
- })
222
- }
223
-
224
183
  #[cfg(test)]
225
184
  mod tests {
226
185
  use std::sync::Arc;
227
186
 
228
187
  use crate::backend::testing::UnitTestBackend;
229
- use crate::json_store::JsonStoreContext;
230
188
  use crate::storage::{StorageContext, StorageWriteSet};
231
- use crate::untracked_state::{
232
- canonicalize_materialized_row, UntrackedStateContext, UntrackedStateRowRequest,
233
- };
189
+ use crate::transaction::prepare_version_ref_row;
190
+ use crate::untracked_state::{UntrackedStateContext, UntrackedStateRowRequest};
234
191
 
235
192
  use super::*;
236
193
 
@@ -356,51 +313,6 @@ mod tests {
356
313
  );
357
314
  }
358
315
 
359
- #[tokio::test]
360
- async fn malformed_snapshot_errors_clearly() {
361
- let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
362
- let untracked_state = UntrackedStateContext::new();
363
- let version_ref = VersionRefContext::new(Arc::new(UntrackedStateContext::new()));
364
- let mut transaction = storage
365
- .begin_write_transaction()
366
- .await
367
- .expect("transaction should open");
368
- let mut row = version_ref_row("version-b", "commit-b", "2026-01-01T00:00:00Z")
369
- .expect("version-ref row should plan");
370
- row.snapshot_content = Some("{not-json".to_string());
371
- let mut writes = StorageWriteSet::new();
372
- let canonical_row = {
373
- let mut json_writer = JsonStoreContext::new().writer();
374
- canonicalize_materialized_row(&mut writes, &mut json_writer, &row)
375
- .expect("malformed row should canonicalize for test setup")
376
- };
377
- untracked_state
378
- .writer(&mut writes)
379
- .stage_rows(&[canonical_row])
380
- .expect("malformed row should write for test setup");
381
- writes
382
- .apply(&mut transaction.as_mut())
383
- .await
384
- .expect("malformed row should apply for test setup");
385
- transaction
386
- .commit()
387
- .await
388
- .expect("transaction should commit");
389
-
390
- let error = version_ref
391
- .reader(storage)
392
- .load_head("version-b")
393
- .await
394
- .expect_err("malformed snapshot should error");
395
-
396
- assert!(
397
- error
398
- .message
399
- .contains("engine2 version-ref snapshot parse failed"),
400
- "unexpected error: {error:?}"
401
- );
402
- }
403
-
404
316
  fn test_version_ref() -> VersionRefContext {
405
317
  VersionRefContext::new(Arc::new(UntrackedStateContext::new()))
406
318
  }
@@ -412,10 +324,7 @@ mod tests {
412
324
  commit_id: &str,
413
325
  timestamp: &str,
414
326
  ) -> Result<(), LixError> {
415
- let canonical_row = {
416
- let mut json_writer = JsonStoreContext::new().writer();
417
- canonical_version_ref_row(writes, &mut json_writer, version_id, commit_id, timestamp)?
418
- };
419
- version_ref.writer(writes).stage_rows(&[canonical_row])
327
+ let canonical_row = prepare_version_ref_row(version_id, commit_id, timestamp)?;
328
+ version_ref.writer(writes).stage_rows(&[canonical_row.row])
420
329
  }
421
330
  }
@@ -1,27 +1,28 @@
1
1
  use serde_json::json;
2
2
 
3
3
  use crate::entity_identity::EntityIdentity;
4
- use crate::transaction::types::StageRow;
4
+ use crate::transaction::types::{TransactionJson, TransactionWriteRow};
5
5
  use crate::GLOBAL_VERSION_ID;
6
6
 
7
7
  pub(crate) const VERSION_DESCRIPTOR_SCHEMA_KEY: &str = "lix_version_descriptor";
8
- pub(crate) const VERSION_DESCRIPTOR_SCHEMA_VERSION: &str = "1";
9
8
  pub(crate) const VERSION_REF_SCHEMA_KEY: &str = "lix_version_ref";
10
- pub(crate) const VERSION_REF_SCHEMA_VERSION: &str = "1";
11
9
 
12
- pub(crate) fn version_descriptor_stage_row(version_id: &str, name: &str, hidden: bool) -> StageRow {
13
- StageRow {
10
+ pub(crate) fn version_descriptor_stage_row(
11
+ version_id: &str,
12
+ name: &str,
13
+ hidden: bool,
14
+ ) -> TransactionWriteRow {
15
+ TransactionWriteRow {
14
16
  entity_id: Some(EntityIdentity::single(version_id)),
15
17
  schema_key: VERSION_DESCRIPTOR_SCHEMA_KEY.to_string(),
16
18
  file_id: None,
17
- snapshot_content: Some(encode_snapshot(json!({
19
+ snapshot: Some(TransactionJson::from_value_unchecked(json!({
18
20
  "id": version_id,
19
21
  "name": name,
20
22
  "hidden": hidden,
21
23
  }))),
22
24
  metadata: None,
23
25
  origin: None,
24
- schema_version: VERSION_DESCRIPTOR_SCHEMA_VERSION.to_string(),
25
26
  created_at: None,
26
27
  updated_at: None,
27
28
  global: true,
@@ -32,18 +33,17 @@ pub(crate) fn version_descriptor_stage_row(version_id: &str, name: &str, hidden:
32
33
  }
33
34
  }
34
35
 
35
- pub(crate) fn version_ref_stage_row(version_id: &str, commit_id: &str) -> StageRow {
36
- StageRow {
36
+ pub(crate) fn version_ref_stage_row(version_id: &str, commit_id: &str) -> TransactionWriteRow {
37
+ TransactionWriteRow {
37
38
  entity_id: Some(EntityIdentity::single(version_id)),
38
39
  schema_key: VERSION_REF_SCHEMA_KEY.to_string(),
39
40
  file_id: None,
40
- snapshot_content: Some(encode_snapshot(json!({
41
+ snapshot: Some(TransactionJson::from_value_unchecked(json!({
41
42
  "id": version_id,
42
43
  "commit_id": commit_id,
43
44
  }))),
44
45
  metadata: None,
45
46
  origin: None,
46
- schema_version: VERSION_REF_SCHEMA_VERSION.to_string(),
47
47
  created_at: None,
48
48
  updated_at: None,
49
49
  global: true,
@@ -54,18 +54,14 @@ pub(crate) fn version_ref_stage_row(version_id: &str, commit_id: &str) -> StageR
54
54
  }
55
55
  }
56
56
 
57
- pub(crate) fn version_descriptor_tombstone_row(version_id: &str) -> StageRow {
57
+ pub(crate) fn version_descriptor_tombstone_row(version_id: &str) -> TransactionWriteRow {
58
58
  let mut row = version_descriptor_stage_row(version_id, "", false);
59
- row.snapshot_content = None;
59
+ row.snapshot = None;
60
60
  row
61
61
  }
62
62
 
63
- pub(crate) fn version_ref_tombstone_row(version_id: &str) -> StageRow {
63
+ pub(crate) fn version_ref_tombstone_row(version_id: &str) -> TransactionWriteRow {
64
64
  let mut row = version_ref_stage_row(version_id, "");
65
- row.snapshot_content = None;
65
+ row.snapshot = None;
66
66
  row
67
67
  }
68
-
69
- fn encode_snapshot(value: serde_json::Value) -> String {
70
- serde_json::to_string(&value).expect("version snapshot should be serializable")
71
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lix-js/sdk",
3
3
  "type": "module",
4
- "version": "0.6.0-preview.2",
4
+ "version": "0.6.0-preview.4",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "files": [
@@ -1,321 +0,0 @@
1
- use crate::changelog::CanonicalChange;
2
- use crate::entity_identity::EntityIdentity;
3
- use crate::json_store::JsonRef;
4
- use crate::LixError;
5
-
6
- const CHANGELOG_FILE_IDENTIFIER: &str = "LXCH";
7
-
8
- pub(crate) fn encode_change(change: &CanonicalChange) -> Result<Vec<u8>, LixError> {
9
- let entity_id = change.entity_id.as_string().map_err(|error| {
10
- LixError::unknown(format!(
11
- "failed to encode changelog entity identity: {error}"
12
- ))
13
- })?;
14
-
15
- let mut builder = flatbuffers::FlatBufferBuilder::with_capacity(256);
16
- let id = builder.create_string(&change.id);
17
- let entity_id = builder.create_string(&entity_id);
18
- let schema_key = builder.create_string(&change.schema_key);
19
- let schema_version = builder.create_string(&change.schema_version);
20
- let file_id = change
21
- .file_id
22
- .as_ref()
23
- .map(|value| builder.create_string(value));
24
- let snapshot_ref = change
25
- .snapshot_ref
26
- .as_ref()
27
- .map(|value| builder.create_vector(value.as_hash_bytes()));
28
- let metadata_ref = change
29
- .metadata_ref
30
- .as_ref()
31
- .map(|value| builder.create_vector(value.as_hash_bytes()));
32
- let created_at = builder.create_string(&change.created_at);
33
-
34
- let root = flatbuffer::create_canonical_change(
35
- &mut builder,
36
- &flatbuffer::CanonicalChangeArgs {
37
- id,
38
- entity_id,
39
- schema_key,
40
- schema_version,
41
- file_id,
42
- snapshot_ref,
43
- metadata_ref,
44
- created_at,
45
- },
46
- );
47
- builder.finish(root, Some(CHANGELOG_FILE_IDENTIFIER));
48
- Ok(builder.finished_data().to_vec())
49
- }
50
-
51
- pub(crate) fn decode_change(bytes: &[u8]) -> Result<CanonicalChange, LixError> {
52
- if bytes.len() < flatbuffers::SIZE_UOFFSET + flatbuffers::FILE_IDENTIFIER_LENGTH
53
- || !flatbuffers::buffer_has_identifier(bytes, CHANGELOG_FILE_IDENTIFIER, false)
54
- {
55
- return Err(LixError::new(
56
- "LIX_ERROR_UNKNOWN",
57
- "failed to decode changelog change: invalid FlatBuffers file identifier",
58
- ));
59
- }
60
-
61
- let change = flatbuffer::root_as_canonical_change(bytes).map_err(|error| {
62
- LixError::new(
63
- "LIX_ERROR_UNKNOWN",
64
- format!("failed to decode changelog change: {error}"),
65
- )
66
- })?;
67
-
68
- let entity_id = required_str(change.entity_id(), "entity_id")?;
69
- let entity_id = EntityIdentity::from_string(entity_id).map_err(|error| {
70
- LixError::unknown(format!(
71
- "failed to decode changelog entity identity: {error}"
72
- ))
73
- })?;
74
-
75
- Ok(CanonicalChange {
76
- id: required_str(change.id(), "id")?.to_string(),
77
- entity_id,
78
- schema_key: required_str(change.schema_key(), "schema_key")?.to_string(),
79
- schema_version: required_str(change.schema_version(), "schema_version")?.to_string(),
80
- file_id: change.file_id().map(ToString::to_string),
81
- snapshot_ref: optional_json_ref(change.snapshot_ref(), "snapshot_ref")?,
82
- metadata_ref: optional_json_ref(change.metadata_ref(), "metadata_ref")?,
83
- created_at: required_str(change.created_at(), "created_at")?.to_string(),
84
- })
85
- }
86
-
87
- fn required_str<'a>(value: Option<&'a str>, field: &str) -> Result<&'a str, LixError> {
88
- value.ok_or_else(|| {
89
- LixError::new(
90
- "LIX_ERROR_UNKNOWN",
91
- format!("failed to decode changelog change: missing required field `{field}`"),
92
- )
93
- })
94
- }
95
-
96
- fn optional_json_ref(
97
- value: Option<flatbuffers::Vector<'_, u8>>,
98
- field: &str,
99
- ) -> Result<Option<JsonRef>, LixError> {
100
- let Some(value) = value else {
101
- return Ok(None);
102
- };
103
- let bytes = value.bytes();
104
- let hash = <[u8; 32]>::try_from(bytes).map_err(|_| {
105
- LixError::new(
106
- "LIX_ERROR_UNKNOWN",
107
- format!("failed to decode changelog change: field `{field}` must be exactly 32 bytes"),
108
- )
109
- })?;
110
- Ok(Some(JsonRef::from_hash_bytes(hash)))
111
- }
112
-
113
- mod flatbuffer {
114
- #[derive(Copy, Clone, PartialEq)]
115
- pub(super) struct CanonicalChange<'a> {
116
- table: flatbuffers::Table<'a>,
117
- }
118
-
119
- impl<'a> flatbuffers::Follow<'a> for CanonicalChange<'a> {
120
- type Inner = CanonicalChange<'a>;
121
-
122
- #[inline]
123
- unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
124
- Self {
125
- table: unsafe { flatbuffers::Table::new(buf, loc) },
126
- }
127
- }
128
- }
129
-
130
- impl<'a> CanonicalChange<'a> {
131
- const VT_ID: flatbuffers::VOffsetT = 4;
132
- const VT_ENTITY_ID: flatbuffers::VOffsetT = 6;
133
- const VT_SCHEMA_KEY: flatbuffers::VOffsetT = 8;
134
- const VT_SCHEMA_VERSION: flatbuffers::VOffsetT = 10;
135
- const VT_FILE_ID: flatbuffers::VOffsetT = 12;
136
- const VT_SNAPSHOT_REF: flatbuffers::VOffsetT = 14;
137
- const VT_METADATA_REF: flatbuffers::VOffsetT = 16;
138
- const VT_CREATED_AT: flatbuffers::VOffsetT = 18;
139
-
140
- #[inline]
141
- pub(super) fn id(&self) -> Option<&'a str> {
142
- unsafe {
143
- self.table
144
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_ID, None)
145
- }
146
- }
147
-
148
- #[inline]
149
- pub(super) fn entity_id(&self) -> Option<&'a str> {
150
- unsafe {
151
- self.table
152
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_ENTITY_ID, None)
153
- }
154
- }
155
-
156
- #[inline]
157
- pub(super) fn schema_key(&self) -> Option<&'a str> {
158
- unsafe {
159
- self.table
160
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_SCHEMA_KEY, None)
161
- }
162
- }
163
-
164
- #[inline]
165
- pub(super) fn schema_version(&self) -> Option<&'a str> {
166
- unsafe {
167
- self.table
168
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_SCHEMA_VERSION, None)
169
- }
170
- }
171
-
172
- #[inline]
173
- pub(super) fn file_id(&self) -> Option<&'a str> {
174
- unsafe {
175
- self.table
176
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_FILE_ID, None)
177
- }
178
- }
179
-
180
- #[inline]
181
- pub(super) fn snapshot_ref(&self) -> Option<flatbuffers::Vector<'a, u8>> {
182
- unsafe {
183
- self.table
184
- .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(
185
- Self::VT_SNAPSHOT_REF,
186
- None,
187
- )
188
- }
189
- }
190
-
191
- #[inline]
192
- pub(super) fn metadata_ref(&self) -> Option<flatbuffers::Vector<'a, u8>> {
193
- unsafe {
194
- self.table
195
- .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(
196
- Self::VT_METADATA_REF,
197
- None,
198
- )
199
- }
200
- }
201
-
202
- #[inline]
203
- pub(super) fn created_at(&self) -> Option<&'a str> {
204
- unsafe {
205
- self.table
206
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_CREATED_AT, None)
207
- }
208
- }
209
- }
210
-
211
- impl flatbuffers::Verifiable for CanonicalChange<'_> {
212
- #[inline]
213
- fn run_verifier(
214
- verifier: &mut flatbuffers::Verifier,
215
- position: usize,
216
- ) -> Result<(), flatbuffers::InvalidFlatbuffer> {
217
- verifier
218
- .visit_table(position)?
219
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>("id", Self::VT_ID, true)?
220
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
221
- "entity_id",
222
- Self::VT_ENTITY_ID,
223
- true,
224
- )?
225
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
226
- "schema_key",
227
- Self::VT_SCHEMA_KEY,
228
- true,
229
- )?
230
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
231
- "schema_version",
232
- Self::VT_SCHEMA_VERSION,
233
- true,
234
- )?
235
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
236
- "file_id",
237
- Self::VT_FILE_ID,
238
- false,
239
- )?
240
- .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(
241
- "snapshot_ref",
242
- Self::VT_SNAPSHOT_REF,
243
- false,
244
- )?
245
- .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(
246
- "metadata_ref",
247
- Self::VT_METADATA_REF,
248
- false,
249
- )?
250
- .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
251
- "created_at",
252
- Self::VT_CREATED_AT,
253
- true,
254
- )?
255
- .finish();
256
- Ok(())
257
- }
258
- }
259
-
260
- pub(super) struct CanonicalChangeArgs<'a> {
261
- pub(super) id: flatbuffers::WIPOffset<&'a str>,
262
- pub(super) entity_id: flatbuffers::WIPOffset<&'a str>,
263
- pub(super) schema_key: flatbuffers::WIPOffset<&'a str>,
264
- pub(super) schema_version: flatbuffers::WIPOffset<&'a str>,
265
- pub(super) file_id: Option<flatbuffers::WIPOffset<&'a str>>,
266
- pub(super) snapshot_ref: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, u8>>>,
267
- pub(super) metadata_ref: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, u8>>>,
268
- pub(super) created_at: flatbuffers::WIPOffset<&'a str>,
269
- }
270
-
271
- pub(super) fn create_canonical_change<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
272
- builder: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
273
- args: &'args CanonicalChangeArgs<'args>,
274
- ) -> flatbuffers::WIPOffset<CanonicalChange<'bldr>> {
275
- let start = builder.start_table();
276
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
277
- CanonicalChange::VT_CREATED_AT,
278
- args.created_at,
279
- );
280
- if let Some(metadata_ref) = args.metadata_ref {
281
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
282
- CanonicalChange::VT_METADATA_REF,
283
- metadata_ref,
284
- );
285
- }
286
- if let Some(snapshot_ref) = args.snapshot_ref {
287
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
288
- CanonicalChange::VT_SNAPSHOT_REF,
289
- snapshot_ref,
290
- );
291
- }
292
- if let Some(file_id) = args.file_id {
293
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
294
- CanonicalChange::VT_FILE_ID,
295
- file_id,
296
- );
297
- }
298
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
299
- CanonicalChange::VT_SCHEMA_VERSION,
300
- args.schema_version,
301
- );
302
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
303
- CanonicalChange::VT_SCHEMA_KEY,
304
- args.schema_key,
305
- );
306
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
307
- CanonicalChange::VT_ENTITY_ID,
308
- args.entity_id,
309
- );
310
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(CanonicalChange::VT_ID, args.id);
311
- let offset = builder.end_table(start);
312
- flatbuffers::WIPOffset::new(offset.value())
313
- }
314
-
315
- #[inline]
316
- pub(super) fn root_as_canonical_change(
317
- bytes: &[u8],
318
- ) -> Result<CanonicalChange<'_>, flatbuffers::InvalidFlatbuffer> {
319
- flatbuffers::root::<CanonicalChange>(bytes)
320
- }
321
- }
@@ -1,92 +0,0 @@
1
- use crate::changelog::{CanonicalChange, ChangelogReader, ChangelogScanRequest};
2
- use crate::storage::{StorageReader, StorageWriteSet};
3
- use crate::LixError;
4
- use tokio::sync::Mutex;
5
-
6
- /// Durable append-only ledger for Lix changes.
7
- ///
8
- /// This layer only records already-generated change facts. Transaction commit
9
- /// code is responsible for producing user changes plus normal `lix_commit`
10
- /// rows before appending them here.
11
- #[derive(Clone, Copy)]
12
- pub(crate) struct ChangelogContext;
13
-
14
- impl ChangelogContext {
15
- pub(crate) fn new() -> Self {
16
- Self
17
- }
18
-
19
- /// Creates a changelog reader over a caller-provided KV store.
20
- ///
21
- /// The caller decides which KV store supplies visibility for the read.
22
- pub(crate) fn reader<S>(&self, store: S) -> ChangelogStoreReader<S>
23
- where
24
- S: StorageReader,
25
- {
26
- ChangelogStoreReader {
27
- store: Mutex::new(store),
28
- }
29
- }
30
-
31
- /// Creates a changelog writer over a transaction-local storage write set.
32
- pub(crate) fn writer<'a>(&self, writes: &'a mut StorageWriteSet) -> ChangelogWriter<'a> {
33
- ChangelogWriter { writes }
34
- }
35
- }
36
-
37
- /// KV-backed changelog reader created by `ChangelogContext`.
38
- pub(crate) struct ChangelogStoreReader<S> {
39
- store: Mutex<S>,
40
- }
41
-
42
- impl<S> ChangelogStoreReader<S>
43
- where
44
- S: StorageReader,
45
- {
46
- #[allow(dead_code)]
47
- pub(crate) async fn load_change(
48
- &self,
49
- change_id: &str,
50
- ) -> Result<Option<CanonicalChange>, LixError> {
51
- let mut store = self.store.lock().await;
52
- crate::changelog::storage::load_change(&mut *store, change_id).await
53
- }
54
-
55
- #[allow(dead_code)]
56
- pub(crate) async fn scan_changes(
57
- &self,
58
- request: &ChangelogScanRequest,
59
- ) -> Result<Vec<CanonicalChange>, LixError> {
60
- let mut store = self.store.lock().await;
61
- crate::changelog::storage::scan_changes(&mut *store, request).await
62
- }
63
- }
64
-
65
- #[async_trait::async_trait]
66
- impl<S> ChangelogReader for ChangelogStoreReader<S>
67
- where
68
- S: StorageReader,
69
- {
70
- async fn load_change(&self, change_id: &str) -> Result<Option<CanonicalChange>, LixError> {
71
- ChangelogStoreReader::load_change(self, change_id).await
72
- }
73
-
74
- async fn scan_changes(
75
- &self,
76
- request: &ChangelogScanRequest,
77
- ) -> Result<Vec<CanonicalChange>, LixError> {
78
- ChangelogStoreReader::scan_changes(self, request).await
79
- }
80
- }
81
-
82
- /// Changelog writer over a transaction-local storage write set.
83
- pub(crate) struct ChangelogWriter<'a> {
84
- writes: &'a mut StorageWriteSet,
85
- }
86
-
87
- impl ChangelogWriter<'_> {
88
- #[allow(dead_code)]
89
- pub(crate) fn stage_changes(&mut self, changes: &[CanonicalChange]) -> Result<(), LixError> {
90
- crate::changelog::storage::stage_changes(self.writes, changes)
91
- }
92
- }