@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,12 +1,11 @@
1
1
  use crate::entity_identity::EntityIdentity;
2
- use crate::json_store::JsonRef;
3
- use crate::untracked_state::UntrackedStateRow;
2
+ use crate::untracked_state::{UntrackedStateRow, UntrackedStateRowRef};
4
3
  use crate::LixError;
5
4
 
6
5
  const UNTRACKED_STATE_FILE_IDENTIFIER: &str = "LXUS";
7
6
 
8
- pub(crate) fn encode_row(row: &UntrackedStateRow) -> Result<Vec<u8>, LixError> {
9
- let entity_id = row.entity_id.as_string().map_err(|error| {
7
+ pub(crate) fn encode_row_ref(row: UntrackedStateRowRef<'_>) -> Result<Vec<u8>, LixError> {
8
+ let entity_id = row.entity_id.as_json_array_text().map_err(|error| {
10
9
  LixError::unknown(format!(
11
10
  "failed to encode untracked-state entity identity: {error}"
12
11
  ))
@@ -14,23 +13,15 @@ pub(crate) fn encode_row(row: &UntrackedStateRow) -> Result<Vec<u8>, LixError> {
14
13
 
15
14
  let mut builder = flatbuffers::FlatBufferBuilder::with_capacity(256);
16
15
  let entity_id = builder.create_string(&entity_id);
17
- let schema_key = builder.create_string(&row.schema_key);
18
- let file_id = row
19
- .file_id
20
- .as_ref()
16
+ let schema_key = builder.create_string(row.schema_key);
17
+ let file_id = row.file_id.map(|value| builder.create_string(value));
18
+ let snapshot_content = row
19
+ .snapshot_content
21
20
  .map(|value| builder.create_string(value));
22
- let snapshot_ref = row
23
- .snapshot_ref
24
- .as_ref()
25
- .map(|value| builder.create_vector(value.as_hash_bytes()));
26
- let metadata_ref = row
27
- .metadata_ref
28
- .as_ref()
29
- .map(|value| builder.create_vector(value.as_hash_bytes()));
30
- let schema_version = builder.create_string(&row.schema_version);
31
- let created_at = builder.create_string(&row.created_at);
32
- let updated_at = builder.create_string(&row.updated_at);
33
- let version_id = builder.create_string(&row.version_id);
21
+ let metadata = row.metadata.map(|value| builder.create_string(value));
22
+ let created_at = builder.create_string(row.created_at);
23
+ let updated_at = builder.create_string(row.updated_at);
24
+ let version_id = builder.create_string(row.version_id);
34
25
 
35
26
  let root = flatbuffer::create_untracked_state_row(
36
27
  &mut builder,
@@ -38,9 +29,8 @@ pub(crate) fn encode_row(row: &UntrackedStateRow) -> Result<Vec<u8>, LixError> {
38
29
  entity_id,
39
30
  schema_key,
40
31
  file_id,
41
- snapshot_ref,
42
- metadata_ref,
43
- schema_version,
32
+ snapshot_content,
33
+ metadata,
44
34
  created_at,
45
35
  updated_at,
46
36
  global: row.global,
@@ -69,7 +59,7 @@ pub(crate) fn decode_row(bytes: &[u8]) -> Result<UntrackedStateRow, LixError> {
69
59
  })?;
70
60
 
71
61
  let entity_id = required_str(row.entity_id(), "entity_id")?;
72
- let entity_id = EntityIdentity::from_string(entity_id).map_err(|error| {
62
+ let entity_id = EntityIdentity::from_json_array_text(entity_id).map_err(|error| {
73
63
  LixError::unknown(format!(
74
64
  "failed to decode untracked-state entity identity: {error}"
75
65
  ))
@@ -79,9 +69,8 @@ pub(crate) fn decode_row(bytes: &[u8]) -> Result<UntrackedStateRow, LixError> {
79
69
  entity_id,
80
70
  schema_key: required_str(row.schema_key(), "schema_key")?.to_string(),
81
71
  file_id: row.file_id().map(ToString::to_string),
82
- snapshot_ref: optional_json_ref(row.snapshot_ref(), "snapshot_ref")?,
83
- metadata_ref: optional_json_ref(row.metadata_ref(), "metadata_ref")?,
84
- schema_version: required_str(row.schema_version(), "schema_version")?.to_string(),
72
+ snapshot_content: row.snapshot_content().map(ToString::to_string),
73
+ metadata: row.metadata().map(ToString::to_string),
85
74
  created_at: required_str(row.created_at(), "created_at")?.to_string(),
86
75
  updated_at: required_str(row.updated_at(), "updated_at")?.to_string(),
87
76
  global: row.global(),
@@ -98,25 +87,6 @@ fn required_str<'a>(value: Option<&'a str>, field: &str) -> Result<&'a str, LixE
98
87
  })
99
88
  }
100
89
 
101
- fn optional_json_ref(
102
- value: Option<flatbuffers::Vector<'_, u8>>,
103
- field: &str,
104
- ) -> Result<Option<JsonRef>, LixError> {
105
- let Some(value) = value else {
106
- return Ok(None);
107
- };
108
- let bytes = value.bytes();
109
- let hash = <[u8; 32]>::try_from(bytes).map_err(|_| {
110
- LixError::new(
111
- "LIX_ERROR_UNKNOWN",
112
- format!(
113
- "failed to decode untracked-state row: field `{field}` must be exactly 32 bytes"
114
- ),
115
- )
116
- })?;
117
- Ok(Some(JsonRef::from_hash_bytes(hash)))
118
- }
119
-
120
90
  mod flatbuffer {
121
91
  #[derive(Copy, Clone, PartialEq)]
122
92
  pub(super) struct UntrackedStateRow<'a> {
@@ -138,13 +108,12 @@ mod flatbuffer {
138
108
  const VT_ENTITY_ID: flatbuffers::VOffsetT = 4;
139
109
  const VT_SCHEMA_KEY: flatbuffers::VOffsetT = 6;
140
110
  const VT_FILE_ID: flatbuffers::VOffsetT = 8;
141
- const VT_SNAPSHOT_REF: flatbuffers::VOffsetT = 10;
142
- const VT_METADATA_REF: flatbuffers::VOffsetT = 12;
143
- const VT_SCHEMA_VERSION: flatbuffers::VOffsetT = 14;
144
- const VT_CREATED_AT: flatbuffers::VOffsetT = 16;
145
- const VT_UPDATED_AT: flatbuffers::VOffsetT = 18;
146
- const VT_GLOBAL: flatbuffers::VOffsetT = 20;
147
- const VT_VERSION_ID: flatbuffers::VOffsetT = 22;
111
+ const VT_SNAPSHOT_CONTENT: flatbuffers::VOffsetT = 10;
112
+ const VT_METADATA: flatbuffers::VOffsetT = 12;
113
+ const VT_CREATED_AT: flatbuffers::VOffsetT = 14;
114
+ const VT_UPDATED_AT: flatbuffers::VOffsetT = 16;
115
+ const VT_GLOBAL: flatbuffers::VOffsetT = 18;
116
+ const VT_VERSION_ID: flatbuffers::VOffsetT = 20;
148
117
 
149
118
  #[inline]
150
119
  pub(super) fn entity_id(&self) -> Option<&'a str> {
@@ -171,36 +140,21 @@ mod flatbuffer {
171
140
  }
172
141
 
173
142
  #[inline]
174
- pub(super) fn snapshot_ref(&self) -> Option<flatbuffers::Vector<'a, u8>> {
175
- unsafe {
176
- self.table
177
- .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(
178
- Self::VT_SNAPSHOT_REF,
179
- None,
180
- )
181
- }
182
- }
183
-
184
- #[inline]
185
- pub(super) fn metadata_ref(&self) -> Option<flatbuffers::Vector<'a, u8>> {
143
+ pub(super) fn snapshot_content(&self) -> Option<&'a str> {
186
144
  unsafe {
187
145
  self.table
188
- .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u8>>>(
189
- Self::VT_METADATA_REF,
190
- None,
191
- )
146
+ .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_SNAPSHOT_CONTENT, None)
192
147
  }
193
148
  }
194
149
 
195
150
  #[inline]
196
- pub(super) fn schema_version(&self) -> Option<&'a str> {
151
+ pub(super) fn metadata(&self) -> Option<&'a str> {
197
152
  unsafe {
198
153
  self.table
199
- .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_SCHEMA_VERSION, None)
154
+ .get::<flatbuffers::ForwardsUOffset<&str>>(Self::VT_METADATA, None)
200
155
  }
201
156
  }
202
157
 
203
- #[inline]
204
158
  pub(super) fn created_at(&self) -> Option<&'a str> {
205
159
  unsafe {
206
160
  self.table
@@ -253,20 +207,15 @@ mod flatbuffer {
253
207
  Self::VT_FILE_ID,
254
208
  false,
255
209
  )?
256
- .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(
257
- "snapshot_ref",
258
- Self::VT_SNAPSHOT_REF,
259
- false,
260
- )?
261
- .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(
262
- "metadata_ref",
263
- Self::VT_METADATA_REF,
210
+ .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
211
+ "snapshot_content",
212
+ Self::VT_SNAPSHOT_CONTENT,
264
213
  false,
265
214
  )?
266
215
  .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
267
- "schema_version",
268
- Self::VT_SCHEMA_VERSION,
269
- true,
216
+ "metadata",
217
+ Self::VT_METADATA,
218
+ false,
270
219
  )?
271
220
  .visit_field::<flatbuffers::ForwardsUOffset<&str>>(
272
221
  "created_at",
@@ -293,9 +242,8 @@ mod flatbuffer {
293
242
  pub(super) entity_id: flatbuffers::WIPOffset<&'a str>,
294
243
  pub(super) schema_key: flatbuffers::WIPOffset<&'a str>,
295
244
  pub(super) file_id: Option<flatbuffers::WIPOffset<&'a str>>,
296
- pub(super) snapshot_ref: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, u8>>>,
297
- pub(super) metadata_ref: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, u8>>>,
298
- pub(super) schema_version: flatbuffers::WIPOffset<&'a str>,
245
+ pub(super) snapshot_content: Option<flatbuffers::WIPOffset<&'a str>>,
246
+ pub(super) metadata: Option<flatbuffers::WIPOffset<&'a str>>,
299
247
  pub(super) created_at: flatbuffers::WIPOffset<&'a str>,
300
248
  pub(super) updated_at: flatbuffers::WIPOffset<&'a str>,
301
249
  pub(super) global: bool,
@@ -320,20 +268,16 @@ mod flatbuffer {
320
268
  UntrackedStateRow::VT_CREATED_AT,
321
269
  args.created_at,
322
270
  );
323
- builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
324
- UntrackedStateRow::VT_SCHEMA_VERSION,
325
- args.schema_version,
326
- );
327
- if let Some(metadata_ref) = args.metadata_ref {
271
+ if let Some(metadata) = args.metadata {
328
272
  builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
329
- UntrackedStateRow::VT_METADATA_REF,
330
- metadata_ref,
273
+ UntrackedStateRow::VT_METADATA,
274
+ metadata,
331
275
  );
332
276
  }
333
- if let Some(snapshot_ref) = args.snapshot_ref {
277
+ if let Some(snapshot_content) = args.snapshot_content {
334
278
  builder.push_slot_always::<flatbuffers::WIPOffset<_>>(
335
- UntrackedStateRow::VT_SNAPSHOT_REF,
336
- snapshot_ref,
279
+ UntrackedStateRow::VT_SNAPSHOT_CONTENT,
280
+ snapshot_content,
337
281
  );
338
282
  }
339
283
  if let Some(file_id) = args.file_id {
@@ -1,7 +1,7 @@
1
1
  use crate::storage::{StorageReader, StorageWriteSet};
2
2
  use crate::untracked_state::{
3
- MaterializedUntrackedStateRow, UntrackedStateIdentity, UntrackedStateRow,
4
- UntrackedStateRowRequest, UntrackedStateScanRequest,
3
+ MaterializedUntrackedStateRow, UntrackedStateIdentity, UntrackedStateIdentityRef,
4
+ UntrackedStateRowRef, UntrackedStateRowRequest, UntrackedStateScanRequest,
5
5
  };
6
6
  use crate::LixError;
7
7
 
@@ -59,6 +59,16 @@ where
59
59
  ) -> Result<Option<MaterializedUntrackedStateRow>, LixError> {
60
60
  crate::untracked_state::storage::load_row(&mut self.store, request).await
61
61
  }
62
+
63
+ pub(crate) async fn existing_identities<'a, I>(
64
+ &mut self,
65
+ identities: I,
66
+ ) -> Result<Vec<UntrackedStateIdentity>, LixError>
67
+ where
68
+ I: IntoIterator<Item = UntrackedStateIdentityRef<'a>>,
69
+ {
70
+ crate::untracked_state::storage::existing_identities(&mut self.store, identities).await
71
+ }
62
72
  }
63
73
 
64
74
  /// Untracked-state writer over a transaction-local storage write set.
@@ -69,14 +79,20 @@ pub(crate) struct UntrackedStateWriter<'a> {
69
79
  impl UntrackedStateWriter<'_> {
70
80
  /// Stages the latest untracked rows for their identities.
71
81
  ///
72
- /// A row with `snapshot_ref = None` is treated as removal because
82
+ /// A row with `snapshot_content = None` is treated as removal because
73
83
  /// untracked state keeps only the current local value, not tombstones.
74
- pub(crate) fn stage_rows(&mut self, rows: &[UntrackedStateRow]) -> Result<(), LixError> {
84
+ pub(crate) fn stage_rows<'a, I>(&mut self, rows: I) -> Result<(), LixError>
85
+ where
86
+ I: IntoIterator<Item = UntrackedStateRowRef<'a>>,
87
+ {
75
88
  crate::untracked_state::storage::stage_rows(self.writes, rows)
76
89
  }
77
90
 
78
91
  /// Removes untracked rows by exact identity.
79
- pub(crate) fn stage_delete_rows(&mut self, identities: &[UntrackedStateIdentity]) {
92
+ pub(crate) fn stage_delete_rows<'a, I>(&mut self, identities: I)
93
+ where
94
+ I: IntoIterator<Item = UntrackedStateIdentityRef<'a>>,
95
+ {
80
96
  crate::untracked_state::storage::stage_delete_rows(self.writes, identities)
81
97
  }
82
98
  }
@@ -1,44 +1,18 @@
1
- use crate::json_store::{JsonRef, JsonStoreReader, JsonStoreWriter};
2
- use crate::storage::{StorageReader, StorageWriteSet};
3
1
  use crate::untracked_state::{MaterializedUntrackedStateRow, UntrackedStateRow};
4
- use crate::{serialize_row_metadata, validate_row_metadata, LixError, RowMetadata};
2
+ use crate::{parse_row_metadata, LixError};
5
3
 
6
- pub(crate) fn canonicalize_materialized_row(
7
- writes: &mut StorageWriteSet,
8
- json_writer: &mut JsonStoreWriter,
9
- row: &MaterializedUntrackedStateRow,
10
- ) -> Result<UntrackedStateRow, LixError> {
11
- let snapshot_ref = stage_optional_json(writes, json_writer, row.snapshot_content.as_deref())?;
12
- let metadata_ref = stage_optional_metadata(writes, json_writer, row.metadata.as_ref())?;
13
- Ok(UntrackedStateRow {
14
- entity_id: row.entity_id.clone(),
15
- schema_key: row.schema_key.clone(),
16
- file_id: row.file_id.clone(),
17
- snapshot_ref,
18
- metadata_ref,
19
- schema_version: row.schema_version.clone(),
20
- created_at: row.created_at.clone(),
21
- updated_at: row.updated_at.clone(),
22
- global: row.global,
23
- version_id: row.version_id.clone(),
24
- })
25
- }
26
-
27
- pub(crate) async fn materialize_row<S>(
28
- json_reader: &mut JsonStoreReader<S>,
4
+ pub(crate) fn materialize_row(
29
5
  row: UntrackedStateRow,
30
6
  projection: &UntrackedMaterializationProjection,
31
- ) -> Result<MaterializedUntrackedStateRow, LixError>
32
- where
33
- S: StorageReader,
34
- {
7
+ ) -> Result<MaterializedUntrackedStateRow, LixError> {
8
+ let deleted = row.snapshot_content.is_none();
35
9
  let snapshot_content = if projection.snapshot_content {
36
- load_optional_json(json_reader, row.snapshot_ref.as_ref(), "snapshot_ref").await?
10
+ row.snapshot_content
37
11
  } else {
38
12
  None
39
13
  };
40
14
  let metadata = if projection.metadata {
41
- load_optional_metadata(json_reader, row.metadata_ref.as_ref()).await?
15
+ load_optional_metadata(row.metadata)?
42
16
  } else {
43
17
  None
44
18
  };
@@ -48,7 +22,7 @@ where
48
22
  file_id: row.file_id,
49
23
  snapshot_content,
50
24
  metadata,
51
- schema_version: row.schema_version,
25
+ deleted,
52
26
  created_at: row.created_at,
53
27
  updated_at: row.updated_at,
54
28
  global: row.global,
@@ -81,77 +55,9 @@ impl UntrackedMaterializationProjection {
81
55
  }
82
56
  }
83
57
 
84
- fn stage_optional_json(
85
- writes: &mut StorageWriteSet,
86
- json_writer: &mut JsonStoreWriter,
87
- value: Option<&str>,
88
- ) -> Result<Option<JsonRef>, LixError> {
89
- let Some(value) = value else {
58
+ fn load_optional_metadata(metadata: Option<String>) -> Result<Option<String>, LixError> {
59
+ let Some(json) = metadata else {
90
60
  return Ok(None);
91
61
  };
92
- json_writer.stage_bytes(writes, value.as_bytes()).map(Some)
93
- }
94
-
95
- fn stage_optional_metadata(
96
- writes: &mut StorageWriteSet,
97
- json_writer: &mut JsonStoreWriter,
98
- value: Option<&RowMetadata>,
99
- ) -> Result<Option<JsonRef>, LixError> {
100
- let Some(value) = value else {
101
- return Ok(None);
102
- };
103
- let serialized = serialize_row_metadata(value);
104
- json_writer
105
- .stage_bytes(writes, serialized.as_bytes())
106
- .map(Some)
107
- }
108
-
109
- async fn load_optional_metadata<S>(
110
- json_reader: &mut JsonStoreReader<S>,
111
- json_ref: Option<&JsonRef>,
112
- ) -> Result<Option<RowMetadata>, LixError>
113
- where
114
- S: StorageReader,
115
- {
116
- let Some(json) = load_optional_json(json_reader, json_ref, "metadata_ref").await? else {
117
- return Ok(None);
118
- };
119
- let metadata = serde_json::from_str::<RowMetadata>(&json).map_err(|error| {
120
- LixError::new(
121
- "LIX_ERROR_INVALID_JSON",
122
- format!("untracked_state metadata_ref is invalid JSON: {error}"),
123
- )
124
- })?;
125
- validate_row_metadata(metadata, "untracked_state metadata_ref").map(Some)
126
- }
127
-
128
- async fn load_optional_json<S>(
129
- json_reader: &mut JsonStoreReader<S>,
130
- json_ref: Option<&JsonRef>,
131
- field: &str,
132
- ) -> Result<Option<String>, LixError>
133
- where
134
- S: StorageReader,
135
- {
136
- let Some(json_ref) = json_ref else {
137
- return Ok(None);
138
- };
139
- let bytes = json_reader.load_bytes(json_ref).await?.ok_or_else(|| {
140
- LixError::new(
141
- "LIX_ERROR_UNKNOWN",
142
- format!(
143
- "untracked_state {field} '{}' is missing from json_store",
144
- json_ref.to_hex()
145
- ),
146
- )
147
- })?;
148
- String::from_utf8(bytes).map(Some).map_err(|error| {
149
- LixError::new(
150
- "LIX_ERROR_UNKNOWN",
151
- format!(
152
- "untracked_state {field} '{}' is not valid UTF-8 JSON bytes: {error}",
153
- json_ref.to_hex()
154
- ),
155
- )
156
- })
62
+ parse_row_metadata(&json, "untracked_state metadata").map(Some)
157
63
  }
@@ -6,12 +6,10 @@ mod types;
6
6
 
7
7
  #[allow(unused_imports)]
8
8
  pub(crate) use context::{UntrackedStateContext, UntrackedStateStoreReader, UntrackedStateWriter};
9
- pub(crate) use materialization::{
10
- canonicalize_materialized_row, materialize_row, UntrackedMaterializationProjection,
11
- };
9
+ pub(crate) use materialization::{materialize_row, UntrackedMaterializationProjection};
12
10
  #[allow(unused_imports)]
13
11
  pub(crate) use types::{
14
12
  MaterializedUntrackedStateRow, UntrackedStateFilter, UntrackedStateIdentity,
15
- UntrackedStateProjection, UntrackedStateRow, UntrackedStateRowRequest,
16
- UntrackedStateScanRequest,
13
+ UntrackedStateIdentityRef, UntrackedStateProjection, UntrackedStateRow, UntrackedStateRowRef,
14
+ UntrackedStateRowRequest, UntrackedStateScanRequest,
17
15
  };