@lix-js/sdk 0.6.0-preview.5 → 0.6.1

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 (274) hide show
  1. package/README.md +76 -4
  2. package/dist/errors.d.ts +7 -0
  3. package/dist/errors.js +19 -0
  4. package/dist/index.d.ts +4 -5
  5. package/dist/index.js +3 -3
  6. package/dist/native.d.ts +1 -0
  7. package/dist/native.js +47 -0
  8. package/dist/open-lix.d.ts +38 -207
  9. package/dist/open-lix.js +59 -284
  10. package/dist/result.d.ts +18 -0
  11. package/dist/result.js +48 -0
  12. package/dist/types.d.ts +114 -1
  13. package/dist/value.d.ts +28 -0
  14. package/dist/value.js +245 -0
  15. package/package.json +38 -71
  16. package/SKILL.md +0 -507
  17. package/dist/builtin-schemas.d.ts +0 -1
  18. package/dist/builtin-schemas.js +0 -1
  19. package/dist/engine-wasm/index.d.ts +0 -87
  20. package/dist/engine-wasm/index.js +0 -339
  21. package/dist/engine-wasm/wasm/lix_engine.d.ts +0 -79
  22. package/dist/engine-wasm/wasm/lix_engine.js +0 -833
  23. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  24. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +0 -27
  25. package/dist/generated/builtin-schemas.d.ts +0 -427
  26. package/dist/generated/builtin-schemas.js +0 -643
  27. package/dist/sqlite/index.d.ts +0 -12
  28. package/dist/sqlite/index.js +0 -359
  29. package/dist-engine-src/README.md +0 -18
  30. package/dist-engine-src/src/backend/capabilities.rs +0 -67
  31. package/dist-engine-src/src/backend/conformance/baseline.rs +0 -1127
  32. package/dist-engine-src/src/backend/conformance/factory.rs +0 -93
  33. package/dist-engine-src/src/backend/conformance/failure_tests.rs +0 -608
  34. package/dist-engine-src/src/backend/conformance/fixtures.rs +0 -26
  35. package/dist-engine-src/src/backend/conformance/mod.rs +0 -75
  36. package/dist-engine-src/src/backend/conformance/model.rs +0 -28
  37. package/dist-engine-src/src/backend/conformance/model_based.rs +0 -257
  38. package/dist-engine-src/src/backend/conformance/persistence.rs +0 -204
  39. package/dist-engine-src/src/backend/conformance/projection.rs +0 -21
  40. package/dist-engine-src/src/backend/conformance/pushdown.rs +0 -24
  41. package/dist-engine-src/src/backend/conformance/runner.rs +0 -90
  42. package/dist-engine-src/src/backend/conformance/scan.rs +0 -24
  43. package/dist-engine-src/src/backend/conformance/write.rs +0 -16
  44. package/dist-engine-src/src/backend/error.rs +0 -94
  45. package/dist-engine-src/src/backend/in_memory.rs +0 -670
  46. package/dist-engine-src/src/backend/mod.rs +0 -39
  47. package/dist-engine-src/src/backend/predicate.rs +0 -80
  48. package/dist-engine-src/src/backend/traits.rs +0 -260
  49. package/dist-engine-src/src/backend/types.rs +0 -239
  50. package/dist-engine-src/src/binary_cas/chunking.rs +0 -31
  51. package/dist-engine-src/src/binary_cas/codec.rs +0 -346
  52. package/dist-engine-src/src/binary_cas/context.rs +0 -139
  53. package/dist-engine-src/src/binary_cas/kv.rs +0 -1038
  54. package/dist-engine-src/src/binary_cas/mod.rs +0 -11
  55. package/dist-engine-src/src/binary_cas/types.rs +0 -121
  56. package/dist-engine-src/src/branch/context.rs +0 -40
  57. package/dist-engine-src/src/branch/lifecycle.rs +0 -221
  58. package/dist-engine-src/src/branch/mod.rs +0 -13
  59. package/dist-engine-src/src/branch/refs.rs +0 -321
  60. package/dist-engine-src/src/branch/stage_rows.rs +0 -67
  61. package/dist-engine-src/src/branch/types.rs +0 -21
  62. package/dist-engine-src/src/catalog/context.rs +0 -412
  63. package/dist-engine-src/src/catalog/mod.rs +0 -10
  64. package/dist-engine-src/src/catalog/schema.rs +0 -4
  65. package/dist-engine-src/src/catalog/snapshot.rs +0 -1114
  66. package/dist-engine-src/src/cel/context.rs +0 -86
  67. package/dist-engine-src/src/cel/error.rs +0 -19
  68. package/dist-engine-src/src/cel/mod.rs +0 -8
  69. package/dist-engine-src/src/cel/provider.rs +0 -9
  70. package/dist-engine-src/src/cel/runtime.rs +0 -167
  71. package/dist-engine-src/src/cel/value.rs +0 -50
  72. package/dist-engine-src/src/changelog/bench_support.rs +0 -785
  73. package/dist-engine-src/src/changelog/change.rs +0 -1
  74. package/dist-engine-src/src/changelog/codec.rs +0 -497
  75. package/dist-engine-src/src/changelog/commit.rs +0 -1
  76. package/dist-engine-src/src/changelog/context.rs +0 -1614
  77. package/dist-engine-src/src/changelog/mod.rs +0 -29
  78. package/dist-engine-src/src/changelog/store.rs +0 -163
  79. package/dist-engine-src/src/changelog/test_support.rs +0 -54
  80. package/dist-engine-src/src/changelog/types.rs +0 -213
  81. package/dist-engine-src/src/commit_graph/context.rs +0 -944
  82. package/dist-engine-src/src/commit_graph/mod.rs +0 -9
  83. package/dist-engine-src/src/commit_graph/types.rs +0 -89
  84. package/dist-engine-src/src/commit_graph/walker.rs +0 -786
  85. package/dist-engine-src/src/common/error.rs +0 -347
  86. package/dist-engine-src/src/common/fingerprint.rs +0 -3
  87. package/dist-engine-src/src/common/fs_path.rs +0 -1336
  88. package/dist-engine-src/src/common/identity.rs +0 -145
  89. package/dist-engine-src/src/common/json_pointer.rs +0 -67
  90. package/dist-engine-src/src/common/metadata.rs +0 -40
  91. package/dist-engine-src/src/common/mod.rs +0 -23
  92. package/dist-engine-src/src/common/types.rs +0 -105
  93. package/dist-engine-src/src/common/wire.rs +0 -222
  94. package/dist-engine-src/src/domain.rs +0 -320
  95. package/dist-engine-src/src/engine.rs +0 -203
  96. package/dist-engine-src/src/entity_pk.rs +0 -402
  97. package/dist-engine-src/src/functions/context.rs +0 -296
  98. package/dist-engine-src/src/functions/deterministic.rs +0 -113
  99. package/dist-engine-src/src/functions/mod.rs +0 -18
  100. package/dist-engine-src/src/functions/provider.rs +0 -130
  101. package/dist-engine-src/src/functions/state.rs +0 -335
  102. package/dist-engine-src/src/functions/types.rs +0 -37
  103. package/dist-engine-src/src/init.rs +0 -692
  104. package/dist-engine-src/src/json_store/compression.rs +0 -77
  105. package/dist-engine-src/src/json_store/context.rs +0 -172
  106. package/dist-engine-src/src/json_store/encoded.rs +0 -15
  107. package/dist-engine-src/src/json_store/mod.rs +0 -38
  108. package/dist-engine-src/src/json_store/store.rs +0 -494
  109. package/dist-engine-src/src/json_store/types.rs +0 -212
  110. package/dist-engine-src/src/lib.rs +0 -92
  111. package/dist-engine-src/src/live_state/context.rs +0 -1883
  112. package/dist-engine-src/src/live_state/mod.rs +0 -21
  113. package/dist-engine-src/src/live_state/overlay.rs +0 -75
  114. package/dist-engine-src/src/live_state/reader.rs +0 -23
  115. package/dist-engine-src/src/live_state/types.rs +0 -231
  116. package/dist-engine-src/src/live_state/visibility.rs +0 -666
  117. package/dist-engine-src/src/plugin/archive.rs +0 -438
  118. package/dist-engine-src/src/plugin/component.rs +0 -183
  119. package/dist-engine-src/src/plugin/install.rs +0 -619
  120. package/dist-engine-src/src/plugin/manifest.rs +0 -516
  121. package/dist-engine-src/src/plugin/materializer.rs +0 -202
  122. package/dist-engine-src/src/plugin/mod.rs +0 -33
  123. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -119
  124. package/dist-engine-src/src/plugin/storage.rs +0 -74
  125. package/dist-engine-src/src/schema/annotations/defaults.rs +0 -275
  126. package/dist-engine-src/src/schema/annotations/mod.rs +0 -1
  127. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -21
  128. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -29
  129. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -29
  130. package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +0 -34
  131. package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +0 -48
  132. package/dist-engine-src/src/schema/builtin/lix_change.json +0 -63
  133. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -45
  134. package/dist-engine-src/src/schema/builtin/lix_commit.json +0 -24
  135. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +0 -53
  136. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -52
  137. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -52
  138. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -40
  139. package/dist-engine-src/src/schema/builtin/lix_label.json +0 -29
  140. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +0 -74
  141. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +0 -25
  142. package/dist-engine-src/src/schema/builtin/mod.rs +0 -220
  143. package/dist-engine-src/src/schema/compatibility.rs +0 -787
  144. package/dist-engine-src/src/schema/definition.json +0 -187
  145. package/dist-engine-src/src/schema/definition.rs +0 -742
  146. package/dist-engine-src/src/schema/key.rs +0 -138
  147. package/dist-engine-src/src/schema/mod.rs +0 -20
  148. package/dist-engine-src/src/schema/seed.rs +0 -14
  149. package/dist-engine-src/src/schema/tests.rs +0 -780
  150. package/dist-engine-src/src/session/context.rs +0 -1059
  151. package/dist-engine-src/src/session/create_branch.rs +0 -94
  152. package/dist-engine-src/src/session/execute.rs +0 -681
  153. package/dist-engine-src/src/session/merge/analysis.rs +0 -108
  154. package/dist-engine-src/src/session/merge/branch.rs +0 -417
  155. package/dist-engine-src/src/session/merge/conflicts.rs +0 -63
  156. package/dist-engine-src/src/session/merge/mod.rs +0 -10
  157. package/dist-engine-src/src/session/merge/stats.rs +0 -61
  158. package/dist-engine-src/src/session/mod.rs +0 -30
  159. package/dist-engine-src/src/session/switch_branch.rs +0 -113
  160. package/dist-engine-src/src/session/transaction.rs +0 -557
  161. package/dist-engine-src/src/sql2/bind/classify.rs +0 -102
  162. package/dist-engine-src/src/sql2/bind/error.rs +0 -5
  163. package/dist-engine-src/src/sql2/bind/expr.rs +0 -29
  164. package/dist-engine-src/src/sql2/bind/mod.rs +0 -12
  165. package/dist-engine-src/src/sql2/bind/public_udf.rs +0 -306
  166. package/dist-engine-src/src/sql2/bind/read.rs +0 -65
  167. package/dist-engine-src/src/sql2/bind/statement.rs +0 -2236
  168. package/dist-engine-src/src/sql2/bind/table.rs +0 -273
  169. package/dist-engine-src/src/sql2/bind/write.rs +0 -86
  170. package/dist-engine-src/src/sql2/branch_scope.rs +0 -436
  171. package/dist-engine-src/src/sql2/catalog/capability.rs +0 -20
  172. package/dist-engine-src/src/sql2/catalog/entity_surface.rs +0 -296
  173. package/dist-engine-src/src/sql2/catalog/mod.rs +0 -15
  174. package/dist-engine-src/src/sql2/catalog/registry.rs +0 -556
  175. package/dist-engine-src/src/sql2/catalog/schema.rs +0 -88
  176. package/dist-engine-src/src/sql2/catalog/surface.rs +0 -41
  177. package/dist-engine-src/src/sql2/change_materialization.rs +0 -122
  178. package/dist-engine-src/src/sql2/context.rs +0 -317
  179. package/dist-engine-src/src/sql2/dml.rs +0 -148
  180. package/dist-engine-src/src/sql2/error.rs +0 -215
  181. package/dist-engine-src/src/sql2/exec/bound_public_write.rs +0 -1593
  182. package/dist-engine-src/src/sql2/exec/datafusion.rs +0 -5266
  183. package/dist-engine-src/src/sql2/exec/fast_write.rs +0 -82
  184. package/dist-engine-src/src/sql2/exec/mod.rs +0 -24
  185. package/dist-engine-src/src/sql2/exec/write.rs +0 -661
  186. package/dist-engine-src/src/sql2/filesystem_planner.rs +0 -1485
  187. package/dist-engine-src/src/sql2/filesystem_predicates.rs +0 -159
  188. package/dist-engine-src/src/sql2/filesystem_visibility.rs +0 -383
  189. package/dist-engine-src/src/sql2/history_projection.rs +0 -56
  190. package/dist-engine-src/src/sql2/history_route.rs +0 -661
  191. package/dist-engine-src/src/sql2/mod.rs +0 -52
  192. package/dist-engine-src/src/sql2/optimize/datafusion.rs +0 -1
  193. package/dist-engine-src/src/sql2/optimize/mod.rs +0 -2
  194. package/dist-engine-src/src/sql2/optimize/simple_write.rs +0 -116
  195. package/dist-engine-src/src/sql2/parse/mod.rs +0 -69
  196. package/dist-engine-src/src/sql2/parse/normalize.rs +0 -1
  197. package/dist-engine-src/src/sql2/plan/branch_scope.rs +0 -24
  198. package/dist-engine-src/src/sql2/plan/mod.rs +0 -5
  199. package/dist-engine-src/src/sql2/plan/predicate.rs +0 -22
  200. package/dist-engine-src/src/sql2/plan/write.rs +0 -147
  201. package/dist-engine-src/src/sql2/predicate_typecheck.rs +0 -504
  202. package/dist-engine-src/src/sql2/providers/branch.rs +0 -1206
  203. package/dist-engine-src/src/sql2/providers/change.rs +0 -445
  204. package/dist-engine-src/src/sql2/providers/directory.rs +0 -2422
  205. package/dist-engine-src/src/sql2/providers/directory_history.rs +0 -645
  206. package/dist-engine-src/src/sql2/providers/entity.rs +0 -1484
  207. package/dist-engine-src/src/sql2/providers/entity_history.rs +0 -452
  208. package/dist-engine-src/src/sql2/providers/file.rs +0 -3686
  209. package/dist-engine-src/src/sql2/providers/file_history.rs +0 -924
  210. package/dist-engine-src/src/sql2/providers/history.rs +0 -426
  211. package/dist-engine-src/src/sql2/providers/lix_state.rs +0 -2542
  212. package/dist-engine-src/src/sql2/providers/mod.rs +0 -508
  213. package/dist-engine-src/src/sql2/read_only.rs +0 -63
  214. package/dist-engine-src/src/sql2/record_batch.rs +0 -17
  215. package/dist-engine-src/src/sql2/result_metadata.rs +0 -29
  216. package/dist-engine-src/src/sql2/runtime.rs +0 -60
  217. package/dist-engine-src/src/sql2/session.rs +0 -83
  218. package/dist-engine-src/src/sql2/storage/constraints.rs +0 -1
  219. package/dist-engine-src/src/sql2/storage/mod.rs +0 -1
  220. package/dist-engine-src/src/sql2/test_support/differential.rs +0 -712
  221. package/dist-engine-src/src/sql2/test_support/generators.rs +0 -354
  222. package/dist-engine-src/src/sql2/test_support/mod.rs +0 -2
  223. package/dist-engine-src/src/sql2/udfs/common.rs +0 -295
  224. package/dist-engine-src/src/sql2/udfs/lix_active_branch_commit_id.rs +0 -53
  225. package/dist-engine-src/src/sql2/udfs/lix_empty_blob.rs +0 -47
  226. package/dist-engine-src/src/sql2/udfs/lix_json.rs +0 -100
  227. package/dist-engine-src/src/sql2/udfs/lix_json_get.rs +0 -99
  228. package/dist-engine-src/src/sql2/udfs/lix_json_get_text.rs +0 -99
  229. package/dist-engine-src/src/sql2/udfs/lix_text_decode.rs +0 -82
  230. package/dist-engine-src/src/sql2/udfs/lix_text_encode.rs +0 -85
  231. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +0 -76
  232. package/dist-engine-src/src/sql2/udfs/lix_uuid_v7.rs +0 -76
  233. package/dist-engine-src/src/sql2/udfs/mod.rs +0 -86
  234. package/dist-engine-src/src/sql2/write_normalization.rs +0 -368
  235. package/dist-engine-src/src/storage/conformance.rs +0 -399
  236. package/dist-engine-src/src/storage/context.rs +0 -620
  237. package/dist-engine-src/src/storage/mod.rs +0 -52
  238. package/dist-engine-src/src/storage/point.rs +0 -440
  239. package/dist-engine-src/src/storage/read_scope.rs +0 -67
  240. package/dist-engine-src/src/storage/reader.rs +0 -867
  241. package/dist-engine-src/src/storage/scan.rs +0 -784
  242. package/dist-engine-src/src/storage/spaces.rs +0 -236
  243. package/dist-engine-src/src/storage/stats.rs +0 -80
  244. package/dist-engine-src/src/storage/write_set.rs +0 -962
  245. package/dist-engine-src/src/storage_bench.rs +0 -171
  246. package/dist-engine-src/src/test_support.rs +0 -450
  247. package/dist-engine-src/src/tracked_state/bench_support.rs +0 -394
  248. package/dist-engine-src/src/tracked_state/codec.rs +0 -1183
  249. package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +0 -358
  250. package/dist-engine-src/src/tracked_state/context.rs +0 -2801
  251. package/dist-engine-src/src/tracked_state/diff.rs +0 -2140
  252. package/dist-engine-src/src/tracked_state/merge.rs +0 -478
  253. package/dist-engine-src/src/tracked_state/mod.rs +0 -35
  254. package/dist-engine-src/src/tracked_state/row_materialization.rs +0 -275
  255. package/dist-engine-src/src/tracked_state/storage.rs +0 -427
  256. package/dist-engine-src/src/tracked_state/tree.rs +0 -3063
  257. package/dist-engine-src/src/tracked_state/types.rs +0 -238
  258. package/dist-engine-src/src/transaction/bench_support.rs +0 -407
  259. package/dist-engine-src/src/transaction/commit.rs +0 -1592
  260. package/dist-engine-src/src/transaction/context.rs +0 -1653
  261. package/dist-engine-src/src/transaction/mod.rs +0 -24
  262. package/dist-engine-src/src/transaction/normalization.rs +0 -877
  263. package/dist-engine-src/src/transaction/prep.rs +0 -37
  264. package/dist-engine-src/src/transaction/schema_resolver.rs +0 -163
  265. package/dist-engine-src/src/transaction/staging.rs +0 -1525
  266. package/dist-engine-src/src/transaction/types.rs +0 -403
  267. package/dist-engine-src/src/transaction/validation.rs +0 -5766
  268. package/dist-engine-src/src/untracked_state/codec.rs +0 -615
  269. package/dist-engine-src/src/untracked_state/context.rs +0 -98
  270. package/dist-engine-src/src/untracked_state/materialization.rs +0 -63
  271. package/dist-engine-src/src/untracked_state/mod.rs +0 -15
  272. package/dist-engine-src/src/untracked_state/storage.rs +0 -898
  273. package/dist-engine-src/src/untracked_state/types.rs +0 -146
  274. package/dist-engine-src/src/wasm/mod.rs +0 -60
@@ -1,780 +0,0 @@
1
- use crate::{validate_lix_schema, validate_lix_schema_definition};
2
- use serde_json::json;
3
-
4
- #[test]
5
- fn validate_lix_schema_definition_passes_for_valid_schema() {
6
- let valid_schema = json!({
7
- "x-lix-key": "test_entity",
8
- "type": "object",
9
- "properties": {
10
- "id": { "type": "string" }
11
- },
12
- "additionalProperties": false
13
- });
14
-
15
- assert!(validate_lix_schema_definition(&valid_schema).is_ok());
16
- }
17
-
18
- #[test]
19
- fn validate_lix_schema_definition_rejects_unprojectable_entity_properties() {
20
- let schema = json!({
21
- "x-lix-key": "test_entity",
22
- "type": "object",
23
- "properties": {
24
- "id": { "type": "string" },
25
- "kind": {}
26
- },
27
- "required": ["id", "kind"],
28
- "additionalProperties": false
29
- });
30
-
31
- let err = validate_lix_schema_definition(&schema).unwrap_err();
32
- assert!(
33
- err.to_string().contains("property '/kind'"),
34
- "error should identify the unprojectable property: {err:?}"
35
- );
36
- assert!(
37
- err.to_string().contains("SQL-projectable JSON Schema type"),
38
- "error should explain the projection requirement: {err:?}"
39
- );
40
- }
41
-
42
- #[test]
43
- fn validate_lix_schema_definition_rejects_reserved_lix_property_prefixes() {
44
- for property_name in ["lixcol_entity_pk", "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
-
67
- #[test]
68
- fn validate_lix_schema_definition_throws_for_invalid_schema() {
69
- let invalid_schema = json!({
70
- "type": "object",
71
- "properties": {
72
- "id": { "type": "string" }
73
- },
74
- "additionalProperties": false
75
- });
76
-
77
- let err = validate_lix_schema_definition(&invalid_schema).unwrap_err();
78
- assert!(err.to_string().contains("Invalid Lix schema definition"));
79
- }
80
-
81
- #[test]
82
- fn validate_lix_schema_validates_both_schema_and_data_successfully() {
83
- let schema = json!({
84
- "x-lix-key": "user",
85
- "type": "object",
86
- "properties": {
87
- "id": { "type": "string" },
88
- "name": { "type": "string" }
89
- },
90
- "required": ["id", "name"],
91
- "additionalProperties": false
92
- });
93
-
94
- let valid_data = json!({
95
- "id": "123",
96
- "name": "John Doe"
97
- });
98
-
99
- assert!(validate_lix_schema(&schema, &valid_data).is_ok());
100
- }
101
-
102
- #[test]
103
- fn validate_lix_schema_throws_when_schema_is_invalid() {
104
- let invalid_schema = json!({
105
- "type": "object",
106
- "properties": {
107
- "id": { "type": "string" }
108
- },
109
- "additionalProperties": false
110
- });
111
-
112
- let data = json!({ "id": "123" });
113
-
114
- let err = validate_lix_schema(&invalid_schema, &data).unwrap_err();
115
- assert!(err.to_string().contains("Invalid Lix schema definition"));
116
- }
117
-
118
- #[test]
119
- fn validate_lix_schema_throws_when_data_does_not_match_schema() {
120
- let schema = json!({
121
- "x-lix-key": "user",
122
- "type": "object",
123
- "properties": {
124
- "id": { "type": "string" },
125
- "name": { "type": "string" }
126
- },
127
- "required": ["id", "name"],
128
- "additionalProperties": false
129
- });
130
-
131
- let invalid_data = json!({ "id": "123" });
132
-
133
- let err = validate_lix_schema(&schema, &invalid_data).unwrap_err();
134
- assert!(err.to_string().contains("Data validation failed"));
135
- }
136
-
137
- #[test]
138
- fn validate_lix_schema_definition_rejects_when_additional_properties_missing() {
139
- let schema = json!({
140
- "x-lix-key": "user",
141
- "type": "object",
142
- "properties": {
143
- "id": { "type": "string" }
144
- },
145
- "required": ["id"]
146
- });
147
-
148
- let err = validate_lix_schema_definition(&schema).unwrap_err();
149
- assert!(err.to_string().contains("Invalid Lix schema definition"));
150
- }
151
-
152
- #[test]
153
- fn additional_properties_must_be_false() {
154
- let schema_with_additional_props = json!({
155
- "x-lix-key": "user",
156
- "type": "object",
157
- "properties": {
158
- "id": { "type": "string" },
159
- "name": { "type": "string" }
160
- },
161
- "required": ["id", "name"],
162
- "additionalProperties": true
163
- });
164
-
165
- assert!(validate_lix_schema_definition(&schema_with_additional_props).is_err());
166
-
167
- let valid_schema = json!({
168
- "x-lix-key": "user",
169
- "type": "object",
170
- "properties": {
171
- "id": { "type": "string" },
172
- "name": { "type": "string" }
173
- },
174
- "required": ["id", "name"],
175
- "additionalProperties": false
176
- });
177
-
178
- assert!(validate_lix_schema_definition(&valid_schema).is_ok());
179
-
180
- let data = json!({
181
- "id": "123",
182
- "name": "John Doe",
183
- "extraField": "not allowed"
184
- });
185
-
186
- let err = validate_lix_schema(&valid_schema, &data).unwrap_err();
187
- assert!(err.to_string().contains("Data validation failed"));
188
- }
189
-
190
- #[test]
191
- fn validate_lix_schema_definition_rejects_missing_primary_key_properties() {
192
- let schema = json!({
193
- "x-lix-key": "missing_pk",
194
- "type": "object",
195
- "properties": {
196
- "value": { "type": "string" }
197
- },
198
- "required": ["value"],
199
- "x-lix-primary-key": ["/entity_pk"],
200
- "additionalProperties": false
201
- });
202
-
203
- let err = validate_lix_schema_definition(&schema).unwrap_err();
204
- assert!(err
205
- .to_string()
206
- .contains("x-lix-primary-key references missing property"));
207
- }
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
-
250
- #[test]
251
- fn validate_lix_schema_definition_rejects_missing_unique_constraint_properties() {
252
- let schema = json!({
253
- "x-lix-key": "missing_unique",
254
- "type": "object",
255
- "properties": {
256
- "value": { "type": "string" }
257
- },
258
- "x-lix-unique": [["/entity_pk", "/value"]],
259
- "additionalProperties": false
260
- });
261
-
262
- let err = validate_lix_schema_definition(&schema).unwrap_err();
263
- assert!(err
264
- .to_string()
265
- .contains("x-lix-unique references missing property"));
266
- }
267
-
268
- #[test]
269
- fn x_key_is_required() {
270
- let schema = json!({
271
- "type": "object",
272
- "x-lix-key": null,
273
- "properties": {
274
- "name": { "type": "string" }
275
- },
276
- "required": ["name"],
277
- "additionalProperties": false
278
- });
279
-
280
- assert!(validate_lix_schema_definition(&schema).is_err());
281
- }
282
-
283
- #[test]
284
- fn x_lix_key_must_be_snake_case() {
285
- let base_schema = json!({
286
- "type": "object",
287
- "properties": {
288
- "name": { "type": "string" }
289
- },
290
- "required": ["name"],
291
- "additionalProperties": false
292
- });
293
-
294
- let invalid_keys = [
295
- "Invalid-Key!",
296
- "also.invalid",
297
- "123starts_with_number",
298
- "contains space",
299
- "camelCaseKey",
300
- "UPPER_CASE",
301
- "mixed-Case_Value",
302
- ];
303
- for key in invalid_keys {
304
- let mut schema = base_schema.clone();
305
- schema["x-lix-key"] = json!(key);
306
- assert!(validate_lix_schema_definition(&schema).is_err());
307
- }
308
-
309
- let valid_keys = ["abc", "abc123", "abc_123", "a", "snake_case_key"];
310
- for key in valid_keys {
311
- let mut schema = base_schema.clone();
312
- schema["x-lix-key"] = json!(key);
313
- assert!(validate_lix_schema_definition(&schema).is_ok());
314
- }
315
- }
316
-
317
- #[test]
318
- fn x_lix_unique_is_optional() {
319
- let schema = json!({
320
- "type": "object",
321
- "x-lix-key": "mock",
322
- "properties": {
323
- "name": { "type": "string" }
324
- },
325
- "required": ["name"],
326
- "additionalProperties": false
327
- });
328
-
329
- assert!(validate_lix_schema_definition(&schema).is_ok());
330
- }
331
-
332
- #[test]
333
- fn x_lix_unique_must_be_array_of_arrays_when_present() {
334
- let schema = json!({
335
- "type": "object",
336
- "x-lix-key": "mock",
337
- "x-lix-unique": [["/id"], ["/name", "/age"]],
338
- "properties": {
339
- "id": { "type": "string" },
340
- "name": { "type": "string" },
341
- "age": { "type": "number" }
342
- },
343
- "required": ["id", "name", "age"],
344
- "additionalProperties": false
345
- });
346
-
347
- assert!(validate_lix_schema_definition(&schema).is_ok());
348
- }
349
-
350
- #[test]
351
- fn x_lix_unique_fails_with_invalid_structure() {
352
- let schema = json!({
353
- "type": "object",
354
- "x-lix-key": "mock",
355
- "x-lix-unique": ["/id", "/name"],
356
- "properties": {
357
- "id": { "type": "string" },
358
- "name": { "type": "string" }
359
- },
360
- "required": ["id", "name"],
361
- "additionalProperties": false
362
- });
363
-
364
- assert!(validate_lix_schema_definition(&schema).is_err());
365
- }
366
-
367
- #[test]
368
- fn x_lix_primary_key_must_include_at_least_one_unique_pointer() {
369
- let base_schema = json!({
370
- "type": "object",
371
- "x-lix-key": "mock",
372
- "properties": {
373
- "id": { "type": "string" }
374
- },
375
- "required": ["id"],
376
- "additionalProperties": false
377
- });
378
-
379
- let mut empty_pk = base_schema.clone();
380
- empty_pk["x-lix-primary-key"] = json!([]);
381
- assert!(validate_lix_schema_definition(&empty_pk).is_err());
382
-
383
- let mut duplicate_pk = base_schema.clone();
384
- duplicate_pk["x-lix-primary-key"] = json!(["/id", "/id"]);
385
- assert!(validate_lix_schema_definition(&duplicate_pk).is_err());
386
-
387
- let mut valid_pk = base_schema.clone();
388
- valid_pk["x-lix-primary-key"] = json!(["/id"]);
389
- assert!(validate_lix_schema_definition(&valid_pk).is_ok());
390
- }
391
-
392
- #[test]
393
- fn x_lix_unique_groups_must_include_unique_pointers() {
394
- let base_schema = json!({
395
- "type": "object",
396
- "x-lix-key": "mock",
397
- "properties": {
398
- "id": { "type": "string" },
399
- "email": { "type": "string" }
400
- },
401
- "required": ["id", "email"],
402
- "additionalProperties": false
403
- });
404
-
405
- let mut empty_group = base_schema.clone();
406
- empty_group["x-lix-unique"] = json!([[]]);
407
- assert!(validate_lix_schema_definition(&empty_group).is_err());
408
-
409
- let mut duplicate_pointers = base_schema.clone();
410
- duplicate_pointers["x-lix-unique"] = json!([["/email", "/email"]]);
411
- assert!(validate_lix_schema_definition(&duplicate_pointers).is_err());
412
-
413
- let mut valid_unique = base_schema.clone();
414
- valid_unique["x-lix-unique"] = json!([["/email"]]);
415
- assert!(validate_lix_schema_definition(&valid_unique).is_ok());
416
- }
417
-
418
- #[test]
419
- fn x_lix_entity_views_is_rejected() {
420
- let schema = json!({
421
- "type": "object",
422
- "x-lix-key": "mock",
423
- "x-lix-entity-views": ["lix_state", "lix_state_by_branch"],
424
- "properties": {
425
- "name": { "type": "string" }
426
- },
427
- "required": ["name"],
428
- "additionalProperties": false
429
- });
430
-
431
- let err =
432
- validate_lix_schema_definition(&schema).expect_err("x-lix-entity-views should be rejected");
433
- assert!(err.to_string().contains("x-lix-entity-views"));
434
- }
435
-
436
- #[test]
437
- fn x_lix_primary_key_is_optional() {
438
- let schema = json!({
439
- "type": "object",
440
- "x-lix-key": "mock",
441
- "properties": {
442
- "name": { "type": "string" }
443
- },
444
- "required": ["name"],
445
- "additionalProperties": false
446
- });
447
-
448
- assert!(validate_lix_schema_definition(&schema).is_ok());
449
- }
450
-
451
- #[test]
452
- fn x_lix_primary_key_must_be_array_of_strings_when_present() {
453
- let schema = json!({
454
- "type": "object",
455
- "x-lix-key": "mock",
456
- "x-lix-primary-key": ["/id", "/branch"],
457
- "properties": {
458
- "id": { "type": "string" },
459
- "branch": { "type": "string" },
460
- "name": { "type": "string" }
461
- },
462
- "required": ["id", "branch", "name"],
463
- "additionalProperties": false
464
- });
465
-
466
- assert!(validate_lix_schema_definition(&schema).is_ok());
467
- }
468
-
469
- #[test]
470
- fn x_lix_foreign_keys_is_optional() {
471
- let schema = json!({
472
- "type": "object",
473
- "x-lix-key": "blog_post",
474
- "properties": {
475
- "id": { "type": "string" },
476
- "author_id": { "type": "string" }
477
- },
478
- "required": ["id", "author_id"],
479
- "additionalProperties": false
480
- });
481
-
482
- assert!(validate_lix_schema_definition(&schema).is_ok());
483
- }
484
-
485
- #[test]
486
- fn x_lix_foreign_keys_with_valid_structure() {
487
- let schema = json!({
488
- "type": "object",
489
- "x-lix-key": "blog_post",
490
- "x-lix-foreign-keys": [
491
- {
492
- "properties": ["/author_id"],
493
- "references": {
494
- "schemaKey": "user_profile",
495
- "properties": ["/id"]
496
- }
497
- },
498
- {
499
- "properties": ["/category_id"],
500
- "references": {
501
- "schemaKey": "post_category",
502
- "properties": ["/id"]
503
- }
504
- }
505
- ],
506
- "properties": {
507
- "id": { "type": "string" },
508
- "author_id": { "type": "string" },
509
- "category_id": { "type": "string" }
510
- },
511
- "required": ["id", "author_id", "category_id"],
512
- "additionalProperties": false
513
- });
514
-
515
- assert!(validate_lix_schema_definition(&schema).is_ok());
516
- }
517
-
518
- #[test]
519
- fn x_lix_foreign_keys_reject_duplicate_pointers() {
520
- let schema = json!({
521
- "type": "object",
522
- "x-lix-key": "invalid_fk_duplicates",
523
- "x-lix-foreign-keys": [
524
- {
525
- "properties": ["/local", "/local"],
526
- "references": {
527
- "schemaKey": "remote_schema",
528
- "properties": ["/id", "/branch"]
529
- }
530
- }
531
- ],
532
- "properties": {
533
- "local": { "type": "string" }
534
- },
535
- "required": ["local"],
536
- "additionalProperties": false
537
- });
538
-
539
- assert!(validate_lix_schema_definition(&schema).is_err());
540
- }
541
-
542
- #[test]
543
- fn x_lix_foreign_keys_fails_without_required_fields() {
544
- let schema = json!({
545
- "type": "object",
546
- "x-lix-key": "blog_post",
547
- "x-lix-foreign-keys": [
548
- {
549
- "properties": ["/author_id"]
550
- }
551
- ],
552
- "properties": {
553
- "id": { "type": "string" },
554
- "author_id": { "type": "string" }
555
- },
556
- "required": ["id", "author_id"],
557
- "additionalProperties": false
558
- });
559
-
560
- assert!(validate_lix_schema_definition(&schema).is_err());
561
- }
562
-
563
- #[test]
564
- fn x_lix_foreign_keys_use_schema_key_identity_only() {
565
- let schema = json!({
566
- "type": "object",
567
- "x-lix-key": "comment",
568
- "x-lix-foreign-keys": [
569
- {
570
- "properties": ["/post_id"],
571
- "references": {
572
- "schemaKey": "blog_post",
573
- "properties": ["/id"]
574
- }
575
- }
576
- ],
577
- "properties": {
578
- "id": { "type": "string" },
579
- "post_id": { "type": "string" }
580
- },
581
- "required": ["id", "post_id"],
582
- "additionalProperties": false
583
- });
584
-
585
- assert!(validate_lix_schema_definition(&schema).is_ok());
586
- }
587
-
588
- #[test]
589
- fn x_lix_foreign_keys_rejects_mode_field() {
590
- let schema = json!({
591
- "type": "object",
592
- "x-lix-key": "child_entity",
593
- "x-lix-primary-key": ["/id"],
594
- "x-lix-foreign-keys": [
595
- {
596
- "properties": ["/parent_id"],
597
- "references": { "schemaKey": "parent_entity", "properties": ["/id"] },
598
- "mode": "materialized"
599
- }
600
- ],
601
- "properties": {
602
- "id": { "type": "string" },
603
- "parent_id": { "type": "string" }
604
- },
605
- "required": ["id", "parent_id"],
606
- "additionalProperties": false
607
- });
608
-
609
- let err = validate_lix_schema_definition(&schema).expect_err("mode should be rejected");
610
- assert!(err.to_string().contains("mode"));
611
- }
612
-
613
- #[test]
614
- fn x_lix_foreign_keys_rejects_scope_field() {
615
- let schema = json!({
616
- "type": "object",
617
- "x-lix-key": "child_entity",
618
- "x-lix-primary-key": ["/id"],
619
- "x-lix-foreign-keys": [
620
- {
621
- "properties": ["/parent_id"],
622
- "references": { "schemaKey": "parent_entity", "properties": ["/id"] },
623
- "scope": ["file_id"]
624
- }
625
- ],
626
- "properties": {
627
- "id": { "type": "string" },
628
- "parent_id": { "type": "string" }
629
- },
630
- "required": ["id", "parent_id"],
631
- "additionalProperties": false
632
- });
633
-
634
- let err = validate_lix_schema_definition(&schema).expect_err("scope should be rejected");
635
- assert!(err.to_string().contains("scope"));
636
- }
637
-
638
- #[test]
639
- fn x_lix_state_foreign_keys_with_ordered_state_address_tuple() {
640
- let schema = json!({
641
- "type": "object",
642
- "x-lix-key": "label_assignment",
643
- "x-lix-state-foreign-keys": [
644
- ["/target_entity_pk", "/target_schema_key", "/target_file_id"]
645
- ],
646
- "x-lix-foreign-keys": [
647
- {
648
- "properties": ["/label_id"],
649
- "references": {
650
- "schemaKey": "lix_label",
651
- "properties": ["/id"]
652
- }
653
- }
654
- ],
655
- "properties": {
656
- "target_entity_pk": {
657
- "type": "array",
658
- "items": { "type": "string" },
659
- "minItems": 1
660
- },
661
- "target_schema_key": { "type": "string" },
662
- "target_file_id": { "type": ["string", "null"] },
663
- "label_id": { "type": "string" }
664
- },
665
- "required": ["target_entity_pk", "target_schema_key", "target_file_id", "label_id"],
666
- "additionalProperties": false
667
- });
668
-
669
- assert!(validate_lix_schema_definition(&schema).is_ok());
670
- }
671
-
672
- #[test]
673
- fn x_lix_state_foreign_keys_rejects_wrong_tuple_order_by_type() {
674
- let schema = json!({
675
- "type": "object",
676
- "x-lix-key": "bad_label_assignment",
677
- "x-lix-state-foreign-keys": [
678
- ["/target_schema_key", "/target_entity_pk", "/target_file_id"]
679
- ],
680
- "properties": {
681
- "target_entity_pk": {
682
- "type": "array",
683
- "items": { "type": "string" },
684
- "minItems": 1
685
- },
686
- "target_schema_key": { "type": "string" },
687
- "target_file_id": { "type": ["string", "null"] }
688
- },
689
- "required": ["target_entity_pk", "target_schema_key", "target_file_id"],
690
- "additionalProperties": false
691
- });
692
-
693
- let err =
694
- validate_lix_schema_definition(&schema).expect_err("wrong tuple order should be rejected");
695
- assert!(
696
- err.message.contains("[entity_pk, schema_key, file_id]"),
697
- "unexpected error: {err:?}"
698
- );
699
- }
700
-
701
- #[test]
702
- fn x_lix_state_foreign_keys_requires_address_tuple_properties() {
703
- let schema = json!({
704
- "type": "object",
705
- "x-lix-key": "optional_label_assignment",
706
- "x-lix-state-foreign-keys": [
707
- ["/target_entity_pk", "/target_schema_key", "/target_file_id"]
708
- ],
709
- "properties": {
710
- "target_entity_pk": {
711
- "type": "array",
712
- "items": { "type": "string" },
713
- "minItems": 1
714
- },
715
- "target_schema_key": { "type": "string" },
716
- "target_file_id": { "type": ["string", "null"] }
717
- },
718
- "required": ["target_entity_pk", "target_schema_key"],
719
- "additionalProperties": false
720
- });
721
-
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
- );
728
- }
729
-
730
- #[test]
731
- fn x_lix_foreign_keys_treat_schema_keys_literally() {
732
- let schema = json!({
733
- "type": "object",
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
- ],
744
- "properties": {
745
- "label_id": { "type": "string" }
746
- },
747
- "required": ["label_id"],
748
- "additionalProperties": false
749
- });
750
-
751
- assert!(validate_lix_schema_definition(&schema).is_ok());
752
- }
753
-
754
- #[test]
755
- fn x_lix_default_accepts_valid_cel_expression() {
756
- let schema = json!({
757
- "type": "object",
758
- "x-lix-key": "mock",
759
- "properties": {
760
- "id": { "type": "string", "x-lix-default": "lix_uuid_v7()" }
761
- },
762
- "additionalProperties": false
763
- });
764
-
765
- assert!(validate_lix_schema_definition(&schema).is_ok());
766
- }
767
-
768
- #[test]
769
- fn x_lix_default_rejects_invalid_cel_expression() {
770
- let schema = json!({
771
- "type": "object",
772
- "x-lix-key": "mock",
773
- "properties": {
774
- "id": { "type": "string", "x-lix-default": "lix_uuid_v7(" }
775
- },
776
- "additionalProperties": false
777
- });
778
-
779
- assert!(validate_lix_schema_definition(&schema).is_err());
780
- }