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

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 (165) hide show
  1. package/SKILL.md +4 -5
  2. package/dist/engine-wasm/wasm/lix_engine.js +1 -1
  3. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  4. package/dist/generated/builtin-schemas.d.ts +87 -162
  5. package/dist/generated/builtin-schemas.js +139 -236
  6. package/dist/open-lix.d.ts +1 -1
  7. package/dist-engine-src/src/binary_cas/types.rs +0 -6
  8. package/dist-engine-src/src/catalog/context.rs +412 -0
  9. package/dist-engine-src/src/catalog/mod.rs +10 -0
  10. package/dist-engine-src/src/catalog/schema.rs +4 -0
  11. package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
  12. package/dist-engine-src/src/cel/mod.rs +1 -1
  13. package/dist-engine-src/src/cel/provider.rs +1 -1
  14. package/dist-engine-src/src/commit_graph/context.rs +328 -1015
  15. package/dist-engine-src/src/commit_graph/mod.rs +2 -3
  16. package/dist-engine-src/src/commit_graph/types.rs +7 -43
  17. package/dist-engine-src/src/commit_graph/walker.rs +57 -81
  18. package/dist-engine-src/src/commit_store/codec.rs +887 -0
  19. package/dist-engine-src/src/commit_store/context.rs +944 -0
  20. package/dist-engine-src/src/commit_store/materialization.rs +84 -0
  21. package/dist-engine-src/src/commit_store/mod.rs +16 -0
  22. package/dist-engine-src/src/commit_store/storage.rs +600 -0
  23. package/dist-engine-src/src/commit_store/types.rs +215 -0
  24. package/dist-engine-src/src/common/identity.rs +15 -5
  25. package/dist-engine-src/src/common/json_pointer.rs +67 -0
  26. package/dist-engine-src/src/common/metadata.rs +17 -12
  27. package/dist-engine-src/src/common/mod.rs +5 -5
  28. package/dist-engine-src/src/domain.rs +324 -0
  29. package/dist-engine-src/src/engine.rs +29 -43
  30. package/dist-engine-src/src/entity_identity.rs +238 -118
  31. package/dist-engine-src/src/functions/context.rs +17 -52
  32. package/dist-engine-src/src/functions/deterministic.rs +1 -1
  33. package/dist-engine-src/src/functions/mod.rs +1 -1
  34. package/dist-engine-src/src/functions/provider.rs +4 -4
  35. package/dist-engine-src/src/functions/state.rs +39 -66
  36. package/dist-engine-src/src/functions/types.rs +1 -1
  37. package/dist-engine-src/src/init.rs +204 -151
  38. package/dist-engine-src/src/json_store/context.rs +354 -60
  39. package/dist-engine-src/src/json_store/encoded.rs +6 -6
  40. package/dist-engine-src/src/json_store/mod.rs +4 -1
  41. package/dist-engine-src/src/json_store/store.rs +884 -11
  42. package/dist-engine-src/src/json_store/types.rs +166 -1
  43. package/dist-engine-src/src/lib.rs +10 -9
  44. package/dist-engine-src/src/live_state/context.rs +608 -830
  45. package/dist-engine-src/src/live_state/mod.rs +3 -3
  46. package/dist-engine-src/src/live_state/overlay.rs +7 -7
  47. package/dist-engine-src/src/live_state/reader.rs +5 -5
  48. package/dist-engine-src/src/live_state/types.rs +19 -36
  49. package/dist-engine-src/src/live_state/visibility.rs +19 -14
  50. package/dist-engine-src/src/plugin/archive.rs +3 -6
  51. package/dist-engine-src/src/plugin/install.rs +0 -18
  52. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
  53. package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
  54. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
  55. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
  56. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
  57. package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
  58. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
  59. package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
  60. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
  61. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
  62. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
  63. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
  64. package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
  65. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
  66. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
  67. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
  68. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
  69. package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
  70. package/dist-engine-src/src/schema/compatibility.rs +787 -0
  71. package/dist-engine-src/src/schema/definition.json +47 -17
  72. package/dist-engine-src/src/schema/definition.rs +202 -96
  73. package/dist-engine-src/src/schema/key.rs +9 -77
  74. package/dist-engine-src/src/schema/mod.rs +4 -4
  75. package/dist-engine-src/src/schema/tests.rs +133 -92
  76. package/dist-engine-src/src/session/context.rs +40 -42
  77. package/dist-engine-src/src/session/create_version.rs +22 -14
  78. package/dist-engine-src/src/session/execute.rs +45 -14
  79. package/dist-engine-src/src/session/merge/apply.rs +4 -4
  80. package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
  81. package/dist-engine-src/src/session/merge/stats.rs +1 -1
  82. package/dist-engine-src/src/session/merge/version.rs +35 -45
  83. package/dist-engine-src/src/session/mod.rs +4 -2
  84. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
  85. package/dist-engine-src/src/session/switch_version.rs +16 -28
  86. package/dist-engine-src/src/sql2/change_provider.rs +14 -20
  87. package/dist-engine-src/src/sql2/classify.rs +61 -26
  88. package/dist-engine-src/src/sql2/context.rs +22 -18
  89. package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
  90. package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
  91. package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
  92. package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
  93. package/dist-engine-src/src/sql2/error.rs +21 -1
  94. package/dist-engine-src/src/sql2/execute.rs +325 -264
  95. package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
  96. package/dist-engine-src/src/sql2/file_provider.rs +533 -108
  97. package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
  98. package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
  99. package/dist-engine-src/src/sql2/history_projection.rs +3 -27
  100. package/dist-engine-src/src/sql2/history_provider.rs +11 -17
  101. package/dist-engine-src/src/sql2/history_route.rs +22 -8
  102. package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
  103. package/dist-engine-src/src/sql2/mod.rs +6 -3
  104. package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
  105. package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
  106. package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
  107. package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
  108. package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
  109. package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
  110. package/dist-engine-src/src/sql2/read_only.rs +10 -12
  111. package/dist-engine-src/src/sql2/session.rs +7 -10
  112. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
  113. package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
  114. package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
  115. package/dist-engine-src/src/sql2/version_provider.rs +46 -31
  116. package/dist-engine-src/src/sql2/version_scope.rs +4 -4
  117. package/dist-engine-src/src/storage_bench.rs +1782 -325
  118. package/dist-engine-src/src/test_support.rs +183 -36
  119. package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
  120. package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
  121. package/dist-engine-src/src/tracked_state/context.rs +1155 -271
  122. package/dist-engine-src/src/tracked_state/diff.rs +249 -57
  123. package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
  124. package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
  125. package/dist-engine-src/src/tracked_state/merge.rs +37 -19
  126. package/dist-engine-src/src/tracked_state/mod.rs +8 -7
  127. package/dist-engine-src/src/tracked_state/storage.rs +138 -6
  128. package/dist-engine-src/src/tracked_state/tree.rs +695 -252
  129. package/dist-engine-src/src/tracked_state/types.rs +176 -6
  130. package/dist-engine-src/src/transaction/commit.rs +695 -435
  131. package/dist-engine-src/src/transaction/context.rs +551 -310
  132. package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
  133. package/dist-engine-src/src/transaction/mod.rs +2 -0
  134. package/dist-engine-src/src/transaction/normalization.rs +311 -447
  135. package/dist-engine-src/src/transaction/prep.rs +37 -0
  136. package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
  137. package/dist-engine-src/src/transaction/staging.rs +701 -406
  138. package/dist-engine-src/src/transaction/types.rs +231 -122
  139. package/dist-engine-src/src/transaction/validation.rs +2717 -1698
  140. package/dist-engine-src/src/untracked_state/codec.rs +40 -96
  141. package/dist-engine-src/src/untracked_state/context.rs +21 -5
  142. package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
  143. package/dist-engine-src/src/untracked_state/mod.rs +3 -5
  144. package/dist-engine-src/src/untracked_state/storage.rs +105 -57
  145. package/dist-engine-src/src/untracked_state/types.rs +63 -13
  146. package/dist-engine-src/src/version/context.rs +1 -13
  147. package/dist-engine-src/src/version/lifecycle.rs +221 -0
  148. package/dist-engine-src/src/version/mod.rs +3 -2
  149. package/dist-engine-src/src/version/refs.rs +12 -103
  150. package/dist-engine-src/src/version/stage_rows.rs +15 -19
  151. package/package.json +1 -1
  152. package/dist-engine-src/src/changelog/codec.rs +0 -321
  153. package/dist-engine-src/src/changelog/context.rs +0 -92
  154. package/dist-engine-src/src/changelog/materialization.rs +0 -121
  155. package/dist-engine-src/src/changelog/mod.rs +0 -13
  156. package/dist-engine-src/src/changelog/reader.rs +0 -20
  157. package/dist-engine-src/src/changelog/storage.rs +0 -220
  158. package/dist-engine-src/src/changelog/types.rs +0 -38
  159. package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
  160. package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
  161. package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
  162. package/dist-engine-src/src/schema_registry.rs +0 -294
  163. package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
  164. package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
  165. package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
@@ -1,45 +1,68 @@
1
- use crate::changelog::{
2
- canonicalize_materialized_change, ChangelogContext, MaterializedCanonicalChange,
3
- };
1
+ use crate::commit_store::{Change, CommitDraftRef, CommitStoreContext};
4
2
  use crate::entity_identity::EntityIdentity;
5
3
  use crate::functions::{
6
4
  FunctionProvider, FunctionProviderHandle, SharedFunctionProvider, SystemFunctionProvider,
7
5
  };
8
- use crate::json_store::JsonStoreContext;
9
- use crate::live_state::{LiveStateContext, LiveStateRow};
6
+ use crate::json_store::{JsonRef, JsonStoreContext, JsonWritePlacementRef, NormalizedJsonRef};
10
7
  use crate::schema::{
11
8
  registered_schema_entity_id, schema_key_from_definition, seed_schema_definitions,
12
9
  };
13
10
  use crate::storage::{StorageContext, StorageWriteSet};
14
- use crate::untracked_state::MaterializedUntrackedStateRow;
15
- use crate::version::{
16
- VERSION_DESCRIPTOR_SCHEMA_KEY, VERSION_DESCRIPTOR_SCHEMA_VERSION, VERSION_REF_SCHEMA_KEY,
17
- VERSION_REF_SCHEMA_VERSION,
18
- };
11
+ use crate::tracked_state::{TrackedStateContext, TrackedStateDeltaRef};
12
+ use crate::untracked_state::{UntrackedStateContext, UntrackedStateRow};
13
+ use crate::version::{VERSION_DESCRIPTOR_SCHEMA_KEY, VERSION_REF_SCHEMA_KEY};
19
14
  use crate::LixError;
20
15
  use crate::GLOBAL_VERSION_ID;
21
16
  use serde_json::json;
17
+ #[cfg(test)]
18
+ use std::sync::Arc;
22
19
 
23
20
  const KEY_VALUE_SCHEMA_KEY: &str = "lix_key_value";
24
- const KEY_VALUE_SCHEMA_VERSION: &str = "1";
25
21
  const LIX_ID_KEY: &str = "lix_id";
26
22
  const WORKSPACE_VERSION_KEY: &str = "lix_workspace_version_id";
27
- const COMMIT_SCHEMA_KEY: &str = "lix_commit";
28
- const COMMIT_SCHEMA_VERSION: &str = "1";
29
23
  const REGISTERED_SCHEMA_KEY: &str = "lix_registered_schema";
30
- const REGISTERED_SCHEMA_VERSION: &str = "1";
31
24
 
32
- /// Pure seed plan for initializing an engine2 repository.
25
+ /// Pure seed plan for initializing an engine repository.
33
26
  ///
34
- /// Tracked bootstrap facts go to the changelog. Moving refs such as
35
- /// `lix_version_ref` are seeded as untracked local state so repository heads can
36
- /// advance without becoming commit members.
27
+ /// Tracked bootstrap facts go to the commit store. Moving refs such as
28
+ /// `lix_version_ref` are seeded as untracked local state so repository heads
29
+ /// can advance without becoming commit members.
37
30
  pub(crate) struct InitSeedPlan {
38
- pub(crate) changes: Vec<MaterializedCanonicalChange>,
39
- pub(crate) untracked_rows: Vec<MaterializedUntrackedStateRow>,
31
+ commit: InitSeedCommit,
32
+ changes: Vec<InitSeedChange>,
33
+ untracked_rows: Vec<InitSeedLiveRow>,
40
34
  pub(crate) receipt: InitReceipt,
41
35
  }
42
36
 
37
+ #[derive(Debug, Clone, PartialEq, Eq)]
38
+ struct InitSeedCommit {
39
+ id: String,
40
+ change_id: String,
41
+ parent_ids: Vec<String>,
42
+ author_account_ids: Vec<String>,
43
+ created_at: String,
44
+ }
45
+
46
+ #[derive(Debug, Clone, PartialEq, Eq)]
47
+ struct InitSeedChange {
48
+ id: String,
49
+ entity_id: EntityIdentity,
50
+ schema_key: String,
51
+ snapshot_content: String,
52
+ created_at: String,
53
+ }
54
+
55
+ #[derive(Debug, Clone, PartialEq, Eq)]
56
+ struct InitSeedLiveRow {
57
+ entity_id: EntityIdentity,
58
+ schema_key: String,
59
+ snapshot_content: String,
60
+ created_at: String,
61
+ updated_at: String,
62
+ global: bool,
63
+ version_id: String,
64
+ }
65
+
43
66
  /// Values generated while planning the initial repository seed.
44
67
  #[derive(Debug, Clone, PartialEq, Eq)]
45
68
  pub struct InitReceipt {
@@ -49,15 +72,14 @@ pub struct InitReceipt {
49
72
  pub initial_commit_id: String,
50
73
  }
51
74
 
52
- /// Builds the canonical bootstrap changes for a new engine2 repository.
75
+ /// Builds the canonical bootstrap changes for a new engine repository.
53
76
  ///
54
77
  /// The initial commit tracks durable content rows. Version refs are moving
55
- /// pointers and therefore live in untracked local state instead of changelog.
78
+ /// pointers and therefore live in untracked local state instead of the commit.
56
79
  pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSeedPlan, LixError> {
57
80
  let main_version_id = functions.call_uuid_v7();
58
81
  let lix_id = functions.call_uuid_v7();
59
82
  let initial_commit_id = functions.call_uuid_v7();
60
- let initial_change_set_id = functions.call_uuid_v7();
61
83
  let timestamp = functions.call_timestamp();
62
84
 
63
85
  let mut registered_schema_changes = Vec::new();
@@ -65,9 +87,8 @@ pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSe
65
87
  let key = schema_key_from_definition(schema)?;
66
88
  registered_schema_changes.push(canonical_change(
67
89
  functions.call_uuid_v7(),
68
- registered_schema_entity_id(&key.schema_key, &key.schema_version)?,
90
+ registered_schema_entity_id(&key.schema_key)?,
69
91
  REGISTERED_SCHEMA_KEY,
70
- REGISTERED_SCHEMA_VERSION,
71
92
  registered_schema_snapshot(schema)?,
72
93
  &timestamp,
73
94
  ));
@@ -77,7 +98,6 @@ pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSe
77
98
  GLOBAL_VERSION_ID.to_string(),
78
99
  EntityIdentity::single(GLOBAL_VERSION_ID),
79
100
  VERSION_DESCRIPTOR_SCHEMA_KEY,
80
- VERSION_DESCRIPTOR_SCHEMA_VERSION,
81
101
  version_descriptor_snapshot(GLOBAL_VERSION_ID, "global", true)?,
82
102
  &timestamp,
83
103
  );
@@ -85,7 +105,6 @@ pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSe
85
105
  functions.call_uuid_v7(),
86
106
  EntityIdentity::single(&main_version_id),
87
107
  VERSION_DESCRIPTOR_SCHEMA_KEY,
88
- VERSION_DESCRIPTOR_SCHEMA_VERSION,
89
108
  version_descriptor_snapshot(&main_version_id, "main", false)?,
90
109
  &timestamp,
91
110
  );
@@ -93,63 +112,44 @@ pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSe
93
112
  functions.call_uuid_v7(),
94
113
  EntityIdentity::single(LIX_ID_KEY),
95
114
  KEY_VALUE_SCHEMA_KEY,
96
- KEY_VALUE_SCHEMA_VERSION,
97
115
  key_value_snapshot(LIX_ID_KEY, &lix_id)?,
98
116
  &timestamp,
99
117
  );
100
118
 
101
- let initial_commit_change_ids = registered_schema_changes
102
- .iter()
103
- .map(|change| change.id.clone())
104
- .chain([
105
- global_version_descriptor_change.id.clone(),
106
- main_version_descriptor_change.id.clone(),
107
- kv_lix_id_change.id.clone(),
108
- ])
109
- .collect::<Vec<_>>();
110
-
111
- let initial_commit_change = canonical_change(
112
- functions.call_uuid_v7(),
113
- EntityIdentity::single(&initial_commit_id),
114
- COMMIT_SCHEMA_KEY,
115
- COMMIT_SCHEMA_VERSION,
116
- commit_snapshot(
117
- &initial_commit_id,
118
- &initial_change_set_id,
119
- &initial_commit_change_ids,
120
- )?,
121
- &timestamp,
122
- );
119
+ let initial_commit = InitSeedCommit {
120
+ id: initial_commit_id.clone(),
121
+ change_id: functions.call_uuid_v7(),
122
+ parent_ids: Vec::new(),
123
+ author_account_ids: Vec::new(),
124
+ created_at: timestamp.clone(),
125
+ };
123
126
  let global_version_ref_row = untracked_row(
124
127
  EntityIdentity::single(GLOBAL_VERSION_ID),
125
128
  VERSION_REF_SCHEMA_KEY,
126
- VERSION_REF_SCHEMA_VERSION,
127
129
  version_ref_snapshot(GLOBAL_VERSION_ID, &initial_commit_id)?,
128
130
  &timestamp,
129
131
  );
130
132
  let main_version_ref_row = untracked_row(
131
133
  EntityIdentity::single(&main_version_id),
132
134
  VERSION_REF_SCHEMA_KEY,
133
- VERSION_REF_SCHEMA_VERSION,
134
135
  version_ref_snapshot(&main_version_id, &initial_commit_id)?,
135
136
  &timestamp,
136
137
  );
137
138
  let workspace_version_row = untracked_row(
138
139
  EntityIdentity::single(WORKSPACE_VERSION_KEY),
139
140
  KEY_VALUE_SCHEMA_KEY,
140
- KEY_VALUE_SCHEMA_VERSION,
141
141
  key_value_snapshot(WORKSPACE_VERSION_KEY, &main_version_id)?,
142
142
  &timestamp,
143
143
  );
144
144
 
145
145
  Ok(InitSeedPlan {
146
+ commit: initial_commit,
146
147
  changes: registered_schema_changes
147
148
  .into_iter()
148
149
  .chain([
149
150
  global_version_descriptor_change,
150
151
  main_version_descriptor_change,
151
152
  kv_lix_id_change,
152
- initial_commit_change,
153
153
  ])
154
154
  .collect(),
155
155
  untracked_rows: vec![
@@ -166,16 +166,17 @@ pub(crate) fn plan_init_seed(functions: FunctionProviderHandle) -> Result<InitSe
166
166
  })
167
167
  }
168
168
 
169
- /// Initializes an empty engine2 repository in one backend transaction.
169
+ /// Initializes an empty engine repository in one backend transaction.
170
170
  ///
171
171
  /// The pure seed planner decides which bootstrap facts exist. This function is
172
172
  /// only responsible for durably writing those facts to their owning stores:
173
- /// changelog for tracked changes, and live_state for the serving projection plus
174
- /// untracked moving refs.
173
+ /// commit_store for tracked changes, and live_state for the serving projection
174
+ /// plus untracked moving refs.
175
175
  pub(crate) async fn initialize(
176
176
  storage: StorageContext,
177
- changelog: &ChangelogContext,
178
- live_state: &LiveStateContext,
177
+ commit_store: &CommitStoreContext,
178
+ tracked_state: &TrackedStateContext,
179
+ untracked_state: &UntrackedStateContext,
179
180
  ) -> Result<InitReceipt, LixError> {
180
181
  let functions = SharedFunctionProvider::new(
181
182
  Box::new(SystemFunctionProvider) as Box<dyn FunctionProvider + Send>
@@ -185,29 +186,64 @@ pub(crate) async fn initialize(
185
186
 
186
187
  let mut transaction = storage.begin_write_transaction().await?;
187
188
  let mut writes = StorageWriteSet::new();
188
- let mut json_writer = JsonStoreContext::new().writer();
189
-
190
- {
191
- let canonical_changes = plan
192
- .changes
193
- .iter()
194
- .map(|change| canonicalize_materialized_change(&mut writes, &mut json_writer, change))
195
- .collect::<Result<Vec<_>, _>>()?;
196
- let mut writer = changelog.writer(&mut writes);
197
- writer.stage_changes(&canonical_changes)?;
198
- }
199
189
 
200
- let mut live_rows = plan
190
+ let authored_changes = plan
201
191
  .changes
202
192
  .iter()
203
- .map(|change| live_state_row_from_initial_change(change, &receipt.initial_commit_id))
204
- .collect::<Vec<_>>();
205
- live_rows.extend(plan.untracked_rows.into_iter().map(LiveStateRow::from));
193
+ .map(seed_change_to_commit_store_change)
194
+ .collect::<Result<Vec<_>, _>>()?;
195
+ JsonStoreContext::new().writer().stage_batch(
196
+ &mut writes,
197
+ JsonWritePlacementRef::CommitPack {
198
+ commit_id: &plan.commit.id,
199
+ pack_id: 0,
200
+ },
201
+ plan.changes
202
+ .iter()
203
+ .map(|change| NormalizedJsonRef::new(change.snapshot_content.as_str())),
204
+ )?;
205
+
206
+ let staged_commit = {
207
+ let commit = CommitDraftRef {
208
+ id: &plan.commit.id,
209
+ change_id: &plan.commit.change_id,
210
+ parent_ids: &plan.commit.parent_ids,
211
+ author_account_ids: &plan.commit.author_account_ids,
212
+ created_at: &plan.commit.created_at,
213
+ };
214
+ let mut writer = commit_store.writer(transaction.as_mut(), &mut writes);
215
+ writer
216
+ .stage_tracked_commit_draft(
217
+ commit,
218
+ authored_changes.iter().map(Change::as_ref).collect(),
219
+ Vec::new(),
220
+ )
221
+ .await?
222
+ };
223
+
224
+ let untracked_rows = plan
225
+ .untracked_rows
226
+ .iter()
227
+ .map(untracked_state_row_from_seed)
228
+ .collect::<Result<Vec<_>, _>>()?;
206
229
 
207
230
  {
208
- let mut writer = live_state.writer(transaction.as_mut());
231
+ untracked_state
232
+ .writer(&mut writes)
233
+ .stage_rows(untracked_rows.iter().map(|row| row.as_ref()))?;
234
+ let deltas = authored_changes
235
+ .iter()
236
+ .zip(&staged_commit.authored_locators)
237
+ .map(|(change, locator)| TrackedStateDeltaRef {
238
+ change: change.as_ref(),
239
+ locator: locator.as_ref(),
240
+ created_at: &change.created_at,
241
+ updated_at: &change.created_at,
242
+ })
243
+ .collect::<Vec<_>>();
244
+ let mut writer = tracked_state.writer(transaction.as_mut(), &mut writes);
209
245
  writer
210
- .stage_rows(&mut writes, &mut json_writer, &live_rows)
246
+ .stage_delta(&receipt.initial_commit_id, None, &deltas)
211
247
  .await?;
212
248
  }
213
249
 
@@ -216,41 +252,42 @@ pub(crate) async fn initialize(
216
252
  Ok(receipt)
217
253
  }
218
254
 
219
- fn live_state_row_from_initial_change(
220
- change: &MaterializedCanonicalChange,
221
- initial_commit_id: &str,
222
- ) -> LiveStateRow {
223
- LiveStateRow {
255
+ fn seed_change_to_commit_store_change(change: &InitSeedChange) -> Result<Change, LixError> {
256
+ Ok(Change {
257
+ id: change.id.clone(),
224
258
  entity_id: change.entity_id.clone(),
225
259
  schema_key: change.schema_key.clone(),
226
- file_id: change.file_id.clone(),
227
- snapshot_content: change.snapshot_content.clone(),
228
- metadata: change.metadata.clone(),
229
- schema_version: change.schema_version.clone(),
260
+ file_id: None,
261
+ snapshot_ref: Some(JsonRef::for_content(change.snapshot_content.as_bytes())),
262
+ metadata_ref: None,
230
263
  created_at: change.created_at.clone(),
231
- updated_at: change.created_at.clone(),
232
- global: true,
233
- change_id: Some(change.id.clone()),
234
- commit_id: Some(initial_commit_id.to_string()),
235
- untracked: false,
236
- version_id: GLOBAL_VERSION_ID.to_string(),
237
- }
264
+ })
265
+ }
266
+
267
+ fn untracked_state_row_from_seed(row: &InitSeedLiveRow) -> Result<UntrackedStateRow, LixError> {
268
+ Ok(UntrackedStateRow {
269
+ entity_id: row.entity_id.clone(),
270
+ schema_key: row.schema_key.clone(),
271
+ file_id: None,
272
+ snapshot_content: Some(row.snapshot_content.clone()),
273
+ metadata: None,
274
+ created_at: row.created_at.clone(),
275
+ updated_at: row.updated_at.clone(),
276
+ global: row.global,
277
+ version_id: row.version_id.clone(),
278
+ })
238
279
  }
239
280
 
240
281
  fn untracked_row(
241
282
  entity_id: EntityIdentity,
242
283
  schema_key: &str,
243
- schema_version: &str,
244
284
  snapshot_content: String,
245
285
  timestamp: &str,
246
- ) -> MaterializedUntrackedStateRow {
247
- MaterializedUntrackedStateRow {
286
+ ) -> InitSeedLiveRow {
287
+ InitSeedLiveRow {
248
288
  entity_id,
249
289
  schema_key: schema_key.to_string(),
250
- file_id: None,
251
- snapshot_content: Some(snapshot_content),
252
- metadata: None,
253
- schema_version: schema_version.to_string(),
290
+ snapshot_content,
254
291
  created_at: timestamp.to_string(),
255
292
  updated_at: timestamp.to_string(),
256
293
  global: true,
@@ -262,18 +299,14 @@ fn canonical_change(
262
299
  id: String,
263
300
  entity_id: EntityIdentity,
264
301
  schema_key: &str,
265
- schema_version: &str,
266
302
  snapshot_content: String,
267
303
  created_at: &str,
268
- ) -> MaterializedCanonicalChange {
269
- MaterializedCanonicalChange {
304
+ ) -> InitSeedChange {
305
+ InitSeedChange {
270
306
  id,
271
307
  entity_id,
272
308
  schema_key: schema_key.to_string(),
273
- schema_version: schema_version.to_string(),
274
- file_id: None,
275
- snapshot_content: Some(snapshot_content),
276
- metadata: None,
309
+ snapshot_content,
277
310
  created_at: created_at.to_string(),
278
311
  }
279
312
  }
@@ -299,19 +332,6 @@ fn registered_schema_snapshot(schema: &serde_json::Value) -> Result<String, LixE
299
332
  }))
300
333
  }
301
334
 
302
- fn commit_snapshot(
303
- id: &str,
304
- change_set_id: &str,
305
- change_ids: &[String],
306
- ) -> Result<String, LixError> {
307
- encode_snapshot(json!({
308
- "id": id,
309
- "change_set_id": change_set_id,
310
- "change_ids": change_ids,
311
- "parent_commit_ids": [],
312
- }))
313
- }
314
-
315
335
  fn version_ref_snapshot(id: &str, commit_id: &str) -> Result<String, LixError> {
316
336
  encode_snapshot(json!({
317
337
  "id": id,
@@ -323,7 +343,7 @@ fn encode_snapshot(value: serde_json::Value) -> Result<String, LixError> {
323
343
  serde_json::to_string(&value).map_err(|error| {
324
344
  LixError::new(
325
345
  "LIX_ERROR_UNKNOWN",
326
- format!("engine2 init seed snapshot serialization failed: {error}"),
346
+ format!("engine init seed snapshot serialization failed: {error}"),
327
347
  )
328
348
  })
329
349
  }
@@ -333,13 +353,17 @@ mod tests {
333
353
  use serde_json::Value as JsonValue;
334
354
 
335
355
  use super::*;
356
+ use crate::backend::{testing::UnitTestBackend, Backend};
336
357
  use crate::functions::{FunctionProvider, SharedFunctionProvider};
358
+ use crate::storage::StorageContext;
359
+ use crate::tracked_state::TrackedStateContext;
360
+ use crate::untracked_state::UntrackedStateContext;
337
361
 
338
362
  #[test]
339
363
  fn plan_init_seed_returns_tracked_changes_and_untracked_workspace_state() {
340
364
  let plan = plan_init_seed(test_functions()).expect("init seed should plan");
341
365
 
342
- assert_eq!(plan.changes.len(), seed_schema_definitions().len() + 4);
366
+ assert_eq!(plan.changes.len(), seed_schema_definitions().len() + 3);
343
367
  assert_eq!(plan.untracked_rows.len(), 3);
344
368
  assert_eq!(plan.receipt.global_version_id, GLOBAL_VERSION_ID);
345
369
  assert_eq!(plan.receipt.main_version_id, "test-uuid-1");
@@ -348,28 +372,23 @@ mod tests {
348
372
  }
349
373
 
350
374
  #[test]
351
- fn plan_init_seed_commit_tracks_schema_registrations_descriptor_and_lix_id_changes() {
375
+ fn plan_init_seed_commit_header_tracks_schema_registrations_descriptor_and_lix_id_changes() {
352
376
  let plan = plan_init_seed(test_functions()).expect("init seed should plan");
353
- let commit_change = plan
354
- .changes
355
- .iter()
356
- .find(|change| change.schema_key == COMMIT_SCHEMA_KEY)
357
- .expect("initial commit change should exist");
358
- let commit_snapshot = snapshot(commit_change);
359
377
 
360
- assert_eq!(
361
- commit_snapshot.get("id").and_then(JsonValue::as_str),
362
- Some(plan.receipt.initial_commit_id.as_str())
363
- );
364
- let change_ids = commit_snapshot
365
- .get("change_ids")
366
- .and_then(JsonValue::as_array)
367
- .expect("change_ids should be an array")
378
+ assert_eq!(plan.commit.id, plan.receipt.initial_commit_id);
379
+ assert_eq!(plan.commit.change_id, "test-uuid-21");
380
+ assert!(plan.commit.parent_ids.is_empty());
381
+ assert!(plan.commit.author_account_ids.is_empty());
382
+ assert_eq!(plan.commit.created_at, "test-timestamp-1");
383
+
384
+ let change_ids = plan
385
+ .changes
368
386
  .iter()
369
- .map(|value| value.as_str().expect("change id should be text"))
387
+ .map(|change| change.id.as_str())
370
388
  .collect::<Vec<_>>();
371
389
  assert_eq!(change_ids.len(), seed_schema_definitions().len() + 3);
372
390
  assert!(change_ids.contains(&"global"));
391
+ assert!(!change_ids.contains(&plan.commit.change_id.as_str()));
373
392
 
374
393
  let registered_schema_change_ids = plan
375
394
  .changes
@@ -460,23 +479,57 @@ mod tests {
460
479
  );
461
480
  }
462
481
 
463
- fn snapshot(change: &MaterializedCanonicalChange) -> JsonValue {
464
- serde_json::from_str(
465
- change
466
- .snapshot_content
467
- .as_deref()
468
- .expect("change should have snapshot"),
482
+ #[tokio::test]
483
+ async fn initialize_writes_initial_commit_through_commit_store() {
484
+ let backend: Arc<dyn Backend + Send + Sync> = Arc::new(UnitTestBackend::new());
485
+ let storage = StorageContext::new(backend);
486
+ let commit_store = CommitStoreContext::new();
487
+ let tracked_state = TrackedStateContext::new();
488
+ let untracked_state = UntrackedStateContext::new();
489
+
490
+ let receipt = initialize(
491
+ storage.clone(),
492
+ &commit_store,
493
+ &tracked_state,
494
+ &untracked_state,
469
495
  )
470
- .expect("snapshot should be JSON")
496
+ .await
497
+ .expect("engine should initialize");
498
+ let reader = commit_store.reader(storage.clone());
499
+ let commit = reader
500
+ .load_commit(&receipt.initial_commit_id)
501
+ .await
502
+ .expect("commit should load")
503
+ .expect("initial commit should exist");
504
+
505
+ assert_eq!(commit.id, receipt.initial_commit_id);
506
+ assert_eq!(commit.change_pack_count, 1);
507
+ assert_eq!(commit.membership_pack_count, 0);
508
+
509
+ let change_pack = reader
510
+ .load_change_pack(&commit.id, 0)
511
+ .await
512
+ .expect("change pack should load")
513
+ .expect("initial change pack should exist");
514
+ assert_eq!(change_pack.len(), seed_schema_definitions().len() + 3);
515
+ assert!(change_pack
516
+ .iter()
517
+ .all(|change| change.id != commit.change_id));
518
+
519
+ let entries = reader
520
+ .load_change_index_entries(&[commit.change_id.clone(), "global".to_string()])
521
+ .await
522
+ .expect("change index should load");
523
+ assert!(entries[0].is_some());
524
+ assert!(entries[1].is_some());
471
525
  }
472
526
 
473
- fn untracked_snapshot(row: &MaterializedUntrackedStateRow) -> JsonValue {
474
- serde_json::from_str(
475
- row.snapshot_content
476
- .as_deref()
477
- .expect("row should have snapshot"),
478
- )
479
- .expect("snapshot should be JSON")
527
+ fn snapshot(change: &InitSeedChange) -> JsonValue {
528
+ serde_json::from_str(&change.snapshot_content).expect("snapshot should be JSON")
529
+ }
530
+
531
+ fn untracked_snapshot(row: &InitSeedLiveRow) -> JsonValue {
532
+ serde_json::from_str(&row.snapshot_content).expect("snapshot should be JSON")
480
533
  }
481
534
 
482
535
  fn test_functions() -> FunctionProviderHandle {