@lix-js/sdk 0.4.6 → 0.5.0-preview.0
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/dist/account/create-account.d.ts +17 -3
- package/dist/account/create-account.d.ts.map +1 -1
- package/dist/account/create-account.js +27 -3
- package/dist/account/create-account.js.map +1 -1
- package/dist/account/create-account.test.js +42 -4
- package/dist/account/create-account.test.js.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/index.js.map +1 -1
- package/dist/account/schema.d.ts +28 -0
- package/dist/account/schema.d.ts.map +1 -0
- package/dist/account/schema.js +55 -0
- package/dist/account/schema.js.map +1 -0
- package/dist/account/schema.test.d.ts +2 -0
- package/dist/account/schema.test.d.ts.map +1 -0
- package/dist/account/schema.test.js +306 -0
- package/dist/account/schema.test.js.map +1 -0
- package/dist/account/switch-account.d.ts +2 -2
- package/dist/account/switch-account.d.ts.map +1 -1
- package/dist/account/switch-account.js +8 -1
- package/dist/account/switch-account.js.map +1 -1
- package/dist/account/switch-account.test.js +27 -6
- package/dist/account/switch-account.test.js.map +1 -1
- package/dist/change/create-change.d.ts +11 -22
- package/dist/change/create-change.d.ts.map +1 -1
- package/dist/change/create-change.js +29 -83
- package/dist/change/create-change.js.map +1 -1
- package/dist/change/create-change.test.js +129 -176
- package/dist/change/create-change.test.js.map +1 -1
- package/dist/change/index.d.ts +1 -2
- package/dist/change/index.d.ts.map +1 -1
- package/dist/change/index.js +1 -2
- package/dist/change/index.js.map +1 -1
- package/dist/change/mock-change.d.ts +1 -1
- package/dist/change/mock-change.d.ts.map +1 -1
- package/dist/change/mock-change.js +1 -0
- package/dist/change/mock-change.js.map +1 -1
- package/dist/change/schema.d.ts +28 -0
- package/dist/change/schema.d.ts.map +1 -0
- package/dist/change/schema.js +62 -0
- package/dist/change/schema.js.map +1 -0
- package/dist/change/schema.test.d.ts +2 -0
- package/dist/change/schema.test.d.ts.map +1 -0
- package/dist/change/schema.test.js +235 -0
- package/dist/change/schema.test.js.map +1 -0
- package/dist/change-author/index.d.ts +2 -0
- package/dist/change-author/index.d.ts.map +1 -0
- package/dist/change-author/index.js +2 -0
- package/dist/change-author/index.js.map +1 -0
- package/dist/change-author/schema.d.ts +31 -0
- package/dist/change-author/schema.d.ts.map +1 -0
- package/dist/change-author/schema.js +35 -0
- package/dist/change-author/schema.js.map +1 -0
- package/dist/change-author/schema.test.d.ts +2 -0
- package/dist/change-author/schema.test.d.ts.map +1 -0
- package/dist/change-author/schema.test.js +256 -0
- package/dist/change-author/schema.test.js.map +1 -0
- package/dist/change-conflict/create-change-conflict.d.ts.map +1 -1
- package/dist/change-conflict/create-change-conflict.js +24 -6
- package/dist/change-conflict/create-change-conflict.js.map +1 -1
- package/dist/change-conflict/create-change-conflict.test.js +13 -11
- package/dist/change-conflict/create-change-conflict.test.js.map +1 -1
- package/dist/change-conflict/detect-change-conflicts.d.ts.map +1 -1
- package/dist/change-conflict/detect-change-conflicts.js +2 -0
- package/dist/change-conflict/detect-change-conflicts.js.map +1 -1
- package/dist/change-conflict/detect-change-conflicts.test.js +17 -13
- package/dist/change-conflict/detect-change-conflicts.test.js.map +1 -1
- package/dist/change-conflict/detect-diverging-entity-conflict.d.ts.map +1 -1
- package/dist/change-conflict/detect-diverging-entity-conflict.js +3 -1
- package/dist/change-conflict/detect-diverging-entity-conflict.js.map +1 -1
- package/dist/change-conflict/detect-diverging-entity-conflict.test.js +23 -21
- package/dist/change-conflict/detect-diverging-entity-conflict.test.js.map +1 -1
- package/dist/change-conflict/garbage-collect-change-conflicts.d.ts.map +1 -1
- package/dist/change-conflict/garbage-collect-change-conflicts.js +2 -0
- package/dist/change-conflict/garbage-collect-change-conflicts.js.map +1 -1
- package/dist/change-conflict/garbage-collect-change-conflicts.test.js +15 -15
- package/dist/change-conflict/garbage-collect-change-conflicts.test.js.map +1 -1
- package/dist/change-conflict/resolve-conflict-by-selecting.d.ts.map +1 -1
- package/dist/change-conflict/resolve-conflict-by-selecting.js +2 -2
- package/dist/change-conflict/resolve-conflict-by-selecting.js.map +1 -1
- package/dist/change-conflict/resolve-conflict-by-selecting.test.js +17 -8
- package/dist/change-conflict/resolve-conflict-by-selecting.test.js.map +1 -1
- package/dist/change-proposal/create-change-proposal.d.ts +16 -0
- package/dist/change-proposal/create-change-proposal.d.ts.map +1 -0
- package/dist/change-proposal/create-change-proposal.js +52 -0
- package/dist/change-proposal/create-change-proposal.js.map +1 -0
- package/dist/change-proposal/create-change-proposal.test.d.ts +2 -0
- package/dist/change-proposal/create-change-proposal.test.d.ts.map +1 -0
- package/dist/change-proposal/create-change-proposal.test.js +91 -0
- package/dist/change-proposal/create-change-proposal.test.js.map +1 -0
- package/dist/change-proposal/database-schema.d.ts +13 -0
- package/dist/change-proposal/database-schema.d.ts.map +1 -0
- package/dist/change-proposal/database-schema.js +17 -0
- package/dist/change-proposal/database-schema.js.map +1 -0
- package/dist/change-proposal/database-schema.test.d.ts +2 -0
- package/dist/change-proposal/database-schema.test.d.ts.map +1 -0
- package/dist/change-proposal/database-schema.test.js +159 -0
- package/dist/change-proposal/database-schema.test.js.map +1 -0
- package/dist/change-proposal/index.d.ts +3 -0
- package/dist/change-proposal/index.d.ts.map +1 -0
- package/dist/change-proposal/index.js +3 -0
- package/dist/change-proposal/index.js.map +1 -0
- package/dist/change-set/apply-change-set.d.ts +10 -0
- package/dist/change-set/apply-change-set.d.ts.map +1 -0
- package/dist/change-set/apply-change-set.js +150 -0
- package/dist/change-set/apply-change-set.js.map +1 -0
- package/dist/change-set/apply-change-set.test.d.ts +2 -0
- package/dist/change-set/apply-change-set.test.d.ts.map +1 -0
- package/dist/change-set/apply-change-set.test.js +390 -0
- package/dist/change-set/apply-change-set.test.js.map +1 -0
- package/dist/change-set/change-set-element-in-symmetric-difference.d.ts.map +1 -1
- package/dist/change-set/create-change-set.d.ts +19 -18
- package/dist/change-set/create-change-set.d.ts.map +1 -1
- package/dist/change-set/create-change-set.js +95 -34
- package/dist/change-set/create-change-set.js.map +1 -1
- package/dist/change-set/create-change-set.test.js +109 -27
- package/dist/change-set/create-change-set.test.js.map +1 -1
- package/dist/change-set/create-checkpoint.d.ts +19 -0
- package/dist/change-set/create-checkpoint.d.ts.map +1 -0
- package/dist/change-set/create-checkpoint.js +86 -0
- package/dist/change-set/create-checkpoint.js.map +1 -0
- package/dist/change-set/create-checkpoint.test.d.ts +2 -0
- package/dist/change-set/create-checkpoint.test.d.ts.map +1 -0
- package/dist/change-set/create-checkpoint.test.js +294 -0
- package/dist/change-set/create-checkpoint.test.js.map +1 -0
- package/dist/change-set/create-merge-change-set.d.ts +23 -0
- package/dist/change-set/create-merge-change-set.d.ts.map +1 -0
- package/dist/change-set/create-merge-change-set.js +68 -0
- package/dist/change-set/create-merge-change-set.js.map +1 -0
- package/dist/change-set/create-merge-change-set.test.d.ts +2 -0
- package/dist/change-set/create-merge-change-set.test.d.ts.map +1 -0
- package/dist/change-set/create-merge-change-set.test.js +211 -0
- package/dist/change-set/create-merge-change-set.test.js.map +1 -0
- package/dist/change-set/create-transition-change-set.d.ts +18 -0
- package/dist/change-set/create-transition-change-set.d.ts.map +1 -0
- package/dist/change-set/create-transition-change-set.js +102 -0
- package/dist/change-set/create-transition-change-set.js.map +1 -0
- package/dist/change-set/create-transition-change-set.test.d.ts +2 -0
- package/dist/change-set/create-transition-change-set.test.d.ts.map +1 -0
- package/dist/change-set/create-transition-change-set.test.js +211 -0
- package/dist/change-set/create-transition-change-set.test.js.map +1 -0
- package/dist/change-set/create-undo-change-set.d.ts +27 -0
- package/dist/change-set/create-undo-change-set.d.ts.map +1 -0
- package/dist/change-set/create-undo-change-set.js +121 -0
- package/dist/change-set/create-undo-change-set.js.map +1 -0
- package/dist/change-set/create-undo-change-set.test.d.ts +2 -0
- package/dist/change-set/create-undo-change-set.test.d.ts.map +1 -0
- package/dist/change-set/create-undo-change-set.test.js +273 -0
- package/dist/change-set/create-undo-change-set.test.js.map +1 -0
- package/dist/change-set/index.d.ts +6 -1
- package/dist/change-set/index.d.ts.map +1 -1
- package/dist/change-set/index.js +6 -1
- package/dist/change-set/index.js.map +1 -1
- package/dist/change-set/schema.d.ts +149 -0
- package/dist/change-set/schema.d.ts.map +1 -0
- package/dist/change-set/schema.js +169 -0
- package/dist/change-set/schema.js.map +1 -0
- package/dist/change-set/schema.test.d.ts +2 -0
- package/dist/change-set/schema.test.d.ts.map +1 -0
- package/dist/change-set/schema.test.js +821 -0
- package/dist/change-set/schema.test.js.map +1 -0
- package/dist/database/execute-sync.d.ts +12 -6
- package/dist/database/execute-sync.d.ts.map +1 -1
- package/dist/database/execute-sync.js +25 -24
- package/dist/database/execute-sync.js.map +1 -1
- package/dist/database/execute-sync.test.js +53 -60
- package/dist/database/execute-sync.test.js.map +1 -1
- package/dist/database/graph-traversal-mode.d.ts +72 -0
- package/dist/database/graph-traversal-mode.d.ts.map +1 -0
- package/dist/database/graph-traversal-mode.js +2 -0
- package/dist/database/graph-traversal-mode.js.map +1 -0
- package/dist/database/index.d.ts +3 -2
- package/dist/database/index.d.ts.map +1 -1
- package/dist/database/index.js +3 -2
- package/dist/database/index.js.map +1 -1
- package/dist/database/init-db.d.ts +2 -0
- package/dist/database/init-db.d.ts.map +1 -1
- package/dist/database/init-db.js +69 -56
- package/dist/database/init-db.js.map +1 -1
- package/dist/database/kysely-plugin/json-column-plugin.d.ts +3 -0
- package/dist/database/kysely-plugin/json-column-plugin.d.ts.map +1 -0
- package/dist/database/kysely-plugin/json-column-plugin.js +168 -0
- package/dist/database/kysely-plugin/json-column-plugin.js.map +1 -0
- package/dist/database/kysely-plugin/parse-jsonb-plugin-v1.d.ts.map +1 -1
- package/dist/database/kysely-plugin/parse-jsonb-plugin-v1.js +5 -10
- package/dist/database/kysely-plugin/parse-jsonb-plugin-v1.js.map +1 -1
- package/dist/database/kysely-plugin/parse-jsonb-plugin-v2.js +1 -1
- package/dist/database/kysely-plugin/parse-jsonb-plugin-v2.js.map +1 -1
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.d.ts +14 -2
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.d.ts.map +1 -1
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.js +145 -74
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.js.map +1 -1
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.test.js +145 -1
- package/dist/database/kysely-plugin/serialize-jsonb-plugin.test.js.map +1 -1
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.d.ts +15 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.d.ts.map +1 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.js +31 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.js.map +1 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.test.d.ts +2 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.test.d.ts.map +1 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.test.js +51 -0
- package/dist/database/kysely-plugin/view-insert-returning-error-plugin.test.js.map +1 -0
- package/dist/database/schema.d.ts +42 -208
- package/dist/database/schema.d.ts.map +1 -1
- package/dist/database/schema.js +35 -1
- package/dist/database/schema.js.map +1 -1
- package/dist/entity-views/entity-state-all.d.ts +217 -0
- package/dist/entity-views/entity-state-all.d.ts.map +1 -0
- package/dist/entity-views/entity-state-all.js +246 -0
- package/dist/entity-views/entity-state-all.js.map +1 -0
- package/dist/entity-views/entity-state-all.test.d.ts +2 -0
- package/dist/entity-views/entity-state-all.test.d.ts.map +1 -0
- package/dist/entity-views/entity-state-all.test.js +371 -0
- package/dist/entity-views/entity-state-all.test.js.map +1 -0
- package/dist/entity-views/entity-state-history.d.ts +178 -0
- package/dist/entity-views/entity-state-history.d.ts.map +1 -0
- package/dist/entity-views/entity-state-history.js +58 -0
- package/dist/entity-views/entity-state-history.js.map +1 -0
- package/dist/entity-views/entity-state-history.test.d.ts +2 -0
- package/dist/entity-views/entity-state-history.test.d.ts.map +1 -0
- package/dist/entity-views/entity-state-history.test.js +274 -0
- package/dist/entity-views/entity-state-history.test.js.map +1 -0
- package/dist/entity-views/entity-state.d.ts +217 -0
- package/dist/entity-views/entity-state.d.ts.map +1 -0
- package/dist/entity-views/entity-state.js +243 -0
- package/dist/entity-views/entity-state.js.map +1 -0
- package/dist/entity-views/entity-state.test.d.ts +2 -0
- package/dist/entity-views/entity-state.test.d.ts.map +1 -0
- package/dist/entity-views/entity-state.test.js +497 -0
- package/dist/entity-views/entity-state.test.js.map +1 -0
- package/dist/entity-views/entity-state_history.d.ts +67 -0
- package/dist/entity-views/entity-state_history.d.ts.map +1 -0
- package/dist/entity-views/entity-state_history.js +58 -0
- package/dist/entity-views/entity-state_history.js.map +1 -0
- package/dist/entity-views/entity-view-builder.d.ts +92 -0
- package/dist/entity-views/entity-view-builder.d.ts.map +1 -0
- package/dist/entity-views/entity-view-builder.js +63 -0
- package/dist/entity-views/entity-view-builder.js.map +1 -0
- package/dist/entity-views/entity-view-builder.test.d.ts +2 -0
- package/dist/entity-views/entity-view-builder.test.d.ts.map +1 -0
- package/dist/entity-views/entity-view-builder.test.js +247 -0
- package/dist/entity-views/entity-view-builder.test.js.map +1 -0
- package/dist/entity-views/generic-types.d.ts +128 -0
- package/dist/entity-views/generic-types.d.ts.map +1 -0
- package/dist/entity-views/generic-types.js +2 -0
- package/dist/entity-views/generic-types.js.map +1 -0
- package/dist/entity-views/generic-types.test.d.ts +2 -0
- package/dist/entity-views/generic-types.test.d.ts.map +1 -0
- package/dist/entity-views/generic-types.test.js +99 -0
- package/dist/entity-views/generic-types.test.js.map +1 -0
- package/dist/entity-views/index.d.ts +2 -0
- package/dist/entity-views/index.d.ts.map +1 -0
- package/dist/entity-views/index.js +2 -0
- package/dist/entity-views/index.js.map +1 -0
- package/dist/entity-views/types.d.ts +309 -0
- package/dist/entity-views/types.d.ts.map +1 -0
- package/dist/entity-views/types.js +2 -0
- package/dist/entity-views/types.js.map +1 -0
- package/dist/entity-views/types.test.d.ts +2 -0
- package/dist/entity-views/types.test.d.ts.map +1 -0
- package/dist/entity-views/types.test.js +62 -0
- package/dist/entity-views/types.test.js.map +1 -0
- package/dist/file/file-handlers.d.ts +15 -0
- package/dist/file/file-handlers.d.ts.map +1 -0
- package/dist/file/file-handlers.js +318 -0
- package/dist/file/file-handlers.js.map +1 -0
- package/dist/file/file-handlers.test.d.ts +2 -0
- package/dist/file/file-handlers.test.d.ts.map +1 -0
- package/dist/file/file-handlers.test.js +151 -0
- package/dist/file/file-handlers.test.js.map +1 -0
- package/dist/file/index.d.ts +1 -1
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +1 -1
- package/dist/file/index.js.map +1 -1
- package/dist/file/materialize-file-data-at-changeset.d.ts +9 -0
- package/dist/file/materialize-file-data-at-changeset.d.ts.map +1 -0
- package/dist/file/materialize-file-data-at-changeset.js +93 -0
- package/dist/file/materialize-file-data-at-changeset.js.map +1 -0
- package/dist/file/materialize-file-data.d.ts +8 -0
- package/dist/file/materialize-file-data.d.ts.map +1 -0
- package/dist/file/materialize-file-data.js +91 -0
- package/dist/file/materialize-file-data.js.map +1 -0
- package/dist/file/materialize-file-data.test.d.ts +2 -0
- package/dist/file/materialize-file-data.test.d.ts.map +1 -0
- package/dist/file/materialize-file-data.test.js +90 -0
- package/dist/file/materialize-file-data.test.js.map +1 -0
- package/dist/file/schema.d.ts +46 -0
- package/dist/file/schema.d.ts.map +1 -0
- package/dist/file/schema.js +265 -0
- package/dist/file/schema.js.map +1 -0
- package/dist/file/schema.test.d.ts +2 -0
- package/dist/file/schema.test.d.ts.map +1 -0
- package/dist/file/schema.test.js +805 -0
- package/dist/file/schema.test.js.map +1 -0
- package/dist/file/store-detected-change-schema.d.ts +8 -0
- package/dist/file/store-detected-change-schema.d.ts.map +1 -0
- package/dist/file/store-detected-change-schema.js +41 -0
- package/dist/file/store-detected-change-schema.js.map +1 -0
- package/dist/file/store-detected-change-schema.test.d.ts +2 -0
- package/dist/file/store-detected-change-schema.test.d.ts.map +1 -0
- package/dist/file/store-detected-change-schema.test.js +211 -0
- package/dist/file/store-detected-change-schema.test.js.map +1 -0
- package/dist/file/unknown-file-fallback-plugin.d.ts +22 -0
- package/dist/file/unknown-file-fallback-plugin.d.ts.map +1 -0
- package/dist/file/unknown-file-fallback-plugin.js +73 -0
- package/dist/file/unknown-file-fallback-plugin.js.map +1 -0
- package/dist/file/unknown-file-fallback-plugin.test.d.ts +2 -0
- package/dist/file/unknown-file-fallback-plugin.test.d.ts.map +1 -0
- package/dist/file/unknown-file-fallback-plugin.test.js +305 -0
- package/dist/file/unknown-file-fallback-plugin.test.js.map +1 -0
- package/dist/hooks/create-hooks.d.ts +72 -0
- package/dist/hooks/create-hooks.d.ts.map +1 -0
- package/dist/hooks/create-hooks.js +29 -0
- package/dist/hooks/create-hooks.js.map +1 -0
- package/dist/hooks/create-hooks.test.d.ts +2 -0
- package/dist/hooks/create-hooks.test.d.ts.map +1 -0
- package/dist/hooks/create-hooks.test.js +98 -0
- package/dist/hooks/create-hooks.test.js.map +1 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -6
- package/dist/index.js.map +1 -1
- package/dist/key-value/index.d.ts +2 -0
- package/dist/key-value/index.d.ts.map +1 -0
- package/dist/key-value/index.js +2 -0
- package/dist/key-value/index.js.map +1 -0
- package/dist/key-value/schema.d.ts +21 -0
- package/dist/key-value/schema.d.ts.map +1 -0
- package/dist/key-value/schema.js +25 -0
- package/dist/key-value/schema.js.map +1 -0
- package/dist/key-value/schema.test.d.ts +2 -0
- package/dist/key-value/schema.test.d.ts.map +1 -0
- package/dist/key-value/schema.test.js +148 -0
- package/dist/key-value/schema.test.js.map +1 -0
- package/dist/label/create-label.d.ts +20 -0
- package/dist/label/create-label.d.ts.map +1 -0
- package/dist/label/create-label.js +45 -0
- package/dist/label/create-label.js.map +1 -0
- package/dist/label/create-label.test.d.ts +2 -0
- package/dist/label/create-label.test.d.ts.map +1 -0
- package/dist/label/create-label.test.js +191 -0
- package/dist/label/create-label.test.js.map +1 -0
- package/dist/label/index.d.ts +3 -0
- package/dist/label/index.d.ts.map +1 -0
- package/dist/label/index.js +3 -0
- package/dist/label/index.js.map +1 -0
- package/dist/label/schema.d.ts +22 -0
- package/dist/label/schema.d.ts.map +1 -0
- package/dist/label/schema.js +28 -0
- package/dist/label/schema.js.map +1 -0
- package/dist/label/schema.test.d.ts +2 -0
- package/dist/label/schema.test.d.ts.map +1 -0
- package/dist/label/schema.test.js +76 -0
- package/dist/label/schema.test.js.map +1 -0
- package/dist/lix/close-lix.d.ts +10 -1
- package/dist/lix/close-lix.d.ts.map +1 -1
- package/dist/lix/close-lix.js +10 -1
- package/dist/lix/close-lix.js.map +1 -1
- package/dist/lix/index.d.ts +3 -2
- package/dist/lix/index.d.ts.map +1 -1
- package/dist/lix/index.js +3 -5
- package/dist/lix/index.js.map +1 -1
- package/dist/lix/new-lix.d.ts +77 -4
- package/dist/lix/new-lix.d.ts.map +1 -1
- package/dist/lix/new-lix.js +303 -8
- package/dist/lix/new-lix.js.map +1 -1
- package/dist/lix/new-lix.test.js +171 -16
- package/dist/lix/new-lix.test.js.map +1 -1
- package/dist/lix/open-lix-in-memory.d.ts +9 -1
- package/dist/lix/open-lix-in-memory.d.ts.map +1 -1
- package/dist/lix/open-lix-in-memory.js +15 -7
- package/dist/lix/open-lix-in-memory.js.map +1 -1
- package/dist/lix/open-lix-in-memory.test.js +0 -6
- package/dist/lix/open-lix-in-memory.test.js.map +1 -1
- package/dist/lix/open-lix.d.ts +68 -6
- package/dist/lix/open-lix.d.ts.map +1 -1
- package/dist/lix/open-lix.js +80 -14
- package/dist/lix/open-lix.js.map +1 -1
- package/dist/lix/open-lix.test.js +54 -22
- package/dist/lix/open-lix.test.js.map +1 -1
- package/dist/lix/storage/in-memory.d.ts +34 -0
- package/dist/lix/storage/in-memory.d.ts.map +1 -0
- package/dist/lix/storage/in-memory.js +57 -0
- package/dist/lix/storage/in-memory.js.map +1 -0
- package/dist/lix/storage/in-memory.test.d.ts +2 -0
- package/dist/lix/storage/in-memory.test.d.ts.map +1 -0
- package/dist/lix/storage/in-memory.test.js +146 -0
- package/dist/lix/storage/in-memory.test.js.map +1 -0
- package/dist/lix/storage/lix-storage-adapter.d.ts +16 -0
- package/dist/lix/storage/lix-storage-adapter.d.ts.map +1 -0
- package/dist/lix/storage/lix-storage-adapter.js +2 -0
- package/dist/lix/storage/lix-storage-adapter.js.map +1 -0
- package/dist/lix/storage/opfs.d.ts +66 -0
- package/dist/lix/storage/opfs.d.ts.map +1 -0
- package/dist/lix/storage/opfs.js +152 -0
- package/dist/lix/storage/opfs.js.map +1 -0
- package/dist/lix/storage/opfs.test.d.ts +2 -0
- package/dist/lix/storage/opfs.test.d.ts.map +1 -0
- package/dist/lix/storage/opfs.test.js +171 -0
- package/dist/lix/storage/opfs.test.js.map +1 -0
- package/dist/lix/to-blob.d.ts +9 -2
- package/dist/lix/to-blob.d.ts.map +1 -1
- package/dist/lix/to-blob.js +9 -2
- package/dist/lix/to-blob.js.map +1 -1
- package/dist/lix/to-blob.test.d.ts +2 -0
- package/dist/lix/to-blob.test.d.ts.map +1 -0
- package/dist/lix/to-blob.test.js +18 -0
- package/dist/lix/to-blob.test.js.map +1 -0
- package/dist/log/create-lix-own-log.d.ts +66 -0
- package/dist/log/create-lix-own-log.d.ts.map +1 -0
- package/dist/log/create-lix-own-log.js +103 -0
- package/dist/log/create-lix-own-log.js.map +1 -0
- package/dist/log/create-lix-own-log.test.d.ts +2 -0
- package/dist/log/create-lix-own-log.test.d.ts.map +1 -0
- package/dist/log/create-lix-own-log.test.js +81 -0
- package/dist/log/create-lix-own-log.test.js.map +1 -0
- package/dist/log/create-log.d.ts +32 -0
- package/dist/log/create-log.d.ts.map +1 -0
- package/dist/log/create-log.js +43 -0
- package/dist/log/create-log.js.map +1 -0
- package/dist/log/index.d.ts +3 -0
- package/dist/log/index.d.ts.map +1 -0
- package/dist/log/index.js +3 -0
- package/dist/log/index.js.map +1 -0
- package/dist/log/schema.d.ts +32 -0
- package/dist/log/schema.d.ts.map +1 -0
- package/dist/log/schema.js +43 -0
- package/dist/log/schema.js.map +1 -0
- package/dist/log/schema.test.d.ts +2 -0
- package/dist/log/schema.test.d.ts.map +1 -0
- package/dist/log/schema.test.js +119 -0
- package/dist/log/schema.test.js.map +1 -0
- package/dist/observe/create-observe.d.ts +17 -0
- package/dist/observe/create-observe.d.ts.map +1 -0
- package/dist/observe/create-observe.js +118 -0
- package/dist/observe/create-observe.js.map +1 -0
- package/dist/observe/create-observe.test.d.ts +2 -0
- package/dist/observe/create-observe.test.d.ts.map +1 -0
- package/dist/observe/create-observe.test.js +384 -0
- package/dist/observe/create-observe.test.js.map +1 -0
- package/dist/observe/index.d.ts +2 -0
- package/dist/observe/index.d.ts.map +1 -0
- package/dist/observe/index.js +2 -0
- package/dist/observe/index.js.map +1 -0
- package/dist/observe/lix-observable.d.ts +31 -0
- package/dist/observe/lix-observable.d.ts.map +1 -0
- package/dist/observe/lix-observable.js +65 -0
- package/dist/observe/lix-observable.js.map +1 -0
- package/dist/observe/lix-observable.test.d.ts +2 -0
- package/dist/observe/lix-observable.test.d.ts.map +1 -0
- package/dist/observe/lix-observable.test.js +187 -0
- package/dist/observe/lix-observable.test.js.map +1 -0
- package/dist/plugin/index.d.ts +2 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/lix-plugin.d.ts +24 -45
- package/dist/plugin/lix-plugin.d.ts.map +1 -1
- package/dist/plugin/lix-plugin.js +1 -1
- package/dist/plugin/lix-plugin.js.map +1 -1
- package/dist/plugin/lix-plugin.test-d.js +17 -11
- package/dist/plugin/lix-plugin.test-d.js.map +1 -1
- package/dist/plugin/mock-json-plugin.d.ts +17 -0
- package/dist/plugin/mock-json-plugin.d.ts.map +1 -0
- package/dist/plugin/mock-json-plugin.flatten.d.ts +3 -0
- package/dist/plugin/mock-json-plugin.flatten.d.ts.map +1 -0
- package/dist/plugin/mock-json-plugin.flatten.js +124 -0
- package/dist/plugin/mock-json-plugin.flatten.js.map +1 -0
- package/dist/plugin/mock-json-plugin.js +101 -0
- package/dist/plugin/mock-json-plugin.js.map +1 -0
- package/dist/plugin/mock-json-plugin.test.d.ts +2 -0
- package/dist/plugin/mock-json-plugin.test.d.ts.map +1 -0
- package/dist/plugin/mock-json-plugin.test.js +164 -0
- package/dist/plugin/mock-json-plugin.test.js.map +1 -0
- package/dist/query-filter/change-conflict-in-version.d.ts.map +1 -1
- package/dist/query-filter/change-has-label.d.ts +9 -3
- package/dist/query-filter/change-has-label.d.ts.map +1 -1
- package/dist/query-filter/change-has-label.js +7 -4
- package/dist/query-filter/change-has-label.js.map +1 -1
- package/dist/query-filter/change-has-label.test.js +36 -11
- package/dist/query-filter/change-has-label.test.js.map +1 -1
- package/dist/query-filter/change-is-leaf.d.ts.map +1 -1
- package/dist/query-filter/change-set-element-in-ancestry-of.d.ts +30 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.js +46 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.js.map +1 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.test.d.ts +2 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.test.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.test.js +323 -0
- package/dist/query-filter/change-set-element-in-ancestry-of.test.js.map +1 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.d.ts +20 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.js +36 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.js.map +1 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.test.d.ts +2 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.test.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.test.js +369 -0
- package/dist/query-filter/change-set-element-in-symmetric-difference.test.js.map +1 -0
- package/dist/query-filter/change-set-element-is-leaf-of.d.ts +29 -0
- package/dist/query-filter/change-set-element-is-leaf-of.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-is-leaf-of.js +91 -0
- package/dist/query-filter/change-set-element-is-leaf-of.js.map +1 -0
- package/dist/query-filter/change-set-element-is-leaf-of.test.d.ts +2 -0
- package/dist/query-filter/change-set-element-is-leaf-of.test.d.ts.map +1 -0
- package/dist/query-filter/change-set-element-is-leaf-of.test.js +515 -0
- package/dist/query-filter/change-set-element-is-leaf-of.test.js.map +1 -0
- package/dist/query-filter/change-set-has-label.d.ts +19 -3
- package/dist/query-filter/change-set-has-label.d.ts.map +1 -1
- package/dist/query-filter/change-set-has-label.js +17 -4
- package/dist/query-filter/change-set-has-label.js.map +1 -1
- package/dist/query-filter/change-set-has-label.test.js +13 -20
- package/dist/query-filter/change-set-has-label.test.js.map +1 -1
- package/dist/query-filter/change-set-is-ancestor-of.d.ts +51 -0
- package/dist/query-filter/change-set-is-ancestor-of.d.ts.map +1 -0
- package/dist/query-filter/change-set-is-ancestor-of.js +63 -0
- package/dist/query-filter/change-set-is-ancestor-of.js.map +1 -0
- package/dist/query-filter/change-set-is-ancestor-of.test.d.ts +2 -0
- package/dist/query-filter/change-set-is-ancestor-of.test.d.ts.map +1 -0
- package/dist/query-filter/change-set-is-ancestor-of.test.js +153 -0
- package/dist/query-filter/change-set-is-ancestor-of.test.js.map +1 -0
- package/dist/query-filter/change-set-is-descendant-of.d.ts +44 -0
- package/dist/query-filter/change-set-is-descendant-of.d.ts.map +1 -0
- package/dist/query-filter/change-set-is-descendant-of.js +56 -0
- package/dist/query-filter/change-set-is-descendant-of.js.map +1 -0
- package/dist/query-filter/change-set-is-descendant-of.test.d.ts +2 -0
- package/dist/query-filter/change-set-is-descendant-of.test.d.ts.map +1 -0
- package/dist/query-filter/change-set-is-descendant-of.test.js +137 -0
- package/dist/query-filter/change-set-is-descendant-of.test.js.map +1 -0
- package/dist/query-filter/index.d.ts +5 -6
- package/dist/query-filter/index.d.ts.map +1 -1
- package/dist/query-filter/index.js +5 -6
- package/dist/query-filter/index.js.map +1 -1
- package/dist/query-filter/version-change-in-difference.d.ts.map +1 -1
- package/dist/query-filter/version-change-in-symmetric-difference.d.ts.map +1 -1
- package/dist/repository/comparison-example.js +173 -0
- package/dist/repository/comparison-example.js.map +1 -0
- package/dist/repository/entity-repository.d.ts +53 -0
- package/dist/repository/entity-repository.d.ts.map +1 -0
- package/dist/repository/entity-repository.js +187 -0
- package/dist/repository/entity-repository.js.map +1 -0
- package/dist/repository/entity-repository.test.d.ts +2 -0
- package/dist/repository/entity-repository.test.d.ts.map +1 -0
- package/dist/repository/entity-repository.test.js +94 -0
- package/dist/repository/entity-repository.test.js.map +1 -0
- package/dist/repository/example.d.ts +6 -0
- package/dist/repository/example.d.ts.map +1 -0
- package/dist/repository/example.js +87 -0
- package/dist/repository/example.js.map +1 -0
- package/dist/repository/file-repository.d.ts +39 -0
- package/dist/repository/file-repository.d.ts.map +1 -0
- package/dist/repository/file-repository.js +93 -0
- package/dist/repository/file-repository.js.map +1 -0
- package/dist/repository/file-repository.test.d.ts +2 -0
- package/dist/repository/file-repository.test.d.ts.map +1 -0
- package/dist/repository/file-repository.test.js +165 -0
- package/dist/repository/file-repository.test.js.map +1 -0
- package/dist/repository/index.d.ts +6 -0
- package/dist/repository/index.d.ts.map +1 -0
- package/dist/repository/index.js +6 -0
- package/dist/repository/index.js.map +1 -0
- package/dist/repository/integration.test.d.ts +2 -0
- package/dist/repository/integration.test.d.ts.map +1 -0
- package/dist/repository/integration.test.js +136 -0
- package/dist/repository/integration.test.js.map +1 -0
- package/dist/repository/key-value-repository.d.ts +30 -0
- package/dist/repository/key-value-repository.d.ts.map +1 -0
- package/dist/repository/key-value-repository.js +60 -0
- package/dist/repository/key-value-repository.js.map +1 -0
- package/dist/repository/key-value-repository.test.d.ts +2 -0
- package/dist/repository/key-value-repository.test.d.ts.map +1 -0
- package/dist/repository/key-value-repository.test.js +122 -0
- package/dist/repository/key-value-repository.test.js.map +1 -0
- package/dist/repository/markdown-plugin-example.js +118 -0
- package/dist/repository/markdown-plugin-example.js.map +1 -0
- package/dist/repository/query-builder.d.ts +69 -0
- package/dist/repository/query-builder.d.ts.map +1 -0
- package/dist/repository/query-builder.js +155 -0
- package/dist/repository/query-builder.js.map +1 -0
- package/dist/repository/query-builder.test.d.ts +2 -0
- package/dist/repository/query-builder.test.d.ts.map +1 -0
- package/dist/repository/query-builder.test.js +244 -0
- package/dist/repository/query-builder.test.js.map +1 -0
- package/dist/repository/repository-manager.d.ts +27 -0
- package/dist/repository/repository-manager.d.ts.map +1 -0
- package/dist/repository/repository-manager.js +19 -0
- package/dist/repository/repository-manager.js.map +1 -0
- package/dist/repository/repository-manager.test.d.ts +2 -0
- package/dist/repository/repository-manager.test.d.ts.map +1 -0
- package/dist/repository/repository-manager.test.js +65 -0
- package/dist/repository/repository-manager.test.js.map +1 -0
- package/dist/repository/test-helpers.js +402 -0
- package/dist/repository/test-helpers.js.map +1 -0
- package/dist/schema-definition/definition.d.ts +406 -0
- package/dist/schema-definition/definition.d.ts.map +1 -0
- package/dist/schema-definition/definition.js +82 -0
- package/dist/schema-definition/definition.js.map +1 -0
- package/dist/schema-definition/definition.test-d.d.ts +2 -0
- package/dist/schema-definition/definition.test-d.d.ts.map +1 -0
- package/dist/schema-definition/definition.test-d.js +177 -0
- package/dist/schema-definition/definition.test-d.js.map +1 -0
- package/dist/schema-definition/definition.test.d.ts +2 -0
- package/dist/schema-definition/definition.test.d.ts.map +1 -0
- package/dist/schema-definition/definition.test.js +324 -0
- package/dist/schema-definition/definition.test.js.map +1 -0
- package/dist/schema-definition/index.d.ts +4 -0
- package/dist/schema-definition/index.d.ts.map +1 -0
- package/dist/schema-definition/index.js +4 -0
- package/dist/schema-definition/index.js.map +1 -0
- package/dist/schema-definition/json-type.d.ts +24 -0
- package/dist/schema-definition/json-type.d.ts.map +1 -0
- package/dist/schema-definition/json-type.js +42 -0
- package/dist/schema-definition/json-type.js.map +1 -0
- package/dist/schema-definition/json-type.test.d.ts +2 -0
- package/dist/schema-definition/json-type.test.d.ts.map +1 -0
- package/dist/schema-definition/json-type.test.js +21 -0
- package/dist/schema-definition/json-type.test.js.map +1 -0
- package/dist/schema-definition/lix-generated.test.d.ts +2 -0
- package/dist/schema-definition/lix-generated.test.d.ts.map +1 -0
- package/dist/schema-definition/lix-generated.test.js +127 -0
- package/dist/schema-definition/lix-generated.test.js.map +1 -0
- package/dist/schema-definition/validate-lix-schema.d.ts +65 -0
- package/dist/schema-definition/validate-lix-schema.d.ts.map +1 -0
- package/dist/schema-definition/validate-lix-schema.js +93 -0
- package/dist/schema-definition/validate-lix-schema.js.map +1 -0
- package/dist/schema-definition/validate-lix-schema.test.d.ts +2 -0
- package/dist/schema-definition/validate-lix-schema.test.d.ts.map +1 -0
- package/dist/schema-definition/validate-lix-schema.test.js +73 -0
- package/dist/schema-definition/validate-lix-schema.test.js.map +1 -0
- package/dist/server-protocol-handler/create-server-protocol-handler.d.ts +0 -1
- package/dist/server-protocol-handler/create-server-protocol-handler.d.ts.map +1 -1
- package/dist/server-protocol-handler/create-server-protocol-handler.js +0 -2
- package/dist/server-protocol-handler/create-server-protocol-handler.js.map +1 -1
- package/dist/server-protocol-handler/environment/create-in-memory-environment.d.ts.map +1 -1
- package/dist/server-protocol-handler/environment/create-in-memory-environment.js +5 -20
- package/dist/server-protocol-handler/environment/create-in-memory-environment.js.map +1 -1
- package/dist/server-protocol-handler/environment/create-in-memory-environment.test.js +13 -14
- package/dist/server-protocol-handler/environment/create-in-memory-environment.test.js.map +1 -1
- package/dist/server-protocol-handler/environment/environment.d.ts +0 -4
- package/dist/server-protocol-handler/environment/environment.d.ts.map +1 -1
- package/dist/server-protocol-handler/routes/get-v1.d.ts.map +1 -1
- package/dist/server-protocol-handler/routes/get-v1.js +1 -1
- package/dist/server-protocol-handler/routes/get-v1.js.map +1 -1
- package/dist/server-protocol-handler/routes/get-v1.test.js +11 -12
- package/dist/server-protocol-handler/routes/get-v1.test.js.map +1 -1
- package/dist/server-protocol-handler/routes/new-v1.d.ts.map +1 -1
- package/dist/server-protocol-handler/routes/new-v1.js +3 -5
- package/dist/server-protocol-handler/routes/new-v1.js.map +1 -1
- package/dist/server-protocol-handler/routes/new-v1.test.js +7 -8
- package/dist/server-protocol-handler/routes/new-v1.test.js.map +1 -1
- package/dist/server-protocol-handler/routes/pull-v1.test.js +48 -32
- package/dist/server-protocol-handler/routes/pull-v1.test.js.map +1 -1
- package/dist/server-protocol-handler/routes/push-v1.d.ts.map +1 -1
- package/dist/server-protocol-handler/routes/push-v1.js +2 -0
- package/dist/server-protocol-handler/routes/push-v1.js.map +1 -1
- package/dist/server-protocol-handler/routes/push-v1.test.js +22 -26
- package/dist/server-protocol-handler/routes/push-v1.test.js.map +1 -1
- package/dist/services/env-variables/index.d.ts +1 -1
- package/dist/services/env-variables/index.js +2 -2
- package/dist/services/env-variables/index.js.map +1 -1
- package/dist/services/telemetry/capture.d.ts.map +1 -1
- package/dist/snapshot/create-snapshot.d.ts +3 -14
- package/dist/snapshot/create-snapshot.d.ts.map +1 -1
- package/dist/snapshot/create-snapshot.js +14 -19
- package/dist/snapshot/create-snapshot.js.map +1 -1
- package/dist/snapshot/create-snapshot.test.js +49 -20
- package/dist/snapshot/create-snapshot.test.js.map +1 -1
- package/dist/snapshot/index.d.ts +1 -0
- package/dist/snapshot/index.d.ts.map +1 -1
- package/dist/snapshot/index.js +1 -0
- package/dist/snapshot/index.js.map +1 -1
- package/dist/snapshot/json-sha-256.d.ts +2 -1
- package/dist/snapshot/json-sha-256.d.ts.map +1 -1
- package/dist/snapshot/json-sha-256.js +1 -3
- package/dist/snapshot/json-sha-256.js.map +1 -1
- package/dist/snapshot/json-sha-256.test.js +40 -2
- package/dist/snapshot/json-sha-256.test.js.map +1 -1
- package/dist/snapshot/mock-json-snapshot.d.ts +1 -1
- package/dist/snapshot/mock-json-snapshot.d.ts.map +1 -1
- package/dist/snapshot/schema.d.ts +8 -0
- package/dist/snapshot/schema.d.ts.map +1 -0
- package/dist/snapshot/schema.js +12 -0
- package/dist/snapshot/schema.js.map +1 -0
- package/dist/snapshot/schema.test.d.ts +2 -0
- package/dist/snapshot/schema.test.d.ts.map +1 -0
- package/dist/snapshot/schema.test.js +116 -0
- package/dist/snapshot/schema.test.js.map +1 -0
- package/dist/state/create-changeset-for-transaction.d.ts +15 -0
- package/dist/state/create-changeset-for-transaction.d.ts.map +1 -0
- package/dist/state/create-changeset-for-transaction.js +237 -0
- package/dist/state/create-changeset-for-transaction.js.map +1 -0
- package/dist/state/entity-view-builder.d.ts +145 -0
- package/dist/state/entity-view-builder.d.ts.map +1 -0
- package/dist/state/entity-view-builder.js +280 -0
- package/dist/state/entity-view-builder.js.map +1 -0
- package/dist/state/entity-view-builder.test.d.ts +2 -0
- package/dist/state/entity-view-builder.test.d.ts.map +1 -0
- package/dist/state/entity-view-builder.test.js +523 -0
- package/dist/state/entity-view-builder.test.js.map +1 -0
- package/dist/state/get-version-record-by-id-or-throw.d.ts +6 -0
- package/dist/state/get-version-record-by-id-or-throw.d.ts.map +1 -0
- package/dist/state/get-version-record-by-id-or-throw.js +36 -0
- package/dist/state/get-version-record-by-id-or-throw.js.map +1 -0
- package/dist/state/handle-state-mutation.d.ts +18 -0
- package/dist/state/handle-state-mutation.d.ts.map +1 -0
- package/dist/state/handle-state-mutation.js +352 -0
- package/dist/state/handle-state-mutation.js.map +1 -0
- package/dist/state/handle-state-mutation.test.d.ts +2 -0
- package/dist/state/handle-state-mutation.test.d.ts.map +1 -0
- package/dist/state/handle-state-mutation.test.js +632 -0
- package/dist/state/handle-state-mutation.test.js.map +1 -0
- package/dist/state/schema.bench.d.ts +2 -0
- package/dist/state/schema.bench.d.ts.map +1 -0
- package/dist/state/schema.bench.js +36 -0
- package/dist/state/schema.bench.js.map +1 -0
- package/dist/state/schema.d.ts +56 -0
- package/dist/state/schema.d.ts.map +1 -0
- package/dist/state/schema.js +1052 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/state/schema.test.d.ts +2 -0
- package/dist/state/schema.test.d.ts.map +1 -0
- package/dist/state/schema.test.js +2030 -0
- package/dist/state/schema.test.js.map +1 -0
- package/dist/state/validate-state-mutation.d.ts +13 -0
- package/dist/state/validate-state-mutation.d.ts.map +1 -0
- package/dist/state/validate-state-mutation.js +485 -0
- package/dist/state/validate-state-mutation.js.map +1 -0
- package/dist/state/validate-state-mutation.test.d.ts +2 -0
- package/dist/state/validate-state-mutation.test.d.ts.map +1 -0
- package/dist/state/validate-state-mutation.test.js +2024 -0
- package/dist/state/validate-state-mutation.test.js.map +1 -0
- package/dist/state-history/schema.d.ts +58 -0
- package/dist/state-history/schema.d.ts.map +1 -0
- package/dist/state-history/schema.js +104 -0
- package/dist/state-history/schema.js.map +1 -0
- package/dist/state-history/schema.test.d.ts +2 -0
- package/dist/state-history/schema.test.d.ts.map +1 -0
- package/dist/state-history/schema.test.js +701 -0
- package/dist/state-history/schema.test.js.map +1 -0
- package/dist/stored-schema/index.d.ts +2 -0
- package/dist/stored-schema/index.d.ts.map +1 -0
- package/dist/stored-schema/index.js +2 -0
- package/dist/stored-schema/index.js.map +1 -0
- package/dist/stored-schema/schema.d.ts +25 -0
- package/dist/stored-schema/schema.d.ts.map +1 -0
- package/dist/stored-schema/schema.js +48 -0
- package/dist/stored-schema/schema.js.map +1 -0
- package/dist/stored-schema/schema.test.d.ts +2 -0
- package/dist/stored-schema/schema.test.d.ts.map +1 -0
- package/dist/stored-schema/schema.test.js +192 -0
- package/dist/stored-schema/schema.test.js.map +1 -0
- package/dist/sync/get-diffing-rows.d.ts +12 -0
- package/dist/sync/get-diffing-rows.d.ts.map +1 -1
- package/dist/sync/get-diffing-rows.js +14 -0
- package/dist/sync/get-diffing-rows.js.map +1 -1
- package/dist/sync/merge-state.d.ts.map +1 -1
- package/dist/sync/merge-state.js +2 -1
- package/dist/sync/merge-state.js.map +1 -1
- package/dist/sync/pull-from-server.d.ts.map +1 -1
- package/dist/sync/pull-from-server.js +2 -1
- package/dist/sync/pull-from-server.js.map +1 -1
- package/dist/sync/pull-from-server.test.js +32 -28
- package/dist/sync/pull-from-server.test.js.map +1 -1
- package/dist/sync/push-to-server.d.ts +10 -1
- package/dist/sync/push-to-server.d.ts.map +1 -1
- package/dist/sync/push-to-server.js +10 -1
- package/dist/sync/push-to-server.js.map +1 -1
- package/dist/sync/push-to-server.test.js +62 -63
- package/dist/sync/push-to-server.test.js.map +1 -1
- package/dist/sync/sync-process.d.ts +1 -1
- package/dist/sync/sync-process.d.ts.map +1 -1
- package/dist/sync/sync-process.js +1 -2
- package/dist/sync/sync-process.js.map +1 -1
- package/dist/sync/sync-process.test.js +20 -17
- package/dist/sync/sync-process.test.js.map +1 -1
- package/dist/thread/create-thread-comment.d.ts +18 -0
- package/dist/thread/create-thread-comment.d.ts.map +1 -0
- package/dist/thread/create-thread-comment.js +47 -0
- package/dist/thread/create-thread-comment.js.map +1 -0
- package/dist/thread/create-thread-comment.test.d.ts +2 -0
- package/dist/thread/create-thread-comment.test.d.ts.map +1 -0
- package/dist/thread/create-thread-comment.test.js +51 -0
- package/dist/thread/create-thread-comment.test.js.map +1 -0
- package/dist/thread/create-thread.d.ts +28 -0
- package/dist/thread/create-thread.d.ts.map +1 -0
- package/dist/thread/create-thread.js +58 -0
- package/dist/thread/create-thread.js.map +1 -0
- package/dist/thread/create-thread.test.d.ts +2 -0
- package/dist/thread/create-thread.test.d.ts.map +1 -0
- package/dist/thread/create-thread.test.js +26 -0
- package/dist/thread/create-thread.test.js.map +1 -0
- package/dist/thread/index.d.ts +4 -0
- package/dist/thread/index.d.ts.map +1 -0
- package/dist/thread/index.js +4 -0
- package/dist/thread/index.js.map +1 -0
- package/dist/thread/schema.d.ts +59 -0
- package/dist/thread/schema.d.ts.map +1 -0
- package/dist/thread/schema.js +66 -0
- package/dist/thread/schema.js.map +1 -0
- package/dist/thread/schema.test.d.ts +2 -0
- package/dist/thread/schema.test.d.ts.map +1 -0
- package/dist/thread/schema.test.js +60 -0
- package/dist/thread/schema.test.js.map +1 -0
- package/dist/version/create-version.d.ts +9 -17
- package/dist/version/create-version.d.ts.map +1 -1
- package/dist/version/create-version.js +30 -57
- package/dist/version/create-version.js.map +1 -1
- package/dist/version/create-version.test.js +70 -113
- package/dist/version/create-version.test.js.map +1 -1
- package/dist/version/index.d.ts +1 -5
- package/dist/version/index.d.ts.map +1 -1
- package/dist/version/index.js +1 -5
- package/dist/version/index.js.map +1 -1
- package/dist/version/schema.d.ts +73 -0
- package/dist/version/schema.d.ts.map +1 -0
- package/dist/version/schema.js +135 -0
- package/dist/version/schema.js.map +1 -0
- package/dist/version/schema.test.d.ts +2 -0
- package/dist/version/schema.test.d.ts.map +1 -0
- package/dist/version/schema.test.js +661 -0
- package/dist/version/schema.test.js.map +1 -0
- package/dist/version/switch-version.d.ts +4 -4
- package/dist/version/switch-version.d.ts.map +1 -1
- package/dist/version/switch-version.js +6 -62
- package/dist/version/switch-version.js.map +1 -1
- package/dist/version/switch-version.test.js +14 -214
- package/dist/version/switch-version.test.js.map +1 -1
- package/dist/zettel-ast/index.d.ts +11 -0
- package/dist/zettel-ast/index.d.ts.map +1 -0
- package/dist/zettel-ast/index.js +11 -0
- package/dist/zettel-ast/index.js.map +1 -0
- package/package.json +10 -9
- package/src/account/create-account.test.ts +49 -4
- package/src/account/create-account.ts +36 -6
- package/src/account/index.ts +5 -1
- package/src/account/schema.test.ts +370 -0
- package/src/account/schema.ts +76 -0
- package/src/account/switch-account.test.ts +29 -6
- package/src/account/switch-account.ts +12 -3
- package/src/change/index.ts +1 -2
- package/src/change/schema.test.ts +284 -0
- package/src/change/schema.ts +93 -0
- package/src/change-author/index.ts +1 -0
- package/src/change-author/schema.test.ts +300 -0
- package/src/change-author/schema.ts +48 -0
- package/src/change-conflict/create-change-conflict.test.ts +14 -11
- package/src/change-conflict/create-change-conflict.ts +29 -6
- package/src/change-conflict/detect-change-conflicts.test.ts +18 -15
- package/src/change-conflict/detect-change-conflicts.ts +3 -0
- package/src/change-conflict/detect-diverging-entity-conflict.test.ts +24 -21
- package/src/change-conflict/detect-diverging-entity-conflict.ts +4 -1
- package/src/change-conflict/garbage-collect-change-conflicts.test.ts +16 -15
- package/src/change-conflict/garbage-collect-change-conflicts.ts +3 -0
- package/src/change-conflict/resolve-conflict-by-selecting.test.ts +18 -8
- package/src/change-conflict/resolve-conflict-by-selecting.ts +3 -2
- package/src/change-proposal/create-change-proposal.test.ts +106 -0
- package/src/change-proposal/create-change-proposal.ts +71 -0
- package/src/change-proposal/database-schema.test.ts +180 -0
- package/src/change-proposal/database-schema.ts +32 -0
- package/src/change-proposal/index.ts +2 -0
- package/src/change-set/apply-change-set.test.ts +469 -0
- package/src/change-set/apply-change-set.ts +186 -0
- package/src/change-set/create-change-set.test.ts +126 -27
- package/src/change-set/create-change-set.ts +117 -41
- package/src/change-set/create-checkpoint.test.ts +387 -0
- package/src/change-set/create-checkpoint.ts +101 -0
- package/src/change-set/create-merge-change-set.test.ts +237 -0
- package/src/change-set/create-merge-change-set.ts +99 -0
- package/src/change-set/create-transition-change-set.test.ts +245 -0
- package/src/change-set/create-transition-change-set.ts +149 -0
- package/src/change-set/create-undo-change-set.test.ts +329 -0
- package/src/change-set/create-undo-change-set.ts +147 -0
- package/src/change-set/index.ts +17 -1
- package/src/change-set/schema.test.ts +981 -0
- package/src/change-set/schema.ts +207 -0
- package/src/database/execute-sync.test.ts +60 -72
- package/src/database/execute-sync.ts +26 -27
- package/src/database/graph-traversal-mode.ts +75 -0
- package/src/database/index.ts +3 -2
- package/src/database/init-db.ts +82 -66
- package/src/database/kysely-plugin/json-column-plugin.ts +215 -0
- package/src/database/kysely-plugin/parse-jsonb-plugin-v1.ts +5 -10
- package/src/database/kysely-plugin/parse-jsonb-plugin-v2.ts +1 -1
- package/src/database/kysely-plugin/serialize-jsonb-plugin.test.ts +177 -2
- package/src/database/kysely-plugin/serialize-jsonb-plugin.ts +186 -87
- package/src/database/kysely-plugin/view-insert-returning-error-plugin.test.ts +62 -0
- package/src/database/kysely-plugin/view-insert-returning-error-plugin.ts +49 -0
- package/src/database/schema.ts +100 -267
- package/src/entity-views/entity-state-all.test.ts +445 -0
- package/src/entity-views/entity-state-all.ts +506 -0
- package/src/entity-views/entity-state-history.test.ts +325 -0
- package/src/entity-views/entity-state-history.ts +226 -0
- package/src/entity-views/entity-state.test.ts +592 -0
- package/src/entity-views/entity-state.ts +502 -0
- package/src/entity-views/entity-view-builder.test.ts +293 -0
- package/src/entity-views/entity-view-builder.ts +148 -0
- package/src/entity-views/index.ts +1 -0
- package/src/entity-views/types.test.ts +99 -0
- package/src/entity-views/types.ts +328 -0
- package/src/file/file-handlers.test.ts +174 -0
- package/src/file/file-handlers.ts +364 -0
- package/src/file/index.ts +5 -1
- package/src/file/materialize-file-data-at-changeset.ts +123 -0
- package/src/file/materialize-file-data.test.ts +107 -0
- package/src/file/materialize-file-data.ts +120 -0
- package/src/file/schema.test.ts +990 -0
- package/src/file/schema.ts +300 -0
- package/src/file/store-detected-change-schema.test.ts +248 -0
- package/src/file/store-detected-change-schema.ts +52 -0
- package/src/file/unknown-file-fallback-plugin.test.ts +368 -0
- package/src/file/unknown-file-fallback-plugin.ts +95 -0
- package/src/hooks/create-hooks.test.ts +125 -0
- package/src/hooks/create-hooks.ts +101 -0
- package/src/hooks/index.ts +1 -0
- package/src/index.ts +10 -6
- package/src/key-value/index.ts +1 -0
- package/src/key-value/schema.test.ts +179 -0
- package/src/key-value/schema.ts +37 -0
- package/src/label/create-label.test.ts +234 -0
- package/src/label/create-label.ts +61 -0
- package/src/label/index.ts +2 -0
- package/src/label/schema.test.ts +92 -0
- package/src/label/schema.ts +40 -0
- package/src/lix/index.ts +3 -5
- package/src/lix/new-lix.test.ts +213 -17
- package/src/lix/new-lix.ts +395 -8
- package/src/lix/open-lix.test.ts +65 -26
- package/src/lix/open-lix.ts +131 -22
- package/src/lix/storage/in-memory.test.ts +180 -0
- package/src/lix/storage/in-memory.ts +69 -0
- package/src/lix/storage/lix-storage-adapter.ts +16 -0
- package/src/lix/storage/opfs.test.ts +215 -0
- package/src/lix/storage/opfs.ts +175 -0
- package/src/log/create-lix-own-log.test.ts +119 -0
- package/src/log/create-lix-own-log.ts +124 -0
- package/src/log/create-log.ts +52 -0
- package/src/log/index.ts +2 -0
- package/src/log/schema.test.ts +140 -0
- package/src/log/schema.ts +55 -0
- package/src/observe/create-observe.test.ts +501 -0
- package/src/observe/create-observe.ts +146 -0
- package/src/observe/index.ts +1 -0
- package/src/observe/lix-observable.test.ts +247 -0
- package/src/observe/lix-observable.ts +92 -0
- package/src/plugin/index.ts +2 -2
- package/src/plugin/lix-plugin.test-d.ts +26 -15
- package/src/plugin/lix-plugin.ts +41 -50
- package/src/plugin/mock-json-plugin.flatten.ts +161 -0
- package/src/plugin/mock-json-plugin.test.ts +214 -0
- package/src/plugin/mock-json-plugin.ts +113 -0
- package/src/query-filter/change-has-label.test.ts +38 -11
- package/src/query-filter/change-has-label.ts +8 -4
- package/src/query-filter/change-set-element-in-ancestry-of.test.ts +354 -0
- package/src/query-filter/change-set-element-in-ancestry-of.ts +64 -0
- package/src/query-filter/change-set-element-in-symmetric-difference.test.ts +410 -0
- package/src/{change-set → query-filter}/change-set-element-in-symmetric-difference.ts +2 -1
- package/src/query-filter/change-set-element-is-leaf-of.test.ts +564 -0
- package/src/query-filter/change-set-element-is-leaf-of.ts +110 -0
- package/src/query-filter/change-set-has-label.test.ts +13 -21
- package/src/query-filter/change-set-has-label.ts +18 -4
- package/src/query-filter/change-set-is-ancestor-of.test.ts +178 -0
- package/src/query-filter/change-set-is-ancestor-of.ts +77 -0
- package/src/query-filter/change-set-is-descendant-of.test.ts +169 -0
- package/src/query-filter/change-set-is-descendant-of.ts +70 -0
- package/src/query-filter/index.ts +5 -6
- package/src/schema-definition/definition.test-d.ts +253 -0
- package/src/schema-definition/definition.test.ts +377 -0
- package/src/schema-definition/definition.ts +445 -0
- package/src/schema-definition/index.ts +13 -0
- package/src/schema-definition/json-type.test.ts +30 -0
- package/src/schema-definition/json-type.ts +53 -0
- package/src/schema-definition/validate-lix-schema.test.ts +85 -0
- package/src/schema-definition/validate-lix-schema.ts +108 -0
- package/src/server-protocol-handler/create-server-protocol-handler.ts +0 -4
- package/src/server-protocol-handler/environment/create-in-memory-environment.test.ts +13 -14
- package/src/server-protocol-handler/environment/create-in-memory-environment.ts +5 -24
- package/src/server-protocol-handler/environment/environment.ts +0 -5
- package/src/server-protocol-handler/routes/get-v1.test.ts +11 -12
- package/src/server-protocol-handler/routes/get-v1.ts +3 -1
- package/src/server-protocol-handler/routes/new-v1.test.ts +7 -8
- package/src/server-protocol-handler/routes/new-v1.ts +3 -5
- package/src/server-protocol-handler/routes/pull-v1.test.ts +49 -33
- package/src/server-protocol-handler/routes/pull-v1.ts +1 -1
- package/src/server-protocol-handler/routes/push-v1.test.ts +26 -27
- package/src/server-protocol-handler/routes/push-v1.ts +4 -1
- package/src/snapshot/schema.test.ts +155 -0
- package/src/snapshot/schema.ts +21 -0
- package/src/state/create-changeset-for-transaction.ts +321 -0
- package/src/state/get-version-record-by-id-or-throw.ts +51 -0
- package/src/state/handle-state-mutation.test.ts +761 -0
- package/src/state/handle-state-mutation.ts +418 -0
- package/src/state/schema.bench.ts +43 -0
- package/src/state/schema.test.ts +2416 -0
- package/src/state/schema.ts +1288 -0
- package/src/state/validate-state-mutation.test.ts +2353 -0
- package/src/state/validate-state-mutation.ts +664 -0
- package/src/state-history/schema.test.ts +827 -0
- package/src/state-history/schema.ts +198 -0
- package/src/stored-schema/index.ts +1 -0
- package/src/stored-schema/schema.test.ts +240 -0
- package/src/stored-schema/schema.ts +67 -0
- package/src/sync/get-diffing-rows.ts +16 -0
- package/src/sync/merge-state.ts +7 -4
- package/src/sync/pull-from-server.test.ts +33 -28
- package/src/sync/pull-from-server.ts +4 -2
- package/src/sync/push-to-server.test.ts +77 -81
- package/src/sync/push-to-server.ts +11 -2
- package/src/sync/sync-process.test.ts +21 -18
- package/src/sync/sync-process.ts +2 -3
- package/src/thread/create-thread-comment.test.ts +63 -0
- package/src/thread/create-thread-comment.ts +56 -0
- package/src/thread/create-thread.test.ts +32 -0
- package/src/thread/create-thread.ts +83 -0
- package/src/thread/index.ts +8 -0
- package/src/thread/schema.test.ts +76 -0
- package/src/thread/schema.ts +85 -0
- package/src/version/create-version.test.ts +78 -125
- package/src/version/create-version.ts +37 -64
- package/src/version/index.ts +5 -6
- package/src/version/schema.test.ts +794 -0
- package/src/version/schema.ts +149 -0
- package/src/version/switch-version.test.ts +14 -275
- package/src/version/switch-version.ts +8 -78
- package/src/zettel-ast/index.ts +10 -0
- package/src/account/database-schema.test.ts +0 -184
- package/src/account/database-schema.ts +0 -54
- package/src/change/apply-changes.test.ts +0 -268
- package/src/change/apply-changes.ts +0 -114
- package/src/change/create-change.test.ts +0 -296
- package/src/change/create-change.ts +0 -129
- package/src/change/mock-change.ts +0 -21
- package/src/change-schema/README.md +0 -3
- package/src/change-schema/index.ts +0 -4
- package/src/change-schema/types.test-d.ts +0 -52
- package/src/change-schema/types.ts +0 -53
- package/src/change-set/change-set-element-in-symmetric-difference.test.ts +0 -128
- package/src/database/apply-schema.ts +0 -272
- package/src/database/init-db.test.ts +0 -626
- package/src/database/mutation-log/database-schema.ts +0 -128
- package/src/database/mutation-log/lix-session.ts +0 -19
- package/src/discussion/create-comment.ts +0 -18
- package/src/discussion/create-discussion.test.ts +0 -45
- package/src/discussion/create-discussion.ts +0 -48
- package/src/discussion/index.ts +0 -2
- package/src/file/validate-file-path.test.ts +0 -44
- package/src/file/validate-file-path.ts +0 -60
- package/src/file-queue/file-handlers.ts +0 -267
- package/src/file-queue/file-queue-process.test.ts +0 -456
- package/src/file-queue/file-queue-process.ts +0 -108
- package/src/file-queue/file-queue-settled.test.ts +0 -56
- package/src/file-queue/file-queue-settled.ts +0 -31
- package/src/file-queue/index.ts +0 -1
- package/src/file-queue/with-skip-file-queue.test.ts +0 -158
- package/src/file-queue/with-skip-file-queue.ts +0 -33
- package/src/key-value/database-schema.test.ts +0 -140
- package/src/key-value/database-schema.ts +0 -66
- package/src/lix/close-lix.ts +0 -8
- package/src/lix/merge.get-leaf-changes-only-in-source.test.ts +0 -143
- package/src/lix/merge.get-leaf-changes-only-in-source.ts +0 -46
- package/src/lix/merge.test.ts +0 -858
- package/src/lix/merge.ts +0 -244
- package/src/lix/open-lix-in-memory.test.ts +0 -34
- package/src/lix/open-lix-in-memory.ts +0 -28
- package/src/lix/to-blob.ts +0 -14
- package/src/own-change-control/apply-own-change.test.ts +0 -361
- package/src/own-change-control/apply-own-change.ts +0 -110
- package/src/own-change-control/change-controlled-tables.test.ts +0 -69
- package/src/own-change-control/change-controlled-tables.ts +0 -102
- package/src/own-change-control/database-triggers.test.ts +0 -259
- package/src/own-change-control/database-triggers.ts +0 -189
- package/src/own-change-control/index.ts +0 -1
- package/src/own-change-control/with-skip-own-change-control.test.ts +0 -57
- package/src/own-change-control/with-skip-own-change-control.ts +0 -34
- package/src/plugin/load-plugin.ts +0 -37
- package/src/plugin/with-transaction.ts +0 -22
- package/src/query-filter/change-conflict-in-version.test.ts +0 -62
- package/src/query-filter/change-conflict-in-version.ts +0 -25
- package/src/query-filter/change-in-version.test.ts +0 -82
- package/src/query-filter/change-in-version.ts +0 -31
- package/src/query-filter/change-is-leaf-in-version.test.ts +0 -77
- package/src/query-filter/change-is-leaf-in-version.ts +0 -36
- package/src/query-filter/change-is-leaf-of.bench.ts +0 -175
- package/src/query-filter/change-is-leaf-of.test.ts +0 -84
- package/src/query-filter/change-is-leaf-of.ts +0 -46
- package/src/query-filter/change-is-leaf.test.ts +0 -140
- package/src/query-filter/change-is-leaf.ts +0 -25
- package/src/query-filter/change-is-lowest-common-ancestor-of.test.ts +0 -173
- package/src/query-filter/change-is-lowest-common-ancestor-of.ts +0 -57
- package/src/query-filter/version-change-in-difference.test.ts +0 -105
- package/src/query-filter/version-change-in-difference.ts +0 -37
- package/src/query-filter/version-change-in-symmetric-difference.test.ts +0 -104
- package/src/query-filter/version-change-in-symmetric-difference.ts +0 -52
- package/src/snapshot/create-snapshot.test.ts +0 -68
- package/src/snapshot/create-snapshot.ts +0 -40
- package/src/snapshot/index.ts +0 -2
- package/src/snapshot/json-sha-256.test.ts +0 -12
- package/src/snapshot/json-sha-256.ts +0 -35
- package/src/snapshot/mock-json-snapshot.ts +0 -14
- package/src/version/merge-version.test.ts +0 -530
- package/src/version/merge-version.ts +0 -88
- package/src/version/update-changes-in-version.test.ts +0 -371
- package/src/version/update-changes-in-version.ts +0 -47
|
@@ -0,0 +1,2024 @@
|
|
|
1
|
+
import { test, expect } from "vitest";
|
|
2
|
+
import { openLix } from "../lix/open-lix.js";
|
|
3
|
+
import { validateStateMutation } from "./validate-state-mutation.js";
|
|
4
|
+
import { sql } from "kysely";
|
|
5
|
+
import { createVersion } from "../version/create-version.js";
|
|
6
|
+
test("throws if the schema is not a valid lix schema", async () => {
|
|
7
|
+
const lix = await openLix({});
|
|
8
|
+
const schema = {
|
|
9
|
+
type: "object",
|
|
10
|
+
"x-lix-version": "1.0",
|
|
11
|
+
properties: {
|
|
12
|
+
name: { type: "string" },
|
|
13
|
+
},
|
|
14
|
+
required: ["name"],
|
|
15
|
+
additionalProperties: false,
|
|
16
|
+
// @ts-expect-error - x-version is missing
|
|
17
|
+
};
|
|
18
|
+
const activeVersion = await lix.db
|
|
19
|
+
.selectFrom("active_version")
|
|
20
|
+
.select("version_id")
|
|
21
|
+
.executeTakeFirstOrThrow();
|
|
22
|
+
expect(() => validateStateMutation({
|
|
23
|
+
lix,
|
|
24
|
+
// @ts-expect-error - x-key is missing
|
|
25
|
+
schema,
|
|
26
|
+
snapshot_content: {},
|
|
27
|
+
operation: "insert",
|
|
28
|
+
version_id: activeVersion.version_id,
|
|
29
|
+
})).toThrowError();
|
|
30
|
+
});
|
|
31
|
+
test("inserts the version and active version schemas to enable validation", async () => {
|
|
32
|
+
const lix = await openLix({});
|
|
33
|
+
const result = await lix.db
|
|
34
|
+
.selectFrom("stored_schema")
|
|
35
|
+
.where("key", "in", ["lix_version", "lix_active_version"])
|
|
36
|
+
.selectAll()
|
|
37
|
+
.execute();
|
|
38
|
+
expect(result.length).toBeGreaterThan(0);
|
|
39
|
+
});
|
|
40
|
+
test("valid lix schema with a valid snapshot passes", async () => {
|
|
41
|
+
const lix = await openLix({});
|
|
42
|
+
const schema = {
|
|
43
|
+
type: "object",
|
|
44
|
+
"x-lix-version": "1.0",
|
|
45
|
+
"x-lix-key": "mock",
|
|
46
|
+
properties: {
|
|
47
|
+
name: { type: "string" },
|
|
48
|
+
},
|
|
49
|
+
required: ["name"],
|
|
50
|
+
additionalProperties: false,
|
|
51
|
+
};
|
|
52
|
+
const snapshot = {
|
|
53
|
+
content: {
|
|
54
|
+
name: "John",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const activeVersion = await lix.db
|
|
58
|
+
.selectFrom("active_version")
|
|
59
|
+
.select("version_id")
|
|
60
|
+
.executeTakeFirstOrThrow();
|
|
61
|
+
expect(() => validateStateMutation({
|
|
62
|
+
lix,
|
|
63
|
+
schema,
|
|
64
|
+
snapshot_content: snapshot.content,
|
|
65
|
+
operation: "insert",
|
|
66
|
+
version_id: activeVersion.version_id,
|
|
67
|
+
})).not.toThrowError();
|
|
68
|
+
});
|
|
69
|
+
test("an invalid snapshot fails", async () => {
|
|
70
|
+
const lix = await openLix({});
|
|
71
|
+
const schema = {
|
|
72
|
+
type: "object",
|
|
73
|
+
"x-lix-version": "1.0",
|
|
74
|
+
"x-lix-key": "mock",
|
|
75
|
+
properties: {
|
|
76
|
+
name: { type: "string" },
|
|
77
|
+
},
|
|
78
|
+
required: ["name"],
|
|
79
|
+
additionalProperties: false,
|
|
80
|
+
};
|
|
81
|
+
const snapshot = {
|
|
82
|
+
content: {
|
|
83
|
+
foo: "John",
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
const activeVersion = await lix.db
|
|
87
|
+
.selectFrom("active_version")
|
|
88
|
+
.select("version_id")
|
|
89
|
+
.executeTakeFirstOrThrow();
|
|
90
|
+
expect(() => validateStateMutation({
|
|
91
|
+
lix,
|
|
92
|
+
schema,
|
|
93
|
+
snapshot_content: snapshot.content,
|
|
94
|
+
operation: "insert",
|
|
95
|
+
version_id: activeVersion.version_id,
|
|
96
|
+
})).toThrowError();
|
|
97
|
+
});
|
|
98
|
+
test("passes when primary key is unique", async () => {
|
|
99
|
+
const lix = await openLix({});
|
|
100
|
+
const schema = {
|
|
101
|
+
type: "object",
|
|
102
|
+
"x-lix-version": "1.0",
|
|
103
|
+
"x-lix-key": "user",
|
|
104
|
+
"x-lix-primary-key": ["id"],
|
|
105
|
+
properties: {
|
|
106
|
+
id: { type: "string" },
|
|
107
|
+
name: { type: "string" },
|
|
108
|
+
},
|
|
109
|
+
required: ["id", "name"],
|
|
110
|
+
additionalProperties: false,
|
|
111
|
+
};
|
|
112
|
+
const snapshot = {
|
|
113
|
+
content: {
|
|
114
|
+
id: "user1",
|
|
115
|
+
name: "John",
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
const activeVersion = await lix.db
|
|
119
|
+
.selectFrom("active_version")
|
|
120
|
+
.select("version_id")
|
|
121
|
+
.executeTakeFirstOrThrow();
|
|
122
|
+
expect(() => validateStateMutation({
|
|
123
|
+
lix,
|
|
124
|
+
schema,
|
|
125
|
+
snapshot_content: snapshot.content,
|
|
126
|
+
operation: "insert",
|
|
127
|
+
version_id: activeVersion.version_id,
|
|
128
|
+
})).not.toThrowError();
|
|
129
|
+
});
|
|
130
|
+
test("throws when primary key violates uniqueness constraint", async () => {
|
|
131
|
+
const lix = await openLix({});
|
|
132
|
+
const schema = {
|
|
133
|
+
type: "object",
|
|
134
|
+
"x-lix-version": "1.0",
|
|
135
|
+
"x-lix-key": "user",
|
|
136
|
+
"x-lix-primary-key": ["id"],
|
|
137
|
+
properties: {
|
|
138
|
+
id: { type: "string" },
|
|
139
|
+
name: { type: "string" },
|
|
140
|
+
},
|
|
141
|
+
required: ["id", "name"],
|
|
142
|
+
additionalProperties: false,
|
|
143
|
+
};
|
|
144
|
+
// Store the schema first
|
|
145
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
146
|
+
// Insert first user into state
|
|
147
|
+
await lix.db
|
|
148
|
+
.insertInto("state_all")
|
|
149
|
+
.values({
|
|
150
|
+
entity_id: "user1",
|
|
151
|
+
file_id: "file1",
|
|
152
|
+
schema_key: "user",
|
|
153
|
+
plugin_key: "test_plugin",
|
|
154
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
155
|
+
snapshot_content: { id: "user1", name: "John" },
|
|
156
|
+
schema_version: "1.0",
|
|
157
|
+
})
|
|
158
|
+
.execute();
|
|
159
|
+
// Try to insert another user with same primary key
|
|
160
|
+
const duplicateSnapshot = {
|
|
161
|
+
content: {
|
|
162
|
+
id: "user1",
|
|
163
|
+
name: "Jane",
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
const activeVersion = await lix.db
|
|
167
|
+
.selectFrom("active_version")
|
|
168
|
+
.select("version_id")
|
|
169
|
+
.executeTakeFirstOrThrow();
|
|
170
|
+
expect(() => validateStateMutation({
|
|
171
|
+
lix,
|
|
172
|
+
schema,
|
|
173
|
+
snapshot_content: duplicateSnapshot.content,
|
|
174
|
+
operation: "insert",
|
|
175
|
+
version_id: activeVersion.version_id,
|
|
176
|
+
})).toThrowError("Primary key constraint violation");
|
|
177
|
+
});
|
|
178
|
+
test("handles composite primary keys", async () => {
|
|
179
|
+
const lix = await openLix({});
|
|
180
|
+
const schema = {
|
|
181
|
+
type: "object",
|
|
182
|
+
"x-lix-version": "1.0",
|
|
183
|
+
"x-lix-key": "user_role",
|
|
184
|
+
"x-lix-primary-key": ["user_id", "role_id"],
|
|
185
|
+
properties: {
|
|
186
|
+
user_id: { type: "string" },
|
|
187
|
+
role_id: { type: "string" },
|
|
188
|
+
assigned_date: { type: "string" },
|
|
189
|
+
},
|
|
190
|
+
required: ["user_id", "role_id", "assigned_date"],
|
|
191
|
+
additionalProperties: false,
|
|
192
|
+
};
|
|
193
|
+
// Store the schema first
|
|
194
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
195
|
+
// Insert first user-role into state
|
|
196
|
+
await lix.db
|
|
197
|
+
.insertInto("state_all")
|
|
198
|
+
.values({
|
|
199
|
+
entity_id: "user_role1",
|
|
200
|
+
file_id: "file1",
|
|
201
|
+
schema_key: "user_role",
|
|
202
|
+
plugin_key: "test_plugin",
|
|
203
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
204
|
+
snapshot_content: {
|
|
205
|
+
user_id: "user1",
|
|
206
|
+
role_id: "admin",
|
|
207
|
+
assigned_date: "2024-01-01",
|
|
208
|
+
},
|
|
209
|
+
schema_version: "1.0",
|
|
210
|
+
})
|
|
211
|
+
.execute();
|
|
212
|
+
const activeVersion = await lix.db
|
|
213
|
+
.selectFrom("active_version")
|
|
214
|
+
.select("version_id")
|
|
215
|
+
.executeTakeFirstOrThrow();
|
|
216
|
+
// This should pass (different composite key)
|
|
217
|
+
expect(() => validateStateMutation({
|
|
218
|
+
lix,
|
|
219
|
+
schema,
|
|
220
|
+
snapshot_content: {
|
|
221
|
+
user_id: "user1",
|
|
222
|
+
role_id: "editor",
|
|
223
|
+
assigned_date: "2024-01-02",
|
|
224
|
+
},
|
|
225
|
+
operation: "insert",
|
|
226
|
+
version_id: activeVersion.version_id,
|
|
227
|
+
})).not.toThrowError();
|
|
228
|
+
// This should fail (same composite key)
|
|
229
|
+
expect(() => validateStateMutation({
|
|
230
|
+
lix,
|
|
231
|
+
schema,
|
|
232
|
+
snapshot_content: {
|
|
233
|
+
user_id: "user1",
|
|
234
|
+
role_id: "admin",
|
|
235
|
+
assigned_date: "2024-01-03",
|
|
236
|
+
},
|
|
237
|
+
operation: "insert",
|
|
238
|
+
version_id: activeVersion.version_id,
|
|
239
|
+
})).toThrowError("Primary key constraint violation");
|
|
240
|
+
});
|
|
241
|
+
test("passes when unique constraint is satisfied", async () => {
|
|
242
|
+
const lix = await openLix({});
|
|
243
|
+
const activeVersion = await lix.db
|
|
244
|
+
.selectFrom("active_version")
|
|
245
|
+
.select("version_id")
|
|
246
|
+
.executeTakeFirstOrThrow();
|
|
247
|
+
const schema = {
|
|
248
|
+
type: "object",
|
|
249
|
+
"x-lix-version": "1.0",
|
|
250
|
+
"x-lix-key": "user",
|
|
251
|
+
"x-lix-primary-key": ["id"],
|
|
252
|
+
"x-lix-unique": [["email"], ["username"]],
|
|
253
|
+
properties: {
|
|
254
|
+
id: { type: "string" },
|
|
255
|
+
email: { type: "string" },
|
|
256
|
+
username: { type: "string" },
|
|
257
|
+
name: { type: "string" },
|
|
258
|
+
},
|
|
259
|
+
required: ["id", "email", "username", "name"],
|
|
260
|
+
additionalProperties: false,
|
|
261
|
+
};
|
|
262
|
+
const snapshot = {
|
|
263
|
+
content: {
|
|
264
|
+
id: "user1",
|
|
265
|
+
email: "john@example.com",
|
|
266
|
+
username: "john_doe",
|
|
267
|
+
name: "John Doe",
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
expect(() => validateStateMutation({
|
|
271
|
+
lix,
|
|
272
|
+
schema,
|
|
273
|
+
snapshot_content: snapshot.content,
|
|
274
|
+
version_id: activeVersion.version_id,
|
|
275
|
+
operation: "insert",
|
|
276
|
+
})).not.toThrowError();
|
|
277
|
+
});
|
|
278
|
+
test("throws when single field unique constraint is violated", async () => {
|
|
279
|
+
const lix = await openLix({});
|
|
280
|
+
const schema = {
|
|
281
|
+
type: "object",
|
|
282
|
+
"x-lix-version": "1.0",
|
|
283
|
+
"x-lix-key": "user",
|
|
284
|
+
"x-lix-primary-key": ["id"],
|
|
285
|
+
"x-lix-unique": [["email"], ["username"]],
|
|
286
|
+
properties: {
|
|
287
|
+
id: { type: "string" },
|
|
288
|
+
email: { type: "string" },
|
|
289
|
+
username: { type: "string" },
|
|
290
|
+
name: { type: "string" },
|
|
291
|
+
},
|
|
292
|
+
required: ["id", "email", "username", "name"],
|
|
293
|
+
additionalProperties: false,
|
|
294
|
+
};
|
|
295
|
+
// Store the schema first
|
|
296
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
297
|
+
// Insert first user into state
|
|
298
|
+
await lix.db
|
|
299
|
+
.insertInto("state_all")
|
|
300
|
+
.values({
|
|
301
|
+
entity_id: "user1",
|
|
302
|
+
file_id: "file1",
|
|
303
|
+
schema_key: "user",
|
|
304
|
+
plugin_key: "test_plugin",
|
|
305
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
306
|
+
snapshot_content: {
|
|
307
|
+
id: "user1",
|
|
308
|
+
email: "john@example.com",
|
|
309
|
+
username: "john_doe",
|
|
310
|
+
name: "John Doe",
|
|
311
|
+
},
|
|
312
|
+
schema_version: "1.0",
|
|
313
|
+
})
|
|
314
|
+
.execute();
|
|
315
|
+
// Try to insert another user with same email (unique constraint violation)
|
|
316
|
+
const duplicateEmailSnapshot = {
|
|
317
|
+
content: {
|
|
318
|
+
id: "user2",
|
|
319
|
+
email: "john@example.com", // Same email
|
|
320
|
+
username: "jane_doe",
|
|
321
|
+
name: "Jane Doe",
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
const activeVersion = await lix.db
|
|
325
|
+
.selectFrom("active_version")
|
|
326
|
+
.select("version_id")
|
|
327
|
+
.executeTakeFirstOrThrow();
|
|
328
|
+
expect(() => validateStateMutation({
|
|
329
|
+
lix,
|
|
330
|
+
schema,
|
|
331
|
+
snapshot_content: duplicateEmailSnapshot.content,
|
|
332
|
+
operation: "insert",
|
|
333
|
+
version_id: activeVersion.version_id,
|
|
334
|
+
})).toThrowError("Unique constraint violation");
|
|
335
|
+
// Try to insert another user with same username (unique constraint violation)
|
|
336
|
+
const duplicateUsernameSnapshot = {
|
|
337
|
+
content: {
|
|
338
|
+
id: "user3",
|
|
339
|
+
email: "jane@example.com",
|
|
340
|
+
username: "john_doe", // Same username
|
|
341
|
+
name: "Jane Smith",
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
expect(() => validateStateMutation({
|
|
345
|
+
lix,
|
|
346
|
+
schema,
|
|
347
|
+
snapshot_content: duplicateUsernameSnapshot.content,
|
|
348
|
+
operation: "insert",
|
|
349
|
+
version_id: activeVersion.version_id,
|
|
350
|
+
})).toThrowError("Unique constraint violation");
|
|
351
|
+
});
|
|
352
|
+
test("handles composite unique constraints", async () => {
|
|
353
|
+
const lix = await openLix({});
|
|
354
|
+
const schema = {
|
|
355
|
+
type: "object",
|
|
356
|
+
"x-lix-version": "1.0",
|
|
357
|
+
"x-lix-key": "product",
|
|
358
|
+
"x-lix-primary-key": ["id"],
|
|
359
|
+
"x-lix-unique": [
|
|
360
|
+
["category", "name"], // Composite unique constraint
|
|
361
|
+
["sku"], // Single field unique constraint
|
|
362
|
+
],
|
|
363
|
+
properties: {
|
|
364
|
+
id: { type: "string" },
|
|
365
|
+
category: { type: "string" },
|
|
366
|
+
name: { type: "string" },
|
|
367
|
+
sku: { type: "string" },
|
|
368
|
+
price: { type: "number" },
|
|
369
|
+
},
|
|
370
|
+
required: ["id", "category", "name", "sku", "price"],
|
|
371
|
+
additionalProperties: false,
|
|
372
|
+
};
|
|
373
|
+
// Store the schema first
|
|
374
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
375
|
+
// Insert first product into state
|
|
376
|
+
await lix.db
|
|
377
|
+
.insertInto("state_all")
|
|
378
|
+
.values({
|
|
379
|
+
entity_id: "product1",
|
|
380
|
+
file_id: "file1",
|
|
381
|
+
schema_key: "product",
|
|
382
|
+
plugin_key: "test_plugin",
|
|
383
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
384
|
+
snapshot_content: {
|
|
385
|
+
id: "product1",
|
|
386
|
+
category: "electronics",
|
|
387
|
+
name: "Laptop",
|
|
388
|
+
sku: "ELEC-LAP-001",
|
|
389
|
+
price: 999.99,
|
|
390
|
+
},
|
|
391
|
+
schema_version: "1.0",
|
|
392
|
+
})
|
|
393
|
+
.execute();
|
|
394
|
+
const activeVersion = await lix.db
|
|
395
|
+
.selectFrom("active_version")
|
|
396
|
+
.select("version_id")
|
|
397
|
+
.executeTakeFirstOrThrow();
|
|
398
|
+
// This should pass (different composite unique key)
|
|
399
|
+
expect(() => validateStateMutation({
|
|
400
|
+
lix,
|
|
401
|
+
schema,
|
|
402
|
+
snapshot_content: {
|
|
403
|
+
id: "product2",
|
|
404
|
+
category: "electronics",
|
|
405
|
+
name: "Desktop", // Different name in same category
|
|
406
|
+
sku: "ELEC-DES-001",
|
|
407
|
+
price: 1299.99,
|
|
408
|
+
},
|
|
409
|
+
operation: "insert",
|
|
410
|
+
version_id: activeVersion.version_id,
|
|
411
|
+
})).not.toThrowError();
|
|
412
|
+
// This should pass (same name in different category)
|
|
413
|
+
expect(() => validateStateMutation({
|
|
414
|
+
lix,
|
|
415
|
+
schema,
|
|
416
|
+
snapshot_content: {
|
|
417
|
+
id: "product3",
|
|
418
|
+
category: "furniture", // Different category
|
|
419
|
+
name: "Laptop", // Same name but different category
|
|
420
|
+
sku: "FURN-LAP-001",
|
|
421
|
+
price: 599.99,
|
|
422
|
+
},
|
|
423
|
+
operation: "insert",
|
|
424
|
+
version_id: activeVersion.version_id,
|
|
425
|
+
})).not.toThrowError();
|
|
426
|
+
// This should fail (same composite unique key: category + name)
|
|
427
|
+
expect(() => validateStateMutation({
|
|
428
|
+
lix,
|
|
429
|
+
schema,
|
|
430
|
+
snapshot_content: {
|
|
431
|
+
id: "product4",
|
|
432
|
+
category: "electronics",
|
|
433
|
+
name: "Laptop", // Same category + name combination
|
|
434
|
+
sku: "ELEC-LAP-002",
|
|
435
|
+
price: 899.99,
|
|
436
|
+
},
|
|
437
|
+
operation: "insert",
|
|
438
|
+
version_id: activeVersion.version_id,
|
|
439
|
+
})).toThrowError("Unique constraint violation");
|
|
440
|
+
// This should fail (same SKU)
|
|
441
|
+
expect(() => validateStateMutation({
|
|
442
|
+
lix,
|
|
443
|
+
schema,
|
|
444
|
+
snapshot_content: {
|
|
445
|
+
id: "product5",
|
|
446
|
+
category: "accessories",
|
|
447
|
+
name: "Mouse",
|
|
448
|
+
sku: "ELEC-LAP-001", // Same SKU
|
|
449
|
+
price: 29.99,
|
|
450
|
+
},
|
|
451
|
+
operation: "insert",
|
|
452
|
+
version_id: activeVersion.version_id,
|
|
453
|
+
})).toThrowError("Unique constraint violation");
|
|
454
|
+
});
|
|
455
|
+
test("passes when foreign key references exist", async () => {
|
|
456
|
+
const lix = await openLix({});
|
|
457
|
+
const userSchema = {
|
|
458
|
+
type: "object",
|
|
459
|
+
"x-lix-version": "1.0",
|
|
460
|
+
"x-lix-key": "user",
|
|
461
|
+
"x-lix-primary-key": ["id"],
|
|
462
|
+
properties: {
|
|
463
|
+
id: { type: "string" },
|
|
464
|
+
name: { type: "string" },
|
|
465
|
+
},
|
|
466
|
+
required: ["id", "name"],
|
|
467
|
+
additionalProperties: false,
|
|
468
|
+
};
|
|
469
|
+
const postSchema = {
|
|
470
|
+
type: "object",
|
|
471
|
+
"x-lix-version": "1.0",
|
|
472
|
+
"x-lix-key": "post",
|
|
473
|
+
"x-lix-primary-key": ["id"],
|
|
474
|
+
"x-lix-foreign-keys": {
|
|
475
|
+
author_id: {
|
|
476
|
+
schemaKey: "user",
|
|
477
|
+
property: "id",
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
properties: {
|
|
481
|
+
id: { type: "string" },
|
|
482
|
+
author_id: { type: "string" },
|
|
483
|
+
title: { type: "string" },
|
|
484
|
+
},
|
|
485
|
+
required: ["id", "author_id", "title"],
|
|
486
|
+
additionalProperties: false,
|
|
487
|
+
};
|
|
488
|
+
// Store schemas
|
|
489
|
+
await lix.db
|
|
490
|
+
.insertInto("stored_schema")
|
|
491
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
492
|
+
.execute();
|
|
493
|
+
// Insert a user that will be referenced
|
|
494
|
+
await lix.db
|
|
495
|
+
.insertInto("state_all")
|
|
496
|
+
.values({
|
|
497
|
+
entity_id: "user1",
|
|
498
|
+
file_id: "file1",
|
|
499
|
+
schema_key: "user",
|
|
500
|
+
plugin_key: "test_plugin",
|
|
501
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
502
|
+
snapshot_content: {
|
|
503
|
+
id: "user1",
|
|
504
|
+
name: "John Doe",
|
|
505
|
+
},
|
|
506
|
+
schema_version: "1.0",
|
|
507
|
+
})
|
|
508
|
+
.execute();
|
|
509
|
+
const activeVersion = await lix.db
|
|
510
|
+
.selectFrom("active_version")
|
|
511
|
+
.select("version_id")
|
|
512
|
+
.executeTakeFirstOrThrow();
|
|
513
|
+
// This should pass - foreign key reference exists
|
|
514
|
+
expect(() => validateStateMutation({
|
|
515
|
+
lix,
|
|
516
|
+
schema: postSchema,
|
|
517
|
+
snapshot_content: {
|
|
518
|
+
id: "post1",
|
|
519
|
+
author_id: "user1",
|
|
520
|
+
title: "My First Post",
|
|
521
|
+
},
|
|
522
|
+
operation: "insert",
|
|
523
|
+
version_id: activeVersion.version_id,
|
|
524
|
+
})).not.toThrowError();
|
|
525
|
+
});
|
|
526
|
+
test("throws when foreign key reference does not exist", async () => {
|
|
527
|
+
const lix = await openLix({});
|
|
528
|
+
const userSchema = {
|
|
529
|
+
type: "object",
|
|
530
|
+
"x-lix-version": "1.0",
|
|
531
|
+
"x-lix-key": "user",
|
|
532
|
+
"x-lix-primary-key": ["id"],
|
|
533
|
+
properties: {
|
|
534
|
+
id: { type: "string" },
|
|
535
|
+
name: { type: "string" },
|
|
536
|
+
},
|
|
537
|
+
required: ["id", "name"],
|
|
538
|
+
additionalProperties: false,
|
|
539
|
+
};
|
|
540
|
+
const postSchema = {
|
|
541
|
+
type: "object",
|
|
542
|
+
"x-lix-version": "1.0",
|
|
543
|
+
"x-lix-key": "post",
|
|
544
|
+
"x-lix-primary-key": ["id"],
|
|
545
|
+
"x-lix-foreign-keys": {
|
|
546
|
+
author_id: {
|
|
547
|
+
schemaKey: "user",
|
|
548
|
+
property: "id",
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
properties: {
|
|
552
|
+
id: { type: "string" },
|
|
553
|
+
author_id: { type: "string" },
|
|
554
|
+
title: { type: "string" },
|
|
555
|
+
},
|
|
556
|
+
required: ["id", "author_id", "title"],
|
|
557
|
+
additionalProperties: false,
|
|
558
|
+
};
|
|
559
|
+
// Store schemas
|
|
560
|
+
await lix.db
|
|
561
|
+
.insertInto("stored_schema")
|
|
562
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
563
|
+
.execute();
|
|
564
|
+
const activeVersion = await lix.db
|
|
565
|
+
.selectFrom("active_version")
|
|
566
|
+
.select("version_id")
|
|
567
|
+
.executeTakeFirstOrThrow();
|
|
568
|
+
// This should fail - foreign key reference does not exist
|
|
569
|
+
expect(() => validateStateMutation({
|
|
570
|
+
lix,
|
|
571
|
+
schema: postSchema,
|
|
572
|
+
snapshot_content: {
|
|
573
|
+
id: "post1",
|
|
574
|
+
author_id: "nonexistent_user",
|
|
575
|
+
title: "My First Post",
|
|
576
|
+
},
|
|
577
|
+
operation: "insert",
|
|
578
|
+
version_id: activeVersion.version_id,
|
|
579
|
+
})).toThrowError("Foreign key constraint violation");
|
|
580
|
+
});
|
|
581
|
+
test("handles multiple foreign keys", async () => {
|
|
582
|
+
const lix = await openLix({});
|
|
583
|
+
const userSchema = {
|
|
584
|
+
type: "object",
|
|
585
|
+
"x-lix-version": "1.0",
|
|
586
|
+
"x-lix-key": "user",
|
|
587
|
+
"x-lix-primary-key": ["id"],
|
|
588
|
+
properties: {
|
|
589
|
+
id: { type: "string" },
|
|
590
|
+
name: { type: "string" },
|
|
591
|
+
},
|
|
592
|
+
required: ["id", "name"],
|
|
593
|
+
additionalProperties: false,
|
|
594
|
+
};
|
|
595
|
+
const categorySchema = {
|
|
596
|
+
type: "object",
|
|
597
|
+
"x-lix-version": "1.0",
|
|
598
|
+
"x-lix-key": "category",
|
|
599
|
+
"x-lix-primary-key": ["id"],
|
|
600
|
+
properties: {
|
|
601
|
+
id: { type: "string" },
|
|
602
|
+
name: { type: "string" },
|
|
603
|
+
},
|
|
604
|
+
required: ["id", "name"],
|
|
605
|
+
additionalProperties: false,
|
|
606
|
+
};
|
|
607
|
+
const postSchema = {
|
|
608
|
+
type: "object",
|
|
609
|
+
"x-lix-version": "1.0",
|
|
610
|
+
"x-lix-key": "post",
|
|
611
|
+
"x-lix-primary-key": ["id"],
|
|
612
|
+
"x-lix-foreign-keys": {
|
|
613
|
+
author_id: {
|
|
614
|
+
schemaKey: "user",
|
|
615
|
+
property: "id",
|
|
616
|
+
},
|
|
617
|
+
category_id: {
|
|
618
|
+
schemaKey: "category",
|
|
619
|
+
property: "id",
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
properties: {
|
|
623
|
+
id: { type: "string" },
|
|
624
|
+
author_id: { type: "string" },
|
|
625
|
+
category_id: { type: "string" },
|
|
626
|
+
title: { type: "string" },
|
|
627
|
+
},
|
|
628
|
+
required: ["id", "author_id", "category_id", "title"],
|
|
629
|
+
additionalProperties: false,
|
|
630
|
+
};
|
|
631
|
+
// Store schemas
|
|
632
|
+
await lix.db
|
|
633
|
+
.insertInto("stored_schema")
|
|
634
|
+
.values([
|
|
635
|
+
{ value: userSchema },
|
|
636
|
+
{ value: categorySchema },
|
|
637
|
+
{ value: postSchema },
|
|
638
|
+
])
|
|
639
|
+
.execute();
|
|
640
|
+
// Insert referenced entities
|
|
641
|
+
await lix.db
|
|
642
|
+
.insertInto("state_all")
|
|
643
|
+
.values([
|
|
644
|
+
{
|
|
645
|
+
entity_id: "user1",
|
|
646
|
+
file_id: "file1",
|
|
647
|
+
schema_key: "user",
|
|
648
|
+
plugin_key: "test_plugin",
|
|
649
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
650
|
+
snapshot_content: {
|
|
651
|
+
id: "user1",
|
|
652
|
+
name: "John Doe",
|
|
653
|
+
},
|
|
654
|
+
schema_version: "1.0",
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
entity_id: "category1",
|
|
658
|
+
file_id: "file1",
|
|
659
|
+
schema_key: "category",
|
|
660
|
+
plugin_key: "test_plugin",
|
|
661
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
662
|
+
snapshot_content: {
|
|
663
|
+
id: "category1",
|
|
664
|
+
name: "Technology",
|
|
665
|
+
},
|
|
666
|
+
schema_version: "1.0",
|
|
667
|
+
},
|
|
668
|
+
])
|
|
669
|
+
.execute();
|
|
670
|
+
const activeVersion = await lix.db
|
|
671
|
+
.selectFrom("active_version")
|
|
672
|
+
.select("version_id")
|
|
673
|
+
.executeTakeFirstOrThrow();
|
|
674
|
+
// This should pass - all foreign key references exist
|
|
675
|
+
expect(() => validateStateMutation({
|
|
676
|
+
lix,
|
|
677
|
+
schema: postSchema,
|
|
678
|
+
snapshot_content: {
|
|
679
|
+
id: "post1",
|
|
680
|
+
author_id: "user1",
|
|
681
|
+
category_id: "category1",
|
|
682
|
+
title: "My Tech Post",
|
|
683
|
+
},
|
|
684
|
+
operation: "insert",
|
|
685
|
+
version_id: activeVersion.version_id,
|
|
686
|
+
})).not.toThrowError();
|
|
687
|
+
// This should fail - category reference does not exist
|
|
688
|
+
expect(() => validateStateMutation({
|
|
689
|
+
lix,
|
|
690
|
+
schema: postSchema,
|
|
691
|
+
snapshot_content: {
|
|
692
|
+
id: "post2",
|
|
693
|
+
author_id: "user1",
|
|
694
|
+
category_id: "nonexistent_category",
|
|
695
|
+
title: "Another Post",
|
|
696
|
+
},
|
|
697
|
+
operation: "insert",
|
|
698
|
+
version_id: activeVersion.version_id,
|
|
699
|
+
})).toThrowError("Foreign key constraint violation");
|
|
700
|
+
});
|
|
701
|
+
test("allows null foreign key values", async () => {
|
|
702
|
+
const lix = await openLix({});
|
|
703
|
+
const userSchema = {
|
|
704
|
+
type: "object",
|
|
705
|
+
"x-lix-version": "1.0",
|
|
706
|
+
"x-lix-key": "user",
|
|
707
|
+
"x-lix-primary-key": ["id"],
|
|
708
|
+
properties: {
|
|
709
|
+
id: { type: "string" },
|
|
710
|
+
name: { type: "string" },
|
|
711
|
+
},
|
|
712
|
+
required: ["id", "name"],
|
|
713
|
+
additionalProperties: false,
|
|
714
|
+
};
|
|
715
|
+
const postSchema = {
|
|
716
|
+
type: "object",
|
|
717
|
+
"x-lix-version": "1.0",
|
|
718
|
+
"x-lix-key": "post",
|
|
719
|
+
"x-lix-primary-key": ["id"],
|
|
720
|
+
"x-lix-foreign-keys": {
|
|
721
|
+
author_id: {
|
|
722
|
+
schemaKey: "user",
|
|
723
|
+
property: "id",
|
|
724
|
+
},
|
|
725
|
+
},
|
|
726
|
+
properties: {
|
|
727
|
+
id: { type: "string" },
|
|
728
|
+
author_id: { type: ["string", "null"] },
|
|
729
|
+
title: { type: "string" },
|
|
730
|
+
},
|
|
731
|
+
required: ["id", "title"],
|
|
732
|
+
additionalProperties: false,
|
|
733
|
+
};
|
|
734
|
+
// Store schemas
|
|
735
|
+
await lix.db
|
|
736
|
+
.insertInto("stored_schema")
|
|
737
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
738
|
+
.execute();
|
|
739
|
+
const activeVersion = await lix.db
|
|
740
|
+
.selectFrom("active_version")
|
|
741
|
+
.select("version_id")
|
|
742
|
+
.executeTakeFirstOrThrow();
|
|
743
|
+
// This should pass - null foreign key is allowed
|
|
744
|
+
expect(() => validateStateMutation({
|
|
745
|
+
lix,
|
|
746
|
+
schema: postSchema,
|
|
747
|
+
snapshot_content: {
|
|
748
|
+
id: "post1",
|
|
749
|
+
author_id: null,
|
|
750
|
+
title: "Anonymous Post",
|
|
751
|
+
},
|
|
752
|
+
operation: "insert",
|
|
753
|
+
version_id: activeVersion.version_id,
|
|
754
|
+
})).not.toThrowError();
|
|
755
|
+
// This should also pass - undefined foreign key (when not required)
|
|
756
|
+
expect(() => validateStateMutation({
|
|
757
|
+
lix,
|
|
758
|
+
schema: postSchema,
|
|
759
|
+
snapshot_content: {
|
|
760
|
+
id: "post2",
|
|
761
|
+
title: "Another Anonymous Post",
|
|
762
|
+
},
|
|
763
|
+
operation: "insert",
|
|
764
|
+
version_id: activeVersion.version_id,
|
|
765
|
+
})).not.toThrowError();
|
|
766
|
+
});
|
|
767
|
+
test("foreign key referencing real SQL table (change.id)", async () => {
|
|
768
|
+
const lix = await openLix({});
|
|
769
|
+
// Insert a real change record into the change table
|
|
770
|
+
await lix.db
|
|
771
|
+
// @ts-expect-error - internal_snapshot is not a public table
|
|
772
|
+
.insertInto("internal_snapshot")
|
|
773
|
+
.values({
|
|
774
|
+
id: "snap1",
|
|
775
|
+
content: sql `jsonb(${JSON.stringify({ id: "entity1" })})`,
|
|
776
|
+
})
|
|
777
|
+
.execute();
|
|
778
|
+
await lix.db
|
|
779
|
+
// @ts-expect-error - internal_change is not a public table
|
|
780
|
+
.insertInto("internal_change")
|
|
781
|
+
.values({
|
|
782
|
+
id: "change1",
|
|
783
|
+
entity_id: "entity1",
|
|
784
|
+
plugin_key: "test_plugin",
|
|
785
|
+
schema_key: "test_schema",
|
|
786
|
+
schema_version: "1.0",
|
|
787
|
+
file_id: "file1",
|
|
788
|
+
snapshot_id: "snap1",
|
|
789
|
+
})
|
|
790
|
+
.execute();
|
|
791
|
+
const changeSetElementSchema = {
|
|
792
|
+
type: "object",
|
|
793
|
+
"x-lix-version": "1.0",
|
|
794
|
+
"x-lix-key": "change_set_element_test",
|
|
795
|
+
"x-lix-foreign-keys": {
|
|
796
|
+
change_id: {
|
|
797
|
+
schemaKey: "lix_change",
|
|
798
|
+
property: "id",
|
|
799
|
+
},
|
|
800
|
+
},
|
|
801
|
+
properties: {
|
|
802
|
+
id: { type: "string" },
|
|
803
|
+
change_id: { type: "string" },
|
|
804
|
+
},
|
|
805
|
+
required: ["id", "change_id"],
|
|
806
|
+
additionalProperties: false,
|
|
807
|
+
};
|
|
808
|
+
const activeVersion = await lix.db
|
|
809
|
+
.selectFrom("active_version")
|
|
810
|
+
.select("version_id")
|
|
811
|
+
.executeTakeFirstOrThrow();
|
|
812
|
+
// This should pass - foreign key references existing change record
|
|
813
|
+
expect(() => validateStateMutation({
|
|
814
|
+
lix,
|
|
815
|
+
schema: changeSetElementSchema,
|
|
816
|
+
snapshot_content: {
|
|
817
|
+
id: "element1",
|
|
818
|
+
change_id: "change1",
|
|
819
|
+
},
|
|
820
|
+
operation: "insert",
|
|
821
|
+
version_id: activeVersion.version_id,
|
|
822
|
+
})).not.toThrowError();
|
|
823
|
+
// This should fail - foreign key references non-existent change
|
|
824
|
+
expect(() => validateStateMutation({
|
|
825
|
+
lix,
|
|
826
|
+
schema: changeSetElementSchema,
|
|
827
|
+
snapshot_content: {
|
|
828
|
+
id: "element2",
|
|
829
|
+
change_id: "nonexistent_change",
|
|
830
|
+
},
|
|
831
|
+
operation: "insert",
|
|
832
|
+
version_id: activeVersion.version_id,
|
|
833
|
+
})).toThrowError("Foreign key constraint violation");
|
|
834
|
+
});
|
|
835
|
+
test("allows updates with same primary key", async () => {
|
|
836
|
+
const lix = await openLix({});
|
|
837
|
+
const activeVersion = await lix.db
|
|
838
|
+
.selectFrom("active_version")
|
|
839
|
+
.select("version_id")
|
|
840
|
+
.executeTakeFirstOrThrow();
|
|
841
|
+
const schema = {
|
|
842
|
+
type: "object",
|
|
843
|
+
"x-lix-version": "1.0",
|
|
844
|
+
"x-lix-key": "user",
|
|
845
|
+
"x-lix-primary-key": ["id"],
|
|
846
|
+
properties: {
|
|
847
|
+
id: { type: "string" },
|
|
848
|
+
name: { type: "string" },
|
|
849
|
+
},
|
|
850
|
+
required: ["id", "name"],
|
|
851
|
+
additionalProperties: false,
|
|
852
|
+
};
|
|
853
|
+
// Store the schema first
|
|
854
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
855
|
+
// Insert initial user
|
|
856
|
+
await lix.db
|
|
857
|
+
.insertInto("state_all")
|
|
858
|
+
.values({
|
|
859
|
+
entity_id: "user1",
|
|
860
|
+
file_id: "file1",
|
|
861
|
+
schema_key: "user",
|
|
862
|
+
plugin_key: "test_plugin",
|
|
863
|
+
version_id: lix.db.selectFrom("active_version").select("version_id"),
|
|
864
|
+
snapshot_content: { id: "user1", name: "John Doe" },
|
|
865
|
+
schema_version: "1.0",
|
|
866
|
+
})
|
|
867
|
+
.execute();
|
|
868
|
+
// This should pass - updating existing record with same primary key
|
|
869
|
+
expect(() => validateStateMutation({
|
|
870
|
+
lix,
|
|
871
|
+
schema,
|
|
872
|
+
snapshot_content: {
|
|
873
|
+
id: "user1", // Same primary key
|
|
874
|
+
name: "John Smith", // Different data
|
|
875
|
+
},
|
|
876
|
+
operation: "update",
|
|
877
|
+
entity_id: "user1",
|
|
878
|
+
version_id: activeVersion.version_id,
|
|
879
|
+
})).not.toThrowError();
|
|
880
|
+
});
|
|
881
|
+
test("unique constraints are validated per version, not globally", async () => {
|
|
882
|
+
const lix = await openLix({});
|
|
883
|
+
const schema = {
|
|
884
|
+
type: "object",
|
|
885
|
+
"x-lix-version": "1.0",
|
|
886
|
+
"x-lix-key": "file",
|
|
887
|
+
"x-lix-primary-key": ["id"],
|
|
888
|
+
"x-lix-unique": [["path"]], // Unique path constraint
|
|
889
|
+
properties: {
|
|
890
|
+
id: { type: "string" },
|
|
891
|
+
path: { type: "string" },
|
|
892
|
+
content: { type: "string" },
|
|
893
|
+
},
|
|
894
|
+
required: ["id", "path", "content"],
|
|
895
|
+
additionalProperties: false,
|
|
896
|
+
};
|
|
897
|
+
// Store the schema first
|
|
898
|
+
await lix.db.insertInto("stored_schema").values({ value: schema }).execute();
|
|
899
|
+
// Create two different versions
|
|
900
|
+
await createVersion({
|
|
901
|
+
lix,
|
|
902
|
+
id: "version0",
|
|
903
|
+
});
|
|
904
|
+
await createVersion({
|
|
905
|
+
lix,
|
|
906
|
+
id: "version1",
|
|
907
|
+
});
|
|
908
|
+
// Insert file with path "/app.js" in version1
|
|
909
|
+
await lix.db
|
|
910
|
+
.insertInto("state_all")
|
|
911
|
+
.values({
|
|
912
|
+
entity_id: "file1",
|
|
913
|
+
file_id: "file1",
|
|
914
|
+
schema_key: "file",
|
|
915
|
+
plugin_key: "test_plugin",
|
|
916
|
+
version_id: "version0",
|
|
917
|
+
snapshot_content: {
|
|
918
|
+
id: "file1",
|
|
919
|
+
path: "/app.js",
|
|
920
|
+
content: "console.log('version 0');",
|
|
921
|
+
},
|
|
922
|
+
schema_version: "1.0",
|
|
923
|
+
})
|
|
924
|
+
.execute();
|
|
925
|
+
// This should pass - same path in different version should be allowed
|
|
926
|
+
expect(() => validateStateMutation({
|
|
927
|
+
lix,
|
|
928
|
+
schema,
|
|
929
|
+
snapshot_content: {
|
|
930
|
+
id: "file2",
|
|
931
|
+
path: "/app.js", // Same path but different version
|
|
932
|
+
content: "console.log('version 1');",
|
|
933
|
+
},
|
|
934
|
+
operation: "insert",
|
|
935
|
+
version_id: "version1",
|
|
936
|
+
})).not.toThrowError();
|
|
937
|
+
// This should fail - same path in same version
|
|
938
|
+
expect(() => validateStateMutation({
|
|
939
|
+
lix,
|
|
940
|
+
schema,
|
|
941
|
+
snapshot_content: {
|
|
942
|
+
id: "file3",
|
|
943
|
+
path: "/app.js", // Same path and same version
|
|
944
|
+
content: "console.log('duplicate');",
|
|
945
|
+
},
|
|
946
|
+
operation: "insert",
|
|
947
|
+
version_id: "version0",
|
|
948
|
+
})).toThrowError("Unique constraint violation");
|
|
949
|
+
});
|
|
950
|
+
test("throws when version_id is not provided", async () => {
|
|
951
|
+
const lix = await openLix({});
|
|
952
|
+
const schema = {
|
|
953
|
+
type: "object",
|
|
954
|
+
"x-lix-version": "1.0",
|
|
955
|
+
"x-lix-key": "user",
|
|
956
|
+
"x-lix-primary-key": ["id"],
|
|
957
|
+
properties: {
|
|
958
|
+
id: { type: "string" },
|
|
959
|
+
name: { type: "string" },
|
|
960
|
+
},
|
|
961
|
+
required: ["id", "name"],
|
|
962
|
+
additionalProperties: false,
|
|
963
|
+
};
|
|
964
|
+
expect(() => validateStateMutation({
|
|
965
|
+
lix,
|
|
966
|
+
schema,
|
|
967
|
+
snapshot_content: { id: "user1", name: "John" },
|
|
968
|
+
operation: "insert",
|
|
969
|
+
// @ts-expect-error - version_id is required but missing
|
|
970
|
+
version_id: undefined,
|
|
971
|
+
})).toThrowError("version_id is required");
|
|
972
|
+
});
|
|
973
|
+
test("throws when referenced version does not exist", async () => {
|
|
974
|
+
const lix = await openLix({});
|
|
975
|
+
const schema = {
|
|
976
|
+
type: "object",
|
|
977
|
+
"x-lix-version": "1.0",
|
|
978
|
+
"x-lix-key": "user",
|
|
979
|
+
"x-lix-primary-key": ["id"],
|
|
980
|
+
properties: {
|
|
981
|
+
id: { type: "string" },
|
|
982
|
+
name: { type: "string" },
|
|
983
|
+
},
|
|
984
|
+
required: ["id", "name"],
|
|
985
|
+
additionalProperties: false,
|
|
986
|
+
};
|
|
987
|
+
expect(() => validateStateMutation({
|
|
988
|
+
lix,
|
|
989
|
+
schema,
|
|
990
|
+
snapshot_content: { id: "user1", name: "John" },
|
|
991
|
+
operation: "insert",
|
|
992
|
+
version_id: "nonexistent_version",
|
|
993
|
+
})).toThrowError("Version with id 'nonexistent_version' does not exist");
|
|
994
|
+
});
|
|
995
|
+
test("passes when version_id is provided and version exists", async () => {
|
|
996
|
+
const lix = await openLix({});
|
|
997
|
+
const schema = {
|
|
998
|
+
type: "object",
|
|
999
|
+
"x-lix-version": "1.0",
|
|
1000
|
+
"x-lix-key": "user",
|
|
1001
|
+
"x-lix-primary-key": ["id"],
|
|
1002
|
+
properties: {
|
|
1003
|
+
id: { type: "string" },
|
|
1004
|
+
name: { type: "string" },
|
|
1005
|
+
},
|
|
1006
|
+
required: ["id", "name"],
|
|
1007
|
+
additionalProperties: false,
|
|
1008
|
+
};
|
|
1009
|
+
const activeVersion = await lix.db
|
|
1010
|
+
.selectFrom("active_version")
|
|
1011
|
+
.select("version_id")
|
|
1012
|
+
.executeTakeFirstOrThrow();
|
|
1013
|
+
expect(() => validateStateMutation({
|
|
1014
|
+
lix,
|
|
1015
|
+
schema,
|
|
1016
|
+
snapshot_content: { id: "user1", name: "John" },
|
|
1017
|
+
operation: "insert",
|
|
1018
|
+
version_id: activeVersion.version_id,
|
|
1019
|
+
})).not.toThrowError();
|
|
1020
|
+
});
|
|
1021
|
+
test("should prevent deletion when foreign keys reference the entity", async () => {
|
|
1022
|
+
const lix = await openLix({});
|
|
1023
|
+
const userSchema = {
|
|
1024
|
+
type: "object",
|
|
1025
|
+
"x-lix-version": "1.0",
|
|
1026
|
+
"x-lix-key": "user",
|
|
1027
|
+
"x-lix-primary-key": ["id"],
|
|
1028
|
+
properties: {
|
|
1029
|
+
id: { type: "string" },
|
|
1030
|
+
name: { type: "string" },
|
|
1031
|
+
},
|
|
1032
|
+
required: ["id", "name"],
|
|
1033
|
+
additionalProperties: false,
|
|
1034
|
+
};
|
|
1035
|
+
const postSchema = {
|
|
1036
|
+
type: "object",
|
|
1037
|
+
"x-lix-version": "1.0",
|
|
1038
|
+
"x-lix-key": "post",
|
|
1039
|
+
"x-lix-primary-key": ["id"],
|
|
1040
|
+
"x-lix-foreign-keys": {
|
|
1041
|
+
author_id: {
|
|
1042
|
+
schemaKey: "user",
|
|
1043
|
+
property: "id",
|
|
1044
|
+
},
|
|
1045
|
+
},
|
|
1046
|
+
properties: {
|
|
1047
|
+
id: { type: "string" },
|
|
1048
|
+
author_id: { type: "string" },
|
|
1049
|
+
title: { type: "string" },
|
|
1050
|
+
},
|
|
1051
|
+
required: ["id", "author_id", "title"],
|
|
1052
|
+
additionalProperties: false,
|
|
1053
|
+
};
|
|
1054
|
+
// Store schemas
|
|
1055
|
+
await lix.db
|
|
1056
|
+
.insertInto("stored_schema")
|
|
1057
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
1058
|
+
.execute();
|
|
1059
|
+
const activeVersion = await lix.db
|
|
1060
|
+
.selectFrom("active_version")
|
|
1061
|
+
.select("version_id")
|
|
1062
|
+
.executeTakeFirstOrThrow();
|
|
1063
|
+
// Insert a user that will be referenced
|
|
1064
|
+
await lix.db
|
|
1065
|
+
.insertInto("state_all")
|
|
1066
|
+
.values({
|
|
1067
|
+
entity_id: "user1",
|
|
1068
|
+
file_id: "file1",
|
|
1069
|
+
schema_key: "user",
|
|
1070
|
+
plugin_key: "test_plugin",
|
|
1071
|
+
version_id: activeVersion.version_id,
|
|
1072
|
+
snapshot_content: {
|
|
1073
|
+
id: "user1",
|
|
1074
|
+
name: "John Doe",
|
|
1075
|
+
},
|
|
1076
|
+
schema_version: "1.0",
|
|
1077
|
+
})
|
|
1078
|
+
.execute();
|
|
1079
|
+
// Insert a post that references the user
|
|
1080
|
+
await lix.db
|
|
1081
|
+
.insertInto("state_all")
|
|
1082
|
+
.values({
|
|
1083
|
+
entity_id: "post1",
|
|
1084
|
+
file_id: "file1",
|
|
1085
|
+
schema_key: "post",
|
|
1086
|
+
plugin_key: "test_plugin",
|
|
1087
|
+
version_id: activeVersion.version_id,
|
|
1088
|
+
snapshot_content: {
|
|
1089
|
+
id: "post1",
|
|
1090
|
+
author_id: "user1",
|
|
1091
|
+
title: "My First Post",
|
|
1092
|
+
},
|
|
1093
|
+
schema_version: "1.0",
|
|
1094
|
+
})
|
|
1095
|
+
.execute();
|
|
1096
|
+
// This should fail - cannot delete user because post references it
|
|
1097
|
+
expect(() => validateStateMutation({
|
|
1098
|
+
lix,
|
|
1099
|
+
schema: userSchema,
|
|
1100
|
+
snapshot_content: {}, // Not used for delete operations
|
|
1101
|
+
operation: "delete",
|
|
1102
|
+
entity_id: "user1",
|
|
1103
|
+
version_id: activeVersion.version_id,
|
|
1104
|
+
})).toThrowError(/Foreign key constraint violation.*referenced by.*post.*author_id/i);
|
|
1105
|
+
});
|
|
1106
|
+
test("should allow deletion when no foreign keys reference the entity", async () => {
|
|
1107
|
+
const lix = await openLix({});
|
|
1108
|
+
const userSchema = {
|
|
1109
|
+
type: "object",
|
|
1110
|
+
"x-lix-version": "1.0",
|
|
1111
|
+
"x-lix-key": "user",
|
|
1112
|
+
"x-lix-primary-key": ["id"],
|
|
1113
|
+
properties: {
|
|
1114
|
+
id: { type: "string" },
|
|
1115
|
+
name: { type: "string" },
|
|
1116
|
+
},
|
|
1117
|
+
required: ["id", "name"],
|
|
1118
|
+
additionalProperties: false,
|
|
1119
|
+
};
|
|
1120
|
+
// Store schema
|
|
1121
|
+
await lix.db
|
|
1122
|
+
.insertInto("stored_schema")
|
|
1123
|
+
.values({ value: userSchema })
|
|
1124
|
+
.execute();
|
|
1125
|
+
const activeVersion = await lix.db
|
|
1126
|
+
.selectFrom("active_version")
|
|
1127
|
+
.select("version_id")
|
|
1128
|
+
.executeTakeFirstOrThrow();
|
|
1129
|
+
// Insert a user with no references
|
|
1130
|
+
await lix.db
|
|
1131
|
+
.insertInto("state_all")
|
|
1132
|
+
.values({
|
|
1133
|
+
entity_id: "user1",
|
|
1134
|
+
file_id: "file1",
|
|
1135
|
+
schema_key: "user",
|
|
1136
|
+
plugin_key: "test_plugin",
|
|
1137
|
+
version_id: activeVersion.version_id,
|
|
1138
|
+
snapshot_content: {
|
|
1139
|
+
id: "user1",
|
|
1140
|
+
name: "John Doe",
|
|
1141
|
+
},
|
|
1142
|
+
schema_version: "1.0",
|
|
1143
|
+
})
|
|
1144
|
+
.execute();
|
|
1145
|
+
// This should pass - no foreign keys reference this user
|
|
1146
|
+
expect(() => validateStateMutation({
|
|
1147
|
+
lix,
|
|
1148
|
+
schema: userSchema,
|
|
1149
|
+
snapshot_content: {}, // Not used for delete operations
|
|
1150
|
+
operation: "delete",
|
|
1151
|
+
entity_id: "user1",
|
|
1152
|
+
version_id: activeVersion.version_id,
|
|
1153
|
+
})).not.toThrowError();
|
|
1154
|
+
});
|
|
1155
|
+
test("should throw when deleting non-existent entity", async () => {
|
|
1156
|
+
const lix = await openLix({});
|
|
1157
|
+
const userSchema = {
|
|
1158
|
+
type: "object",
|
|
1159
|
+
"x-lix-version": "1.0",
|
|
1160
|
+
"x-lix-key": "user",
|
|
1161
|
+
"x-lix-primary-key": ["id"],
|
|
1162
|
+
properties: {
|
|
1163
|
+
id: { type: "string" },
|
|
1164
|
+
name: { type: "string" },
|
|
1165
|
+
},
|
|
1166
|
+
required: ["id", "name"],
|
|
1167
|
+
additionalProperties: false,
|
|
1168
|
+
};
|
|
1169
|
+
const activeVersion = await lix.db
|
|
1170
|
+
.selectFrom("active_version")
|
|
1171
|
+
.select("version_id")
|
|
1172
|
+
.executeTakeFirstOrThrow();
|
|
1173
|
+
// This should fail - entity does not exist
|
|
1174
|
+
expect(() => validateStateMutation({
|
|
1175
|
+
lix,
|
|
1176
|
+
schema: userSchema,
|
|
1177
|
+
snapshot_content: {},
|
|
1178
|
+
operation: "delete",
|
|
1179
|
+
entity_id: "nonexistent_user",
|
|
1180
|
+
version_id: activeVersion.version_id,
|
|
1181
|
+
})).toThrowError(/Entity deletion failed/);
|
|
1182
|
+
});
|
|
1183
|
+
test("should throw when entity_id is missing for delete operations", async () => {
|
|
1184
|
+
const lix = await openLix({});
|
|
1185
|
+
const userSchema = {
|
|
1186
|
+
type: "object",
|
|
1187
|
+
"x-lix-version": "1.0",
|
|
1188
|
+
"x-lix-key": "user",
|
|
1189
|
+
"x-lix-primary-key": ["id"],
|
|
1190
|
+
properties: {
|
|
1191
|
+
id: { type: "string" },
|
|
1192
|
+
name: { type: "string" },
|
|
1193
|
+
},
|
|
1194
|
+
required: ["id", "name"],
|
|
1195
|
+
additionalProperties: false,
|
|
1196
|
+
};
|
|
1197
|
+
const activeVersion = await lix.db
|
|
1198
|
+
.selectFrom("active_version")
|
|
1199
|
+
.select("version_id")
|
|
1200
|
+
.executeTakeFirstOrThrow();
|
|
1201
|
+
// This should fail - entity_id is required for delete
|
|
1202
|
+
expect(() => validateStateMutation({
|
|
1203
|
+
lix,
|
|
1204
|
+
schema: userSchema,
|
|
1205
|
+
snapshot_content: {},
|
|
1206
|
+
operation: "delete",
|
|
1207
|
+
// entity_id is missing
|
|
1208
|
+
version_id: activeVersion.version_id,
|
|
1209
|
+
})).toThrowError("entity_id is required for delete operations");
|
|
1210
|
+
});
|
|
1211
|
+
test("should handle deletion validation for change sets referenced by versions", async () => {
|
|
1212
|
+
const lix = await openLix({});
|
|
1213
|
+
// Create a change set
|
|
1214
|
+
await lix.db
|
|
1215
|
+
.insertInto("change_set_all")
|
|
1216
|
+
.values({ id: "cs_referenced", lixcol_version_id: "global" })
|
|
1217
|
+
.execute();
|
|
1218
|
+
// Create a version that references the change set
|
|
1219
|
+
await lix.db
|
|
1220
|
+
.insertInto("version")
|
|
1221
|
+
.values({
|
|
1222
|
+
id: "v1",
|
|
1223
|
+
name: "test_version",
|
|
1224
|
+
change_set_id: "cs_referenced",
|
|
1225
|
+
working_change_set_id: "cs_referenced",
|
|
1226
|
+
})
|
|
1227
|
+
.execute();
|
|
1228
|
+
// const activeVersion = await lix.db
|
|
1229
|
+
// .selectFrom("active_version")
|
|
1230
|
+
// .select("version_id")
|
|
1231
|
+
// .executeTakeFirstOrThrow();
|
|
1232
|
+
// Get the change set schema
|
|
1233
|
+
const changeSetSchema = await lix.db
|
|
1234
|
+
.selectFrom("stored_schema")
|
|
1235
|
+
.select("value")
|
|
1236
|
+
.where("key", "=", "lix_change_set")
|
|
1237
|
+
.executeTakeFirstOrThrow();
|
|
1238
|
+
// This should fail - cannot delete change set because version references it
|
|
1239
|
+
expect(() => validateStateMutation({
|
|
1240
|
+
lix,
|
|
1241
|
+
schema: changeSetSchema.value,
|
|
1242
|
+
snapshot_content: {},
|
|
1243
|
+
operation: "delete",
|
|
1244
|
+
entity_id: "cs_referenced",
|
|
1245
|
+
version_id: "global",
|
|
1246
|
+
})).toThrowError(/Foreign key constraint violation.*Cannot delete entity.*referenced by.*lix_version/i);
|
|
1247
|
+
});
|
|
1248
|
+
test("should parse JSON object properties before validation", async () => {
|
|
1249
|
+
const lix = await openLix({});
|
|
1250
|
+
// Define a schema with an object property
|
|
1251
|
+
const documentSchema = {
|
|
1252
|
+
type: "object",
|
|
1253
|
+
"x-lix-version": "1.0",
|
|
1254
|
+
"x-lix-key": "document",
|
|
1255
|
+
"x-lix-primary-key": ["id"],
|
|
1256
|
+
properties: {
|
|
1257
|
+
id: { type: "string" },
|
|
1258
|
+
title: { type: "string" },
|
|
1259
|
+
body: {
|
|
1260
|
+
type: "object",
|
|
1261
|
+
properties: {
|
|
1262
|
+
type: { type: "string" },
|
|
1263
|
+
content: { type: "array" },
|
|
1264
|
+
},
|
|
1265
|
+
required: ["type", "content"],
|
|
1266
|
+
},
|
|
1267
|
+
},
|
|
1268
|
+
required: ["id", "title", "body"],
|
|
1269
|
+
additionalProperties: false,
|
|
1270
|
+
};
|
|
1271
|
+
// Store the schema
|
|
1272
|
+
await lix.db
|
|
1273
|
+
.insertInto("stored_schema")
|
|
1274
|
+
.values({ value: documentSchema })
|
|
1275
|
+
.execute();
|
|
1276
|
+
const activeVersion = await lix.db
|
|
1277
|
+
.selectFrom("active_version")
|
|
1278
|
+
.select("version_id")
|
|
1279
|
+
.executeTakeFirstOrThrow();
|
|
1280
|
+
// Test with valid JSON object - this should pass
|
|
1281
|
+
const validSnapshotContent = {
|
|
1282
|
+
id: "doc1",
|
|
1283
|
+
title: "Test Document",
|
|
1284
|
+
body: JSON.stringify({
|
|
1285
|
+
type: "zettel_doc",
|
|
1286
|
+
content: [
|
|
1287
|
+
{
|
|
1288
|
+
type: "zettel_text_block",
|
|
1289
|
+
zettel_key: "test_key",
|
|
1290
|
+
style: "zettel_normal",
|
|
1291
|
+
children: [],
|
|
1292
|
+
},
|
|
1293
|
+
],
|
|
1294
|
+
}),
|
|
1295
|
+
};
|
|
1296
|
+
expect(() => validateStateMutation({
|
|
1297
|
+
lix,
|
|
1298
|
+
schema: documentSchema,
|
|
1299
|
+
snapshot_content: validSnapshotContent,
|
|
1300
|
+
operation: "insert",
|
|
1301
|
+
version_id: activeVersion.version_id,
|
|
1302
|
+
})).not.toThrowError();
|
|
1303
|
+
// Test with invalid JSON object - this should fail
|
|
1304
|
+
const invalidSnapshotContent = {
|
|
1305
|
+
id: "doc2",
|
|
1306
|
+
title: "Invalid Document",
|
|
1307
|
+
body: JSON.stringify({
|
|
1308
|
+
type: "invalid_type", // Missing required 'content' property
|
|
1309
|
+
}),
|
|
1310
|
+
};
|
|
1311
|
+
expect(() => validateStateMutation({
|
|
1312
|
+
lix,
|
|
1313
|
+
schema: documentSchema,
|
|
1314
|
+
snapshot_content: invalidSnapshotContent,
|
|
1315
|
+
operation: "insert",
|
|
1316
|
+
version_id: activeVersion.version_id,
|
|
1317
|
+
})).toThrowError(/body.*must have required property.*content/);
|
|
1318
|
+
// Test with malformed JSON string - this should fail
|
|
1319
|
+
const malformedSnapshotContent = {
|
|
1320
|
+
id: "doc3",
|
|
1321
|
+
title: "Malformed Document",
|
|
1322
|
+
body: "{ invalid json",
|
|
1323
|
+
};
|
|
1324
|
+
expect(() => validateStateMutation({
|
|
1325
|
+
lix,
|
|
1326
|
+
schema: documentSchema,
|
|
1327
|
+
snapshot_content: malformedSnapshotContent,
|
|
1328
|
+
operation: "insert",
|
|
1329
|
+
version_id: activeVersion.version_id,
|
|
1330
|
+
})).toThrowError(/Invalid JSON in property 'body'/);
|
|
1331
|
+
});
|
|
1332
|
+
test("foreign key validation should fail when referenced entity exists in different non-inheriting version", async () => {
|
|
1333
|
+
const lix = await openLix({});
|
|
1334
|
+
// Mock schema for a "User" entity
|
|
1335
|
+
const userSchema = {
|
|
1336
|
+
"x-lix-key": "mock_user",
|
|
1337
|
+
"x-lix-version": "1.0",
|
|
1338
|
+
"x-lix-primary-key": ["id"],
|
|
1339
|
+
type: "object",
|
|
1340
|
+
properties: {
|
|
1341
|
+
id: { type: "string" },
|
|
1342
|
+
name: { type: "string" },
|
|
1343
|
+
},
|
|
1344
|
+
required: ["id", "name"],
|
|
1345
|
+
additionalProperties: false,
|
|
1346
|
+
};
|
|
1347
|
+
// Mock schema for a "Post" entity that references User
|
|
1348
|
+
const postSchema = {
|
|
1349
|
+
"x-lix-key": "mock_post",
|
|
1350
|
+
"x-lix-version": "1.0",
|
|
1351
|
+
"x-lix-primary-key": ["id"],
|
|
1352
|
+
"x-lix-foreign-keys": {
|
|
1353
|
+
author_id: {
|
|
1354
|
+
schemaKey: "mock_user",
|
|
1355
|
+
property: "id",
|
|
1356
|
+
},
|
|
1357
|
+
},
|
|
1358
|
+
type: "object",
|
|
1359
|
+
properties: {
|
|
1360
|
+
id: { type: "string" },
|
|
1361
|
+
title: { type: "string" },
|
|
1362
|
+
author_id: { type: "string" },
|
|
1363
|
+
},
|
|
1364
|
+
required: ["id", "title", "author_id"],
|
|
1365
|
+
additionalProperties: false,
|
|
1366
|
+
};
|
|
1367
|
+
// Register our mock schemas
|
|
1368
|
+
await lix.db
|
|
1369
|
+
.insertInto("stored_schema")
|
|
1370
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
1371
|
+
.execute();
|
|
1372
|
+
// Create two separate versions that don't inherit from each other
|
|
1373
|
+
const versionA = await createVersion({
|
|
1374
|
+
lix,
|
|
1375
|
+
name: "version-a",
|
|
1376
|
+
});
|
|
1377
|
+
const versionB = await createVersion({
|
|
1378
|
+
lix,
|
|
1379
|
+
name: "version-b",
|
|
1380
|
+
});
|
|
1381
|
+
// Verify they don't inherit from each other
|
|
1382
|
+
// Both should inherit from global, but not from each other
|
|
1383
|
+
expect(versionA.inherits_from_version_id).toBe("global");
|
|
1384
|
+
expect(versionB.inherits_from_version_id).toBe("global");
|
|
1385
|
+
// Create a user in version A
|
|
1386
|
+
await lix.db
|
|
1387
|
+
.insertInto("state_all")
|
|
1388
|
+
.values({
|
|
1389
|
+
entity_id: "user-1",
|
|
1390
|
+
schema_key: "mock_user",
|
|
1391
|
+
file_id: "test",
|
|
1392
|
+
plugin_key: "test_plugin",
|
|
1393
|
+
snapshot_content: {
|
|
1394
|
+
id: "user-1",
|
|
1395
|
+
name: "Alice",
|
|
1396
|
+
},
|
|
1397
|
+
schema_version: "1.0",
|
|
1398
|
+
version_id: versionA.id,
|
|
1399
|
+
})
|
|
1400
|
+
.execute();
|
|
1401
|
+
// BUG: This should FAIL because user-1 doesn't exist in version B's context
|
|
1402
|
+
// but the current foreign key validation logic will find user-1 in version A
|
|
1403
|
+
// and incorrectly allow this validation to succeed
|
|
1404
|
+
expect(() => validateStateMutation({
|
|
1405
|
+
lix,
|
|
1406
|
+
schema: postSchema,
|
|
1407
|
+
snapshot_content: {
|
|
1408
|
+
id: "post-1",
|
|
1409
|
+
title: "My Post",
|
|
1410
|
+
author_id: "user-1", // References user-1 which only exists in version A
|
|
1411
|
+
},
|
|
1412
|
+
operation: "insert",
|
|
1413
|
+
version_id: versionB.id,
|
|
1414
|
+
})).toThrow(/Foreign key constraint violation.*mock_user.*user-1/);
|
|
1415
|
+
// Verify that user-1 indeed doesn't exist in version B's context
|
|
1416
|
+
const userInVersionB = await lix.db
|
|
1417
|
+
.selectFrom("state_all")
|
|
1418
|
+
.where("entity_id", "=", "user-1")
|
|
1419
|
+
.where("schema_key", "=", "mock_user")
|
|
1420
|
+
.where("version_id", "=", versionB.id)
|
|
1421
|
+
.selectAll()
|
|
1422
|
+
.execute();
|
|
1423
|
+
expect(userInVersionB).toHaveLength(0);
|
|
1424
|
+
// But verify it does exist in version A
|
|
1425
|
+
const userInVersionA = await lix.db
|
|
1426
|
+
.selectFrom("state_all")
|
|
1427
|
+
.where("entity_id", "=", "user-1")
|
|
1428
|
+
.where("schema_key", "=", "mock_user")
|
|
1429
|
+
.where("version_id", "=", versionA.id)
|
|
1430
|
+
.selectAll()
|
|
1431
|
+
.execute();
|
|
1432
|
+
expect(userInVersionA).toHaveLength(1);
|
|
1433
|
+
});
|
|
1434
|
+
test("should allow self-referential foreign keys", async () => {
|
|
1435
|
+
const lix = await openLix({});
|
|
1436
|
+
// Define a schema with self-referential foreign key (like version inheritance)
|
|
1437
|
+
const versionSchema = {
|
|
1438
|
+
type: "object",
|
|
1439
|
+
"x-lix-version": "1.0",
|
|
1440
|
+
"x-lix-key": "mock_version",
|
|
1441
|
+
"x-lix-primary-key": ["id"],
|
|
1442
|
+
"x-lix-foreign-keys": {
|
|
1443
|
+
inherits_from_version_id: {
|
|
1444
|
+
schemaKey: "mock_version", // Self-referential foreign key
|
|
1445
|
+
property: "id",
|
|
1446
|
+
},
|
|
1447
|
+
},
|
|
1448
|
+
properties: {
|
|
1449
|
+
id: { type: "string" },
|
|
1450
|
+
name: { type: "string" },
|
|
1451
|
+
inherits_from_version_id: { type: ["string", "null"] },
|
|
1452
|
+
},
|
|
1453
|
+
required: ["id", "name"],
|
|
1454
|
+
additionalProperties: false,
|
|
1455
|
+
};
|
|
1456
|
+
// Store the schema
|
|
1457
|
+
await lix.db
|
|
1458
|
+
.insertInto("stored_schema")
|
|
1459
|
+
.values({ value: versionSchema })
|
|
1460
|
+
.execute();
|
|
1461
|
+
const activeVersion = await lix.db
|
|
1462
|
+
.selectFrom("active_version")
|
|
1463
|
+
.select("version_id")
|
|
1464
|
+
.executeTakeFirstOrThrow();
|
|
1465
|
+
// Insert a parent version first (with null inheritance)
|
|
1466
|
+
await lix.db
|
|
1467
|
+
.insertInto("state_all")
|
|
1468
|
+
.values({
|
|
1469
|
+
entity_id: "version0",
|
|
1470
|
+
file_id: "file1",
|
|
1471
|
+
schema_key: "mock_version",
|
|
1472
|
+
plugin_key: "test_plugin",
|
|
1473
|
+
version_id: activeVersion.version_id,
|
|
1474
|
+
snapshot_content: {
|
|
1475
|
+
id: "version0",
|
|
1476
|
+
name: "version0",
|
|
1477
|
+
inherits_from_version_id: null,
|
|
1478
|
+
},
|
|
1479
|
+
schema_version: "1.0",
|
|
1480
|
+
})
|
|
1481
|
+
.execute();
|
|
1482
|
+
// This should pass - child version referencing parent version (valid self-referential FK)
|
|
1483
|
+
expect(() => validateStateMutation({
|
|
1484
|
+
lix,
|
|
1485
|
+
schema: versionSchema,
|
|
1486
|
+
snapshot_content: {
|
|
1487
|
+
id: "version1",
|
|
1488
|
+
name: "version1",
|
|
1489
|
+
inherits_from_version_id: "version0", // References another entity in same schema
|
|
1490
|
+
},
|
|
1491
|
+
operation: "insert",
|
|
1492
|
+
version_id: activeVersion.version_id,
|
|
1493
|
+
})).not.toThrowError();
|
|
1494
|
+
// This should also pass - version with null inheritance (no foreign key constraint)
|
|
1495
|
+
expect(() => validateStateMutation({
|
|
1496
|
+
lix,
|
|
1497
|
+
schema: versionSchema,
|
|
1498
|
+
snapshot_content: {
|
|
1499
|
+
id: "version2",
|
|
1500
|
+
name: "version2",
|
|
1501
|
+
inherits_from_version_id: null, // No foreign key reference
|
|
1502
|
+
},
|
|
1503
|
+
operation: "insert",
|
|
1504
|
+
version_id: activeVersion.version_id,
|
|
1505
|
+
})).not.toThrowError();
|
|
1506
|
+
// This should fail - referencing non-existent version
|
|
1507
|
+
expect(() => validateStateMutation({
|
|
1508
|
+
lix,
|
|
1509
|
+
schema: versionSchema,
|
|
1510
|
+
snapshot_content: {
|
|
1511
|
+
id: "version3",
|
|
1512
|
+
name: "version3",
|
|
1513
|
+
inherits_from_version_id: "nonexistent_version",
|
|
1514
|
+
},
|
|
1515
|
+
operation: "insert",
|
|
1516
|
+
version_id: activeVersion.version_id,
|
|
1517
|
+
})).toThrowError("Foreign key constraint violation");
|
|
1518
|
+
});
|
|
1519
|
+
test("should allow self-referential foreign keys for update operations", async () => {
|
|
1520
|
+
const lix = await openLix({});
|
|
1521
|
+
// Define a schema with self-referential foreign key
|
|
1522
|
+
const versionSchema = {
|
|
1523
|
+
type: "object",
|
|
1524
|
+
"x-lix-version": "1.0",
|
|
1525
|
+
"x-lix-key": "mock_version",
|
|
1526
|
+
"x-lix-primary-key": ["id"],
|
|
1527
|
+
"x-lix-foreign-keys": {
|
|
1528
|
+
inherits_from_version_id: {
|
|
1529
|
+
schemaKey: "mock_version",
|
|
1530
|
+
property: "id",
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
properties: {
|
|
1534
|
+
id: { type: "string" },
|
|
1535
|
+
name: { type: "string" },
|
|
1536
|
+
inherits_from_version_id: { type: ["string", "null"] },
|
|
1537
|
+
},
|
|
1538
|
+
required: ["id", "name"],
|
|
1539
|
+
additionalProperties: false,
|
|
1540
|
+
};
|
|
1541
|
+
// Store the schema
|
|
1542
|
+
await lix.db
|
|
1543
|
+
.insertInto("stored_schema")
|
|
1544
|
+
.values({ value: versionSchema })
|
|
1545
|
+
.execute();
|
|
1546
|
+
const activeVersion = await lix.db
|
|
1547
|
+
.selectFrom("active_version")
|
|
1548
|
+
.select("version_id")
|
|
1549
|
+
.executeTakeFirstOrThrow();
|
|
1550
|
+
// Insert initial versions
|
|
1551
|
+
await lix.db
|
|
1552
|
+
.insertInto("state_all")
|
|
1553
|
+
.values([
|
|
1554
|
+
{
|
|
1555
|
+
entity_id: "version0",
|
|
1556
|
+
file_id: "file1",
|
|
1557
|
+
schema_key: "mock_version",
|
|
1558
|
+
plugin_key: "test_plugin",
|
|
1559
|
+
version_id: activeVersion.version_id,
|
|
1560
|
+
snapshot_content: {
|
|
1561
|
+
id: "version0",
|
|
1562
|
+
name: "version0",
|
|
1563
|
+
inherits_from_version_id: null,
|
|
1564
|
+
},
|
|
1565
|
+
schema_version: "1.0",
|
|
1566
|
+
},
|
|
1567
|
+
{
|
|
1568
|
+
entity_id: "version1",
|
|
1569
|
+
file_id: "file1",
|
|
1570
|
+
schema_key: "mock_version",
|
|
1571
|
+
plugin_key: "test_plugin",
|
|
1572
|
+
version_id: activeVersion.version_id,
|
|
1573
|
+
snapshot_content: {
|
|
1574
|
+
id: "version1",
|
|
1575
|
+
name: "version1",
|
|
1576
|
+
inherits_from_version_id: "version0",
|
|
1577
|
+
},
|
|
1578
|
+
schema_version: "1.0",
|
|
1579
|
+
},
|
|
1580
|
+
])
|
|
1581
|
+
.execute();
|
|
1582
|
+
// This should pass - updating to reference a different valid version
|
|
1583
|
+
expect(() => validateStateMutation({
|
|
1584
|
+
lix,
|
|
1585
|
+
schema: versionSchema,
|
|
1586
|
+
snapshot_content: {
|
|
1587
|
+
id: "version1",
|
|
1588
|
+
name: "version1_updated",
|
|
1589
|
+
inherits_from_version_id: null, // Change from version0 to null
|
|
1590
|
+
},
|
|
1591
|
+
operation: "update",
|
|
1592
|
+
entity_id: "version1",
|
|
1593
|
+
version_id: activeVersion.version_id,
|
|
1594
|
+
})).not.toThrowError();
|
|
1595
|
+
// This should fail - updating to reference non-existent version
|
|
1596
|
+
expect(() => validateStateMutation({
|
|
1597
|
+
lix,
|
|
1598
|
+
schema: versionSchema,
|
|
1599
|
+
snapshot_content: {
|
|
1600
|
+
id: "version1",
|
|
1601
|
+
name: "version1_updated",
|
|
1602
|
+
inherits_from_version_id: "nonexistent_version",
|
|
1603
|
+
},
|
|
1604
|
+
operation: "update",
|
|
1605
|
+
entity_id: "version1",
|
|
1606
|
+
version_id: activeVersion.version_id,
|
|
1607
|
+
})).toThrowError("Foreign key constraint violation");
|
|
1608
|
+
});
|
|
1609
|
+
test("should prevent deletion when self-referential foreign keys reference the entity", async () => {
|
|
1610
|
+
const lix = await openLix({});
|
|
1611
|
+
// Define a schema with self-referential foreign key
|
|
1612
|
+
const versionSchema = {
|
|
1613
|
+
type: "object",
|
|
1614
|
+
"x-lix-version": "1.0",
|
|
1615
|
+
"x-lix-key": "mock_version",
|
|
1616
|
+
"x-lix-primary-key": ["id"],
|
|
1617
|
+
"x-lix-foreign-keys": {
|
|
1618
|
+
inherits_from_version_id: {
|
|
1619
|
+
schemaKey: "mock_version",
|
|
1620
|
+
property: "id",
|
|
1621
|
+
},
|
|
1622
|
+
},
|
|
1623
|
+
properties: {
|
|
1624
|
+
id: { type: "string" },
|
|
1625
|
+
name: { type: "string" },
|
|
1626
|
+
inherits_from_version_id: { type: ["string", "null"] },
|
|
1627
|
+
},
|
|
1628
|
+
required: ["id", "name"],
|
|
1629
|
+
additionalProperties: false,
|
|
1630
|
+
};
|
|
1631
|
+
// Store the schema
|
|
1632
|
+
await lix.db
|
|
1633
|
+
.insertInto("stored_schema")
|
|
1634
|
+
.values({ value: versionSchema })
|
|
1635
|
+
.execute();
|
|
1636
|
+
const activeVersion = await lix.db
|
|
1637
|
+
.selectFrom("active_version")
|
|
1638
|
+
.select("version_id")
|
|
1639
|
+
.executeTakeFirstOrThrow();
|
|
1640
|
+
// Insert parent and child versions
|
|
1641
|
+
await lix.db
|
|
1642
|
+
.insertInto("state_all")
|
|
1643
|
+
.values([
|
|
1644
|
+
{
|
|
1645
|
+
entity_id: "version0",
|
|
1646
|
+
file_id: "file1",
|
|
1647
|
+
schema_key: "mock_version",
|
|
1648
|
+
plugin_key: "test_plugin",
|
|
1649
|
+
version_id: activeVersion.version_id,
|
|
1650
|
+
snapshot_content: {
|
|
1651
|
+
id: "version0",
|
|
1652
|
+
name: "version0",
|
|
1653
|
+
inherits_from_version_id: null,
|
|
1654
|
+
},
|
|
1655
|
+
schema_version: "1.0",
|
|
1656
|
+
},
|
|
1657
|
+
{
|
|
1658
|
+
entity_id: "version1",
|
|
1659
|
+
file_id: "file1",
|
|
1660
|
+
schema_key: "mock_version",
|
|
1661
|
+
plugin_key: "test_plugin",
|
|
1662
|
+
version_id: activeVersion.version_id,
|
|
1663
|
+
snapshot_content: {
|
|
1664
|
+
id: "version1",
|
|
1665
|
+
name: "version1",
|
|
1666
|
+
inherits_from_version_id: "version0", // References version0
|
|
1667
|
+
},
|
|
1668
|
+
schema_version: "1.0",
|
|
1669
|
+
},
|
|
1670
|
+
])
|
|
1671
|
+
.execute();
|
|
1672
|
+
// This should fail - cannot delete version0 because version1 references it
|
|
1673
|
+
expect(() => validateStateMutation({
|
|
1674
|
+
lix,
|
|
1675
|
+
schema: versionSchema,
|
|
1676
|
+
snapshot_content: {},
|
|
1677
|
+
operation: "delete",
|
|
1678
|
+
entity_id: "version0",
|
|
1679
|
+
version_id: activeVersion.version_id,
|
|
1680
|
+
})).toThrowError(/Foreign key constraint violation.*referenced by.*mock_version.*inherits_from_version_id/);
|
|
1681
|
+
// This should pass - can delete version1 (no other versions reference it)
|
|
1682
|
+
expect(() => validateStateMutation({
|
|
1683
|
+
lix,
|
|
1684
|
+
schema: versionSchema,
|
|
1685
|
+
snapshot_content: {},
|
|
1686
|
+
operation: "delete",
|
|
1687
|
+
entity_id: "version1",
|
|
1688
|
+
version_id: activeVersion.version_id,
|
|
1689
|
+
})).not.toThrowError();
|
|
1690
|
+
});
|
|
1691
|
+
// Foreign keys are restricted to the current version context to maintain data integrity
|
|
1692
|
+
// and prevent confusing dependency relationships across version boundaries. While entities
|
|
1693
|
+
// can be inherited from parent versions through the copy-on-write system, foreign key
|
|
1694
|
+
// constraints require explicit, direct relationships within the same version scope.
|
|
1695
|
+
// This design choice ensures that:
|
|
1696
|
+
// 1. FK constraints are predictable and version-scoped
|
|
1697
|
+
// 2. No hidden dependencies exist across version boundaries
|
|
1698
|
+
// 3. Copy-on-write semantics remain clear and isolated
|
|
1699
|
+
// 4. Data integrity is maintained within each version context
|
|
1700
|
+
test("should prevent foreign key references to inherited entities from different version contexts", async () => {
|
|
1701
|
+
const lix = await openLix({});
|
|
1702
|
+
// Create a thread in global context
|
|
1703
|
+
await lix.db
|
|
1704
|
+
.insertInto("thread_all")
|
|
1705
|
+
.values({
|
|
1706
|
+
id: "global_thread",
|
|
1707
|
+
metadata: { title: "Global Thread" },
|
|
1708
|
+
lixcol_version_id: "global",
|
|
1709
|
+
})
|
|
1710
|
+
.execute();
|
|
1711
|
+
// Get the active version (should be "main" version)
|
|
1712
|
+
const activeVersion = await lix.db
|
|
1713
|
+
.selectFrom("active_version")
|
|
1714
|
+
.select("version_id")
|
|
1715
|
+
.executeTakeFirstOrThrow();
|
|
1716
|
+
// Get the thread comment schema
|
|
1717
|
+
const threadCommentSchema = await lix.db
|
|
1718
|
+
.selectFrom("stored_schema")
|
|
1719
|
+
.select("value")
|
|
1720
|
+
.where("key", "=", "lix_thread_comment")
|
|
1721
|
+
.executeTakeFirstOrThrow();
|
|
1722
|
+
// This should FAIL: attempting to create a thread_comment in the active version
|
|
1723
|
+
// that references a thread that only exists in global context.
|
|
1724
|
+
// Foreign keys should only work within the same version context.
|
|
1725
|
+
expect(() => validateStateMutation({
|
|
1726
|
+
lix,
|
|
1727
|
+
schema: threadCommentSchema.value,
|
|
1728
|
+
snapshot_content: {
|
|
1729
|
+
id: "comment1",
|
|
1730
|
+
thread_id: "global_thread", // References thread in global context
|
|
1731
|
+
parent_id: null,
|
|
1732
|
+
body: {
|
|
1733
|
+
type: "zettel_doc",
|
|
1734
|
+
content: [
|
|
1735
|
+
{
|
|
1736
|
+
type: "zettel_text_block",
|
|
1737
|
+
zettel_key: "test_key",
|
|
1738
|
+
style: "zettel_normal",
|
|
1739
|
+
children: [],
|
|
1740
|
+
},
|
|
1741
|
+
],
|
|
1742
|
+
},
|
|
1743
|
+
},
|
|
1744
|
+
operation: "insert",
|
|
1745
|
+
version_id: activeVersion.version_id, // But creating comment in active version context
|
|
1746
|
+
})).toThrow(/Foreign key constraint violation.*lix_thread.*global_thread/);
|
|
1747
|
+
});
|
|
1748
|
+
test("should prevent change set elements from referencing change sets defined in global context", async () => {
|
|
1749
|
+
const lix = await openLix({});
|
|
1750
|
+
// Create a change set in global context
|
|
1751
|
+
await lix.db
|
|
1752
|
+
.insertInto("change_set_all")
|
|
1753
|
+
.values({
|
|
1754
|
+
id: "global_change_set",
|
|
1755
|
+
lixcol_version_id: "global",
|
|
1756
|
+
})
|
|
1757
|
+
.execute();
|
|
1758
|
+
// Get the active version (should be "main" version)
|
|
1759
|
+
const activeVersion = await lix.db
|
|
1760
|
+
.selectFrom("active_version")
|
|
1761
|
+
.select("version_id")
|
|
1762
|
+
.executeTakeFirstOrThrow();
|
|
1763
|
+
// Get the change set element schema
|
|
1764
|
+
const changeSetElementSchema = await lix.db
|
|
1765
|
+
.selectFrom("stored_schema")
|
|
1766
|
+
.select("value")
|
|
1767
|
+
.where("key", "=", "lix_change_set_element")
|
|
1768
|
+
.executeTakeFirstOrThrow();
|
|
1769
|
+
// This should FAIL: attempting to create a change_set_element in the active version
|
|
1770
|
+
// that references a change set that exists in global context.
|
|
1771
|
+
// The bug is that this currently passes when it should fail.
|
|
1772
|
+
expect(() => validateStateMutation({
|
|
1773
|
+
lix,
|
|
1774
|
+
schema: changeSetElementSchema.value,
|
|
1775
|
+
snapshot_content: {
|
|
1776
|
+
change_set_id: "global_change_set", // References change set in global context
|
|
1777
|
+
change_id: "dummy_change_id",
|
|
1778
|
+
entity_id: "dummy_entity_id",
|
|
1779
|
+
file_id: "dummy_file_id",
|
|
1780
|
+
schema_key: "dummy_schema_key",
|
|
1781
|
+
},
|
|
1782
|
+
operation: "insert",
|
|
1783
|
+
version_id: activeVersion.version_id, // But creating element in active version context
|
|
1784
|
+
})).toThrow(/Foreign key constraint violation.*lix_change_set.*global_change_set/);
|
|
1785
|
+
});
|
|
1786
|
+
// Untracked state foreign key tests
|
|
1787
|
+
// SCENARIO: Tracked → Untracked Foreign Key Reference
|
|
1788
|
+
// WHY THIS TEST EXISTS: Untracked entities are local-only and won't be synced to remote.
|
|
1789
|
+
// If a tracked entity references an untracked entity, it would create broken references
|
|
1790
|
+
// when synced because the untracked entity doesn't exist on the remote.
|
|
1791
|
+
// BEHAVIOR: DISALLOWED - This would break data integrity during sync operations.
|
|
1792
|
+
test("should prevent tracked entities from referencing untracked entities", async () => {
|
|
1793
|
+
const lix = await openLix({});
|
|
1794
|
+
const userSchema = {
|
|
1795
|
+
type: "object",
|
|
1796
|
+
"x-lix-version": "1.0",
|
|
1797
|
+
"x-lix-key": "user",
|
|
1798
|
+
"x-lix-primary-key": ["id"],
|
|
1799
|
+
properties: {
|
|
1800
|
+
id: { type: "string" },
|
|
1801
|
+
name: { type: "string" },
|
|
1802
|
+
},
|
|
1803
|
+
required: ["id", "name"],
|
|
1804
|
+
additionalProperties: false,
|
|
1805
|
+
};
|
|
1806
|
+
const postSchema = {
|
|
1807
|
+
type: "object",
|
|
1808
|
+
"x-lix-version": "1.0",
|
|
1809
|
+
"x-lix-key": "post",
|
|
1810
|
+
"x-lix-primary-key": ["id"],
|
|
1811
|
+
"x-lix-foreign-keys": {
|
|
1812
|
+
author_id: {
|
|
1813
|
+
schemaKey: "user",
|
|
1814
|
+
property: "id",
|
|
1815
|
+
},
|
|
1816
|
+
},
|
|
1817
|
+
properties: {
|
|
1818
|
+
id: { type: "string" },
|
|
1819
|
+
author_id: { type: "string" },
|
|
1820
|
+
title: { type: "string" },
|
|
1821
|
+
},
|
|
1822
|
+
required: ["id", "author_id", "title"],
|
|
1823
|
+
additionalProperties: false,
|
|
1824
|
+
};
|
|
1825
|
+
// Store schemas
|
|
1826
|
+
await lix.db
|
|
1827
|
+
.insertInto("stored_schema")
|
|
1828
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
1829
|
+
.execute();
|
|
1830
|
+
const activeVersion = await lix.db
|
|
1831
|
+
.selectFrom("active_version")
|
|
1832
|
+
.select("version_id")
|
|
1833
|
+
.executeTakeFirstOrThrow();
|
|
1834
|
+
// Insert an untracked user
|
|
1835
|
+
await lix.db
|
|
1836
|
+
.insertInto("state_all")
|
|
1837
|
+
.values({
|
|
1838
|
+
entity_id: "untracked_user",
|
|
1839
|
+
file_id: "file1",
|
|
1840
|
+
schema_key: "user",
|
|
1841
|
+
plugin_key: "test_plugin",
|
|
1842
|
+
version_id: activeVersion.version_id,
|
|
1843
|
+
snapshot_content: {
|
|
1844
|
+
id: "untracked_user",
|
|
1845
|
+
name: "Untracked User",
|
|
1846
|
+
},
|
|
1847
|
+
schema_version: "1.0",
|
|
1848
|
+
untracked: true,
|
|
1849
|
+
})
|
|
1850
|
+
.execute();
|
|
1851
|
+
// This should FAIL - tracked entity cannot reference untracked entity
|
|
1852
|
+
expect(() => validateStateMutation({
|
|
1853
|
+
lix,
|
|
1854
|
+
schema: postSchema,
|
|
1855
|
+
snapshot_content: {
|
|
1856
|
+
id: "post1",
|
|
1857
|
+
author_id: "untracked_user", // References untracked user
|
|
1858
|
+
title: "My Post",
|
|
1859
|
+
},
|
|
1860
|
+
operation: "insert",
|
|
1861
|
+
version_id: activeVersion.version_id,
|
|
1862
|
+
})).toThrow(/Foreign key constraint violation.*tracked entities cannot reference untracked entities.*This would create broken references during sync/);
|
|
1863
|
+
});
|
|
1864
|
+
// SCENARIO: Untracked → Tracked Foreign Key Reference
|
|
1865
|
+
// WHY THIS TEST EXISTS: Untracked entities are local-only and won't be synced.
|
|
1866
|
+
// Since they remain local, they can safely reference tracked entities without
|
|
1867
|
+
// breaking data integrity. The untracked entity simply won't exist on remote.
|
|
1868
|
+
// BEHAVIOR: ALLOWED - Safe because untracked entities don't participate in sync.
|
|
1869
|
+
test("should allow untracked entities to reference tracked entities", async () => {
|
|
1870
|
+
const lix = await openLix({});
|
|
1871
|
+
const userSchema = {
|
|
1872
|
+
type: "object",
|
|
1873
|
+
"x-lix-version": "1.0",
|
|
1874
|
+
"x-lix-key": "user",
|
|
1875
|
+
"x-lix-primary-key": ["id"],
|
|
1876
|
+
properties: {
|
|
1877
|
+
id: { type: "string" },
|
|
1878
|
+
name: { type: "string" },
|
|
1879
|
+
},
|
|
1880
|
+
required: ["id", "name"],
|
|
1881
|
+
additionalProperties: false,
|
|
1882
|
+
};
|
|
1883
|
+
const postSchema = {
|
|
1884
|
+
type: "object",
|
|
1885
|
+
"x-lix-version": "1.0",
|
|
1886
|
+
"x-lix-key": "post",
|
|
1887
|
+
"x-lix-primary-key": ["id"],
|
|
1888
|
+
"x-lix-foreign-keys": {
|
|
1889
|
+
author_id: {
|
|
1890
|
+
schemaKey: "user",
|
|
1891
|
+
property: "id",
|
|
1892
|
+
},
|
|
1893
|
+
},
|
|
1894
|
+
properties: {
|
|
1895
|
+
id: { type: "string" },
|
|
1896
|
+
author_id: { type: "string" },
|
|
1897
|
+
title: { type: "string" },
|
|
1898
|
+
},
|
|
1899
|
+
required: ["id", "author_id", "title"],
|
|
1900
|
+
additionalProperties: false,
|
|
1901
|
+
};
|
|
1902
|
+
// Store schemas
|
|
1903
|
+
await lix.db
|
|
1904
|
+
.insertInto("stored_schema")
|
|
1905
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
1906
|
+
.execute();
|
|
1907
|
+
const activeVersion = await lix.db
|
|
1908
|
+
.selectFrom("active_version")
|
|
1909
|
+
.select("version_id")
|
|
1910
|
+
.executeTakeFirstOrThrow();
|
|
1911
|
+
// Insert a tracked user
|
|
1912
|
+
await lix.db
|
|
1913
|
+
.insertInto("state_all")
|
|
1914
|
+
.values({
|
|
1915
|
+
entity_id: "tracked_user",
|
|
1916
|
+
file_id: "file1",
|
|
1917
|
+
schema_key: "user",
|
|
1918
|
+
plugin_key: "test_plugin",
|
|
1919
|
+
version_id: activeVersion.version_id,
|
|
1920
|
+
snapshot_content: {
|
|
1921
|
+
id: "tracked_user",
|
|
1922
|
+
name: "Tracked User",
|
|
1923
|
+
},
|
|
1924
|
+
schema_version: "1.0",
|
|
1925
|
+
untracked: false,
|
|
1926
|
+
})
|
|
1927
|
+
.execute();
|
|
1928
|
+
// Create validation arguments for untracked post
|
|
1929
|
+
const validationArgs = {
|
|
1930
|
+
lix,
|
|
1931
|
+
schema: postSchema,
|
|
1932
|
+
snapshot_content: {
|
|
1933
|
+
id: "untracked_post",
|
|
1934
|
+
author_id: "tracked_user", // References tracked user
|
|
1935
|
+
title: "My Untracked Post",
|
|
1936
|
+
},
|
|
1937
|
+
operation: "insert",
|
|
1938
|
+
version_id: activeVersion.version_id,
|
|
1939
|
+
untracked: true, // Mark as untracked
|
|
1940
|
+
};
|
|
1941
|
+
// This should PASS - untracked entity can reference tracked entity
|
|
1942
|
+
expect(() => validateStateMutation(validationArgs)).not.toThrow();
|
|
1943
|
+
});
|
|
1944
|
+
// SCENARIO: Untracked → Untracked Foreign Key Reference
|
|
1945
|
+
// WHY THIS TEST EXISTS: Both entities are local-only and won't be synced.
|
|
1946
|
+
// They exist in the same local scope, so references between them are valid
|
|
1947
|
+
// and won't cause any sync issues since neither entity leaves the local system.
|
|
1948
|
+
// BEHAVIOR: ALLOWED - Both entities remain local, maintaining referential integrity.
|
|
1949
|
+
test("should allow untracked entities to reference other untracked entities", async () => {
|
|
1950
|
+
const lix = await openLix({});
|
|
1951
|
+
const userSchema = {
|
|
1952
|
+
type: "object",
|
|
1953
|
+
"x-lix-version": "1.0",
|
|
1954
|
+
"x-lix-key": "user",
|
|
1955
|
+
"x-lix-primary-key": ["id"],
|
|
1956
|
+
properties: {
|
|
1957
|
+
id: { type: "string" },
|
|
1958
|
+
name: { type: "string" },
|
|
1959
|
+
},
|
|
1960
|
+
required: ["id", "name"],
|
|
1961
|
+
additionalProperties: false,
|
|
1962
|
+
};
|
|
1963
|
+
const postSchema = {
|
|
1964
|
+
type: "object",
|
|
1965
|
+
"x-lix-version": "1.0",
|
|
1966
|
+
"x-lix-key": "post",
|
|
1967
|
+
"x-lix-primary-key": ["id"],
|
|
1968
|
+
"x-lix-foreign-keys": {
|
|
1969
|
+
author_id: {
|
|
1970
|
+
schemaKey: "user",
|
|
1971
|
+
property: "id",
|
|
1972
|
+
},
|
|
1973
|
+
},
|
|
1974
|
+
properties: {
|
|
1975
|
+
id: { type: "string" },
|
|
1976
|
+
author_id: { type: "string" },
|
|
1977
|
+
title: { type: "string" },
|
|
1978
|
+
},
|
|
1979
|
+
required: ["id", "author_id", "title"],
|
|
1980
|
+
additionalProperties: false,
|
|
1981
|
+
};
|
|
1982
|
+
// Store schemas
|
|
1983
|
+
await lix.db
|
|
1984
|
+
.insertInto("stored_schema")
|
|
1985
|
+
.values([{ value: userSchema }, { value: postSchema }])
|
|
1986
|
+
.execute();
|
|
1987
|
+
const activeVersion = await lix.db
|
|
1988
|
+
.selectFrom("active_version")
|
|
1989
|
+
.select("version_id")
|
|
1990
|
+
.executeTakeFirstOrThrow();
|
|
1991
|
+
// Insert an untracked user
|
|
1992
|
+
await lix.db
|
|
1993
|
+
.insertInto("state_all")
|
|
1994
|
+
.values({
|
|
1995
|
+
entity_id: "untracked_user",
|
|
1996
|
+
file_id: "file1",
|
|
1997
|
+
schema_key: "user",
|
|
1998
|
+
plugin_key: "test_plugin",
|
|
1999
|
+
version_id: activeVersion.version_id,
|
|
2000
|
+
snapshot_content: {
|
|
2001
|
+
id: "untracked_user",
|
|
2002
|
+
name: "Untracked User",
|
|
2003
|
+
},
|
|
2004
|
+
schema_version: "1.0",
|
|
2005
|
+
untracked: true,
|
|
2006
|
+
})
|
|
2007
|
+
.execute();
|
|
2008
|
+
// Create validation arguments for untracked post
|
|
2009
|
+
const validationArgs = {
|
|
2010
|
+
lix,
|
|
2011
|
+
schema: postSchema,
|
|
2012
|
+
snapshot_content: {
|
|
2013
|
+
id: "untracked_post",
|
|
2014
|
+
author_id: "untracked_user", // References untracked user
|
|
2015
|
+
title: "My Untracked Post",
|
|
2016
|
+
},
|
|
2017
|
+
operation: "insert",
|
|
2018
|
+
version_id: activeVersion.version_id,
|
|
2019
|
+
untracked: true, // Mark as untracked
|
|
2020
|
+
};
|
|
2021
|
+
// This should PASS - untracked entity can reference another untracked entity
|
|
2022
|
+
expect(() => validateStateMutation(validationArgs)).not.toThrow();
|
|
2023
|
+
});
|
|
2024
|
+
//# sourceMappingURL=validate-state-mutation.test.js.map
|