@lix-js/sdk 0.6.0-preview.3 → 0.6.0-preview.5
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/README.md +1 -1
- package/SKILL.md +105 -65
- package/dist/engine-wasm/index.js +4 -4
- package/dist/engine-wasm/wasm/lix_engine.d.ts +30 -6
- package/dist/engine-wasm/wasm/lix_engine.js +187 -117
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +14 -8
- package/dist/generated/builtin-schemas.d.ts +69 -69
- package/dist/generated/builtin-schemas.js +94 -94
- package/dist/open-lix.d.ts +42 -28
- package/dist/open-lix.js +49 -10
- package/dist/sqlite/index.js +86 -30
- package/dist-engine-src/README.md +3 -3
- package/dist-engine-src/src/backend/capabilities.rs +67 -0
- package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
- package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
- package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
- package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
- package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
- package/dist-engine-src/src/backend/conformance/model.rs +28 -0
- package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
- package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
- package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
- package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
- package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
- package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
- package/dist-engine-src/src/backend/conformance/write.rs +16 -0
- package/dist-engine-src/src/backend/error.rs +94 -0
- package/dist-engine-src/src/backend/in_memory.rs +670 -0
- package/dist-engine-src/src/backend/mod.rs +36 -9
- package/dist-engine-src/src/backend/predicate.rs +80 -0
- package/dist-engine-src/src/backend/traits.rs +260 -0
- package/dist-engine-src/src/backend/types.rs +224 -81
- package/dist-engine-src/src/binary_cas/context.rs +8 -8
- package/dist-engine-src/src/binary_cas/kv.rs +234 -259
- package/dist-engine-src/src/{version → branch}/context.rs +12 -12
- package/dist-engine-src/src/branch/lifecycle.rs +221 -0
- package/dist-engine-src/src/branch/mod.rs +13 -0
- package/dist-engine-src/src/branch/refs.rs +321 -0
- package/dist-engine-src/src/branch/stage_rows.rs +67 -0
- package/dist-engine-src/src/branch/types.rs +21 -0
- package/dist-engine-src/src/catalog/context.rs +18 -18
- package/dist-engine-src/src/catalog/snapshot.rs +8 -8
- package/dist-engine-src/src/changelog/bench_support.rs +785 -0
- package/dist-engine-src/src/changelog/change.rs +1 -0
- package/dist-engine-src/src/changelog/codec.rs +497 -0
- package/dist-engine-src/src/changelog/commit.rs +1 -0
- package/dist-engine-src/src/changelog/context.rs +1614 -0
- package/dist-engine-src/src/changelog/mod.rs +29 -0
- package/dist-engine-src/src/changelog/store.rs +163 -0
- package/dist-engine-src/src/changelog/test_support.rs +54 -0
- package/dist-engine-src/src/changelog/types.rs +213 -0
- package/dist-engine-src/src/commit_graph/context.rs +317 -274
- package/dist-engine-src/src/commit_graph/mod.rs +2 -4
- package/dist-engine-src/src/commit_graph/types.rs +22 -42
- package/dist-engine-src/src/commit_graph/walker.rs +133 -103
- package/dist-engine-src/src/common/error.rs +52 -18
- package/dist-engine-src/src/common/identity.rs +2 -2
- package/dist-engine-src/src/common/mod.rs +1 -1
- package/dist-engine-src/src/domain.rs +42 -46
- package/dist-engine-src/src/engine.rs +74 -96
- package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
- package/dist-engine-src/src/functions/context.rs +56 -52
- package/dist-engine-src/src/functions/state.rs +51 -52
- package/dist-engine-src/src/init.rs +288 -154
- package/dist-engine-src/src/json_store/context.rs +15 -266
- package/dist-engine-src/src/json_store/mod.rs +26 -0
- package/dist-engine-src/src/json_store/store.rs +103 -718
- package/dist-engine-src/src/json_store/types.rs +4 -9
- package/dist-engine-src/src/lib.rs +49 -19
- package/dist-engine-src/src/live_state/context.rs +654 -790
- package/dist-engine-src/src/live_state/mod.rs +9 -3
- package/dist-engine-src/src/live_state/overlay.rs +4 -4
- package/dist-engine-src/src/live_state/types.rs +30 -21
- package/dist-engine-src/src/live_state/visibility.rs +514 -71
- package/dist-engine-src/src/plugin/install.rs +48 -48
- package/dist-engine-src/src/plugin/manifest.rs +7 -7
- package/dist-engine-src/src/plugin/materializer.rs +0 -275
- package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
- package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
- package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
- package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
- package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
- package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
- package/dist-engine-src/src/schema/compatibility.rs +11 -11
- package/dist-engine-src/src/schema/definition.json +2 -2
- package/dist-engine-src/src/schema/definition.rs +5 -5
- package/dist-engine-src/src/schema/key.rs +3 -3
- package/dist-engine-src/src/schema/mod.rs +1 -1
- package/dist-engine-src/src/schema/tests.rs +18 -18
- package/dist-engine-src/src/session/context.rs +819 -124
- package/dist-engine-src/src/session/create_branch.rs +94 -0
- package/dist-engine-src/src/session/execute.rs +260 -57
- package/dist-engine-src/src/session/merge/analysis.rs +9 -3
- package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
- package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
- package/dist-engine-src/src/session/merge/mod.rs +5 -6
- package/dist-engine-src/src/session/merge/stats.rs +7 -11
- package/dist-engine-src/src/session/mod.rs +19 -16
- package/dist-engine-src/src/session/switch_branch.rs +113 -0
- package/dist-engine-src/src/session/transaction.rs +557 -0
- package/dist-engine-src/src/sql2/bind/classify.rs +102 -0
- package/dist-engine-src/src/sql2/bind/error.rs +5 -0
- package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
- package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
- package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +98 -3
- package/dist-engine-src/src/sql2/bind/read.rs +65 -0
- package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
- package/dist-engine-src/src/sql2/bind/table.rs +273 -0
- package/dist-engine-src/src/sql2/bind/write.rs +86 -0
- package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
- package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
- package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
- package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
- package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
- package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
- package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
- package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
- package/dist-engine-src/src/sql2/context.rs +36 -30
- package/dist-engine-src/src/sql2/error.rs +4 -5
- package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
- package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
- package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
- package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
- package/dist-engine-src/src/sql2/exec/write.rs +661 -0
- package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
- package/dist-engine-src/src/sql2/history_projection.rs +8 -8
- package/dist-engine-src/src/sql2/history_route.rs +35 -31
- package/dist-engine-src/src/sql2/mod.rs +30 -24
- package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
- package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
- package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
- package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
- package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
- package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
- package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
- package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
- package/dist-engine-src/src/sql2/plan/write.rs +147 -0
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
- package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
- package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
- package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
- package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
- package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
- package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
- package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
- package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
- package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
- package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
- package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
- package/dist-engine-src/src/sql2/read_only.rs +2 -2
- package/dist-engine-src/src/sql2/session.rs +47 -96
- package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
- package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
- package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
- package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
- package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
- package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
- package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
- package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
- package/dist-engine-src/src/storage/conformance.rs +399 -0
- package/dist-engine-src/src/storage/context.rs +552 -288
- package/dist-engine-src/src/storage/mod.rs +48 -10
- package/dist-engine-src/src/storage/point.rs +440 -0
- package/dist-engine-src/src/storage/read_scope.rs +43 -64
- package/dist-engine-src/src/storage/reader.rs +867 -0
- package/dist-engine-src/src/storage/scan.rs +784 -0
- package/dist-engine-src/src/storage/spaces.rs +236 -0
- package/dist-engine-src/src/storage/stats.rs +80 -0
- package/dist-engine-src/src/storage/write_set.rs +962 -0
- package/dist-engine-src/src/storage_bench.rs +136 -4828
- package/dist-engine-src/src/test_support.rs +360 -138
- package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
- package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
- package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
- package/dist-engine-src/src/tracked_state/context.rs +1927 -993
- package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
- package/dist-engine-src/src/tracked_state/merge.rs +74 -88
- package/dist-engine-src/src/tracked_state/mod.rs +19 -16
- package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
- package/dist-engine-src/src/tracked_state/storage.rs +243 -191
- package/dist-engine-src/src/tracked_state/tree.rs +247 -371
- package/dist-engine-src/src/tracked_state/types.rs +49 -42
- package/dist-engine-src/src/transaction/bench_support.rs +407 -0
- package/dist-engine-src/src/transaction/commit.rs +821 -713
- package/dist-engine-src/src/transaction/context.rs +705 -600
- package/dist-engine-src/src/transaction/mod.rs +13 -2
- package/dist-engine-src/src/transaction/normalization.rs +63 -76
- package/dist-engine-src/src/transaction/prep.rs +13 -13
- package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
- package/dist-engine-src/src/transaction/staging.rs +228 -434
- package/dist-engine-src/src/transaction/types.rs +41 -98
- package/dist-engine-src/src/transaction/validation.rs +382 -446
- package/dist-engine-src/src/untracked_state/codec.rs +337 -29
- package/dist-engine-src/src/untracked_state/context.rs +7 -7
- package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
- package/dist-engine-src/src/untracked_state/mod.rs +1 -1
- package/dist-engine-src/src/untracked_state/storage.rs +659 -157
- package/dist-engine-src/src/untracked_state/types.rs +21 -21
- package/package.json +71 -68
- package/dist-engine-src/src/backend/kv.rs +0 -358
- package/dist-engine-src/src/backend/testing.rs +0 -658
- package/dist-engine-src/src/commit_store/codec.rs +0 -887
- package/dist-engine-src/src/commit_store/context.rs +0 -944
- package/dist-engine-src/src/commit_store/materialization.rs +0 -84
- package/dist-engine-src/src/commit_store/mod.rs +0 -16
- package/dist-engine-src/src/commit_store/storage.rs +0 -600
- package/dist-engine-src/src/commit_store/types.rs +0 -215
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
- package/dist-engine-src/src/session/create_version.rs +0 -88
- package/dist-engine-src/src/session/merge/apply.rs +0 -23
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
- package/dist-engine-src/src/session/switch_version.rs +0 -109
- package/dist-engine-src/src/sql2/classify.rs +0 -182
- package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
- package/dist-engine-src/src/sql2/execute.rs +0 -3440
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
- package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
- package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -166
- package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -25
- package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
- package/dist-engine-src/src/sql2/version_scope.rs +0 -394
- package/dist-engine-src/src/storage/types.rs +0 -501
- package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
- package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
- package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
- package/dist-engine-src/src/version/lifecycle.rs +0 -221
- package/dist-engine-src/src/version/mod.rs +0 -13
- package/dist-engine-src/src/version/refs.rs +0 -330
- package/dist-engine-src/src/version/stage_rows.rs +0 -67
- package/dist-engine-src/src/version/types.rs +0 -21
package/README.md
CHANGED
|
@@ -6,4 +6,4 @@ WASM-backed JavaScript SDK for Lix.
|
|
|
6
6
|
|
|
7
7
|
If you are an AI coding agent using this package, read [`SKILL.md`](./SKILL.md) before building examples, demos, tests, or applications with `@lix-js/sdk`.
|
|
8
8
|
|
|
9
|
-
The skill documents the current preview API, recommended SQLite backend setup, schema registration flow, entity-table writes,
|
|
9
|
+
The skill documents the current preview API, recommended SQLite backend setup, schema registration flow, entity-table writes, branch workflows, merge behavior, and known sharp edges.
|
package/SKILL.md
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lix-js-sdk
|
|
3
|
-
description: Use this skill when building examples, demos, tests, or applications with @lix-js/sdk: opening a Lix, registering schemas, writing entities through generated SQL tables, creating named
|
|
3
|
+
description: Use this skill when building examples, demos, tests, or applications with @lix-js/sdk: opening a Lix, registering schemas, writing entities through generated SQL tables, creating named branches, merging, and querying change history.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Lix JS SDK Skill
|
|
7
7
|
|
|
8
8
|
## What Is Lix
|
|
9
9
|
|
|
10
|
-
Lix is an embeddable
|
|
10
|
+
Lix is an embeddable branch control system for structured application state. It gives apps named branches, merge, and an immutable SQL-queryable change journal without asking the app to build those systems from scratch.
|
|
11
11
|
|
|
12
12
|
Current `@lix-js/sdk` capabilities:
|
|
13
13
|
|
|
14
14
|
- Register JSON schemas as tracked entity tables.
|
|
15
15
|
- Read and write entities through generated SQL tables.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Group related writes in explicit transactions so they commit once.
|
|
17
|
+
- Create named branches of state and write/read across branches.
|
|
18
|
+
- Merge one branch into the active branch.
|
|
18
19
|
- Query `lix_change` for history, audit, activity feeds, and undo-style features.
|
|
19
|
-
- Store files as bytes with `lix_file` and
|
|
20
|
+
- Store files as bytes with `lix_file` and branch them like other entities.
|
|
20
21
|
|
|
21
22
|
Product direction:
|
|
22
23
|
|
|
23
|
-
- Lix is designed to
|
|
24
|
-
- Parser plugins that turn file contents into app entities are not shipped through the JS SDK yet. Do not promise this behavior in demos. Today, `lix_file`
|
|
24
|
+
- Lix is designed to track files of any kind by parsing them into typed entities on write.
|
|
25
|
+
- Parser plugins that turn file contents into app entities are not shipped through the JS SDK yet. Do not promise this behavior in demos. Today, `lix_file` tracks bytes, while app entities are modeled directly through registered schemas.
|
|
25
26
|
|
|
26
|
-
Every row in every registered schema is a tracked entity. Merge granularity is currently per-entity, not per-field: two
|
|
27
|
+
Every row in every registered schema is a tracked entity. Merge granularity is currently per-entity, not per-field: two branches editing different rows merge cleanly; two branches editing the same row conflict, even if the fields are disjoint. Model collaborative domains as many small entities, such as sections, blocks, paragraphs, message keys, or line items.
|
|
27
28
|
|
|
28
|
-
Use Lix vocabulary in user-facing copy.
|
|
29
|
+
Use Lix vocabulary in user-facing copy. Lix uses **branch** for named lines of work.
|
|
29
30
|
|
|
30
31
|
## When To Use This Skill
|
|
31
32
|
|
|
@@ -34,8 +35,9 @@ Use this skill when you need to write or debug consumer code using `@lix-js/sdk`
|
|
|
34
35
|
- Opening a persistent `.lix` file.
|
|
35
36
|
- Registering schemas.
|
|
36
37
|
- Writing and reading generated SQL entity tables.
|
|
38
|
+
- Grouping imports, migrations, and batch writes into one transaction.
|
|
37
39
|
- Reading `execute()` results.
|
|
38
|
-
- Creating, switching, previewing, and merging
|
|
40
|
+
- Creating, switching, previewing, and merging branches.
|
|
39
41
|
- Querying history through `lix_change`.
|
|
40
42
|
- Building app demos, examples, smoke tests, or product flows around the SDK.
|
|
41
43
|
|
|
@@ -47,9 +49,10 @@ Do not use this skill for raw SQLite access, private engine/wasm internals, SDK
|
|
|
47
49
|
2. Open with `createBetterSqlite3Backend({ path })`; do not open `.lix` with raw SQLite.
|
|
48
50
|
3. Register a schema with `x-lix-key`, `x-lix-primary-key`, and `additionalProperties: false`.
|
|
49
51
|
4. Write rows through the generated table named by `x-lix-key`.
|
|
50
|
-
5. Use
|
|
51
|
-
6.
|
|
52
|
-
7.
|
|
52
|
+
5. Use `beginTransaction()` for imports, migrations, and multi-row writes that should be one commit.
|
|
53
|
+
6. Use `<schema>_by_branch` plus `lixcol_branch_id` for side-by-side branch reads/writes.
|
|
54
|
+
7. Query `lix_change` for audit/history instead of hand-rolling audit tables.
|
|
55
|
+
8. Wrap `mergeBranch()` in `try/catch` whenever conflicts are possible.
|
|
53
56
|
|
|
54
57
|
## Core Rules
|
|
55
58
|
|
|
@@ -58,11 +61,13 @@ Do not use this skill for raw SQLite access, private engine/wasm internals, SDK
|
|
|
58
61
|
- Use numbered SQL placeholders: `$1`, `$2`, `$3`; bare `?` is rejected.
|
|
59
62
|
- Use `lix_json($1)` when inserting JSON text into JSON-typed columns.
|
|
60
63
|
- Use scalar SQL functions `SELECT lix_uuid_v7()` and `SELECT lix_timestamp()` when consumer code needs Lix-generated UUID v7 ids or ISO timestamps. Do not call them as table functions with `SELECT * FROM ...`.
|
|
64
|
+
- Use `beginTransaction()` for batch writes. One `lix.execute()` write is one transaction and therefore one commit.
|
|
65
|
+
- Do not call `execute()` through the parent `lix` handle while a transaction is active; use the transaction handle for reads and writes until `commit()` or `rollback()`.
|
|
61
66
|
- Use stable, namespaced, lowercase schema keys like `acme_section`, not generic names like `task`.
|
|
62
67
|
- Always include `x-lix-primary-key` and `additionalProperties: false` on app schemas.
|
|
63
|
-
- Use
|
|
68
|
+
- Use branch names from the user's vocabulary, such as `"Marketing edit"` or `"Q3 pricing draft"`.
|
|
64
69
|
- Model concurrent-edit domains as collections of small rows because merge is per-row today.
|
|
65
|
-
- Prefer `
|
|
70
|
+
- Prefer `_by_branch` tables for demos, sync, agent inspection, and side-by-side diffs.
|
|
66
71
|
- Close handles in scripts and tests with `await lix.close()`.
|
|
67
72
|
|
|
68
73
|
## Install And Open
|
|
@@ -103,9 +108,9 @@ Use the version of this skill that ships with the installed `@lix-js/sdk` packag
|
|
|
103
108
|
|
|
104
109
|
Useful installed-package references:
|
|
105
110
|
|
|
106
|
-
- `dist-engine-src/src/sql2/
|
|
107
|
-
- `dist-engine-src/src/sql2/
|
|
108
|
-
- `dist-engine-src/src/sql2/
|
|
111
|
+
- `dist-engine-src/src/sql2/providers/entity.rs` - registered schema SQL surfaces.
|
|
112
|
+
- `dist-engine-src/src/sql2/providers/change.rs` - `lix_change` projection.
|
|
113
|
+
- `dist-engine-src/src/sql2/providers/branch.rs` - writable `lix_branch` surface.
|
|
109
114
|
- `dist-engine-src/src/transaction/validation.rs` - primary-key, unique, foreign-key, and shape validation.
|
|
110
115
|
- `dist-engine-src/src/schema/definition.json` - Lix schema-definition meta-schema.
|
|
111
116
|
- `dist-engine-src/src/schema/builtin/` - built-in entity table shapes.
|
|
@@ -203,6 +208,38 @@ Accessors return `undefined` when the cell kind does not match. Branch on `value
|
|
|
203
208
|
|
|
204
209
|
`Row` also has convenience methods when native JS values are enough: `get(name)`, `tryGet(name)`, `getAt(index)`, `toObject()`, and `toValueMap()`.
|
|
205
210
|
|
|
211
|
+
## Transactions
|
|
212
|
+
|
|
213
|
+
Use `beginTransaction()` whenever several writes belong to one logical operation: CSV imports, seed scripts, migrations, bulk updates, or multi-table changes. A write through `lix.execute()` opens and commits its own transaction, so thousands of separate `execute()` writes become thousands of commits. A transaction handle stages those writes and commits them together.
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
const tx = await lix.beginTransaction();
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
for (const note of notes) {
|
|
220
|
+
await tx.execute(
|
|
221
|
+
"INSERT INTO acme_note (id, title, done) VALUES ($1, $2, $3)",
|
|
222
|
+
[note.id, note.title, false],
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
await tx.commit();
|
|
227
|
+
} catch (error) {
|
|
228
|
+
await tx.rollback();
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Transaction rules:
|
|
234
|
+
|
|
235
|
+
- `tx.execute()` has the same result shape as `lix.execute()`.
|
|
236
|
+
- Writes are visible to later reads on the same transaction before commit.
|
|
237
|
+
- `commit()` makes the whole transaction durable as one commit.
|
|
238
|
+
- `rollback()` drops the staged writes.
|
|
239
|
+
- After `commit()` or `rollback()`, the transaction handle is closed and cannot be reused.
|
|
240
|
+
- A Lix handle allows one active transaction at a time. While it is active, use `tx.execute()` for reads and writes; parent-handle `lix.execute()` is rejected until the transaction closes.
|
|
241
|
+
- Do not use a callback-style transaction helper. The JS SDK mirrors the Rust SDK shape: explicitly `beginTransaction()`, then `commit()` or `rollback()`.
|
|
242
|
+
|
|
206
243
|
## Registering Schemas
|
|
207
244
|
|
|
208
245
|
Register app schemas by inserting JSON into `lix_registered_schema.value`:
|
|
@@ -218,11 +255,11 @@ Schema basics:
|
|
|
218
255
|
|
|
219
256
|
- `x-lix-key` becomes the generated SQL table name.
|
|
220
257
|
- Compatible schema amendments are keyed by `x-lix-key`.
|
|
221
|
-
- `x-lix-primary-key` tells Lix how to derive
|
|
258
|
+
- `x-lix-primary-key` tells Lix how to derive `entity_pk`.
|
|
222
259
|
- Primary-key entries are JSON Pointers with a leading slash, such as `["/id"]` or `["/owner/email"]`.
|
|
223
260
|
- Use `additionalProperties: false` so accidental fields fail fast.
|
|
224
261
|
|
|
225
|
-
Without `x-lix-primary-key`, table-style INSERTs fail with an error like `requires
|
|
262
|
+
Without `x-lix-primary-key`, table-style INSERTs fail with an error like `requires lixcol_entity_pk because the schema has no x-lix-primary-key`.
|
|
226
263
|
|
|
227
264
|
Uniqueness is not inferred from ordinary JSON Schema fields. If a non-primary-key field must be unique, declare it explicitly:
|
|
228
265
|
|
|
@@ -247,7 +284,7 @@ Discover live schemas before guessing:
|
|
|
247
284
|
|
|
248
285
|
```ts
|
|
249
286
|
const schemas = await lix.execute(
|
|
250
|
-
"SELECT
|
|
287
|
+
"SELECT lixcol_entity_pk, value FROM lix_registered_schema ORDER BY lixcol_entity_pk",
|
|
251
288
|
);
|
|
252
289
|
|
|
253
290
|
for (const row of schemas.rows) {
|
|
@@ -256,58 +293,58 @@ for (const row of schemas.rows) {
|
|
|
256
293
|
}
|
|
257
294
|
```
|
|
258
295
|
|
|
259
|
-
##
|
|
296
|
+
## Branches And `_by_branch`
|
|
260
297
|
|
|
261
|
-
Capture the initial active
|
|
298
|
+
Capture the initial active branch id instead of hardcoding `"main"`:
|
|
262
299
|
|
|
263
300
|
```ts
|
|
264
|
-
const published = await lix.
|
|
301
|
+
const published = await lix.activeBranchId();
|
|
265
302
|
```
|
|
266
303
|
|
|
267
|
-
Create
|
|
304
|
+
Create branches with names from the user's domain:
|
|
268
305
|
|
|
269
306
|
```ts
|
|
270
|
-
const marketing = await lix.
|
|
271
|
-
const legal = await lix.
|
|
307
|
+
const marketing = await lix.createBranch({ name: "Marketing edit" });
|
|
308
|
+
const legal = await lix.createBranch({ name: "Legal review" });
|
|
272
309
|
```
|
|
273
310
|
|
|
274
|
-
Every registered schema `X` gets a sibling table `
|
|
311
|
+
Every registered schema `X` gets a sibling table `X_by_branch` with `lixcol_branch_id`. Use it for side-by-side reads and for writes to non-active branches.
|
|
275
312
|
|
|
276
313
|
```ts
|
|
277
314
|
await lix.execute(
|
|
278
|
-
`UPDATE
|
|
315
|
+
`UPDATE acme_note_by_branch
|
|
279
316
|
SET title = $1
|
|
280
|
-
WHERE id = $2 AND
|
|
317
|
+
WHERE id = $2 AND lixcol_branch_id = $3`,
|
|
281
318
|
["Sharper launch copy", "n1", marketing.id],
|
|
282
319
|
);
|
|
283
320
|
|
|
284
321
|
const sideBySide = await lix.execute(
|
|
285
322
|
`SELECT v.name, n.title
|
|
286
|
-
FROM
|
|
287
|
-
JOIN
|
|
323
|
+
FROM acme_note_by_branch n
|
|
324
|
+
JOIN lix_branch v ON v.id = n.lixcol_branch_id
|
|
288
325
|
WHERE n.id = $1
|
|
289
|
-
AND n.
|
|
326
|
+
AND n.lixcol_branch_id IN ($2, $3)
|
|
290
327
|
ORDER BY v.name`,
|
|
291
328
|
["n1", published, marketing.id],
|
|
292
329
|
);
|
|
293
330
|
```
|
|
294
331
|
|
|
295
|
-
Rules for `
|
|
332
|
+
Rules for `_by_branch`:
|
|
296
333
|
|
|
297
|
-
- Reads filter by `
|
|
298
|
-
- INSERTs require `
|
|
299
|
-
- UPDATEs and DELETEs must include `
|
|
300
|
-
- The non-suffixed table is the active-
|
|
334
|
+
- Reads filter by `lixcol_branch_id`, or omit the filter to scan all branches.
|
|
335
|
+
- INSERTs require `lixcol_branch_id`.
|
|
336
|
+
- UPDATEs and DELETEs must include `lixcol_branch_id` in the WHERE clause.
|
|
337
|
+
- The non-suffixed table is the active-branch view.
|
|
301
338
|
|
|
302
|
-
`
|
|
339
|
+
`switchBranch()` is for app code with a current working branch concept. `mergeBranch()` always merges into the active branch, so switch first if you need a different target.
|
|
303
340
|
|
|
304
341
|
## Merging
|
|
305
342
|
|
|
306
|
-
`
|
|
343
|
+
`mergeBranch()` merges the source branch into the currently active branch:
|
|
307
344
|
|
|
308
345
|
```ts
|
|
309
346
|
try {
|
|
310
|
-
const merge = await lix.
|
|
347
|
+
const merge = await lix.mergeBranch({ sourceBranchId: marketing.id });
|
|
311
348
|
console.log(merge.outcome, merge.changeStats.total);
|
|
312
349
|
} catch (error) {
|
|
313
350
|
console.error("Merge conflict", error);
|
|
@@ -320,18 +357,18 @@ Common outcomes:
|
|
|
320
357
|
- `"fastForward"` - target advanced to source without a merge commit.
|
|
321
358
|
- `"mergeCommitted"` - a new merge commit was created.
|
|
322
359
|
|
|
323
|
-
`
|
|
360
|
+
`mergeBranchPreview()` reports the same merge decision without advancing refs, staging changes, or creating commits. Merge conflicts are returned as preview data.
|
|
324
361
|
|
|
325
|
-
Conflicts throw from `
|
|
362
|
+
Conflicts throw from `mergeBranch()`. If both branches modified the same entity since their merge base, Lix raises a `LixError`. Conflict detection is row-level today, not field-level. To reproduce a conflict in a demo, fork all contending branches from the same base before merging any of them.
|
|
326
363
|
|
|
327
364
|
## Demo Pattern To Imitate
|
|
328
365
|
|
|
329
366
|
For richer demos, show these four things:
|
|
330
367
|
|
|
331
|
-
1. Isolation: one SELECT against `<schema>
|
|
368
|
+
1. Isolation: one SELECT against `<schema>_by_branch` shows several branches side by side.
|
|
332
369
|
2. Clean parallel merges: two reviewers edit different entities and both land.
|
|
333
370
|
3. Audit history: `lix_change` is queryable SQL.
|
|
334
|
-
4. Conflict handling: two
|
|
371
|
+
4. Conflict handling: two branches edit the same entity and `mergeBranch()` throws.
|
|
335
372
|
|
|
336
373
|
Shape the domain as a collection of small entities:
|
|
337
374
|
|
|
@@ -341,20 +378,20 @@ Shape the domain as a collection of small entities:
|
|
|
341
378
|
Demo recipe:
|
|
342
379
|
|
|
343
380
|
1. Register a schema such as `acme_section`.
|
|
344
|
-
2. Seed several rows in the published
|
|
345
|
-
3. Create all reviewer
|
|
346
|
-
4. Write each reviewer's changes through `
|
|
347
|
-
5. Read side by side by joining `
|
|
381
|
+
2. Seed several rows in the published branch.
|
|
382
|
+
3. Create all reviewer branches up front from the same base.
|
|
383
|
+
4. Write each reviewer's changes through `acme_section_by_branch`.
|
|
384
|
+
5. Read side by side by joining `acme_section_by_branch` to `lix_branch`.
|
|
348
385
|
6. Merge non-overlapping row edits successfully.
|
|
349
386
|
7. Query `lix_change`.
|
|
350
387
|
8. Catch the deliberate same-row conflict.
|
|
351
388
|
|
|
352
389
|
## Files With `lix_file`
|
|
353
390
|
|
|
354
|
-
`lix_file` stores files as
|
|
391
|
+
`lix_file` stores files as branched bytes. Parent directories are created automatically.
|
|
355
392
|
|
|
356
393
|
```ts
|
|
357
|
-
await lix.execute("INSERT INTO lix_file (id, path, data) VALUES ($1, $2, $3)", [
|
|
394
|
+
await lix.execute("INSERT INTO lix_file (id, path, data, hidden) VALUES ($1, $2, $3, false)", [
|
|
358
395
|
"file-readme",
|
|
359
396
|
"/docs/readme.md",
|
|
360
397
|
new TextEncoder().encode("# Hello\n"),
|
|
@@ -380,29 +417,30 @@ Columns consumers usually need:
|
|
|
380
417
|
| `path` | Absolute path like `/docs/readme.md`. |
|
|
381
418
|
| `data` | File contents as bytes. |
|
|
382
419
|
| `hidden` | UI hint; does not affect storage. |
|
|
383
|
-
| `lixcol_*` |
|
|
420
|
+
| `lixcol_*` | Branch/change metadata, including `lixcol_branch_id` where exposed. |
|
|
384
421
|
|
|
385
|
-
`
|
|
422
|
+
`lix_file_by_branch` exists for cross-branch file reads and writes. Files-as-parsed-entities are product direction, not current JS SDK behavior.
|
|
386
423
|
|
|
387
424
|
## The Change Journal
|
|
388
425
|
|
|
389
|
-
`lix_change` is an immutable SQL table of changes across registered schemas and
|
|
426
|
+
`lix_change` is an immutable SQL table of changes across registered schemas and branches. Use it for audit logs, blame, history, activity feeds, and undo-style UI.
|
|
390
427
|
|
|
391
|
-
Important columns include `id`, `
|
|
428
|
+
Important columns include `id`, `entity_pk`, `schema_key`, `snapshot_content`, `created_at`, and `lixcol_*` metadata.
|
|
392
429
|
|
|
393
430
|
```ts
|
|
394
431
|
// Audit log for one entity, oldest to newest.
|
|
395
432
|
await lix.execute(
|
|
396
433
|
`SELECT created_at, snapshot_content
|
|
397
434
|
FROM lix_change
|
|
398
|
-
WHERE schema_key = $1
|
|
435
|
+
WHERE schema_key = $1
|
|
436
|
+
AND lix_json_get_text(entity_pk, 0) = $2
|
|
399
437
|
ORDER BY created_at`,
|
|
400
438
|
["acme_note", "n1"],
|
|
401
439
|
);
|
|
402
440
|
|
|
403
441
|
// Latest activity across a schema.
|
|
404
442
|
await lix.execute(
|
|
405
|
-
`SELECT created_at,
|
|
443
|
+
`SELECT created_at, entity_pk, snapshot_content
|
|
406
444
|
FROM lix_change
|
|
407
445
|
WHERE schema_key = $1
|
|
408
446
|
ORDER BY created_at DESC
|
|
@@ -419,20 +457,20 @@ Common tables:
|
|
|
419
457
|
|
|
420
458
|
| Table | What it gives consumers |
|
|
421
459
|
| ----------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
422
|
-
| `
|
|
460
|
+
| `lix_branch` | Writable branch surface: `id`, `name`, `hidden`, `commit_id`. |
|
|
423
461
|
| `lix_change` | Immutable change journal. |
|
|
424
|
-
| `lix_file` |
|
|
462
|
+
| `lix_file` | Branched byte storage for files. |
|
|
425
463
|
| `lix_registered_schema` | Registry of app schemas plus built-ins; also exposes the Lix schema-definition meta-schema at runtime. |
|
|
426
464
|
|
|
427
|
-
`
|
|
465
|
+
`lix_branch` can be updated for admin flows:
|
|
428
466
|
|
|
429
467
|
```ts
|
|
430
|
-
await lix.execute("UPDATE
|
|
468
|
+
await lix.execute("UPDATE lix_branch SET hidden = true WHERE id = $1", [
|
|
431
469
|
marketing.id,
|
|
432
470
|
]);
|
|
433
471
|
```
|
|
434
472
|
|
|
435
|
-
There is no documented `
|
|
473
|
+
There is no documented `deleteBranch()` helper in this preview. If the product wants reversible cleanup, hide the branch. If it wants removal, `DELETE FROM lix_branch WHERE id = $1` is the SQL surface; the engine rejects deleting the global branch and active branch.
|
|
436
474
|
|
|
437
475
|
Use `lix_json($1)` to parse JSON text parameters when writing JSON-typed columns:
|
|
438
476
|
|
|
@@ -453,12 +491,14 @@ Other UDFs, such as `lix_json_get`, `lix_uuid_v7`, `lix_text_encode`, and `lix_e
|
|
|
453
491
|
| Use public imports from `@lix-js/sdk` and `@lix-js/sdk/sqlite`. | Importing `engine-wasm` or private internals. |
|
|
454
492
|
| Use `$1`, `$2`, `$3` placeholders. | Bare `?` placeholders. |
|
|
455
493
|
| Use `lix_json($1)` for JSON parameters. | Inlining stringified JSON directly into SQL. |
|
|
456
|
-
| Use `
|
|
457
|
-
|
|
|
494
|
+
| Use `beginTransaction()` for imports and batch writes that should be one commit. | Loops of standalone `lix.execute()` writes for bulk imports. |
|
|
495
|
+
| Use the transaction handle for reads and writes until it commits or rolls back. | Calling parent-handle `execute()` during an active transaction. |
|
|
496
|
+
| Use `_by_branch` for cross-branch reads/writes. | Switching branches just to render a side-by-side view. |
|
|
497
|
+
| Name branches in user vocabulary. | User-facing words like branch, branch-1, or generic Draft. |
|
|
458
498
|
| Model collaborative data as small rows. | One giant row when multiple reviewers edit different parts. |
|
|
459
499
|
| Add `x-lix-unique` for non-primary unique fields. | Assuming JSON Schema property metadata creates uniqueness. |
|
|
460
500
|
| Read `snapshot_content` as JSON/native and handle null. | Blindly `JSON.parse(row.value(...).asText())`. |
|
|
461
|
-
| Wrap `
|
|
501
|
+
| Wrap `mergeBranch()` in `try/catch`. | Assuming merges cannot conflict. |
|
|
462
502
|
|
|
463
503
|
## Reporting SDK Friction
|
|
464
504
|
|
|
@@ -178,8 +178,7 @@ function isJsonValue(value) {
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
function normalizeJsonValue(value, seen = new WeakSet()) {
|
|
181
|
-
if (value === null ||
|
|
182
|
-
typeof value === "boolean") {
|
|
181
|
+
if (value === null || typeof value === "boolean") {
|
|
183
182
|
return value;
|
|
184
183
|
}
|
|
185
184
|
if (typeof value === "string") {
|
|
@@ -272,9 +271,10 @@ function base64ToBytes(base64) {
|
|
|
272
271
|
const engineWasmUrl = new URL("./wasm/lix_engine.wasm", import.meta.url);
|
|
273
272
|
function isNodeRuntime() {
|
|
274
273
|
const processLike = globalThis.process;
|
|
274
|
+
const runtimeBranches = processLike?.["ver" + "sions"];
|
|
275
275
|
return (!!processLike &&
|
|
276
|
-
typeof
|
|
277
|
-
!!
|
|
276
|
+
typeof runtimeBranches === "object" &&
|
|
277
|
+
!!runtimeBranches?.node);
|
|
278
278
|
}
|
|
279
279
|
async function tryReadNodeFileFromViteHttpUrl(url) {
|
|
280
280
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -11,7 +11,11 @@ export class Lix {
|
|
|
11
11
|
/**
|
|
12
12
|
* @returns {Promise<string>}
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
activeBranchId(): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* @returns {Promise<LixTransaction>}
|
|
17
|
+
*/
|
|
18
|
+
beginTransaction(): Promise<LixTransaction>;
|
|
15
19
|
/**
|
|
16
20
|
* @returns {Promise<void>}
|
|
17
21
|
*/
|
|
@@ -20,12 +24,12 @@ export class Lix {
|
|
|
20
24
|
* @param {any} args
|
|
21
25
|
* @returns {Promise<any>}
|
|
22
26
|
*/
|
|
23
|
-
|
|
27
|
+
createBranch(args: any): Promise<any>;
|
|
24
28
|
/**
|
|
25
29
|
* Executes one DataFusion SQL statement against this Lix session.
|
|
26
30
|
*
|
|
27
31
|
* The SQL dialect is DataFusion SQL, not SQLite SQL. Positional
|
|
28
|
-
* placeholders use `$1`, `$2`, and so on. SQLite-specific catalog
|
|
32
|
+
* placeholders use `?` or `$1`, `$2`, and so on. SQLite-specific catalog
|
|
29
33
|
* tables and transaction statements such as `sqlite_master`, `BEGIN`,
|
|
30
34
|
* and `COMMIT` are not part of this contract; use
|
|
31
35
|
* `information_schema` for catalog inspection.
|
|
@@ -38,17 +42,37 @@ export class Lix {
|
|
|
38
42
|
* @param {any} args
|
|
39
43
|
* @returns {Promise<any>}
|
|
40
44
|
*/
|
|
41
|
-
|
|
45
|
+
mergeBranch(args: any): Promise<any>;
|
|
42
46
|
/**
|
|
43
47
|
* @param {any} args
|
|
44
48
|
* @returns {Promise<any>}
|
|
45
49
|
*/
|
|
46
|
-
|
|
50
|
+
mergeBranchPreview(args: any): Promise<any>;
|
|
47
51
|
/**
|
|
48
52
|
* @param {any} args
|
|
49
53
|
* @returns {Promise<any>}
|
|
50
54
|
*/
|
|
51
|
-
|
|
55
|
+
switchBranch(args: any): Promise<any>;
|
|
56
|
+
}
|
|
57
|
+
export class LixTransaction {
|
|
58
|
+
static __wrap(ptr: any): any;
|
|
59
|
+
__destroy_into_raw(): number | undefined;
|
|
60
|
+
__wbg_ptr: number | undefined;
|
|
61
|
+
free(): void;
|
|
62
|
+
/**
|
|
63
|
+
* @returns {Promise<void>}
|
|
64
|
+
*/
|
|
65
|
+
commit(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* @param {any} sql
|
|
68
|
+
* @param {any} params
|
|
69
|
+
* @returns {Promise<any>}
|
|
70
|
+
*/
|
|
71
|
+
execute(sql: any, params: any): Promise<any>;
|
|
72
|
+
/**
|
|
73
|
+
* @returns {Promise<void>}
|
|
74
|
+
*/
|
|
75
|
+
rollback(): Promise<void>;
|
|
52
76
|
}
|
|
53
77
|
export function initSync(module: any): any;
|
|
54
78
|
declare function __wbg_init(module_or_path: any): Promise<any>;
|