@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.
- package/SKILL.md +46 -8
- package/dist/engine-wasm/wasm/lix_engine.d.ts +25 -1
- package/dist/engine-wasm/wasm/lix_engine.js +60 -2
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +5 -0
- package/dist/generated/builtin-schemas.d.ts +87 -162
- package/dist/generated/builtin-schemas.js +139 -236
- package/dist/open-lix.d.ts +10 -3
- package/dist/open-lix.js +39 -0
- package/dist-engine-src/src/binary_cas/types.rs +0 -6
- package/dist-engine-src/src/catalog/context.rs +412 -0
- package/dist-engine-src/src/catalog/mod.rs +10 -0
- package/dist-engine-src/src/catalog/schema.rs +4 -0
- package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
- package/dist-engine-src/src/cel/mod.rs +1 -1
- package/dist-engine-src/src/cel/provider.rs +1 -1
- package/dist-engine-src/src/commit_graph/context.rs +328 -1015
- package/dist-engine-src/src/commit_graph/mod.rs +2 -3
- package/dist-engine-src/src/commit_graph/types.rs +7 -43
- package/dist-engine-src/src/commit_graph/walker.rs +57 -81
- package/dist-engine-src/src/commit_store/codec.rs +887 -0
- package/dist-engine-src/src/commit_store/context.rs +944 -0
- package/dist-engine-src/src/commit_store/materialization.rs +84 -0
- package/dist-engine-src/src/commit_store/mod.rs +16 -0
- package/dist-engine-src/src/commit_store/storage.rs +600 -0
- package/dist-engine-src/src/commit_store/types.rs +215 -0
- package/dist-engine-src/src/common/identity.rs +15 -5
- package/dist-engine-src/src/common/json_pointer.rs +67 -0
- package/dist-engine-src/src/common/metadata.rs +17 -12
- package/dist-engine-src/src/common/mod.rs +5 -5
- package/dist-engine-src/src/domain.rs +324 -0
- package/dist-engine-src/src/engine.rs +29 -43
- package/dist-engine-src/src/entity_identity.rs +238 -118
- package/dist-engine-src/src/functions/context.rs +17 -52
- package/dist-engine-src/src/functions/deterministic.rs +1 -1
- package/dist-engine-src/src/functions/mod.rs +1 -1
- package/dist-engine-src/src/functions/provider.rs +4 -4
- package/dist-engine-src/src/functions/state.rs +39 -66
- package/dist-engine-src/src/functions/types.rs +1 -1
- package/dist-engine-src/src/init.rs +204 -151
- package/dist-engine-src/src/json_store/context.rs +354 -60
- package/dist-engine-src/src/json_store/encoded.rs +6 -6
- package/dist-engine-src/src/json_store/mod.rs +4 -1
- package/dist-engine-src/src/json_store/store.rs +884 -11
- package/dist-engine-src/src/json_store/types.rs +166 -1
- package/dist-engine-src/src/lib.rs +11 -10
- package/dist-engine-src/src/live_state/context.rs +608 -830
- package/dist-engine-src/src/live_state/mod.rs +3 -3
- package/dist-engine-src/src/live_state/overlay.rs +7 -7
- package/dist-engine-src/src/live_state/reader.rs +5 -5
- package/dist-engine-src/src/live_state/types.rs +19 -36
- package/dist-engine-src/src/live_state/visibility.rs +19 -14
- package/dist-engine-src/src/plugin/archive.rs +3 -6
- package/dist-engine-src/src/plugin/install.rs +0 -18
- package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
- package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
- package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
- package/dist-engine-src/src/schema/compatibility.rs +787 -0
- package/dist-engine-src/src/schema/definition.json +47 -17
- package/dist-engine-src/src/schema/definition.rs +202 -96
- package/dist-engine-src/src/schema/key.rs +9 -77
- package/dist-engine-src/src/schema/mod.rs +4 -4
- package/dist-engine-src/src/schema/tests.rs +133 -92
- package/dist-engine-src/src/session/context.rs +86 -48
- package/dist-engine-src/src/session/create_version.rs +22 -14
- package/dist-engine-src/src/session/execute.rs +117 -23
- package/dist-engine-src/src/session/merge/apply.rs +4 -4
- package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
- package/dist-engine-src/src/session/merge/stats.rs +1 -1
- package/dist-engine-src/src/session/merge/version.rs +35 -45
- package/dist-engine-src/src/session/mod.rs +9 -7
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
- package/dist-engine-src/src/session/switch_version.rs +17 -28
- package/dist-engine-src/src/session/transaction.rs +76 -0
- package/dist-engine-src/src/sql2/change_provider.rs +14 -20
- package/dist-engine-src/src/sql2/classify.rs +75 -48
- package/dist-engine-src/src/sql2/context.rs +22 -18
- package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
- package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
- package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
- package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
- package/dist-engine-src/src/sql2/error.rs +24 -5
- package/dist-engine-src/src/sql2/execute.rs +426 -272
- package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
- package/dist-engine-src/src/sql2/file_provider.rs +533 -108
- package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
- package/dist-engine-src/src/sql2/history_projection.rs +3 -27
- package/dist-engine-src/src/sql2/history_provider.rs +11 -17
- package/dist-engine-src/src/sql2/history_route.rs +22 -8
- package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
- package/dist-engine-src/src/sql2/mod.rs +8 -4
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
- package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
- package/dist-engine-src/src/sql2/public_bind/dml.rs +172 -0
- package/dist-engine-src/src/sql2/public_bind/mod.rs +26 -0
- package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
- package/dist-engine-src/src/sql2/read_only.rs +10 -12
- package/dist-engine-src/src/sql2/session.rs +7 -10
- package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
- package/dist-engine-src/src/sql2/udfs/public_call.rs +238 -0
- package/dist-engine-src/src/sql2/version_provider.rs +46 -31
- package/dist-engine-src/src/sql2/version_scope.rs +4 -4
- package/dist-engine-src/src/storage_bench.rs +1782 -325
- package/dist-engine-src/src/test_support.rs +183 -36
- package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
- package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
- package/dist-engine-src/src/tracked_state/context.rs +1155 -271
- package/dist-engine-src/src/tracked_state/diff.rs +249 -57
- package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
- package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
- package/dist-engine-src/src/tracked_state/merge.rs +37 -19
- package/dist-engine-src/src/tracked_state/mod.rs +8 -7
- package/dist-engine-src/src/tracked_state/storage.rs +138 -6
- package/dist-engine-src/src/tracked_state/tree.rs +695 -252
- package/dist-engine-src/src/tracked_state/types.rs +176 -6
- package/dist-engine-src/src/transaction/commit.rs +695 -435
- package/dist-engine-src/src/transaction/context.rs +551 -310
- package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
- package/dist-engine-src/src/transaction/mod.rs +2 -0
- package/dist-engine-src/src/transaction/normalization.rs +311 -447
- package/dist-engine-src/src/transaction/prep.rs +37 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
- package/dist-engine-src/src/transaction/staging.rs +701 -406
- package/dist-engine-src/src/transaction/types.rs +231 -122
- package/dist-engine-src/src/transaction/validation.rs +2717 -1698
- package/dist-engine-src/src/untracked_state/codec.rs +40 -96
- package/dist-engine-src/src/untracked_state/context.rs +21 -5
- package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
- package/dist-engine-src/src/untracked_state/mod.rs +3 -5
- package/dist-engine-src/src/untracked_state/storage.rs +105 -57
- package/dist-engine-src/src/untracked_state/types.rs +63 -13
- package/dist-engine-src/src/version/context.rs +1 -13
- package/dist-engine-src/src/version/lifecycle.rs +221 -0
- package/dist-engine-src/src/version/mod.rs +3 -2
- package/dist-engine-src/src/version/refs.rs +12 -103
- package/dist-engine-src/src/version/stage_rows.rs +15 -19
- package/package.json +1 -1
- package/dist-engine-src/src/changelog/codec.rs +0 -321
- package/dist-engine-src/src/changelog/context.rs +0 -92
- package/dist-engine-src/src/changelog/materialization.rs +0 -121
- package/dist-engine-src/src/changelog/mod.rs +0 -13
- package/dist-engine-src/src/changelog/reader.rs +0 -20
- package/dist-engine-src/src/changelog/storage.rs +0 -220
- package/dist-engine-src/src/changelog/types.rs +0 -38
- package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
- package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
- package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
- package/dist-engine-src/src/schema_registry.rs +0 -294
- package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
- package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
- package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
|
@@ -6,20 +6,14 @@ use crate::LixError;
|
|
|
6
6
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
7
7
|
pub struct SchemaKey {
|
|
8
8
|
pub schema_key: String,
|
|
9
|
-
pub schema_version: String,
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
impl SchemaKey {
|
|
13
|
-
pub fn new(schema_key: impl Into<String
|
|
12
|
+
pub fn new(schema_key: impl Into<String>) -> Self {
|
|
14
13
|
Self {
|
|
15
14
|
schema_key: schema_key.into(),
|
|
16
|
-
schema_version: schema_version.into(),
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
pub fn version_number(&self) -> Option<u64> {
|
|
21
|
-
self.schema_version.parse::<u64>().ok()
|
|
22
|
-
}
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
pub fn schema_key_from_definition(schema: &JsonValue) -> Result<SchemaKey, LixError> {
|
|
@@ -38,20 +32,8 @@ pub fn schema_key_from_definition(schema: &JsonValue) -> Result<SchemaKey, LixEr
|
|
|
38
32
|
hint: None,
|
|
39
33
|
details: None,
|
|
40
34
|
})?;
|
|
41
|
-
let schema_version = object
|
|
42
|
-
.get("x-lix-version")
|
|
43
|
-
.and_then(JsonValue::as_str)
|
|
44
|
-
.ok_or_else(|| LixError {
|
|
45
|
-
code: "LIX_ERROR_UNKNOWN".to_string(),
|
|
46
|
-
message: "schema definition must include string x-lix-version".to_string(),
|
|
47
|
-
hint: None,
|
|
48
|
-
details: None,
|
|
49
|
-
})?;
|
|
50
35
|
|
|
51
|
-
Ok(SchemaKey::new(
|
|
52
|
-
schema_key.to_string(),
|
|
53
|
-
schema_version.to_string(),
|
|
54
|
-
))
|
|
36
|
+
Ok(SchemaKey::new(schema_key.to_string()))
|
|
55
37
|
}
|
|
56
38
|
|
|
57
39
|
pub fn schema_from_registered_snapshot(
|
|
@@ -79,59 +61,26 @@ pub fn schema_from_registered_snapshot(
|
|
|
79
61
|
hint: None,
|
|
80
62
|
details: None,
|
|
81
63
|
})?;
|
|
82
|
-
let schema_version = value
|
|
83
|
-
.get("x-lix-version")
|
|
84
|
-
.and_then(|value| value.as_str())
|
|
85
|
-
.ok_or_else(|| LixError {
|
|
86
|
-
code: "LIX_ERROR_UNKNOWN".to_string(),
|
|
87
|
-
message: "registered schema value.x-lix-version must be string".to_string(),
|
|
88
|
-
hint: None,
|
|
89
|
-
details: None,
|
|
90
|
-
})?;
|
|
91
64
|
|
|
92
65
|
Ok((
|
|
93
|
-
SchemaKey::new(schema_key.to_string()
|
|
66
|
+
SchemaKey::new(schema_key.to_string()),
|
|
94
67
|
JsonValue::Object(value.clone()),
|
|
95
68
|
))
|
|
96
69
|
}
|
|
97
70
|
|
|
98
|
-
pub(crate) fn
|
|
99
|
-
key: &SchemaKey,
|
|
100
|
-
) -> Result<(), LixError> {
|
|
101
|
-
if key.schema_version != "1" {
|
|
102
|
-
return Err(LixError::new(
|
|
103
|
-
LixError::CODE_SCHEMA_DEFINITION,
|
|
104
|
-
format!(
|
|
105
|
-
"schema '{}' uses x-lix-version '{}', but schema evolution is not supported yet; register schemas with x-lix-version '1'",
|
|
106
|
-
key.schema_key, key.schema_version
|
|
107
|
-
),
|
|
108
|
-
));
|
|
109
|
-
}
|
|
110
|
-
Ok(())
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
pub(crate) fn registered_schema_entity_id(
|
|
114
|
-
schema_key: &str,
|
|
115
|
-
schema_version: &str,
|
|
116
|
-
) -> Result<EntityIdentity, LixError> {
|
|
71
|
+
pub(crate) fn registered_schema_entity_id(schema_key: &str) -> Result<EntityIdentity, LixError> {
|
|
117
72
|
EntityIdentity::from_primary_key_paths(
|
|
118
73
|
&serde_json::json!({
|
|
119
74
|
"value": {
|
|
120
75
|
"x-lix-key": schema_key,
|
|
121
|
-
"x-lix-version": schema_version,
|
|
122
76
|
}
|
|
123
77
|
}),
|
|
124
|
-
&[
|
|
125
|
-
vec!["value".to_string(), "x-lix-key".to_string()],
|
|
126
|
-
vec!["value".to_string(), "x-lix-version".to_string()],
|
|
127
|
-
],
|
|
78
|
+
&[vec!["value".to_string(), "x-lix-key".to_string()]],
|
|
128
79
|
)
|
|
129
80
|
.map_err(|error| {
|
|
130
81
|
LixError::new(
|
|
131
82
|
LixError::CODE_SCHEMA_DEFINITION,
|
|
132
|
-
format!(
|
|
133
|
-
"registered schema identity could not be derived for schema '{schema_key}' version '{schema_version}': {error}"
|
|
134
|
-
),
|
|
83
|
+
format!("registered schema identity could not be derived for schema '{schema_key}': {error}"),
|
|
135
84
|
)
|
|
136
85
|
})
|
|
137
86
|
}
|
|
@@ -142,32 +91,17 @@ mod tests {
|
|
|
142
91
|
|
|
143
92
|
use super::{schema_from_registered_snapshot, schema_key_from_definition, SchemaKey};
|
|
144
93
|
|
|
145
|
-
#[test]
|
|
146
|
-
fn schema_key_entity_id_and_numeric_version() {
|
|
147
|
-
let key = SchemaKey::new("users", "42");
|
|
148
|
-
|
|
149
|
-
assert_eq!(key.version_number(), Some(42));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
#[test]
|
|
153
|
-
fn schema_key_non_numeric_version_returns_none() {
|
|
154
|
-
let key = SchemaKey::new("users", "v2");
|
|
155
|
-
|
|
156
|
-
assert_eq!(key.version_number(), None);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
94
|
#[test]
|
|
160
95
|
fn schema_from_registered_snapshot_extracts_key_and_schema() {
|
|
161
96
|
let snapshot = json!({
|
|
162
97
|
"value": {
|
|
163
98
|
"x-lix-key": "profile",
|
|
164
|
-
"x-lix-version": "1",
|
|
165
99
|
"type": "object"
|
|
166
100
|
}
|
|
167
101
|
});
|
|
168
102
|
|
|
169
103
|
let (key, schema) = schema_from_registered_snapshot(&snapshot).expect("schema is valid");
|
|
170
|
-
assert_eq!(key, SchemaKey::new("profile"
|
|
104
|
+
assert_eq!(key, SchemaKey::new("profile"));
|
|
171
105
|
assert_eq!(schema["type"], json!("object"));
|
|
172
106
|
}
|
|
173
107
|
|
|
@@ -184,7 +118,6 @@ mod tests {
|
|
|
184
118
|
let snapshot = json!({
|
|
185
119
|
"value": {
|
|
186
120
|
"x-lix-key": 1,
|
|
187
|
-
"x-lix-version": "1"
|
|
188
121
|
}
|
|
189
122
|
});
|
|
190
123
|
|
|
@@ -193,14 +126,13 @@ mod tests {
|
|
|
193
126
|
}
|
|
194
127
|
|
|
195
128
|
#[test]
|
|
196
|
-
fn
|
|
129
|
+
fn schema_key_from_definition_extracts_key() {
|
|
197
130
|
let schema = json!({
|
|
198
131
|
"x-lix-key": "users",
|
|
199
|
-
"x-lix-version": "2",
|
|
200
132
|
"type": "object"
|
|
201
133
|
});
|
|
202
134
|
|
|
203
135
|
let key = schema_key_from_definition(&schema).expect("schema key");
|
|
204
|
-
assert_eq!(key, SchemaKey::new("users"
|
|
136
|
+
assert_eq!(key, SchemaKey::new("users"));
|
|
205
137
|
}
|
|
206
138
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
mod annotations;
|
|
2
1
|
mod builtin;
|
|
2
|
+
#[allow(dead_code)]
|
|
3
|
+
pub(crate) mod compatibility;
|
|
3
4
|
mod definition;
|
|
4
5
|
mod key;
|
|
5
6
|
pub(crate) mod seed;
|
|
6
7
|
#[cfg(test)]
|
|
7
8
|
mod tests;
|
|
8
9
|
|
|
9
|
-
pub(crate) use
|
|
10
|
-
pub(crate) use builtin::lix_state_surface_schema_definition;
|
|
10
|
+
pub(crate) use compatibility::validate_schema_amendment;
|
|
11
11
|
pub(crate) use definition::{compile_lix_schema, format_lix_schema_validation_errors};
|
|
12
12
|
pub use definition::{
|
|
13
13
|
lix_schema_definition, lix_schema_definition_json, validate_lix_schema,
|
|
14
14
|
validate_lix_schema_definition,
|
|
15
15
|
};
|
|
16
|
-
pub(crate) use key::
|
|
16
|
+
pub(crate) use key::registered_schema_entity_id;
|
|
17
17
|
pub use key::{schema_from_registered_snapshot, schema_key_from_definition, SchemaKey};
|
|
18
18
|
#[cfg(test)]
|
|
19
19
|
pub(crate) use seed::seed_schema_definition;
|
|
@@ -5,7 +5,6 @@ use serde_json::json;
|
|
|
5
5
|
fn validate_lix_schema_definition_passes_for_valid_schema() {
|
|
6
6
|
let valid_schema = json!({
|
|
7
7
|
"x-lix-key": "test_entity",
|
|
8
|
-
"x-lix-version": "1",
|
|
9
8
|
"type": "object",
|
|
10
9
|
"properties": {
|
|
11
10
|
"id": { "type": "string" }
|
|
@@ -20,7 +19,6 @@ fn validate_lix_schema_definition_passes_for_valid_schema() {
|
|
|
20
19
|
fn validate_lix_schema_definition_rejects_unprojectable_entity_properties() {
|
|
21
20
|
let schema = json!({
|
|
22
21
|
"x-lix-key": "test_entity",
|
|
23
|
-
"x-lix-version": "1",
|
|
24
22
|
"type": "object",
|
|
25
23
|
"properties": {
|
|
26
24
|
"id": { "type": "string" },
|
|
@@ -41,10 +39,34 @@ fn validate_lix_schema_definition_rejects_unprojectable_entity_properties() {
|
|
|
41
39
|
);
|
|
42
40
|
}
|
|
43
41
|
|
|
42
|
+
#[test]
|
|
43
|
+
fn validate_lix_schema_definition_rejects_reserved_lix_property_prefixes() {
|
|
44
|
+
for property_name in ["lixcol_entity_id", "lix_internal", "lixfoo"] {
|
|
45
|
+
let schema = json!({
|
|
46
|
+
"x-lix-key": "test_entity",
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"id": { "type": "string" },
|
|
50
|
+
property_name: { "type": "string" }
|
|
51
|
+
},
|
|
52
|
+
"required": ["id", property_name],
|
|
53
|
+
"additionalProperties": false
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
let err = validate_lix_schema_definition(&schema)
|
|
57
|
+
.expect_err("reserved property names should be rejected");
|
|
58
|
+
assert!(
|
|
59
|
+
err.to_string().contains(&format!(
|
|
60
|
+
"property '/{property_name}' uses reserved prefix 'lix'"
|
|
61
|
+
)),
|
|
62
|
+
"error should identify the reserved property name: {err:?}"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
44
67
|
#[test]
|
|
45
68
|
fn validate_lix_schema_definition_throws_for_invalid_schema() {
|
|
46
69
|
let invalid_schema = json!({
|
|
47
|
-
"x-lix-version": "1",
|
|
48
70
|
"type": "object",
|
|
49
71
|
"properties": {
|
|
50
72
|
"id": { "type": "string" }
|
|
@@ -60,7 +82,6 @@ fn validate_lix_schema_definition_throws_for_invalid_schema() {
|
|
|
60
82
|
fn validate_lix_schema_validates_both_schema_and_data_successfully() {
|
|
61
83
|
let schema = json!({
|
|
62
84
|
"x-lix-key": "user",
|
|
63
|
-
"x-lix-version": "1",
|
|
64
85
|
"type": "object",
|
|
65
86
|
"properties": {
|
|
66
87
|
"id": { "type": "string" },
|
|
@@ -81,7 +102,6 @@ fn validate_lix_schema_validates_both_schema_and_data_successfully() {
|
|
|
81
102
|
#[test]
|
|
82
103
|
fn validate_lix_schema_throws_when_schema_is_invalid() {
|
|
83
104
|
let invalid_schema = json!({
|
|
84
|
-
"x-lix-version": "1",
|
|
85
105
|
"type": "object",
|
|
86
106
|
"properties": {
|
|
87
107
|
"id": { "type": "string" }
|
|
@@ -99,7 +119,6 @@ fn validate_lix_schema_throws_when_schema_is_invalid() {
|
|
|
99
119
|
fn validate_lix_schema_throws_when_data_does_not_match_schema() {
|
|
100
120
|
let schema = json!({
|
|
101
121
|
"x-lix-key": "user",
|
|
102
|
-
"x-lix-version": "1",
|
|
103
122
|
"type": "object",
|
|
104
123
|
"properties": {
|
|
105
124
|
"id": { "type": "string" },
|
|
@@ -119,7 +138,6 @@ fn validate_lix_schema_throws_when_data_does_not_match_schema() {
|
|
|
119
138
|
fn validate_lix_schema_definition_rejects_when_additional_properties_missing() {
|
|
120
139
|
let schema = json!({
|
|
121
140
|
"x-lix-key": "user",
|
|
122
|
-
"x-lix-version": "1",
|
|
123
141
|
"type": "object",
|
|
124
142
|
"properties": {
|
|
125
143
|
"id": { "type": "string" }
|
|
@@ -135,7 +153,6 @@ fn validate_lix_schema_definition_rejects_when_additional_properties_missing() {
|
|
|
135
153
|
fn additional_properties_must_be_false() {
|
|
136
154
|
let schema_with_additional_props = json!({
|
|
137
155
|
"x-lix-key": "user",
|
|
138
|
-
"x-lix-version": "1",
|
|
139
156
|
"type": "object",
|
|
140
157
|
"properties": {
|
|
141
158
|
"id": { "type": "string" },
|
|
@@ -149,7 +166,6 @@ fn additional_properties_must_be_false() {
|
|
|
149
166
|
|
|
150
167
|
let valid_schema = json!({
|
|
151
168
|
"x-lix-key": "user",
|
|
152
|
-
"x-lix-version": "1",
|
|
153
169
|
"type": "object",
|
|
154
170
|
"properties": {
|
|
155
171
|
"id": { "type": "string" },
|
|
@@ -175,7 +191,6 @@ fn additional_properties_must_be_false() {
|
|
|
175
191
|
fn validate_lix_schema_definition_rejects_missing_primary_key_properties() {
|
|
176
192
|
let schema = json!({
|
|
177
193
|
"x-lix-key": "missing_pk",
|
|
178
|
-
"x-lix-version": "1",
|
|
179
194
|
"type": "object",
|
|
180
195
|
"properties": {
|
|
181
196
|
"value": { "type": "string" }
|
|
@@ -191,11 +206,51 @@ fn validate_lix_schema_definition_rejects_missing_primary_key_properties() {
|
|
|
191
206
|
.contains("x-lix-primary-key references missing property"));
|
|
192
207
|
}
|
|
193
208
|
|
|
209
|
+
#[test]
|
|
210
|
+
fn validate_lix_schema_definition_rejects_non_string_primary_key_properties() {
|
|
211
|
+
let schema = json!({
|
|
212
|
+
"x-lix-key": "numeric_pk",
|
|
213
|
+
"type": "object",
|
|
214
|
+
"properties": {
|
|
215
|
+
"id": { "type": "number" },
|
|
216
|
+
"value": { "type": "string" }
|
|
217
|
+
},
|
|
218
|
+
"required": ["id", "value"],
|
|
219
|
+
"x-lix-primary-key": ["/id"],
|
|
220
|
+
"additionalProperties": false
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
let err = validate_lix_schema_definition(&schema).unwrap_err();
|
|
224
|
+
assert!(err
|
|
225
|
+
.to_string()
|
|
226
|
+
.contains("x-lix-primary-key property \"/id\" must have type \"string\""));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#[test]
|
|
230
|
+
fn validate_lix_schema_definition_rejects_optional_primary_key_properties() {
|
|
231
|
+
let schema = json!({
|
|
232
|
+
"x-lix-key": "optional_pk",
|
|
233
|
+
"type": "object",
|
|
234
|
+
"properties": {
|
|
235
|
+
"id": { "type": "string" },
|
|
236
|
+
"value": { "type": "string" }
|
|
237
|
+
},
|
|
238
|
+
"required": ["value"],
|
|
239
|
+
"x-lix-primary-key": ["/id"],
|
|
240
|
+
"additionalProperties": false
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
let err = validate_lix_schema_definition(&schema)
|
|
244
|
+
.expect_err("primary-key property should be required");
|
|
245
|
+
assert!(err
|
|
246
|
+
.to_string()
|
|
247
|
+
.contains("x-lix-primary-key property \"/id\" must be required"));
|
|
248
|
+
}
|
|
249
|
+
|
|
194
250
|
#[test]
|
|
195
251
|
fn validate_lix_schema_definition_rejects_missing_unique_constraint_properties() {
|
|
196
252
|
let schema = json!({
|
|
197
253
|
"x-lix-key": "missing_unique",
|
|
198
|
-
"x-lix-version": "1",
|
|
199
254
|
"type": "object",
|
|
200
255
|
"properties": {
|
|
201
256
|
"value": { "type": "string" }
|
|
@@ -215,7 +270,6 @@ fn x_key_is_required() {
|
|
|
215
270
|
let schema = json!({
|
|
216
271
|
"type": "object",
|
|
217
272
|
"x-lix-key": null,
|
|
218
|
-
"x-lix-version": "1",
|
|
219
273
|
"properties": {
|
|
220
274
|
"name": { "type": "string" }
|
|
221
275
|
},
|
|
@@ -230,7 +284,6 @@ fn x_key_is_required() {
|
|
|
230
284
|
fn x_lix_key_must_be_snake_case() {
|
|
231
285
|
let base_schema = json!({
|
|
232
286
|
"type": "object",
|
|
233
|
-
"x-lix-version": "1",
|
|
234
287
|
"properties": {
|
|
235
288
|
"name": { "type": "string" }
|
|
236
289
|
},
|
|
@@ -266,7 +319,6 @@ fn x_lix_unique_is_optional() {
|
|
|
266
319
|
let schema = json!({
|
|
267
320
|
"type": "object",
|
|
268
321
|
"x-lix-key": "mock",
|
|
269
|
-
"x-lix-version": "1",
|
|
270
322
|
"properties": {
|
|
271
323
|
"name": { "type": "string" }
|
|
272
324
|
},
|
|
@@ -282,7 +334,6 @@ fn x_lix_unique_must_be_array_of_arrays_when_present() {
|
|
|
282
334
|
let schema = json!({
|
|
283
335
|
"type": "object",
|
|
284
336
|
"x-lix-key": "mock",
|
|
285
|
-
"x-lix-version": "1",
|
|
286
337
|
"x-lix-unique": [["/id"], ["/name", "/age"]],
|
|
287
338
|
"properties": {
|
|
288
339
|
"id": { "type": "string" },
|
|
@@ -301,7 +352,6 @@ fn x_lix_unique_fails_with_invalid_structure() {
|
|
|
301
352
|
let schema = json!({
|
|
302
353
|
"type": "object",
|
|
303
354
|
"x-lix-key": "mock",
|
|
304
|
-
"x-lix-version": "1",
|
|
305
355
|
"x-lix-unique": ["/id", "/name"],
|
|
306
356
|
"properties": {
|
|
307
357
|
"id": { "type": "string" },
|
|
@@ -319,7 +369,6 @@ fn x_lix_primary_key_must_include_at_least_one_unique_pointer() {
|
|
|
319
369
|
let base_schema = json!({
|
|
320
370
|
"type": "object",
|
|
321
371
|
"x-lix-key": "mock",
|
|
322
|
-
"x-lix-version": "1",
|
|
323
372
|
"properties": {
|
|
324
373
|
"id": { "type": "string" }
|
|
325
374
|
},
|
|
@@ -345,7 +394,6 @@ fn x_lix_unique_groups_must_include_unique_pointers() {
|
|
|
345
394
|
let base_schema = json!({
|
|
346
395
|
"type": "object",
|
|
347
396
|
"x-lix-key": "mock",
|
|
348
|
-
"x-lix-version": "1",
|
|
349
397
|
"properties": {
|
|
350
398
|
"id": { "type": "string" },
|
|
351
399
|
"email": { "type": "string" }
|
|
@@ -372,7 +420,6 @@ fn x_lix_entity_views_is_rejected() {
|
|
|
372
420
|
let schema = json!({
|
|
373
421
|
"type": "object",
|
|
374
422
|
"x-lix-key": "mock",
|
|
375
|
-
"x-lix-version": "1",
|
|
376
423
|
"x-lix-entity-views": ["lix_state", "lix_state_by_version"],
|
|
377
424
|
"properties": {
|
|
378
425
|
"name": { "type": "string" }
|
|
@@ -391,7 +438,6 @@ fn x_lix_primary_key_is_optional() {
|
|
|
391
438
|
let schema = json!({
|
|
392
439
|
"type": "object",
|
|
393
440
|
"x-lix-key": "mock",
|
|
394
|
-
"x-lix-version": "1",
|
|
395
441
|
"properties": {
|
|
396
442
|
"name": { "type": "string" }
|
|
397
443
|
},
|
|
@@ -407,7 +453,6 @@ fn x_lix_primary_key_must_be_array_of_strings_when_present() {
|
|
|
407
453
|
let schema = json!({
|
|
408
454
|
"type": "object",
|
|
409
455
|
"x-lix-key": "mock",
|
|
410
|
-
"x-lix-version": "1",
|
|
411
456
|
"x-lix-primary-key": ["/id", "/version"],
|
|
412
457
|
"properties": {
|
|
413
458
|
"id": { "type": "string" },
|
|
@@ -426,7 +471,6 @@ fn x_lix_foreign_keys_is_optional() {
|
|
|
426
471
|
let schema = json!({
|
|
427
472
|
"type": "object",
|
|
428
473
|
"x-lix-key": "blog_post",
|
|
429
|
-
"x-lix-version": "1",
|
|
430
474
|
"properties": {
|
|
431
475
|
"id": { "type": "string" },
|
|
432
476
|
"author_id": { "type": "string" }
|
|
@@ -443,7 +487,6 @@ fn x_lix_foreign_keys_with_valid_structure() {
|
|
|
443
487
|
let schema = json!({
|
|
444
488
|
"type": "object",
|
|
445
489
|
"x-lix-key": "blog_post",
|
|
446
|
-
"x-lix-version": "1",
|
|
447
490
|
"x-lix-foreign-keys": [
|
|
448
491
|
{
|
|
449
492
|
"properties": ["/author_id"],
|
|
@@ -477,7 +520,6 @@ fn x_lix_foreign_keys_reject_duplicate_pointers() {
|
|
|
477
520
|
let schema = json!({
|
|
478
521
|
"type": "object",
|
|
479
522
|
"x-lix-key": "invalid_fk_duplicates",
|
|
480
|
-
"x-lix-version": "1",
|
|
481
523
|
"x-lix-foreign-keys": [
|
|
482
524
|
{
|
|
483
525
|
"properties": ["/local", "/local"],
|
|
@@ -502,7 +544,6 @@ fn x_lix_foreign_keys_fails_without_required_fields() {
|
|
|
502
544
|
let schema = json!({
|
|
503
545
|
"type": "object",
|
|
504
546
|
"x-lix-key": "blog_post",
|
|
505
|
-
"x-lix-version": "1",
|
|
506
547
|
"x-lix-foreign-keys": [
|
|
507
548
|
{
|
|
508
549
|
"properties": ["/author_id"]
|
|
@@ -520,18 +561,16 @@ fn x_lix_foreign_keys_fails_without_required_fields() {
|
|
|
520
561
|
}
|
|
521
562
|
|
|
522
563
|
#[test]
|
|
523
|
-
fn
|
|
564
|
+
fn x_lix_foreign_keys_use_schema_key_identity_only() {
|
|
524
565
|
let schema = json!({
|
|
525
566
|
"type": "object",
|
|
526
567
|
"x-lix-key": "comment",
|
|
527
|
-
"x-lix-version": "1",
|
|
528
568
|
"x-lix-foreign-keys": [
|
|
529
569
|
{
|
|
530
570
|
"properties": ["/post_id"],
|
|
531
571
|
"references": {
|
|
532
572
|
"schemaKey": "blog_post",
|
|
533
|
-
"properties": ["/id"]
|
|
534
|
-
"schemaVersion": "1"
|
|
573
|
+
"properties": ["/id"]
|
|
535
574
|
}
|
|
536
575
|
}
|
|
537
576
|
],
|
|
@@ -543,7 +582,7 @@ fn x_lix_foreign_keys_rejects_schema_version() {
|
|
|
543
582
|
"additionalProperties": false
|
|
544
583
|
});
|
|
545
584
|
|
|
546
|
-
assert!(validate_lix_schema_definition(&schema).
|
|
585
|
+
assert!(validate_lix_schema_definition(&schema).is_ok());
|
|
547
586
|
}
|
|
548
587
|
|
|
549
588
|
#[test]
|
|
@@ -551,7 +590,6 @@ fn x_lix_foreign_keys_rejects_mode_field() {
|
|
|
551
590
|
let schema = json!({
|
|
552
591
|
"type": "object",
|
|
553
592
|
"x-lix-key": "child_entity",
|
|
554
|
-
"x-lix-version": "1",
|
|
555
593
|
"x-lix-primary-key": ["/id"],
|
|
556
594
|
"x-lix-foreign-keys": [
|
|
557
595
|
{
|
|
@@ -577,7 +615,6 @@ fn x_lix_foreign_keys_rejects_scope_field() {
|
|
|
577
615
|
let schema = json!({
|
|
578
616
|
"type": "object",
|
|
579
617
|
"x-lix-key": "child_entity",
|
|
580
|
-
"x-lix-version": "1",
|
|
581
618
|
"x-lix-primary-key": ["/id"],
|
|
582
619
|
"x-lix-foreign-keys": [
|
|
583
620
|
{
|
|
@@ -599,19 +636,14 @@ fn x_lix_foreign_keys_rejects_scope_field() {
|
|
|
599
636
|
}
|
|
600
637
|
|
|
601
638
|
#[test]
|
|
602
|
-
fn
|
|
639
|
+
fn x_lix_state_foreign_keys_with_ordered_state_address_tuple() {
|
|
603
640
|
let schema = json!({
|
|
604
641
|
"type": "object",
|
|
605
|
-
"x-lix-key": "
|
|
606
|
-
"x-lix-
|
|
642
|
+
"x-lix-key": "label_assignment",
|
|
643
|
+
"x-lix-state-foreign-keys": [
|
|
644
|
+
["/target_entity_id", "/target_schema_key", "/target_file_id"]
|
|
645
|
+
],
|
|
607
646
|
"x-lix-foreign-keys": [
|
|
608
|
-
{
|
|
609
|
-
"properties": ["/entity_id", "/schema_key", "/file_id"],
|
|
610
|
-
"references": {
|
|
611
|
-
"schemaKey": "lix_state",
|
|
612
|
-
"properties": ["/entity_id", "/schema_key", "/file_id"]
|
|
613
|
-
}
|
|
614
|
-
},
|
|
615
647
|
{
|
|
616
648
|
"properties": ["/label_id"],
|
|
617
649
|
"references": {
|
|
@@ -621,12 +653,16 @@ fn x_lix_foreign_keys_with_composite_key() {
|
|
|
621
653
|
}
|
|
622
654
|
],
|
|
623
655
|
"properties": {
|
|
624
|
-
"
|
|
625
|
-
|
|
626
|
-
|
|
656
|
+
"target_entity_id": {
|
|
657
|
+
"type": "array",
|
|
658
|
+
"items": { "type": "string" },
|
|
659
|
+
"minItems": 1
|
|
660
|
+
},
|
|
661
|
+
"target_schema_key": { "type": "string" },
|
|
662
|
+
"target_file_id": { "type": ["string", "null"] },
|
|
627
663
|
"label_id": { "type": "string" }
|
|
628
664
|
},
|
|
629
|
-
"required": ["
|
|
665
|
+
"required": ["target_entity_id", "target_schema_key", "target_file_id", "label_id"],
|
|
630
666
|
"additionalProperties": false
|
|
631
667
|
});
|
|
632
668
|
|
|
@@ -634,78 +670,85 @@ fn x_lix_foreign_keys_with_composite_key() {
|
|
|
634
670
|
}
|
|
635
671
|
|
|
636
672
|
#[test]
|
|
637
|
-
fn
|
|
673
|
+
fn x_lix_state_foreign_keys_rejects_wrong_tuple_order_by_type() {
|
|
638
674
|
let schema = json!({
|
|
639
675
|
"type": "object",
|
|
640
|
-
"x-lix-key": "
|
|
641
|
-
"x-lix-
|
|
642
|
-
|
|
643
|
-
{
|
|
644
|
-
"properties": ["/entity_id", "/schema_key", "/file_id"],
|
|
645
|
-
"references": {
|
|
646
|
-
"schemaKey": "state",
|
|
647
|
-
"properties": ["/entity_id", "/schema_key", "/file_id"]
|
|
648
|
-
}
|
|
649
|
-
}
|
|
676
|
+
"x-lix-key": "bad_label_assignment",
|
|
677
|
+
"x-lix-state-foreign-keys": [
|
|
678
|
+
["/target_schema_key", "/target_entity_id", "/target_file_id"]
|
|
650
679
|
],
|
|
651
680
|
"properties": {
|
|
652
|
-
"
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
assert!(validate_lix_schema_definition(&schema).is_err());
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
#[test]
|
|
664
|
-
fn x_version_is_required() {
|
|
665
|
-
let schema = json!({
|
|
666
|
-
"type": "object",
|
|
667
|
-
"x-lix-version": null,
|
|
668
|
-
"x-lix-key": "mock",
|
|
669
|
-
"properties": {
|
|
670
|
-
"name": { "type": "string" }
|
|
681
|
+
"target_entity_id": {
|
|
682
|
+
"type": "array",
|
|
683
|
+
"items": { "type": "string" },
|
|
684
|
+
"minItems": 1
|
|
685
|
+
},
|
|
686
|
+
"target_schema_key": { "type": "string" },
|
|
687
|
+
"target_file_id": { "type": ["string", "null"] }
|
|
671
688
|
},
|
|
672
|
-
"required": ["
|
|
689
|
+
"required": ["target_entity_id", "target_schema_key", "target_file_id"],
|
|
673
690
|
"additionalProperties": false
|
|
674
691
|
});
|
|
675
692
|
|
|
676
|
-
|
|
693
|
+
let err =
|
|
694
|
+
validate_lix_schema_definition(&schema).expect_err("wrong tuple order should be rejected");
|
|
695
|
+
assert!(
|
|
696
|
+
err.message.contains("[entity_id, schema_key, file_id]"),
|
|
697
|
+
"unexpected error: {err:?}"
|
|
698
|
+
);
|
|
677
699
|
}
|
|
678
700
|
|
|
679
701
|
#[test]
|
|
680
|
-
fn
|
|
702
|
+
fn x_lix_state_foreign_keys_requires_address_tuple_properties() {
|
|
681
703
|
let schema = json!({
|
|
682
704
|
"type": "object",
|
|
683
|
-
"x-lix-
|
|
684
|
-
"x-lix-
|
|
705
|
+
"x-lix-key": "optional_label_assignment",
|
|
706
|
+
"x-lix-state-foreign-keys": [
|
|
707
|
+
["/target_entity_id", "/target_schema_key", "/target_file_id"]
|
|
708
|
+
],
|
|
685
709
|
"properties": {
|
|
686
|
-
"
|
|
710
|
+
"target_entity_id": {
|
|
711
|
+
"type": "array",
|
|
712
|
+
"items": { "type": "string" },
|
|
713
|
+
"minItems": 1
|
|
714
|
+
},
|
|
715
|
+
"target_schema_key": { "type": "string" },
|
|
716
|
+
"target_file_id": { "type": ["string", "null"] }
|
|
687
717
|
},
|
|
688
|
-
"required": ["
|
|
718
|
+
"required": ["target_entity_id", "target_schema_key"],
|
|
689
719
|
"additionalProperties": false
|
|
690
720
|
});
|
|
691
721
|
|
|
692
|
-
|
|
722
|
+
let err = validate_lix_schema_definition(&schema)
|
|
723
|
+
.expect_err("state foreign key tuple fields should be required");
|
|
724
|
+
assert!(
|
|
725
|
+
err.message.contains("file_id") && err.message.contains("must be required"),
|
|
726
|
+
"unexpected error: {err:?}"
|
|
727
|
+
);
|
|
693
728
|
}
|
|
694
729
|
|
|
695
730
|
#[test]
|
|
696
|
-
fn
|
|
731
|
+
fn x_lix_foreign_keys_treat_schema_keys_literally() {
|
|
697
732
|
let schema = json!({
|
|
698
733
|
"type": "object",
|
|
699
|
-
"x-lix-
|
|
700
|
-
"x-lix-
|
|
734
|
+
"x-lix-key": "custom_label_assignment",
|
|
735
|
+
"x-lix-foreign-keys": [
|
|
736
|
+
{
|
|
737
|
+
"properties": ["/label_id"],
|
|
738
|
+
"references": {
|
|
739
|
+
"schemaKey": "label",
|
|
740
|
+
"properties": ["/id"]
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
],
|
|
701
744
|
"properties": {
|
|
702
|
-
"
|
|
745
|
+
"label_id": { "type": "string" }
|
|
703
746
|
},
|
|
704
|
-
"required": ["
|
|
747
|
+
"required": ["label_id"],
|
|
705
748
|
"additionalProperties": false
|
|
706
749
|
});
|
|
707
750
|
|
|
708
|
-
assert!(validate_lix_schema_definition(&schema).
|
|
751
|
+
assert!(validate_lix_schema_definition(&schema).is_ok());
|
|
709
752
|
}
|
|
710
753
|
|
|
711
754
|
#[test]
|
|
@@ -713,7 +756,6 @@ fn x_lix_default_accepts_valid_cel_expression() {
|
|
|
713
756
|
let schema = json!({
|
|
714
757
|
"type": "object",
|
|
715
758
|
"x-lix-key": "mock",
|
|
716
|
-
"x-lix-version": "1",
|
|
717
759
|
"properties": {
|
|
718
760
|
"id": { "type": "string", "x-lix-default": "lix_uuid_v7()" }
|
|
719
761
|
},
|
|
@@ -728,7 +770,6 @@ fn x_lix_default_rejects_invalid_cel_expression() {
|
|
|
728
770
|
let schema = json!({
|
|
729
771
|
"type": "object",
|
|
730
772
|
"x-lix-key": "mock",
|
|
731
|
-
"x-lix-version": "1",
|
|
732
773
|
"properties": {
|
|
733
774
|
"id": { "type": "string", "x-lix-default": "lix_uuid_v7(" }
|
|
734
775
|
},
|