@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
@@ -21,19 +21,19 @@ use futures_util::{stream, TryStreamExt};
21
21
  use tokio::sync::Mutex;
22
22
 
23
23
  use crate::commit_graph::CommitGraphReader;
24
- use crate::{serialize_row_metadata, LixError, RowMetadata};
24
+ use crate::{serialize_row_metadata, LixError};
25
25
 
26
26
  use super::history_route::{
27
27
  load_history_entries, parse_history_filter, HistoryColumnStyle, HistoryRoute,
28
28
  HistoryViewDescriptor,
29
29
  };
30
30
  use super::result_metadata::json_field;
31
- use super::SqlChangelogQuerySource;
31
+ use super::SqlCommitStoreQuerySource;
32
32
 
33
33
  pub(crate) async fn register_history_providers(
34
34
  session: &SessionContext,
35
35
  commit_graph: Box<dyn CommitGraphReader>,
36
- query_source: SqlChangelogQuerySource,
36
+ query_source: SqlCommitStoreQuerySource,
37
37
  ) -> Result<Arc<dyn TableProvider>, LixError> {
38
38
  let provider: Arc<dyn TableProvider> = Arc::new(LixStateHistoryProvider::new(
39
39
  Arc::new(Mutex::new(commit_graph)),
@@ -48,7 +48,7 @@ pub(crate) async fn register_history_providers(
48
48
  pub(crate) struct LixStateHistoryProvider {
49
49
  schema: SchemaRef,
50
50
  commit_graph: Arc<Mutex<Box<dyn CommitGraphReader>>>,
51
- query_source: SqlChangelogQuerySource,
51
+ query_source: SqlCommitStoreQuerySource,
52
52
  }
53
53
 
54
54
  impl std::fmt::Debug for LixStateHistoryProvider {
@@ -60,7 +60,7 @@ impl std::fmt::Debug for LixStateHistoryProvider {
60
60
  impl LixStateHistoryProvider {
61
61
  pub(crate) fn new(
62
62
  commit_graph: Arc<Mutex<Box<dyn CommitGraphReader>>>,
63
- query_source: SqlChangelogQuerySource,
63
+ query_source: SqlCommitStoreQuerySource,
64
64
  ) -> Self {
65
65
  Self {
66
66
  schema: lix_state_history_schema(),
@@ -121,7 +121,7 @@ impl TableProvider for LixStateHistoryProvider {
121
121
 
122
122
  struct LixStateHistoryScanExec {
123
123
  commit_graph: Arc<Mutex<Box<dyn CommitGraphReader>>>,
124
- query_source: SqlChangelogQuerySource,
124
+ query_source: SqlCommitStoreQuerySource,
125
125
  schema: SchemaRef,
126
126
  projection: Option<Vec<usize>>,
127
127
  route: HistoryRoute,
@@ -141,7 +141,7 @@ impl std::fmt::Debug for LixStateHistoryScanExec {
141
141
  impl LixStateHistoryScanExec {
142
142
  fn new(
143
143
  commit_graph: Arc<Mutex<Box<dyn CommitGraphReader>>>,
144
- query_source: SqlChangelogQuerySource,
144
+ query_source: SqlCommitStoreQuerySource,
145
145
  schema: SchemaRef,
146
146
  projection: Option<Vec<usize>>,
147
147
  route: HistoryRoute,
@@ -268,12 +268,11 @@ impl ExecutionPlan for LixStateHistoryScanExec {
268
268
 
269
269
  fn lix_state_history_schema() -> SchemaRef {
270
270
  Arc::new(Schema::new(vec![
271
- Field::new("entity_id", DataType::Utf8, false),
271
+ json_field("entity_id", false),
272
272
  Field::new("schema_key", DataType::Utf8, false),
273
273
  Field::new("file_id", DataType::Utf8, true),
274
274
  json_field("snapshot_content", true),
275
275
  json_field("metadata", true),
276
- Field::new("schema_version", DataType::Utf8, false),
277
276
  Field::new("change_id", DataType::Utf8, false),
278
277
  Field::new("observed_commit_id", DataType::Utf8, false),
279
278
  Field::new("commit_created_at", DataType::Utf8, false),
@@ -303,8 +302,7 @@ struct StateHistorySqlRow {
303
302
  schema_key: String,
304
303
  file_id: Option<String>,
305
304
  snapshot_content: Option<String>,
306
- metadata: Option<RowMetadata>,
307
- schema_version: String,
305
+ metadata: Option<String>,
308
306
  change_id: String,
309
307
  observed_commit_id: String,
310
308
  commit_created_at: String,
@@ -332,9 +330,6 @@ fn state_history_record_batch(
332
330
  .map(|row| row.metadata.as_ref().map(serialize_row_metadata))
333
331
  .collect::<Vec<_>>(),
334
332
  )),
335
- "schema_version" => {
336
- string_array(rows.iter().map(|row| Some(row.schema_version.as_str())))
337
- }
338
333
  "change_id" => string_array(rows.iter().map(|row| Some(row.change_id.as_str()))),
339
334
  "observed_commit_id" => {
340
335
  string_array(rows.iter().map(|row| Some(row.observed_commit_id.as_str())))
@@ -365,7 +360,7 @@ fn string_array<'a>(values: impl Iterator<Item = Option<&'a str>>) -> ArrayRef {
365
360
 
366
361
  async fn load_state_history_rows(
367
362
  commit_graph: Arc<Mutex<Box<dyn CommitGraphReader>>>,
368
- query_source: SqlChangelogQuerySource,
363
+ query_source: SqlCommitStoreQuerySource,
369
364
  route: &HistoryRoute,
370
365
  ) -> Result<Vec<StateHistorySqlRow>, LixError> {
371
366
  let entries = load_history_entries(
@@ -383,12 +378,11 @@ async fn load_state_history_rows(
383
378
  .into_iter()
384
379
  .map(|entry| -> Result<StateHistorySqlRow, LixError> {
385
380
  Ok(StateHistorySqlRow {
386
- entity_id: entry.change.entity_id.as_string()?,
381
+ entity_id: entry.change.entity_id.as_json_array_text()?,
387
382
  schema_key: entry.change.schema_key,
388
383
  file_id: entry.change.file_id,
389
384
  snapshot_content: entry.change.snapshot_content,
390
385
  metadata: entry.change.metadata,
391
- schema_version: entry.change.schema_version,
392
386
  change_id: entry.change.id,
393
387
  observed_commit_id: entry.observed_commit_id,
394
388
  commit_created_at: entry.commit_created_at,
@@ -6,12 +6,12 @@ use datafusion::logical_expr::expr::InList;
6
6
  use datafusion::logical_expr::{Expr, Operator};
7
7
  use tokio::sync::Mutex;
8
8
 
9
- use crate::changelog::{materialize_change, MaterializedCanonicalChange};
10
9
  use crate::commit_graph::{CommitGraphChangeHistoryRequest, CommitGraphReader};
11
10
  use crate::entity_identity::EntityIdentity;
12
11
  use crate::LixError;
13
12
 
14
13
  use super::SqlJsonReader;
14
+ use crate::commit_store::{materialize_change, MaterializedChange};
15
15
 
16
16
  /// Shared routing state for commit-shaped history SQL surfaces.
17
17
  ///
@@ -133,7 +133,7 @@ impl HistoryRoute {
133
133
  /// history surfaces.
134
134
  #[derive(Debug, Clone)]
135
135
  pub(crate) struct HistoryEntry {
136
- pub(crate) change: MaterializedCanonicalChange,
136
+ pub(crate) change: MaterializedChange,
137
137
  pub(crate) observed_commit_id: String,
138
138
  pub(crate) commit_created_at: String,
139
139
  pub(crate) start_commit_id: String,
@@ -145,7 +145,6 @@ pub(crate) const HISTORY_COL_SCHEMA_KEY: &str = "lixcol_schema_key";
145
145
  pub(crate) const HISTORY_COL_FILE_ID: &str = "lixcol_file_id";
146
146
  pub(crate) const HISTORY_COL_SNAPSHOT_CONTENT: &str = "lixcol_snapshot_content";
147
147
  pub(crate) const HISTORY_COL_METADATA: &str = "lixcol_metadata";
148
- pub(crate) const HISTORY_COL_SCHEMA_VERSION: &str = "lixcol_schema_version";
149
148
  pub(crate) const HISTORY_COL_CHANGE_ID: &str = "lixcol_change_id";
150
149
  pub(crate) const HISTORY_COL_OBSERVED_COMMIT_ID: &str = "lixcol_observed_commit_id";
151
150
  pub(crate) const HISTORY_COL_COMMIT_CREATED_AT: &str = "lixcol_commit_created_at";
@@ -191,7 +190,7 @@ pub(crate) fn commit_graph_history_request(
191
190
  entity_ids: route
192
191
  .entity_ids
193
192
  .iter()
194
- .map(|entity_id| EntityIdentity::single(entity_id))
193
+ .filter_map(|entity_id| EntityIdentity::from_json_array_text(entity_id).ok())
195
194
  .collect(),
196
195
  schema_keys,
197
196
  file_ids: route.file_ids.clone(),
@@ -253,7 +252,7 @@ pub(crate) async fn load_history_entries(
253
252
  .collect::<BTreeMap<_, _>>();
254
253
 
255
254
  for entry in entries {
256
- let change = materialize_change(&mut json_reader, entry.change).await?;
255
+ let change = materialize_change(&mut json_reader, entry.located_change).await?;
257
256
  rows.push(HistoryEntry {
258
257
  commit_created_at: commit_created_at_by_id
259
258
  .get(&entry.observed_commit_id)
@@ -411,17 +410,18 @@ fn parse_history_binary_filter(
411
410
  let right = &*binary_expr.right;
412
411
  match (column_name, &binary_expr.op, right) {
413
412
  ("start_commit_id", Operator::Eq, Expr::Literal(ScalarValue::Utf8(Some(value)), _))
414
- | ("entity_id", Operator::Eq, Expr::Literal(ScalarValue::Utf8(Some(value)), _))
415
413
  | ("schema_key", Operator::Eq, Expr::Literal(ScalarValue::Utf8(Some(value)), _))
416
414
  | ("file_id", Operator::Eq, Expr::Literal(ScalarValue::Utf8(Some(value)), _)) => {
417
415
  Some(match column_name {
418
416
  "start_commit_id" => HistoryFilterTerm::StartCommitIds(vec![value.clone()]),
419
- "entity_id" => HistoryFilterTerm::EntityIds(vec![value.clone()]),
420
417
  "schema_key" => HistoryFilterTerm::SchemaKeys(vec![value.clone()]),
421
418
  "file_id" => HistoryFilterTerm::FileIds(vec![value.clone()]),
422
419
  _ => unreachable!(),
423
420
  })
424
421
  }
422
+ ("entity_id", Operator::Eq, Expr::Literal(ScalarValue::Utf8(Some(value)), _)) => {
423
+ canonical_entity_id_value(value).map(|value| HistoryFilterTerm::EntityIds(vec![value]))
424
+ }
425
425
  ("depth", Operator::Eq, depth_expr) => {
426
426
  scalar_i64_literal(depth_expr).map(HistoryFilterTerm::ExactDepth)
427
427
  }
@@ -464,7 +464,7 @@ fn parse_history_in_list_filter(
464
464
 
465
465
  match column_name {
466
466
  "start_commit_id" => Some(HistoryFilterTerm::StartCommitIds(values)),
467
- "entity_id" => Some(HistoryFilterTerm::EntityIds(values)),
467
+ "entity_id" => canonical_entity_id_values(values).map(HistoryFilterTerm::EntityIds),
468
468
  "schema_key" => Some(HistoryFilterTerm::SchemaKeys(values)),
469
469
  "file_id" => Some(HistoryFilterTerm::FileIds(values)),
470
470
  _ => None,
@@ -518,6 +518,20 @@ fn apply_conjunctive_values_filter(bucket: &mut Vec<String>, incoming_values: Ve
518
518
  bucket.is_empty()
519
519
  }
520
520
 
521
+ fn canonical_entity_id_values(values: Vec<String>) -> Option<Vec<String>> {
522
+ values
523
+ .into_iter()
524
+ .map(|value| canonical_entity_id_value(&value))
525
+ .collect()
526
+ }
527
+
528
+ fn canonical_entity_id_value(value: &str) -> Option<String> {
529
+ EntityIdentity::from_json_array_text(value)
530
+ .ok()?
531
+ .as_json_array_text()
532
+ .ok()
533
+ }
534
+
521
535
  fn canonical_history_column_name(name: &str, column_style: HistoryColumnStyle) -> Option<&str> {
522
536
  match (column_style, name) {
523
537
  (HistoryColumnStyle::Bare, "start_commit_id")